[CalendarServer-changes] [14131] twext/trunk/twext/internet/ssl.py

source_changes at macosforge.org source_changes at macosforge.org
Mon Nov 3 13:16:27 PST 2014


Revision: 14131
          http://trac.calendarserver.org//changeset/14131
Author:   cdaboo at apple.com
Date:     2014-11-03 13:16:26 -0800 (Mon, 03 Nov 2014)
Log Message:
-----------
Client certificate verification support.

Modified Paths:
--------------
    twext/trunk/twext/internet/ssl.py

Modified: twext/trunk/twext/internet/ssl.py
===================================================================
--- twext/trunk/twext/internet/ssl.py	2014-11-02 17:10:06 UTC (rev 14130)
+++ twext/trunk/twext/internet/ssl.py	2014-11-03 21:16:26 UTC (rev 14131)
@@ -23,21 +23,33 @@
 ]
 
 from OpenSSL.SSL import Context as SSLContext, SSLv23_METHOD, OP_NO_SSLv2, \
-    OP_CIPHER_SERVER_PREFERENCE, OP_NO_SSLv3
+    OP_CIPHER_SERVER_PREFERENCE, OP_NO_SSLv3, VERIFY_NONE, VERIFY_PEER, \
+    VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE
 
 from twisted.internet.ssl import DefaultOpenSSLContextFactory
+from twisted.internet._sslverify import Certificate
 
 
 class ChainingOpenSSLContextFactory (DefaultOpenSSLContextFactory):
     def __init__(
         self, privateKeyFileName, certificateFileName,
         sslmethod=SSLv23_METHOD, certificateChainFile=None,
-        passwdCallback=None, ciphers=None
+        passwdCallback=None, ciphers=None,
+        verifyClient=False, requireClientCertificate=False,
+        verifyClientOnce=True, verifyClientDepth=9,
+        clientCACertFileNames=[], sendCAsToClient=True
     ):
         self.certificateChainFile = certificateChainFile
         self.passwdCallback = passwdCallback
         self.ciphers = ciphers
 
+        self.verifyClient = verifyClient
+        self.requireClientCertificate = requireClientCertificate
+        self.verifyClientOnce = verifyClientOnce
+        self.verifyClientDepth = verifyClientDepth
+        self.clientCACertFileNames = clientCACertFileNames
+        self.sendCAsToClient = sendCAsToClient
+
         DefaultOpenSSLContextFactory.__init__(
             self,
             privateKeyFileName,
@@ -67,4 +79,31 @@
         if self.certificateChainFile != "":
             ctx.use_certificate_chain_file(self.certificateChainFile)
 
+        verifyFlags = VERIFY_NONE
+        if self.verifyClient:
+            verifyFlags = VERIFY_PEER
+            if self.requireClientCertificate:
+                verifyFlags |= VERIFY_FAIL_IF_NO_PEER_CERT
+            if self.verifyClientOnce:
+                verifyFlags |= VERIFY_CLIENT_ONCE
+            if self.clientCACertFileNames:
+                store = ctx.get_cert_store()
+                for cert in self.clientCACertFileNames:
+                    with open(cert) as f:
+                        certpem = f.read()
+                    cert = Certificate.loadPEM(certpem)
+                    store.add_cert(cert.original)
+                    if self.sendCAsToClient:
+                        ctx.add_client_ca(cert.original)
+
+        # It'd be nice if pyOpenSSL let us pass None here for this behavior (as
+        # the underlying OpenSSL API call allows NULL to be passed).  It
+        # doesn't, so we'll supply a function which does the same thing.
+        def _verifyCallback(conn, cert, errno, depth, preverify_ok):
+            return preverify_ok
+        ctx.set_verify(verifyFlags, _verifyCallback)
+
+        if self.verifyClientDepth is not None:
+            ctx.set_verify_depth(self.verifyClientDepth)
+
         self._context = ctx
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20141103/a7ea3afa/attachment.html>


More information about the calendarserver-changes mailing list