[Twisted-Python] database access via cred and ssl encryption
Clark C. Evans
cce at clarkevans.com
Fri May 16 20:27:08 MDT 2003
Joe,
My requirement was to have a server authenticate via a client
via a server certificate known by the client. To implement
this, I had to patch the internet/ssl.py file; and to make
the 'fetch' aspect easy, I had a small change to web/client.py
As far as I know, these patches have not been applied; however,
you may find them useful...
Clark
-------------- next part --------------
39c39
< from OpenSSL import SSL
---
> from OpenSSL import SSL, crypto
57a58,60
> def dumpCertificate(cert, filetype = crypto.FILETYPE_PEM ):
> ''' a helper to dump an incoming cert as a PEM '''
> return crypto.dump_certificate(filetype, cert)
62,63c65,67
< sslmethod=SSL.SSLv23_METHOD):
< self.privateKeyFileName = privateKeyFileName
---
> sslmethod=SSL.SSLv23_METHOD, verifyCallback = None):
> self.verifyCallback = (verifyCallback, )
> self.privateKeyFileName = privateKeyFileName
67a72,77
>
> def verifyCertificate(self, conn, cert, errno, depth, retcode):
> cb = self.verifyCallback[0]
> if cb: return cb(cert)
> return 1
>
71a82,83
> if self.verifyCallback[0]:
> ctx.set_verify(SSL.VERIFY_PEER, self.verifyCertificate)
-------------- next part --------------
--- client.py.orig Tue Mar 25 18:10:28 2003
+++ client.py Tue Mar 25 18:55:08 2003
@@ -63,7 +63,8 @@
l = self.headers.get('location')
if not l:
self.handleStatusDefault()
- host, port, url = _parse(l[0])
+ https, host, port, url = _parse(l[0])
+ assert not https, "https redirects not implemented yet"
self.factory.host, self.factory.url = host, url
reactor.connectTCP(host, port, self.factory)
self.quietLoss = 1
@@ -105,7 +106,9 @@
protocol = HTTPPageGetter
- def __init__(self, host, url, method='GET', postdata=None, headers=None, agent="Twisted PageGetter"):
+ def __init__(self, host, url, method='GET', postdata=None,
+ headers=None, agent=None):
+ if agent is None: agent = "Twisted PageGetter"
if headers is not None:
self.headers = headers
if postdata is not None:
@@ -141,8 +144,10 @@
protocol = HTTPPageDownloader
value = None
- def __init__(self, host, url, fileName, method='GET', postdata=None, headers=None, agent="Twisted client"):
- HTTPClientFactory.__init__(self, host, url, method=method, postdata=postdata, headers=headers, agent=agent)
+ def __init__(self, host, url, fileName, method='GET', postdata=None,
+ headers=None, agent = None):
+ HTTPClientFactory.__init__(self, host, url, method,
+ postdata, headers, agent)
self.fileName = fileName
self.deferred = defer.Deferred()
self.waiting = 1
@@ -166,26 +171,59 @@
def _parse(url):
parsed = urlparse.urlparse(url)
url = urlparse.urlunparse(('','')+parsed[2:])
- host, port = parsed[1], 80
+ host = parsed[1]
+ if 'https' == parsed[0]:
+ https, port = 1, 443
+ else:
+ https, port = 0, 80
if ':' in host:
host, port = host.split(':')
port = int(port)
- return host, port, url
+ return https, host, port, url
-def getPage(url, *args, **kwargs):
+def getPage(url, method='GET', postdata=None, headers=None, agent = None):
'''download a web page
Download a page. Return a deferred, which will
callback with a page or errback with a description
of the error.
'''
- host, port, url = _parse(url)
- factory = HTTPClientFactory(host, url, *args, **kwargs)
+ https, host, port, path = _parse(url)
+ if https: return getSecurePage(url, method, postdata, headers, agent)
+ factory = HTTPClientFactory(host, path, method, postdata, headers, agent)
reactor.connectTCP(host, port, factory)
return factory.deferred
+try:
+ from twisted.internet import ssl
+ def getSecurePage(url, method='GET', postdata=None, headers=None,
+ agent = None,
+ privateKeyFileName = None, certificateFileName = None,
+ sslmethod=ssl.SSL.SSLv23_METHOD, verifyCallback = None,
+ serverCertificateFileName = None):
+ """ download a secure page """
+ https, host, port, path = _parse(url)
+ if serverCertificateFileName:
+ cert = file(serverCertificateFileName).read()
+ verifyCallback = lambda rhs: ssl.dumpCertificate(cert) == rhs
+ if verifyCallback or certificateFileName or privateKeyFileName:
+ context = ssl.DefaultOpenSSLContextFactory(
+ privateKeyFileName, certificateFileName,
+ sslmethod, verifyCallback)
+ context.isClient = 1
+ else:
+ context = ssl.ClientContextFactory()
+ factory = HTTPClientFactory(host, path, method, postdata, headers)
+ reactor.connectSSL(host, port, factory, context)
+ return factory.deferred
+except:
+ def getSecurePage(*args,**kwargs):
+ raise Exception("ssl not available")
+
def downloadPage(url, file, *args, **kwargs):
- host, port, url = _parse(url)
- factory = HTTPDownloader(host, url, file, *args, **kwargs)
+ https, host, port, path = _parse(url)
+ assert not https, "https is not yet implemented here"
+ factory = HTTPDownloader(host, path, file, *args, **kwargs)
reactor.connectTCP(host, port, factory)
return factory.deferred
+
More information about the Twisted-Python
mailing list