Checking the issued and expiry dates for the certificates involved a certificate chain

Is it possible to check the issued and expiry dates for the certificates involved in a certificate chain by just passing a domain?

I tired various openssl s_client attributes, but I am not able to get the required information.

Requirement:

Pass a domain (along with port 443), and using a script or a command in linux output the issued and expiry dates involved in the certificate chain for the domain(web server).


Solution 1:

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)

Solution 2:

I'm not aware of a plugin to check issue dates, but checking the expiration date of certificates is a standard feature of the check_http plugin.

Specifically, see the -C option. As in:

./check_http -H www.google.com -C 14
OK - Certificate 'www.google.com' will expire on 09/11/2014 11:04.

Note that this will work on anything that uses SSL (LDAPS, IMAPS, etc.), not just HTTPS.

If you want to check certificates in the chain, you might want to try something like check_ssl_cert. (I have never used it, but the usage info looks like it does what you want.)