[Twisted-Python] ssl.py patch + example client /w server certificate verify

Clark C. Evans cce at clarkevans.com
Tue Mar 25 13:57:33 MST 2003


Howdy.  Thanks to those who helped me get this bootstrapped, so that
others may find the task easier... here is an example of a client
which has its own certificate, and verifies a known client certificate.

        from twisted.internet import reactor, protocol
        from twisted.protocols import http
        from twisted.internet import ssl

        class Client(http.HTTPClient):
            def connectionMade(self):
                print 'Connected.'
                self.sendCommand('GET', "/")
                self.sendHeader('User-Agent', 'Twisted-Example')
                self.endHeaders()
                print 'Sent request.'
        
            def handleResponse(self, data):
                print 'Got response.'
                #print data
        
        
        def verifyCert(cert): 
            return ssl.dumpCertificate(cert) == file("server.crt").read()
        
        def fetchURL():
            print 'Connecting to.'
            context = ssl.DefaultOpenSSLContextFactory(
                          "client.key","client.crt",
                          verifyCallback = verifyCert)
            context.isClient = 1
            factory = protocol.ClientFactory()
            factory.protocol = Client
            reactor.connectSSL('localhost', 8443, factory, context)
        
        if __name__ == '__main__':
            reactor.callLater(5,reactor.stop)
            reactor.callLater(1,fetchURL)
            reactor.run()
        
Anyway, it's not the prettiest... in particular, why is there a 
separate class Default* ... could not this default behavior gone
into the shorter ssl.ContextFactory? 

And... here is the patch to ssl.py

--- ssl.py.orig	Tue Mar 25 13:44:40 2003
+++ ssl.py	Tue Mar 25 15:32:15 2003
@@ -36,7 +36,7 @@
 """
 
 # System imports
-from OpenSSL import SSL
+from OpenSSL import SSL, crypto
 import socket
 
 # sibling imports
@@ -55,20 +55,32 @@
         """Return a SSL.Context object. override in subclasses."""
         raise NotImplementedError
 
+def dumpCertificate(cert, filetype = crypto.FILETYPE_PEM ):
+    ''' a helper to dump an incoming cert as a PEM '''
+    return crypto.dump_certificate(filetype, cert)
 
 class DefaultOpenSSLContextFactory(ContextFactory):
 
     def __init__(self, privateKeyFileName, certificateFileName,
-                 sslmethod=SSL.SSLv23_METHOD):
-        self.privateKeyFileName = privateKeyFileName
+                 sslmethod=SSL.SSLv23_METHOD, verifyCallback = None):
+        self.verifyCallback      = (verifyCallback, )      
+        self.privateKeyFileName  = privateKeyFileName
         self.certificateFileName = certificateFileName
         self.sslmethod = sslmethod
         self.cacheContext()
 
+                        
+    def verifyCertificate(self, conn, cert, errno, depth, retcode):
+        cb = self.verifyCallback[0]
+        if cb: return cb(cert)
+        return 1
+
     def cacheContext(self):
         ctx = SSL.Context(self.sslmethod)
         ctx.use_certificate_file(self.certificateFileName)
         ctx.use_privatekey_file(self.privateKeyFileName)
+        if self.verifyCallback[0]:
+            ctx.set_verify(SSL.VERIFY_PEER, self.verifyCertificate) 
         self._context = ctx
 
     def __getstate__(self):






More information about the Twisted-Python mailing list