Moved loading account info from rest session to session
This commit is contained in:
@@ -84,9 +84,6 @@ namespace BNetServer
|
||||
input.Label = "Log In";
|
||||
_formInputs.Inputs.Add(input);
|
||||
|
||||
_loginTicketCleanupTimer = new Timer(CleanupLoginTickets);
|
||||
_loginTicketCleanupTimer.Change(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10));
|
||||
|
||||
_certificate = new X509Certificate2("BNetServer.pfx");
|
||||
|
||||
return true;
|
||||
@@ -110,52 +107,12 @@ namespace BNetServer
|
||||
return _certificate;
|
||||
}
|
||||
|
||||
public void AddLoginTicket(string id, AccountInfo accountInfo)
|
||||
{
|
||||
_validLoginTickets[id] = new LoginTicket() { Id = id, Account = accountInfo, ExpiryTime = Time.UnixTime + 10 };
|
||||
}
|
||||
|
||||
public AccountInfo VerifyLoginTicket(string id)
|
||||
{
|
||||
var accountInfo = _validLoginTickets.LookupByKey(id);
|
||||
if (accountInfo != null)
|
||||
{
|
||||
if (accountInfo.ExpiryTime > Time.UnixTime)
|
||||
{
|
||||
_validLoginTickets.Remove(id);
|
||||
return accountInfo.Account;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void CleanupLoginTickets(object state)
|
||||
{
|
||||
long now = Time.UnixTime;
|
||||
|
||||
foreach (var pair in _validLoginTickets.ToList())
|
||||
{
|
||||
if (pair.Value.ExpiryTime < now)
|
||||
_validLoginTickets.Remove(pair.Key);
|
||||
}
|
||||
}
|
||||
|
||||
FormInputs _formInputs;
|
||||
IPEndPoint _externalAddress;
|
||||
IPEndPoint _localAddress;
|
||||
Dictionary<string, LoginTicket> _validLoginTickets = new Dictionary<string, LoginTicket>();
|
||||
Timer _loginTicketCleanupTimer;
|
||||
X509Certificate2 _certificate;
|
||||
}
|
||||
|
||||
class LoginTicket
|
||||
{
|
||||
public string Id;
|
||||
public AccountInfo Account;
|
||||
public long ExpiryTime;
|
||||
}
|
||||
|
||||
public enum BanMode
|
||||
{
|
||||
Ip = 0,
|
||||
|
||||
@@ -92,83 +92,54 @@ namespace BNetServer.Networking
|
||||
}
|
||||
}
|
||||
|
||||
PreparedStatement stmt = DB.Login.GetPreparedStatement(LoginStatements.SEL_BNET_ACCOUNT_INFO);
|
||||
PreparedStatement stmt = DB.Login.GetPreparedStatement(LoginStatements.SEL_BNET_AUTHENTICATION);
|
||||
stmt.AddValue(0, login);
|
||||
|
||||
SQLResult result = DB.Login.Query(stmt);
|
||||
if (result.IsEmpty())
|
||||
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);
|
||||
uint accountId = result.Read<uint>(0);
|
||||
string pass_hash = result.Read<string>(1);
|
||||
uint failedLogins = result.Read<uint>(2);
|
||||
string loginTicket = result.Read<string>(3);
|
||||
uint loginTicketExpiry = result.Read<uint>(4);
|
||||
bool isBanned = result.Read<ulong>(5) != 0;
|
||||
|
||||
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())
|
||||
if (loginTicket.IsEmpty() || loginTicketExpiry < Time.UnixTime)
|
||||
{
|
||||
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);
|
||||
loginTicket = "TC-" + ticket.ToHexString();
|
||||
}
|
||||
else if (!accountInfo.IsBanned)
|
||||
|
||||
stmt = DB.Login.GetPreparedStatement(LoginStatements.UPD_BNET_AUTHENTICATION);
|
||||
stmt.AddValue(0, loginTicket);
|
||||
stmt.AddValue(1, Time.UnixTime + 3600);
|
||||
stmt.AddValue(2, accountId);
|
||||
|
||||
DB.Login.Execute(stmt);
|
||||
loginResult.LoginTicket = loginTicket;
|
||||
}
|
||||
else if (!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);
|
||||
Log.outDebug(LogFilter.Network, "[{0}, Account {1}, Id {2}] Attempted to connect with wrong password!", request.Host, login, accountId);
|
||||
|
||||
if (maxWrongPassword != 0)
|
||||
{
|
||||
SQLTransaction trans = new SQLTransaction();
|
||||
stmt = DB.Login.GetPreparedStatement(LoginStatements.UPD_BNET_FAILED_LOGINS);
|
||||
stmt.AddValue(0, accountInfo.Id);
|
||||
stmt.AddValue(0, accountId);
|
||||
trans.Append(stmt);
|
||||
|
||||
++accountInfo.FailedLogins;
|
||||
++failedLogins;
|
||||
|
||||
Log.outDebug(LogFilter.Network, "MaxWrongPass : {0}, failed_login : {1}", maxWrongPassword, accountInfo.Id);
|
||||
Log.outDebug(LogFilter.Network, "MaxWrongPass : {0}, failed_login : {1}", maxWrongPassword, accountId);
|
||||
|
||||
if (accountInfo.FailedLogins >= maxWrongPassword)
|
||||
if (failedLogins >= maxWrongPassword)
|
||||
{
|
||||
BanMode banType = ConfigMgr.GetDefaultValue("WrongPass.BanType", BanMode.Ip);
|
||||
int banTime = ConfigMgr.GetDefaultValue("WrongPass.BanTime", 600);
|
||||
@@ -176,7 +147,7 @@ namespace BNetServer.Networking
|
||||
if (banType == BanMode.Account)
|
||||
{
|
||||
stmt = DB.Login.GetPreparedStatement(LoginStatements.INS_BNET_ACCOUNT_AUTO_BANNED);
|
||||
stmt.AddValue(0, accountInfo.Id);
|
||||
stmt.AddValue(0, accountId);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -188,7 +159,7 @@ namespace BNetServer.Networking
|
||||
trans.Append(stmt);
|
||||
|
||||
stmt = DB.Login.GetPreparedStatement(LoginStatements.UPD_BNET_RESET_FAILED_LOGINS);
|
||||
stmt.AddValue(0, accountInfo.Id);
|
||||
stmt.AddValue(0, accountId);
|
||||
trans.Append(stmt);
|
||||
}
|
||||
|
||||
@@ -199,6 +170,14 @@ namespace BNetServer.Networking
|
||||
loginResult.AuthenticationState = "DONE";
|
||||
SendResponse(HttpCode.Ok, loginResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void SendResponse<T>(HttpCode code, T response)
|
||||
{
|
||||
|
||||
@@ -214,6 +214,7 @@ namespace BNetServer.Networking
|
||||
|
||||
_locale = logonRequest.Locale;
|
||||
_os = logonRequest.Platform;
|
||||
_build = (uint)logonRequest.ApplicationVersion;
|
||||
|
||||
var endpoint = Global.SessionMgr.GetAddressForClient(GetRemoteIpAddress());
|
||||
|
||||
@@ -227,12 +228,54 @@ namespace BNetServer.Networking
|
||||
|
||||
public BattlenetRpcErrorCode HandleVerifyWebCredentials(Bgs.Protocol.Authentication.V1.VerifyWebCredentialsRequest verifyWebCredentialsRequest)
|
||||
{
|
||||
Bgs.Protocol.Authentication.V1.LogonResult logonResult = new Bgs.Protocol.Authentication.V1.LogonResult();
|
||||
logonResult.ErrorCode = 0;
|
||||
_accountInfo = Global.SessionMgr.VerifyLoginTicket(verifyWebCredentialsRequest.WebCredentials.ToStringUtf8());
|
||||
if (_accountInfo == null)
|
||||
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
|
||||
@@ -274,6 +317,8 @@ namespace BNetServer.Networking
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -412,15 +457,16 @@ namespace BNetServer.Networking
|
||||
if (_gameAccountInfo == null)
|
||||
return BattlenetRpcErrorCode.UtilServerInvalidIdentityArgs;
|
||||
|
||||
bool clientInfoOk = false;
|
||||
Variant clientInfo = GetParam(Params, "Param_ClientInfo");
|
||||
if (clientInfo != null)
|
||||
{
|
||||
var realmListTicketClientInformation = Json.CreateObject<RealmListTicketClientInformation>(clientInfo.BlobValue.ToStringUtf8(), true);
|
||||
_build = (uint)realmListTicketClientInformation.Info.ClientVersion.Build;
|
||||
clientInfoOk = true;
|
||||
_clientSecret.AddRange(realmListTicketClientInformation.Info.Secret.Select(x => Convert.ToByte(x)).ToArray());
|
||||
}
|
||||
|
||||
if (_build == 0)
|
||||
if (!clientInfoOk)
|
||||
return BattlenetRpcErrorCode.WowServicesDeniedRealmListTicket;
|
||||
|
||||
PreparedStatement stmt = DB.Login.GetPreparedStatement(LoginStatements.UPD_BNET_LAST_LOGIN_INFO);
|
||||
@@ -592,7 +638,7 @@ namespace BNetServer.Networking
|
||||
IsLockedToIP = result.Read<bool>(2);
|
||||
LockCountry = result.Read<string>(3);
|
||||
LastIP = result.Read<string>(4);
|
||||
FailedLogins = result.Read<uint>(5);
|
||||
LoginTicketExpiry = result.Read<uint>(5);
|
||||
IsBanned = result.Read<ulong>(6) != 0;
|
||||
IsPermanenetlyBanned = result.Read<ulong>(7) != 0;
|
||||
PasswordVerifier = result.Read<string>(9);
|
||||
@@ -614,7 +660,7 @@ namespace BNetServer.Networking
|
||||
public bool IsLockedToIP;
|
||||
public string LockCountry;
|
||||
public string LastIP;
|
||||
public uint FailedLogins;
|
||||
public uint LoginTicketExpiry;
|
||||
public bool IsBanned;
|
||||
public bool IsPermanenetlyBanned;
|
||||
public string PasswordVerifier;
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Framework.Database
|
||||
{
|
||||
public override void PreparedStatements()
|
||||
{
|
||||
const string BnetAccountInfo = "ba.id, ba.email, ba.locked, ba.lock_country, ba.last_ip, ba.failed_logins, bab.unbandate > UNIX_TIMESTAMP() OR bab.unbandate = bab.bandate, bab.unbandate = bab.bandate";
|
||||
const string BnetAccountInfo = "ba.id, ba.email, ba.locked, ba.lock_country, ba.last_ip, ba.LoginTicketExpiry, bab.unbandate > UNIX_TIMESTAMP() OR bab.unbandate = bab.bandate, bab.unbandate = bab.bandate";
|
||||
const string BnetGameAccountInfo = "a.id, a.username, ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate, ab.unbandate = ab.bandate, aa.gmlevel";
|
||||
|
||||
PrepareStatement(LoginStatements.SEL_REALMLIST, "SELECT id, name, address, localAddress, localSubnetMask, port, icon, flag, timezone, allowedSecurityLevel, population, gamebuild, Region, Battlegroup FROM realmlist WHERE flag <> 3 ORDER BY name");
|
||||
@@ -117,9 +117,11 @@ namespace Framework.Database
|
||||
PrepareStatement(LoginStatements.SEL_ACCOUNT_MUTE_INFO, "SELECT mutedate, mutetime, mutereason, mutedby FROM account_muted WHERE guid = ? ORDER BY mutedate ASC");
|
||||
PrepareStatement(LoginStatements.DEL_ACCOUNT_MUTED, "DELETE FROM account_muted WHERE guid = ?");
|
||||
|
||||
PrepareStatement(LoginStatements.SEL_BNET_ACCOUNT_INFO, "SELECT " + BnetAccountInfo + ", " + BnetGameAccountInfo + ", ba.sha_pass_hash" +
|
||||
PrepareStatement(LoginStatements.SEL_BNET_AUTHENTICATION, "SELECT ba.id, ba.sha_pass_hash, ba.failed_logins, ba.LoginTicket, ba.LoginTicketExpiry, bab.unbandate > UNIX_TIMESTAMP() OR bab.unbandate = bab.bandate FROM battlenet_accounts ba LEFT JOIN battlenet_account_bans bab ON ba.id = bab.id WHERE email = ?");
|
||||
PrepareStatement(LoginStatements.UPD_BNET_AUTHENTICATION, "UPDATE battlenet_accounts SET LoginTicket = ?, LoginTicketExpiry = ? WHERE id = ?");
|
||||
PrepareStatement(LoginStatements.SEL_BNET_ACCOUNT_INFO, "SELECT " + BnetAccountInfo + ", " + BnetGameAccountInfo +
|
||||
" FROM battlenet_accounts ba LEFT JOIN battlenet_account_bans bab ON ba.id = bab.id LEFT JOIN account a ON ba.id = a.battlenet_account" +
|
||||
" LEFT JOIN account_banned ab ON a.id = ab.id AND ab.active = 1 LEFT JOIN account_access aa ON a.id = aa.id AND aa.RealmID = -1 WHERE ba.email = ? ORDER BY a.id");
|
||||
" LEFT JOIN account_banned ab ON a.id = ab.id AND ab.active = 1 LEFT JOIN account_access aa ON a.id = aa.id AND aa.RealmID = -1 WHERE ba.LoginTicket = ? ORDER BY a.id");
|
||||
PrepareStatement(LoginStatements.UPD_BNET_LAST_LOGIN_INFO, "UPDATE battlenet_accounts SET last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE id = ?");
|
||||
PrepareStatement(LoginStatements.UPD_BNET_GAME_ACCOUNT_LOGIN_INFO, "UPDATE account SET sessionkey = ?, last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE username = ?");
|
||||
PrepareStatement(LoginStatements.SEL_BNET_CHARACTER_COUNTS_BY_ACCOUNT_ID, "SELECT rc.acctid, rc.numchars, r.id, r.Region, r.Battlegroup FROM realmcharacters rc INNER JOIN realmlist r ON rc.realmid = r.id WHERE rc.acctid = ?");
|
||||
@@ -263,6 +265,8 @@ namespace Framework.Database
|
||||
SEL_ACCOUNT_MUTE_INFO,
|
||||
DEL_ACCOUNT_MUTED,
|
||||
|
||||
SEL_BNET_AUTHENTICATION,
|
||||
UPD_BNET_AUTHENTICATION,
|
||||
SEL_BNET_ACCOUNT_INFO,
|
||||
UPD_BNET_LAST_LOGIN_INFO,
|
||||
UPD_BNET_GAME_ACCOUNT_LOGIN_INFO,
|
||||
|
||||
Reference in New Issue
Block a user