Python Failed to Verify any CRLs for SSL/TLS connections
<p>In Python 3.4, a <code>verify_flags</code> that can be used to check if a certificate was revoked against CRL, by set it to <code>VERIFY_CRL_CHECK_LEAF</code> or <code>VERIFY_CRL_CHECK_CHAIN</code>.</p>

<p>I wrote a simple program for testing. But on my systems, this script failed to verify ANY connections even if it's perfectly valid. </p>

<pre><code>import ssl
import socket

def tlscheck(domain, port):
        addr = domain

        ctx = ssl.create_default_context()
        ctx.options &amp;= 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)
</code></pre>

<p>My code always quits with <code>ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:645)</code>. </p>

<p>First I suspected that the certificate database was not loaded properly. But after I tried <code>load_default_certs()</code>, <code>set_default_verify_paths()</code>, <code>load_verify_locations(cafile="/etc/ssl/certs/ca-certificates.crt")</code>, and none of them worked.</p>

<p>Also, <code>ctx.options &amp;= ssl.CERT_REQUIRED</code> 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.</p>

<p>I know "/etc/ssl/certs/ca-certificates.crt" contains valid CAs. What is the problem?</p>

<p>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:</p>

<ul>
<li>get the CRL distribution points from the certificate. For stackoverflow.com one is <a href="http://crl3.digicert.com/sha2-ha-server-g5.crl" rel="nofollow">http://crl3.digicert.com/sha2-ha-server-g5.crl</a></li>
<li>download the current CRL from there</li>
<li>convert it from the DER format to PEM format, because this is what is expected in the next step: <br>
<code>openssl crl -inform der -in sha2-ha-server-g5.crl  &gt; sha2-ha-server-g5.crl.pem</code></li>
<li>add the location to the verify_locations:<br>
<code>ctx.load_verify_locations(cafile="./sha2-ha-server-g5.crl.pem")</code></li>
</ul>

<p>This way you can verify the certificate against the CRL. </p>

python ssl