I am using Python 3. I am using a SSLContext
from the ssl
library.
I would like to know how to request and get the remote peer certificate (as with SSLSocket.getpeercert()
) but in the CERT_NONE
mode. Currently, I get an empty dict (which is expected as per the documentation). So, can I do that without digging into private stuff?
N.B.
I am not trying to reimplement crypto. Actually, I don't need any crypto, however I need the context (and a socket) and the remote certificate (again, for information purpose, not to authenticate or actually encrypt anything).
Python/OpenSSL mix requesting the client certificate certificate with validating it:
CERT_NONE
(OpenSSL: SSL_VERIFY_NONE
) will not request the certificate from the client at all. This means the client will not send a certificate.
CERT_REQUIRE
(OpenSSL: SSL_VERFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT
) and CERT_OPTIONAL
(OpenSSL: SSL_VERIFY_PEER
) will request the certificate but then also fail if the certificate could not be verified.
What you would need is to require the certificate but then have a way to handle the validation yourself and just accept all client certificates. This could be done with a custom verification callback. In OpenSSL this could be done with SSL_CTX_set_verify. But unfortunately the Python ssl library don't seem to expose the necessary interface to have your own validation callback. But it should be possible to do with pyOpenSSL which lets you set your own verification callback.
I found a way without straying away from the default ssl
library (which has the advantage of being there):
socket.getpeercert(binary_form=True)
gives the certificate in DER format which is good enough for what I have to do.
Afaik, returning an empty dict is to avoid blindly trusting what people send in clear text and has not been verified.