OLD | NEW |
| (Empty) |
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: U{Paul Swartz<mailto:z3p@twistedmatrix.com>} | |
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 services = { | |
29 'ssh-userauth':userauth.SSHUserAuthServer, | |
30 'ssh-connection':connection.SSHConnection | |
31 } | |
32 def startFactory(self): | |
33 # disable coredumps | |
34 if resource: | |
35 resource.setrlimit(resource.RLIMIT_CORE, (0,0)) | |
36 else: | |
37 log.msg('INSECURE: unable to disable core dumps.') | |
38 if not hasattr(self,'publicKeys'): | |
39 self.publicKeys = self.getPublicKeys() | |
40 for keyType, value in self.publicKeys.items(): | |
41 if isinstance(value, str): | |
42 warnings.warn("Returning a mapping from strings to " | |
43 "strings from getPublicKeys()/publicKeys (in %s) " | |
44 "is deprecated. Return a mapping from " | |
45 "strings to Key objects instead." % | |
46 (qual(self.__class__)), | |
47 DeprecationWarning, stacklevel=1) | |
48 self.publicKeys[keyType] = keys.Key.fromString(value) | |
49 if not hasattr(self,'privateKeys'): | |
50 self.privateKeys = self.getPrivateKeys() | |
51 for keyType, value in self.privateKeys.items(): | |
52 if not isinstance(value, keys.Key): | |
53 warnings.warn("Returning a mapping from strings to " | |
54 "PyCrypto key objects from " | |
55 "getPrivateKeys()/privateKeys (in %s) " | |
56 "is deprecated. Return a mapping from " | |
57 "strings to Key objects instead." % | |
58 (qual(self.__class__),), | |
59 DeprecationWarning, stacklevel=1) | |
60 self.privateKeys[keyType] = keys.Key(value) | |
61 if not self.publicKeys or not self.privateKeys: | |
62 raise error.ConchError('no host keys, failing') | |
63 if not hasattr(self,'primes'): | |
64 self.primes = self.getPrimes() | |
65 | |
66 def buildProtocol(self, addr): | |
67 t = transport.SSHServerTransport() | |
68 t.supportedPublicKeys = self.privateKeys.keys() | |
69 if not self.primes: | |
70 log.msg('disabling diffie-hellman-group-exchange because we ' | |
71 'cannot find moduli file') | |
72 ske = t.supportedKeyExchanges[:] | |
73 ske.remove('diffie-hellman-group-exchange-sha1') | |
74 t.supportedKeyExchanges = ske | |
75 t.factory = self | |
76 return t | |
77 | |
78 def getPublicKeys(self): | |
79 """ | |
80 Called when the factory is started to get the public portions of the | |
81 servers host keys. Returns a dictionary mapping SSH key types to | |
82 public key strings. | |
83 | |
84 @rtype: C{dict} | |
85 """ | |
86 raise NotImplementedError('getPublicKeys unimplemented') | |
87 | |
88 def getPrivateKeys(self): | |
89 """ | |
90 Called when the factory is started to get the private portions of the | |
91 servers host keys. Returns a dictionary mapping SSH key types to | |
92 C{Crypto.PublicKey.pubkey.pubkey} objects. | |
93 | |
94 @rtype: C{dict} | |
95 """ | |
96 raise NotImplementedError('getPrivateKeys unimplemented') | |
97 | |
98 def getPrimes(self): | |
99 """ | |
100 Called when the factory is started to get Diffie-Hellman generators and | |
101 primes to use. Returns a dictionary mapping number of bits to lists | |
102 of tuple of (generator, prime). | |
103 | |
104 @rtype: C{dict} | |
105 """ | |
106 | |
107 def getDHPrime(self, bits): | |
108 """ | |
109 Return a tuple of (g, p) for a Diffe-Hellman process, with p being as | |
110 close to bits bits as possible. | |
111 | |
112 @type bits: C{int} | |
113 @rtype: C{tuple} | |
114 """ | |
115 primesKeys = self.primes.keys() | |
116 primesKeys.sort(lambda x, y: cmp(abs(x - bits), abs(y - bits))) | |
117 realBits = primesKeys[0] | |
118 return random.choice(self.primes[realBits]) | |
119 | |
120 def getService(self, transport, service): | |
121 """ | |
122 Return a class to use as a service for the given transport. | |
123 | |
124 @type transport: L{transport.SSHServerTransport} | |
125 @type service: C{str} | |
126 @rtype: subclass of L{service.SSHService} | |
127 """ | |
128 if service == 'ssh-userauth' or hasattr(transport, 'avatar'): | |
129 return self.services[service] | |
OLD | NEW |