diff --git a/src/commands/default/unloggedin.py b/src/commands/default/unloggedin.py index 3c4d52d512..a6caadbe64 100644 --- a/src/commands/default/unloggedin.py +++ b/src/commands/default/unloggedin.py @@ -60,83 +60,17 @@ class CmdConnect(MuxCommand): session.msg("Incorrect password.") return - # We are logging in, get/setup the player object controlled by player - - # Check if this is the first time the - # *player* connects - if player.db.FIRST_LOGIN: - player.at_first_login() - del player.db.FIRST_LOGIN - player.at_pre_login() - - character = player.character - if character: - # this player has a character. Check if it's the - # first time *this character* logs in - if character.db.FIRST_LOGIN: - character.at_first_login() - del character.db.FIRST_LOGIN - # run character login hook - character.at_pre_login() - - # actually do the login + # actually do the login. This will call all hooks. session.session_login(player) - - # post-login hooks - player.at_post_login() + + # we are logged in. Look around. + character = player.character if character: - character.at_post_login() - character.execute_cmd('look') + character.execute_cmd("look") else: - player.execute_cmd('look') + # we have no character yet; use player's look, if it exists + player.execute_cmd("look") - # run look - #print "character:", character, character.scripts.all(), character.cmdset.current - - # - # character = player.character - # if not character: - # # Create a new character object to tie the player to. This should - # # usually not be needed unless the old character object was manually - # # deleted. - # default_home_id = ServerConfig.objects.conf("default_home") - # default_home = ObjectDB.objects.get_id(default_home_id) - # typeclass = settings.BASE_CHARACTER_TYPECLASS - # character = create.create_object(typeclass=typeclass, - # key=player.name, - # location=default_home, - # home=default_home, - # player=player) - - # character.db.FIRST_LOGIN = "True" - - # # Getting ready to log the player in. - - # # Check if this is the first time the - # # *player* connects - # if player.db.FIRST_LOGIN: - # player.at_first_login() - # del player.db.FIRST_LOGIN - - # # check if this is the first time the *character* - # # character (needs not be the first time the player - # # does so, e.g. if the player has several characters) - # if character.db.FIRST_LOGIN: - # character.at_first_login() - # del character.db.FIRST_LOGIN - - # # actually do the login, calling - # # customization hooks before and after. - # player.at_pre_login() - # character.at_pre_login() - - # session.session_login(player) - - # player.at_post_login() - # character.at_post_login() - # # run look - # #print "character:", character, character.scripts.all(), character.cmdset.current - # character.execute_cmd('look') class CmdCreate(MuxCommand): """ diff --git a/src/server/session.py b/src/server/session.py index 6c76385c43..ce72ce77f7 100644 --- a/src/server/session.py +++ b/src/server/session.py @@ -58,6 +58,43 @@ class IOdata(object): self.__dict__.update(**kwargs) +def _login(session, player): + """ + For logging a player in. Removed this from CmdConnect because ssh + wanted to call it for autologin. + """ + # We are logging in, get/setup the player object controlled by player + + # Check if this is the first time the + # *player* connects (should be set by the + if player.db.FIRST_LOGIN: + player.at_first_login() + del player.db.FIRST_LOGIN + player.at_pre_login() + + character = player.character + if character: + # this player has a character. Check if it's the + # first time *this character* logs in (this should be + # set by the initial create command) + if character.db.FIRST_LOGIN: + character.at_first_login() + del character.db.FIRST_LOGIN + # run character login hook + character.at_pre_login() + + # actually do the login + session.session_login(player) + + # post-login hooks + player.at_post_login() + if character: + character.at_post_login() + character.execute_cmd('look') + else: + player.execute_cmd('look') + + #------------------------------------------------------------ # SessionBase class #------------------------------------------------------------ @@ -110,10 +147,28 @@ class SessionBase(object): def session_login(self, player): """ - Private startup mechanisms that need to run at login + Startup mechanisms that need to run at login player - the connected player """ + # Check if this is the first time the *player* logs in + if player.db.FIRST_LOGIN: + player.at_first_login() + del player.db.FIRST_LOGIN + player.at_pre_login() + + character = player.character + if character: + # this player has a character. Check if it's the + # first time *this character* logs in + if character.db.FIRST_LOGIN: + character.at_first_login() + del character.db.FIRST_LOGIN + # run character login hook + character.at_pre_login() + + # actually do the login by assigning session data + self.player = player self.user = player.user self.uid = self.user.id @@ -132,9 +187,14 @@ class SessionBase(object): #add session to connected list SESSIONS.add_loggedin_session(self) - #call hook + #call login hook self.at_login(player) + # post-login hooks + player.at_post_login() + if character: + character.at_post_login() + def session_disconnect(self): """ Clean up the session, removing it from the game and doing some diff --git a/src/server/ssh.py b/src/server/ssh.py index 309369a394..bba56b47ec 100644 --- a/src/server/ssh.py +++ b/src/server/ssh.py @@ -19,10 +19,13 @@ from twisted.conch.insults import insults from twisted.conch.manhole_ssh import TerminalRealm, _Glue, ConchFactory from twisted.conch.manhole import Manhole, recvline from twisted.internet import defer +from twisted.conch import interfaces as iconch +from twisted.python import components from django.conf import settings from src.server import session +from src.players.models import PlayerDB from src.utils import ansi, utils, logger - +#from src.commands.default.unloggedin import _login ENCODINGS = settings.ENCODINGS @@ -37,6 +40,13 @@ class SshProtocol(Manhole, session.Session): them. All communication between game and player goes through here. """ + def __init__(self, player): + """ + For setting up the player. If player is not None then we'll + login automatically. + """ + self.player = player + def terminalSize(self, width, height): """ @@ -48,9 +58,12 @@ class SshProtocol(Manhole, session.Session): self.terminal.cursorHome() self.width = width self.height = height + # initialize the session self.session_connect(self.getClientAddress()) - + if self.player is not None: + self.session_login(self.player) + self.execute_cmd('look') def connectionMade(self): """ @@ -161,7 +174,6 @@ class SshProtocol(Manhole, session.Session): """ self.telnet_markup = True # show connection screen - self.execute_cmd('look') def at_login(self, player): """ @@ -184,7 +196,7 @@ class SshProtocol(Manhole, session.Session): def at_data_out(self, string, data=None): """ - Data Evennia -> Player access hook. 'data' argument is ignored. + Data Evennia -> Player access hook. 'data' argument is a dict parsed for string settings. """ try: string = utils.to_str(string, encoding=self.encoding) @@ -216,6 +228,7 @@ class SshProtocol(Manhole, session.Session): logger.log_errmsg(str(e)) + class ExtraInfoAuthServer(SSHUserAuthServer): def auth_password(self, packet): """ @@ -230,10 +243,11 @@ class ExtraInfoAuthServer(SSHUserAuthServer): return self.portal.login(c, None, IConchUser).addErrback( self._ebPassword) - -class AnyAuth(object): +class PlayerDBPasswordChecker(object): """ - Special auth method that accepts any credentials. + Checks the django db for the correct credentials for + username/password otherwise it returns the player or None which is + useful for the Realm. """ credentialInterfaces = (credentials.IUsernamePassword,) @@ -242,8 +256,31 @@ class AnyAuth(object): up = credentials.IUsernamePassword(c, None) username = up.username password = up.password - src_ip = str(up.transport.transport.getPeer().host) - return defer.succeed(username) + player = PlayerDB.objects.get_player_from_name(username) + res = None + if player and player.user.check_password(password): + res = player + return defer.succeed(res) + +class PassAvatarIdTerminalRealm(TerminalRealm): + """ + Returns an avatar that passes the avatarId through to the + protocol. This is probably not the best way to do it. + """ + + def _getAvatar(self, avatarId): + comp = components.Componentized() + user = self.userFactory(comp, avatarId) + sess = self.sessionFactory(comp) + + sess.transportFactory = self.transportFactory + sess.chainedProtocolFactory = lambda : self.chainedProtocolFactory(avatarId) + + comp.setComponent(iconch.IConchUser, user) + comp.setComponent(iconch.ISession, sess) + + return user + class TerminalSessionTransport_getPeer: @@ -276,6 +313,7 @@ class TerminalSessionTransport_getPeer: self.chainedProtocol.terminalProtocol.terminalSize(width, height) + def getKeyPair(pubkeyfile, privkeyfile): """ This function looks for RSA keypair files in the current directory. If they @@ -302,6 +340,7 @@ def getKeyPair(pubkeyfile, privkeyfile): return Key.fromString(publicKeyString), Key.fromString(privateKeyString) + def makeFactory(configdict): """ Creates the ssh server factory. @@ -310,21 +349,21 @@ def makeFactory(configdict): pubkeyfile = "ssh-public.key" privkeyfile = "ssh-private.key" - def chainProtocolFactory(): + def chainProtocolFactory(username=None): return insults.ServerProtocol( configdict['protocolFactory'], - *configdict.get('protocolConfigdict', ()), + *configdict.get('protocolConfigdict', (username,)), **configdict.get('protocolKwArgs', {})) - rlm = TerminalRealm() + rlm = PassAvatarIdTerminalRealm() rlm.transportFactory = TerminalSessionTransport_getPeer rlm.chainedProtocolFactory = chainProtocolFactory factory = ConchFactory(Portal(rlm)) - + try: - # create/get RSA keypair + # create/get RSA keypair publicKey, privateKey = getKeyPair(pubkeyfile, privkeyfile) - factory.publicKeys = {'ssh-rsa': publicKey} + factory.publicKeys = {'ssh-rsa': publicKey} factory.privateKeys = {'ssh-rsa': privateKey} except Exception, e: print " getKeyPair error: %s\n WARNING: Evennia could not auto-generate SSH keypair. Using conch default keys instead." % e @@ -333,6 +372,6 @@ def makeFactory(configdict): factory.services = factory.services.copy() factory.services['ssh-userauth'] = ExtraInfoAuthServer - factory.portal.registerChecker(AnyAuth()) + factory.portal.registerChecker(PlayerDBPasswordChecker()) return factory diff --git a/src/server/telnet.py b/src/server/telnet.py index b3b002faeb..b79491cc72 100644 --- a/src/server/telnet.py +++ b/src/server/telnet.py @@ -105,7 +105,7 @@ class TelnetProtocol(StatefulTelnetProtocol, session.Session): def at_data_out(self, string, data=None): """ - Data Evennia -> Player access hook. 'data' argument is ignored. + Data Evennia -> Player access hook. 'data' argument is a dict parsed for string settings. """ try: string = utils.to_str(string, encoding=self.encoding)