From b752006d6f7cc992f3ed775d5b3d570d047e5e10 Mon Sep 17 00:00:00 2001 From: MagicBot Date: Sun, 31 Mar 2024 10:09:32 -0400 Subject: [PATCH] Handlers created for VersionInfoMsg and ClientLoginInfoMsg --- .../handlers/ClientLoginInfoMsgHandler.java | 172 ++++++++++++++++ .../handlers/VersionInfoMsgHandler.java | 76 +++++++ src/engine/server/login/LoginServer.java | 4 +- .../server/login/LoginServerMsgHandler.java | 190 +----------------- 4 files changed, 255 insertions(+), 187 deletions(-) create mode 100644 src/engine/net/client/handlers/ClientLoginInfoMsgHandler.java create mode 100644 src/engine/net/client/handlers/VersionInfoMsgHandler.java diff --git a/src/engine/net/client/handlers/ClientLoginInfoMsgHandler.java b/src/engine/net/client/handlers/ClientLoginInfoMsgHandler.java new file mode 100644 index 00000000..c19c5045 --- /dev/null +++ b/src/engine/net/client/handlers/ClientLoginInfoMsgHandler.java @@ -0,0 +1,172 @@ +// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . +// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· +// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ +// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ +// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ +// Magicbane Emulator Project © 2013 - 2022 +// www.magicbane.com + +package engine.net.client.handlers; + +import engine.Enum; +import engine.exception.MsgSendException; +import engine.gameManager.ConfigManager; +import engine.gameManager.DbManager; +import engine.gameManager.SessionManager; +import engine.net.client.ClientConnection; +import engine.net.client.msg.ClientNetMsg; +import engine.net.client.msg.login.ClientLoginInfoMsg; +import engine.objects.Account; +import engine.objects.PlayerCharacter; +import engine.server.MBServerStatics; +import engine.server.login.LoginServer; +import engine.server.login.LoginServerMsgHandler; +import engine.session.Session; +import org.pmw.tinylog.Logger; + +public class ClientLoginInfoMsgHandler extends AbstractClientMsgHandler { + + public ClientLoginInfoMsgHandler() { + super(ClientLoginInfoMsg.class); + } + + @Override + protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException { + + PlayerCharacter playerCharacter = origin.getPlayerCharacter(); + + // Member variable declaration + + ClientLoginInfoMsg msg; + + // Member variable assignment + + msg = (ClientLoginInfoMsg) baseMsg; + + // Add zero length strings to eliminate the need for null checking. + String uname = msg.getUname(); + String pass = msg.getPword(); + + // Check to see if there is actually any data in uname.pass + if (uname.length() == 0) { + LoginServerMsgHandler.KickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, "The username provided was zero length.", origin); + return true; + } + + if (pass.length() == 0) { + LoginServerMsgHandler.KickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, "The password provided was zero length.", origin); + return true; + } + + if (LoginServer.loginServerRunning == false) { + LoginServerMsgHandler.KickToLogin(MBServerStatics.LOGINERROR_LOGINSERVER_BUSY, "", origin); + return true; + } + + Account account; + + account = DbManager.AccountQueries.GET_ACCOUNT(uname); + + // Create the account if it doesn't exist and MB_LOGIN_AUTOREG is TRUE; + // This is to support MagicBox users without a web hosting skillset. + + if (account == null) { + + if (ConfigManager.MB_LOGIN_AUTOREG.getValue().equalsIgnoreCase("false")) { + LoginServerMsgHandler.KickToLogin(MBServerStatics.LOGINERROR_INVALID_USERNAME_PASSWORD, "Could not find account (" + uname + ')', origin); + Logger.info("Could not find account (" + uname + ')'); + return true; + } + + Logger.info("AutoRegister: " + uname + "/" + pass); + DbManager.AccountQueries.CREATE_SINGLE(uname, pass); + account = DbManager.AccountQueries.GET_ACCOUNT(uname); + + if (account == null) { + LoginServerMsgHandler.KickToLogin(MBServerStatics.LOGINERROR_INVALID_USERNAME_PASSWORD, "Could not find account (" + uname + ')', origin); + Logger.info("Could not auto-create (" + uname + ')'); + return true; + } + } + + if (account.getLastLoginFailure() + MBServerStatics.RESET_LOGIN_ATTEMPTS_AFTER < System.currentTimeMillis()) + account.resetLoginAttempts(); + + // TODO: Log the login attempts IP, name, password and timestamp + // Check number invalid login attempts. If 5 or greater, kick to login. + if (account.getLoginAttempts() >= MBServerStatics.MAX_LOGIN_ATTEMPTS) { + + LoginServerMsgHandler.KickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, "Too many login in attempts for '" + uname + '\'', origin); + Logger.info("Too many login in attempts for '" + uname + '\''); + return true; + } + + if (account.lastPasswordCheck < System.currentTimeMillis()) { + account.lastPasswordCheck = System.currentTimeMillis() + MBServerStatics.ONE_MINUTE; + } + + // Attempt to validate login + try { + if (!account.passIsValid(pass, origin.getClientIpAddress(), origin.machineID)) { + + account.incrementLoginAttempts(); + LoginServerMsgHandler.KickToLogin(MBServerStatics.LOGINERROR_INVALID_USERNAME_PASSWORD, "", origin); + Logger.info("Incorrect password(" + uname + ')'); + return true; + } + } catch (IllegalArgumentException e1) { + LoginServerMsgHandler.KickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, "", origin); + Logger.info("Failed forum account validation(" + uname + ')'); + } + + // Account deactivated + + if (account.status.equals(Enum.AccountStatus.BANNED)) { + LoginServerMsgHandler.KickToLogin(MBServerStatics.LOGINERROR_NO_MORE_PLAYTIME_ON_ACCOUNT, "", origin); + return true; + } + + // Check to see if we have a Session mapped with this Account: + Session session = SessionManager.getSession(account); + + // If there is, then the account is in use and must be handled: + // kick the 'other connection' + if (session != null) + LoginServerMsgHandler.KickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, "Your account has been accessed from a different IP & Port.", session.getConn()); // Logout the character + + + // TODO implement character logout + // Get a new session + session = SessionManager.getNewSession(account, origin); + + // Set Invalid Login Attempts to 0 + account.resetLoginAttempts(); + + // Send Login Response + ClientLoginInfoMsg loginResponse = new ClientLoginInfoMsg(msg); + loginResponse.setUnknown06(8323072); + loginResponse.setUnknown07(3276800); + loginResponse.setUnknown08(196608); + loginResponse.setUnknown09((short) 15); + + origin.sendMsg(loginResponse); + + // send character select screen + try { + LoginServerMsgHandler.sendCharacterSelectScreen(session); + } catch (Exception e) { + Logger.error("Unable to Send Character Select Screen to client"); + LoginServerMsgHandler.KickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, "Unable to send Character Select Screen to client.", origin); + return true; + } + + // Logging + String addyPort = origin.getRemoteAddressAndPortAsString(); + int id = account.getObjectUUID(); + + Logger.info(uname + '(' + id + ") has successfully logged in from " + addyPort); + + return true; + } + +} \ No newline at end of file diff --git a/src/engine/net/client/handlers/VersionInfoMsgHandler.java b/src/engine/net/client/handlers/VersionInfoMsgHandler.java new file mode 100644 index 00000000..7305c47d --- /dev/null +++ b/src/engine/net/client/handlers/VersionInfoMsgHandler.java @@ -0,0 +1,76 @@ +// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ . +// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌· +// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀ +// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌ +// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀ +// Magicbane Emulator Project © 2013 - 2022 +// www.magicbane.com + +package engine.net.client.handlers; + +import engine.exception.MsgSendException; +import engine.net.client.ClientConnection; +import engine.net.client.msg.ClientNetMsg; +import engine.net.client.msg.login.VersionInfoMsg; +import engine.objects.PlayerCharacter; +import engine.server.MBServerStatics; +import engine.server.login.LoginServer; +import engine.server.login.LoginServerMsgHandler; + +public class VersionInfoMsgHandler extends AbstractClientMsgHandler { + + public VersionInfoMsgHandler() { + super(VersionInfoMsg.class); + } + + @Override + protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) throws MsgSendException { + + PlayerCharacter playerCharacter = origin.getPlayerCharacter(); + String cMajorVer; + String cMinorVer; + VersionInfoMsg outVim; + + // Member variable declaration + + VersionInfoMsg msg; + + // Member variable assignment + + msg = (VersionInfoMsg) baseMsg; + + cMajorVer = msg.getMajorVersion(); + cMinorVer = msg.getMinorVersion(); + + if (!cMajorVer.equals(LoginServer.getDefaultVersionInfo().getMajorVersion())) { + LoginServerMsgHandler.KickToLogin(MBServerStatics.LOGINERROR_INCORRECT_CLIENT_VERSION, "Major Version Failure: " + cMajorVer, origin); + return true; + } + + /* if (!cMinorVer.equals(this.server.getDefaultVersionInfo().getMinorVersion())) { + this.KickToLogin(MBServerStatics.LOGINERROR_INCORRECT_CLIENT_VERSION, "Minor Version Failure: " + cMinorVer, cc); + return; + } */ + + if (cMinorVer == null) { + LoginServerMsgHandler.KickToLogin(MBServerStatics.LOGINERROR_INCORRECT_CLIENT_VERSION, "Minor Version Failure: ", origin); + return true; + } + + if (cMinorVer.length() < 8 || cMinorVer.length() > 16) { + LoginServerMsgHandler.KickToLogin(MBServerStatics.LOGINERROR_INCORRECT_CLIENT_VERSION, "Minor Version Failure: ", origin); + return true; + } + + // set MachineID for this connection + + origin.machineID = cMinorVer; + + // send fake right back to the client + outVim = new VersionInfoMsg(msg.getMajorVersion(), LoginServer.getDefaultVersionInfo().getMinorVersion()); + origin.sendMsg(outVim); + + return true; + } + +} \ No newline at end of file diff --git a/src/engine/server/login/LoginServer.java b/src/engine/server/login/LoginServer.java index caed89c9..4b0eef28 100644 --- a/src/engine/server/login/LoginServer.java +++ b/src/engine/server/login/LoginServer.java @@ -55,7 +55,7 @@ public class LoginServer { public static boolean worldServerRunning = false; public static boolean loginServerRunning = false; public static ServerStatusMsg serverStatusMsg = new ServerStatusMsg(0, (byte) 1); - private VersionInfoMsg versionInfoMessage; + private static VersionInfoMsg versionInfoMessage; // This is the entrypoint for the MagicBane Login Server when // it is executed by the command line scripts. The fun begins here! @@ -365,7 +365,7 @@ public class LoginServer { } } - public VersionInfoMsg getDefaultVersionInfo() { + public static VersionInfoMsg getDefaultVersionInfo() { return versionInfoMessage; } diff --git a/src/engine/server/login/LoginServerMsgHandler.java b/src/engine/server/login/LoginServerMsgHandler.java index 81ee5470..cf76cf5a 100644 --- a/src/engine/server/login/LoginServerMsgHandler.java +++ b/src/engine/server/login/LoginServerMsgHandler.java @@ -9,10 +9,8 @@ package engine.server.login; -import engine.Enum; import engine.Enum.DispatchChannel; import engine.Enum.GameObjectType; -import engine.gameManager.ConfigManager; import engine.gameManager.DbManager; import engine.gameManager.SessionManager; import engine.job.JobScheduler; @@ -75,23 +73,6 @@ public class LoginServerMsgHandler implements NetMsgHandler { try { switch (protocolMsg) { - - case VERSIONINFO: - this.VerifyCorrectClientVersion((VersionInfoMsg) clientNetMsg); - break; - - case LOGIN: - if (LoginServer.loginServerRunning == true) - this.Login((ClientLoginInfoMsg) clientNetMsg, origin); - else - this.KickToLogin(MBServerStatics.LOGINERROR_LOGINSERVER_BUSY, "", origin); - break; - - case KEEPALIVESERVERCLIENT: - // echo the keep alive back - origin.sendMsg(clientNetMsg); - break; - case SELECTSERVER: this.SendServerInfo(origin); break; @@ -126,169 +107,8 @@ public class LoginServerMsgHandler implements NetMsgHandler { return true; } - private void VerifyCorrectClientVersion(VersionInfoMsg vim) { - ClientConnection cc; - String cMajorVer; - String cMinorVer; - VersionInfoMsg outVim; - - cc = (ClientConnection) vim.getOrigin(); - cMajorVer = vim.getMajorVersion(); - cMinorVer = vim.getMinorVersion(); - - // if (!cMajorVer.equals(this.server.getDefaultVersionInfo().getMajorVersion())) { - // this.KickToLogin(MBServerStatics.LOGINERROR_INCORRECT_CLIENT_VERSION, "Major Version Failure: " + cMajorVer, cc); - // return; - // } - - /* if (!cMinorVer.equals(this.server.getDefaultVersionInfo().getMinorVersion())) { - this.KickToLogin(MBServerStatics.LOGINERROR_INCORRECT_CLIENT_VERSION, "Minor Version Failure: " + cMinorVer, cc); - return; - } */ - - // if (cMinorVer == null) { - // this.KickToLogin(MBServerStatics.LOGINERROR_INCORRECT_CLIENT_VERSION, "Minor Version Failure: ", cc); - // return; - // } - - // if (cMinorVer.length() < 8 || cMinorVer.length() > 16) { - // this.KickToLogin(MBServerStatics.LOGINERROR_INCORRECT_CLIENT_VERSION, "Minor Version Failure: ", cc); - // return; - // } - - // set MachineID for this connection - - cc.machineID = cMinorVer; - - // send fake right back to the client - outVim = new VersionInfoMsg(vim.getMajorVersion(), this.server.getDefaultVersionInfo().getMinorVersion()); - cc.sendMsg(outVim); - } - - // our data access should be in a separate object - private void Login(ClientLoginInfoMsg clientLoginInfoMessage, ClientConnection clientConnection) { - - // Add zero length strings to eliminate the need for null checking. - String uname = clientLoginInfoMessage.getUname(); - String pass = clientLoginInfoMessage.getPword(); - - // Check to see if there is actually any data in uname.pass - if (uname.length() == 0) { - this.KickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, "The username provided was zero length.", clientConnection); - return; - } - - if (pass.length() == 0) { - this.KickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, "The password provided was zero length.", clientConnection); - return; - } - - Account account; - - account = DbManager.AccountQueries.GET_ACCOUNT(uname); - - // Create the account if it doesn't exist and MB_LOGIN_AUTOREG is TRUE; - // This is to support MagicBox users without a web hosting skillset. - - if (account == null) { - - if (ConfigManager.MB_LOGIN_AUTOREG.getValue().equalsIgnoreCase("false")) { - this.KickToLogin(MBServerStatics.LOGINERROR_INVALID_USERNAME_PASSWORD, "Could not find account (" + uname + ')', clientConnection); - Logger.info("Could not find account (" + uname + ')'); - return; - } - - Logger.info("AutoRegister: " + uname + "/" + pass); - DbManager.AccountQueries.CREATE_SINGLE(uname, pass); - account = DbManager.AccountQueries.GET_ACCOUNT(uname); - - if (account == null) { - this.KickToLogin(MBServerStatics.LOGINERROR_INVALID_USERNAME_PASSWORD, "Could not find account (" + uname + ')', clientConnection); - Logger.info("Could not auto-create (" + uname + ')'); - return; - } - } - - if (account.getLastLoginFailure() + MBServerStatics.RESET_LOGIN_ATTEMPTS_AFTER < System.currentTimeMillis()) - account.resetLoginAttempts(); - - // TODO: Log the login attempts IP, name, password and timestamp - // Check number invalid login attempts. If 5 or greater, kick to login. - if (account.getLoginAttempts() >= MBServerStatics.MAX_LOGIN_ATTEMPTS) { - - this.KickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, "Too many login in attempts for '" + uname + '\'', clientConnection); - Logger.info("Too many login in attempts for '" + uname + '\''); - return; - } - - if (account.lastPasswordCheck < System.currentTimeMillis()) { - account.lastPasswordCheck = System.currentTimeMillis() + MBServerStatics.ONE_MINUTE; - } - - // Attempt to validate login - try { - if (!account.passIsValid(pass, clientConnection.getClientIpAddress(), clientConnection.machineID)) { - - account.incrementLoginAttempts(); - this.KickToLogin(MBServerStatics.LOGINERROR_INVALID_USERNAME_PASSWORD, "", clientConnection); - Logger.info("Incorrect password(" + uname + ')'); - return; - } - } catch (IllegalArgumentException e1) { - this.KickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, "", clientConnection); - Logger.info("Failed forum account validation(" + uname + ')'); - } - - // Account deactivated - - if (account.status.equals(Enum.AccountStatus.BANNED)) { - this.KickToLogin(MBServerStatics.LOGINERROR_NO_MORE_PLAYTIME_ON_ACCOUNT, "", clientConnection); - return; - } - - // Check to see if we have a Session mapped with this Account: - Session session = SessionManager.getSession(account); - - // If there is, then the account is in use and must be handled: - // kick the 'other connection' - if (session != null) - this.KickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, "Your account has been accessed from a different IP & Port.", session.getConn()); // Logout the character - - - // TODO implement character logout - // Get a new session - session = SessionManager.getNewSession(account, clientConnection); - - // Set Invalid Login Attempts to 0 - account.resetLoginAttempts(); - - // Send Login Response - ClientLoginInfoMsg loginResponse = new ClientLoginInfoMsg(clientLoginInfoMessage); - loginResponse.setUnknown06(8323072); - loginResponse.setUnknown07(3276800); - loginResponse.setUnknown08(196608); - loginResponse.setUnknown09((short) 15); - - clientConnection.sendMsg(loginResponse); - - // send character select screen - try { - this.sendCharacterSelectScreen(session); - } catch (Exception e) { - Logger.error("Unable to Send Character Select Screen to client"); - this.KickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, "Unable to send Character Select Screen to client.", clientConnection); - return; - } - - // Logging - String addyPort = clientConnection.getRemoteAddressAndPortAsString(); - int id = account.getObjectUUID(); - - Logger.info(uname + '(' + id + ") has successfully logged in from " + addyPort); - - } - private void KickToLogin(int errCode, String message, ClientConnection origin) { + public static void KickToLogin(int errCode, String message, ClientConnection origin) { LoginErrorMsg msg = new LoginErrorMsg(errCode, message); PlayerCharacter player = origin.getPlayerCharacter(); @@ -307,18 +127,18 @@ public class LoginServerMsgHandler implements NetMsgHandler { JobScheduler.getInstance().scheduleJob(dj, 250); } - protected void sendCharacterSelectScreen(Session s) { + public static void sendCharacterSelectScreen(Session s) { sendCharacterSelectScreen(s, false); } - private void sendCharacterSelectScreen(Session s, boolean fromCommit) { + private static void sendCharacterSelectScreen(Session s, boolean fromCommit) { if (s.getAccount() != null) { CharSelectScreenMsg cssm = new CharSelectScreenMsg(s, fromCommit); s.getConn().sendMsg(cssm); } else { Logger.error("No Account Found: Unable to Send Character Select Screen"); - this.KickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, "Unable to send Character Select Screen to client.", s.getConn()); + LoginServerMsgHandler.KickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, "Unable to send Character Select Screen to client.", s.getConn()); } } @@ -430,7 +250,7 @@ public class LoginServerMsgHandler implements NetMsgHandler { if (player == null) { Logger.info("Unable to find character ID " + gameServerIPRequestMessage.getCharacterUUID()); - this.KickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, "PlayerCharacter lookup failed in .RequestGameServer().", conn); + KickToLogin(MBServerStatics.LOGINERROR_UNABLE_TO_LOGIN, "PlayerCharacter lookup failed in .RequestGameServer().", conn); return; }