viff

changeset 820:facc9f1f0bb1

Switch to PyOpenSSL for SSL/TLS support. This removes the dependency on the GnuTLS library and should make it possible to use VIFF with SSL support under Windows.
author Martin Geisler <mg@daimi.au.dk>
date Sat, 12 Jul 2008 18:14:38 +0200
parents 1ed10c3ce40c
children b767a45cec65
files viff/runtime.py
diffstat 1 files changed, 43 insertions(+), 31 deletions(-) [+]
line diff
     1.1 --- a/viff/runtime.py	Sat Jul 12 16:12:17 2008 +0200
     1.2 +++ b/viff/runtime.py	Sat Jul 12 18:14:38 2008 +0200
     1.3 @@ -257,10 +257,6 @@
     1.4  
     1.5      def connectionMade(self):
     1.6          self.sendString(str(self.factory.runtime.id))
     1.7 -        try:
     1.8 -            self.peer_cert = self.transport.socket.peer_certificate
     1.9 -        except AttributeError:
    1.10 -            self.peer_cert = None
    1.11  
    1.12      def connectionLost(self, reason):
    1.13          reason.trap(ConnectionDone)
    1.14 @@ -275,15 +271,18 @@
    1.15          if self.peer_id is None:
    1.16              # TODO: Handle ValueError if the string cannot be decoded.
    1.17              self.peer_id = int(string)
    1.18 -            if self.peer_cert:
    1.19 +            try:
    1.20 +                cert = self.transport.getPeerCertificate()
    1.21 +            except AttributeError:
    1.22 +                cert = None
    1.23 +            if cert:
    1.24                  # The player ID are stored in the serial number of the
    1.25                  # certificate -- this makes it easy to check that the
    1.26                  # player is who he claims to be.
    1.27 -                if self.peer_cert.serial_number != self.peer_id:
    1.28 +                if cert.get_serial_number() != self.peer_id:
    1.29                      print "Peer %s claims to be %d, aborting!" \
    1.30 -                        % (self.peer_cert.subject, self.peer_id)
    1.31 +                        % (cert.get_subject(), self.peer_id)
    1.32                      self.transport.loseConnection()
    1.33 -
    1.34              self.factory.identify_peer(self)
    1.35          else:
    1.36              program_counter, data_type, data = marshal.loads(string)
    1.37 @@ -410,25 +409,25 @@
    1.38          group.add_option("-k", "--security-parameter", type="int", metavar="K",
    1.39                           help=("Security parameter. Comparisons will leak "
    1.40                                 "information with probability 2**-K."))
    1.41 -        group.add_option("--no-tls", action="store_false", dest="tls",
    1.42 -                         help="Disable the use of secure TLS connections.")
    1.43 -        group.add_option("--tls", action="store_true",
    1.44 -                         help=("Enable the use of secure TLS connections "
    1.45 -                               "(if the GNUTLS bindings are available)."))
    1.46 +        group.add_option("--no-ssl", action="store_false", dest="ssl",
    1.47 +                         help="Disable the use of secure SSL connections.")
    1.48 +        group.add_option("--ssl", action="store_true",
    1.49 +                         help=("Enable the use of secure SSL connections "
    1.50 +                               "(if the OpenSSL bindings are available)."))
    1.51          group.add_option("--deferred-debug", action="store_true",
    1.52                           help="Enable extra debug output for deferreds.")
    1.53  
    1.54          try:
    1.55              # Using __import__ since we do not use the module, we are
    1.56              # only interested in the side-effect.
    1.57 -            __import__('gnutls')
    1.58 -            have_gnutls = True
    1.59 +            __import__('OpenSSL')
    1.60 +            have_openssl = True
    1.61          except ImportError:
    1.62 -            have_gnutls = False
    1.63 +            have_openssl = False
    1.64  
    1.65          parser.set_defaults(bit_length=32,
    1.66                              security_parameter=30,
    1.67 -                            tls=have_gnutls,
    1.68 +                            ssl=have_openssl,
    1.69                              deferred_debug=False)
    1.70  
    1.71      def __init__(self, player, threshold, options=None):
    1.72 @@ -1499,27 +1498,40 @@
    1.73      runtime = runtime_class(players[id], threshold, options)
    1.74      factory = ShareExchangerFactory(runtime, players, result)
    1.75  
    1.76 -    if options and options.tls:
    1.77 -        print "Using TLS"
    1.78 -        from gnutls.interfaces.twisted import X509Credentials
    1.79 -        from gnutls.crypto import X509Certificate, X509PrivateKey
    1.80 +    if options and options.ssl:
    1.81 +        print "Using SSL"
    1.82 +        from twisted.internet.ssl import ContextFactory, ClientContextFactory
    1.83 +        from OpenSSL import SSL
    1.84  
    1.85 -        # TODO: Make the file names configurable.
    1.86 -        cert = X509Certificate(open('player-%d.cert' % id).read())
    1.87 -        key = X509PrivateKey(open('player-%d.key' % id).read())
    1.88 -        ca = X509Certificate(open('ca.cert').read())
    1.89 -        cred = X509Credentials(cert, key, [ca])
    1.90 -        cred.verify_peer = True
    1.91 -        reactor.listenTLS(players[id].port, factory, cred)
    1.92 +        class SSLContextFactory(ContextFactory):
    1.93 +            def __init__(self, id):
    1.94 +                """Create new SSL context factory for *id*."""
    1.95 +                self.id = id
    1.96 +                ctx = SSL.Context(SSL.SSLv3_METHOD)
    1.97 +                # TODO: Make the file names configurable.
    1.98 +                ctx.use_certificate_file('player-%d.cert' % id)
    1.99 +                ctx.use_privatekey_file('player-%d.key' % id)
   1.100 +                ctx.check_privatekey()
   1.101 +
   1.102 +                ctx.load_verify_locations('ca.cert')
   1.103 +                ctx.set_verify(SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT,
   1.104 +                               lambda conn, cert, errnum, depth, ok: ok)
   1.105 +                self.ctx = ctx
   1.106 +
   1.107 +            def getContext(self):
   1.108 +                return self.ctx
   1.109 +
   1.110 +        ctx_factory = SSLContextFactory(id)
   1.111 +        reactor.listenSSL(players[id].port, factory, ctx_factory)
   1.112      else:
   1.113 -        print "Not using TLS"
   1.114 +        print "Not using SSL"
   1.115          reactor.listenTCP(players[id].port, factory)
   1.116  
   1.117      for peer_id, player in players.iteritems():
   1.118          if peer_id > id:
   1.119              print "Will connect to %s" % player
   1.120 -            if options and options.tls:
   1.121 -                reactor.connectTLS(player.host, player.port, factory, cred)
   1.122 +            if options and options.ssl:
   1.123 +                reactor.connectSSL(player.host, player.port, factory, ctx_factory)
   1.124              else:
   1.125                  reactor.connectTCP(player.host, player.port, factory)
   1.126