python validation ssl client-certificates pyopenssl

python - Validación de certificados de cliente en PyOpenSSL



validation client-certificates (1)

Estoy escribiendo una aplicación que requiere que se instale un certificado en el navegador del cliente. He encontrado esto en los documentos de PyOpenSSL para el objeto "Contexto" pero no puedo ver nada sobre cómo se supone que la devolución de llamada debe validar el certificado, solo que debería, de alguna manera.

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.

Le estoy diciendo al objeto de contexto dónde están mis claves (autofirmadas) (ver a continuación), así que supongo que no entiendo por qué no es suficiente para que la biblioteca compruebe si el certificado presentado por el cliente es válido. ¿Qué se debe hacer en esta función de devolución de llamada?

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()

Advertencia: la codificación para la diversión aquí, definitivamente no es un profesional, así que si mi Q revela mi cojera total, ingenuidad y / o falta de comprensión fundamental cuando se trata de SSL, ¡por favor, no sea tan rudo!

Gracias :)

Roger


En la documentación de OpenSSL para set_verify() , la clave que le interesa es el código de retorno :

la devolución de llamada debe tomar cinco argumentos: un objeto Connection, un objeto X509 y tres variables enteras, que a su vez son el número de error potencial, la profundidad del error y el código de retorno . La devolución de llamada debe devolver true si pasa la verificación y false en caso contrario.

Hay un ejemplo completo de trabajo que muestra más o menos lo que quiere hacer: ¿ cuándo se verifican los certificados de cliente?

Esencialmente, puede ignorar los primeros 4 argumentos y simplemente verificar el valor del código de retorno en el quinto argumento, así:

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()

Nota: Hice otro cambio que es from OpenSSL.SSL import ... para simplificar un poco su código mientras lo estaba probando para que no tenga el SSL. Prefijo delante de cada símbolo de importación.