You don't need the root certificate in the chain (though I don't believe having it hurts anything).
That error is more of a warning from openssl in this case I think. I believe what it means is just that openssl doesn't know that it should trust the root certificate of that chain. If you pull out just the root certificate from that bundle and point that openssl command at it with the -CAfile
argument I expect that "error" should go away.
Inside the sf_bundle.crt file you should see two
-----BEGIN CERTIFICATE-----
....
-----END CERTIFICATE-----
blocks (possibly with plain text above each block showing what certificate the block contains). If you split each of those blocks into its own file so you end up with block1.crt
and block2.crt
you should be able to run openssl x509 -noout -subject -in <file.crt>
on each of them to get their respective certificate subject lines.
Assuming that block2.crt
has a subject line of /C=US/O=Starfield Technologies, Inc./OU=Starfield Class 2 Certification Authority
you should then be able to run openssl s_client -CAfile block2.crt -connect imap.domain.ltd:465
and that should, hopefully, connect without giving you the self-signed certificate error.
The answer is yes, you can do it with openssl
, you can easily wrap this up as a "check" script, but I'm not aware of a plugin that already does this.
First, cache the server certificate and intermediate chain:
echo Q | openssl s_client \
-connect www.google.com:443 -servername www.google.com -showcerts > chain.pem
(this chain file contains the site certificate, and the intermediate chain, along with other junk)
You should use -servername www.google.com
as well so that SNI enabled sites return the expected certificate.
If you only wish to output the details of each certificate in the chain file:
gawk 'BEGIN { pipe="openssl x509 -noout -subject -dates -serial "} \
/^-+BEGIN CERT/,/^-+END CERT/ { print | pipe }
/^-+END CERT/ { close(pipe); printf("\n")} ' chain.pem
Add/omit -serial
, -issuer
, -fingerprint
, -purpose
as preferred, to the embedded openssl
command. You can even glue both steps together as one line with (taking care to omit the redirection and chain.pem
occurrences):
echo Q | openssl ... | gawk ...
If you wish to properly validate the chain, including date ranges, then read on.
Next, pull out just the site (first) certificate, I'll use sed
here because I'm lazy ;-)
sed -n '/-BEGIN/,/-END/p;/-END/q' chain.pem > site.pem
Then verify:
openssl verify -verbose -CAfile chain.pem site.pem
This is where the wheels come off: Google (correctly) does not provide the (self-signed) root CA (or "trust anchor") in the chain:
site.pem: /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
error 2 at 2 depth lookup:unable to get issuer certificate
So, pull the root certificate from Geotrust, save it and and set it up a suitable CA directory:
cd /usr/local/nagios/var/CA # example!
wget http://www.geotrust.com/resources/root_certificates/certificates/Equifax_Secure_Certificate_Authority.pem
c_rehash .
And try again:
openssl verify -verbose \
-CAfile chain.pem -CApath /usr/local/nagios/var/CA site.pem
(note the extra -CApath
parameter) and you get:
site.pem: OK
Now the bad news, openssl
doesn't set the return code to indicate success, failure or anything useful. You will need to process the output to make sure that everything is ok, basically anything other than a single line with "OK" indicates a problem. The expired certs you are looking for will show as:
error 10 at 2 depth lookup:certificate has expired
(where the depth may vary).
Notes and caveats:
- the server-provided chain should not contain the root (if it does, the client ought ignore it), work around this by adding
-CApath /some/path
to point to a (pre-hashed) directory of trusted root certs as shown above
- this does not catch mis-ordering of the chain file, nor superfluous certs in the chain file (neither are usually a problem for browsers, but a site validator will usually flag them -- at the very least these needlessly clutter up HTTPS handshakes)
- there's no requirement for the entire chain to be presented by the server, especially for longer chains, in which case adding those to the CApath directory will be required also
- the
chain.pem
created here has extra text junk in it, this doesn't present a problem for openssl
- each non-root certificate will link to its parent by name ("Issuer" field) and ID ("Authority Key Identifier" field) which you can use to find it. The AIA ("Authority Information Access") might also contain URLs to make obtaining them easier, but I find that is not usually the case)
Best Answer
Here is simple oneliner:
It's working on my CentOS, it's make three files
outfile00
,outfile01
andoutfile02
. So you could take certificate that you want from file.