Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
    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
Exemplo n.º 3
0
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
Exemplo n.º 4
0
    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
Exemplo n.º 5
0
    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)
Exemplo n.º 7
0
    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)
Exemplo n.º 8
0
    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)
Exemplo n.º 9
0
    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)
Exemplo n.º 10
0
    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)
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")],
        })
Exemplo n.º 12
0
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()])
Exemplo n.º 13
0
    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)
Exemplo n.º 14
0
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()])
Exemplo n.º 15
0
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")],
        })
Exemplo n.º 16
0
    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)