Reposting this since it got lost in the churn.

I have a Perl script using that is failing mysteriously to connect with
an HTTPS site requiring client certificates for authentication. Here's
the command that allows me to connect to the site in question:

openssl s_client -connect hostname:443 -cert test.crt
     -key test.key -CAfile cacerts.crt -prexit

I can then do a GET on the directory protected with cert auth. Something
key to note is that the connection is not successfu1l unless -CAfile is
present to show the server that my client's certificate (test.crt)
chains to a CA trusted by the server.

Here is debug output from my script:

-----BEGIN OUTPUT
SSL_connect:before/connect initialization
SSL_connect:SSLv2/v3 write client hello A
SSL_connect:SSLv3 read server hello A
SSL_connect:SSLv3 read server certificate A
SSL_connect:SSLv3 read server done A
SSL_connect:SSLv3 write client key exchange A
SSL_connect:SSLv3 write change cipher spec A
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL_connect:SSLv3 read finished A
SSL_connect:SSL renegotiate ciphers
SSL_connect:SSLv3 write client hello A
SSL_connect:SSLv3 read server hello A
SSL_connect:SSLv3 read server certificate A
SSL_connect:SSLv3 read server certificate request A
SSL_connect:SSLv3 read server done A
SSL_connect:SSLv3 write client certificate A
SSL_connect:SSLv3 write client key exchange A
SSL_connect:SSLv3 write certificate verify A
SSL_connect:SSLv3 write change cipher spec A
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL3 alert read:fatal:unknown CA
SSL_connect:failed in SSLv3 read finished A
-----END OUTPUT-----

The Perl module my script is using, Crypt::SSLeay, has options
comparable to -CAfile and -CAdir, but when specified I get the following
debug output which seems to be telling me that the *client* failed to
verify the server's cert:

-----BEGIN OUTPUT-----SSL_connect:before/connect initialization
SSL_connect:SSLv2/v3 write client hello A
SSL_connect:SSLv3 read server hello A
SSL3 alert write:fatal:unknown CA
SSL_connect:error in SSLv3 read server certificate B
SSL_connect:error in SSLv3 read server certificate B
SSL_connect:before/connect initialization
SSL_connect:SSLv3 write client hello A
SSL_connect:SSLv3 read server hello A
SSL3 alert write:fatal:bad certificate
SSL_connect:error in SSLv3 read server certificate B
SSL_connect:before/connect initialization
SSL_connect:SSLv2 write client hello A
SSL_connect:failed in SSLv2 read server hello A
-----END OUTPUT-----

So I need to figure out where things are going wrong in Crypt::SSLeay,
which is basically just a wrapper around OpenSSL. Since I was successful
in connecting with s_client, I looked in s_client.c and found this:

      SSL_CTX_set_verify(ctx,verify,verify_callback);
      if (!set_cert_stuff(ctx,cert_file,key_file))
        goto end;

      if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) ||
          (!SSL_CTX_set_default_verify_paths(ctx)))
        {
          /* BIO_printf(bio_err,"error setting default verify
locations\n"); */
          ERR_print_errors(bio_err);
          /* goto end; */
        }

      store = SSL_CTX_get_cert_store(ctx);
      X509_STORE_set_flags(store, vflags);

      con=SSL_new(ctx);

So it would appear that SSL_CTX_load_verify_locations is the OpenSSL
function that gets called with CAfile. Looking inside SSLeay.xs, which
implements the Perl glue to OpenSSL functions, I find:

      SV*
      SSL_CTX_set_verify(ctx)
        SSL_CTX* ctx
        PREINIT:
          char* CAfile;
          char* CAdir;
        CODE:
          CAfile=getenv("HTTPS_CA_FILE");
          CAdir =getenv("HTTPS_CA_DIR");

          if(!CAfile && !CAdir) {
            SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
            RETVAL = newSViv(0);
          } else {
            SSL_CTX_load_verify_locations(ctx,CAfile,CAdir);
            SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
            RETVAL = newSViv(1);
          }
        OUTPUT:
          RETVAL

This appears to be doing the right thing since it calls
SSL_CTX_load_verify_locations, but I am unsure that I understand Perl XS
well enough to confirm this.

It may be unimportant, but the only suspicious thing I can see is that
s_client calls SSL_CTX_set_verify before calling
SSL_CTX_load_verify_locations whereas SSLeay.xs reverses the order of
those calls. Is that significant? If not, does anyone have hints as to
where to look for a solution?

Thanks,
-- 
Sean Evans

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    [EMAIL PROTECTED]
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to