I need to scrape some data from an HTTPS site that requires client
certificates for authentication. I am able to access the site with a
certificate loaded in Netscape 7.1, so I exported the certificate to
PKCS12 and tried the following in Perl using LWP::UserAgent (which makes
use of Crypt::SSLeay for HTTPS):
__BEGIN__
use strict;
use LWP::UserAgent;
# DEBUGGING SWITCH / LOW LEVEL SSL DIAGNOSTICS
$ENV{HTTPS_DEBUG} = 1;
# DEFAULT SSL VERSION
$ENV{HTTPS_VERSION} = '3';
# CLIENT PKCS12 CERT SUPPORT
$ENV{HTTPS_PKCS12_FILE} = 'test.p12';
$ENV{HTTPS_PKCS12_PASSWORD} = 'password';
my $ua = new LWP::UserAgent;
my $req = new HTTP::Request('GET', 'https://example.com');
my $res = $ua->request($req);
print $res->status_line."\n";
__END__
Here's the debug output I get:
__BEGIN__
SSL_connect:before/connect initialization
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 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:certificate unknown
SSL_connect:failed in SSLv3 read finished A
500 read failed: error:14094416:SSL routines:SSL3_READ_BYTES:sslv3 alert
certificate unknown | error:140940E5:SSL routines:SSL3_READ_BYTES:ssl
handshake failure
__END__
The only explanation I have found for 'certificate unknown' in the spec
is not terribly helpful: "Some other (unspecified) issue arose in
processing the certificate, rendering it unacceptable." Does anyone have
any idea why the server is unhappy with my exported cert?
Thanks,
--
Sean Evans
______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List openss...@openssl.org
Automated List Manager majo...@openssl.org
I'm not familiar with that perl module. There are several possibilities. It
might not support PKCS#12. If it does support PKCS#12 it might not be sending
the whole client certificate chain.
You can check the NS 7.1 exported PKCS#12 file is OK with:
openssl pkcs12 -in file.p12 -out file.pem
You could also try connecting to s_server to see if it sends the certificate
properly or using s_client to connect to the HTTPS server and seeing if that
can be made to work.
Steve.
--
Dr Stephen N. Henson. Email, S/MIME and PGP keys: see homepage
OpenSSL project core developer and freelance consultant.
Funding needed! Details on homepage.
Homepage: http://www.drh-consultancy.demon.co.uk
The module claims support for PKCS#12. I'm guessing I would use s_server
to see if it sends the whole chain, but I'm new to this. Could you tell
me what I should look for to verify that the request is good?
> You can check the NS 7.1 exported PKCS#12 file is OK with:
>
> openssl pkcs12 -in file.p12 -out file.pem
This works fine.
Thanks for your quick response, Steve, I was unable to get help on the
appropriate Perl list.
--
Sean Evans
> > I'm not familiar with that perl module. There are several
> > possibilities. It might not support PKCS#12. If it does support
> > PKCS#12 it might not be sending the whole client certificate chain.
>
> The module claims support for PKCS#12. I'm guessing I would use s_server
> to see if it sends the whole chain, but I'm new to this. Could you tell
> me what I should look for to verify that the request is good?
>
From the 'apps' directory:
openssl s_server -verify 9 -www
then connect to localhost on port 4433 should do the trick. This makes it
behave like web server that sends a status page back with the connection
details.
Steve.
--
Dr Stephen N. Henson. Email, S/MIME and PGP keys: see homepage
OpenSSL project core developer and freelance consultant.
Funding needed! Details on homepage.
Homepage: http://www.drh-consultancy.demon.co.uk
> openssl s_server -verify 9 -www
This gave me my first non-enigmatic debug output, for which I thank you.
:-)
I get 'unable to verify the first certificate' which apparently means
that the chain is not included with the cert exported from Netscape.
Since I have no way to change the way Netscape exports certs, is there a
way to add the chain manually? Is that even what I should be trying to do?
I appreciate the help.
--
Sean Evans
> Steve,
>
> > openssl s_server -verify 9 -www
>
> This gave me my first non-enigmatic debug output, for which I thank you.
> :-)
>
> I get 'unable to verify the first certificate' which apparently means
> that the chain is not included with the cert exported from Netscape.
Either that or the perl module isn't including the full path when it performs
client authentication from a PKCS#12 file.
See what happens when you do:
openssl pkcs12 -in whatever.p12 -nokeys -cacerts -out cacerts.pem
If cacerts.pem is non empty you need to add the certificates in there as
'other certificates' or as the trusted certificate file using whatever options
that perl module requires.
Steve.
--
Dr Stephen N. Henson. Email, S/MIME and PGP keys: see homepage
OpenSSL project core developer and freelance consultant.
Funding needed! Details on homepage.
Homepage: http://www.drh-consultancy.demon.co.uk
Not sure what you mean by 'full path'.
> See what happens when you do:
>
> openssl pkcs12 -in whatever.p12 -nokeys -cacerts -out cacerts.pem
>
> If cacerts.pem is non empty you need to add the certificates in there
> as 'other certificates' or as the trusted certificate file using
> whatever options that perl module requires.
cacerts.pem was non empty, so I tried adding the certs in there to the
ca-bundle.crt file that I snagged from my Apache2 installation.
Crypt::SSLeay allows one to set an environment variable that points to
the location of a CA certificate peer verification. Is this, more or
less, what you were suggesting:
# CLIENT CERT SUPPORT
$ENV{HTTPS_CERT_FILE} = 'test.pem';
$ENV{HTTPS_KEY_FILE} = 'testkey.pem';
# CA CERT PEER VERIFICATION
$ENV{HTTPS_CA_FILE} = 'ca-bundle.crt';
$ENV{HTTPS_CA_DIR} = '.';
The Perl module seemed like it might be the problem, so I am now trying
to use s_client to figure out what's going on. Here's what I did:
1/ Exported my client certificate and key from the PKCS12 bag to PEM
files with:
openssl pkcs12 -in test.p12 -out test.pem -clcerts -nokeys
openssl pkcs12 -in test.p12 -out testkey.pem -nodes -nocerts
2/ Tried connecting using s_client like so:
openssl s_client -connect hostname:port -cert test.pem /
-key testkey.pem
This was the output:
-----BEGIN OUTPUT-----
Loading 'screen' into random state - done
CONNECTED(00000790)
depth=2 /C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification
Authority
verify error:num=19:self signed certificate in certificate chain
verify return:0
---
Certificate chain
0 s:/C=US/ST=california/L=Mountain view/O=Organization/OU=Unit/OU=Te
rms of use at blah.com/CN=hostname
i:/O=VeriSign Trust Network/OU=VeriSign, Inc./OU=VeriSign
International Serve
r CA - Class 3/OU=www.verisign.com/CPS Incorp.by Ref. LIABILITY
LTD.(c)97 VeriSi
gn
1 s:/O=VeriSign Trust Network/OU=VeriSign, Inc./OU=VeriSign
International Serve
r CA - Class 3/OU=www.verisign.com/CPS Incorp.by Ref. LIABILITY
LTD.(c)97 VeriSi
gn
i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification
Authority
2 s:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification
Authority
i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification
Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIEEjCCA3ugAwIBAgIQBAWMKuizg0P75Q9zLM5/tDANBgkqhkiG9w0BAQQFADCB
ujEfMB0GA1UEChMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazEXMBUGA1UECxMOVmVy
aVNpZ24sIEluYy4xMzAxBgNVBAsTKlZlcmlTaWduIEludGVybmF0aW9uYWwgU2Vy
dmVyIENBIC0gQ2xhc3MgMzFJMEcGA1UECxNAd3d3LnZlcmlzaWduLmNvbS9DUFMg
SW5jb3JwLmJ5IFJlZi4gTElBQklMSVRZIExURC4oYyk5NyBWZXJpU2lnbjAeFw0w
MjEyMjAwMDAwMDBaFw0wNDEyMTkyMzU5NTlaMIHFMQswCQYDVQQGEwJVUzETMBEG
A1UECBMKY2FsaWZvcm5pYTEWMBQGA1UEBxQNTW91bnRhaW4gdmlldzEXMBUGA1UE
ChQOQW1lcmljYSBPbmxpbmUxFjAUBgNVBAsUDUlDIE9wZXJhdGlvbnMxMzAxBgNV
BAsUKlRlcm1zIG9mIHVzZSBhdCB3d3cudmVyaXNpZ24uY29tL3JwYSAoYykwMDEj
MCEGA1UEAxQadGlja2V0dHJhY2tlci5uZXRzY2FwZS5jb20wgZ8wDQYJKoZIhvcN
AQEBBQADgY0AMIGJAoGBALcMI8KfUlFzBIQpaXvQB2NwJFpC/mdMFYX40R9I9oTU
iE2fK4XvzdHp0V2ZpRC/aTzIROcTIOck8m9ZzBIRnWqJKI8sf+d9ilus5WVHO21K
hHmpPGBrg70tMRulmxzeMUrxQrH1NEk7YmcaVIen59eSCIv+ruCOsi7rEhaEMEtX
AgMBAAGjggEKMIIBBjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDBGBgNVHR8EPzA9
MDugOaA3hjVodHRwOi8vY3JsLnZlcmlzaWduLmNvbS9DbGFzczNJbnRlcm5hdGlv
bmFsU2VydmVyLmNybDBEBgNVHSAEPTA7MDkGC2CGSAGG+EUBBxcDMCowKAYIKwYB
BQUHAgEWHGh0dHBzOi8vd3d3LnZlcmlzaWduLmNvbS9ycGEwKAYDVR0lBCEwHwYJ
YIZIAYb4QgQBBggrBgEFBQcDAQYIKwYBBQUHAwIwNAYIKwYBBQUHAQEEKDAmMCQG
CCsGAQUFBzABhhhodHRwOi8vb2NzcC52ZXJpc2lnbi5jb20wDQYJKoZIhvcNAQEE
BQADgYEAzf/jJ69D1PkwD0G+DrX/u1/ygHAst1DANAWo6bqxIYhkEUr/sTeSF65Q
ZwbwiSWf3NmvkOlPnMv3utWWa59sHw9agsvAfU3Q1DMwrpexM2eQ12Lj5vFuMi6v
/pYa3r5amkHAPv+h2+/B+fmM58e4VL76bOsaipgnbsKIjFGU65Y=
-----END CERTIFICATE-----
subject=/C=US/ST=california/L=Mountain view/O=organization/OU=unit/OU
=Terms of use at blah.com (c)00/CN=hostname
issuer=/O=VeriSign Trust Network/OU=VeriSign, Inc./OU=VeriSign
International Server CA - Class 3/OU=www.verisign.com/CPS Incorp.by Ref.
LIABILITY LTD.(c)97 Veri
Sign
---
No client certificate CA names sent
---
SSL handshake has read 2670 bytes and written 324 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-MD5
Server public key is 1024 bit
SSL-Session:
Protocol : TLSv1
Cipher : RC4-MD5
Session-ID:
05FE8CF3DEEFD6DACE59BB346C88D64B60027E6DF726FA18969634D47F7FBC48
Session-ID-ctx:
Master-Key:
5D8315F1257DD09DC6B72DF2479CFE96009CD5F5AC034B13D76D32092CADE621
6233EB2A4407D7A80026019134CF9B98
Key-Arg : None
Start Time: 1081453101
Timeout : 300 (sec)
Verify return code: 19 (self signed certificate in certificate chain)
---
get /
depth=2 /C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification
Authority
verify error:num=19:self signed certificate in certificate chain
verify return:0
3868:error:14094416:SSL routines:SSL3_READ_BYTES:sslv3 alert certificate
unknown
:.\ssl\s3_pkt.c:1052:SSL alert number 46
3868:error:140940E5:SSL routines:SSL3_READ_BYTES:ssl handshake
failure:.\ssl\s3_
pkt.c:989:
-----END OUTPUT-----
I'm at a loss, this is the same error I was getting from the Perl
module. I see plenty of dangerous-sounding messages in the output, but I
am uncertain which ones are pertinent. Any and all ideas welcome.
Thanks,
--
Sean Evans
Technical Support
703-265-0397
http://enterprise.aim.com
http://enterprise.netscape.com
> > > I get 'unable to verify the first certificate' which apparently
> > > means that the chain is not included with the cert exported from
> > > Netscape.
> >
> > Either that or the perl module isn't including the full path when it
> > performs
> > client authentication from a PKCS#12 file.
>
> Not sure what you mean by 'full path'.
>
The PKCS#12 file will typically contain the user certificate and private key
and any other certificates in the path.
If the perl module doesn't include any other certificates that could be the
problem.
> > See what happens when you do:
> >
> > openssl pkcs12 -in whatever.p12 -nokeys -cacerts -out cacerts.pem
> >
> > If cacerts.pem is non empty you need to add the certificates in there
> > as 'other certificates' or as the trusted certificate file using
> > whatever options that perl module requires.
>
> cacerts.pem was non empty, so I tried adding the certs in there to the
> ca-bundle.crt file that I snagged from my Apache2 installation.
> Crypt::SSLeay allows one to set an environment variable that points to
> the location of a CA certificate peer verification. Is this, more or
> less, what you were suggesting:
>
> # CLIENT CERT SUPPORT
> $ENV{HTTPS_CERT_FILE} = 'test.pem';
> $ENV{HTTPS_KEY_FILE} = 'testkey.pem';
>
> # CA CERT PEER VERIFICATION
> $ENV{HTTPS_CA_FILE} = 'ca-bundle.crt';
> $ENV{HTTPS_CA_DIR} = '.';
>
>
Yes thats's it. Since cacerts.pem is not empty the Netscape export is OK.
The 'self signed' error message is OK. It just means that s_client hasn't been
told which server certificates to trust.
As it stands s_client wont use any intermediate client CA certificates. I
suggest you also include "-CAfile cacerts.pem" on the s_client command line.
Also try the -prexit command line option. That should get you a list of valid
client CA names after you do "GET /".
Steve.
--
Dr Stephen N. Henson. Email, S/MIME and PGP keys: see homepage
OpenSSL project core developer and freelance consultant.
Funding needed! Details on homepage.
Homepage: http://www.drh-consultancy.demon.co.uk
I tried running s_server and connecting with s_client like so:
openssl s_server -cert snakeoil-rsa.crt -key snakeoil-rsa.key -www
openssl s_client -connect localhost:4433 -cert test.pem -key testkey.pem
The problem is that s_server is telling me 'no client certificate
available'. Why would s_client not be presenting the certificate? I
created test.pem and testkey.pem using:
openssl pkcs12 -in test.p12 -out test.pem -clcerts -nokeys
openssl pkcs12 -in test.p12 -out testkey.pem -nocerts -nodes
Is there something I've missed?
--
Sean Evans
Technical Support
703-265-0397
http://enterprise.aim.com
http://enterprise.netscape.com
______________________________________________________________________
> > Also try the -prexit command line option. That should get you a list
> > of valid
> > client CA names after you do "GET /".
>
> I tried running s_server and connecting with s_client like so:
>
I meant try that on the server that's giving the error.
> openssl s_server -cert snakeoil-rsa.crt -key snakeoil-rsa.key -www
> openssl s_client -connect localhost:4433 -cert test.pem -key testkey.pem
>
> The problem is that s_server is telling me 'no client certificate
> available'. Why would s_client not be presenting the certificate? I
> created test.pem and testkey.pem using:
>
> openssl pkcs12 -in test.p12 -out test.pem -clcerts -nokeys
> openssl pkcs12 -in test.p12 -out testkey.pem -nocerts -nodes
>
> Is there something I've missed?
>
The server must request a certificate for the client to send one. You need
"-verify 9" or something similar in the s_server command.
Steve.
--
Dr Stephen N. Henson. Email, S/MIME and PGP keys: see homepage
OpenSSL project core developer and freelance consultant.
Funding needed! Details on homepage.
Homepage: http://www.drh-consultancy.demon.co.uk