| 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 |