root / trunk / twisted / conch / ssh / factory.py

Revision 24901, 4.6 kB (checked in by jml, 10 months ago)

Make SSHFactory use self.protocol to construct protocol instances.

  • Author: mwh
  • Reviewer: jml
  • Fixes #3443

Previously SSHFactory always instantiated an SSHServerTransport. This
commit allows subclasses of SSHFactory to specify their own protocol --
usually a subclass of SSHServerTransport.

Line 
1 # Copyright (c) 2001-2008 Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4 """
5 A Factory for SSH servers, along with an OpenSSHFactory to use the same
6 data sources as OpenSSH.
7
8 Maintainer: Paul Swartz
9 """
10
11 try:
12     import resource
13 except ImportError:
14     resource = None
15
16 from twisted.internet import protocol
17 from twisted.python import log
18 from twisted.python.reflect import qual
19
20 from twisted.conch import error
21 from twisted.conch.ssh import keys
22 import transport, userauth, connection
23
24 import random
25 import warnings
26
27 class SSHFactory(protocol.Factory):
28
29     protocol = transport.SSHServerTransport
30
31     services = {
32         'ssh-userauth':userauth.SSHUserAuthServer,
33         'ssh-connection':connection.SSHConnection
34     }
35     def startFactory(self):
36         # disable coredumps
37         if resource:
38             resource.setrlimit(resource.RLIMIT_CORE, (0,0))
39         else:
40             log.msg('INSECURE: unable to disable core dumps.')
41         if not hasattr(self,'publicKeys'):
42             self.publicKeys = self.getPublicKeys()
43         for keyType, value in self.publicKeys.items():
44             if isinstance(value, str):
45                 warnings.warn("Returning a mapping from strings to "
46                         "strings from getPublicKeys()/publicKeys (in %s) "
47                         "is deprecated.  Return a mapping from "
48                         "strings to Key objects instead." %
49                         (qual(self.__class__)),
50                         DeprecationWarning, stacklevel=1)
51                 self.publicKeys[keyType] = keys.Key.fromString(value)
52         if not hasattr(self,'privateKeys'):
53             self.privateKeys = self.getPrivateKeys()
54         for keyType, value in self.privateKeys.items():
55             if not isinstance(value, keys.Key):
56                 warnings.warn("Returning a mapping from strings to "
57                         "PyCrypto key objects from "
58                         "getPrivateKeys()/privateKeys (in %s) "
59                         "is deprecated.  Return a mapping from "
60                         "strings to Key objects instead." %
61                         (qual(self.__class__),),
62                         DeprecationWarning, stacklevel=1)
63                 self.privateKeys[keyType] = keys.Key(value)
64         if not self.publicKeys or not self.privateKeys:
65             raise error.ConchError('no host keys, failing')
66         if not hasattr(self,'primes'):
67             self.primes = self.getPrimes()
68
69     def buildProtocol(self, addr):
70         t = protocol.Factory.buildProtocol(self, addr)
71         t.supportedPublicKeys = self.privateKeys.keys()
72         if not self.primes:
73             log.msg('disabling diffie-hellman-group-exchange because we '
74                     'cannot find moduli file')
75             ske = t.supportedKeyExchanges[:]
76             ske.remove('diffie-hellman-group-exchange-sha1')
77             t.supportedKeyExchanges = ske
78         return t
79
80     def getPublicKeys(self):
81         """
82         Called when the factory is started to get the public portions of the
83         servers host keys.  Returns a dictionary mapping SSH key types to
84         public key strings.
85
86         @rtype: C{dict}
87         """
88         raise NotImplementedError('getPublicKeys unimplemented')
89
90     def getPrivateKeys(self):
91         """
92         Called when the factory is started to get the  private portions of the
93         servers host keys.  Returns a dictionary mapping SSH key types to
94         C{Crypto.PublicKey.pubkey.pubkey} objects.
95
96         @rtype: C{dict}
97         """
98         raise NotImplementedError('getPrivateKeys unimplemented')
99
100     def getPrimes(self):
101         """
102         Called when the factory is started to get Diffie-Hellman generators and
103         primes to use.  Returns a dictionary mapping number of bits to lists
104         of tuple of (generator, prime).
105
106         @rtype: C{dict}
107         """
108
109     def getDHPrime(self, bits):
110         """
111         Return a tuple of (g, p) for a Diffe-Hellman process, with p being as
112         close to bits bits as possible.
113
114         @type bits: C{int}
115         @rtype:     C{tuple}
116         """
117         primesKeys = self.primes.keys()
118         primesKeys.sort(lambda x, y: cmp(abs(x - bits), abs(y - bits)))
119         realBits = primesKeys[0]
120         return random.choice(self.primes[realBits])
121
122     def getService(self, transport, service):
123         """
124         Return a class to use as a service for the given transport.
125
126         @type transport:    L{transport.SSHServerTransport}
127         @type service:      C{str}
128         @rtype:             subclass of L{service.SSHService}
129         """
130         if service == 'ssh-userauth' or hasattr(transport, 'avatar'):
131             return self.services[service]
Note: See TracBrowser for help on using the browser.