def __init__(self, window_agents): Thread.__init__(self) # Make sure this thread is a daemon not to prevent program exit. self.daemon = True realm = manhole_ssh.TerminalRealm() namespace = { 'Gtk': Gtk, 'walk': walk, 'widgets': lambda: walk(iter(window_agents).next()), 'window_agents': window_agents, 'window': lambda: iter(window_agents).next() } realm.chainedProtocolFactory.protocolFactory = \ lambda _: manhole.Manhole(namespace) p = portal.Portal(realm) p.registerChecker( checkers.InMemoryUsernamePasswordDatabaseDontUse(nemo='nemo')) reactor.listenTCP(2222, manhole_ssh.ConchFactory(p)) # Starting the thread is not enough because the Python interpreter # is no running all the time and therefore the thread will not run # too. Workaround this by using a timer to run the interpreter # periodically. def timer(): time.sleep(0.001) # Yield to other threads. return True GObject.timeout_add(10, timer)
def __init__(self, port, checker, using_ssh=True): service.MultiService.__init__(self) if type(port) is int: port = 'tcp:%d' % port self.port = port self.checker = checker def makeNamespace(): namespace = dict(consoleNamespace) return namespace def makeProtocol(): namespace = makeNamespace() p = insults.ServerProtocol(FriendlyManhole, namespace) return p if using_ssh: r = manhole_ssh.TerminalRealm() r.chainedProtocolFactory = makeProtocol p = portal.Portal(r, [self.checker]) f = manhole_ssh.ConchFactory(p) else: 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)
def start_ssh_server(port, username, password, namespace): """ Start an SSH server on the given port, exposing a Python prompt with the given namespace. """ # This is a lot of boilerplate, see http://tm.tl/6429 for a ticket to # provide a utility function that simplifies this. from twisted.internet import reactor from twisted.conch.insults import insults from twisted.conch import manhole, manhole_ssh from twisted.cred.checkers import (InMemoryUsernamePasswordDatabaseDontUse as MemoryDB) from twisted.cred.portal import Portal sshRealm = manhole_ssh.TerminalRealm() def chainedProtocolFactory(): return insults.ServerProtocol(manhole.Manhole, namespace) sshRealm.chainedProtocolFactory = chainedProtocolFactory sshPortal = Portal(sshRealm, [MemoryDB(**{username: password})]) reactor.listenTCP(port, manhole_ssh.ConchFactory(sshPortal), interface="127.0.0.1")
def startSSHManhole(self): namespace = self.getConsoleLocals() realm = manhole_ssh.TerminalRealm() # If we don't do this, the server will generate an exception when # you resize the SSH window realm.sessionFactory.windowChanged = lambda *args, **kwargs: None def getManhole(_): return Manhole(namespace) realm.chainedProtocolFactory.protocolFactory = getManhole p = portal.Portal(realm) # Username/Password authentication passwordDB = checkers.InMemoryUsernamePasswordDatabaseDontUse() passwordDB.addUser('trosnoth', '') p.registerChecker(passwordDB) factory = manhole_ssh.ConchFactory(p) manholePort = 6799 try: reactor.listenTCP(manholePort, factory) except CannotListenError: log.error('Error starting manhole on port %d', manholePort) except ConchError as e: log.error('Error starting manhole on port %d: %s', manholePort, e.value) else: log.warning('SSH manhole started on port %d with password ""', manholePort)
def getManholeFactory(namespace, password): realm = manhole_ssh.TerminalRealm() # If we don't do this, the server will generate an exception when # you resize the SSH window def windowChanged(self, size): pass realm.sessionFactory.windowChanged = windowChanged def getManhole(_): return Manhole(namespace) realm.chainedProtocolFactory.protocolFactory = getManhole p = portal.Portal(realm) # Username/Password authentication passwordDB = checkers.InMemoryUsernamePasswordDatabaseDontUse() passwordDB.addUser('trosnoth', password) p.registerChecker(passwordDB) factory = manhole_ssh.ConchFactory(p) privatePath = getPath(user, 'authserver', 'manhole_rsa') if not os.path.isfile(privatePath): generateKeys(privatePath) if os.path.isfile(privatePath): factory.privateKeys[b'ssh-rsa'] = k = keys.Key.fromFile(privatePath) if not hasattr(k._keyObject, 'sign'): log.warn('SSH manhole may require newer version of cryptography!') publicPath = privatePath + '.pub' if os.path.isfile(publicPath): factory.publicKeys[b'ssh-rsa'] = keys.Key.fromFile(publicPath) return factory
def setupAdminSSHServer(configuration, director, services): """ Set up a server that will enable an admin user to SSH into the load-balancers's running Python Interpreter. """ if not configuration.admin.sshEnable: return host, port = util.splitHostPort(configuration.admin.sshListen) # set up a manhole def getManhole(serverProtocol): startingNamespace = { 'config': configuration, 'services': services, } return manhole.Manhole(util.getNamespace(startingNamespace)) realm = manhole_ssh.TerminalRealm() realm.chainedProtocolFactory.protocolFactory = getManhole p = portal.Portal(realm) p.registerChecker(auth.LBAdminAuthChecker(configuration.admin)) factory = manhole_ssh.ConchFactory(p) admin = internet.TCPServer(port, factory, interface=host) admin.setName('adminSSH') return admin
def getShellFactory(interpreterType, **namespace): sshPortal = portalFactory(interpreterType, namespace) factory = manhole_ssh.ConchFactory(sshPortal) factory.privateKeys = {'ssh-rsa': util.getPrivKey()} factory.publicKeys = {'ssh-rsa': util.getPubKey()} factory.portal.registerChecker(cred.PublicKeyDatabase()) return factory
def create_remote_factory(namespace, users): realm = manhole_ssh.TerminalRealm() def create_remote_protocol(_): return manhole.ColoredManhole(namespace) realm.chainedProtocolFactory.protocolFactory = create_remote_protocol p = portal.Portal(realm) users = {key: value.encode() for key, value in users.items()} p.registerChecker( checkers.InMemoryUsernamePasswordDatabaseDontUse(**users)) f = manhole_ssh.ConchFactory(p) ssh_key_base_path = path.join(config.config_dir, "ssh-keys") ssh_pubkey_path = path.join(ssh_key_base_path, "ssh_host_rsa_key.pub") ssh_privkey_path = path.join(ssh_key_base_path, "ssh_host_rsa_key") try: f.publicKeys[b"ssh-rsa"] = keys.Key.fromFile(ssh_pubkey_path) f.privateKeys[b"ssh-rsa"] = keys.Key.fromFile(ssh_privkey_path) except FileNotFoundError: print("ERROR: You don't have any keys in the host key location") print("Generate one with:") print(" mkdir {}".format(ssh_key_base_path)) print(" ssh-keygen -f {} -t rsa".format(ssh_privkey_path)) print("make sure to specify no password") sys.exit(1) return f
def manhole(username, password, globals): """Starts a ssh listener with password authentication using the given username and password. Clients connecting to the ssh listener will find themselves in a colored python shell with the supplied globals. Args: username(str): The username ssh clients should auth with. password(str): The password ssh clients should auth with. globals(dict): The variables to expose in the shell. Returns: twisted.internet.protocol.Factory: A factory to pass to ``listenTCP`` """ checker = checkers.InMemoryUsernamePasswordDatabaseDontUse( **{username: password}) rlm = manhole_ssh.TerminalRealm() rlm.chainedProtocolFactory = lambda: insults.ServerProtocol( ColoredManhole, dict(globals, __name__="__console__")) factory = manhole_ssh.ConchFactory(portal.Portal(rlm, [checker])) factory.publicKeys['ssh-rsa'] = Key.fromString(PUBLIC_KEY) factory.privateKeys['ssh-rsa'] = Key.fromString(PRIVATE_KEY) return factory
def start_listening(self): config = self.get_config() for listener in config.listeners: if listener["type"] == "http": self._listener_http(config, listener) elif listener["type"] == "manhole": checker = checkers.InMemoryUsernamePasswordDatabaseDontUse( matrix="rabbithole") rlm = manhole_ssh.TerminalRealm() rlm.chainedProtocolFactory = lambda: insults.ServerProtocol( ColoredManhole, { "__name__": "__console__", "hs": self, }) f = manhole_ssh.ConchFactory(portal.Portal(rlm, [checker])) reactor.listenTCP(listener["port"], f, interface=listener.get( "bind_address", '127.0.0.1')) else: logger.warn("Unrecognized listener type: %s", listener["type"])
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
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. @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) sshService = strports.service(options['sshPort'], sshFactory) sshService.setServiceParent(svc) return svc
def getManholeFactory(namespace, **passwords): realm = manhole_ssh.TerminalRealm() def getManhole(_): return manhole.Manhole(namespace) realm.chainedProtocolFactory.protocolFactory = getManhole p = portal.Portal(realm) p.registerChecker( checkers.InMemoryUsernamePasswordDatabaseDontUse(**passwords)) f = manhole_ssh.ConchFactory(p) return f
def makeFactory(store, ampFactory): shellGlobals = {"store": store, "ampFactory": ampFactory} makeManhole = lambda _ign: manhole.ColoredManhole(shellGlobals) realm = manhole_ssh.TerminalRealm() realm.chainedProtocolFactory.protocolFactory = makeManhole p = portal.Portal(realm, [checker]) return manhole_ssh.ConchFactory(p)
def makeSSHService(listen, passwd, namespace=None): namespace = namespace or {} checker = checkers.FilePasswordDB(passwd) sshRealm = manhole_ssh.TerminalRealm() sshRealm.chainedProtocolFactory = chainedProtocolFactory(namespace) sshPortal = portal.Portal(sshRealm, [checker]) sshFactory = manhole_ssh.ConchFactory(sshPortal) sshService = strports.service("tcp:%d" % listen, sshFactory) return sshService
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
def create_remote_factory(namespace, users): realm = manhole_ssh.TerminalRealm() def create_remote_protocol(_): return manhole.Manhole(namespace) realm.chainedProtocolFactory.protocolFactory = create_remote_protocol p = portal.Portal(realm) p.registerChecker( checkers.InMemoryUsernamePasswordDatabaseDontUse(**users)) f = manhole_ssh.ConchFactory(p) return f
def setup_middleware(self): self.validate_config() checker = SSHPubKeyDatabase(self.authorized_keys) ssh_realm = manhole_ssh.TerminalRealm() ssh_realm.chainedProtocolFactory = manhole_tap.chainedProtocolFactory({ 'worker': self.worker, }) ssh_portal = portal.Portal(ssh_realm, [checker]) factory = manhole_ssh.ConchFactory(ssh_portal) endpoint = serverFromString(reactor, self.twisted_endpoint) self.socket = yield endpoint.listen(factory)
def openSSHManhole(authorizedKeysFile, namespace, portNum=-1): from twisted.conch import manhole_ssh def makeProtocol(): return insults.ServerProtocol(manhole.Manhole, namespace) checker = SSHPublicKeyChecker(authorizedKeysFile) sshRealm = manhole_ssh.TerminalRealm() sshRealm.chainedProtocolFactory = makeProtocol sshPortal = portal.Portal(sshRealm, [checker]) sshFactory = manhole_ssh.ConchFactory(sshPortal) port = reactor.listenTCP(portNum, sshFactory, interface='localhost') return port
def get_manhole_factory(namespace, **passwords): """Get a Manhole Factory """ realm = manhole_ssh.TerminalRealm() realm.chainedProtocolFactory.protocolFactory = ( lambda _: EnhancedColoredManhole(namespace)) p = portal.Portal(realm) p.registerChecker( checkers.InMemoryUsernamePasswordDatabaseDontUse(**passwords)) return manhole_ssh.ConchFactory(p)
def getManholeFactory(namespace): realm = manhole_ssh.TerminalRealm() def getManhole(_): return manhole.ColoredManhole(namespace) realm.chainedProtocolFactory.protocolFactory = getManhole p = portal.Portal(realm) p.registerChecker(ManholeDiSSOmniaGPublicKeyDatabase()) p.registerChecker(ManholeDiSSOmniaGUserAuthDatabase()) f = manhole_ssh.ConchFactory(p) return f
def getManholeFactory(namespace): realm = manhole_ssh.TerminalRealm() def getManhole(_): return manhole.Manhole(namespace) realm.chainedProtocolFactory.protocolFactory = getManhole p = portal.Portal(realm) checker = checkers.InMemoryUsernamePasswordDatabaseDontUse() checker.addUser(config.USERNAME, config.PASSWORD) p.registerChecker(checker) f = manhole_ssh.ConchFactory(p) return f
def getManholeFactory(**users): # Create a terminal realm = manhole_ssh.TerminalRealm() realm.chainedProtocolFactory.protocolFactory = PythonManhole users = {key: value.encode() for key, value in users.items()} p = portal.Portal(realm) p.registerChecker( checkers.InMemoryUsernamePasswordDatabaseDontUse(**users)) # Create a factory f = manhole_ssh.ConchFactory(p) f.publicKeys[b'ssh-rsa'] = keys.Key.fromString(public_rsa) f.privateKeys[b'ssh-rsa'] = keys.Key.fromString(private_rsa) return f
def createManhole(port=2222, users={'gemrb': 'password'}): """Create a twisted manhole for accessing the embedded python interpreter""" namespace = {'GemRB': GemRB} def makeProtocol(): return insults.ServerProtocol(manhole.ColoredManhole, namespace) r = manhole_ssh.TerminalRealm() r.chainedProtocolFactory = makeProtocol c = checkers.InMemoryUsernamePasswordDatabaseDontUse() for (username, password) in users.iteritems(): c.addUser(username, password) p = portal.Portal(r, [c]) f = manhole_ssh.ConchFactory(p) return reactor.listenTCP(port, f)
def getHyShellFactory(**namespace): """ The "namespace" kwargs here contains the passed objects that will be accessible via the shell, namely: * "app" * "services" These two are passed in the call to hydeyhole.app.service.makeService. """ sshRealm = hyshell.HyTerminalRealm(namespace) sshPortal = portal.Portal(sshRealm) factory = manhole_ssh.ConchFactory(sshPortal) factory.privateKeys = {'ssh-rsa': util.getPrivKey()} factory.publicKeys = {'ssh-rsa': util.getPubKey()} factory.portal.registerChecker(cred.PublicKeyDatabase()) return factory
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
def __init__(self, port, pws, **kw): kw.update(globals()) kw['pp'] = pprint realm = manhole_ssh.TerminalRealm() manhole = ManholeWithCompleter(kw) def windowChanged(_, win_size): manhole.terminalSize(*reversed(win_size[:2])) realm.sessionFactory.windowChanged = windowChanged realm.chainedProtocolFactory.protocolFactory = lambda _: manhole portal = Portal(realm) portal.registerChecker(InMemoryUsernamePasswordDatabaseDontUse(**pws)) factory = manhole_ssh.ConchFactory(portal) public_key_str, private_key_str = get_rsa_keys() factory.publicKeys = {'ssh-rsa': keys.Key.fromString(public_key_str)} factory.privateKeys = {'ssh-rsa': keys.Key.fromString(private_key_str)} reactor.listenTCP(port, factory, interface='localhost')
def get_manhole_factory(namespace): """ Build a twisted manhole factory """ from twisted.conch import manhole, manhole_ssh from twisted.cred import portal, checkers # I really hate Twisted's default colors colors = { 'identifier': '\x1b[1;36m', 'keyword': '\x1b[33m', 'parameter': '\x1b[33m', 'variable': '\x1b[36m', 'string': '\x1b[35m', 'number': '\x1b[1;32m', 'op': '\x1b[33m' } manhole.VT102Writer.typeToColor.update(colors) realm = manhole_ssh.TerminalRealm() def get_manhole(_): return manhole.ColoredManhole(namespace) realm.chainedProtocolFactory.protocolFactory = get_manhole p = portal.Portal(realm) checker = checkers.InMemoryUsernamePasswordDatabaseDontUse() checker.addUser(config.backdoor_user, config.backdoor_password) p.registerChecker(checker) factory = manhole_ssh.ConchFactory(p) # As of Twisted~v16.0.0 we now have to give host SSH keys to any subclass of SSHFactory key_path = os.path.expanduser(config.ssh_key_path) factory.publicKeys = { 'ssh-rsa': Key.fromFile(key_path) } factory.privateKeys = { 'ssh-rsa': Key.fromFile(key_path) } return factory
def InstallManagementConsole(namespace, users={'admin': 'admin'}, port=503): ''' Helper method to start an ssh management console for the modbus server. :param namespace: The data to constrain the server to :param users: The users to login with :param port: The port to host the server on ''' from twisted.internet import reactor def build_protocol(): p = insults.ServerProtocol(manhole.ColoredManhole, namespace) return p r = manhole_ssh.TerminalRealm() r.chainedProtocolFactory = build_protocol c = checkers.InMemoryUsernamePasswordDatabaseDontUse(**users) p = portal.Portal(r, [c]) factory = manhole_ssh.ConchFactory(p) reactor.listenTCP(port, factory)
def manhole(settings: ManholeConfig, globals: Dict[str, Any]) -> Factory: """Starts a ssh listener with password authentication using the given username and password. Clients connecting to the ssh listener will find themselves in a colored python shell with the supplied globals. Args: username: The username ssh clients should auth with. password: The password ssh clients should auth with. globals: The variables to expose in the shell. Returns: A factory to pass to ``listenTCP`` """ username = settings.username password = settings.password.encode("ascii") priv_key = settings.priv_key if priv_key is None: priv_key = Key.fromString(PRIVATE_KEY) pub_key = settings.pub_key if pub_key is None: pub_key = Key.fromString(PUBLIC_KEY) checker = checkers.InMemoryUsernamePasswordDatabaseDontUse(**{username: password}) rlm = manhole_ssh.TerminalRealm() # mypy ignored here because: # - can't deduce types of lambdas # - variable is Type[ServerProtocol], expr is Callable[[], ServerProtocol] rlm.chainedProtocolFactory = lambda: insults.ServerProtocol( # type: ignore[misc,assignment] SynapseManhole, dict(globals, __name__="__console__") ) factory = manhole_ssh.ConchFactory(portal.Portal(rlm, [checker])) # conch has the wrong type on these dicts (says bytes to bytes, # should be bytes to Keys judging by how it's used). factory.privateKeys[b"ssh-rsa"] = priv_key # type: ignore[assignment] factory.publicKeys[b"ssh-rsa"] = pub_key # type: ignore[assignment] return factory