Wie kann ich Apache veranlassen, ein Client-SSL-Zertifikat anzufordern, ohne es anhand einer bekannten Zertifizierungsstelle überprüfen zu müssen?

9

Ich verwende Apache2 (2.2.3), um eine Site bereitzustellen, auf der sich Clients mit Zertifikaten authentifizieren sollen. Da ich nur überprüfen muss, ob ein Benutzer, der ein bestimmtes Zertifikat vorlegt, derselbe Benutzer ist, der dieses Zertifikat in der Vergangenheit vorgelegt hat, ist die CA, die das Zertifikat signiert, irrelevant. Es scheint jedoch, dass die Verwendung SSLVerifyClient requireerfordert SSLCACertificateFile ...(oder SSLCACertificatePath ...) und dann Apache nur Zertifikate akzeptiert, die von einer Zertifizierungsstelle in dieser Datei / diesem Pfad signiert wurden. Gibt es eine Möglichkeit, Apache dazu zu bringen, ein Client-Zertifikat zu akzeptieren, unabhängig von der ausstellenden / singenden Zertifizierungsstelle? (dh überprüfen Sie, ob der Client über den entsprechenden privaten Schlüssel zum präsentierten öffentlichen Schlüssel verfügt, ohne die ausstellende / signierende Zertifizierungsstelle zu überprüfen)

Isaac
quelle
Wie wollen Sie nachverfolgen, welche Zertifikate authentifiziert wurden?
Shane Madden
@ShaneMadden: So etwas wie eine Tabelle, die Zertifikate internen Benutzer-IDs zuordnet. Die Mechanik der Public-Key-Kryptographie würde einen Passwortaustausch ersetzen.
Isaac
2
Richtig - ich möchte damit sagen, dass Apache keine Tabellenzuordnung von Zertifikaten zu internen Benutzer-IDs durchführt. Wenn sich Benutzer mit Client-Zertifikaten authentifizieren sollen, geben Sie den von Ihnen signierten Benutzerzertifikaten. Wie Sie bereits erwähnt haben, gibt es OpenID-Anbieter, die genau das tun. Apache's mod_sslwurde entwickelt, um Benutzer basierend auf einer Zertifikatsignierungsbeziehung zu authentifizieren. Wenn Sie dies aus irgendeinem Grund lieber ignorieren möchten, müssen Sie die Zertifikatauthentifizierung in Ihrem eigenen Code implementieren, der auch die Zuordnung von Zertifikat zu Benutzer übernimmt.
Shane Madden
@ShaneMadden: Ich hatte gehofft, die Ausstellung von Zertifikaten zu vermeiden. Wenn ich nur von mir ausgestellte Zertifikate akzeptiere, sind Smartcard-basierte Zertifikate nicht verfügbar. Egal was ich mache, ein Teil des Systems wird auf Anwendungsebene stattfinden, aber da dort alle mod_sslMaschinen vorhanden sind, hatte ich gehofft, dass es einen Teil der Arbeit für mich erledigen könnte.
Isaac
1
@ShaneMadden Ein Vorteil von optional_no_caist, dass es für die Benutzeroberfläche besser sein kann, da Sie eine HTTP-Fehlermeldung anzeigen können, wenn etwas mit dem Zertifikat nicht stimmt (Sie könnten es nicht anders, da ein fehlerhaftes Client-Zertifikat die Verbindung vor der HTTP-Schicht stoppen würde ). Dies ist auch nützlich, wenn Sie alternative Methoden zum Überprüfen eines Zertifikats (z . B. WebID ) ausprobieren möchten . Sie haben Recht, Sie möchten, dass etwas die Überprüfung durchführt, und das würde nur dann wirklich funktionieren, wenn die Anforderung von Code (z. B. in PHP / CGI / Java) verarbeitet wird, nicht so sehr von Dateien.
Bruno

Antworten:

10

Wie Sie festgestellt haben, können Sie die Zertifikatsüberprüfung auf SSL / TLS-Handshake-Ebene in Apache Httpd mithilfe von deaktivieren SSLVerifyCLient optional_no_ca.

Das zweite Problem, mit dem Sie konfrontiert werden, besteht darin, den Client zum Senden des Zertifikats zu bewegen. Da Ihr Zertifikat nicht für eine PKI vorgesehen ist, kann es selbstsigniert sein und verschiedene Aussteller haben.

Wenn ein Client-Zertifikat angefordert wird, sendet der Server während des Handhsakes eine CertificateRequestTLS-Nachricht an den Client. Diese Nachricht enthält die certificate_authoritiesListe:

Eine Liste der definierten Namen akzeptabler Zertifizierungsstellen. Diese definierten Namen können einen gewünschten definierten Namen für eine Stammzertifizierungsstelle oder für eine untergeordnete Zertifizierungsstelle angeben; Somit kann diese Nachricht verwendet werden, um sowohl bekannte Wurzeln als auch einen gewünschten Autorisierungsraum zu beschreiben. Wenn die Liste certificate_authorities leer ist, kann der Client jedes Zertifikat des entsprechenden ClientCertificateType senden, es sei denn, es liegt eine gegenteilige externe Vereinbarung vor.

