I'm writing an app that requires a cert to be installed in the client browser. I've found this in the PyOpenSSL docs for the "Context" object but I can't see anything about how the callback is supposed to validate the cert, only that it should, somehow.
set_verify(mode, callback) Set the verification flags for this Context object to mode and specify that callback should be used for verification callbacks. mode should be one of VERIFY_NONE and VERIFY_PEER. If VERIFY_PEER is used, mode can be OR:ed with VERIFY_FAIL_IF_NO_PEER_CERT and VERIFY_CLIENT_ONCE to further control the behaviour. callback should take five arguments: A Connection object, an X509 object, and three integer variables, which are in turn potential error number, error depth and return code. callback should return true if verification passes and false otherwise.
I'm telling the Context object where my (self signed) keys are (see below) so I guess I don't understand why that's not enough for the library to check if the cert presented by the client is a valid one. What should one do in this callback function?
class SecureAJAXServer(PlainAJAXServer):
def __init__(self, server_address, HandlerClass):
BaseServer.__init__(self, server_address, HandlerClass)
ctx = SSL.Context(SSL.SSLv23_METHOD)
ctx.use_privatekey_file ('keys/server.key')
ctx.use_certificate_file('keys/server.crt')
ctx.set_session_id("My_experimental_AJAX_Server")
ctx.set_verify( SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT | SSL.VERIFY_CLIENT_ONCE, callback_func )
self.socket = SSL.Connection(ctx, socket.socket(self.address_family, self.socket_type))
self.server_bind()
self.server_activate()
Caveat: Coding for fun here, def not a pro so if my Q reveals my total lameness, naivety and/or fundamental lack of understanding when it comes to SSL please don't be too rough!
Thanks :)
Roger
The certificate has to be validated against its signing authority This is accomplished by verifying the signature on the certificate with the signing authority's public key. In addition, certificate revocation lists (CRLs) are checked to ensure the cert hasn't been blacklisted.
Certification holders may now have others easily verify their certification status by using a unique certificate verification code. The code can be found in the top right-hand corner on all digital certificates issued by the Python Institute.
What Does Client Authentication Certificate Mean? A client authentication certificate is a certificate used to authenticate clients during an SSL handshake. It authenticates users who access a server by exchanging the client authentication certificate.
Either the client did not send the certificate for some reason or else the client did not have a certificate issued by a CA that was also trusted by IIS server. If the client sends a certificate which is not mutually trusted by both client and the server you may see this error.
In the OpenSSL documentation for set_verify()
, the key that you care about is the return code:
callback should take five arguments: A Connection object, an X509 object, and three integer variables, which are in turn potential error number, error depth and return code. callback should return true if verification passes and false otherwise.
There is a a full working example that shows more or less what you want to do: When are client certificates verified?
Essentially you can ignore the first 4 arguments and just check the value of the return code in the fifth argument like so:
from OpenSSL.SSL import Context, Connection, SSLv23_METHOD
from OpenSSL.SSL import VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE
class SecureAJAXServer(BaseServer):
def verify_callback(connection, x509, errnum, errdepth, ok):
if not ok:
print "Bad Certs"
else:
print "Certs are fine"
return ok
def __init__(self, server_address, HandlerClass):
BaseServer.__init__(self, server_address, HandlerClass)
ctx = Context(SSLv23_METHOD)
ctx.use_privatekey_file ('keys/server.key')
ctx.use_certificate_file('keys/server.crt')
ctx.set_session_id("My_experimental_AJAX_Server")
ctx.set_verify( VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE, verify_callback )
self.socket = Connection(ctx, socket.socket(self.address_family, self.socket_type))
self.server_bind()
self.server_activate()
Note: I made one other change which is from OpenSSL.SSL import ...
to simplify your code a bit while I was testing it so you don't have the SSL.
prefix in front of every import symbol.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With