Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

For example, I want to find out when the certificate for encrypted.google.com expires (i.e. Not After date), and what other domains may use it for authentication (Subject Alternative Names).

share|improve this question
    
I don't think we need the x509 tag. In 30k+ Q's this the 1st time it's come up, I think for the level of this Q the use of ssl and certificates is plenty. Please correct me if I'm wrong. –  slm Dec 11 '13 at 2:33
    
These are all the Q's that contain x509: unix.stackexchange.com/search?q=x509 –  slm Dec 11 '13 at 2:40
    
On the off chance I asked this Q on meta: meta.unix.stackexchange.com/questions/2565/… –  slm Dec 11 '13 at 2:44
    
Looking at answers below, apparently the x509 certificates had little to none to do with the problem. –  Braiam Dec 12 '13 at 15:15

2 Answers 2

up vote 7 down vote accepted

You could simply write it:

openssl s_client -showcerts -connect encrypted.google.com:443 < /dev/null \
   2> /dev/null | openssl x509 -noout -enddate

Other options than -enddate can be used to retrieve other fields. -text outputs most of the information.

See also keytool from java:

keytool -printcert -sslserver encrypted.google.com:443

It will print the whole certificate chain if possible (some of the certificate possibly retrieved from the Java certificate store).

share|improve this answer
    
what about Subject Alternative Names? –  J.F. Sebastian Dec 10 '13 at 22:23
1  
@J.F.Sebastian, openssl x509 only displays it with -text –  Stéphane Chazelas Dec 10 '13 at 22:40
    
@J.F.Sebastian - I saw no other method in wiki either beyond -text. wiki.cacert.org/FAQ/subjectAltName. I think what Stephane's provided is your answer. –  slm Dec 11 '13 at 2:56
1  
@slm, note that J.F.Sebastian answered his own question, he was just sharing his nice script to retrieve certificate information in a useful way. I was just mentioning an alternative way to call the openssl command. (generally, you don't need -in as openssl takes its input from stdin, and you can retrieve (some) individual parameters without having to parse the output of -text). –  Stéphane Chazelas Dec 11 '13 at 9:57
    
@StephaneChazelas - I hadn't given the other answer a thorough look, since it looked like an awful lot of code, now looking at it I see what you're saying. Thanks. –  slm Dec 11 '13 at 12:49

To print server's certificate as text using openssl:

#!/bin/bash
#
# Show server's certificate in a human-readable form.
#
# Usage: $ show-cert HOST [PORT]
#
exec <&- # close stdin to suppress `read:errno=0` from openssl
exec openssl x509 -noout -text \
     -in <(openssl s_client -connect "$1":"${2:-443}" -showcerts)

Or using Python to get output in json format:

#!/usr/bin/env python3
"""Show server's certificate as json.

Usage:
  $ %(prog)s HOST [PORT]
"""
import json
import socket
import ssl
import sys

# from ssl.py Python 3.4
def create_client_context(*, cafile=None, capath=None, cadata=None):
    context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
    # SSLv2 considered harmful.
    context.options |= ssl.OP_NO_SSLv2
    # disable compression to prevent CRIME attacks (OpenSSL 1.0+)
    context.options |= getattr(ssl._ssl, "OP_NO_COMPRESSION", 0)
    # disallow ciphers with known vulnerabilities
    # HIGH: high encryption cipher suites with key length >= 128 bits (no MD5)
    # !aNULL: only authenticated cipher suites (no anonymous DH)
    # !RC4: no RC4 streaming cipher, RC4 is broken
    # !DSS: RSA is preferred over DSA
    _RESTRICTED_CIPHERS = 'HIGH:!aNULL:!RC4:!DSS'
    context.set_ciphers(_RESTRICTED_CIPHERS)
    # verify certs and host name in client mode
    context.verify_mode = ssl.CERT_REQUIRED
    if cafile or capath or cadata:
        context.load_verify_locations(cafile, capath, cadata)
    else:
        context.set_default_verify_paths() # may fail silently!
    return context


# from ssl.py
def getcert(addr):
    """Retrieve server's certificate at the specified address (host, port)."""
    with  socket.create_connection(addr) as sock:
        context = create_client_context()
        with context.wrap_socket(sock) as sslsock:
            cert = sslsock.getpeercert()
            ssl.match_hostname(cert, addr[0])
            return cert

def main(argv):
    host = argv[1]
    port = int(argv[2]) if len(argv) > 2 else 443
    print(json.dumps(getcert((host, port)), indent=2, sort_keys=True))

if __name__ == "__main__":
    main(sys.argv)

Example:

$ getcert encrypted.google.com | jq -r '.notAfter, .subjectAltName[][1]'
Mar 20 00:00:00 2014 GMT
*.google.com
*.android.com
*.appengine.google.com
*.cloud.google.com
...

The latest version: getcert.py

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.