예제 #1
0
        public void HandlePacket(GameClient client, GSPacketIn packet)
        {
            if (client == null)
            {
                return;
            }

            string ipAddress = client.TcpEndpointAddress;

            byte   major;
            byte   minor;
            byte   build;
            string password;
            string userName;

            /// <summary>
            /// Packet Format Change above 1.115
            /// </summary>

            if (client.Version < GameClient.eClientVersion.Version1115)
            {
                packet.Skip(2);                 //Skip the client_type byte

                major    = (byte)packet.ReadByte();
                minor    = (byte)packet.ReadByte();
                build    = (byte)packet.ReadByte();
                password = packet.ReadString(20);


                bool v174;
                //the logger detection we had is no longer working
                //bool loggerUsing = false;
                switch (client.Version)
                {
                case GameClient.eClientVersion.Version168:
                case GameClient.eClientVersion.Version169:
                case GameClient.eClientVersion.Version170:
                case GameClient.eClientVersion.Version171:
                case GameClient.eClientVersion.Version172:
                case GameClient.eClientVersion.Version173:
                    v174 = false;
                    break;

                default:
                    v174 = true;
                    break;
                }

                if (v174)
                {
                    packet.Skip(11);
                }
                else
                {
                    packet.Skip(7);
                }

                uint c2 = packet.ReadInt();
                uint c3 = packet.ReadInt();
                uint c4 = packet.ReadInt();

                if (v174)
                {
                    packet.Skip(27);
                }
                else
                {
                    packet.Skip(31);
                }

                userName = packet.ReadString(20);
            }
            else if (client.Version < GameClient.eClientVersion.Version1126)             // 1.125+ only // we support 1.109 and 1.125+ only
            {
                // client type
                packet.Skip(1);

                //version
                major = (byte)packet.ReadByte();
                minor = (byte)packet.ReadByte();
                build = (byte)packet.ReadByte();

                // revision
                packet.Skip(1);
                // build
                packet.Skip(2);

                if (client.Version <= GameClient.eClientVersion.Version1124)
                {
                    userName = packet.ReadShortPascalStringLowEndian();
                    password = packet.ReadShortPascalStringLowEndian();
                }
                else
                {
                    userName = packet.ReadIntPascalStringLowEndian();
                    password = packet.ReadIntPascalStringLowEndian();
                }
            }
            else
            {
                userName = packet.ReadIntPascalStringLowEndian();
                password = packet.ReadIntPascalStringLowEndian();
            }


            /*
             * if (c2 == 0 && c3 == 0x05000000 && c4 == 0xF4000000)
             * {
             *      loggerUsing = true;
             *      Log.Warn("logger detected (" + username + ")");
             * }*/

            // check server status
            if (GameServer.Instance.ServerStatus == eGameServerStatus.GSS_Closed)
            {
                client.IsConnected = false;
                client.Out.SendLoginDenied(eLoginError.GameCurrentlyClosed);
                Log.Info(ipAddress + " disconnected because game is closed!");
                GameServer.Instance.Disconnect(client);

                return;
            }

            // check connection allowed with serverrules
            try
            {
                if (!GameServer.ServerRules.IsAllowedToConnect(client, userName))
                {
                    if (Log.IsInfoEnabled)
                    {
                        Log.Info(ipAddress + " disconnected because IsAllowedToConnect returned false!");
                    }

                    GameServer.Instance.Disconnect(client);

                    return;
                }
            }
            catch (Exception e)
            {
                if (Log.IsErrorEnabled)
                {
                    Log.Error("Error shutting down Client after IsAllowedToConnect failed!", e);
                }
            }

            // Handle connection
            EnterLock(userName);

            try
            {
                Account playerAccount;
                // Make sure that client won't quit
                lock (client)
                {
                    GameClient.eClientState state = client.ClientState;
                    if (state != GameClient.eClientState.NotConnected)
                    {
                        Log.DebugFormat("wrong client state on connect {0} {1}", userName, state.ToString());
                        return;
                    }

                    if (Log.IsInfoEnabled)
                    {
                        Log.Info(string.Format("({0})User {1} logging on! ({2} type:{3} add:{4})", ipAddress, userName, client.Version,
                                               (client.ClientType), client.ClientAddons.ToString("G")));
                    }
                    // check client already connected
                    GameClient findclient = WorldMgr.GetClientByAccountName(userName, true);
                    if (findclient != null)
                    {
                        client.IsConnected = false;

                        if (findclient.ClientState == GameClient.eClientState.Connecting)
                        {
                            if (Log.IsInfoEnabled)
                            {
                                Log.Info("User is already connecting, ignored.");
                            }

                            client.Out.SendLoginDenied(eLoginError.AccountAlreadyLoggedIn);

                            return;
                        }                         // in login

                        if (findclient.ClientState == GameClient.eClientState.Linkdead)
                        {
                            if (Log.IsInfoEnabled)
                            {
                                Log.Info("User is still being logged out from linkdeath!");
                            }

                            client.Out.SendLoginDenied(eLoginError.AccountIsInLogoutProcedure);
                        }
                        else
                        {
                            if (Log.IsInfoEnabled)
                            {
                                Log.Info("User already logged in!");
                            }

                            client.Out.SendLoginDenied(eLoginError.AccountAlreadyLoggedIn);
                        }

                        GameServer.Instance.Disconnect(client);

                        return;
                    }

                    Regex goodName = new Regex("^[a-zA-Z0-9]*$");
                    if (!goodName.IsMatch(userName) || string.IsNullOrWhiteSpace(userName))
                    {
                        if (Log.IsInfoEnabled)
                        {
                            Log.Info("Invalid symbols in account name \"" + userName + "\" found!");
                        }

                        client.IsConnected = false;
                        if (client != null && client.Out != null)
                        {
                            client.Out.SendLoginDenied(eLoginError.AccountInvalid);
                        }
                        else
                        {
                            Log.Warn("Client or Client.Out null on invalid name failure.  Disconnecting.");
                        }

                        GameServer.Instance.Disconnect(client);

                        return;
                    }
                    else
                    {
                        playerAccount = GameServer.Database.FindObjectByKey <Account>(userName);

                        client.PingTime = DateTime.Now.Ticks;

                        if (playerAccount == null)
                        {
                            //check autocreate ...

                            if (GameServer.Instance.Configuration.AutoAccountCreation && Properties.ALLOW_AUTO_ACCOUNT_CREATION)
                            {
                                // autocreate account
                                if (string.IsNullOrEmpty(password))
                                {
                                    client.IsConnected = false;
                                    client.Out.SendLoginDenied(eLoginError.AccountInvalid);
                                    GameServer.Instance.Disconnect(client);

                                    if (Log.IsInfoEnabled)
                                    {
                                        Log.Info("Account creation failed, no password set for Account: " + userName);
                                    }

                                    return;
                                }

                                // check for account bombing
                                TimeSpan ts;
                                var      allAccByIp = DOLDB <Account> .SelectObjects(DB.Column(nameof(Account.LastLoginIP)).IsEqualTo(ipAddress));

                                int totalacc = 0;
                                foreach (Account ac in allAccByIp)
                                {
                                    ts = DateTime.Now - ac.CreationDate;
                                    if (ts.TotalMinutes < Properties.TIME_BETWEEN_ACCOUNT_CREATION_SAMEIP && totalacc > 1)
                                    {
                                        Log.Warn("Account creation: too many from same IP within set minutes - " + userName + " : " + ipAddress);

                                        client.IsConnected = false;
                                        client.Out.SendLoginDenied(eLoginError.PersonalAccountIsOutOfTime);
                                        GameServer.Instance.Disconnect(client);

                                        return;
                                    }

                                    totalacc++;
                                }
                                if (totalacc >= Properties.TOTAL_ACCOUNTS_ALLOWED_SAMEIP)
                                {
                                    Log.Warn("Account creation: too many accounts created from same ip - " + userName + " : " + ipAddress);

                                    client.IsConnected = false;
                                    client.Out.SendLoginDenied(eLoginError.AccountNoAccessThisGame);
                                    GameServer.Instance.Disconnect(client);

                                    return;
                                }

                                // per timeslice - for preventing account bombing via different ip
                                if (Properties.TIME_BETWEEN_ACCOUNT_CREATION > 0)
                                {
                                    ts = DateTime.Now - m_lastAccountCreateTime;
                                    if (ts.TotalMinutes < Properties.TIME_BETWEEN_ACCOUNT_CREATION)
                                    {
                                        Log.Warn("Account creation: time between account creation too small - " + userName + " : " + ipAddress);

                                        client.IsConnected = false;
                                        client.Out.SendLoginDenied(eLoginError.PersonalAccountIsOutOfTime);
                                        GameServer.Instance.Disconnect(client);

                                        return;
                                    }
                                }

                                m_lastAccountCreateTime = DateTime.Now;

                                playerAccount                   = new Account();
                                playerAccount.Name              = userName;
                                playerAccount.Password          = CryptPassword(password);
                                playerAccount.Realm             = 0;
                                playerAccount.CreationDate      = DateTime.Now;
                                playerAccount.LastLogin         = DateTime.Now;
                                playerAccount.LastLoginIP       = ipAddress;
                                playerAccount.LastClientVersion = ((int)client.Version).ToString();
                                playerAccount.Language          = Properties.SERV_LANGUAGE;
                                playerAccount.PrivLevel         = 1;

                                if (Log.IsInfoEnabled)
                                {
                                    Log.Info("New account created: " + userName);
                                }

                                GameServer.Database.AddObject(playerAccount);

                                // Log account creation
                                AuditMgr.AddAuditEntry(client, AuditType.Account, AuditSubtype.AccountCreate, "", userName);
                            }
                            else
                            {
                                if (Log.IsInfoEnabled)
                                {
                                    Log.Info("No such account found and autocreation deactivated!");
                                }

                                client.IsConnected = false;
                                client.Out.SendLoginDenied(eLoginError.AccountNotFound);
                                GameServer.Instance.Disconnect(client);

                                return;
                            }
                        }
                        else
                        {
                            // check password
                            if (!playerAccount.Password.StartsWith("##"))
                            {
                                playerAccount.Password = CryptPassword(playerAccount.Password);
                            }

                            if (!CryptPassword(password).Equals(playerAccount.Password))
                            {
                                if (Log.IsInfoEnabled)
                                {
                                    Log.Info("(" + client.TcpEndpoint + ") Wrong password!");
                                }

                                client.IsConnected = false;
                                client.Out.SendLoginDenied(eLoginError.WrongPassword);

                                // Log failure
                                AuditMgr.AddAuditEntry(client, AuditType.Account, AuditSubtype.AccountFailedLogin, "", userName);

                                GameServer.Instance.Disconnect(client);

                                return;
                            }

                            // save player infos
                            playerAccount.LastLogin         = DateTime.Now;
                            playerAccount.LastLoginIP       = ipAddress;
                            playerAccount.LastClientVersion = ((int)client.Version).ToString();
                            if (string.IsNullOrEmpty(playerAccount.Language))
                            {
                                playerAccount.Language = Properties.SERV_LANGUAGE;
                            }

                            GameServer.Database.SaveObject(playerAccount);
                        }
                    }

                    //Save the account table
                    client.Account = playerAccount;

                    // create session ID here to disable double login bug
                    if (WorldMgr.CreateSessionID(client) < 0)
                    {
                        if (Log.IsInfoEnabled)
                        {
                            Log.InfoFormat("Too many clients connected, denied login to " + playerAccount.Name);
                        }

                        client.IsConnected = false;
                        client.Out.SendLoginDenied(eLoginError.TooManyPlayersLoggedIn);
                        client.Disconnect();

                        return;
                    }

                    client.Out.SendLoginGranted();
                    client.ClientState = GameClient.eClientState.Connecting;

                    // Log entry
                    AuditMgr.AddAuditEntry(client, AuditType.Account, AuditSubtype.AccountSuccessfulLogin, "", userName);
                }
            }
            catch (DatabaseException e)
            {
                if (Log.IsErrorEnabled)
                {
                    Log.Error("LoginRequestHandler", e);
                }

                client.IsConnected = false;
                client.Out.SendLoginDenied(eLoginError.CannotAccessUserAccount);
                GameServer.Instance.Disconnect(client);
            }
            catch (Exception e)
            {
                if (Log.IsErrorEnabled)
                {
                    Log.Error("LoginRequestHandler", e);
                }

                client.Out.SendLoginDenied(eLoginError.CannotAccessUserAccount);
                GameServer.Instance.Disconnect(client);
            }
            finally
            {
                ExitLock(userName);
            }
        }
