Exemple #1
0
        public void HandleLoginRequest(HttpHeader request)
        {
            LogonData   loginForm   = Json.CreateObject <LogonData>(request.Content);
            LogonResult loginResult = new LogonResult();

            if (loginForm == null)
            {
                loginResult.AuthenticationState = "LOGIN";
                loginResult.ErrorCode           = "UNABLE_TO_DECODE";
                loginResult.ErrorMessage        = "There was an internal error while connecting to Battle.net. Please try again later.";
                SendResponse(HttpCode.BadRequest, loginResult);
                return;
            }

            string login    = "";
            string password = "";

            for (int i = 0; i < loginForm.Inputs.Count; ++i)
            {
                switch (loginForm.Inputs[i].Id)
                {
                case "account_name":
                    login = loginForm.Inputs[i].Value;
                    break;

                case "password":
                    password = loginForm.Inputs[i].Value;
                    break;
                }
            }

            PreparedStatement stmt = DB.Login.GetPreparedStatement(LoginStatements.SEL_BNET_ACCOUNT_INFO);

            stmt.AddValue(0, login);

            SQLResult result = DB.Login.Query(stmt);

            if (result.IsEmpty())
            {
                loginResult.AuthenticationState = "LOGIN";
                loginResult.ErrorCode           = "UNABLE_TO_DECODE";
                loginResult.ErrorMessage        = "There was an internal error while connecting to Battle.net. Please try again later.";
                SendResponse(HttpCode.BadRequest, loginResult);

                return;
            }

            string pass_hash = result.Read <string>(13);

            var accountInfo = new AccountInfo();

            accountInfo.LoadResult(result);

            if (CalculateShaPassHash(login, password) == pass_hash)
            {
                stmt = DB.Login.GetPreparedStatement(LoginStatements.SEL_BNET_CHARACTER_COUNTS_BY_BNET_ID);
                stmt.AddValue(0, accountInfo.Id);

                SQLResult characterCountsResult = DB.Login.Query(stmt);
                if (!characterCountsResult.IsEmpty())
                {
                    do
                    {
                        accountInfo.GameAccounts[characterCountsResult.Read <uint>(0)]
                        .CharacterCounts[new RealmHandle(characterCountsResult.Read <byte>(3), characterCountsResult.Read <byte>(4), characterCountsResult.Read <uint>(2)).GetAddress()] = characterCountsResult.Read <byte>(1);
                    } while (characterCountsResult.NextRow());
                }


                stmt = DB.Login.GetPreparedStatement(LoginStatements.SEL_BNET_LAST_PLAYER_CHARACTERS);
                stmt.AddValue(0, accountInfo.Id);

                SQLResult lastPlayerCharactersResult = DB.Login.Query(stmt);
                if (!lastPlayerCharactersResult.IsEmpty())
                {
                    RealmHandle realmId = new RealmHandle(lastPlayerCharactersResult.Read <byte>(1), lastPlayerCharactersResult.Read <byte>(2), lastPlayerCharactersResult.Read <uint>(3));

                    LastPlayedCharacterInfo lastPlayedCharacter = new LastPlayedCharacterInfo();
                    lastPlayedCharacter.RealmId        = realmId;
                    lastPlayedCharacter.CharacterName  = lastPlayerCharactersResult.Read <string>(4);
                    lastPlayedCharacter.CharacterGUID  = lastPlayerCharactersResult.Read <ulong>(5);
                    lastPlayedCharacter.LastPlayedTime = lastPlayerCharactersResult.Read <uint>(6);

                    accountInfo.GameAccounts[lastPlayerCharactersResult.Read <uint>(0)].LastPlayedCharacters[realmId.GetSubRegionAddress()] = lastPlayedCharacter;
                }

                byte[] ticket = new byte[0].GenerateRandomKey(20);
                loginResult.LoginTicket = "TC-" + ticket.ToHexString();

                Global.SessionMgr.AddLoginTicket(loginResult.LoginTicket, accountInfo);
            }
            else if (!accountInfo.IsBanned)
            {
                uint maxWrongPassword = ConfigMgr.GetDefaultValue("WrongPass.MaxCount", 0u);

                if (ConfigMgr.GetDefaultValue("WrongPass.Logging", false))
                {
                    Log.outDebug(LogFilter.Network, "[{0}, Account {1}, Id {2}] Attempted to connect with wrong password!", request.Host, login, accountInfo.Id);
                }

                if (maxWrongPassword != 0)
                {
                    SQLTransaction trans = new SQLTransaction();
                    stmt = DB.Login.GetPreparedStatement(LoginStatements.UPD_BNET_FAILED_LOGINS);
                    stmt.AddValue(0, accountInfo.Id);
                    trans.Append(stmt);

                    ++accountInfo.FailedLogins;

                    Log.outDebug(LogFilter.Network, "MaxWrongPass : {0}, failed_login : {1}", maxWrongPassword, accountInfo.Id);

                    if (accountInfo.FailedLogins >= maxWrongPassword)
                    {
                        BanMode banType = ConfigMgr.GetDefaultValue("WrongPass.BanType", BanMode.Ip);
                        int     banTime = ConfigMgr.GetDefaultValue("WrongPass.BanTime", 600);

                        if (banType == BanMode.Account)
                        {
                            stmt = DB.Login.GetPreparedStatement(LoginStatements.INS_BNET_ACCOUNT_AUTO_BANNED);
                            stmt.AddValue(0, accountInfo.Id);
                        }
                        else
                        {
                            stmt = DB.Login.GetPreparedStatement(LoginStatements.INS_IP_AUTO_BANNED);
                            stmt.AddValue(0, request.Host);
                        }

                        stmt.AddValue(1, banTime);
                        trans.Append(stmt);

                        stmt = DB.Login.GetPreparedStatement(LoginStatements.UPD_BNET_RESET_FAILED_LOGINS);
                        stmt.AddValue(0, accountInfo.Id);
                        trans.Append(stmt);
                    }

                    DB.Login.CommitTransaction(trans);
                }
            }

            loginResult.AuthenticationState = "DONE";
            SendResponse(HttpCode.Ok, loginResult);
        }
