2013-03-19 9 views
26

überprüfen Ich weiß, es wird selten verwendet, aber ist es möglich, auf das Client-Zertifikat in Snap zuzugreifen?Wie kann ich das Client-Zertifikat mit Snap

Wenn nicht, ist es möglich, einen anderen Webstapel zu verwenden?

+1

Allgemein möchte ich wissen, ob ein Haskell-Web-Framework Unterstützung für die zertifikatbasierte Client-Authentifizierung bietet. –

+0

Dies ist eine Art von Nicht-Antwort, aber als Workaround können Sie nginx verwenden, um Zertifikate zu überprüfen und den DN über eine Kopfzeile zu übergeben. –

Antwort

1

Dies ist nicht verfügbar in Snap snap-server Paket, das ich davon ausgehe ist, wie Sie Ihren Server laufen.

Buuuuut es ist nicht schwierig zu bauen, entweder durch Gabelung oder als separates Modul (Sie müssen jedoch etwas Code kopieren, da einige interne Werte, die Sie brauchen, nicht exportiert werden). bindHttps, located in Snap.Internal.Http.Server.TLS, ist, was Sie anvisieren möchten. Diese Funktion ist weitgehend ein Wrapper um Aufrufe an OpenSSL.Session aus der HsOpenSSL-Bibliothek, die selbst ein lockeres Wrapper um die OpenSSL-Bibliothek ist.

Zum Glück für uns OpenSSL hat volle Unterstützung für Client-Zertifikate. Sie müssen einfach verification mode auf SSL_VERIFY_PEER setzen. Es gibt auch andere Knöpfe, an denen man herumspielen kann. Sie müssen außerdem sicherstellen, dass Sie eine Zertifikatskette installieren, um das Clientzertifikat tatsächlich zu überprüfen. Eine Kette von Vertrauen und all dem Jazz. Als Referenz siehe nginx does it.

Noch besser ist diese Funktion exposed in HsOpenSSL als die Funktion contextSetVerificationMode :: SSLContext -> VerificationMode -> IO(). Sie werden feststellen, dass ctx :: SSLContext in der Definition von Snap bindHttps existiert. Alles, was Sie tun müssen, ist entweder kopieren oder Gabel dieses Modul und führen Sie Ihre Anrufe.

Es wäre so etwas wie dieser (ungeprüfte Code alert) aussehen:

± % diff -u /tmp/{old,new} 
--- /tmp/old 2016-04-11 11:02:42.000000000 -0400 
+++ /tmp/new 2016-04-11 11:02:56.000000000 -0400 
@@ -19,6 +19,7 @@ 

     ctx <- SSL.context 
     SSL.contextSetPrivateKeyFile ctx key 
+  SSL.contextSetVerificationMode ctx (SSL.VerifyPeer True True (Just (\_ _ -> return True))) 
     if chainCert 
     then SSL.contextSetCertificateChainFile ctx cert 
     else SSL.contextSetCertificateFile ctx cert 

Der erste boolean sagt OpenSSL zum Scheitern verurteilt, wenn kein Client-Zertifikat vorhanden ist. Der zweite boolesche Wert teilt OpenSSL mit, dass das Client-Zertifikat nur bei der ersten Anforderung benötigt wird und bei Neuverhandlungen nicht mehr benötigt wird. Der dritte Wert ist ein Rückruf. Ich denke, das Richtige ist, True im Rückruf zurückzugeben. Es ist, was nginx does sowieso ist.

Verwandte Themen