Browser verwenden dies, um auszuwählen, welches Client-Zertifikat gesendet werden soll (falls vorhanden).

(Beachten Sie, dass der Teil über die leere Liste nur in der Spezifikation ab TLS 1.1 enthalten ist. SSL 3.0 und TLS 1.0 enthalten keine Informationen dazu und funktionieren in der Praxis auch.)

Sie erhalten dafür zwei Möglichkeiten.

  • Wenn die von Ihnen erwarteten Client-Zertifikate selbst signiert werden, haben alle unterschiedliche Aussteller. Da Sie nicht wissen, was Sie erwartet, muss der Server eine leere Liste senden. Verwenden Sie dazu die SSLCADNRequestFileDirektive und zeigen Sie auf eine Datei, die nur eine leere Zeile enthält (wenn ich mich gut erinnere, funktioniert sie nicht mit einer vollständig leeren Datei).

  • Die zweite (weniger saubere) Option. Soll sich auf einen Aussteller-DN einigen, der allen von Ihnen erwarteten Client-Zertifikaten gemeinsam ist, unabhängig davon, ob sie tatsächlich von diesem CA-Zertifikat ausgestellt wurden oder nicht (oder ob diese CA überhaupt existiert oder nicht). Auf diese Weise würden Sie das PKI-Modell erheblich brechen (mehr).

    Wenn Sie sich auf einen Emittenten-DN wie CN=Dummy CA(zum Beispiel) einigen . Jeder kann ein selbstsigniertes Zertifikat erstellen, das CN=Dummy CAals Betreff-DN (und Aussteller-DN) verwendet wird, möglicherweise mit unterschiedlichen Schlüsseln. Obwohl die SSLCADNRequestFileDirektive erwartet, mit Zertifikaten zum Erstellen der Liste konfiguriert zu werden, werden diese nicht zum Überprüfen des Client-Zertifikats verwendet. Dies ist nur eine komplizierte (aber im Kontext der anderen Direktiven natürliche) Methode zum Konfigurieren der certificate_authoritiesListe. Wenn Sie als Dienst ein selbstsigniertes Zertifikat mit diesen Namen einfügen SSLCADNRequestFile, wird die CertificateRequestTLS-Nachricht CN=Dummy CAin der certificate_authoritiesListe verwendet (dies sind nur Namen, derzeit keine Zertifikate). Der Client kann dann sein eigenes Zertifikat mit dem Aussteller-DN abholenCN=Dummy CA, ob seine Signatur durch dieses Zertifikat überprüft werden konnte oder nicht (dieselben Schlüssel) oder nicht, da an diesen Schritten ohnehin keine Signaturprüfung beteiligt ist.

SSLVerifyCLient optional_no_caDenken Sie jedoch daran, dass mit keine echte Zertifikatsüberprüfung durchgeführt wird (ich nehme an, Sie könnten die SSL_CLIENT_VERIFYVariable überprüfen , wenn Ihre manuelle Überprüfung nur eine Ersatzlösung für eine PKI ist, die Sie ohnehin konfiguriert haben). Zu diesem Zeitpunkt wissen Sie lediglich, dass der Client über den privaten Schlüssel für das von ihm vorgelegte öffentliche Schlüsselzertifikat verfügt (garantiert durch die TLS- CertificateVerifyNachricht): Sie müssen eine Form der Überprüfung durchführen, wenn eine Authentifizierung für einige erfolgen soll Sortieren. (Sie können keinem Inhalt des Zertifikats vertrauen, dh keiner Bindung zwischen seinem öffentlichen Schlüssel und den darin enthaltenen Namen / Attributen.)

Dies funktioniert für Dateien nicht gut, aber Sie können dies für eine Anwendung tun (z. B. PHP / CGI / ... sogar Java, wenn Sie das Zertifikat an den Proxy-Java-Server übergeben). Eine grundlegende Möglichkeit wäre, eine bereits bekannte Liste öffentlicher Schlüssel zu haben, oder Sie könnten sich die Ideen in FOAF + SSL / WebID ansehen .

Bruno
quelle
2

Die Verwendung SSLVerifyCLient optional_no_ca(anstelle von require) führt dazu, dass Apache die ausstellende Zertifizierungsstelle nicht überprüft (und daher keine Zertifizierungsstellendatei oder keinen CA-Pfad benötigt). Der Client / Benutzer kann kein Zertifikat einreichen. Daher muss die Überprüfung, ob überhaupt ein Zertifikat verwendet wurde, separat durchgeführt werden.

(Anscheinend habe ich die mod_sslDokumentation einfach nicht gründlich gelesen .)

Isaac
quelle