RAHHH
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
# -*- test-case-name: twisted.conch.test.test_unix -*-
|
||||
# Copyright (c) Twisted Matrix Laboratories.
|
||||
# See LICENSE for details.
|
||||
|
||||
|
||||
from zope.interface import implementer
|
||||
|
||||
from twisted.conch.interfaces import IConchUser
|
||||
from twisted.cred.checkers import (
|
||||
AllowAnonymousAccess,
|
||||
InMemoryUsernamePasswordDatabaseDontUse,
|
||||
)
|
||||
from twisted.cred.credentials import (
|
||||
Anonymous,
|
||||
IAnonymous,
|
||||
IUsernamePassword,
|
||||
UsernamePassword,
|
||||
)
|
||||
from twisted.cred.error import LoginDenied
|
||||
from twisted.cred.portal import Portal
|
||||
from twisted.internet.interfaces import IReactorProcess
|
||||
from twisted.python.fakepwd import UserDatabase
|
||||
from twisted.python.reflect import requireModule
|
||||
from twisted.trial import unittest
|
||||
from .test_session import StubClient, StubConnection
|
||||
|
||||
cryptography = requireModule("cryptography")
|
||||
unix = requireModule("twisted.conch.unix")
|
||||
|
||||
if unix is not None:
|
||||
from twisted.conch.unix import UnixConchUser, UnixSSHRealm
|
||||
|
||||
|
||||
@implementer(IReactorProcess)
|
||||
class MockProcessSpawner:
|
||||
"""
|
||||
An L{IReactorProcess} that logs calls to C{spawnProcess}.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._spawnProcessCalls = []
|
||||
|
||||
def spawnProcess(
|
||||
self,
|
||||
processProtocol,
|
||||
executable,
|
||||
args=(),
|
||||
env={},
|
||||
path=None,
|
||||
uid=None,
|
||||
gid=None,
|
||||
usePTY=0,
|
||||
childFDs=None,
|
||||
):
|
||||
"""
|
||||
Log a call to C{spawnProcess}. Do not actually spawn a process.
|
||||
"""
|
||||
self._spawnProcessCalls.append(
|
||||
{
|
||||
"processProtocol": processProtocol,
|
||||
"executable": executable,
|
||||
"args": args,
|
||||
"env": env,
|
||||
"path": path,
|
||||
"uid": uid,
|
||||
"gid": gid,
|
||||
"usePTY": usePTY,
|
||||
"childFDs": childFDs,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
shouldSkip = (
|
||||
"Cannot run without cryptography"
|
||||
if cryptography is None
|
||||
else "Unix system required"
|
||||
if unix is None
|
||||
else None
|
||||
)
|
||||
|
||||
|
||||
class TestSSHSessionForUnixConchUser(unittest.TestCase):
|
||||
skip = shouldSkip
|
||||
|
||||
def testExecCommandEnvironment(self) -> None:
|
||||
"""
|
||||
C{execCommand} sets the C{HOME} environment variable to the avatar's home
|
||||
directory.
|
||||
"""
|
||||
userdb = UserDatabase()
|
||||
homeDirectory = "/made/up/path/"
|
||||
userName = "user"
|
||||
userdb.addUser(userName, home=homeDirectory)
|
||||
self.patch(unix, "pwd", userdb)
|
||||
mockReactor = MockProcessSpawner()
|
||||
avatar = UnixConchUser(userName)
|
||||
avatar.conn = StubConnection(transport=StubClient())
|
||||
session = unix.SSHSessionForUnixConchUser(avatar, reactor=mockReactor)
|
||||
protocol = None
|
||||
command = ["not-actually-executed"]
|
||||
session.execCommand(protocol, command)
|
||||
[call] = mockReactor._spawnProcessCalls
|
||||
self.assertEqual(homeDirectory, call["env"]["HOME"])
|
||||
|
||||
|
||||
class TestUnixSSHRealm(unittest.TestCase):
|
||||
"""
|
||||
Tests for L{UnixSSHRealm}.
|
||||
"""
|
||||
|
||||
skip = shouldSkip
|
||||
|
||||
def test_unixSSHRealm(self) -> None:
|
||||
"""
|
||||
L{UnixSSHRealm} is an L{IRealm} whose C{.requestAvatar} method returns
|
||||
a L{UnixConchUser}.
|
||||
"""
|
||||
userdb = UserDatabase()
|
||||
home = "/testing/home/value"
|
||||
userdb.addUser("user", home=home)
|
||||
self.patch(unix, "pwd", userdb)
|
||||
pwdb = InMemoryUsernamePasswordDatabaseDontUse(user=b"password")
|
||||
p = Portal(UnixSSHRealm(), [pwdb])
|
||||
|
||||
# there seems to be a bug in mypy-zope where sometimes things don't
|
||||
# implement their superinterfaces; 0.3.11, when we upgrade to 0.9.0
|
||||
# this type declaration will be extraneous
|
||||
creds: IUsernamePassword = UsernamePassword(b"user", b"password")
|
||||
result = p.login(creds, None, IConchUser)
|
||||
resultInterface, avatar, logout = self.successResultOf(result)
|
||||
self.assertIsInstance(avatar, UnixConchUser)
|
||||
assert isinstance(avatar, UnixConchUser) # legibility for mypy
|
||||
self.assertEqual(avatar.getHomeDir(), home)
|
||||
|
||||
def test_unixSSHRefusesAnonymousLogins(self) -> None:
|
||||
"""
|
||||
L{UnixSSHRealm} will refuse anonymous logins.
|
||||
"""
|
||||
p = Portal(UnixSSHRealm(), [AllowAnonymousAccess()])
|
||||
result = p.login(IAnonymous(Anonymous()), None, IConchUser)
|
||||
loginDenied = self.failureResultOf(result)
|
||||
self.assertIsInstance(loginDenied.value, LoginDenied)
|
||||
Reference in New Issue
Block a user