2

RHEL 4 システム (openssl 0.9.8b) で Web サービス クライアントをコーディングしようとしています (アップグレードはオプションではありません)。使用する CA 証明書ファイルを取得しました。2 つの証明書があり、1 つは自己署名ルート証明書です。「openssl s_client」で動作しますが、コードからは動作しません。そこで、SSL_get_verify_result からエラー 7 (SSL 証明書の検証に失敗しました) が発生します。

テストプログラムを作成しました。基本的な部分は次のとおりです。

SSL_library_init();
SSL_load_error_strings();
ctx = SSL_CTX_new(SSLv23_method());
SSL_CTX_load_verify_locations(ctx, "/etc/pki/mycert/cacert.pem", 0);
ssl = SSL_new(ctx);
sbio = BIO_new_socket(sock, BIO_NOCLOSE); /* The socket is already connected */
SSL_set_bio(ssl, sbio, sbio);
SSL_connect(ssl);
err = SSL_get_verify_result(ssl);

接続が機能し、サーバーが証明書を送信します。PEM_write_X509 でダンプし、「openssl verify」で受け入れられることを確認しました。

利用した

SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);

コールバック関数で検証の手順を書き出すには:

static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
{
    char    buf[256];
    X509   *err_cert;
    int     err, depth;

    err_cert = X509_STORE_CTX_get_current_cert(ctx);
    err = X509_STORE_CTX_get_error(ctx);
    depth = X509_STORE_CTX_get_error_depth(ctx);

    X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);

if (!preverify_ok)
    printf("verify error:num=%d:%s:depth=%d:%s\n", err,
             X509_verify_cert_error_string(err), depth, buf);
else
    printf("Preverify OK, depth=%d:%s, err=%d\n", depth, buf, err);
...

この出力は次のとおりです (一部の証明書データは「...」に置き換えられます)。

Preverify OK, depth=2:/ST=GP/L=JHB/C ... QA Root CA 01, err=0
Preverify OK, depth=1:/C=ZA/DC=za/DC ... QA Issue CA 01, err=0
verify error:num=7:certificate signature failure:depth=0:/C=ZA ...

この CA 証明書ファイルを「-CAfile」として「openssl s_client」を実行すると、出力は次のように始まります。

depth=2 /ST=GP/L=JHB/C ... QA Root CA 01
verify return:1
depth=1 /C=ZA/DC=za/DC ... QA Issue CA 01
verify return:1
depth=0 /C=ZA/ST ...
verify return:1

では、「openssl s_client」が行っていることとコードが行っていることの違いは何ですか?

4

1 に答える 1