def request_env(self, data): """ Process a request to pass an environment variable. @param data: The environment variable name and value, each encoded as an SSH protocol string and concatenated. @type data: L{bytes} @return: A true value if the request to pass this environment variable was accepted, otherwise a false value. """ if not self.session: self.session = ISession(self.avatar) if not ISessionSetEnv.providedBy(self.session): log.warn( "Can't handle environment variables for SSH avatar {avatar}: " "{session} does not provide ISessionSetEnv interface. " "It should be decorated with @implementer(ISession, " "ISessionSetEnv) to support env variables.", avatar=self.avatar, session=self.session, ) return 0 name, value, data = common.getNS(data, 2) try: self.session.setEnv(name, value) except EnvironmentVariableNotPermitted: return 0 except Exception: log.failure("Error setting environment variable {name}", name=name) return 0 else: return 1
def test_avatarAdaptsToRestrictedExecOnlySession(self): # When Conch tries to adapt the SSH server avatar to ISession, it # adapts to a RestrictedExecOnlySession. This means that a # RestrictedExecOnlySession handles any requests to execute a command. session = ISession(self.avatar) self.assertTrue( isinstance(session, RestrictedExecOnlySession), "ISession(avatar) doesn't adapt to ExecOnlySession. " "Got %r instead." % (session, )) self.assertEqual(get_BZR_PLUGIN_PATH_for_subprocess(), session.environment['BZR_PLUGIN_PATH']) self.assertEqual('*****@*****.**' % self.avatar.username, session.environment['BZR_EMAIL']) executable, arguments = session.getCommandToRun( 'bzr serve --inet --directory=/ --allow-writes') interpreter = '%s/bin/py' % config.root self.assertEqual(interpreter, executable) self.assertEqual([ interpreter, get_bzr_path(), 'lp-serve', '--inet', str(self.avatar.user_id) ], list(arguments)) self.assertRaises(ForbiddenCommand, session.getCommandToRun, 'rm -rf /')
def test_avatarAdaptsToOnlyRestrictedSession(self): config.push('codehosting-no-forking', "[codehosting]\nuse_forking_daemon: False\n") self.addCleanup(config.pop, 'codehosting-no-forking') session = ISession(self.avatar) self.failIf(isinstance(session, ForkingRestrictedExecOnlySession), "ISession(avatar) shouldn't adapt to " " ForkingRestrictedExecOnlySession when forking is disabled. ")
def test_interfaces(self): """ L{ShellAccount} powers up the item on which it is installed for L{IConchUser} and the L{IConchUser} powerup is adaptable to L{ISession}. """ avatar = IConchUser(self.store) self.assertTrue(verifyObject(IConchUser, avatar)) session = ISession(avatar) self.assertTrue(verifyObject(ISession, session))
def request_window_change(self, data): if not self.session: self.session = ISession(self.avatar) winSize = parseRequest_window_change(data) try: self.session.windowChanged(winSize) except Exception: log.failure("Error changing window size") return 0 else: return 1
def request_pty_req(self, data): if not self.session: self.session = ISession(self.avatar) term, windowSize, modes = parseRequest_pty_req(data) log.msg('pty request: %s %s' % (term, windowSize)) try: self.session.getPty(term, windowSize, modes) except: log.err() return 0 else: return 1
def request_window_change(self, data): if not self.session: self.session = ISession(self.avatar) winSize = parseRequest_window_change(data) try: self.session.windowChanged(winSize) except: log.msg('error changing window size') log.err() return 0 else: return 1
def request_shell(self, data): log.info("Getting shell") if not self.session: self.session = ISession(self.avatar) try: pp = SSHSessionProcessProtocol(self) self.session.openShell(pp) except Exception: log.failure("Error getting shell") return 0 else: self.client = pp return 1
def request_shell(self, data): log.msg('getting shell') if not self.session: self.session = ISession(self.avatar) try: pp = SSHSessionProcessProtocol(self) self.session.openShell(pp) except: log.deferr() return 0 else: self.client = pp return 1
def request_exec(self, data): if not self.session: self.session = ISession(self.avatar) f, data = common.getNS(data) log.info('Executing command "{f}"', f=f) try: pp = SSHSessionProcessProtocol(self) self.session.execCommand(pp, f) except Exception: log.failure('Error executing command "{f}"', f=f) return 0 else: self.client = pp return 1
def request_exec(self, data): if not self.session: self.session = ISession(self.avatar) f,data = common.getNS(data) log.msg('executing command "%s"' % f) try: pp = SSHSessionProcessProtocol(self) self.session.execCommand(pp, f) except: log.deferr() return 0 else: self.client = pp return 1
def request_pty_req(self, data): if not self.session: self.session = ISession(self.avatar) term, windowSize, modes = parseRequest_pty_req(data) log.info('Handling pty request: {term!r} {windowSize!r}', term=term, windowSize=windowSize) try: self.session.getPty(term, windowSize, modes) except Exception: log.failure('Error handling pty request') return 0 else: return 1
def test_openShell(self): """ The L{ISession} adapter of the L{IConchUser} powerup implements C{openShell} so as to associate the given L{IProcessProtocol} with a transport. """ proto = ProcessProtocol() session = ISession(IConchUser(self.store)) # XXX See Twisted ticket #3864 proto.session = session proto.write = lambda bytes: None # XXX See #2895. session.getPty(None, (123, 456, 789, 1000), None) session.openShell(proto) self.assertNotIdentical(proto.transport, None)
def test_avatarAdaptsToForkingRestrictedExecOnlySession(self): config.push('codehosting-forking', "[codehosting]\nuse_forking_daemon: True\n") self.addCleanup(config.pop, 'codehosting-forking') session = ISession(self.avatar) self.assertTrue( isinstance(session, ForkingRestrictedExecOnlySession), "ISession(avatar) doesn't adapt to " " ForkingRestrictedExecOnlySession. " "Got %r instead." % (session, )) executable, arguments = session.getCommandToRun( 'bzr serve --inet --directory=/ --allow-writes') executable, arguments, env = session.getCommandToFork( executable, arguments, session.environment) self.assertEqual('bzr', executable) self.assertEqual( ['bzr', 'lp-serve', '--inet', str(self.avatar.user_id)], list(arguments))
def request_env(self, data): """ data should contain two netstrings. The first is an env var name, the second its requested value. """ name, rest = getNS(data) value, rest = getNS(rest) if rest: raise ValueError("Bad data given in env request.") if name in ENV_WHITELIST: log.msg("env request: %s=%s" % (name, value)) if not self.session: self.session = ISession(self.avatar) self.session.environ[name] = value return True else: log.msg("env request REJECTED: %s=%s" % (name, value)) return False