예제 #2
0
        public void HandlePacket(GameClient client, GSPacketIn packet)
        {
            if (client == null)
            {
                return;
            }

            string ipAddress = client.TcpEndpointAddress;

            byte   major;
            byte   minor;
            byte   build;
            string password;
            string userName;

            if (client.Version >= GameClient.eClientVersion.Version1126)
            {
                // Read Login
                userName = packet.ReadIntPascalStringLowEndian();

                // Read Password
                password = packet.ReadIntPascalStringLowEndian();
            }
            else if (client.Version == GameClient.eClientVersion.Version1125)
            {
                // 1.125

                // client type
                packet.Skip(1);

                //version
                major = (byte)packet.ReadByte();
                minor = (byte)packet.ReadByte();
                build = (byte)packet.ReadByte();

                // revision
                packet.Skip(1);
                // build
                packet.Skip(2);

                // Read Login
                userName = packet.ReadIntPascalStringLowEndian();

                // Read Password
                password = packet.ReadIntPascalStringLowEndian();
            }
            else
            {
                // 1.115c - 1.124

                // client type
                packet.Skip(1);

                //version
                major = (byte)packet.ReadByte();
                minor = (byte)packet.ReadByte();
                build = (byte)packet.ReadByte();

                // revision
                packet.Skip(1);
                // build
                packet.Skip(2);

                // Read Login
                userName = packet.ReadShortPascalStringLowEndian();

                // Read Password
                password = packet.ReadShortPascalStringLowEndian();
            }

            // check server status
            if (GameServer.Instance.ServerStatus == eGameServerStatus.GSS_Closed)
            {
                client.IsConnected = false;
                client.Out.SendLoginDenied(eLoginError.GameCurrentlyClosed);
                log.Info(ipAddress + " disconnected because game is closed!");
                GameServer.Instance.Disconnect(client);

                return;
            }

            // check connection allowed with serverrules
            try
            {
                if (!GameServer.ServerRules.IsAllowedToConnect(client, userName))
                {
                    if (log.IsInfoEnabled)
                    {
                        log.Info($"{ipAddress} disconnected because IsAllowedToConnect returned false!");
                    }

                    GameServer.Instance.Disconnect(client);

                    return;
                }
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled)
                {
                    log.Error("Error shutting down Client after IsAllowedToConnect failed!", e);
                }
            }

            // Handle connection
            EnterLock(userName);

            try
            {
                // Make sure that client won't quit
                lock (client)
                {
                    GameClient.eClientState state = client.ClientState;
                    if (state != GameClient.eClientState.NotConnected)
                    {
                        log.Debug($"wrong client state on connect {userName} {state}");
                        return;
                    }

                    if (log.IsInfoEnabled)
                    {
                        log.Info($"({ipAddress})User {userName} logging on! ({client.Version} type:{client.ClientType} add:{client.ClientAddons:G})");
                    }

                    // check client already connected
                    GameClient findclient = WorldMgr.GetClientByAccountName(userName, true);
                    if (findclient != null)
                    {
                        client.IsConnected = false;

                        if (findclient.ClientState == GameClient.eClientState.Connecting)
                        {
                            if (log.IsInfoEnabled)
                            {
                                log.Info("User is already connecting, ignored.");
                            }

                            client.Out.SendLoginDenied(eLoginError.AccountAlreadyLoggedIn);

                            return;
                        } // in login

                        if (findclient.ClientState == GameClient.eClientState.Linkdead)
                        {
                            if (log.IsInfoEnabled)
                            {
                                log.Info("User is still being logged out from linkdeath!");
                            }

                            client.Out.SendLoginDenied(eLoginError.AccountIsInLogoutProcedure);
                        }
                        else
                        {
                            if (log.IsInfoEnabled)
                            {
                                log.Info("User already logged in!");
                            }

                            client.Out.SendLoginDenied(eLoginError.AccountAlreadyLoggedIn);
                        }

                        GameServer.Instance.Disconnect(client);

                        return;
                    }

                    Regex   goodName = new Regex("^[a-zA-Z0-9]*$");
                    Account playerAccount;
                    if (!goodName.IsMatch(userName) || string.IsNullOrWhiteSpace(userName))
                    {
                        if (log.IsInfoEnabled)
                        {
                            log.Info($"Invalid symbols in account name \"{userName}\" found!");
                        }

                        client.IsConnected = false;
                        if (client.Out != null)
                        {
                            client.Out.SendLoginDenied(eLoginError.AccountInvalid);
                        }
                        else
                        {
                            log.Warn("Client or Client.Out null on invalid name failure.  Disconnecting.");
                        }

                        GameServer.Instance.Disconnect(client);

                        return;
                    }
                    else
                    {
                        playerAccount = GameServer.Database.FindObjectByKey <Account>(userName);

                        client.PingTime = DateTime.Now.Ticks;

                        if (playerAccount == null)
                        {
                            // check autocreate ...
                            if (GameServer.Instance.Configuration.AutoAccountCreation && Properties.ALLOW_AUTO_ACCOUNT_CREATION)
                            {
                                // autocreate account
                                if (string.IsNullOrEmpty(password))
                                {
                                    client.IsConnected = false;
                                    client.Out.SendLoginDenied(eLoginError.AccountInvalid);
                                    GameServer.Instance.Disconnect(client);

                                    if (log.IsInfoEnabled)
                                    {
                                        log.Info($"Account creation failed, no password set for Account: {userName}");
                                    }

                                    return;
                                }

                                // check for account bombing
                                TimeSpan        ts;
                                IList <Account> allAccByIp = GameServer.Database.SelectObjects <Account>("`LastLoginIP` = @LastLoginIP", new QueryParameter("@LastLoginIP", ipAddress));
                                int             totalacc   = 0;
                                foreach (Account ac in allAccByIp)
                                {
                                    ts = DateTime.Now - ac.CreationDate;
                                    if (ts.TotalMinutes < Properties.TIME_BETWEEN_ACCOUNT_CREATION_SAMEIP && totalacc > 1)
                                    {
                                        log.Warn($"Account creation: too many from same IP within set minutes - {userName} : {ipAddress}");

                                        client.IsConnected = false;
                                        client.Out.SendLoginDenied(eLoginError.PersonalAccountIsOutOfTime);
                                        GameServer.Instance.Disconnect(client);

                                        return;
                                    }

                                    totalacc++;
                                }

                                if (totalacc >= Properties.TOTAL_ACCOUNTS_ALLOWED_SAMEIP)
                                {
                                    log.Warn($"Account creation: too many accounts created from same ip - {userName} : {ipAddress}");

                                    client.IsConnected = false;
                                    client.Out.SendLoginDenied(eLoginError.AccountNoAccessThisGame);
                                    GameServer.Instance.Disconnect(client);

                                    return;
                                }

                                // per timeslice - for preventing account bombing via different ip
                                if (Properties.TIME_BETWEEN_ACCOUNT_CREATION > 0)
                                {
                                    ts = DateTime.Now - _lastAccountCreateTime;
                                    if (ts.TotalMinutes < Properties.TIME_BETWEEN_ACCOUNT_CREATION)
                                    {
                                        log.Warn($"Account creation: time between account creation too small - {userName} : {ipAddress}");

                                        client.IsConnected = false;
                                        client.Out.SendLoginDenied(eLoginError.PersonalAccountIsOutOfTime);
                                        GameServer.Instance.Disconnect(client);

                                        return;
                                    }
                                }

                                _lastAccountCreateTime = DateTime.Now;

                                playerAccount = new Account
                                {
                                    Name              = userName,
                                    Password          = CryptPassword(password),
                                    Realm             = 0,
                                    CreationDate      = DateTime.Now,
                                    LastLogin         = DateTime.Now,
                                    LastLoginIP       = ipAddress,
                                    LastClientVersion = ((int)client.Version).ToString(),
                                    Language          = Properties.SERV_LANGUAGE,
                                    PrivLevel         = 1
                                };

                                if (log.IsInfoEnabled)
                                {
                                    log.Info($"New account created: {userName}");
                                }

                                GameServer.Database.AddObject(playerAccount);

                                // Log account creation
                                AuditMgr.AddAuditEntry(client, AuditType.Account, AuditSubtype.AccountCreate, string.Empty, userName);
                            }
                            else
                            {
                                if (log.IsInfoEnabled)
                                {
                                    log.Info("No such account found and autocreation deactivated!");
                                }

                                client.IsConnected = false;
                                client.Out.SendLoginDenied(eLoginError.AccountNotFound);
                                GameServer.Instance.Disconnect(client);

                                return;
                            }
                        }
                        else
                        {
                            // check password
                            if (!playerAccount.Password.StartsWith("##"))
                            {
                                playerAccount.Password = CryptPassword(playerAccount.Password);
                            }

                            if (!CryptPassword(password).Equals(playerAccount.Password))
                            {
                                if (log.IsInfoEnabled)
                                {
                                    log.Info($"({client.TcpEndpoint}) Wrong password!");
                                }

                                client.IsConnected = false;
                                client.Out.SendLoginDenied(eLoginError.WrongPassword);

                                // Log failure
                                AuditMgr.AddAuditEntry(client, AuditType.Account, AuditSubtype.AccountFailedLogin, string.Empty, userName);

                                GameServer.Instance.Disconnect(client);

                                return;
                            }

                            // save player infos
                            playerAccount.LastLogin         = DateTime.Now;
                            playerAccount.LastLoginIP       = ipAddress;
                            playerAccount.LastClientVersion = ((int)client.Version).ToString();
                            if (string.IsNullOrEmpty(playerAccount.Language))
                            {
                                playerAccount.Language = Properties.SERV_LANGUAGE;
                            }

                            GameServer.Database.SaveObject(playerAccount);
                        }
                    }

                    // Save the account table
                    client.Account = playerAccount;

                    // create session ID here to disable double login bug
                    if (WorldMgr.CreateSessionID(client) < 0)
                    {
                        if (log.IsInfoEnabled)
                        {
                            log.InfoFormat("Too many clients connected, denied login to {0}", playerAccount.Name);
                        }

                        client.IsConnected = false;
                        client.Out.SendLoginDenied(eLoginError.TooManyPlayersLoggedIn);
                        client.Disconnect();

                        return;
                    }

                    client.Out.SendLoginGranted();
                    client.ClientState = GameClient.eClientState.Connecting;

                    // Log entry
                    AuditMgr.AddAuditEntry(client, AuditType.Account, AuditSubtype.AccountSuccessfulLogin, string.Empty, userName);
                }
            }
            catch (DatabaseException e)
            {
                if (log.IsErrorEnabled)
                {
                    log.Error("LoginRequestHandler", e);
                }

                client.IsConnected = false;
                client.Out.SendLoginDenied(eLoginError.CannotAccessUserAccount);
                GameServer.Instance.Disconnect(client);
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled)
                {
                    log.Error("LoginRequestHandler", e);
                }

                client.Out.SendLoginDenied(eLoginError.CannotAccessUserAccount);
                GameServer.Instance.Disconnect(client);
            }
            finally
            {
                ExitLock(userName);
            }
        }