def makeFactory(configdict): """ Creates the ssh server factory. """ def chainProtocolFactory(username=None): return insults.ServerProtocol( configdict['protocolFactory'], *configdict.get('protocolConfigdict', (username, )), **configdict.get('protocolKwArgs', {})) rlm = PassAvatarIdTerminalRealm() rlm.transportFactory = TerminalSessionTransport_getPeer rlm.chainedProtocolFactory = chainProtocolFactory factory = ConchFactory(Portal(rlm)) factory.sessionhandler = configdict['sessions'] try: # create/get RSA keypair publicKey, privateKey = getKeyPair(_PUBLIC_KEY_FILE, _PRIVATE_KEY_FILE) factory.publicKeys = {b'ssh-rsa': publicKey} factory.privateKeys = {b'ssh-rsa': privateKey} except Exception as err: print(_NO_AUTOGEN.format(err=err)) factory.services = factory.services.copy() factory.services['ssh-userauth'] = ExtraInfoAuthServer factory.portal.registerChecker(AccountDBPasswordChecker(factory)) return factory
def makeFactory(configdict): """ Creates the ssh server factory. """ pubkeyfile = "ssh-public.key" privkeyfile = "ssh-private.key" def chainProtocolFactory(username=None): return insults.ServerProtocol( configdict['protocolFactory'], *configdict.get('protocolConfigdict', (username,)), **configdict.get('protocolKwArgs', {})) rlm = PassAvatarIdTerminalRealm() rlm.transportFactory = TerminalSessionTransport_getPeer rlm.chainedProtocolFactory = chainProtocolFactory factory = ConchFactory(Portal(rlm)) factory.sessionhandler = configdict['sessions'] try: # create/get RSA keypair publicKey, privateKey = getKeyPair(pubkeyfile, privkeyfile) factory.publicKeys = {'ssh-rsa': publicKey} factory.privateKeys = {'ssh-rsa': privateKey} except Exception as e: print(" getKeyPair error: %(e)s\n WARNING: Evennia could not auto-generate SSH keypair. Using conch default keys instead." % {'e': e}) print(" If this error persists, create game/%(pub)s and game/%(priv)s yourself using third-party tools." % {'pub': pubkeyfile, 'priv': privkeyfile}) factory.services = factory.services.copy() factory.services['ssh-userauth'] = ExtraInfoAuthServer factory.portal.registerChecker(PlayerDBPasswordChecker(factory)) return factory
def makeFactory(configdict): """ Creates the ssh server factory. """ pubkeyfile = "ssh-public.key" privkeyfile = "ssh-private.key" def chainProtocolFactory(username=None): return insults.ServerProtocol( configdict['protocolFactory'], *configdict.get('protocolConfigdict', (username, )), **configdict.get('protocolKwArgs', {})) rlm = PassAvatarIdTerminalRealm() rlm.transportFactory = TerminalSessionTransport_getPeer rlm.chainedProtocolFactory = chainProtocolFactory factory = ConchFactory(Portal(rlm)) factory.sessionhandler = configdict['sessions'] try: # create/get RSA keypair publicKey, privateKey = getKeyPair(pubkeyfile, privkeyfile) factory.publicKeys = {'ssh-rsa': publicKey} factory.privateKeys = {'ssh-rsa': privateKey} except Exception, e: print " getKeyPair error: %(e)s\n WARNING: Evennia could not auto-generate SSH keypair. Using conch default keys instead." % { 'e': e } print " If this error persists, create game/%(pub)s and game/%(priv)s yourself using third-party tools." % { 'pub': pubkeyfile, 'priv': privkeyfile }
def makeFactory(configdict): """ Creates the ssh server factory. """ def chainProtocolFactory(username=None): return insults.ServerProtocol( configdict['protocolFactory'], *configdict.get('protocolConfigdict', (username,)), **configdict.get('protocolKwArgs', {})) rlm = PassAvatarIdTerminalRealm() rlm.transportFactory = TerminalSessionTransport_getPeer rlm.chainedProtocolFactory = chainProtocolFactory factory = ConchFactory(Portal(rlm)) factory.sessionhandler = configdict['sessions'] try: # create/get RSA keypair publicKey, privateKey = getKeyPair(_PUBLIC_KEY_FILE, _PRIVATE_KEY_FILE) factory.publicKeys = {'ssh-rsa': publicKey} factory.privateKeys = {'ssh-rsa': privateKey} except Exception as err: print(_NO_AUTOGEN.format(err=err)) factory.services = factory.services.copy() factory.services['ssh-userauth'] = ExtraInfoAuthServer factory.portal.registerChecker(AccountDBPasswordChecker(factory)) return factory
def createManholeListener(): sshRealm = TerminalRealm() sshRealm.chainedProtocolFactory.protocolFactory = lambda _: Manhole( namespace) if settings.MANHOLE_PUBLIC_KEY == 'None': credChecker = checkers.InMemoryUsernamePasswordDatabaseDontUse() credChecker.addUser(settings.MANHOLE_USER.encode('utf-8'), ''.encode('utf-8')) else: userKeys = { settings.MANHOLE_USER.encode('utf-8'): settings.MANHOLE_PUBLIC_KEY.encode('utf-8'), } credChecker = PublicKeyChecker(userKeys) sshPortal = portal.Portal(sshRealm) sshPortal.registerChecker(credChecker) sessionFactory = ConchFactory(sshPortal) # set ssh host keys if settings.MANHOLE_HOST_KEY_DIR == "": raise CarbonConfigException("MANHOLE_HOST_KEY_DIR not defined") openSSHFactory = OpenSSHFactory() openSSHFactory.dataRoot = settings.MANHOLE_HOST_KEY_DIR sessionFactory.publicKeys = openSSHFactory.getPublicKeys() sessionFactory.privateKeys = openSSHFactory.getPrivateKeys() return sessionFactory
def makeFactory(configdict): """ Creates the ssh server factory. """ pubkeyfile = os.path.join(_GAME_DIR, "server", "ssh-public.key") privkeyfile = os.path.join(_GAME_DIR, "server", "ssh-private.key") def chainProtocolFactory(username=None): return insults.ServerProtocol( configdict['protocolFactory'], *configdict.get('protocolConfigdict', (username,)), **configdict.get('protocolKwArgs', {})) rlm = PassAvatarIdTerminalRealm() rlm.transportFactory = TerminalSessionTransport_getPeer rlm.chainedProtocolFactory = chainProtocolFactory factory = ConchFactory(Portal(rlm)) factory.sessionhandler = configdict['sessions'] try: # create/get RSA keypair publicKey, privateKey = getKeyPair(pubkeyfile, privkeyfile) factory.publicKeys = {'ssh-rsa': publicKey} factory.privateKeys = {'ssh-rsa': privateKey} except Exception as err: print ( "getKeyPair error: {err}\n WARNING: Evennia could not " \ "auto-generate SSH keypair. Using conch default keys instead.\n" \ "If this error persists, create {pub} and " \ "{priv} yourself using third-party tools.".format( err=err, pub=pubkeyfile, priv=privkeyfile)) factory.services = factory.services.copy() factory.services['ssh-userauth'] = ExtraInfoAuthServer factory.portal.registerChecker(PlayerDBPasswordChecker(factory)) return factory
def makeFactory(configdict): """ Creates the ssh server factory. """ pubkeyfile = os.path.join(_GAME_DIR, "server", "ssh-public.key") privkeyfile = os.path.join(_GAME_DIR, "server", "ssh-private.key") def chainProtocolFactory(username=None): return insults.ServerProtocol( configdict['protocolFactory'], *configdict.get('protocolConfigdict', (username, )), **configdict.get('protocolKwArgs', {})) rlm = PassAvatarIdTerminalRealm() rlm.transportFactory = TerminalSessionTransport_getPeer rlm.chainedProtocolFactory = chainProtocolFactory factory = ConchFactory(Portal(rlm)) factory.sessionhandler = configdict['sessions'] try: # create/get RSA keypair publicKey, privateKey = getKeyPair(pubkeyfile, privkeyfile) factory.publicKeys = {'ssh-rsa': publicKey} factory.privateKeys = {'ssh-rsa': privateKey} except Exception as err: print ( "getKeyPair error: {err}\n WARNING: Evennia could not " \ "auto-generate SSH keypair. Using conch default keys instead.\n" \ "If this error persists, create {pub} and " \ "{priv} yourself using third-party tools.".format( err=err, pub=pubkeyfile, priv=privkeyfile)) factory.services = factory.services.copy() factory.services['ssh-userauth'] = ExtraInfoAuthServer factory.portal.registerChecker(PlayerDBPasswordChecker(factory)) return factory
def start_manhole(self, config, details=None): """ Start a Manhole service within this process. **Usage:** This procedure is registered under * ``crossbar.node.<node_id>.worker.<worker_id>.start_manhole`` - for native workers * ``crossbar.node.<node_id>.controller.start_manhole`` - for node controllers The procedure takes a Manhole service configuration which defines a listening endpoint for the service and a list of users including passwords, e.g. .. code-block:: javascript { "endpoint": { "type": "tcp", "port": 6022 }, "users": [ { "user": "******", "password": "******" } ] } **Errors:** The procedure may raise the following errors: * ``crossbar.error.invalid_configuration`` - the provided configuration is invalid * ``crossbar.error.already_started`` - the Manhole service is already running (or starting) * ``crossbar.error.feature_unavailable`` - the required support packages are not installed **Events:** The procedure will publish an event when the service **is starting** to * ``crossbar.node.<node_id>.worker.<worker_id>.on_manhole_starting`` - for native workers * ``crossbar.node.<node_id>.controller.on_manhole_starting`` - for node controllers and publish an event when the service **has started** to * ``crossbar.node.<node_id>.worker.<worker_id>.on_manhole_started`` - for native workers * ``crossbar.node.<node_id>.controller.on_manhole_started`` - for node controllers :param config: Manhole service configuration. :type config: dict """ self.log.debug("{cls}.start_manhole(config = {config})", cls=self.__class__.__name__, config=config) if not _HAS_MANHOLE: emsg = "Could not start manhole: required packages are missing ({})".format( _MANHOLE_MISSING_REASON) self.log.error(emsg) raise ApplicationError(u"crossbar.error.feature_unavailable", emsg) if self._manhole_service: emsg = "Could not start manhole - already running (or starting)" self.log.warn(emsg) raise ApplicationError(u"crossbar.error.already_started", emsg) try: self.personality.check_manhole(self.personality, config) except Exception as e: emsg = "Could not start manhole: invalid configuration ({})".format( e) self.log.error(emsg) raise ApplicationError(u'crossbar.error.invalid_configuration', emsg) from twisted.conch.ssh import keys from twisted.conch.manhole_ssh import (ConchFactory, TerminalRealm, TerminalSession) from twisted.conch.manhole import ColoredManhole from twisted.conch.checkers import SSHPublicKeyDatabase class PublicKeyChecker(SSHPublicKeyDatabase): def __init__(self, userKeys): self.userKeys = {} for username, keyData in userKeys.items(): self.userKeys[username] = keys.Key.fromString( data=keyData).blob() def checkKey(self, credentials): username = credentials.username.decode('utf8') if username in self.userKeys: keyBlob = self.userKeys[username] return keyBlob == credentials.blob # setup user authentication # authorized_keys = { 'oberstet': 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCz7K1QwDhaq/Bi8o0uqiJQuVFCDQL5rbRvMClLHRx9KE3xP2Fh2eapzXuYGSgtG9Fyz1UQd+1oNM3wuNnT/DsBUBQrECP4bpFIHcJkMaFTARlCagkXosWsadzNnkW0osUCuHYMrzBJuXWF2GH+0OFCtVu+8E+4Mhvchu9xsHG8PM92SpI6aP0TtmT9D/0Bsm9JniRj8kndeS+iWG4s/pEGj7Rg7eGnbyQJt/9Jc1nWl6PngGbwp63dMVmh+8LP49PtfnxY8m9fdwpL4oW9U8beYqm8hyfBPN2yDXaehg6RILjIa7LU2/6bu96ZgnIz26zi/X9XlnJQt2aahWJs1+GR oberstet@thinkpad-t430s' } checker = PublicKeyChecker(authorized_keys) # setup manhole namespace # namespace = {'session': self} class PatchedTerminalSession(TerminalSession): # get rid of # exceptions.AttributeError: TerminalSession instance has no attribute 'windowChanged' def windowChanged(self, winSize): pass rlm = TerminalRealm() rlm.sessionFactory = PatchedTerminalSession # monkey patch rlm.chainedProtocolFactory.protocolFactory = lambda _: ColoredManhole( namespace) ptl = portal.Portal(rlm) ptl.registerChecker(checker) factory = ConchFactory(ptl) factory.noisy = False private_key = keys.Key.fromFile( os.path.join(self.cbdir, 'ssh_host_rsa_key')) public_key = private_key.public() publicKeys = {b'ssh-rsa': public_key} privateKeys = {b'ssh-rsa': private_key} factory.publicKeys = publicKeys factory.privateKeys = privateKeys self._manhole_service = ManholeService(config, details.caller) starting_topic = '{}.on_manhole_starting'.format(self._uri_prefix) starting_info = self._manhole_service.marshal() # the caller gets a progressive result .. if details.progress: details.progress(starting_info) # .. while all others get an event self.publish(starting_topic, starting_info, options=PublishOptions(exclude=details.caller)) try: self._manhole_service.port = yield create_listening_port_from_config( config['endpoint'], self.cbdir, factory, self._reactor, self.log) except Exception as e: self._manhole_service = None emsg = "Manhole service endpoint cannot listen: {}".format(e) self.log.error(emsg) raise ApplicationError(u"crossbar.error.cannot_listen", emsg) # alright, manhole has started self._manhole_service.started = datetime.utcnow() self._manhole_service.status = 'started' started_topic = '{}.on_manhole_started'.format(self._uri_prefix) started_info = self._manhole_service.marshal() self.publish(started_topic, started_info, options=PublishOptions(exclude=details.caller)) returnValue(started_info)
def start_manhole(self, config, details=None): """ Start a Manhole service within this process. **Usage:** This procedure is registered under * ``crossbar.node.<node_id>.worker.<worker_id>.start_manhole`` - for native workers * ``crossbar.node.<node_id>.controller.start_manhole`` - for node controllers The procedure takes a Manhole service configuration which defines a listening endpoint for the service and a list of users including passwords, e.g. .. code-block:: javascript { "endpoint": { "type": "tcp", "port": 6022 }, "users": [ { "user": "******", "password": "******" } ] } **Errors:** The procedure may raise the following errors: * ``crossbar.error.invalid_configuration`` - the provided configuration is invalid * ``crossbar.error.already_started`` - the Manhole service is already running (or starting) * ``crossbar.error.feature_unavailable`` - the required support packages are not installed **Events:** The procedure will publish an event when the service **is starting** to * ``crossbar.node.<node_id>.worker.<worker_id>.on_manhole_starting`` - for native workers * ``crossbar.node.<node_id>.controller.on_manhole_starting`` - for node controllers and publish an event when the service **has started** to * ``crossbar.node.<node_id>.worker.<worker_id>.on_manhole_started`` - for native workers * ``crossbar.node.<node_id>.controller.on_manhole_started`` - for node controllers :param config: Manhole service configuration. :type config: dict """ self.log.debug("{cls}.start_manhole(config = {config})", cls=self.__class__.__name__, config=config) if not _HAS_MANHOLE: emsg = "Could not start manhole: required packages are missing ({})".format(_MANHOLE_MISSING_REASON) self.log.error(emsg) raise ApplicationError(u"crossbar.error.feature_unavailable", emsg) if self._manhole_service: emsg = "Could not start manhole - already running (or starting)" self.log.warn(emsg) raise ApplicationError(u"crossbar.error.already_started", emsg) try: self.personality.check_manhole(self.personality, config) except Exception as e: emsg = "Could not start manhole: invalid configuration ({})".format(e) self.log.error(emsg) raise ApplicationError(u'crossbar.error.invalid_configuration', emsg) from twisted.conch.ssh import keys from twisted.conch.manhole_ssh import ( ConchFactory, TerminalRealm, TerminalSession) from twisted.conch.manhole import ColoredManhole from twisted.conch.checkers import SSHPublicKeyDatabase class PublicKeyChecker(SSHPublicKeyDatabase): def __init__(self, userKeys): self.userKeys = {} for username, keyData in userKeys.items(): self.userKeys[username] = keys.Key.fromString(data=keyData).blob() def checkKey(self, credentials): username = credentials.username.decode('utf8') if username in self.userKeys: keyBlob = self.userKeys[username] return keyBlob == credentials.blob # setup user authentication # authorized_keys = { 'oberstet': 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCz7K1QwDhaq/Bi8o0uqiJQuVFCDQL5rbRvMClLHRx9KE3xP2Fh2eapzXuYGSgtG9Fyz1UQd+1oNM3wuNnT/DsBUBQrECP4bpFIHcJkMaFTARlCagkXosWsadzNnkW0osUCuHYMrzBJuXWF2GH+0OFCtVu+8E+4Mhvchu9xsHG8PM92SpI6aP0TtmT9D/0Bsm9JniRj8kndeS+iWG4s/pEGj7Rg7eGnbyQJt/9Jc1nWl6PngGbwp63dMVmh+8LP49PtfnxY8m9fdwpL4oW9U8beYqm8hyfBPN2yDXaehg6RILjIa7LU2/6bu96ZgnIz26zi/X9XlnJQt2aahWJs1+GR oberstet@thinkpad-t430s' } checker = PublicKeyChecker(authorized_keys) # setup manhole namespace # namespace = {'session': self} class PatchedTerminalSession(TerminalSession): # get rid of # exceptions.AttributeError: TerminalSession instance has no attribute 'windowChanged' def windowChanged(self, winSize): pass rlm = TerminalRealm() rlm.sessionFactory = PatchedTerminalSession # monkey patch rlm.chainedProtocolFactory.protocolFactory = lambda _: ColoredManhole(namespace) ptl = portal.Portal(rlm) ptl.registerChecker(checker) factory = ConchFactory(ptl) factory.noisy = False private_key = keys.Key.fromFile(os.path.join(self.cbdir, 'ssh_host_rsa_key')) public_key = private_key.public() publicKeys = { b'ssh-rsa': public_key } privateKeys = { b'ssh-rsa': private_key } factory.publicKeys = publicKeys factory.privateKeys = privateKeys self._manhole_service = ManholeService(config, details.caller) starting_topic = '{}.on_manhole_starting'.format(self._uri_prefix) starting_info = self._manhole_service.marshal() # the caller gets a progressive result .. if details.progress: details.progress(starting_info) # .. while all others get an event self.publish(starting_topic, starting_info, options=PublishOptions(exclude=details.caller)) try: self._manhole_service.port = yield create_listening_port_from_config(config['endpoint'], self.cbdir, factory, self._reactor, self.log) except Exception as e: self._manhole_service = None emsg = "Manhole service endpoint cannot listen: {}".format(e) self.log.error(emsg) raise ApplicationError(u"crossbar.error.cannot_listen", emsg) # alright, manhole has started self._manhole_service.started = datetime.utcnow() self._manhole_service.status = 'started' started_topic = '{}.on_manhole_started'.format(self._uri_prefix) started_info = self._manhole_service.marshal() self.publish(started_topic, started_info, options=PublishOptions(exclude=details.caller)) returnValue(started_info)