I have a CentOS 5.9 server, from which I need to make SSL connections to another server. The remote server has a certificate ultimately signed by the GeoTrust Global CA. At the time of writing, this certificate is the second one listed on GeoTrust's download page. I am getting inconsistent results, depending on whether I use OpenSSL or curl to make the connection:
openssl s_client -connect <server>:443 -CAfile /path/to/GeoTrustCA.pem
works fine, but
curl --cacert /path/to/GeoTrustCA.pem https://<server>/
fails with the standard "could not verify certificate" error.
Here are details of the tools I'm using:
$ curl --version
curl 7.15.5 (i386-redhat-linux-gnu) libcurl/7.15.5
OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5 Protocols: tftp ftp telnet dict
ldap http file https ftps Features: GSS-Negotiate IDN IPv6 Largefile
NTLM SSL libz
and
$ openssl version
OpenSSL 0.9.8e-fips-rhel5 01 Jul 2008
I'm stumped. The server I'm connecting to has been working with no apparent problems for years: I've never heard of anyone or any system being unable to connect to it like this.
Best Answer
I was curious about this so I did some testing. From what I can tell, there appears to be a fundamental difference in what
openssl
andcurl
take into consideration when using their root CA switches (-CAfile
and--cacert
respectively).When the
--cacert
switch is used incurl
, it appears to ONLY use the admin-specified root during verification. For example, I download the GeoTrust PEM file you mentioned earlier and tried using it to fetch a page from yahoo:Now, I tried the same test with
openssl
:You'll note that there are no errors in the initial chain description and that it shows
Verify return code: 0 (ok)
at the bottom.So even though GeoTrust isn't mentioned at all in the certificate chain, OpenSSL is somehow able to validate/verify the root.
Hmmm...
That got me to thinking about where the default truststore for openssl is... for some reason I had difficulty finding information about it online (I'm sure it's well documented and I'm just blind). Upon poking around on my system, I came across
/etc/pki/tls/certs/ca-bundle.crt
I searched in ca-bundle.crt and removed the root that yahoo uses (/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority) and ran the same exact command again:
This time, we get verification errors.
Soooooo, with all that said, I'm inclined to suspect the following:
curl
ONLY uses the root you tell it to use.openssl
uses the root you point it to ANNNND whatever roots are in its default truststore.As for why openssl does this? No idea. The documentation for that switch doesn't mention this workflow/behavior:
Perhaps someone else can examine the code for openssl and elaborate further.