2013-03-19 15 views
26

So che è usato raramente, ma è possibile accedere al certificato client in Snap?Come posso controllare il certificato client usando Snap

In caso contrario, è possibile utilizzare uno stack Web diverso?

+1

Più in generale, vorrei sapere se un framework Web Haskell fornisce supporto per l'autenticazione client basata su certificato. –

+0

Questa è una sorta di non risposta, ma come soluzione alternativa, è possibile utilizzare nginx per verificare i certificati e passare il DN attraverso un'intestazione. –

risposta

1

Questo non è disponibile nel pacchetto Snap snap-server, che presumo sia come si sta eseguendo il server.

Buuuuu non è difficile da compilare, né con un fork o come un modulo separato (dovrete copiare un po 'di codice, anche se alcuni valori interni di cui avrete bisogno non verranno esportati). bindHttps, located in Snap.Internal.Http.Server.TLS, è ciò che desideri scegliere come target. Questa funzione è in gran parte un wrapper per le chiamate a OpenSSL.Session dalla libreria HsOpenSSL, che a sua volta è un involucro libero attorno alla libreria OpenSSL.

Fortunato per noi OpenSSL ha pieno supporto per i certificati client. Devi semplicemente impostare verification mode su SSL_VERIFY_PEER. Ci sono anche altre manopole con le quali puoi giocare. È inoltre necessario assicurarsi di installare una catena di certificati per verificare effettivamente il certificato del client. Catena di fiducia e tutto quel jazz. Per riferimento, vedere come nginx does it.

Ancora meglio, questa funzione è exposed in HsOpenSSL come la funzione contextSetVerificationMode :: SSLContext -> VerificationMode -> IO(). Noterai che ctx :: SSLContext esiste nella definizione di Snap bindHttps. Tutto quello che dovrai fare è copiare o forgiare quel modulo e presentare le tue chiamate.

Sarebbe simile a questa (non verificata avviso codice):

± % 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 

La prima booleano dice OpenSSL a fallire se non certificato client è presente. Il secondo booleano indica a OpenSSL che il certificato client è necessario solo alla prima richiesta e non è più necessario per le rinegoziazioni. Il terzo valore è un callback. Penso che la cosa giusta da fare sia restituire True nel callback. È quello che nginx does, comunque.