Commits

Anonymous committed 90fb922

pre-0.3.0

Comments (0)

Files changed (21)

 
-tlslite version 0.2.4                                             March 5, 2004
+tlslite version 0.2.7                                            March 12, 2004
 Trevor Perrin <trevp at trevp.net>
 http://trevp.net/tlslite/
 ===============================================================================
 3 Installation
 4 Getting Started with the Command-Line Tools
 5 Getting Started with the Library
-6 Using TLS Lite with httplib and SocketServer
-7 Using TLS Lite with asyncore
-8 SECURITY CONSIDERATIONS
-9 History
-10 References
+6 Using TLS Lite with httplib
+7 Using TLS Lite with SocketServer
+8 Using TLS Lite with asyncore
+9 Using TLS Lite with Twisted
+10 SECURITY CONSIDERATIONS
+11 History
+12 References
 
 
 1 Introduction
 On Windows:
   Run the installer in the 'installers' directory.
   *OR*
-  Run 'python setup.py install' (this only works if your system has a compiler
+  Run 'setup.py install' (this only works if your system has a compiler
   available).
 
 Anywhere else:
-  - Run 'python setup.py install'
+  - Run 'setup.py install'
 
 Test the Installation:
-  - From the distribution's root directory, run:
-    'python tls.py servertest ./test'
+  - From the distribution's ./test subdirectory, run:
+      tls.py servertest localhost .
   - While the test server is waiting, run:
-    'python tls.py clienttest ./test'
+      tls.py clienttest localhost .
   If both say "Test succeeded" at the end, you're ready to go.
 
+  (WARNING: Be careful running these scripts from the distribution's root
+  directory.  Depending on your path, the scripts may load the local copy of the
+  library instead of the installed version, with unpredictable results).
+
 
 4 Getting Started with the Command-Line Tools
 ==============================================
 5) Use the TLSConnection to exchange data.
 6) Call close() on the TLSConnection when you're done.
 
-TLS Lite also integrates with httplib, SocketServer, and asyncore.  When used
-with these, some of the steps are performed for you.  See the sections following
-this one for details.
+TLS Lite also integrates with httplib, SocketServer, asyncore, and Twisted.
+When used with these, some of the steps are performed for you.  See the sections
+following this one for details.
 
 5 Step 1 - create a socket
 ---------------------------
 
 5 Step 2 - construct a TLSConnection
 -------------------------------------
-  import tlslite
-  connection = tlslite.TLSConnection(sock)
+  from tlslite.all import *
+  connection = TLSConnection(sock)
 
 5 Step 3 - call a handshake function (client)
 ----------------------------------------------
 
   #Load X.509 certChain and privateKey.
   s = open("./test/clientX509Cert.pem").read()
-  x509 = tlslite.X509()
+  x509 = X509()
   x509.parse(s)
-  certChain = tlslite.X509CertChain([x509])
+  certChain = X509CertChain([x509])
   s = open("./test/clientX509Key.pem").read()
-  privateKey = tlslite.parsePEMKey(s, private=True)
+  privateKey = keyfactory.parsePEMKey(s, private=True)
 
 The SRP and SharedKey functions both do mutual authentication with a username
 and password.  The difference is this: SRP is slow but safer when using low-
 parameters of at least 2048 bits, and you only want to use the AES-256 cipher,
 and you only want to allow TLS (version 3.1), not SSL (version 3.0), you can do:
 
-  settings = tlslite.HandshakeSettings()
+  settings = HandshakeSettings()
   settings.minKeySize = 2048
   settings.cipherNames = ["aes256"]
   settings.minVersion = (3,1)
 database.
 
   #On-disk database (use no-arg constructor if you want an in-memory DB)
-  verifierDB = tlslite.VerifierDB("./test/verifierDB")
+  verifierDB = VerifierDB("./test/verifierDB")
 
   #Open the pre-existing database (can also 'create()' a new one)
   verifierDB.open()
 
   #Add to the database
-  N, g, salt, verifier = tlslite.makeVerifier("alice", "abra123cadabra", 2048)
+  N, g, salt, verifier = makeVerifier("alice", "abra123cadabra", 2048)
   verifierDB["alice"] = N, g, salt, verifier
 
   #Perform a handshake using the database
 keys.  The SharedKeyDB class manages an in-memory or on-disk shared key
 database.
 
-  sharedKeyDB = tlslite.SharedKeyDB("./test/sharedkeyDB")
+  sharedKeyDB = SharedKeyDB("./test/sharedkeyDB")
   sharedKeyDB.open()
   sharedKeyDB["alice"] = "PaVBVZkYqAjCQCu6UBL2xgsnZhw"
   connection.handshakeServer(sharedKeyDB=sharedKeyDB)
 section, for finer control over handshaking details.  Finally, the server can
 maintain a SessionCache, which will allow clients to use session resumption:
 
-  sessionCache = tlslite.SessionCache()
+  sessionCache = SessionCache()
   connection.handshakeServer(verifierDB=verifierDB, sessionCache=sessionCache)
 
 It should be noted that the session cache, and the verifier and shared key
 To save yourself the trouble of inspecting fingerprints after the handshake, you
 can pass a Checker object into the handshake function.  The checker will be
 called if the handshake completes successfully.  If the other party's
-fingerprint isn't approved by the checker, a subclass of AuthenticationError
+fingerprint isn't approved by the checker, a subclass of TLSAuthenticationError
 will be raised.  For example, to perform a handshake with a server based on its
 X.509 fingerprint, do:
 
   try:
