Пример #1
0
    def test_noRegeneration(self):
        """
        L{keys._getPersistentRSAKey} will not regenerate the key if the key
        already exists.
        """
        tempDir = FilePath(self.mktemp())
        keyFile = tempDir.child("mykey.pem")

        key = keys._getPersistentRSAKey(keyFile, keySize=512)
        self.assertEqual(key.size(), 512)
        self.assertTrue(keyFile.exists())
        keyContent = keyFile.getContent()

        # Set the key size to 1024 bits. Since it exists already, it will find
        # the 512 bit key, and not generate a 1024 bit key.
        key = keys._getPersistentRSAKey(keyFile, keySize=1024)
        self.assertEqual(key.size(), 512)
        self.assertEqual(keyFile.getContent(), keyContent)
Пример #2
0
    def test_noRegeneration(self):
        """
        L{keys._getPersistentRSAKey} will not regenerate the key if the key
        already exists.
        """
        tempDir = FilePath(self.mktemp())
        keyFile = tempDir.child("mykey.pem")

        key = keys._getPersistentRSAKey(keyFile, keySize=512)
        self.assertEqual(key.size(), 512)
        self.assertTrue(keyFile.exists())
        keyContent = keyFile.getContent()

        # Set the key size to 1024 bits. Since it exists already, it will find
        # the 512 bit key, and not generate a 1024 bit key.
        key = keys._getPersistentRSAKey(keyFile, keySize=1024)
        self.assertEqual(key.size(), 512)
        self.assertEqual(keyFile.getContent(), keyContent)
Пример #3
0
    def test_providedArguments(self):
        """
        L{keys._getPersistentRSAKey} will put the key in
        C{directory}/C{filename}, with the key length of C{keySize}.
        """
        tempDir = FilePath(self.mktemp())
        keyFile = tempDir.child("mykey.pem")

        key = keys._getPersistentRSAKey(keyFile, keySize=512)
        self.assertEqual(key.size(), 512)
        self.assertTrue(keyFile.exists())
Пример #4
0
    def test_keySizeZero(self):
        """
        If the key generated by L{keys.getPersistentRSAKey} is set to None
        the key size should then become 0.
        """
        tempDir = FilePath(self.mktemp())
        keyFile = tempDir.child("mykey.pem")

        key = keys._getPersistentRSAKey(keyFile, keySize=512)
        key._keyObject = None
        self.assertEqual( key.size(), 0)
Пример #5
0
    def test_providedArguments(self):
        """
        L{keys._getPersistentRSAKey} will put the key in
        C{directory}/C{filename}, with the key length of C{keySize}.
        """
        tempDir = FilePath(self.mktemp())
        keyFile = tempDir.child("mykey.pem")

        key = keys._getPersistentRSAKey(keyFile, keySize=512)
        self.assertEqual(key.size(), 512)
        self.assertTrue(keyFile.exists())
Пример #6
0
    def setUp(self):
        if not ssh:
            raise unittest.SkipTest(
                "cryptography requirements missing, can't run historic "
                "recvline tests over ssh")

        u, p = b'testuser', b'testpass'
        rlm = TerminalRealm()
        rlm.userFactory = TestUser
        rlm.chainedProtocolFactory = lambda: insultsServer

        checker = checkers.InMemoryUsernamePasswordDatabaseDontUse()
        checker.addUser(u, p)
        ptl = portal.Portal(rlm)
        ptl.registerChecker(checker)
        sshFactory = ConchFactory(ptl)

        sshKey = keys._getPersistentRSAKey(filepath.FilePath(self.mktemp()),
                                           keySize=512)
        sshFactory.publicKeys[b"ssh-rsa"] = sshKey
        sshFactory.privateKeys[b"ssh-rsa"] = sshKey

        sshFactory.serverProtocol = self.serverProtocol
        sshFactory.startFactory()

        recvlineServer = self.serverProtocol()
        insultsServer = insults.ServerProtocol(lambda: recvlineServer)
        sshServer = sshFactory.buildProtocol(None)
        clientTransport = LoopbackRelay(sshServer)

        recvlineClient = NotifyingExpectableBuffer()
        insultsClient = insults.ClientProtocol(lambda: recvlineClient)
        sshClient = TestTransport(lambda: insultsClient, (), {}, u, p,
                                  self.WIDTH, self.HEIGHT)
        serverTransport = LoopbackRelay(sshClient)

        sshClient.makeConnection(clientTransport)
        sshServer.makeConnection(serverTransport)

        self.recvlineClient = recvlineClient
        self.sshClient = sshClient
        self.sshServer = sshServer
        self.clientTransport = clientTransport
        self.serverTransport = serverTransport

        return recvlineClient.onConnection
Пример #7
0
    def setUp(self):
        if not ssh:
            raise unittest.SkipTest(
                "cryptography requirements missing, can't run historic "
                "recvline tests over ssh")

        u, p = b'testuser', b'testpass'
        rlm = TerminalRealm()
        rlm.userFactory = TestUser
        rlm.chainedProtocolFactory = lambda: insultsServer

        checker = checkers.InMemoryUsernamePasswordDatabaseDontUse()
        checker.addUser(u, p)
        ptl = portal.Portal(rlm)
        ptl.registerChecker(checker)
        sshFactory = ConchFactory(ptl)

        sshKey = keys._getPersistentRSAKey(filepath.FilePath(self.mktemp()),
                                           keySize=512)
        sshFactory.publicKeys[b"ssh-rsa"] = sshKey
        sshFactory.privateKeys[b"ssh-rsa"] = sshKey

        sshFactory.serverProtocol = self.serverProtocol
        sshFactory.startFactory()

        recvlineServer = self.serverProtocol()
        insultsServer = insults.ServerProtocol(lambda: recvlineServer)
        sshServer = sshFactory.buildProtocol(None)
        clientTransport = LoopbackRelay(sshServer)

        recvlineClient = NotifyingExpectableBuffer()
        insultsClient = insults.ClientProtocol(lambda: recvlineClient)
        sshClient = TestTransport(lambda: insultsClient, (), {}, u, p, self.WIDTH, self.HEIGHT)
        serverTransport = LoopbackRelay(sshClient)

        sshClient.makeConnection(clientTransport)
        sshServer.makeConnection(serverTransport)

        self.recvlineClient = recvlineClient
        self.sshClient = sshClient
        self.sshServer = sshServer
        self.clientTransport = clientTransport
        self.serverTransport = serverTransport

        return recvlineClient.onConnection
Пример #8
0
def conch_helper(endpoint,
                 proto=None,
                 namespace=dict(),
                 keyDir=None,
                 keySize=4096):
    """
    Return a L{SSHKeyDirectory} based SSH service with the given parameters.

    Authorized keys are read as per L{SSHKeyDirectory} with ``baseDir`` being
    ``keyDir/users``.

    @param endpoint: endpoint for the SSH service
    @param namespace: the manhole namespace
    @param keyDir: directory that holds server/server.key file and
        users directory, which is used as ``baseDir`` in L{SSHKeyDirectory}
    @see: L{SSHKeyDirectory}
    """
    if keyDir is None:
        from twisted.python._appdirs import getDataDirectory

        keyDir = getDataDirectory()

    keyDir = filepath.FilePath(keyDir)
    keyDir.child("server").makedirs(True)
    keyDir.child("users").makedirs(True)

    checker = SSHPublicKeyChecker(SSHKeyDirectory(keyDir.child("users")))

    if proto is None:
        sshRealm = manhole_ssh.TerminalRealm()
        sshRealm.chainedProtocolFactory = chainedProtocolFactory(namespace)
    else:
        sshRealm = SSHSimpleRealm(proto)
    sshPortal = portal.Portal(sshRealm, [checker])

    sshKeyPath = keyDir.child("server").child("server.key")
    sshKey = keys._getPersistentRSAKey(sshKeyPath, keySize)

    sshFactory = manhole_ssh.ConchFactory(sshPortal)
    sshFactory.publicKeys[b"ssh-rsa"] = sshKey
    sshFactory.privateKeys[b"ssh-rsa"] = sshKey

    sshService = strports.service(endpoint, sshFactory)
    return sshService
Пример #9
0
def makeService(options):
    """
    Create a manhole server service.

    @type options: C{dict}
    @param options: A mapping describing the configuration of
    the desired service.  Recognized key/value pairs are::

        "telnetPort": strports description of the address on which
                      to listen for telnet connections.  If None,
                      no telnet service will be started.

        "sshPort": strports description of the address on which to
                   listen for ssh connections.  If None, no ssh
                   service will be started.

        "namespace": dictionary containing desired initial locals
                     for manhole connections.  If None, an empty
                     dictionary will be used.

        "passwd": Name of a passwd(5)-format username/password file.

        "sshKeyDir": The folder that the SSH server key will be kept in.

        "sshKeyName": The filename of the key.

        "sshKeySize": The size of the key, in bits. Default is 4096.

    @rtype: L{twisted.application.service.IService}
    @return: A manhole service.
    """
    svc = service.MultiService()

    namespace = options['namespace']
    if namespace is None:
        namespace = {}

    checker = checkers.FilePasswordDB(options['passwd'])

    if options['telnetPort']:
        telnetRealm = _StupidRealm(telnet.TelnetBootstrapProtocol,
                                   insults.ServerProtocol,
                                   manhole.ColoredManhole, namespace)

        telnetPortal = portal.Portal(telnetRealm, [checker])

        telnetFactory = protocol.ServerFactory()
        telnetFactory.protocol = makeTelnetProtocol(telnetPortal)
        telnetService = strports.service(options['telnetPort'], telnetFactory)
        telnetService.setServiceParent(svc)

    if options['sshPort']:
        sshRealm = manhole_ssh.TerminalRealm()
        sshRealm.chainedProtocolFactory = chainedProtocolFactory(namespace)

        sshPortal = portal.Portal(sshRealm, [checker])
        sshFactory = manhole_ssh.ConchFactory(sshPortal)

        if options['sshKeyDir'] != "<USER DATA DIR>":
            keyDir = options['sshKeyDir']
        else:
            from twisted.python._appdirs import getDataDirectory
            keyDir = getDataDirectory()

        keyLocation = filepath.FilePath(keyDir).child(options['sshKeyName'])

        sshKey = keys._getPersistentRSAKey(keyLocation,
                                           int(options['sshKeySize']))
        sshFactory.publicKeys["ssh-rsa"] = sshKey
        sshFactory.privateKeys["ssh-rsa"] = sshKey

        sshService = strports.service(options['sshPort'], sshFactory)
        sshService.setServiceParent(svc)

    return svc
Пример #10
0
def makeService(options):
    """
    Create a manhole server service.

    @type options: C{dict}
    @param options: A mapping describing the configuration of
    the desired service.  Recognized key/value pairs are::

        "telnetPort": strports description of the address on which
                      to listen for telnet connections.  If None,
                      no telnet service will be started.

        "sshPort": strports description of the address on which to
                   listen for ssh connections.  If None, no ssh
                   service will be started.

        "namespace": dictionary containing desired initial locals
                     for manhole connections.  If None, an empty
                     dictionary will be used.

        "passwd": Name of a passwd(5)-format username/password file.

        "sshKeyDir": The folder that the SSH server key will be kept in.

        "sshKeyName": The filename of the key.

        "sshKeySize": The size of the key, in bits. Default is 4096.

    @rtype: L{twisted.application.service.IService}
    @return: A manhole service.
    """
    svc = service.MultiService()

    namespace = options['namespace']
    if namespace is None:
        namespace = {}

    checker = checkers.FilePasswordDB(options['passwd'])

    if options['telnetPort']:
        telnetRealm = _StupidRealm(telnet.TelnetBootstrapProtocol,
                                   insults.ServerProtocol,
                                   manhole.ColoredManhole,
                                   namespace)

        telnetPortal = portal.Portal(telnetRealm, [checker])

        telnetFactory = protocol.ServerFactory()
        telnetFactory.protocol = makeTelnetProtocol(telnetPortal)
        telnetService = strports.service(options['telnetPort'],
                                         telnetFactory)
        telnetService.setServiceParent(svc)

    if options['sshPort']:
        sshRealm = manhole_ssh.TerminalRealm()
        sshRealm.chainedProtocolFactory = chainedProtocolFactory(namespace)

        sshPortal = portal.Portal(sshRealm, [checker])
        sshFactory = manhole_ssh.ConchFactory(sshPortal)

        if options['sshKeyDir'] != "<USER DATA DIR>":
            keyDir = options['sshKeyDir']
        else:
            from twisted.python._appdirs import getDataDirectory
            keyDir = getDataDirectory()

        keyLocation = filepath.FilePath(keyDir).child(options['sshKeyName'])

        sshKey = keys._getPersistentRSAKey(keyLocation,
                                           int(options['sshKeySize']))
        sshFactory.publicKeys["ssh-rsa"] = sshKey
        sshFactory.privateKeys["ssh-rsa"] = sshKey

        sshService = strports.service(options['sshPort'], sshFactory)
        sshService.setServiceParent(svc)

    return svc
