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

Clark C. Evans cce at clarkevans.com
Tue Mar 25 18:04:10 EST 2003


With some help from etrepum (Bob Ippolito), the example is smaller,
and it even includes using POST.   Thanks Bob.

    from twisted.internet import reactor, ssl
    from twisted.web import client
    import urllib
    
    HOST = 'localhost'; PORT = 8443
    serverCertificate = file("server.crt").read()
    
    def verifyCert(cert):
        return ssl.dumpCertificate(cert) == serverCertificate
    
    def getdata():
        postdata = urllib.urlencode({'some': 'argument', 'another': 'arg'})
        headers  = {"Content-type":"application/x-www-form-urlencoded"}
        context  = ssl.DefaultOpenSSLContextFactory(
                      "client.key","client.crt",
                      verifyCallback = verifyCert)
        factory = client.HTTPClientFactory(HOST, "/some/path", "POST",
                                    postdata,  headers )
        reactor.connectSSL(HOST, PORT, factory, context)
        return factory.deferred
    
    def result(data): print data
    
    if __name__ == '__main__':
        reactor.callLater(5, reactor.stop)
        deferred = getdata()
        deferred.addCallback(result)
        reactor.run()

Ooh, this still requires the following patch to twisted.internet.ssl

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