Exemple #1
0
        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();
        }
Exemple #3
0
        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();
        }
Exemple #4
0
        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));
        }