[issue18293] ssl.wrap_socket (cert_reqs=...), getpeercert, and unvalidated certificates

Christian Heimes report at bugs.python.org
Tue Jun 25 15:00:35 CEST 2013


Christian Heimes added the comment:

> Thanks for the pointer about being able to get the server's DER certificate.  That will be useful.  Is there some reason to return DER but not PEM?  Or is this perhaps a bug that could be fixed in a future version of Python's ssl module?

It doesn't matter how getpeercert() returns the raw cert. PEM and DER
encode the X.509 same in ASN.1 notation. PEM is just the base64
representation with some line breaks surrounded BEGIN/END CERTIFICATE lines.

> Christian wrote: "Optional and required verification makes only a differen[ce] for client side certs."
> 
> I believe there is one small exception:  With SSL_VERIFY_NONE, a client will continue talking with a server with an invalid certificate.  With SSL_VERIFY_PEER, when a client fails to verify the server's certificate, the client will terminate the connection.

You are referring to server side certs, that is the server provides a
cert and the client verifies it. I was talking about client side cert
(aka server mode), a rarely used mode in which the client side provides
a cert to the server. In CERT_OPTIONAL mode the client is allowed to
send no cert. CERT_REQUIRED is mapped to SSL_VERIFY_PEER |
SSL_VERIFY_FAIL_IF_NO_PEER_CERT.

> Ideally, I would like a client to be able to get both of  the following from the API: (a) the server's certificate (and chain?), and (b) whether or not the certificate (and chain?) is valid (against a given sets of root certs).

In client mode you already have the server's cert and as much of the
chain as the peer (server) provides. SSL_VERIFY_NONE makes no difference
because the server cert is used in the ClientHello / ServerHello
handshake and session key negotiation.

Perhaps you are a bit confused by Python's ssl API. Somebody once made
the choice to return an empty dict from getpeercert(False) when
SSL_VERIFY_NONE is used. That's all. :)
http://hg.python.org/cpython/file/76196691b5d0/Modules/_ssl.c#l1098

> I'm not sure how much of this functionality the Python developers might be interested in putting into Python 3.4?  Given that M2Crypto does not work with Python 3.x at all (at least not yet?), I am interested in finding something that will work with Python 3.x and give me the functionality I want.

I'd rather not implement a full wrapper for X509_STORE_CTX and X509
certs. It's way too much code, super complex and easily confuses even
experienced developers. Python's ssl module is limited to core
functionality by design and choice.

However I might be intrigue to implement support for
SSL_CTX_set_cert_verify_callback() or SSL_CTX_set_verify().
SSL_CTX_set_cert_verify_callback() has more potential, e.g.

def cert_verify_callback(sslsocket, storectx, verify_ok):
    context = sslsocket.context

storectx is a minimal X509_STORE_CTX object and verify_ok the boolean
return value of X509_verify_cert(). Without a cert verify callback
OpenSSL just uses the return value of X509_verify_cert()
(ssl/ssl_cert.c:ssl_verify_cert_chain()). sslsocket gives you access to
the peer's cert and chain (with #18233).

The callback could be used for multiple uses cases like cert
blacklisting, too.

----------

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue18293>
_______________________________________


More information about the Python-bugs-list mailing list