def setUp(self): self.factory = OpenSSHFactory() self.keysDir = FilePath(self.mktemp()) self.keysDir.makedirs() self.factory.dataRoot = self.keysDir.path self.moduliDir = FilePath(self.mktemp()) self.moduliDir.makedirs() self.factory.moduliRoot = self.moduliDir.path self.keysDir.child("ssh_host_foo").setContent(b"foo") self.keysDir.child("bar_key").setContent(b"foo") self.keysDir.child("ssh_host_one_key").setContent( keydata.privateRSA_openssh) self.keysDir.child("ssh_host_two_key").setContent( keydata.privateDSA_openssh) self.keysDir.child("ssh_host_three_key").setContent( b"not a key content") self.keysDir.child("ssh_host_one_key.pub").setContent( keydata.publicRSA_openssh) self.moduliDir.child("moduli").setContent(b""" # $OpenBSD: moduli,v 1.xx 2016/07/26 12:34:56 jhacker Exp $ # Time Type Tests Tries Size Generator Modulus 20030501000000 2 6 100 2047 2 FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF """) self.mockos = MockOS() self.patch(os, "seteuid", self.mockos.seteuid) self.patch(os, "setegid", self.mockos.setegid)
def __init__(self, base_path): """ :param FilePath base_path: The path beneath which all of the temporary SSH server-related files will be created. An ``ssh`` directory will be created as a child of this directory to hold the key pair that is generated. An ``sshd`` directory will also be created here to hold the generated host key. A ``home`` directory is also created here and used as the home directory for shell logins to the server. """ self.home = base_path.child(b"home") self.home.makedirs() ssh_path = base_path.child(b"ssh") ssh_path.makedirs() self.key_path = ssh_path.child(b"key") key = generate_ssh_key(self.key_path) sshd_path = base_path.child(b"sshd") sshd_path.makedirs() self.host_key_path = sshd_path.child(b"ssh_host_key") generate_ssh_key(self.host_key_path) factory = OpenSSHFactory() realm = _UnixSSHRealm(self.home) checker = _InMemoryPublicKeyChecker(public_key=key.public()) factory.portal = Portal(realm, [checker]) factory.dataRoot = sshd_path.path factory.moduliRoot = b"/etc/ssh" self._port = reactor.listenTCP(0, factory, interface=b"127.0.0.1") self.ip = IPAddress(self._port.getHost().host) self.port = self._port.getHost().port
def createManholeListener(): sshRealm = TerminalRealm() sshRealm.chainedProtocolFactory.protocolFactory = lambda _: Manhole( namespace) if settings.MANHOLE_PUBLIC_KEY == 'None': credChecker = checkers.InMemoryUsernamePasswordDatabaseDontUse() credChecker.addUser(settings.MANHOLE_USER.encode('utf-8'), ''.encode('utf-8')) else: userKeys = { settings.MANHOLE_USER.encode('utf-8'): settings.MANHOLE_PUBLIC_KEY.encode('utf-8'), } credChecker = PublicKeyChecker(userKeys) sshPortal = portal.Portal(sshRealm) sshPortal.registerChecker(credChecker) sessionFactory = ConchFactory(sshPortal) # set ssh host keys if settings.MANHOLE_HOST_KEY_DIR == "": raise CarbonConfigException("MANHOLE_HOST_KEY_DIR not defined") openSSHFactory = OpenSSHFactory() openSSHFactory.dataRoot = settings.MANHOLE_HOST_KEY_DIR sessionFactory.publicKeys = openSSHFactory.getPublicKeys() sessionFactory.privateKeys = openSSHFactory.getPrivateKeys() return sessionFactory
def __init__(self, base_path): """ :param FilePath base_path: The path beneath which all of the temporary SSH server-related files will be created. An ``ssh`` directory will be created as a child of this directory to hold the key pair that is generated. An ``sshd`` directory will also be created here to hold the generated host key. A ``home`` directory is also created here and used as the home directory for shell logins to the server. """ self.home = base_path.child(b"home") self.home.makedirs() ssh_path = base_path.child(b"ssh") ssh_path.makedirs() self.key_path = ssh_path.child(b"key") check_call( [ b"ssh-keygen", # Specify the path where the generated key is written. b"-f", self.key_path.path, # Specify an empty passphrase. b"-N", b"", # Generate as little output as possible. b"-q", ] ) key = Key.fromFile(self.key_path.path) sshd_path = base_path.child(b"sshd") sshd_path.makedirs() self.host_key_path = sshd_path.child(b"ssh_host_key") check_call( [ b"ssh-keygen", # See above for option explanations. b"-f", self.host_key_path.path, b"-N", b"", b"-q", ] ) factory = OpenSSHFactory() realm = _UnixSSHRealm(self.home) checker = _InMemoryPublicKeyChecker(public_key=key.public()) factory.portal = Portal(realm, [checker]) factory.dataRoot = sshd_path.path factory.moduliRoot = b"/etc/ssh" self._port = reactor.listenTCP(0, factory, interface=b"127.0.0.1") self.ip = IPAddress(self._port.getHost().host) self.port = self._port.getHost().port
def __init__(self, base_path): """ :param FilePath base_path: The path beneath which all of the temporary SSH server-related files will be created. An ``ssh`` directory will be created as a child of this directory to hold the key pair that is generated. An ``sshd`` directory will also be created here to hold the generated host key. A ``home`` directory is also created here and used as the home directory for shell logins to the server. """ self.home = base_path.child(b"home") self.home.makedirs() ssh_path = base_path.child(b"ssh") ssh_path.makedirs() self.key_path = ssh_path.child(b"key") check_call([ b"ssh-keygen", # Specify the path where the generated key is written. b"-f", self.key_path.path, # Specify an empty passphrase. b"-N", b"", # Generate as little output as possible. b"-q" ]) key = Key.fromFile(self.key_path.path) sshd_path = base_path.child(b"sshd") sshd_path.makedirs() self.host_key_path = sshd_path.child(b"ssh_host_key") check_call([ b"ssh-keygen", # See above for option explanations. b"-f", self.host_key_path.path, b"-N", b"", b"-q" ]) factory = OpenSSHFactory() realm = UnixSSHRealm(self.home) checker = _InMemoryPublicKeyChecker(public_key=key.public()) factory.portal = Portal(realm, [checker]) factory.dataRoot = sshd_path.path factory.moduliRoot = b"/etc/ssh" self._port = reactor.listenTCP(0, factory, interface=b"127.0.0.1") self.ip = IPAddress(self._port.getHost().host) self.port = self._port.getHost().port
def setUp(self): self.factory = OpenSSHFactory() self.keysDir = FilePath(self.mktemp()) self.keysDir.makedirs() self.factory.dataRoot = self.keysDir.path self.moduliDir = FilePath(self.mktemp()) self.moduliDir.makedirs() self.factory.moduliRoot = self.moduliDir.path self.keysDir.child("ssh_host_foo").setContent(b"foo") self.keysDir.child("bar_key").setContent(b"foo") self.keysDir.child("ssh_host_one_key").setContent( keydata.privateRSA_openssh) self.keysDir.child("ssh_host_two_key").setContent( keydata.privateDSA_openssh) self.keysDir.child("ssh_host_three_key").setContent( b"not a key content") self.keysDir.child("ssh_host_one_key.pub").setContent( keydata.publicRSA_openssh) self.moduliDir.child("moduli").setContent(b""" # $OpenBSD: moduli,v 1.xx 2016/07/26 12:34:56 jhacker Exp $ # Time Type Tests Tries Size Generator Modulus 20030501000000 2 6 100 2047 2 FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF 19981111000000 2 6 100 1023 2 FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF """) self.mockos = MockOS() self.patch(os, "seteuid", self.mockos.seteuid) self.patch(os, "setegid", self.mockos.setegid)
def makeService(self, options): """ Construct a TCPServer from a factory defined in myproject. """ _portal = portal.Portal( essftp.EssFTPRealm(essftp.FilePath(options['root']).path), options.get('credCheckers', [SSHPublicKeyChecker(UNIXAuthorizedKeysFiles())])) if options['keyDirectory']: factory = OpenSSHFactory() factory.portal = _portal factory.dataRoot = options['keyDirectory'] factory.moduliRoot = options['moduli'] else: factory = ConchFactory(_portal) return internet.TCPServer(int(options["port"]), factory)
def setUp(self): self.factory = OpenSSHFactory() self.keysDir = FilePath(self.mktemp()) self.keysDir.makedirs() self.factory.dataRoot = self.keysDir.path self.keysDir.child("ssh_host_foo").setContent("foo") self.keysDir.child("bar_key").setContent("foo") self.keysDir.child("ssh_host_one_key").setContent( keydata.privateRSA_openssh) self.keysDir.child("ssh_host_two_key").setContent( keydata.privateDSA_openssh) self.keysDir.child("ssh_host_three_key").setContent( "not a key content") self.keysDir.child("ssh_host_one_key.pub").setContent( keydata.publicRSA_openssh) self.mockos = MockOS() self.patch(os, "seteuid", self.mockos.seteuid) self.patch(os, "setegid", self.mockos.setegid)
def setUp(self): self.factory = OpenSSHFactory() self.keysDir = FilePath(self.mktemp()) self.keysDir.makedirs() self.factory.dataRoot = self.keysDir.path self.keysDir.child("ssh_host_foo").setContent("foo") self.keysDir.child("bar_key").setContent("foo") self.keysDir.child("ssh_host_one_key").setContent(keydata.privateRSA_openssh) self.keysDir.child("ssh_host_two_key").setContent(keydata.privateDSA_openssh) self.keysDir.child("ssh_host_three_key").setContent("not a key content") self.keysDir.child("ssh_host_one_key.pub").setContent(keydata.publicRSA_openssh) self.mockos = MockOS() self.patch(os, "seteuid", self.mockos.seteuid) self.patch(os, "setegid", self.mockos.setegid)
class OpenSSHFactoryTests(TestCase): """ Tests for L{OpenSSHFactory}. """ if getattr(os, "geteuid", None) is None: skip = "geteuid/seteuid not available" elif OpenSSHFactory is None: skip = "Cannot run without cryptography or PyASN1" def setUp(self): self.factory = OpenSSHFactory() self.keysDir = FilePath(self.mktemp()) self.keysDir.makedirs() self.factory.dataRoot = self.keysDir.path self.moduliDir = FilePath(self.mktemp()) self.moduliDir.makedirs() self.factory.moduliRoot = self.moduliDir.path self.keysDir.child("ssh_host_foo").setContent(b"foo") self.keysDir.child("bar_key").setContent(b"foo") self.keysDir.child("ssh_host_one_key").setContent( keydata.privateRSA_openssh) self.keysDir.child("ssh_host_two_key").setContent( keydata.privateDSA_openssh) self.keysDir.child("ssh_host_three_key").setContent( b"not a key content") self.keysDir.child("ssh_host_one_key.pub").setContent( keydata.publicRSA_openssh) self.moduliDir.child("moduli").setContent(b""" # $OpenBSD: moduli,v 1.xx 2016/07/26 12:34:56 jhacker Exp $ # Time Type Tests Tries Size Generator Modulus 20030501000000 2 6 100 2047 2 FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF 19981111000000 2 6 100 1023 2 FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF """) self.mockos = MockOS() self.patch(os, "seteuid", self.mockos.seteuid) self.patch(os, "setegid", self.mockos.setegid) def test_getPublicKeys(self): """ L{OpenSSHFactory.getPublicKeys} should return the available public keys in the data directory """ keys = self.factory.getPublicKeys() self.assertEqual(len(keys), 1) keyTypes = keys.keys() self.assertEqual(list(keyTypes), [b'ssh-rsa']) def test_getPrivateKeys(self): """ Will return the available private keys in the data directory, ignoring key files which failed to be loaded. """ keys = self.factory.getPrivateKeys() self.assertEqual(len(keys), 2) keyTypes = keys.keys() self.assertEqual(set(keyTypes), set([b'ssh-rsa', b'ssh-dss'])) self.assertEqual(self.mockos.seteuidCalls, []) self.assertEqual(self.mockos.setegidCalls, []) def test_getPrivateKeysAsRoot(self): """ L{OpenSSHFactory.getPrivateKeys} should switch to root if the keys aren't readable by the current user. """ keyFile = self.keysDir.child("ssh_host_two_key") # Fake permission error by changing the mode keyFile.chmod(0000) self.addCleanup(keyFile.chmod, 0o777) # And restore the right mode when seteuid is called savedSeteuid = os.seteuid def seteuid(euid): keyFile.chmod(0o777) return savedSeteuid(euid) self.patch(os, "seteuid", seteuid) keys = self.factory.getPrivateKeys() self.assertEqual(len(keys), 2) keyTypes = keys.keys() self.assertEqual(set(keyTypes), set([b'ssh-rsa', b'ssh-dss'])) self.assertEqual(self.mockos.seteuidCalls, [0, os.geteuid()]) self.assertEqual(self.mockos.setegidCalls, [0, os.getegid()]) def test_getPrimes(self): """ L{OpenSSHFactory.getPrimes} should return the available primes in the moduli directory. """ primes = self.factory.getPrimes() self.assertEqual(primes, { 1024: [getDHGeneratorAndPrime(b"diffie-hellman-group1-sha1")], 2048: [getDHGeneratorAndPrime(b"diffie-hellman-group14-sha1")], })
class OpenSSHFactoryTests(TestCase): """ Tests for L{OpenSSHFactory}. """ if getattr(os, "geteuid", None) is None: skip = "geteuid/seteuid not available" elif OpenSSHFactory is None: skip = "Cannot run without cryptography or PyASN1" def setUp(self): self.factory = OpenSSHFactory() self.keysDir = FilePath(self.mktemp()) self.keysDir.makedirs() self.factory.dataRoot = self.keysDir.path self.keysDir.child("ssh_host_foo").setContent("foo") self.keysDir.child("bar_key").setContent("foo") self.keysDir.child("ssh_host_one_key").setContent( keydata.privateRSA_openssh) self.keysDir.child("ssh_host_two_key").setContent( keydata.privateDSA_openssh) self.keysDir.child("ssh_host_three_key").setContent( "not a key content") self.keysDir.child("ssh_host_one_key.pub").setContent( keydata.publicRSA_openssh) self.mockos = MockOS() self.patch(os, "seteuid", self.mockos.seteuid) self.patch(os, "setegid", self.mockos.setegid) def test_getPublicKeys(self): """ L{OpenSSHFactory.getPublicKeys} should return the available public keys in the data directory """ keys = self.factory.getPublicKeys() self.assertEqual(len(keys), 1) keyTypes = keys.keys() self.assertEqual(keyTypes, ['ssh-rsa']) def test_getPrivateKeys(self): """ Will return the available private keys in the data directory, ignoring key files which failed to be loaded. """ keys = self.factory.getPrivateKeys() self.assertEqual(len(keys), 2) keyTypes = keys.keys() self.assertEqual(set(keyTypes), set(['ssh-rsa', 'ssh-dss'])) self.assertEqual(self.mockos.seteuidCalls, []) self.assertEqual(self.mockos.setegidCalls, []) def test_getPrivateKeysAsRoot(self): """ L{OpenSSHFactory.getPrivateKeys} should switch to root if the keys aren't readable by the current user. """ keyFile = self.keysDir.child("ssh_host_two_key") # Fake permission error by changing the mode keyFile.chmod(0000) self.addCleanup(keyFile.chmod, 0777) # And restore the right mode when seteuid is called savedSeteuid = os.seteuid def seteuid(euid): keyFile.chmod(0777) return savedSeteuid(euid) self.patch(os, "seteuid", seteuid) keys = self.factory.getPrivateKeys() self.assertEqual(len(keys), 2) keyTypes = keys.keys() self.assertEqual(set(keyTypes), set(['ssh-rsa', 'ssh-dss'])) self.assertEqual(self.mockos.seteuidCalls, [0, os.geteuid()]) self.assertEqual(self.mockos.setegidCalls, [0, os.getegid()])
def __init__(self, port, checker, ssh_hostkey_dir=None): """ @type port: string or int @param port: what port should the Manhole listen on? This is a strports specification string, like 'tcp:12345' or 'tcp:12345:interface=127.0.0.1'. Bare integers are treated as a simple tcp port. @type checker: an object providing the L{twisted.cred.checkers.ICredentialsChecker} interface @param checker: if provided, this checker is used to authenticate the client instead of using the username/password scheme. You must either provide a username/password or a Checker. Some useful values are:: import twisted.cred.checkers as credc import twisted.conch.checkers as conchc c = credc.AllowAnonymousAccess # completely open c = credc.FilePasswordDB(passwd_filename) # file of name:passwd c = conchc.UNIXPasswordDatabase # getpwnam() (probably /etc/passwd) @type ssh_hostkey_dir: str @param ssh_hostkey_dir: directory which contains ssh host keys for this server """ # unfortunately, these don't work unless we're running as root # c = credc.PluggableAuthenticationModulesChecker: PAM # c = conchc.SSHPublicKeyDatabase() # ~/.ssh/authorized_keys # and I can't get UNIXPasswordDatabase to work service.AsyncMultiService.__init__(self) if isinstance(port, int): port = "tcp:%d" % port self.port = port # for comparison later self.checker = checker # to maybe compare later def makeNamespace(): master = self.master namespace = { 'master': master, 'status': master.getStatus(), 'show': show, } return namespace def makeProtocol(): namespace = makeNamespace() p = insults.ServerProtocol(manhole.ColoredManhole, namespace) return p self.ssh_hostkey_dir = ssh_hostkey_dir if self.ssh_hostkey_dir: self.using_ssh = True if not self.ssh_hostkey_dir: raise ValueError("Most specify a value for ssh_hostkey_dir") r = manhole_ssh.TerminalRealm() r.chainedProtocolFactory = makeProtocol p = portal.Portal(r, [self.checker]) f = manhole_ssh.ConchFactory(p) openSSHFactory = OpenSSHFactory() openSSHFactory.dataRoot = self.ssh_hostkey_dir openSSHFactory.dataModuliRoot = self.ssh_hostkey_dir f.publicKeys = openSSHFactory.getPublicKeys() f.privateKeys = openSSHFactory.getPrivateKeys() else: self.using_ssh = False r = _TelnetRealm(makeNamespace) p = portal.Portal(r, [self.checker]) f = protocol.ServerFactory() f.protocol = makeTelnetProtocol(p) s = strports.service(self.port, f) s.setServiceParent(self)
class OpenSSHFactoryTests(TestCase): """ Tests for L{OpenSSHFactory}. """ if getattr(os, "geteuid", None) is None: skip = "geteuid/seteuid not available" elif OpenSSHFactory is None: skip = "Cannot run without PyCrypto or PyASN1" def setUp(self): self.factory = OpenSSHFactory() self.keysDir = FilePath(self.mktemp()) self.keysDir.makedirs() self.factory.dataRoot = self.keysDir.path self.keysDir.child("ssh_host_foo").setContent("foo") self.keysDir.child("bar_key").setContent("foo") self.keysDir.child("ssh_host_one_key").setContent( keydata.privateRSA_openssh) self.keysDir.child("ssh_host_two_key").setContent( keydata.privateDSA_openssh) self.keysDir.child("ssh_host_three_key").setContent( "not a key content") self.keysDir.child("ssh_host_one_key.pub").setContent( keydata.publicRSA_openssh) self.mockos = MockOS() self.patch(os, "seteuid", self.mockos.seteuid) self.patch(os, "setegid", self.mockos.setegid) def test_getPublicKeys(self): """ L{OpenSSHFactory.getPublicKeys} should return the available public keys in the data directory """ keys = self.factory.getPublicKeys() self.assertEquals(len(keys), 1) keyTypes = keys.keys() self.assertEqual(keyTypes, ['ssh-rsa']) def test_getPrivateKeys(self): """ L{OpenSSHFactory.getPrivateKeys} should return the available private keys in the data directory. """ keys = self.factory.getPrivateKeys() self.assertEquals(len(keys), 2) keyTypes = keys.keys() self.assertEqual(set(keyTypes), set(['ssh-rsa', 'ssh-dss'])) self.assertEquals(self.mockos.seteuidCalls, []) self.assertEquals(self.mockos.setegidCalls, []) def test_getPrivateKeysAsRoot(self): """ L{OpenSSHFactory.getPrivateKeys} should switch to root if the keys aren't readable by the current user. """ keyFile = self.keysDir.child("ssh_host_two_key") # Fake permission error by changing the mode keyFile.chmod(0000) self.addCleanup(keyFile.chmod, 0777) # And restore the right mode when seteuid is called savedSeteuid = os.seteuid def seteuid(euid): keyFile.chmod(0777) return savedSeteuid(euid) self.patch(os, "seteuid", seteuid) keys = self.factory.getPrivateKeys() self.assertEquals(len(keys), 2) keyTypes = keys.keys() self.assertEqual(set(keyTypes), set(['ssh-rsa', 'ssh-dss'])) self.assertEquals(self.mockos.seteuidCalls, [0, os.geteuid()]) self.assertEquals(self.mockos.setegidCalls, [0, os.getegid()])
class OpenSSHFactoryTests(TestCase): """ Tests for L{OpenSSHFactory}. """ def setUp(self): self.factory = OpenSSHFactory() self.keysDir = FilePath(self.mktemp()) self.keysDir.makedirs() self.factory.dataRoot = self.keysDir.path self.moduliDir = FilePath(self.mktemp()) self.moduliDir.makedirs() self.factory.moduliRoot = self.moduliDir.path self.keysDir.child("ssh_host_foo").setContent(b"foo") self.keysDir.child("bar_key").setContent(b"foo") self.keysDir.child("ssh_host_one_key").setContent( keydata.privateRSA_openssh) self.keysDir.child("ssh_host_two_key").setContent( keydata.privateDSA_openssh) self.keysDir.child("ssh_host_three_key").setContent( b"not a key content") self.keysDir.child("ssh_host_one_key.pub").setContent( keydata.publicRSA_openssh) self.moduliDir.child("moduli").setContent(b""" # $OpenBSD: moduli,v 1.xx 2016/07/26 12:34:56 jhacker Exp $ # Time Type Tests Tries Size Generator Modulus 20030501000000 2 6 100 2047 2 FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF """) self.mockos = MockOS() self.patch(os, "seteuid", self.mockos.seteuid) self.patch(os, "setegid", self.mockos.setegid) def test_getPublicKeys(self): """ L{OpenSSHFactory.getPublicKeys} should return the available public keys in the data directory """ keys = self.factory.getPublicKeys() self.assertEqual(len(keys), 1) keyTypes = keys.keys() self.assertEqual(list(keyTypes), [b'ssh-rsa']) def test_getPrivateKeys(self): """ Will return the available private keys in the data directory, ignoring key files which failed to be loaded. """ keys = self.factory.getPrivateKeys() self.assertEqual(len(keys), 2) keyTypes = keys.keys() self.assertEqual(set(keyTypes), set([b'ssh-rsa', b'ssh-dss'])) self.assertEqual(self.mockos.seteuidCalls, []) self.assertEqual(self.mockos.setegidCalls, []) def test_getPrivateKeysAsRoot(self): """ L{OpenSSHFactory.getPrivateKeys} should switch to root if the keys aren't readable by the current user. """ keyFile = self.keysDir.child("ssh_host_two_key") # Fake permission error by changing the mode keyFile.chmod(0000) self.addCleanup(keyFile.chmod, 0o777) # And restore the right mode when seteuid is called savedSeteuid = os.seteuid def seteuid(euid): keyFile.chmod(0o777) return savedSeteuid(euid) self.patch(os, "seteuid", seteuid) keys = self.factory.getPrivateKeys() self.assertEqual(len(keys), 2) keyTypes = keys.keys() self.assertEqual(set(keyTypes), set([b'ssh-rsa', b'ssh-dss'])) self.assertEqual(self.mockos.seteuidCalls, [0, os.geteuid()]) self.assertEqual(self.mockos.setegidCalls, [0, os.getegid()]) def test_getPrimes(self): """ L{OpenSSHFactory.getPrimes} should return the available primes in the moduli directory. """ primes = self.factory.getPrimes() self.assertEqual(primes, { 2048: [getDHGeneratorAndPrime(b"diffie-hellman-group14-sha1")], })
def __init__(self, port, checker, ssh_hostkey_dir=None): """ @type port: string or int @param port: what port should the Manhole listen on? This is a strports specification string, like 'tcp:12345' or 'tcp:12345:interface=127.0.0.1'. Bare integers are treated as a simple tcp port. @type checker: an object providing the L{twisted.cred.checkers.ICredentialsChecker} interface @param checker: if provided, this checker is used to authenticate the client instead of using the username/password scheme. You must either provide a username/password or a Checker. Some useful values are:: import twisted.cred.checkers as credc import twisted.conch.checkers as conchc c = credc.AllowAnonymousAccess # completely open c = credc.FilePasswordDB(passwd_filename) # file of name:passwd c = conchc.UNIXPasswordDatabase # getpwnam() (probably /etc/passwd) @type ssh_hostkey_dir: str @param ssh_hostkey_dir: directory which contains ssh host keys for this server """ # unfortunately, these don't work unless we're running as root # c = credc.PluggableAuthenticationModulesChecker: PAM # c = conchc.SSHPublicKeyDatabase() # ~/.ssh/authorized_keys # and I can't get UNIXPasswordDatabase to work super().__init__() if isinstance(port, int): port = "tcp:%d" % port self.port = port # for comparison later self.checker = checker # to maybe compare later def makeNamespace(): master = self.master namespace = { 'master': master, 'status': master.getStatus(), 'show': show, } return namespace def makeProtocol(): namespace = makeNamespace() p = insults.ServerProtocol(manhole.ColoredManhole, namespace) return p self.ssh_hostkey_dir = ssh_hostkey_dir if self.ssh_hostkey_dir: self.using_ssh = True if not self.ssh_hostkey_dir: raise ValueError("Most specify a value for ssh_hostkey_dir") r = manhole_ssh.TerminalRealm() r.chainedProtocolFactory = makeProtocol p = portal.Portal(r, [self.checker]) f = manhole_ssh.ConchFactory(p) openSSHFactory = OpenSSHFactory() openSSHFactory.dataRoot = self.ssh_hostkey_dir openSSHFactory.dataModuliRoot = self.ssh_hostkey_dir f.publicKeys = openSSHFactory.getPublicKeys() f.privateKeys = openSSHFactory.getPrivateKeys() else: self.using_ssh = False r = _TelnetRealm(makeNamespace) p = portal.Portal(r, [self.checker]) f = protocol.ServerFactory() f.protocol = makeTelnetProtocol(p) s = strports.service(self.port, f) s.setServiceParent(self)