How to utilize openssl in Linux to check SSL certificate details

SSL certificates are an integral component in securing data and connectivity to other systems. Learn tips on how you can use the Linux openssl command to find critical certificate details.

istock-689019766-1.jpg

Image: Getty Images/iStockphoto

Administering SSL certificates can be quite a chore, especially when it comes time to renew or replace them. Expiring SSL certificates can be devastating for technological operations, with the impact ranging from worrisome browser error messages to complete production outages. Therefore, it's important to not only keep an eye on upcoming SSL certificate expirations (network scans or at the very least a log keeping track of these certificates are essential) but to completely verify the success of renewing/replacing these certificates.

SEE: 5 Linux server distributions you should be using (TechRepublic Premium)

Certificate files in Linux are generally in the /etc/pki/tls/certs folder or possibly within an application-specific folder such as /etc/httpd for Apache (depending on the whim of the person or vendor who configured/built the application). These generally use .pem or .crt extensions and will likely be named '(hostname).pem' '(hostname).crt', but sometimes the generic "server" file name is used as well.

The openssl command is a veritable Swiss Army knife of functions you can use to administer your certificates. To example the details of a particular certificate, run the following command:

openssl x509 -in (path to certificate and certificate filename) -text -noout

You will see output similar to the following. The Issuer, Subject, Not Before/Note After and Subject Alternative Names fields will have the most useful details:

Certificate:
Data:
Version: 3 (0x2)
Serial Number:
11:00:00:05:16:07:eb:1b:1d:9f:88:81:98:00:00:00:00:05:16
Signature Algorithm: sha256WithRSAEncryption
Issuer: DC=int, DC=dev, CN=dev issuing low 01
Validity
Not Before: Mar 19 15:32:02 2021 GMT
Not After : Mar 19 15:42:02 2022 GMT
Subject: C=US, ST=MA, L=Boston, O=Contoso, OU=Systems, CN=test.contoso.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:e9:0d:7a:8c:55:54:4f:ef:67:a7:a0:54:de:8f:
bd:6c:cd:fe:e5:01:22:40:90:df:39:97:5a:f6:76:
c1:d9:00:d7:88:7e:7b:63:65:99:59:be:08:4a:3c:
2b:63:13:0d:42:3e:95:9d:cf:2f:2e:48:35:0e:9c:
6c:3f:b5:fd:75:4f:7c:86:34:80:c1:86:be:bf:0e:
0a:da:a7:eb:8b:97:9f:29:34:1b:fa:c8:b4:f5:57:
ec:98:a9:d1:d4:dc:07:6e:e0:14:51:a3:7a:5e:1c:
b4:e6:a1:14:01:59:a3:a3:04:f0:75:0c:2e:6f:34:
2c:72:a8:51:09:0d:ad:53:f4:34:58:ab:23:01:b8:
51:1a:2c:c3:3f:e2:75:4e:8d:55:9a:2b:60:c4:60:
67:7e:e9:82:78:73:fe:fc:38:a3:1f:1b:30:f7:46:
95:4f:88:b1:97:e1:6d:f6:85:3c:79:37:f5:47:44:
66:16:ad:3a:f2:fc:ce:db:a4:0c:2d:6d:1e:9e:20:
b9:b5:eb:ba:de:93:3a:02:a7:80:3f:f5:ca:21:d2:
b1:34:56:ba:95:df:0f:3a:f5:fa:83:96:fe:aa:51:
20:9d:20:d5:b2:85:24:90:ea:c7:cd:5d:a2:e7:a5:
ff:c3:d2:23:f9:ba:8c:ad:37:8b:8f:84:ad:22:04:
fc:2d
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Alternative Name:
DNS:test.contoso.com, DNS:testhost.contoso.com
X509v3 Subject Key Identifier:
93:F0:A5:5F:72:91:05:67:84:42:D2:0B:A1:48:54:8E:4E:BB:E0:A0
X509v3 Authority Key Identifier:
keyid:7D:F8:78:35:EE:A6:43:93:EF:E6:92:79:C9:15:49:12:51:77:EB:BB

X509v3 CRL Distribution Points:

Full Name:
URI:ldap:///CN=dev%20issuing%20low%2001,CN=ca1,CN=CDP,CN=Public%20Key%20Services,CN=Services,CN=Configuration,DC=dev,DC=int?certificateRevocationList?base?objectClass=cRLDistributionPoint

Authority Information Access:
CA Issuers - URI:ldap:///CN=dev%20issuing%20low%2001,CN=AIA,CN=Public%20Key%20Services,CN=Services,CN=Configuration,DC=dev,DC=int?cACertificate?base?objectClass=certificationAuthority