-    checker = tlslite.Checker(\
+    checker = Checker(\
               x509Fingerprint='e049ff930af76d43ff4c658b268786f4df1296f2')
     connection.handshakeClientNoAuth(checker=checker)
-  except tlslite.AuthenticationError:
+  except TLSAuthenticationError:
     print "Authentication failure"
 
 If the handshake fails for any reason, an exception will be raised.  If the
-socket timed out or was unexpectedly closed, a socket.error will be raised.
-Otherwise, either a TLSLocalAlert or TLSRemoteAlert will be raised, depending on
-whether the local or remote implementation signalled the error.  The exception
-object has a 'description' member which identifies the error based on the codes
-in RFC 2246.  A TLSLocalAlert also has a 'message' string that may have more
-details.
+socket timed out or was unexpectedly closed, a socket.error or
+TLSAbruptCloseError will be raised.  Otherwise, either a TLSLocalAlert or
+TLSRemoteAlert will be raised, depending on whether the local or remote
+implementation signalled the error.  The exception object has a 'description'
+member which identifies the error based on the codes in RFC 2246.  A
+TLSLocalAlert also has a 'message' string that may have more details.
 
 Example of handling a remote alert:
 
   try:
       [...]
-  except tlslite.TLSRemoteAlert, alert:
-      if alert.description == tlslite.AlertDescription.unknown_srp_username:
+  except TLSRemoteAlert, alert:
+      if alert.description == AlertDescription.unknown_srp_username:
           print "Unknown user."
   [...]
 
 -------------------------
 Now that you have a connection, you can call read() and write() as if it were a
 socket.SSL object.  You can also call send(), sendall(), recv(), and makefile()
-as if it were a socket.  These calls may raise TLSLocalAlert, TLSRemoteAlert, or
-socket.error, just like the handshake functions.
+as if it were a socket.  These calls may raise TLSLocalAlert, TLSRemoteAlert,
+socket.error, or TLSAbruptCloseError, just like the handshake functions.
 
-Once the TLS connection is closed by the other side, calls to read() will return
-an empty string.  If the socket is closed by the other side without first
-closing the TLS connection, a call to read() or write() will return a
-socket.error.
+Once the TLS connection is closed by the other side, calls to read() or recv()
+will return an empty string.  If the socket is closed by the other side without
+first closing the TLS connection, calls to read() or recv() will return a
+TLSAbruptCloseError, and calls to write() or send() will return a socket.error.
 
 5 Step 6 - close the connection
 --------------------------------
-When you're finished sending data, you should call close() to shut the
-connection down and signal the other side you're done.  When the connection is
-closed properly, the socket stays open and can be used for exchanging non-secure
-data, the session object can be used for session resumption, and the connection
-object can be re-used by calling another handshake function.
+When you're finished sending data, you should call close() to close the
+connection down.  When the connection is closed properly, the socket stays open
+and can be used for exchanging non-secure data, the session object can be used
+for session resumption, and the connection object can be re-used by calling
+another handshake function.
 
-If a socket.error or alert is raised, the connection will be automatically
-closed; you don't need to call close().  Furthermore, you will probably not be
-able to re-use the socket, the connection object, or the session object, and
-you shouldn't even try.
+If an exception is raised, the connection will be automatically closed; you
+don't need to call close().  Furthermore, you will probably not be able to re-
+use the socket, the connection object, or the session object, and you shouldn't
+even try.
 
 By default, calling close() will leave the socket open.  If you set the
 connection's closeSocket flag to True, the connection will take ownership of the
 socket, and close it when the connection is closed.
 
 
-6 Using TLS Lite with httplib and SocketServer
-===============================================
+6 Using TLS Lite with httplib
+==============================
 TLS Lite comes with an HTTPTLSConnection class that extends httplib to work over
 SSL/TLS connections.  Depending on how you construct it, it will do different
 types of authentication.  For example:
 
   #No authentication whatsoever
-  h = tlslite.HTTPTLSConnection("www.amazon.com", 443)
+  h = HTTPTLSConnection("www.amazon.com", 443)
   h.request("GET", "")
   r = h.getresponse()
   [...]
 
   #Authenticate server based on its X.509 fingerprint
-  h = tlslite.HTTPTLSConnection("www.amazon.com", 443,
+  h = HTTPTLSConnection("www.amazon.com", 443,
           x509Fingerprint="e049ff930af76d43ff4c658b268786f4df1296f2")
   [...]
 
   #Authenticate server based on its cryptoID
-  h = tlslite.HTTPTLSConnection("localhost", 443,
+  h = HTTPTLSConnection("localhost", 443,
           cryptoID="dmqb6.fq345.cxk6g.5fha3")
   [...]
 
   #Mutually authenticate with SRP
-  h = tlslite.HTTPTLSConnection("localhost", 443,
+  h = HTTPTLSConnection("localhost", 443,
           username="alice", password="abra123cadabra")
   [...]
 
   #Mutually authenticate with a shared key
-  h = tlslite.HTTPTLSConnection("localhost", 443,
+  h = HTTPTLSConnection("localhost", 443,
           username="alice", sharedKey="PaVBVZkYqAjCQCu6UBL2xgsnZhw")
   [...]
 
   #Mutually authenticate with SRP, *AND* authenticate the server based
   #on its cryptoID
-  h = tlslite.HTTPTLSConnection("localhost", 443,
+  h = HTTPTLSConnection("localhost", 443,
           username="alice", password="abra123cadabra",
           cryptoID="dmqb6.fq345.cxk6g.5fha3")
   [...]
 
-You can also use TLS Lite to implement servers using Python's SocketServer
-framework.  TLS Lite comes with a TLSMixIn class.  You can combine this with a
-TCPServer such as HTTPServer.  To combine them, define a new class that inherits
-from both of them (with the mix-in first). Then implement the handshake()
-method, doing some sort of server handshake on the connection argument.  If the
-handshake method returns True, the RequestHandler will be triggered.  Below is a
-complete example of a threaded HTTPS server.
+
+7 Using TLS Lite with SocketServer
+===================================
+You can use TLS Lite to implement servers using Python's SocketServer framework.
+TLS Lite comes with a TLSMixIn class.  You can combine this with a TCPServer
+such as HTTPServer.  To combine them, define a new class that inherits from both
+of them (with the mix-in first). Then implement the handshake() method, doing
+some sort of server handshake on the connection argument.  If the handshake
+method returns True, the RequestHandler will be triggered.  Below is a complete
+example of a threaded HTTPS server.
 
   from SocketServer import *
   from BaseHTTPServer import *
   from SimpleHTTPServer import *
-  from tlslite import *
+  from tlslite.all import *
 
   s = open("./serverX509Cert.pem").read()
   x509 = X509()
               tlsConnection.handshakeServer(certChain=certChain,
                                             privateKey=privateKey,
                                             sessionCache=sessionCache)
+              tlsConnection.ignoreAbruptClose = True
               return True
           except TLSAlert, alert:
               print "Handshake failure:", str(alert)
   httpd.serve_forever()
 
 
-7 Using TLS Lite with asyncore
+8 Using TLS Lite with asyncore
 ===============================
 TLS Lite can be used with subclasses of asyncore.dispatcher.  See the comments
 in TLSAsyncDispatcherMixIn.py for details.  This is still experimental, and may
 Below is an example of combining Medusa's http_channel with
 TLSAsyncDispatcherMixIn:
 
-  class http_tls_channel(tlslite.TLSAsyncDispatcherMixIn,
+  class http_tls_channel(TLSAsyncDispatcherMixIn,
                          http_server.http_channel):
       ac_in_buffer_size = 16384
 
       def __init__ (self, server, conn, addr):
           http_server.http_channel.__init__(self, server, conn, addr)
-          tlslite.TLSAsyncDispatcherMixIn.__init__(self, conn)
+          TLSAsyncDispatcherMixIn.__init__(self, conn)
           self.setServerHandshakeOp(certChain=certChain, privateKey=privateKey)
 
 
-8 Security Considerations
-==========================
+9 Using TLS Lite with Twisted
+==============================
+TLS Lite can be used with Twisted protocols.  Below is a complete example of
+using TLS Lite with a Twisted echo server.
+
+There are two server implementations below.  Echo is the original protocol,
+which is oblivious to TLS.  Echo1 subclasses Echo and negotiates TLS when the
+client connects.  Echo2 subclasses Echo and negotiates TLS when the client sends
+"STARTTLS".
+
+  from twisted.internet.protocol import Protocol, Factory
+  from twisted.internet import reactor
+  from twisted.protocols.policies import WrappingFactory
+  from twisted.protocols.basic import LineReceiver
+  from twisted.python import log
+  from twisted.python.failure import Failure
+  import sys
+  import tlslite
+
+  s = open("./serverX509Cert.pem").read()
+  x509 = tlslite.X509()
+  x509.parse(s)
+  certChain = tlslite.X509CertChain([x509])
+
+  s = open("./serverX509Key.pem").read()
+  privateKey = tlslite.parsePEMKey(s, private=True)
+
+  verifierDB = tlslite.VerifierDB("verifierDB")
+  verifierDB.open()
+
+  class Echo(LineReceiver):
+      def connectionMade(self):
+          self.transport.write("Welcome to the echo server!\r\n")
+
+      def lineReceived(self, line):
+          self.transport.write(line + "\r\n")
+
+  class Echo1(Echo):
+      def connectionMade(self):
+          if not self.transport.tlsStarted:
+              self.transport.setServerHandshakeOp(certChain=certChain,
+                                                  privateKey=privateKey,
+                                                  verifierDB=verifierDB)
+          else:
+              Echo.connectionMade(self)
+
+      def connectionLost(self, reason):
+          pass #Handle any TLS exceptions here
+
+  class Echo2(Echo):
+      def lineReceived(self, data):
+          if data == "STARTTLS":
+              self.transport.setServerHandshakeOp(certChain=certChain,
+                                                  privateKey=privateKey,
+                                                  verifierDB=verifierDB)
+          else:
+              Echo.lineReceived(self, data)
+
+      def connectionLost(self, reason):
+          pass #Handle any TLS exceptions here
+
+  factory = Factory()
+  factory.protocol = Echo1
+  #factory.protocol = Echo2
+
+  wrappingFactory = WrappingFactory(factory)
+  wrappingFactory.protocol = tlslite.TLSTwistedProtocolWrapper
+
+  log.startLogging(sys.stdout)
+  reactor.listenTCP(1079, wrappingFactory)
+  reactor.run()
+
+
+10 Security Considerations
+===========================
 TLS Lite is alpha-quality code.  Don't use it for anything important.
 
 
-9 History
-==========
+11 History
+===========
+0.2.7 - 3/12/2004
+ - changed Twisted error handling to use connectionLost()
+ - added ignoreAbruptClose
+0.2.6 - 3/11/2004
+ - added Twisted errorHandler
+ - added TLSAbruptCloseError
+ - added 'integration' subdirectory
+0.2.5 - 3/10/2004
+ - improved asynchronous support a bit
+ - added first-draft of Twisted support
 0.2.4 - 3/5/2004
  - cleaned up asyncore support
  - added proof-of-concept for Twisted
  - first release
 
 
-10 References
+12 References
 ==============
 [0] http://www.ietf.org/rfc/rfc2246.txt
 [1] http://www.trevp.net/tls_srp/draft-ietf-tls-srp-06.html
 [10] http://gmpy.sourceforge.net/
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 if __name__ != "__main__":
     raise "This must be run as a command, not used as a module!"
 
+#import tlslite
+#from tlslite.constants import AlertDescription, Fault
 
-import tlslite
-from tlslite.utils.jython_compat import formatExceptionTrace
+#from tlslite.utils.jython_compat import formatExceptionTrace
+#from tlslite.X509 import X509, X509CertChain
+
+from tlslite.api import *
 
 
 def parsePrivateKey(s):
     try:
-        return tlslite.parsePEMKey(s, private=True)
+        return parsePEMKey(s, private=True)
     except Exception, e:
         print e
-        return tlslite.parseXMLKey(s, private=True)
+        return parseXMLKey(s, private=True)
 
 
 def clientTest(address, dir):
         if hasattr(sock, 'settimeout'): #It's a python 2.3 feature
             sock.settimeout(5)
         sock.connect(address)
-        c = tlslite.TLSConnection(sock)
+        c = TLSConnection(sock)
         return c
 
     test = 0
     connection.sock.close()
 
     print "Test 2 - shared key faults"
-    for fault in tlslite.ClientSharedKeyFault.faults + tlslite.GenericFault.faults:
+    for fault in Fault.clientSharedKeyFaults + Fault.genericFaults:
         connection = connect()
         connection.fault = fault
         try:
             connection.handshakeClientSharedKey("shared", "key")
-            print "  Good Fault %s" % (tlslite.faultNames[fault])
-        except tlslite.FaultError, e:
-            print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
+            print "  Good Fault %s" % (Fault.faultNames[fault])
+        except TLSFaultError, e:
+            print "  BAD FAULT %s: %s" % (Fault.faultNames[fault], str(e))
             badFault = True
         connection.sock.close()
 
     connection.close()
 
     print "Test 4 - SRP faults"
-    for fault in tlslite.ClientSRPFault.faults + tlslite.GenericFault.faults:
+    for fault in Fault.clientSrpFaults + Fault.genericFaults:
         connection = connect()
         connection.fault = fault
         try:
             connection.handshakeClientSRP("test", "password")
-            print "  Good Fault %s" % (tlslite.faultNames[fault])
-        except tlslite.FaultError, e:
-            print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
+            print "  Good Fault %s" % (Fault.faultNames[fault])
+        except TLSFaultError, e:
+            print "  BAD FAULT %s: %s" % (Fault.faultNames[fault], str(e))
             badFault = True
         connection.sock.close()
 
     print "Test 6 - good SRP: with X.509 certificate"
     connection = connect()
     connection.handshakeClientSRP("test", "password")
-    assert(isinstance(connection.session.serverCertChain, tlslite.X509CertChain))
+    assert(isinstance(connection.session.serverCertChain, X509CertChain))
     connection.close()
     connection.sock.close()
 
     print "Test 7 - X.509 with SRP faults"
-    for fault in tlslite.ClientSRPFault.faults + tlslite.GenericFault.faults:
+    for fault in Fault.clientSrpFaults + Fault.genericFaults:
         connection = connect()
         connection.fault = fault
         try:
             connection.handshakeClientSRP("test", "password")
-            print "  Good Fault %s" % (tlslite.faultNames[fault])
-        except tlslite.FaultError, e:
-            print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
+            print "  Good Fault %s" % (Fault.faultNames[fault])
+        except TLSFaultError, e:
+            print "  BAD FAULT %s: %s" % (Fault.faultNames[fault], str(e))
             badFault = True
         connection.sock.close()
 
         connection.sock.close()
 
         print "Test 9 - CryptoID with SRP faults"
-        for fault in tlslite.ClientSRPFault.faults + tlslite.GenericFault.faults:
+        for fault in Fault.clientSrpFaults + Fault.genericFaults:
             connection = connect()
             connection.fault = fault
             try:
                 connection.handshakeClientSRP("test", "password")
-                print "  Good Fault %s" % (tlslite.faultNames[fault])
-            except tlslite.FaultError, e:
-                print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
+                print "  Good Fault %s" % (Fault.faultNames[fault])
+            except TLSFaultError, e:
+                print "  BAD FAULT %s: %s" % (Fault.faultNames[fault], str(e))
                 badFault = True
             connection.sock.close()
 
     print "Test 10 - good X509"
     connection = connect()
-    connection.handshakeClientNoAuth()
-    assert(isinstance(connection.session.serverCertChain, tlslite.X509CertChain))
+    connection.handshakeClientCert()
+    assert(isinstance(connection.session.serverCertChain, X509CertChain))
     connection.close()
     connection.sock.close()
 
     print "Test 10.a - good X509, SSLv3"
     connection = connect()
-    settings = tlslite.HandshakeSettings()
+    settings = HandshakeSettings()
     settings.minVersion = (3,0)
     settings.maxVersion = (3,0)
-    connection.handshakeClientNoAuth(settings=settings)
-    assert(isinstance(connection.session.serverCertChain, tlslite.X509CertChain))
+    connection.handshakeClientCert(settings=settings)
+    assert(isinstance(connection.session.serverCertChain, X509CertChain))
     connection.close()
     connection.sock.close()
 
     print "Test 11 - X.509 faults"
-    for fault in tlslite.ClientNoAuthFault.faults + tlslite.GenericFault.faults:
+    for fault in Fault.clientNoAuthFaults + Fault.genericFaults:
         connection = connect()
         connection.fault = fault
         try:
-            connection.handshakeClientNoAuth()
-            print "  Good Fault %s" % (tlslite.faultNames[fault])
-        except tlslite.FaultError, e:
-            print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
+            connection.handshakeClientCert()
+            print "  Good Fault %s" % (Fault.faultNames[fault])
+        except TLSFaultError, e:
+            print "  BAD FAULT %s: %s" % (Fault.faultNames[fault], str(e))
             badFault = True
         connection.sock.close()
 
     if cryptoIDlibLoaded:
         print "Test 12 - good cryptoID"
         connection = connect()
-        connection.handshakeClientNoAuth()
+        connection.handshakeClientCert()
         assert(isinstance(connection.session.serverCertChain, cryptoIDlib.CertChain))
         assert(connection.session.serverCertChain.validate())
         connection.close()
         connection.sock.close()
 
         print "Test 13 - cryptoID faults"
-        for fault in tlslite.ClientNoAuthFault.faults + tlslite.GenericFault.faults:
+        for fault in Fault.clientNoAuthFaults + Fault.genericFaults:
             connection = connect()
             connection.fault = fault
             try:
-                connection.handshakeClientNoAuth()
-                print "  Good Fault %s" % (tlslite.faultNames[fault])
-            except tlslite.FaultError, e:
-                print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
+                connection.handshakeClientCert()
+                print "  Good Fault %s" % (Fault.faultNames[fault])
+            except TLSFaultError, e:
+                print "  BAD FAULT %s: %s" % (Fault.faultNames[fault], str(e))
                 badFault = True
             connection.sock.close()
 
     print "Test 14 - good mutual X509"
-    x509Cert = tlslite.X509().parse(open(os.path.join(dir, "clientX509Cert.pem")).read())
-    x509Chain = tlslite.X509CertChain([x509Cert])
+    x509Cert = X509().parse(open(os.path.join(dir, "clientX509Cert.pem")).read())
+    x509Chain = X509CertChain([x509Cert])
     s = open(os.path.join(dir, "clientX509Key.pem")).read()
-    x509Key = tlslite.parsePEMKey(s, private=True)
+    x509Key = parsePEMKey(s, private=True)
 
     connection = connect()
     connection.handshakeClientCert(x509Chain, x509Key)
-    assert(isinstance(connection.session.serverCertChain, tlslite.X509CertChain))
+    assert(isinstance(connection.session.serverCertChain, X509CertChain))
     connection.close()
     connection.sock.close()
 
     print "Test 14.a - good mutual X509, SSLv3"
     connection = connect()
-    settings = tlslite.HandshakeSettings()
+    settings = HandshakeSettings()
     settings.minVersion = (3,0)
     settings.maxVersion = (3,0)
     connection.handshakeClientCert(x509Chain, x509Key, settings=settings)
-    assert(isinstance(connection.session.serverCertChain, tlslite.X509CertChain))
+    assert(isinstance(connection.session.serverCertChain, X509CertChain))
     connection.close()
     connection.sock.close()
 
     print "Test 15 - mutual X.509 faults"
-    for fault in tlslite.ClientCertFault.faults + tlslite.GenericFault.faults:
+    for fault in Fault.clientCertFaults + Fault.genericFaults:
         connection = connect()
         connection.fault = fault
         try:
             connection.handshakeClientCert(x509Chain, x509Key)
-            print "  Good Fault %s" % (tlslite.faultNames[fault])
-        except tlslite.FaultError, e:
-            print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
+            print "  Good Fault %s" % (Fault.faultNames[fault])
+        except TLSFaultError, e:
+            print "  BAD FAULT %s: %s" % (Fault.faultNames[fault], str(e))
             badFault = True
         connection.sock.close()
 
     if cryptoIDlibLoaded:
         print "Test 16 - good mutual cryptoID"
         cryptoIDChain = cryptoIDlib.CertChain().parse(open(os.path.join(dir, "serverCryptoIDChain.xml"), "r").read())
-        cryptoIDKey = tlslite.parseXMLKey(open(os.path.join(dir, "serverCryptoIDKey.xml"), "r").read(), private=True)
+        cryptoIDKey = parseXMLKey(open(os.path.join(dir, "serverCryptoIDKey.xml"), "r").read(), private=True)
 
         connection = connect()
         connection.handshakeClientCert(cryptoIDChain, cryptoIDKey)
         connection.sock.close()
 
         print "Test 17 - mutual cryptoID faults"
-        for fault in tlslite.ClientCertFault.faults + tlslite.GenericFault.faults:
+        for fault in Fault.clientCertFaults + Fault.genericFaults:
             connection = connect()
             connection.fault = fault
             try:
                 connection.handshakeClientCert(cryptoIDChain, cryptoIDKey)
-                print "  Good Fault %s" % (tlslite.faultNames[fault])
-            except tlslite.FaultError, e:
-                print "  BAD FAULT %s: %s" % (tlslite.faultNames[fault], str(e))
+                print "  Good Fault %s" % (Fault.faultNames[fault])
+            except TLSFaultError, e:
+                print "  BAD FAULT %s: %s" % (Fault.faultNames[fault], str(e))
                 badFault = True
             connection.sock.close()
 
     try:
         connection.handshakeClientSRP("test", "garbage", session=session)
         assert()
-    except tlslite.TLSRemoteAlert, alert:
-        if alert.description != tlslite.AlertDescription.bad_record_mac:
+    except TLSRemoteAlert, alert:
+        if alert.description != AlertDescription.bad_record_mac:
             raise
     connection.sock.close()
 
     htmlBody = open(os.path.join(dir, "index.html")).read()
     fingerprint = None
     for y in range(2):
-        h = tlslite.HTTPTLSConnection(address[0], address[1], x509Fingerprint=fingerprint)
+        h = HTTPTLSConnection(\
+                address[0], address[1], x509Fingerprint=fingerprint)
         for x in range(3):
             h.request("GET", "/index.html")
             r = h.getresponse()
         fingerprint = None
         protocol = None
         for y in range(2):
-            h = tlslite.HTTPTLSConnection(address[0], address[1],
+            h = HTTPTLSConnection(\
+                         address[0], address[1],
                          username="test", password="password",
                          cryptoID=fingerprint, protocol=protocol)
             for x in range(3):
         time.sleep(2)
 
     implementations = []
-    if tlslite.cryptlibpyLoaded:
+    if cryptlibpyLoaded:
         implementations.append("cryptlib")
-    if tlslite.m2cryptoLoaded:
+    if m2cryptoLoaded:
         implementations.append("openssl")
-    if tlslite.pycryptoLoaded:
+    if pycryptoLoaded:
         implementations.append("pycrypto")
     implementations.append("python")
 
             print "Test 22:",
             connection = connect()
 
-            settings = tlslite.HandshakeSettings()
+            settings = HandshakeSettings()
             settings.cipherNames = [cipher]
             settings.cipherImplementations = [implementation, "python"]
             connection.handshakeClientSharedKey("shared", "key", settings=settings)
             print "Test 23:",
             connection = connect()
 
-            settings = tlslite.HandshakeSettings()
+            settings = HandshakeSettings()
             settings.cipherNames = [cipher]
             settings.cipherImplementations = [implementation, "python"]
             connection.handshakeClientSharedKey("shared", "key", settings=settings)
     lsock.listen(5)
 
     def connect():
-        return tlslite.TLSConnection(lsock.accept()[0])
+        return TLSConnection(lsock.accept()[0])
 
     print "Test 1 - good shared key"
-    sharedKeyDB = tlslite.SharedKeyDB()
+    sharedKeyDB = SharedKeyDB()
     sharedKeyDB["shared"] = "key"
     sharedKeyDB["shared2"] = "key2"
     connection = connect()
     connection.sock.close()
 
     print "Test 2 - shared key faults"
-    for fault in tlslite.ClientSharedKeyFault.faults + tlslite.GenericFault.faults:
+    for fault in Fault.clientSharedKeyFaults + Fault.genericFaults:
         connection = connect()
         connection.fault = fault
         try:
     print "Test 3 - good SRP"
     #verifierDB = tlslite.VerifierDB(os.path.join(dir, "verifierDB"))
     #verifierDB.open()
-    verifierDB = tlslite.VerifierDB()
+    verifierDB = VerifierDB()
     verifierDB.create()
-    entry = tlslite.makeVerifier("test", "password", 1536)
+    entry = VerifierDB.makeVerifier("test", "password", 1536)
     verifierDB["test"] = entry
 
     connection = connect()
     connection.sock.close()
 
     print "Test 4 - SRP faults"
-    for fault in tlslite.ClientSRPFault.faults + tlslite.GenericFault.faults:
+    for fault in Fault.clientSrpFaults + Fault.genericFaults:
         connection = connect()
         connection.fault = fault
         try:
     connection.sock.close()
 
     print "Test 6 - good SRP: with X.509 cert"
-    x509Cert = tlslite.X509().parse(open(os.path.join(dir, "serverX509Cert.pem")).read())
-    x509Chain = tlslite.X509CertChain([x509Cert])
+    x509Cert = X509().parse(open(os.path.join(dir, "serverX509Cert.pem")).read())
+    x509Chain = X509CertChain([x509Cert])
     s = open(os.path.join(dir, "serverX509Key.pem")).read()
-    x509Key = tlslite.parsePEMKey(s, private=True)
+    x509Key = parsePEMKey(s, private=True)
 
     connection = connect()
     connection.handshakeServer(verifierDB=verifierDB, \
     connection.sock.close()
 
     print "Test 7 - X.509 with SRP faults"
-    for fault in tlslite.ClientSRPFault.faults + tlslite.GenericFault.faults:
+    for fault in Fault.clientSrpFaults + Fault.genericFaults:
         connection = connect()
         connection.fault = fault
         try:
     if cryptoIDlibLoaded:
         print "Test 8 - good SRP: with cryptoID certs"
         cryptoIDChain = cryptoIDlib.CertChain().parse(open(os.path.join(dir, "serverCryptoIDChain.xml"), "r").read())
-        cryptoIDKey = tlslite.parseXMLKey(open(os.path.join(dir, "serverCryptoIDKey.xml"), "r").read(), private=True)
+        cryptoIDKey = parseXMLKey(open(os.path.join(dir, "serverCryptoIDKey.xml"), "r").read(), private=True)
         connection = connect()
         connection.handshakeServer(verifierDB=verifierDB, \
                                    certChain=cryptoIDChain, privateKey=cryptoIDKey)
         connection.sock.close()
 
         print "Test 9 - cryptoID with SRP faults"
-        for fault in tlslite.ClientSRPFault.faults + tlslite.GenericFault.faults:
+        for fault in Fault.clientSrpFaults + Fault.genericFaults:
             connection = connect()
             connection.fault = fault
             try:
 
     print "Test 10.a - good X.509, SSL v3"
     connection = connect()
-    settings = tlslite.HandshakeSettings()
+    settings = HandshakeSettings()
     settings.minVersion = (3,0)
     settings.maxVersion = (3,0)
     connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, settings=settings)
     connection.sock.close()
 
     print "Test 11 - X.509 faults"
-    for fault in tlslite.ClientNoAuthFault.faults + tlslite.GenericFault.faults:
+    for fault in Fault.clientNoAuthFaults + Fault.genericFaults:
         connection = connect()
         connection.fault = fault
         try:
         connection.sock.close()
 
         print "Test 13 - cryptoID faults"
-        for fault in tlslite.ClientNoAuthFault.faults + tlslite.GenericFault.faults:
+        for fault in Fault.clientNoAuthFaults + Fault.genericFaults:
             connection = connect()
             connection.fault = fault
             try:
     print "Test 14 - good mutual X.509"
     connection = connect()
     connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, reqCert=True)
-    assert(isinstance(connection.session.serverCertChain, tlslite.X509CertChain))
+    assert(isinstance(connection.session.serverCertChain, X509CertChain))
     connection.close()
     connection.sock.close()
 
     print "Test 14a - good mutual X.509, SSLv3"
     connection = connect()
-    settings = tlslite.HandshakeSettings()
+    settings = HandshakeSettings()
     settings.minVersion = (3,0)
     settings.maxVersion = (3,0)
     connection.handshakeServer(certChain=x509Chain, privateKey=x509Key, reqCert=True, settings=settings)
-    assert(isinstance(connection.session.serverCertChain, tlslite.X509CertChain))
+    assert(isinstance(connection.session.serverCertChain, X509CertChain))
     connection.close()
     connection.sock.close()
 
     print "Test 15 - mutual X.509 faults"
-    for fault in tlslite.ClientCertFault.faults + tlslite.GenericFault.faults:
+    for fault in Fault.clientCertFaults + Fault.genericFaults:
         connection = connect()
         connection.fault = fault
         try:
         connection.sock.close()
 
         print "Test 17 - mutual cryptoID faults"
-        for fault in tlslite.ClientCertFault.faults + tlslite.GenericFault.faults:
+        for fault in Fault.clientCertFaults + Fault.genericFaults:
             connection = connect()
             connection.fault = fault
             try:
             connection.sock.close()
 
     print "Test 18 - good SRP, prepare to resume"
-    sessionCache = tlslite.SessionCache()
+    sessionCache = SessionCache()
     connection = connect()
     connection.handshakeServer(verifierDB=verifierDB, sessionCache=sessionCache)
     connection.close()
     try:
         connection.read(min=1, max=1)
         assert() #Client is going to close the socket without a close_notify
-    except socket.error, e:
+    except TLSAbruptCloseError, e:
         pass
     connection = connect()
     try:
         connection.handshakeServer(verifierDB=verifierDB, sessionCache=sessionCache)
-    except tlslite.TLSLocalAlert, alert:
-        if alert.description != tlslite.AlertDescription.bad_record_mac:
+    except TLSLocalAlert, alert:
+        if alert.description != AlertDescription.bad_record_mac:
             raise
     connection.sock.close()
 
     #Close the current listening socket
     lsock.close()
 
-    #Create and run an HTTP Server using TLSMixIn
-    class MyHTTPServer(tlslite.TLSMixIn, BaseHTTPServer.HTTPServer):
+    #Create and run an HTTP Server using TLSSocketServerMixIn
+    class MyHTTPServer(TLSSocketServerMixIn,
+                       BaseHTTPServer.HTTPServer):
         def handshake(self, tlsConnection):
                 tlsConnection.handshakeServer(certChain=x509Chain, privateKey=x509Key)
                 return True
     lsock.listen(5)
 
     def connect():
-        return tlslite.TLSConnection(lsock.accept()[0])
+        return TLSConnection(lsock.accept()[0])
 
     if cryptoIDlibLoaded:
         print "Test 21a - HTTPS test SRP+cryptoID"
         #Close the current listening socket
         lsock.close()
 
-        #Create and run an HTTP Server using TLSMixIn
-        class MyHTTPServer(tlslite.TLSMixIn, BaseHTTPServer.HTTPServer):
+        #Create and run an HTTP Server using TLSSocketServerMixIn
+        class MyHTTPServer(TLSSocketServerMixIn,
+                           BaseHTTPServer.HTTPServer):
             def handshake(self, tlsConnection):
                     tlsConnection.handshakeServer(certChain=cryptoIDChain, privateKey=cryptoIDKey,
                                                   verifierDB=verifierDB)
         lsock.listen(5)
 
         def connect():
-            return tlslite.TLSConnection(lsock.accept()[0])
+            return TLSConnection(lsock.accept()[0])
 
 
 
     implementations = []
-    if tlslite.cryptlibpyLoaded:
+    if cryptlibpyLoaded:
         implementations.append("cryptlib")
-    if tlslite.m2cryptoLoaded:
+    if m2cryptoLoaded:
         implementations.append("openssl")
-    if tlslite.pycryptoLoaded:
+    if pycryptoLoaded:
         implementations.append("pycrypto")
     implementations.append("python")
 
             print "Test 22:",
             connection = connect()
 
-            settings = tlslite.HandshakeSettings()
+            settings = HandshakeSettings()
             settings.cipherNames = [cipher]
             settings.cipherImplementations = [implementation, "python"]
 
             print "Test 23:",
             connection = connect()
 
-            settings = tlslite.HandshakeSettings()
+            settings = HandshakeSettings()
             settings.cipherNames = [cipher]
             settings.cipherImplementations = [implementation, "python"]
 
 
 if len(sys.argv) == 1 or (len(sys.argv)==2 and sys.argv[1].lower().endswith("help")):
     print ""
-    print "Version: 0.2.4"
+    print "Version: 0.2.7"
     print ""
-    print "RNG: %s" % tlslite.prngName
+    print "RNG: %s" % prngName
     print ""
     print "Modules:"
-    if tlslite.cryptlibpyLoaded:
+    if cryptlibpyLoaded:
         print "  cryptlib_py : Loaded"
     else:
         print "  cryptlib_py : Not Loaded"
-    if tlslite.m2cryptoLoaded:
+    if m2cryptoLoaded:
         print "  M2Crypto    : Loaded"
     else:
         print "  M2Crypto    : Not Loaded"
-    if tlslite.pycryptoLoaded:
+    if pycryptoLoaded:
         print "  pycrypto    : Loaded"
     else:
         print "  pycrypto    : Not Loaded"
-    if tlslite.gmpyLoaded:
+    if gmpyLoaded:
         print "  GMPY        : Loaded"
     else:
         print "  GMPY        : Not Loaded"
             sock.connect(address)
 
             #Instantiate TLSConnections
-            return tlslite.TLSConnection(sock)
+            return TLSConnection(sock)
 
         try:
             if cmd == "clientnoauth":
                 args.getLast(2)
                 connection = connect()
                 start = time.clock()
-                connection.handshakeClientNoAuth()
+                connection.handshakeClientCert()
             elif cmd == "clientsrp":
                 username = args.get(3)
                 password = args.getLast(4)
 
                 #Try to create X.509 cert chain
                 if not certChain:
-                    x509 = tlslite.X509()
+                    x509 = X509()
                     x509.parse(s1)
-                    certChain = tlslite.X509CertChain([x509])
+                    certChain = X509CertChain([x509])
                     privateKey = parsePrivateKey(s2)
 
                 connection = connect()
             else:
                 raise SyntaxError("Unknown command")
 
-        except tlslite.TLSLocalAlert, a:
-            if a.description == tlslite.AlertDescription.bad_record_mac:
+        except TLSLocalAlert, a:
+            if a.description == AlertDescription.bad_record_mac:
                 if cmd == "clientsharedkey":
                     print "Bad sharedkey password"
                 else:
                     raise
-            elif a.description == tlslite.AlertDescription.user_canceled:
+            elif a.description == AlertDescription.user_canceled:
                 print str(a)
             else:
                 raise
             sys.exit()
-        except tlslite.TLSRemoteAlert, a:
-            if a.description == tlslite.AlertDescription.unknown_srp_username:
+        except TLSRemoteAlert, a:
+            if a.description == AlertDescription.unknown_srp_username:
                 if cmd == "clientsrp":
                     print "Unknown username"
                 else:
                     raise
-            elif a.description == tlslite.AlertDescription.bad_record_mac:
+            elif a.description == AlertDescription.bad_record_mac:
                 if cmd == "clientsrp":
                     print "Bad username or password"
                 else:
                     raise
-            elif a.description == tlslite.AlertDescription.handshake_failure:
+            elif a.description == AlertDescription.handshake_failure:
                 print "Unable to negotiate mutually acceptable parameters"
             else:
                 raise
 
         verifierDB = None
         if verifierDBFilename:
-            verifierDB = tlslite.VerifierDB(verifierDBFilename)
+            verifierDB = VerifierDB(verifierDBFilename)
             verifierDB.open()
 
         sharedKeyDB = None
         if sharedKeyDBFilename:
-            sharedKeyDB = tlslite.SharedKeyDB(sharedKeyDBFilename)
+            sharedKeyDB = SharedKeyDB(sharedKeyDBFilename)
             sharedKeyDB.open()
 
         certChain = None
 
             #Try to create X.509 cert chain
             if not certChain:
-                x509 = tlslite.X509()
+                x509 = X509()
                 x509.parse(s1)
-                certChain = tlslite.X509CertChain([x509])
+                certChain = X509CertChain([x509])
                 privateKey = parsePrivateKey(s2)
 
 
         #Create handler function - performs handshake, then echos all bytes received
         def handler(sock):
             try:
-                connection = tlslite.TLSConnection(sock)
-                settings = tlslite.HandshakeSettings()
+                connection = TLSConnection(sock)
+                settings = HandshakeSettings()
                 connection.handshakeServer(sharedKeyDB=sharedKeyDB, verifierDB=verifierDB, \
                                            certChain=certChain, privateKey=privateKey, \
                                            reqCert=reqCert, settings=settings)
                     if s[-1]=='\n':
                         connection.write(s)
                         s = ""
-            except tlslite.TLSLocalAlert, a:
-                if a.description == tlslite.AlertDescription.unknown_srp_username:
+            except TLSLocalAlert, a:
+                if a.description == AlertDescription.unknown_srp_username:
                     print "Unknown SRP username"
-                elif a.description == tlslite.AlertDescription.bad_record_mac:
+                elif a.description == AlertDescription.bad_record_mac:
                     if cmd == "serversrp" or cmd == "serversrpcert":
                         print "Bad SRP password"
                     else:
                         raise
-                elif a.description == tlslite.AlertDescription.handshake_failure:
+                elif a.description == AlertDescription.handshake_failure:
                     print "Unable to negotiate mutually acceptable parameters"
                 else:
                     raise
-            except tlslite.TLSRemoteAlert, a:
-                if a.description == tlslite.AlertDescription.bad_record_mac:
+            except TLSRemoteAlert, a:
+                if a.description == AlertDescription.bad_record_mac:
                     if cmd == "serversharedkey":
                         print "Bad sharedkey password"
                     else:
                         raise
-                elif a.description == tlslite.AlertDescription.user_canceled:
+                elif a.description == AlertDescription.user_canceled:
                     print "Handshake cancelled"
-                elif a.description == tlslite.AlertDescription.handshake_failure:
+                elif a.description == AlertDescription.handshake_failure:
                     print "Unable to negotiate mutually acceptable parameters"
-                elif a.description == tlslite.AlertDescription.close_notify:
+                elif a.description == AlertDescription.close_notify:
                     pass
                 else:
                     raise
 
     else:
         print "Bad command: '%s'" % cmd
-except tlslite.TLSRemoteAlert, a:
+except TLSRemoteAlert, a:
     print str(a)
     raise
 
     raise "This must be run as a command, not used as a module!"
 
 
-from tlslite import *
+from tlslite.api import *
 
 if len(sys.argv) == 1 or (len(sys.argv)==2 and sys.argv[1].lower().endswith("help")):
     print ""
-    print "Version: 0.2.4"
+    print "Version: 0.2.7"
     print ""
     print "RNG: %s" % prngName
     print ""
             db = VerifierDB(dbName)
             db.open()
             bits = int(args.getLast(5))
-            N, g, salt, verifier = makeVerifier(username, password, bits)
+            N, g, salt, verifier = VerifierDB.makeVerifier(username, password, bits)
             db[username] = N, g, salt, verifier
         except ValueError:
             db = SharedKeyDB(dbName)
 
         if isinstance(db, VerifierDB):
             print "SRP Database"
+            for username in db.keys():
+                N, g, s, v = db[username]
+                print cryptomath.numBits(N), username
         else:
             print "Shared Key Database"
-        for username in db.keys():
-            N, g, s, v = db[username]
-            print cryptomath.numBits(N), username
+            for username in db.keys():
+                print username
     else:
         print "Bad command: '%s'" % cmd
 except:
     exts = None
 
 setup(name="tlslite",
-      version="0.2.4",
+      version="0.2.7",
       author="Trevor Perrin",
       author_email="trevp@trevp.net",
       url="http://trevp.net/tlslite/",
       description="tlslite implements SSL v3 and TLS v1 with SRP, shared-keys, cryptoID, or X.509 authentication.",
       license="public domain",
       scripts=["scripts/tls.py", "scripts/tlsdb.py"],
-      packages=["tlslite", "tlslite.utils"],
+      packages=["tlslite", "tlslite.utils", "tlslite.integration"],
       ext_modules=exts)

test/httpsserver.py

+from SocketServer import *
+from BaseHTTPServer import *
+from SimpleHTTPServer import *
+from tlslite.api import *
+
+s = open("./serverX509Cert.pem").read()
+x509 = X509()
+x509.parse(s)
+certChain = X509CertChain([x509])
+
+s = open("./serverX509Key.pem").read()
+privateKey = parsePEMKey(s, private=True)
+
+sessionCache = SessionCache()
+
+class MyHTTPServer(ThreadingMixIn, TLSMixIn, HTTPServer):
+    def handshake(self, tlsConnection):
+        try:
+            tlsConnection.handshakeServer(certChain=certChain,
+                                          privateKey=privateKey,
+                                          sessionCache=sessionCache)
+            tlsConnection.ignoreAbruptClose = True
+            return True
+        except TLSAlert, alert:
+            print "Handshake failure:", str(alert)
+            return False
+
+httpd = MyHTTPServer(('localhost', 443), SimpleHTTPRequestHandler)
+httpd.serve_forever()

test/twistedclient.py

+
+from tlslite.api import *
+import socket
+
+s = socket.socket()
+
+s.connect( ("localhost", 1079) )
+
+"""
+#Only use this for Echo2
+s.send("000\r\n")
+while 1:
+    val= s.recv(100)
+    print val,
+    if val.endswith("000\r\n"):
+        break
+
+s.send("STARTTLS\r\n")
+"""
+
+connection = TLSConnection(s)
+#connection.handshakeClientNoAuth()
+connection.handshakeClientSRP("test", "password")
+
+connection.send("abc\r\n")
+print connection.recv(100),
+print connection.recv(100),
+
+connection.send("def\r\n")
+print connection.recv(100),
+
+connection.close()
+connection.sock.close()

test/twistedserver.py

+
+from twisted.internet.protocol import Protocol, Factory
+from twisted.internet import reactor
+from twisted.protocols.policies import WrappingFactory
+from twisted.protocols.basic import LineReceiver
+from twisted.python import log
+from twisted.python.failure import Failure
+import sys
+from tlslite.api import *
+
+s = open("./serverX509Cert.pem").read()
+x509 = X509()
+x509.parse(s)
+certChain = X509CertChain([x509])
+
+s = open("./serverX509Key.pem").read()
+privateKey = parsePEMKey(s, private=True)
+
+verifierDB = VerifierDB("verifierDB")
+verifierDB.open()
+
+class Echo(LineReceiver):
+  def connectionMade(self):
+      self.transport.write("Welcome to the echo server!\r\n")
+
+  def lineReceived(self, line):
+      self.transport.write(line + "\r\n")
+
+class Echo1(Echo):
+  def connectionMade(self):
+      if not self.transport.tlsStarted:
+          self.transport.setServerHandshakeOp(certChain=certChain,
+                                              privateKey=privateKey,
+                                              verifierDB=verifierDB)
+      else:
+          Echo.connectionMade(self)
+
+  def connectionLost(self, reason):
+      pass #Handle any TLS exceptions here
+
+class Echo2(Echo):
+  def lineReceived(self, data):
+      if data == "STARTTLS":
+          self.transport.setServerHandshakeOp(certChain=certChain,
+                                              privateKey=privateKey,
+                                              verifierDB=verifierDB)
+      else:
+          Echo.lineReceived(self, data)
+
+  def connectionLost(self, reason):
+      pass #Handle any TLS exceptions here
+
+factory = Factory()
+factory.protocol = Echo1
+#factory.protocol = Echo2
+
+wrappingFactory = WrappingFactory(factory)
+wrappingFactory.protocol = TLSTwistedProtocolWrapper
+
+log.startLogging(sys.stdout)
+reactor.listenTCP(1079, wrappingFactory)
+reactor.run()

test/verifierDB

Binary file added.

tlslite/AsyncStateMachine.py

-"""
-This class implements a state machine for using TLS Lite with select-based
-asynchronous communications (like Twisted or asyncore).
-
-The class signals wantsReadsEvent() and wantsWriteEvent().  When passed
-an event through readEvent() or writeEvent() calls, the class updates its
-state and "forwards" an event to its superclass, if applicable.
-"""
-
-class AsyncStateMachine:
-
-    def __init__(self):
-        self.clear()
-
-    def clear(self):
-        #These store the various asynchronous operations
-        #(i.e. generators).  Only one of them, at most,
-        #is ever active at a time.
-        self.handshaker = None
-        self.closer = None
-        self.reader = None
-        self.writer = None
-
-        #This stores the result from the last call to the
-        #currently active operation.  If 0 it indicates
-        #that the operation wants to read, if 1 it
-        #indicates that the operation wants to write.  If
-        #None, there is no active operation.
-        self.result = None
-
-    def checkAssert(self, maxActive=1):
-        #This checks that only one operation, at most, is
-        #active, and that self.result is set appropriately.
-        activeOps = 0
-        if self.handshaker:
-            activeOps += 1
-        if self.closer:
-            activeOps += 1
-        if self.reader:
-            activeOps += 1
-        if self.writer:
-            activeOps += 1
-
-        if self.result == None:
-            assert(activeOps == 0)
-        elif self.result in (0,1):
-            assert(activeOps == 1)
-        else:
-            assert()
-        assert (activeOps <= maxActive)
-
-    def wantsReadEvent(self):
-        #If there's an active operation, does it want to read?
-        if self.result != None:
-            return self.result == 0
-        return None
-
-    def wantsWriteEvent(self):
-        #If there's an active operation, does it want to write?
-        if self.result != None:
-            return self.result == 1
-        return None
-
-    #Superclass implements these to be notified when events occur
-
-    def forwardConnectEvent(self):
-        pass
-
-    def forwardCloseEvent(self):
-        pass
-
-    def forwardReadEvent(self, readBuffer):
-        pass
-
-    def forwardWriteEvent(self):
-        pass
-
-    def readEvent(self):
-        try:
-            self.checkAssert()
-            if self.handshaker:
-                self.doHandshakeOp()
-            elif self.closer:
-                self.doCloseOp()
-            elif self.reader:
-                self.doReadOp()
-            elif self.writer:
-                self.doWriteOp()
-            else:
-                self.reader = self.tlsConnection.readAsync(16384)
-                self.doReadOp()
-        except:
-            self.clear()
-            raise
-
-    def writeEvent(self):
-        try:
-            self.checkAssert()
-            if self.handshaker:
-                self.doHandshakeOp()
-            elif self.closer:
-                self.doCloseOp()
-            elif self.reader:
-                self.doReadOp()
-            elif self.writer:
-                self.doWriteOp()
-            else:
-                self.forwardWriteEvent()
-        except:
-            self.clear()
-            raise
-
-    def doHandshakeOp(self):
-        try:
-            self.result = self.handshaker.next()
-        except StopIteration:
-            self.handshaker = None
-            self.result = None
-            self.forwardConnectEvent()
-
-    def doCloseOp(self):
-        try:
-            self.result = self.closer.next()
-        except StopIteration:
-            self.closer = None
-            self.result = None
-            self.forwardCloseEvent()
-
-    def doReadOp(self):
-        self.result = self.reader.next()
-        if not self.result in (0,1):
-            readBuffer = self.result
-            self.reader = None
-            self.result = None
-            self.forwardReadEvent(readBuffer)
-
-    def doWriteOp(self):
-        try:
-            self.result = self.writer.next()
-        except StopIteration:
-            self.writer = None
-            self.result = None
-
-    def setHandshakeOp(self, handshaker):
-        try:
-            self.checkAssert(0)
-            self.handshaker = handshaker
-            self.doHandshakeOp()
-        except:
-            self.clear()
-            raise
-
-    def setServerHandshakeOp(self, **args):
-        handshaker = self.tlsConnection.handshakeServerAsync(**args)
-        self.setHandshakeOp(handshaker)
-
-    def setCloseOp(self):
-        try:
-            self.checkAssert(0)
-            self.closer = self.tlsConnection.closeAsync()
-            self.doCloseOp()
-        except:
-            self.clear()
-            raise
-
-    def setWriteOp(self, writeBuffer):
-        try:
-            self.checkAssert(0)
-            self.writer = self.tlsConnection.writeAsync(writeBuffer)
-            self.doWriteOp()
-        except:
-            self.clear()
-            raise
-

tlslite/BaseDB.py

+"""Base class for SharedKeyDB and VerifierDB."""
+
+import anydbm
+import thread
+
+class BaseDB:
+    def __init__(self, filename, type):
+        self.type = type
+        self.filename = filename
+        if self.filename:
+            self.db = None
+        else:
+            self.db = {}
+        self.lock = thread.allocate_lock()
+
+    def create(self):
+        """Create a new on-disk database."""
+        if self.filename:
+            self.db = anydbm.open(self.filename, "n") #raises anydbm.error
+            self.db["--Reserved--type"] = self.type
+            self.db.sync()
+        else:
+            self.db = {}
+
+    def open(self):
+        """Open a pre-existing on-disk database."""
+        if not self.filename:
+            raise ValueError("Can only open on-disk databases")
+        self.db = anydbm.open(self.filename, "w") #raises anydbm.error
+        try:
+            if self.db["--Reserved--type"] != self.type:
+                raise ValueError("Not a %s database" % self.type)
+        except KeyError:
+            raise ValueError("Not a recognized database")
+
+    def __getitem__(self, username):
+        if self.db == None:
+            raise AssertionError("DB not open")
+
+        self.lock.acquire()
+        try:
+            valueStr = self.db[username]
+        finally:
+            self.lock.release()
+
+        return self._getItem(username, valueStr)
+
+    def __setitem__(self, username, value):
+        if self.db == None:
+            raise AssertionError("DB not open")
+
+        valueStr = self._setItem(username, value)
+
+        self.lock.acquire()
+        try:
+            if self.db.has_key(username):
+                raise ValueError("Can't add duplicate entry")
+            self.db[username] = valueStr
+            if not self.db[username]:
+                raise AssertionError()
+            if self.filename:
+                self.db.sync()
+        finally:
+            self.lock.release()
+
+    def __delitem__(self, username):
+        if self.db == None:
+            raise AssertionError("DB not open")
+
+        self.lock.acquire()
+        try:
+            if not self.db.has_key(username):
+                raise KeyError()
+            del(self.db[username])
+            if self.filename:
+                self.db.sync()
+        finally:
+            self.lock.release()
+
+    def __contains__(self, username):
+        """Check if the database contains the specified username.
+
+        @type username: str
+        @param username: The username to check for.
+
+        @rtype: bool
+        @return: True if the database contains the username, False
+        otherwise.
+
+        """
+        if self.db == None:
+            raise AssertionError("DB not open")
+
+        self.lock.acquire()
+        try:
+            return self.db.has_key(username)
+        finally:
+            self.lock.release()
+
+    def check(self, username, param):
+        value = self.__getitem__(username)
+        return self._checkItem(username, value, param)
+
+    def keys(self):
+        """Return a list of usernames in the database.
+
+        @rtype: list
+        @return: The usernames in the database.
+        """
+        if self.db == None:
+            raise AssertionError("DB not open")
+
+        self.lock.acquire()
+        try:
+            usernames = self.db.keys()
+        finally:
+            self.lock.release()
+        usernames = [u for u in usernames if not u.startswith("--Reserved--")]
+        return usernames

tlslite/HTTPTLSConnection.py

-
-import socket
-import httplib
-from alerts import *
-from Checker import Checker
-from TLSConnection import *
-
-
-#To do handshaking, subclass HTTPBaseTLSConnection and override handshake()
-
-class HTTPBaseTLSConnection(httplib.HTTPConnection):
-
-    default_port = 443
-
-    def __init__(self, host, port=None, strict=None):
-        httplib.HTTPConnection.__init__(self, host, port, strict)
-        self.tlsSession = None
-
-    def connect(self):
-        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        if hasattr(sock, 'settimeout'):
-            sock.settimeout(10)
-        sock.connect((self.host, self.port))
-        self.sock = TLSConnection(sock)  #Use a TLSConnection to emulate a socket
-        self.sock.closeSocket = True  #When httplib closes this, close the socket
-        self.handshake(self.sock, self.tlsSession)
-        self.tlsSession = self.sock.session
-
-
-    #Call a handshake function here, using the current connection and the
-    #session object, which may be None or may be a resumable or nonresumable
-    #session.
-    #If the handshake doesn't complete to your liking, raise an exception
-    def handshake(self, tlsConnection, tlsSession):
-        raise NotImplementedError()       
-    
-    
-class HTTPTLSConnection(HTTPBaseTLSConnection):
-
-    def __init__(self, host, port=None, 
-                 username=None, password=None, sharedKey=None, 
-                 certChain=None, privateKey=None,
-                 cryptoID=None, protocol=None,
-                 x509Fingerprint=None):
-        HTTPBaseTLSConnection.__init__(self, host, port)
-        
-        self.username = None
-        self.password = None
-        self.sharedKey = None
-        self.certChain = None
-        self.privateKey = None
-        self.checker = None
-        
-        #SRP Authentication
-        if username and password and not (sharedKey or certChain or privateKey):
-            self.username = username
-            self.password = password
-        
-        #Shared Key Authentication
-        elif username and sharedKey and not (password or certChain or privateKey):
-            self.username = username
-            self.sharedKey = sharedKey
-        
-        #Certificate Chain Authentication
-        elif certChain and privateKey and not (username or password or sharedKey):
-            self.certChain = certChain
-            self.privateKey = privateKey
-
-        #No Authentication
-        elif not password and not username and not sharedKey and not certChain and not privateKey:
-            pass
-            
-        else:
-            raise ValueError("Bad parameters")
-           
-        #Authenticate the server based on its cryptoID or fingerprint
-        if sharedKey and (cryptoID or protocol or x509Fingerprint):
-            raise ValueError("Can't use shared keys with other forms of authentication")
-
-        self.setChecker(cryptoID, protocol, x509Fingerprint)
-
-    #If we've connected previously, this will check that session.
-    #It will also check all connections going forward
-    def setChecker(self, cryptoID=None, protocol=None, x509Fingerprint=None):
-        self.checker = Checker(cryptoID=cryptoID, protocol=protocol, 
-                               x509Fingerprint=x509Fingerprint)
-        if self.tlsSession:
-            self.checker(self.sock)
-        
-    def handshake(self, tlsConnection, tlsSession):
-        if self.username and self.password:
-            tlsConnection.handshakeClientSRP(username=self.username, 
-                                             password=self.password, 
-                                             checker=self.checker,
-                                             session=tlsSession)
-        elif self.username and self.sharedKey:
-            tlsConnection.handshakeClientSharedKey(username=self.username, 
-                                                   sharedKey=self.sharedKey)
-        elif self.certChain and self.privateKey:
-            tlsConnection.handshakeClientCert(certChain=self.certChain, 
-                                              privateKey=self.privateKey, 
-                                              checker=self.checker,
-                                              session=tlsSession)
-        else:
-            tlsConnection.handshakeClientNoAuth(checker=self.checker, session=tlsSession)

tlslite/TLSAsyncDispatcherMixIn.py

-"""
-Overview
----------
-This class can be mixed-in with an asyncore.dispatcher.  It essentially sits
-between the dispatcher and the select loop, intercepting events and only
-calling the dispatcher when applicable.
-
-In the case of handle_read(), a read operation will be activated, and when
-it completes, the bytes will be placed in a buffer where the dispatcher can
-retrieve them by calling recv(), and the dispatcher's handle_read() will be
-called.
-
-In the case of handle_write(), the dispatcher's handle_write() will be
-called, and when it calls send(), a write operation will be activated.
-
-Initialization
----------------
-To use this class, you must combine it with an asyncore.dispatcher, and
-pass in a handshake operation with setServerHandshakeOp().
-
-Below is an example of using this class with medusa.  This class is mixed
-in with http_channel to create http_tls_channel.  Note:
- - the mix-in is listed first in the inheritance list
- - the input buffer size must be at least 16K, otherwise the dispatcher
-   might not read all the bytes from the TLS layer, leaving some in limbo.
- - IE has a problem receiving a whole HTTP response in a single TLS record,
-   so HTML pages containing '\r\n\r\n' won't be displayed on IE.
-
-Add the following text into 'start_medusa.py', in the 'HTTP Server' section:
-
-import tlslite
-s = open("./serverX509Cert.pem").read()
-x509 = tlslite.X509()
-x509.parse(s)
-certChain = tlslite.X509CertChain([x509])
-
-s = open("./serverX509Key.pem").read()
-privateKey = tlslite.parsePEMKey(s, private=True)
-
-class http_tls_channel(tlslite.TLSAsyncDispatcherMixIn,
-                       http_server.http_channel):
-    ac_in_buffer_size = 16384
-
-    def __init__ (self, server, conn, addr):
-        http_server.http_channel.__init__(self, server, conn, addr)
-        tlslite.TLSAsyncDispatcherMixIn.__init__(self, conn)
-        self.setServerHandshakeOp(certChain=certChain, privateKey=privateKey)
-
-hs.channel_class = http_tls_channel
-
-Errors
--------
-If the TLS layer raises an exception, the exception will be caught in
-asyncore.dispatcher, which will call close() on this class.  The TLS layer
-always closes the TLS connection before raising an exception, so the
-close operation will complete right away, causing asyncore.dispatcher.close()
-to be called, which closes the socket and removes this instance from the
-asyncore loop.
-
-"""
-
-
-import asyncore
-from TLSConnection import TLSConnection
-from AsyncStateMachine import AsyncStateMachine
-
-
-class TLSAsyncDispatcherMixIn(AsyncStateMachine):
-
-    def __init__(self, sock=None):
-        AsyncStateMachine.__init__(self)
-
-        if sock:
-            self.tlsConnection = TLSConnection(sock)
-
-        #Calculate the sibling I'm being mixed in with.
-        #This is necessary since we override functions
-        #like readable(), handle_read(), etc., but we
-        #also want to call the sibling's versions.
-        for cl in self.__class__.__bases__:
-            if cl != TLSAsyncDispatcherMixIn and cl != AsyncStateMachine:
-                self.siblingClass = cl
-                break
-        else:
-            assert()
-
-    def readable(self):
-        result = self.wantsReadEvent()
-        if result != None:
-            return result
-        return self.siblingClass.readable(self)
-
-    def writable(self):
-        result = self.wantsWriteEvent()
-        if result != None:
-            return result
-        return self.siblingClass.writable(self)
-
-    def handle_read(self):
-        self.readEvent()
-
-    def handle_write(self):
-        self.writeEvent()
-
-    def forwardConnectEvent(self):
-        self.siblingClass.handle_connect(self)
-
-    def forwardCloseEvent(self):
-        asyncore.dispatcher.close(self)
-
-    def forwardReadEvent(self, readBuffer):
-        self.readBuffer = readBuffer
-        self.siblingClass.handle_read(self)
-
-    def forwardWriteEvent(self):
-        self.siblingClass.handle_write(self)
-
-    def recv(self, bufferSize=16384):
-        assert(bufferSize >= 16384 and self.readBuffer != None)
-        return self.readBuffer
-        self.readBuffer = None
-
-    def send(self, writeBuffer):
-        self.setWriteOp(writeBuffer)
-        return len(writeBuffer)
-
-    def close(self):
-        if hasattr(self, "tlsConnection"):
-            self.setCloseOp()
-        else:
-            asyncore.dispatcher.close(self)

tlslite/TLSMixIn.py

-
-from TLSConnection import TLSConnection
-
-class TLSMixIn:
-
-    def finish_request(self, sock, client_address):
-        tlsConnection = TLSConnection(sock)
-        if self.handshake(tlsConnection) == True:
-            self.RequestHandlerClass(tlsConnection, client_address, self)
-            tlsConnection.close()
-
-    #Implement this method to do some form of handshaking.  Return True
-    #if the handshake finishes properly and the request is authorized.
-    def handshake(self, tlsConnection):
-        raise NotImplementedError()

tlslite/TLSTwistedMixIn.py

-
-from TLSConnection import TLSConnection
-from AsyncStateMachine import AsyncStateMachine
-
-
-class TLSTwistedMixIn(AsyncStateMachine):
-
-    def __init__(self, sock=None):
-        AsyncStateMachine.__init__(self)
-
-        if sock:
-            self.tlsConnection = TLSConnection(sock)
-
-        #Calculate the sibling I'm being mixed in with.
-        #This is necessary since we override functions
-        #like doRead(), doWrite(), etc., but we
-        #also want to call the sibling's versions.
-        for cl in self.__class__.__bases__:
-            if cl != TLSTwistedMixIn and cl != AsyncStateMachine:
-                self.siblingClass = cl
-                break
-        else:
-            assert()
-
-    def readable(self):
-        result = self.wantsReadEvent()
-        if result != None:
-            return result
-        return self.siblingClass.readable(self)
-
-    def writable(self):
-        result = self.wantsWriteEvent()
-        if result != None:
-            return result
-        return self.siblingClass.writable(self)
-
-
-    def doRead(self):
-        self.readEvent()
-        if self.wantsReadEvent():
-            self.startReading()
-        if self.wantsWriteEvent():
-            self.startWriting()
-
-    def doWrite(self):
-        self.writeEvent()
-        if self.wantsReadEvent():
-            self.startReading()
-        if self.wantsWriteEvent():
-            self.startWriting()
-
-    def forwardConnectEvent(self):
-        pass
-
-    def forwardCloseEvent(self):
-        pass
-        #asyncore.dispatcher.close(self)
-
-    def forwardReadEvent(self, readBuffer):
-        self.protocol.dataReceived(readBuffer)
-
-    def forwardWriteEvent(self):
-        self.siblingClass.doWrite(self)
-
-    def writeSomeData(self, data):
-        self.setWriteOp(data)
-        return len(data)
-
-    def loseConnection(self):
-        pass
-        #if hasattr(self, "tlsConnection"):
-        #    self.setCloseOp()
-        #else:
-        #    asyncore.dispatcher.close(self)

tlslite/X509CertChain.py

+"""Class representing an X.509 certificate chain."""
+
+class X509CertChain:
+    """This class represents a chain of X.509 certificates."""
+
+    def __init__(self, x509List=None):
+        """Create a new X509CertChain.
+
+        @type x509List: list
+        @param x509List: A list of L{tlslite.X509.X509} instances.
+        """
+        if x509List:
+            self.x509List = x509List
+        else:
+            self.x509List = []
+
+    def getNumCerts(self):
+        return len(self.x509List)
+
+    def getEndEntityPublicKey(self):
+        if self.getNumCerts == 0:
+            raise AssertionError()
+        return self.x509List[0].publicKey
+
+    def getFingerprint(self):
+        if self.getNumCerts == 0:
+            raise AssertionError()
+        return self.x509List[0].getFingerprint()
+
+    def validate(self):
+        raise NotImplementedError()

tlslite/alerts.py

-
-from constants import AlertDescription, AlertLevel
-
-class TLSAlert(Exception):
-    pass
-
-class TLSLocalAlert(TLSAlert):
-    def __init__(self, alert, message=None):
-        self.description = alert.description
-        self.level = alert.level
-        self.message = message
-        
-    def __str__(self):
-        alertStr = descriptionStr.get(self.description)
-        if alertStr == None:
-            alertStr = str(self.description)    
-        if self.message:
-            return alertStr + ": " + self.message
-        else:
-            return alertStr
-    
-class TLSRemoteAlert(TLSAlert):
-    def __init__(self, alert):
-        self.description = alert.description
-        self.level = alert.level
-
-    def __str__(self):
-        alertStr = descriptionStr.get(self.description)
-        if alertStr == None:
-            alertStr = str(self.description)
-        return alertStr
-        
-descriptionStr = {\
-    AlertDescription.close_notify: "close_notify",\
-    AlertDescription.unexpected_message: "unexpected_message",\
-    AlertDescription.bad_record_mac: "bad_record_mac",\
-    AlertDescription.decryption_failed: "decryption_failed",\
-    AlertDescription.record_overflow: "record_overflow",\
-    AlertDescription.decompression_failure: "decompression_failure",\
-    AlertDescription.handshake_failure: "handshake_failure",\
-    AlertDescription.no_certificate: "no certificate",\
-    AlertDescription.bad_certificate: "bad_certificate",\
-    AlertDescription.unsupported_certificate: "unsupported_certificate",\
-    AlertDescription.certificate_revoked: "certificate_revoked",\
-    AlertDescription.certificate_expired: "certificate_expired",\
-    AlertDescription.certificate_unknown: "certificate_unknown",\
-    AlertDescription.illegal_parameter: "illegal_parameter",\
-    AlertDescription.unknown_ca: "unknown_ca",\
-    AlertDescription.access_denied: "access_denied",\
-    AlertDescription.decode_error: "decode_error",\
-    AlertDescription.decrypt_error: "decrypt_error",\
-    AlertDescription.export_restriction: "export_restriction",\
-    AlertDescription.protocol_version: "protocol_version",\
-    AlertDescription.insufficient_security: "insufficient_security",\
-    AlertDescription.internal_error: "internal_error",\
-    AlertDescription.user_canceled: "user_canceled",\
-    AlertDescription.no_renegotiation: "no_renegotiation",\
-    AlertDescription.unknown_srp_username: "unknown_srp_username",\
-    AlertDescription.missing_srp_username: "missing_srp_username"}        
+"""Import this module for easy access to TLS Lite objects.
+
+The TLS Lite API consists of classes, functions, and variables spread
+throughout this package.  Instead of importing them individually with::
+
+    from tlslite.TLSConnection import TLSConnection
+    from tlslite.HandshakeSettings import HandshakeSettings
+    from tlslite.errors import *
+    .
+    .
+
+It's easier to do::
+
+    from tlslite.api import *
+
+This imports all the important objects (TLSConnection, Checker,
+HandshakeSettings, etc.) into the global namespace.
+"""
+
+
+from constants import AlertLevel, AlertDescription, Fault
+from errors import *
+from Checker import Checker
+from HandshakeSettings import HandshakeSettings
+from Session import Session
+from SessionCache import SessionCache
+from SharedKeyDB import SharedKeyDB
+from TLSConnection import TLSConnection
+from VerifierDB import VerifierDB
+from X509 import X509
+from X509CertChain import X509CertChain
+
+from integration.HTTPTLSConnection import HTTPTLSConnection
+from integration.TLSSocketServerMixIn import TLSSocketServerMixIn
+from integration.TLSAsyncDispatcherMixIn import TLSAsyncDispatcherMixIn
+try:
+    import twisted
+    del(twisted)
+    from integration.TLSTwistedProtocolWrapper import TLSTwistedProtocolWrapper
+except ImportError:
+    pass
+
+from utils.cryptomath import cryptlibpyLoaded, m2cryptoLoaded, gmpyLoaded, \
+                             pycryptoLoaded, prngName
+from utils.keyfactory import generateRSAKey, parsePEMKey, parseXMLKey, \
+                             parseAsPublicKey, parsePrivateKey

tlslite/errors.py

+"""Exception classes.
+@sort: TLSError, TLSAbruptCloseError, TLSAlert, TLSLocalAlert, TLSRemoteAlert,
+TLSAuthenticationError, TLSNoAuthenticationError, TLSAuthenticationTypeError,
+TLSFingerprintError, TLSAuthorizationError, TLSValidationError, TLSFaultError
+"""
+
+from constants import AlertDescription, AlertLevel
+
+class TLSError(Exception):
+    """Base class for all TLS Lite exceptions."""
+    pass
+
+class TLSAbruptCloseError(TLSError):
+    """The socket was closed without a proper TLS shutdown.
+
+    The TLS specification mandates that an alert of some sort
+    must be sent before the underlying socket is closed.  If the socket
+    is closed without this, it could signify that an attacker is trying
+    to truncate the connection.  It could also signify a misbehaving
+    TLS implementation, or a random network failure.
+    """
+    pass