Just had the need to quickly check if the certificate of a domain was revoked or not, and found this tutorial: OpenSSL: Manually verify a certificate against a CRL
Well done, but two problems:
- If the server doesn’t send all certificates (including the root CA), the verify process will fail
- Too much to type…
So i quickly created a bash script to address these issues and do all the stuff much more easily.
It takes one to three options:
- <domain>: The domain you want to check (f.ex. “google.com”)
- <keepfiles>: (Optional) 0 or 1. Keep all the certs and don’t clean it up at the end (it creates all files in you current folder as <domain>.yyy.zzz)
- <trusted CA file>: (Optional) The path to the file containing the locally installed/trusted CAs. On CentOS/Fedora it automatically uses “/etc/pki/tls/certs/ca-bundle.crt”. If you get an error like “error 2 at 2 depth lookup:unable to get issuer certificate” you very likely have to specify it.
Download: checkcertcrl.sh
#!/bin/bash if [ -z "$1" ]; then echo "Usage: $0 <domain> [<keepfiles (0/1)>] [<trusted CA file bu<a href="https://nethack.ch/wp-content/uploads/2016/08/checkcertcrl.sh_.gz" rel="">checkcertcrl.sh</a>ndle path>]" exit 1 fi DOMAIN=$1 KEEPFILES=0 if [ "$2" = "1" ]; then KEEPFILES=1 fi LOCALCAFILE="" if [ ! -z "$3" ] && [ ! -f "$3" ]; then echo "ERROR: The file \"${3}\" does not exists. It must point to a file containing your local trusted CAs. For CentOS f.ex. it's \"/etc/pki/tls/certs/ca-bundle.crt\" by default." exit 1 else if [ -z "$3" ]; then # Check if the default CentOS CA bundle exists and use this if no other file was specified if [ -f "/etc/pki/tls/certs/ca-bundle.crt" ]; then LOCALCAFILE="/etc/pki/tls/certs/ca-bundle.crt" fi else LOCALCAFILE="$3" fi fi # Get the domain certificate echo -n " Get domain certificate: " openssl s_client -connect ${DOMAIN}:443 -servername ${DOMAIN} 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p' > ${DOMAIN}.cert.pem echo "OK" echo -n " Get the CRL file: " # Get CRL URL from cert and download it CRLURL=`openssl x509 -noout -text -in ${DOMAIN}.cert.pem | grep -A 4 'X509v3 CRL Distribution Points' | grep URI | cut -d':' -f 2-10` # Check if a CRL URL was returned and exit if not if [ "$CRLURL" = "" ]; then echo -e "ERROR: No CRL URL found in certificate. Verification not possible.\n Could be that it's OCSP only." exit 1 fi wget --quiet -O ${DOMAIN}.crl.der $CRLURL if [ $? -ne 0 ]; then echo "ERROR: Failed to download CRL" exit 1 fi echo "OK" # Convert CRL to pem echo -n " Convert CRL: " openssl crl -inform DER -in ${DOMAIN}.crl.der -outform PEM -out ${DOMAIN}.crl.pem echo "OK" # Get all certificates in the chain echo -n " Get all certificates in chain: " OLDIFS=$IFS; IFS=':' certificates=$(openssl s_client -connect ${DOMAIN}:443 -servername ${DOMAIN} -showcerts -tlsextdebug -tls1 2>&1 </dev/null | sed -n '/-----BEGIN/,/-----END/ {/-----BEGIN/ s/^/:/; p}'); for certificate in ${certificates#:}; do echo $certificate >> ${DOMAIN}.chain.pem ; done; IFS=$OLDIFS echo "OK" # Merge local CAs, chain and CRL echo -n " Merge chain and CRL: " cat $LOCALCAFILE ${DOMAIN}.chain.pem ${DOMAIN}.crl.pem > ${DOMAIN}.crl_chain.pem echo "OK" # Finally, check if the cert was revoked echo " Verify certificate:" openssl verify -crl_check -CAfile ${DOMAIN}.crl_chain.pem ${DOMAIN}.cert.pem # Cleanup if [ $KEEPFILES = 0 ]; then rm -f ${DOMAIN}.cert.pem ${DOMAIN}.crl.der ${DOMAIN}.crl.pem ${DOMAIN}.chain.pem ${DOMAIN}.crl_chain.pem fi exit 0