1.3.6.1.4.1.311.20.2:
...W.e.b.S.e.r.v.e.r
Signature Algorithm: sha256WithRSAEncryption
76:d6:6e:35:53:71:3b:1b:f6:12:23:b5:14:e2:73:c9:e7:d0:
68:e7:37:ab:35:bc:fc:e5:41:75:f1:84:11:20:ce:84:94:dc:
86:1d:11:7a:bd:a0:5a:8a:3b:ac:fc:f1:4d:5f:3a:3f:88:a8:
ff:ad:2e:2a:3f:91:a3:d5:28:f2:84:87:b6:17:62:a6:d2:d2:
25:34:e3:6d:c0:3b:93:f1:a2:22:8e:80:a1:fe:54:65:d6:10:
da:78:4b:0a:f7:eb:75:d5:9d:17:0b:87:8f:5c:2d:39:49:59:
b7:e6:b1:4a:c2:f0:de:68:6a:36:56:85:16:a4:01:46:21:b6:
49:33:0b:4a:ec:c5:69:6b:fa:ea:d7:d4:95:e1:f4:2d:17:c5:
ad:bd:1f:b6:73:cd:6c:ae:5d:ad:ed:0f:82:ed:43:1c:0e:ed:
54:93:83:d8:76:45:d6:45:3d:10:17:f4:eb:8a:84:e8:9a:9c:
c6:5c:92:df:2e:c0:64:6d:03:78:cd:59:dd:f3:e6:bb:5c:ac:
c0:9b:55:3f:a5:b6:12:90:0c:ea:e1:05:37:6b:19:86:53:f1:
83:d7:0b:23:6d:fe:5b:c8:2f:22:e3:b5:6a:bf:cd:45:27:62:
d8:1b:1c:a9:be:be:71:0c:07:bd:d3:c2:a4:63:1e:eb:7f:22:
31:3a:8b:25 

It's also equally useful to run a check against the port associated with an SSL certificate (e.g., 443 for a web server). You can run this command to check the expiration date of a certificate. I highly recommend running this before and after replacing or renewing an SSL certificate to confirm success. Note that when replacing application related certificates (such as for Apache) you'll likely need to restart the application or it to pick up the new certificate.

Either use this command on the host system itself or run it remotely against that system, substituting for "localhost" the fully qualified domain name (FQDN) of the host you wish to check and changing the port 443 as needed to match the open port associated with the SSL certificate.

openssl s_client -connect localhost:443 2>/dev/null | openssl x509 -noout -dates

You should receive output similar to the following:

Not Before: Mar 19 15:32:02 2021 GMT
Not After : Mar 19 15:42:02 2022 GMT  

This script below can also be used to extrapolate even more details about a certificate and as above can be used locally or remotely. 

I call it ssl_validate.sh, but you can copy the contents into a new script file with whatever name you like, use chmod +x to make it executable, and then use it with the following syntax:

./ssl_validate.sh (or whichever script name you choose) server.company.com:443, where "server.company.com" is the fully qualified domain name (FQDN) of the host you wish to check and 443 is the port it's listening on associated with the SSL certificate.

You need to ensure you have a path to that server and port such as through approved firewall entries.

The script will return output similar to the following to display the most salient details of the SSL certificate:

server.company.com:443  ;  SSL  ;  CN: (CN of the SSL certificate) ;  Subject (Subject of the SSL certificate)  ;  Issuer: (Issuer of the SSL certificate)   ;  notBefore: (Creation date of the SSL certificate) ;  notAfter: (Expiration date of the SSL certificate)  ;  DaysUntilExpiration: (Days remaining until the SSL certificate expires)  ;  Errors:  (Any related errors with the SSL certificate)

The script starts below:

delim=" ; "

export delim

serverport=${1}

export serverport

echo "#${serverport}"

date_today=$(date +%F)

datediff() {

    d1=$(date -d "$1" +%s)

    d2=$(date -d "$2" +%s)

    echo $(( (d1 - d2) / 86400 )) days

}

export -f datediff

sslscan() {

        local sp=${1}

tls_content=$(echo "Q" | openssl s_client -showcerts -connect ${serverport} 2>&1)

        if [[ "$?" == 0 ]]; then

                tls_errors=$(echo "${tls_content}" | grep -i error )

                tls_cert_subject=$(echo "${tls_content}" | openssl x509 -noout -subject )

                tls_cert_issuer=$(echo "${tls_content}" | openssl x509 -noout -issuer )

                tls_cert_cn=$(echo "${tls_content}" | openssl x509 -noout -subject | sed -e "s/.*CN=\([^\/]*\).*/\1/" )

                tls_cert_dates=$(echo "${tls_content}" | openssl x509 -noout -dates )

                tls_cert_notafter_date=$(echo "${tls_cert_dates}" | grep notAfter |sed -e "s/notAfter=//" | tr -d '\n')

                tls_cert_notbefore_date=$(echo "${tls_cert_dates}" | grep notBefor |sed -e "s/notBefore=//" | tr -d '\n')

                tls_cert_datediff=$(datediff "${tls_cert_notafter_date}" "${date_today}")

                echo -n "${serverport} ${delim} SSL"

                echo -n " ${delim} CN:"

                echo -n " ${tls_cert_cn}"

                echo -n " ${delim} Subject:"

                echo -n " ${tls_cert_subject}"

                echo -n " ${delim} Issuer:"

                echo -n " ${tls_cert_issuer}"

                echo -n " ${delim} notBefore:"

                echo -n " ${tls_cert_notbefore_date}"

                echo -n " ${delim} notAfter:"

                echo -n " ${tls_cert_notafter_date}"

                echo -n " ${delim} DaysUntilExpiration:"

                echo -n " ${tls_cert_datediff}"

                echo -n " ${delim} Errors:"

                echo -n " ${tls_errors}"

                echo

        else

                tls_errors=$(echo "${tls_content}" | tr '\n' '/' | tr ' ' '_' )

                status="ERROR: ${tls_errors}"

                echo -n "${serverport} ${delim} ${status}"

                echo

        fi

}

export -f sslscan

timeout 3 bash -c "sslscan ${serverport}"

if [[ $? != 0 ]]; then

        echo -n "${serverport} ${delim} ERROR: CONNECTION_TIMED_OUT"

        echo

fi

Also see