The trust store used by my Firefox browser (on Windows) contains a lot of root CA certificates,
and also some intermediate CA certificates (maybe I imported them, maybe my sysadmin did, maybe they came with my browser, but they're there). The root CA certificates are self-signed, the intermediate CA certificates are signed using another certificate from my trust store.
Other browser's trust stores that I checked:
curl's (usually located at
/usr/share/curl/curl-ca-bundle.crt
) and
Java's (usually located at
$JRE/lib/security/cacerts
and accessed with
keytool -keystore cacerts -storepass changeit -list
) do not contain intermediate certificates (at least not the one I'm using below). They do contain the usual list of root certificates.
My Web server's SSL certificate is signed using one of those intermediate certificates. Here's what my chain looks like:
- GTE Cybertrust Global Root is signed by GTE Cybertrust Global Root (I saved this certificate to a file called
global.crt
) - Cybertrust Educational CA is signed by GTE Cybertrust Global Root (I saved this certificate to a file called
educational.crt
) - My server's certificate is signed by Cybertrust Educational CA (I saved this certificate to a file called
myserver.crt
)
To verify the signature by hand using
openssl I can use:
openssl verify -CAfile global.crt -untrusted educational.crt myserver.crt
When I first installed the certificate for my Web server (an
Apache httpd 2.0 server), I merely configured my own certificate (and corresponding private key):
SSLCertificateFile myserver.crt
This worked fine in my Firefox, which I used to test this server.
But curl refuses (unless I use the
--insecure
or the
--cacert
option with a concatenation of the two Cybertrust certificates). Apparently the Web server needs to send the intermediate CA certificate as well (and possibly also the root CA certificate). Here's the correct setup:
SSLCertificateFile myserver.crt
SSLCertificateChainFile educational.crt
SSLCACertificateFile global.crt
While having intermediate certificates in you local trust store doesn't make you less secure, if you're testing your Web server setup it's a good idea to also test it with a minimal trust store. In fact, I found that the best way to test your server's SSL settings is using openssl:
openssl s_client -host myserver.com -port 443
This doesn't use a trust store at all. It shows the certificate chain and gives either an error 20 (unable to get local issuer certificate, in case the server only send the server and intermediate certificates), or an error 19 (self signed certificate in chain, in case the server also sent the root certificate). (Both errors are expected, other errors indicate something may be wrong.)