Exemple #2
0
        public BattlenetRpcErrorCode HandleVerifyWebCredentials(Bgs.Protocol.Authentication.V1.VerifyWebCredentialsRequest verifyWebCredentialsRequest)
        {
            PreparedStatement stmt = DB.Login.GetPreparedStatement(LoginStatements.SEL_BNET_ACCOUNT_INFO);

            stmt.AddValue(0, verifyWebCredentialsRequest.WebCredentials.ToStringUtf8());

            SQLResult result = DB.Login.Query(stmt);

            if (result.IsEmpty())
            {
                return(BattlenetRpcErrorCode.Denied);
            }

            _accountInfo = new AccountInfo();
            _accountInfo.LoadResult(result);

            if (_accountInfo.LoginTicketExpiry < Time.UnixTime)
            {
                return(BattlenetRpcErrorCode.TimedOut);
            }

            stmt = DB.Login.GetPreparedStatement(LoginStatements.SEL_BNET_CHARACTER_COUNTS_BY_BNET_ID);
            stmt.AddValue(0, _accountInfo.Id);

            SQLResult characterCountsResult = DB.Login.Query(stmt);

            if (!characterCountsResult.IsEmpty())
            {
                do
                {
                    RealmHandle realmId = new RealmHandle(characterCountsResult.Read <byte>(3), characterCountsResult.Read <byte>(4), characterCountsResult.Read <uint>(2));
                    _accountInfo.GameAccounts[characterCountsResult.Read <uint>(0)].CharacterCounts[realmId.GetAddress()] = characterCountsResult.Read <byte>(1);
                } while (characterCountsResult.NextRow());
            }

            stmt = DB.Login.GetPreparedStatement(LoginStatements.SEL_BNET_LAST_PLAYER_CHARACTERS);
            stmt.AddValue(0, _accountInfo.Id);

            SQLResult lastPlayerCharactersResult = DB.Login.Query(stmt);

            if (!lastPlayerCharactersResult.IsEmpty())
            {
                do
                {
                    RealmHandle realmId = new RealmHandle(lastPlayerCharactersResult.Read <byte>(1), lastPlayerCharactersResult.Read <byte>(2), lastPlayerCharactersResult.Read <uint>(3));

                    LastPlayedCharacterInfo lastPlayedCharacter = new LastPlayedCharacterInfo();
                    lastPlayedCharacter.RealmId        = realmId;
                    lastPlayedCharacter.CharacterName  = lastPlayerCharactersResult.Read <string>(4);
                    lastPlayedCharacter.CharacterGUID  = lastPlayerCharactersResult.Read <ulong>(5);
                    lastPlayedCharacter.LastPlayedTime = lastPlayerCharactersResult.Read <uint>(6);

                    _accountInfo.GameAccounts[lastPlayerCharactersResult.Read <uint>(0)].LastPlayedCharacters[realmId.GetSubRegionAddress()] = lastPlayedCharacter;
                } while (lastPlayerCharactersResult.NextRow());
            }

            string ip_address = GetRemoteIpAddress().ToString();

            // If the IP is 'locked', check that the player comes indeed from the correct IP address
            if (_accountInfo.IsLockedToIP)
            {
                Log.outDebug(LogFilter.Session, "Session.HandleVerifyWebCredentials: Account '{0}' is locked to IP - '{1}' is logging in from '{2}'",
                             _accountInfo.Login, _accountInfo.LastIP, ip_address);

                if (_accountInfo.LastIP != ip_address)
                {
                    return(BattlenetRpcErrorCode.RiskAccountLocked);
                }
            }
            else
            {
                Log.outDebug(LogFilter.Session, "Session.HandleVerifyWebCredentials: Account '{0}' is not locked to ip", _accountInfo.Login);
                if (_accountInfo.LockCountry.IsEmpty() || _accountInfo.LockCountry == "00")
                {
                    Log.outDebug(LogFilter.Session, "Session.HandleVerifyWebCredentials: Account '{0}' is not locked to country", _accountInfo.Login);
                }
                else if (!_accountInfo.LockCountry.IsEmpty() && !_ipCountry.IsEmpty())
                {
                    Log.outDebug(LogFilter.Session, "Session.HandleVerifyWebCredentials: Account '{0}' is locked to country: '{1}' Player country is '{2}'",
                                 _accountInfo.Login, _accountInfo.LockCountry, _ipCountry);

                    if (_ipCountry != _accountInfo.LockCountry)
                    {
                        return(BattlenetRpcErrorCode.RiskAccountLocked);
                    }
                }
            }

            // If the account is banned, reject the logon attempt
            if (_accountInfo.IsBanned)
            {
                if (_accountInfo.IsPermanenetlyBanned)
                {
                    Log.outDebug(LogFilter.Session, "{0} Session.HandleVerifyWebCredentials: Banned account {1} tried to login!", GetClientInfo(), _accountInfo.Login);
                    return(BattlenetRpcErrorCode.GameAccountBanned);
                }
                else
                {
                    Log.outDebug(LogFilter.Session, "{0} Session.HandleVerifyWebCredentials: Temporarily banned account {1} tried to login!", GetClientInfo(), _accountInfo.Login);
                    return(BattlenetRpcErrorCode.GameAccountSuspended);
                }
            }

            Bgs.Protocol.Authentication.V1.LogonResult logonResult = new Bgs.Protocol.Authentication.V1.LogonResult();
            logonResult.ErrorCode      = 0;
            logonResult.AccountId      = new EntityId();
            logonResult.AccountId.Low  = _accountInfo.Id;
            logonResult.AccountId.High = 0x100000000000000;
            foreach (var pair in _accountInfo.GameAccounts)
            {
                EntityId gameAccountId = new EntityId();
                gameAccountId.Low  = pair.Value.Id;
                gameAccountId.High = 0x200000200576F57;
                logonResult.GameAccountId.Add(gameAccountId);
            }

            if (!_ipCountry.IsEmpty())
            {
                logonResult.GeoipCountry = _ipCountry;
            }

            logonResult.SessionKey = ByteString.CopyFrom(new byte[64].GenerateRandomKey(64));

            _authed = true;

            SendRequest((uint)OriginalHash.AuthenticationListener, 5, logonResult);
            return(BattlenetRpcErrorCode.Ok);
        }
        BattlenetRpcErrorCode HandleVerifyWebCredentials(VerifyWebCredentialsRequest verifyWebCredentialsRequest)
        {
            if (verifyWebCredentialsRequest.WebCredentials.IsEmpty)
            {
                return(BattlenetRpcErrorCode.Denied);
            }

            PreparedStatement stmt = DB.Login.GetPreparedStatement(LoginStatements.SelBnetAccountInfo);

            stmt.AddValue(0, verifyWebCredentialsRequest.WebCredentials.ToStringUtf8());

            SQLResult result = DB.Login.Query(stmt);

            if (result.IsEmpty())
            {
                return(BattlenetRpcErrorCode.Denied);
            }

            accountInfo = new AccountInfo(result);

            if (accountInfo.LoginTicketExpiry < Time.UnixTime)
            {
                return(BattlenetRpcErrorCode.TimedOut);
            }

            stmt = DB.Login.GetPreparedStatement(LoginStatements.SelBnetCharacterCountsByAccountId);
            stmt.AddValue(0, accountInfo.Id);

            SQLResult characterCountsResult = DB.Login.Query(stmt);

            if (!characterCountsResult.IsEmpty())
            {
                do
                {
                    var realmId = new RealmId(characterCountsResult.Read <byte>(3), characterCountsResult.Read <byte>(4), characterCountsResult.Read <uint>(2));
                    accountInfo.GameAccounts[characterCountsResult.Read <uint>(0)].CharacterCounts[realmId.GetAddress()] = characterCountsResult.Read <byte>(1);
                } while (characterCountsResult.NextRow());
            }

            stmt = DB.Login.GetPreparedStatement(LoginStatements.SelBnetLastPlayerCharacters);
            stmt.AddValue(0, accountInfo.Id);

            SQLResult lastPlayerCharactersResult = DB.Login.Query(stmt);

            if (!lastPlayerCharactersResult.IsEmpty())
            {
                do
                {
                    var realmId = new RealmId(lastPlayerCharactersResult.Read <byte>(1), lastPlayerCharactersResult.Read <byte>(2), lastPlayerCharactersResult.Read <uint>(3));

                    LastPlayedCharacterInfo lastPlayedCharacter = new LastPlayedCharacterInfo();
                    lastPlayedCharacter.RealmId        = realmId;
                    lastPlayedCharacter.CharacterName  = lastPlayerCharactersResult.Read <string>(4);
                    lastPlayedCharacter.CharacterGUID  = lastPlayerCharactersResult.Read <ulong>(5);
                    lastPlayedCharacter.LastPlayedTime = lastPlayerCharactersResult.Read <uint>(6);

                    accountInfo.GameAccounts[lastPlayerCharactersResult.Read <uint>(0)].LastPlayedCharacters[realmId.GetSubRegionAddress()] = lastPlayedCharacter;
                } while (lastPlayerCharactersResult.NextRow());
            }

            string ip_address = GetRemoteIpEndPoint().ToString();

            // If the IP is 'locked', check that the player comes indeed from the correct IP address
            if (accountInfo.IsLockedToIP)
            {
                Log.outDebug(LogFilter.Session, $"Session.HandleVerifyWebCredentials: Account: {accountInfo.Login} is locked to IP: {accountInfo.LastIP} is logging in from IP: {ip_address}");

                if (accountInfo.LastIP != ip_address)
                {
                    return(BattlenetRpcErrorCode.RiskAccountLocked);
                }
            }
            else
            {
                Log.outDebug(LogFilter.Session, $"Session.HandleVerifyWebCredentials: Account: {accountInfo.Login} is not locked to ip");
                if (accountInfo.LockCountry.IsEmpty() || accountInfo.LockCountry == "00")
                {
                    Log.outDebug(LogFilter.Session, $"Session.HandleVerifyWebCredentials: Account: {accountInfo.Login} is not locked to country");
                }
                else if (!accountInfo.LockCountry.IsEmpty() && !ipCountry.IsEmpty())
                {
                    Log.outDebug(LogFilter.Session, $"Session.HandleVerifyWebCredentials: Account: {accountInfo.Login} is locked to Country: {accountInfo.LockCountry} player Country: {ipCountry}");

                    if (ipCountry != accountInfo.LockCountry)
                    {
                        return(BattlenetRpcErrorCode.RiskAccountLocked);
                    }
                }
            }

            // If the account is banned, reject the logon attempt
            if (accountInfo.IsBanned)
            {
                if (accountInfo.IsPermanenetlyBanned)
                {
                    Log.outDebug(LogFilter.Session, $"{GetClientInfo()} Session.HandleVerifyWebCredentials: Banned account {accountInfo.Login} tried to login!");
                    return(BattlenetRpcErrorCode.GameAccountBanned);
                }
                else
                {
                    Log.outDebug(LogFilter.Session, $"{GetClientInfo()} Session.HandleVerifyWebCredentials: Temporarily banned account {accountInfo.Login} tried to login!");
                    return(BattlenetRpcErrorCode.GameAccountSuspended);
                }
            }

            LogonResult logonResult = new LogonResult();

            logonResult.ErrorCode      = 0;
            logonResult.AccountId      = new EntityId();
            logonResult.AccountId.Low  = accountInfo.Id;
            logonResult.AccountId.High = 0x100000000000000;
            foreach (var pair in accountInfo.GameAccounts)
            {
                EntityId gameAccountId = new EntityId();
                gameAccountId.Low  = pair.Value.Id;
                gameAccountId.High = 0x200000200576F57;
                logonResult.GameAccountId.Add(gameAccountId);
            }

            if (!ipCountry.IsEmpty())
            {
                logonResult.GeoipCountry = ipCountry;
            }

            logonResult.SessionKey = ByteString.CopyFrom(new byte[64].GenerateRandomKey(64));

            authed = true;

            SendRequest((uint)OriginalHash.AuthenticationListener, 5, logonResult);
            return(BattlenetRpcErrorCode.Ok);
        }