public BattlenetRpcErrorCode JoinRealm(uint realmAddress, uint build, IPAddress clientAddress, Array <byte> clientSecret, LocaleConstant locale, string os, string accountName, Bgs.Protocol.GameUtilities.V1.ClientResponse response) { Realm realm = GetRealm(new RealmHandle(realmAddress)); if (realm != null) { if (realm.Flags.HasAnyFlag(RealmFlags.Offline) || realm.Build != build) { return(BattlenetRpcErrorCode.UserServerNotPermittedOnRealm); } RealmListServerIPAddresses serverAddresses = new RealmListServerIPAddresses(); AddressFamily addressFamily = new AddressFamily(); addressFamily.Id = 1; var address = new Address(); address.Ip = realm.GetAddressForClient(clientAddress).Address.ToString(); address.Port = realm.Port; addressFamily.Addresses.Add(address); serverAddresses.Families.Add(addressFamily); byte[] compressed = Json.Deflate("JSONRealmListServerIPAddresses", serverAddresses); byte[] serverSecret = new byte[0].GenerateRandomKey(32); Sha256 sha256 = new Sha256(); sha256.Process(clientSecret.ToArray(), clientSecret.Count); sha256.Finish(serverSecret, 32); PreparedStatement stmt = DB.Login.GetPreparedStatement(LoginStatements.UPD_BNET_GAME_ACCOUNT_LOGIN_INFO); stmt.AddValue(0, sha256.Digest.ToHexString()); stmt.AddValue(1, clientAddress.ToString()); stmt.AddValue(2, locale); stmt.AddValue(3, os); stmt.AddValue(4, accountName); DB.Login.Execute(stmt); Bgs.Protocol.Attribute attribute = new Bgs.Protocol.Attribute(); attribute.Name = "Param_RealmJoinTicket"; attribute.Value = new Bgs.Protocol.Variant(); attribute.Value.BlobValue = Google.Protobuf.ByteString.CopyFrom(accountName, System.Text.Encoding.UTF8); response.Attribute.Add(attribute); attribute = new Bgs.Protocol.Attribute(); attribute.Name = "Param_ServerAddresses"; attribute.Value = new Bgs.Protocol.Variant(); attribute.Value.BlobValue = Google.Protobuf.ByteString.CopyFrom(compressed); response.Attribute.Add(attribute); attribute = new Bgs.Protocol.Attribute(); attribute.Name = "Param_JoinSecret"; attribute.Value = new Bgs.Protocol.Variant(); attribute.Value.BlobValue = Google.Protobuf.ByteString.CopyFrom(serverSecret); response.Attribute.Add(attribute); return(BattlenetRpcErrorCode.Ok); } return(BattlenetRpcErrorCode.UtilServerUnknownRealm); }
public override void Write() { ByteBuffer whereBuffer = new ByteBuffer(); whereBuffer.WriteUInt8((byte)Payload.Where.Type); switch (Payload.Where.Type) { case AddressType.IPv4: whereBuffer.WriteBytes(Payload.Where.IPv4); break; case AddressType.IPv6: whereBuffer.WriteBytes(Payload.Where.IPv6); break; case AddressType.NamedSocket: whereBuffer.WriteString(Payload.Where.NameSocket); break; default: break; } Sha256 hash = new Sha256(); hash.Process(whereBuffer.GetData(), (int)whereBuffer.GetSize()); hash.Process((uint)Payload.Where.Type); hash.Finish(BitConverter.GetBytes(Payload.Port)); Payload.Signature = RsaCrypt.RSA.SignHash(hash.Digest, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1).Reverse().ToArray(); _worldPacket.WriteBytes(Payload.Signature, (uint)Payload.Signature.Length); _worldPacket.WriteBytes(whereBuffer); _worldPacket.WriteUInt16(Payload.Port); _worldPacket.WriteUInt32((uint)Serial); _worldPacket.WriteUInt8(Con); _worldPacket.WriteUInt64(Key); }
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)); }