void HandleAuthContinuedSessionCallback(AuthContinuedSession authSession, SQLResult result) { if (result.IsEmpty()) { SendAuthResponseError(BattlenetRpcErrorCode.Denied); CloseSocket(); return; } ConnectToKey key = new ConnectToKey(); _key = key.Raw = authSession.Key; uint accountId = key.AccountId; string login = result.Read <string>(0); _sessionKey = result.Read <string>(1).ToByteArray(); HmacSha256 hmac = new HmacSha256(_sessionKey); hmac.Process(BitConverter.GetBytes(authSession.Key), 8); hmac.Process(authSession.LocalChallenge, authSession.LocalChallenge.Length); hmac.Process(_serverChallenge, 16); hmac.Finish(ContinuedSessionSeed, 16); if (!hmac.Digest.Compare(authSession.Digest)) { Log.outError(LogFilter.Network, "WorldSocket.HandleAuthContinuedSession: Authentication failed for account: {0} ('{1}') address: {2}", accountId, login, GetRemoteIpAddress()); CloseSocket(); return; } SendPacket(new EnableEncryption()); }
public override void Write() { HmacSha256 hash = new HmacSha256(EncryptionKey); hash.Process(BitConverter.GetBytes(Enabled), 1); hash.Finish(EnableEncryptionSeed, 16); _worldPacket.WriteBytes(RsaCrypt.RSA.SignHash(hash.Digest, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1).Reverse().ToArray()); _worldPacket.WriteBit(Enabled); _worldPacket.FlushBits(); }
void HandleAuthContinuedSessionCallback(AuthContinuedSession authSession, SQLResult result) { if (result.IsEmpty()) { SendAuthResponseError(BattlenetRpcErrorCode.Denied); CloseSocket(); return; } ConnectToKey key = new ConnectToKey(); _key = key.Raw = authSession.Key; uint accountId = key.AccountId; string login = result.Read <string>(0); _sessionKey = result.Read <byte[]>(1); HmacSha256 hmac = new HmacSha256(_sessionKey); hmac.Process(BitConverter.GetBytes(authSession.Key), 8); hmac.Process(authSession.LocalChallenge, authSession.LocalChallenge.Length); hmac.Process(_serverChallenge, 16); hmac.Finish(ContinuedSessionSeed, 16); if (!hmac.Digest.Compare(authSession.Digest)) { Log.outError(LogFilter.Network, "WorldSocket.HandleAuthContinuedSession: Authentication failed for account: {0} ('{1}') address: {2}", accountId, login, GetRemoteIpAddress()); CloseSocket(); return; } HmacSha256 encryptKeyGen = new HmacSha256(_sessionKey); encryptKeyGen.Process(authSession.LocalChallenge, authSession.LocalChallenge.Length); encryptKeyGen.Process(_serverChallenge, 16); encryptKeyGen.Finish(EncryptionKeySeed, 16); // only first 16 bytes of the hmac are used Buffer.BlockCopy(encryptKeyGen.Digest, 0, _encryptKey, 0, 16); SendPacket(new EnterEncryptedMode(_encryptKey, true)); AsyncRead(); }
void HandleAuthSessionCallback(AuthSession authSession, SQLResult result) { // Stop if the account is not found if (result.IsEmpty()) { Log.outError(LogFilter.Network, "HandleAuthSession: Sent Auth Response (unknown account)."); CloseSocket(); return; } AccountInfo account = new AccountInfo(result.GetFields()); // For hook purposes, we get Remoteaddress at this point. string address = GetRemoteIpAddress().ToString(); byte[] clientSeed = ClientTypeSeed_Win; if (account.game.OS == "Wn64") { clientSeed = ClientTypeSeed_Wn64; } else if (account.game.OS == "Mc64") { clientSeed = ClientTypeSeed_Mc64; } Sha256 digestKeyHash = new Sha256(); digestKeyHash.Process(account.game.SessionKey, account.game.SessionKey.Length); digestKeyHash.Finish(clientSeed, clientSeed.Length); HmacSha256 hmac = new HmacSha256(digestKeyHash.Digest); hmac.Process(authSession.LocalChallenge, authSession.LocalChallenge.Count); hmac.Process(_serverChallenge, 16); hmac.Finish(AuthCheckSeed, 16); // Check that Key and account name are the same on client and server if (!hmac.Digest.Compare(authSession.Digest)) { Log.outError(LogFilter.Network, "WorldSocket.HandleAuthSession: Authentication failed for account: {0} ('{1}') address: {2}", account.game.Id, authSession.RealmJoinTicket, address); CloseSocket(); return; } Sha256 keyData = new Sha256(); keyData.Finish(account.game.SessionKey, account.game.SessionKey.Length); HmacSha256 sessionKeyHmac = new HmacSha256(keyData.Digest); sessionKeyHmac.Process(_serverChallenge, 16); sessionKeyHmac.Process(authSession.LocalChallenge, authSession.LocalChallenge.Count); sessionKeyHmac.Finish(SessionKeySeed, 16); _sessionKey = new byte[40]; var sessionKeyGenerator = new SessionKeyGenerator(sessionKeyHmac.Digest, 32); sessionKeyGenerator.Generate(_sessionKey, 40); // As we don't know if attempted login process by ip works, we update last_attempt_ip right away PreparedStatement stmt = DB.Login.GetPreparedStatement(LoginStatements.UPD_LAST_ATTEMPT_IP); stmt.AddValue(0, address); stmt.AddValue(1, authSession.RealmJoinTicket); DB.Login.Execute(stmt); // This also allows to check for possible "hack" attempts on account stmt = DB.Login.GetPreparedStatement(LoginStatements.UPD_ACCOUNT_INFO_CONTINUED_SESSION); stmt.AddValue(0, _sessionKey.ToHexString()); stmt.AddValue(1, account.game.Id); DB.Login.Execute(stmt); // First reject the connection if packet contains invalid data or realm state doesn't allow logging in if (Global.WorldMgr.IsClosed()) { SendAuthResponseError(BattlenetRpcErrorCode.Denied); Log.outError(LogFilter.Network, "WorldSocket.HandleAuthSession: World closed, denying client ({0}).", GetRemoteIpAddress()); CloseSocket(); return; } if (authSession.RealmID != Global.WorldMgr.GetRealm().Id.Realm) { SendAuthResponseError(BattlenetRpcErrorCode.Denied); Log.outError(LogFilter.Network, "WorldSocket.HandleAuthSession: Client {0} requested connecting with realm id {1} but this realm has id {2} set in config.", GetRemoteIpAddress().ToString(), authSession.RealmID, Global.WorldMgr.GetRealm().Id.Realm); CloseSocket(); return; } // Must be done before WorldSession is created bool wardenActive = WorldConfig.GetBoolValue(WorldCfg.WardenEnabled); if (wardenActive && account.game.OS != "Win" && account.game.OS != "Wn64" && account.game.OS != "Mc64") { SendAuthResponseError(BattlenetRpcErrorCode.Denied); Log.outError(LogFilter.Network, "WorldSocket.HandleAuthSession: Client {0} attempted to log in using invalid client OS ({1}).", address, account.game.OS); CloseSocket(); return; } //Re-check ip locking (same check as in auth). if (account.battleNet.IsLockedToIP) // if ip is locked { if (account.battleNet.LastIP != address) { SendAuthResponseError(BattlenetRpcErrorCode.RiskAccountLocked); Log.outDebug(LogFilter.Network, "HandleAuthSession: Sent Auth Response (Account IP differs)."); CloseSocket(); return; } } else if (!account.battleNet.LockCountry.IsEmpty() && account.battleNet.LockCountry != "00" && !_ipCountry.IsEmpty()) { if (account.battleNet.LockCountry != _ipCountry) { SendAuthResponseError(BattlenetRpcErrorCode.RiskAccountLocked); Log.outDebug(LogFilter.Network, "WorldSocket.HandleAuthSession: Sent Auth Response (Account country differs. Original country: {0}, new country: {1}).", account.battleNet.LockCountry, _ipCountry); CloseSocket(); return; } } long mutetime = account.game.MuteTime; //! Negative mutetime indicates amount of seconds to be muted effective on next login - which is now. if (mutetime < 0) { mutetime = Time.UnixTime + mutetime; stmt = DB.Login.GetPreparedStatement(LoginStatements.UPD_MUTE_TIME_LOGIN); stmt.AddValue(0, mutetime); stmt.AddValue(1, account.game.Id); DB.Login.Execute(stmt); } if (account.IsBanned()) // if account banned { SendAuthResponseError(BattlenetRpcErrorCode.GameAccountBanned); Log.outError(LogFilter.Network, "WorldSocket:HandleAuthSession: Sent Auth Response (Account banned)."); CloseSocket(); return; } // Check locked state for server AccountTypes allowedAccountType = Global.WorldMgr.GetPlayerSecurityLimit(); if (allowedAccountType > AccountTypes.Player && account.game.Security < allowedAccountType) { SendAuthResponseError(BattlenetRpcErrorCode.ServerIsPrivate); Log.outInfo(LogFilter.Network, "WorldSocket:HandleAuthSession: User tries to login but his security level is not enough"); CloseSocket(); return; } Log.outDebug(LogFilter.Network, "WorldSocket:HandleAuthSession: Client '{0}' authenticated successfully from {1}.", authSession.RealmJoinTicket, address); // Update the last_ip in the database stmt = DB.Login.GetPreparedStatement(LoginStatements.UPD_LAST_IP); stmt.AddValue(0, address); stmt.AddValue(1, authSession.RealmJoinTicket); DB.Login.Execute(stmt); _worldSession = new WorldSession(account.game.Id, authSession.RealmJoinTicket, account.battleNet.Id, this, account.game.Security, (Expansion)account.game.Expansion, mutetime, account.game.OS, account.battleNet.Locale, account.game.Recruiter, account.game.IsRectuiter); // Initialize Warden system only if it is enabled by config //if (wardenActive) //_worldSession.InitWarden(_sessionKey); _queryProcessor.AddQuery(_worldSession.LoadPermissionsAsync().WithCallback(LoadSessionPermissionsCallback)); }