Check if the certificate of a domain was revoked

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
This entry was posted in Bash, Linux, Security, SSL/TLS and tagged , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *