Ejemplo n.º 1
0
    def setUp(self):
        self.checker = SSHPublicKeyDatabase()
        self.sshDir = FilePath(self.mktemp())
        self.sshDir.makedirs()

        self.key1 = base64.encodestring("foobar")
        self.key2 = base64.encodestring("eggspam")
        self.content = "t1 %s foo\nt2 %s egg\n" % (self.key1, self.key2)

        self.mockos = MockOS()
        self.mockos.path = self.sshDir.path
        self.patch(os.path, "expanduser", self.mockos.expanduser)
        self.patch(pwd, "getpwnam", self.mockos.getpwnam)
        self.patch(os, "seteuid", self.mockos.seteuid)
        self.patch(os, "setegid", self.mockos.setegid)
Ejemplo n.º 2
0
def setupManhole(application, config):
    """Setup an SSH manhole for the API service.

    The manhole port is taken from the C{manhole-port} option in the config
    file. If this option is not provided the api port plus 100 is used.

    @param application: The fluidinfo API L{Application} object.
    @param config: The configuration object.
    """
    servicePort = config.getint('service', 'port')
    if config.has_option('service', 'manhole-port'):
        manholePort = config.getint('service', 'manhole-port')
    else:
        manholePort = servicePort + 100

    def getManhole(_):
        manhole = Manhole(globals())
        ps1 = 'fluidinfo-api [%d] > ' % servicePort
        ps2 = '... '.rjust(len(ps1))
        manhole.ps = (ps1, ps2)
        return manhole

    realm = TerminalRealm()
    realm.chainedProtocolFactory.protocolFactory = getManhole
    portal = Portal(realm)
    portal.registerChecker(SSHPublicKeyDatabase())
    factory = ConchFactory(portal)
    manholeService = TCPServer(manholePort, factory, interface='127.0.0.1')
    manholeService.setServiceParent(application)
Ejemplo n.º 3
0
 def _cbRequestAvatarId(self, validKey, credentials):
     returnMe = SSHPublicKeyDatabase._cbRequestAvatarId(
         self, validKey[0], credentials)
     if returnMe == validKey[1].username:
         return validKey[1]
     else:
         return returnMe
Ejemplo n.º 4
0
 def generateChecker(self, argstring=''):
     """
     This checker factory ignores the argument string. Everything
     needed to authenticate users is pulled out of the public keys
     listed in user .ssh/ directories.
     """
     return SSHPublicKeyDatabase()
Ejemplo n.º 5
0
 def checkKey(self, credentials):
     """Override the default behavior so that we
     only allow the owner user."""
     if not credentials.username in self.allowed_users:
         return False
     else:
         return SSHPublicKeyDatabase.checkKey(self, credentials)
Ejemplo n.º 6
0
def getShellFactory(interpreterType, **namespace):
    realm = ShellTerminalRealm(namespace, CommandAPI)
    sshPortal = portal.Portal(realm)
    factory = manhole_ssh.ConchFactory(sshPortal)
    factory.privateKeys = {'ssh-rsa': dreamssh_util.getPrivKey()}
    factory.publicKeys = {'ssh-rsa': dreamssh_util.getPubKey()}
    factory.portal.registerChecker(SSHPublicKeyDatabase())
    return factory
Ejemplo n.º 7
0
 def getAuthorizedKeysFiles(self, credentials):
     if config.ssh.usesystemkeys:
         return SSHPublicKeyDatabase.getAuthorizedKeysFiles(
             self, credentials)
     return [
         FilePath(
             config.ssh.userauthkeys.replace("{{USER}}",
                                             credentials.username))
     ]
Ejemplo n.º 8
0
def getGameShellFactory(**namespace):
    game = None
    sshRealm = gameshell.TerminalRealm(namespace, game)
    sshPortal = portal.Portal(sshRealm)
    factory = manhole_ssh.ConchFactory(sshPortal)
    factory.privateKeys = {'ssh-rsa': util.getPrivKey()}
    factory.publicKeys = {'ssh-rsa': util.getPubKey()}
    factory.portal.registerChecker(SSHPublicKeyDatabase())
    return factory
Ejemplo n.º 9
0
    def setUp(self):
        self.checker = SSHPublicKeyDatabase()
        self.key1 = base64.encodestring("foobar")
        self.key2 = base64.encodestring("eggspam")
        self.content = "t1 %s foo\nt2 %s egg\n" % (self.key1, self.key2)

        self.mockos = MockOS()
        self.mockos.path = FilePath(self.mktemp())
        self.mockos.path.makedirs()
        self.sshDir = self.mockos.path.child('.ssh')
        self.sshDir.makedirs()

        userdb = UserDatabase()
        userdb.addUser('user', 'password', 1, 2, 'first last',
                self.mockos.path.path, '/bin/shell')

        self.patch(pwd, "getpwnam", userdb.getpwnam)
        self.patch(os, "seteuid", self.mockos.seteuid)
        self.patch(os, "setegid", self.mockos.setegid)
Ejemplo n.º 10
0
 def test_registerChecker(self):
     """
     L{SSHProcotolChecker.registerChecker} should add the given checker to
     the list of registered checkers.
     """
     checker = SSHProtocolChecker()
     self.assertEquals(checker.credentialInterfaces, [])
     checker.registerChecker(SSHPublicKeyDatabase(), )
     self.assertEquals(checker.credentialInterfaces, [ISSHPrivateKey])
     self.assertIsInstance(checker.checkers[ISSHPrivateKey],
                           SSHPublicKeyDatabase)
Ejemplo n.º 11
0
 def test_registerCheckerWithInterface(self):
     """
     If a apecific interface is passed into
     L{SSHProtocolChecker.registerChecker}, that interface should be
     registered instead of what the checker specifies in
     credentialIntefaces.
     """
     checker = SSHProtocolChecker()
     self.assertEquals(checker.credentialInterfaces, [])
     checker.registerChecker(SSHPublicKeyDatabase(), IUsernamePassword)
     self.assertEquals(checker.credentialInterfaces, [IUsernamePassword])
     self.assertIsInstance(checker.checkers[IUsernamePassword],
                           SSHPublicKeyDatabase)
Ejemplo n.º 12
0
    def setUp(self):
        self.checker = SSHPublicKeyDatabase()
        self.sshDir = FilePath(self.mktemp())
        self.sshDir.makedirs()

        self.key1 = base64.encodestring("foobar")
        self.key2 = base64.encodestring("eggspam")
        self.content = "t1 %s foo\nt2 %s egg\n" % (self.key1, self.key2)

        self.mockos = MockOS()
        self.mockos.path = self.sshDir.path
        self.patch(os.path, "expanduser", self.mockos.expanduser)
        self.patch(pwd, "getpwnam", self.mockos.getpwnam)
        self.patch(os, "seteuid", self.mockos.seteuid)
        self.patch(os, "setegid", self.mockos.setegid)
Ejemplo n.º 13
0
 def checkKey(self, credentials):
     if config.ssh.usesystemkeys:
         return SSHPublicKeyDatabase.checkKey(self, credentials)
     for filePath in self.getAuthorizedKeysFiles(credentials):
         if not filePath.exists():
             continue
         lines = filePath.open()
         for line in lines:
             lineData = line.split()
             if len(lineData) < 2:
                 continue
             try:
                 if base64.decodestring(lineData[1]) == credentials.blob:
                     return True
             except binascii.Error:
                 continue
     return False
Ejemplo n.º 14
0
 def checkKey(self, credentials):
     if config.ssh.usesystemkeys:
         return SSHPublicKeyDatabase.checkKey(
             self, credentials)
     for filePath in self.getAuthorizedKeysFiles(credentials):
         if not filePath.exists():
             continue
         lines = filePath.open()
         for line in lines:
             lineData = line.split()
             if len(lineData) < 2:
                 continue
             try:
                 if base64.decodestring(lineData[1]) == credentials.blob:
                     return True
             except binascii.Error:
                 continue
     return False
Ejemplo n.º 15
0
    def setUp(self):
        self.checker = SSHPublicKeyDatabase()
        self.key1 = base64.encodestring("foobar")
        self.key2 = base64.encodestring("eggspam")
        self.content = "t1 %s foo\nt2 %s egg\n" % (self.key1, self.key2)

        self.mockos = MockOS()
        self.mockos.path = FilePath(self.mktemp())
        self.mockos.path.makedirs()
        self.sshDir = self.mockos.path.child('.ssh')
        self.sshDir.makedirs()

        userdb = UserDatabase()
        userdb.addUser('user', 'password', 1, 2, 'first last',
                self.mockos.path.path, '/bin/shell')

        self.patch(pwd, "getpwnam", userdb.getpwnam)
        self.patch(os, "seteuid", self.mockos.seteuid)
        self.patch(os, "setegid", self.mockos.setegid)
Ejemplo n.º 16
0
class SSHPublicKeyDatabaseTests(TestCase):
    """
    Tests for L{SSHPublicKeyDatabase}.
    """

    if pwd is None:
        skip = "Cannot run without pwd module"
    elif SSHPublicKeyDatabase is None:
        skip = "Cannot run without PyCrypto"

    def setUp(self):
        self.checker = SSHPublicKeyDatabase()
        self.sshDir = FilePath(self.mktemp())
        self.sshDir.makedirs()

        self.key1 = base64.encodestring("foobar")
        self.key2 = base64.encodestring("eggspam")
        self.content = "t1 %s foo\nt2 %s egg\n" % (self.key1, self.key2)

        self.mockos = MockOS()
        self.mockos.path = self.sshDir.path
        self.patch(os.path, "expanduser", self.mockos.expanduser)
        self.patch(pwd, "getpwnam", self.mockos.getpwnam)
        self.patch(os, "seteuid", self.mockos.seteuid)
        self.patch(os, "setegid", self.mockos.setegid)


    def _testCheckKey(self, filename):
        self.sshDir.child(filename).setContent(self.content)
        user = UsernamePassword("user", "password")
        user.blob = "foobar"
        self.assertTrue(self.checker.checkKey(user))
        user.blob = "eggspam"
        self.assertTrue(self.checker.checkKey(user))
        user.blob = "notallowed"
        self.assertFalse(self.checker.checkKey(user))


    def test_checkKey(self):
        """
        L{SSHPublicKeyDatabase.checkKey} should retrieve the content of the
        authorized_keys file and check the keys against that file.
        """
        self._testCheckKey("authorized_keys")
        self.assertEquals(self.mockos.seteuidCalls, [])
        self.assertEquals(self.mockos.setegidCalls, [])


    def test_checkKey2(self):
        """
        L{SSHPublicKeyDatabase.checkKey} should retrieve the content of the
        authorized_keys2 file and check the keys against that file.
        """
        self._testCheckKey("authorized_keys2")
        self.assertEquals(self.mockos.seteuidCalls, [])
        self.assertEquals(self.mockos.setegidCalls, [])


    def test_checkKeyAsRoot(self):
        """
        If the key file is readable, L{SSHPublicKeyDatabase.checkKey} should
        switch its uid/gid to the ones of the authenticated user.
        """
        keyFile = self.sshDir.child("authorized_keys")
        keyFile.setContent(self.content)
        # 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)
        user = UsernamePassword("user", "password")
        user.blob = "foobar"
        self.assertTrue(self.checker.checkKey(user))
        self.assertEquals(self.mockos.seteuidCalls, [0, 1, 0, os.getuid()])
        self.assertEquals(self.mockos.setegidCalls, [2, os.getgid()])
Ejemplo n.º 17
0
    """Authentication/authorization backend using the 'login' PAM service"""

    credentialInterfaces = IUsernamePassword,
    implements(ICredentialsChecker)

    def requestAvatarId(self, credentials):
        if pam.authenticate(credentials.username, credentials.password):
            return defer.succeed(credentials.username)
        return defer.fail(UnauthorizedLogin("invalid password"))


class UnixSSHdFactory(factory.SSHFactory):
    publicKeys = {'ssh-rsa': keys.Key.fromString(data=publicKey)}
    privateKeys = {'ssh-rsa': keys.Key.fromString(data=privateKey)}
    services = {
        'ssh-userauth': userauth.SSHUserAuthServer,
        'ssh-connection': connection.SSHConnection
    }


# Components have already been registered in twisted.conch.unix

portal = portal.Portal(UnixSSHRealm())
portal.registerChecker(PamPasswordDatabase())  # Supports PAM
portal.registerChecker(SSHPublicKeyDatabase())  # Supports PKI
UnixSSHdFactory.portal = portal

if __name__ == '__main__':
    reactor.listenTCP(5022, UnixSSHdFactory())
    reactor.run()
Ejemplo n.º 18
0
class SSHPublicKeyDatabaseTestCase(TestCase):
    """
    Tests for L{SSHPublicKeyDatabase}.
    """

    if pwd is None:
        skip = "Cannot run without pwd module"
    elif SSHPublicKeyDatabase is None:
        skip = "Cannot run without PyCrypto or PyASN1"

    def setUp(self):
        self.checker = SSHPublicKeyDatabase()
        self.key1 = base64.encodestring("foobar")
        self.key2 = base64.encodestring("eggspam")
        self.content = "t1 %s foo\nt2 %s egg\n" % (self.key1, self.key2)

        self.mockos = MockOS()
        self.mockos.path = FilePath(self.mktemp())
        self.mockos.path.makedirs()
        self.sshDir = self.mockos.path.child('.ssh')
        self.sshDir.makedirs()

        userdb = UserDatabase()
        userdb.addUser('user', 'password', 1, 2, 'first last',
                self.mockos.path.path, '/bin/shell')

        self.patch(pwd, "getpwnam", userdb.getpwnam)
        self.patch(os, "seteuid", self.mockos.seteuid)
        self.patch(os, "setegid", self.mockos.setegid)


    def _testCheckKey(self, filename):
        self.sshDir.child(filename).setContent(self.content)
        user = UsernamePassword("user", "password")
        user.blob = "foobar"
        self.assertTrue(self.checker.checkKey(user))
        user.blob = "eggspam"
        self.assertTrue(self.checker.checkKey(user))
        user.blob = "notallowed"
        self.assertFalse(self.checker.checkKey(user))


    def test_checkKey(self):
        """
        L{SSHPublicKeyDatabase.checkKey} should retrieve the content of the
        authorized_keys file and check the keys against that file.
        """
        self._testCheckKey("authorized_keys")
        self.assertEquals(self.mockos.seteuidCalls, [])
        self.assertEquals(self.mockos.setegidCalls, [])


    def test_checkKey2(self):
        """
        L{SSHPublicKeyDatabase.checkKey} should retrieve the content of the
        authorized_keys2 file and check the keys against that file.
        """
        self._testCheckKey("authorized_keys2")
        self.assertEquals(self.mockos.seteuidCalls, [])
        self.assertEquals(self.mockos.setegidCalls, [])


    def test_checkKeyAsRoot(self):
        """
        If the key file is readable, L{SSHPublicKeyDatabase.checkKey} should
        switch its uid/gid to the ones of the authenticated user.
        """
        keyFile = self.sshDir.child("authorized_keys")
        keyFile.setContent(self.content)
        # 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)
        user = UsernamePassword("user", "password")
        user.blob = "foobar"
        self.assertTrue(self.checker.checkKey(user))
        self.assertEquals(self.mockos.seteuidCalls, [0, 1, 0, os.getuid()])
        self.assertEquals(self.mockos.setegidCalls, [2, os.getgid()])


    def test_requestAvatarId(self):
        """
        L{SSHPublicKeyDatabase.requestAvatarId} should return the avatar id
        passed in if its C{_checkKey} method returns True.
        """
        def _checkKey(ignored):
            return True
        self.patch(self.checker, 'checkKey', _checkKey)
        credentials = SSHPrivateKey('test', 'ssh-rsa', keydata.publicRSA_openssh,
                                    'foo', keys.Key.fromString(keydata.privateRSA_openssh).sign('foo'))
        d = self.checker.requestAvatarId(credentials)
        def _verify(avatarId):
            self.assertEquals(avatarId, 'test')
        return d.addCallback(_verify)


    def test_requestAvatarIdWithoutSignature(self):
        """
        L{SSHPublicKeyDatabase.requestAvatarId} should raise L{ValidPublicKey}
        if the credentials represent a valid key without a signature.  This
        tells the user that the key is valid for login, but does not actually
        allow that user to do so without a signature.
        """
        def _checkKey(ignored):
            return True
        self.patch(self.checker, 'checkKey', _checkKey)
        credentials = SSHPrivateKey('test', 'ssh-rsa', keydata.publicRSA_openssh, None, None)
        d = self.checker.requestAvatarId(credentials)
        return self.assertFailure(d, ValidPublicKey)


    def test_requestAvatarIdInvalidKey(self):
        """
        If L{SSHPublicKeyDatabase.checkKey} returns False,
        C{_cbRequestAvatarId} should raise L{UnauthorizedLogin}.
        """
        def _checkKey(ignored):
            return False
        self.patch(self.checker, 'checkKey', _checkKey)
        d = self.checker.requestAvatarId(None);
        return self.assertFailure(d, UnauthorizedLogin)


    def test_requestAvatarIdInvalidSignature(self):
        """
        Valid keys with invalid signatures should cause
        L{SSHPublicKeyDatabase.requestAvatarId} to return a {UnauthorizedLogin}
        failure
        """
        def _checkKey(ignored):
            return True
        self.patch(self.checker, 'checkKey', _checkKey)
        credentials = SSHPrivateKey('test', 'ssh-rsa', keydata.publicRSA_openssh,
                                    'foo', keys.Key.fromString(keydata.privateDSA_openssh).sign('foo'))
        d = self.checker.requestAvatarId(credentials)
        return self.assertFailure(d, UnauthorizedLogin)


    def test_requestAvatarIdNormalizeException(self):
        """
        Exceptions raised while verifying the key should be normalized into an
        C{UnauthorizedLogin} failure.
        """
        def _checkKey(ignored):
            return True
        self.patch(self.checker, 'checkKey', _checkKey)
        credentials = SSHPrivateKey('test', None, 'blob', 'sigData', 'sig')
        d = self.checker.requestAvatarId(credentials)
        def _verifyLoggedException(failure):
            errors = self.flushLoggedErrors(keys.BadKeyError)
            self.assertEqual(len(errors), 1)
            return failure
        d.addErrback(_verifyLoggedException)
        return self.assertFailure(d, UnauthorizedLogin)
Ejemplo n.º 19
0
class SSHPublicKeyDatabaseTests(TestCase):
    """
    Tests for L{SSHPublicKeyDatabase}.
    """

    if pwd is None:
        skip = "Cannot run without pwd module"
    elif SSHPublicKeyDatabase is None:
        skip = "Cannot run without PyCrypto"

    def setUp(self):
        self.checker = SSHPublicKeyDatabase()
        self.sshDir = FilePath(self.mktemp())
        self.sshDir.makedirs()

        self.key1 = base64.encodestring("foobar")
        self.key2 = base64.encodestring("eggspam")
        self.content = "t1 %s foo\nt2 %s egg\n" % (self.key1, self.key2)

        self.mockos = MockOS()
        self.mockos.path = self.sshDir.path
        self.patch(os.path, "expanduser", self.mockos.expanduser)
        self.patch(pwd, "getpwnam", self.mockos.getpwnam)
        self.patch(os, "seteuid", self.mockos.seteuid)
        self.patch(os, "setegid", self.mockos.setegid)

    def _testCheckKey(self, filename):
        self.sshDir.child(filename).setContent(self.content)
        user = UsernamePassword("user", "password")
        user.blob = "foobar"
        self.assertTrue(self.checker.checkKey(user))
        user.blob = "eggspam"
        self.assertTrue(self.checker.checkKey(user))
        user.blob = "notallowed"
        self.assertFalse(self.checker.checkKey(user))

    def test_checkKey(self):
        """
        L{SSHPublicKeyDatabase.checkKey} should retrieve the content of the
        authorized_keys file and check the keys against that file.
        """
        self._testCheckKey("authorized_keys")
        self.assertEquals(self.mockos.seteuidCalls, [])
        self.assertEquals(self.mockos.setegidCalls, [])

    def test_checkKey2(self):
        """
        L{SSHPublicKeyDatabase.checkKey} should retrieve the content of the
        authorized_keys2 file and check the keys against that file.
        """
        self._testCheckKey("authorized_keys2")
        self.assertEquals(self.mockos.seteuidCalls, [])
        self.assertEquals(self.mockos.setegidCalls, [])

    def test_checkKeyAsRoot(self):
        """
        If the key file is readable, L{SSHPublicKeyDatabase.checkKey} should
        switch its uid/gid to the ones of the authenticated user.
        """
        keyFile = self.sshDir.child("authorized_keys")
        keyFile.setContent(self.content)
        # 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)
        user = UsernamePassword("user", "password")
        user.blob = "foobar"
        self.assertTrue(self.checker.checkKey(user))
        self.assertEquals(self.mockos.seteuidCalls, [0, 1, 0, os.getuid()])
        self.assertEquals(self.mockos.setegidCalls, [2, os.getgid()])
Ejemplo n.º 20
0
    def getAuthorizedKeysFiles(self, credentials):
        if self.authorized_keys is not None:
            return [FilePath(ak) for ak in self.authorized_keys]

        return SSHPublicKeyDatabase.getAuthorizedKeysFiles(self, credentials)
Ejemplo n.º 21
0
 def _cbRequestAvatarId(self, validKey, credentials):
     returnMe = SSHPublicKeyDatabase._cbRequestAvatarId(self, validKey[0], credentials)
     if returnMe == validKey[1].username:
         return validKey[1]
     else:
         return returnMe
Ejemplo n.º 22
0
class SSHPublicKeyDatabaseTestCase(TestCase):
    """
    Tests for L{SSHPublicKeyDatabase}.
    """

    if pwd is None:
        skip = "Cannot run without pwd module"
    elif SSHPublicKeyDatabase is None:
        skip = "Cannot run without PyCrypto or PyASN1"

    def setUp(self):
        self.checker = SSHPublicKeyDatabase()
        self.sshDir = FilePath(self.mktemp())
        self.sshDir.makedirs()

        self.key1 = base64.encodestring("foobar")
        self.key2 = base64.encodestring("eggspam")
        self.content = "t1 %s foo\nt2 %s egg\n" % (self.key1, self.key2)

        self.mockos = MockOS()
        self.mockos.path = self.sshDir.path
        self.patch(os.path, "expanduser", self.mockos.expanduser)
        self.patch(pwd, "getpwnam", self.mockos.getpwnam)
        self.patch(os, "seteuid", self.mockos.seteuid)
        self.patch(os, "setegid", self.mockos.setegid)

    def _testCheckKey(self, filename):
        self.sshDir.child(filename).setContent(self.content)
        user = UsernamePassword("user", "password")
        user.blob = "foobar"
        self.assertTrue(self.checker.checkKey(user))
        user.blob = "eggspam"
        self.assertTrue(self.checker.checkKey(user))
        user.blob = "notallowed"
        self.assertFalse(self.checker.checkKey(user))

    def test_checkKey(self):
        """
        L{SSHPublicKeyDatabase.checkKey} should retrieve the content of the
        authorized_keys file and check the keys against that file.
        """
        self._testCheckKey("authorized_keys")
        self.assertEquals(self.mockos.seteuidCalls, [])
        self.assertEquals(self.mockos.setegidCalls, [])

    def test_checkKey2(self):
        """
        L{SSHPublicKeyDatabase.checkKey} should retrieve the content of the
        authorized_keys2 file and check the keys against that file.
        """
        self._testCheckKey("authorized_keys2")
        self.assertEquals(self.mockos.seteuidCalls, [])
        self.assertEquals(self.mockos.setegidCalls, [])

    def test_checkKeyAsRoot(self):
        """
        If the key file is readable, L{SSHPublicKeyDatabase.checkKey} should
        switch its uid/gid to the ones of the authenticated user.
        """
        keyFile = self.sshDir.child("authorized_keys")
        keyFile.setContent(self.content)
        # 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)
        user = UsernamePassword("user", "password")
        user.blob = "foobar"
        self.assertTrue(self.checker.checkKey(user))
        self.assertEquals(self.mockos.seteuidCalls, [0, 1, 0, os.getuid()])
        self.assertEquals(self.mockos.setegidCalls, [2, os.getgid()])

    def test_requestAvatarId(self):
        """
        L{SSHPublicKeyDatabase.requestAvatarId} should return the avatar id
        passed in if its C{_checkKey} method returns True.
        """
        def _checkKey(ignored):
            return True

        self.patch(self.checker, 'checkKey', _checkKey)
        credentials = SSHPrivateKey(
            'test', 'ssh-rsa', keydata.publicRSA_openssh, 'foo',
            keys.Key.fromString(keydata.privateRSA_openssh).sign('foo'))
        d = self.checker.requestAvatarId(credentials)

        def _verify(avatarId):
            self.assertEquals(avatarId, 'test')

        return d.addCallback(_verify)

    def test_requestAvatarIdWithoutSignature(self):
        """
        L{SSHPublicKeyDatabase.requestAvatarId} should raise L{ValidPublicKey}
        if the credentials represent a valid key without a signature.  This
        tells the user that the key is valid for login, but does not actually
        allow that user to do so without a signature.
        """
        def _checkKey(ignored):
            return True

        self.patch(self.checker, 'checkKey', _checkKey)
        credentials = SSHPrivateKey('test', 'ssh-rsa',
                                    keydata.publicRSA_openssh, None, None)
        d = self.checker.requestAvatarId(credentials)
        return self.assertFailure(d, ValidPublicKey)

    def test_requestAvatarIdInvalidKey(self):
        """
        If L{SSHPublicKeyDatabase.checkKey} returns False,
        C{_cbRequestAvatarId} should raise L{UnauthorizedLogin}.
        """
        def _checkKey(ignored):
            return False

        self.patch(self.checker, 'checkKey', _checkKey)
        d = self.checker.requestAvatarId(None)
        return self.assertFailure(d, UnauthorizedLogin)

    def test_requestAvatarIdInvalidSignature(self):
        """
        Valid keys with invalid signatures should cause
        L{SSHPublicKeyDatabase.requestAvatarId} to return a {UnauthorizedLogin}
        failure
        """
        def _checkKey(ignored):
            return True

        self.patch(self.checker, 'checkKey', _checkKey)
        credentials = SSHPrivateKey(
            'test', 'ssh-rsa', keydata.publicRSA_openssh, 'foo',
            keys.Key.fromString(keydata.privateDSA_openssh).sign('foo'))
        d = self.checker.requestAvatarId(credentials)
        return self.assertFailure(d, UnauthorizedLogin)

    def test_requestAvatarIdNormalizeException(self):
        """
        Exceptions raised while verifying the key should be normalized into an
        C{UnauthorizedLogin} failure.
        """
        def _checkKey(ignored):
            return True

        self.patch(self.checker, 'checkKey', _checkKey)
        credentials = SSHPrivateKey('test', None, 'blob', 'sigData', 'sig')
        d = self.checker.requestAvatarId(credentials)

        def _verifyLoggedException(failure):
            errors = self.flushLoggedErrors(keys.BadKeyError)
            self.assertEqual(len(errors), 1)
            return failure

        d.addErrback(_verifyLoggedException)
        return self.assertFailure(d, UnauthorizedLogin)
Ejemplo n.º 23
0
 def getAuthorizedKeysFiles(self, credentials):
     if config.ssh.usesystemkeys:
         return SSHPublicKeyDatabase.getAuthorizedKeysFiles(
             self, credentials)
     return [FilePath(
         config.ssh.userauthkeys.replace("{{USER}}", credentials.username))]