16 Stimmen

Überprüfen von Clientzertifikaten in PyOpenSSL

Ich schreibe eine App, die erfordert, dass ein Zertifikat im Browser des Clients installiert wird. Ich habe dies in der PyOpenSSL-Dokumentation für das "Context"-Objekt gefunden, aber ich kann nichts darüber finden, wie der Callback das Zertifikat validieren soll, nur dass es irgendwie sollte.

   set\_verify(mode, callback)
      Legt die Überprüfungsflags für dieses Context-Objekt auf den Modus fest und
      gibt an, dass der Callback für Überprüfungsrückrufe verwendet werden soll.
      Modus sollte einer von VERIFY\_NONE und VERIFY\_PEER sein. Wenn
      VERIFY\_PEER verwendet wird, kann der Modus mit
      VERIFY\_FAIL\_IF\_NO\_PEER\_CERT und VERIFY\_CLIENT\_ONCE kombiniert werden, um das Verhalten weiter zu steuern. Der Callback sollte fünf Argumente enthalten: Ein
      Verbindungsobjekt, ein X509-Objekt und drei Ganzzahlvariablen,
      die wiederum potenzielle Fehlernummer, Fehler Tiefe und Rückgabecode sind. Der Callback sollte true zurückgeben, wenn die Überprüfung erfolgreich ist, und
      andernfalls false.

Ich sage dem Context-Objekt, wo meine (selbstsignierten) Schlüssel sind (siehe unten), daher verstehe ich nicht, warum das nicht ausreicht, damit die Bibliothek überprüft, ob das vom Client vorgelegte Zertifikat gültig ist. Was muss man in dieser Callback-Funktion tun?

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

Hinweis: Ich programmiere hier aus Spaß, bin definitiv kein Profi, daher bitte sei nicht zu hart, wenn meine Frage meine totale Ahnungslosigkeit, Naivität und/oder grundlegendes Verständnis für SSL offenbart!

Danke :)

Roger

5voto

aculich Punkte 14009

In der OpenSSL-Dokumentation für set_verify() ist der Schlüssel, den Sie interessiert, der Rückgabecode:

Der Rückruf sollte fünf Argumente annehmen: Ein Verbindungsobjekt, ein X509-Objekt und drei Ganzzahlvariablen, die wiederum potenzielle Fehler, Fehlerstufe und den Rückgabecode darstellen. Der Rückruf sollte true zurückgeben, wenn die Überprüfung erfolgreich ist, andernfalls false.

Es gibt ein voll funktionsfähiges Beispiel, das mehr oder weniger zeigt, was Sie tun möchten: Wann werden Client-Zertifikate überprüft?

Im Wesentlichen können Sie die ersten 4 Argumente ignorieren und einfach den Wert des Rückgabecodes im fünften Argument überprüfen, wie folgt:

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 "Schlechte Zertifikate"
        else:
            print "Zertifikate sind in Ordnung"
        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("Mein_experimenteller_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()

Hinweis: Ich habe noch eine weitere Änderung vorgenommen, die from OpenSSL.SSL import ... ist, um Ihren Code etwas zu vereinfachen, während ich ihn getestet habe, damit Sie nicht das Präfix SSL. vor jedem Importsymbol haben.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X