[Twisted-Python] Implementing STARTTLS in a protocol
Kevin Horn
kevin.horn at gmail.com
Fri May 23 11:29:44 MDT 2008
Howdy list,
I'm trying to implement a protocol using Twisted which has a "STARTTLS"
command to switch the protocol from plain TCP to TCP over TLS.
I've mostly been going by the way that the imap4.py module seems to do it,
but I can't seem to get a handshake to complete.
I found this page ( http://wiki.vislab.usyd.edu.au/moin.cgi/SSLCertNotes )
which was helpful, but I don't want to force client cert authentication.
In order to separate this problem from other issues, I've adapted the echo
protocol code from above the above page to try and get a simple test case
(my code below)
I am recieving the following output and traceback when running the client
code ( on both Windows and Linux ):
using TLSv1:
>tls_echoclient.py
Sending: Hello, world!
receive: ERROR: Must authenticate
Sending: STARTTLS
receive: READY
Sending: Continuing
connection lost (protocol)
connection lost: [('SSL routines', 'SSL3_READ_BYTES', 'sslv3 alert handshake
failure'), ('SSL routines', 'SSL3_READ_BYTES', 'ssl handshake failure')]
Traceback (most recent call last):
File "C:\Documents and
Settings\kevinh\Desktop\mine_id\sandbox\funsize\sslecho\tls_echoclient.py",
line 58, in <module>
reactor.run()
File "C:\Python25\lib\site-packages\twisted\internet\posixbase.py", line
223, in run
self.mainLoop()
File "C:\Python25\lib\site-packages\twisted\internet\posixbase.py", line
234, in mainLoop
self.doIteration(t)
File "C:\Python25\lib\site-packages\twisted\internet\selectreactor.py",
line 140, in doSelect
_logrun(selectable, _drdw, selectable, method, dict)
--- <exception caught here> ---
File "C:\Python25\lib\site-packages\twisted\python\log.py", line 51, in
callWithLogger
return callWithContext({"system": lp}, func, *args, **kw)
<< SNIP >>
File "C:\Python25\lib\site-packages\twisted\internet\base.py", line 490,
in stop
"Can't stop reactor that isn't running.")
twisted.internet.error.ReactorNotRunning: Can't stop reactor that isn't
running.
What am I doing wrong? Is there a SSL config option I'm setting
incorrectly? Do I need to use a different SSL Context? Am I totally off
base?
Thanks,
Kevin Horn
========= tls_echoserver.py
# adapted from: http://wiki.vislab.usyd.edu.au/moin.cgi/SSLCertNotes
import sys
from OpenSSL import SSL
from twisted.python import log
from twisted.internet import ssl, reactor
from twisted.protocols.basic import LineReceiver
from twisted.internet.protocol import Factory
private_key_file = "privkey_dsa.pem"
cert_file_name = "cacert.pem"
sslmethod = ssl.SSL.TLSv1_METHOD
#~ sslmethod = ssl.SSL.SSLv23_METHOD
class Echo(LineReceiver):
donetls = 0
def sendLine(self, line):
print "Sending:",line
LineReceiver.sendLine(self,line)
def lineReceived(self, line):
print "Got:",line
if self.donetls:
print "Sending OK"
self.transport.write("OK")
elif line == "STARTTLS":
self.sendLine("READY")
#~ self.tlsCtx = CtxFactory()
self.tlsCtx = ssl.DefaultOpenSSLContextFactory(private_key_file,
cert_file_name,
sslmethod)
self.transport.startTLS(self.tlsCtx)
self.donetls = 1
else:
self.sendLine("ERROR: Must authenticate")
factory = Factory()
factory.protocol = Echo
reactor.listenTCP(8000, factory)
reactor.run()
========= tls_echoclient.py
# adapted from: http://wiki.vislab.usyd.edu.au/moin.cgi/SSLCertNotes
from OpenSSL import SSL
import sys
from twisted.internet.protocol import ClientFactory
from twisted.protocols.basic import LineReceiver
from twisted.internet import ssl, reactor
class EchoClient(LineReceiver):
end="Bye-bye!"
def connectionMade(self):
self.sendLine("Hello, world!") # Signals error
def connectionLost(self, reason):
print 'connection lost (protocol)'
reactor.stop()
def sendLine(self, line):
print "Sending:",line
LineReceiver.sendLine(self,line)
def lineReceived(self, line):
print "receive:", line
if line == "ERROR: Must authenticate":
self.sendLine("STARTTLS")
elif line == "READY":
#~ self.ctx = CxtFactory()
self.ctx = ssl.ClientContextFactory()
self.ctx.method = ssl.SSL.TLSv1_METHOD
#~ self.ctx.method = ssl.SSL.SSLv23_METHOD
self.transport.startTLS(self.ctx)
self.sendLine("Continuing");
else:
self.sendLine("wibble")
class EchoClientFactory(ClientFactory):
protocol = EchoClient
def clientConnectionFailed(self, connector, reason):
print 'connection failed:', reason.getErrorMessage()
reactor.stop()
def clientConnectionLost(self, connector, reason):
print 'connection lost:', reason.getErrorMessage()
reactor.stop()
factory = EchoClientFactory()
reactor.connectTCP('localhost', 8000, factory)
reactor.run()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: </pipermail/twisted-python/attachments/20080523/5d57088c/attachment.html>
More information about the Twisted-Python
mailing list