In Python 3.4, a verify_flags
that can be used to check if a certificate was revoked against CRL, by set it to VERIFY_CRL_CHECK_LEAF
or VERIFY_CRL_CHECK_CHAIN
.
I wrote a simple program for testing. But on my systems, this script failed to verify ANY connections even if it's perfectly valid.
import ssl
import socket
def tlscheck(domain, port):
addr = domain
ctx = ssl.create_default_context()
ctx.options &= ssl.CERT_REQUIRED
ctx.verify_flags = ssl.VERIFY_CRL_CHECK_LEAF
ctx.check_hostname = True
#ctx.load_default_certs()
#ctx.set_default_verify_paths()
#ctx.load_verify_locations(cafile="/etc/ssl/certs/ca-certificates.crt")
sock = ctx.wrap_socket(socket.socket(), server_hostname=addr)
sock.connect((addr, port))
import pprint
print("TLS Ceritificate:")
pprint.pprint(sock.getpeercert())
print("TLS Version:", sock.version())
print("TLS Cipher:", sock.cipher()[0])
exit()
tlscheck("stackoverflow.com", 443)
My code always quits with ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:645)
.
First I suspected that the certificate database was not loaded properly. But after I tried load_default_certs()
, set_default_verify_paths()
, load_verify_locations(cafile="/etc/ssl/certs/ca-certificates.crt")
, and none of them worked.
Also, ctx.options &= ssl.CERT_REQUIRED
works as expected, it can tell if a certificate chain is trusted or not. But not for CRLs... It also indicates that my CAs are correct.
I know "/etc/ssl/certs/ca-certificates.crt" contains valid CAs. What is the problem?
To check against CRL you have to manually download the CRL and put them in the right place so that the underlying OpenSSL library will find it. There is no automatic downloading of CRL and specifying the place where to look for the CRL is not intuitive either. What you can do:
openssl crl -inform der -in sha2-ha-server-g5.crl > sha2-ha-server-g5.crl.pem
ctx.load_verify_locations(cafile="./sha2-ha-server-g5.crl.pem")
This way you can verify the certificate against the CRL.