Пример #11
0
def getManholeFactory(namespace, user, secret, keydir=None):
    """
    Get an administrative manhole into the application.

    :param namespace: the namespace to show in the manhole
    :type namespace: dict
    :param user: the user to authenticate into the administrative shell.
    :type user: str
    :param secret: pass for this manhole
    :type secret: str
    """
    import string

    from twisted.cred import portal
    from twisted.conch import manhole, manhole_ssh
    from twisted.conch import recvline
    from twisted.conch.insults import insults
    from twisted.conch.ssh import keys
    from twisted.cred.checkers import (InMemoryUsernamePasswordDatabaseDontUse
                                       as MemoryDB)
    from twisted.python import filepath

    try:
        from IPython.core.completer import Completer
    except ImportError:
        from rlcompleter import Completer

    class EnhancedColoredManhole(manhole.ColoredManhole):
        """
        A nicer Manhole with some autocomplete support.

        See the patch in https://twistedmatrix.com/trac/ticket/6863
        Since you're reading this, it'd be good if *you* can help getting that
        patch into twisted :)
        """

        completion = True

        def handle_TAB(self):
            """
            If tab completion is available and enabled then perform some tab
            completion.
            """
            if not self.completion:
                recvline.HistoricRecvLine.handle_TAB(self)
                return
            # If we only have whitespace characters on this line we pass
            # through the tab
            if set(self.lineBuffer).issubset(string.whitespace):
                recvline.HistoricRecvLine.handle_TAB(self)
                return
            cp = Completer(namespace=self.namespace)
            cp.limit_to__all__ = False
            lineLeft, lineRight = self.currentLineBuffer()

            # Extract all the matches
            matches = []
            n = 0
            while True:
                match = cp.complete(lineLeft, n)
                if match is None:
                    break
                n += 1
                matches.append(match)

            if not matches:
                return

            if len(matches) == 1:
                # Found the match so replace the line. This is apparently how
                # we replace a line
                self.handle_HOME()
                self.terminal.eraseToLineEnd()

                self.lineBuffer = []
                self._deliverBuffer(matches[0] + lineRight)
            else:
                # Must have more than one match, display them
                matches.sort()
                self.terminal.write("\n")
                self.terminal.write("   ".join(matches))
                self.terminal.write("\n\n")
                self.drawInputLine()

        def keystrokeReceived(self, keyID, modifier):
            """
            Act upon any keystroke received.
            """
            self.keyHandlers.update({'\b': self.handle_BACKSPACE})
            m = self.keyHandlers.get(keyID)
            if m is not None:
                m()
            elif keyID in string.printable:
                self.characterReceived(keyID, False)

    class chainedProtocolFactory:
        def __init__(self, namespace):
            self.namespace = namespace

        def __call__(self):
            return insults.ServerProtocol(EnhancedColoredManhole,
                                          self.namespace)

    sshRealm = manhole_ssh.TerminalRealm()
    sshRealm.chainedProtocolFactory = chainedProtocolFactory(namespace)

    checker = MemoryDB(**{user: secret})
    sshPortal = portal.Portal(sshRealm, [checker])
    sshFactory = manhole_ssh.ConchFactory(sshPortal)

    if not keydir:
        from twisted.python._appdirs import getDataDirectory
        keydir = getDataDirectory()

    keyLocation = filepath.FilePath(keydir).child('id_rsa')
    sshKey = keys._getPersistentRSAKey(keyLocation, 4096)
    sshFactory.publicKeys[b"ssh-rsa"] = sshKey
    sshFactory.privateKeys[b"ssh-rsa"] = sshKey
    return sshFactory