Beispiel #1
0
        public static void HandleAuthContinuedSession(AuthContinuedSession authContinuedSession, WorldSession session)
        {
            var gameAccount = Manager.Redirect.GetGameAccountFromRedirect(authContinuedSession.Key);

            // Delete redirect key
            Manager.Redirect.DeleteGameAccountRedirect(authContinuedSession.Key);

            if (gameAccount != null)
            {
                var sha1 = new SHA1Managed();

                var emailBytes      = Encoding.UTF8.GetBytes(gameAccount.Account.Id + "#" + gameAccount.Index);
                var sessionKeyBytes = gameAccount.SessionKey.ToByteArray();
                var challengeBytes  = BitConverter.GetBytes(session.Challenge);

                sha1.TransformBlock(emailBytes, 0, emailBytes.Length, emailBytes, 0);
                sha1.TransformBlock(sessionKeyBytes, 0, 40, sessionKeyBytes, 0);
                sha1.TransformFinalBlock(challengeBytes, 0, 4);

                if (sha1.Hash.Compare(authContinuedSession.Digest))
                {
                    session.Crypt = new Framework.Cryptography.WoW.WoWCrypt();
                    session.Crypt.Initialize(gameAccount.SessionKey.ToByteArray(), session.ClientSeed, session.ServerSeed);

                    // Resume on the new connection
                    session.Send(new ResumeComms());

                    return;
                }
            }

            session.Dispose();
        }
Beispiel #2
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());
        }
Beispiel #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();
        }
Beispiel #4
0
        void HandleAuthContinuedSession(AuthContinuedSession authSession)
        {
            ConnectToKey key = new ConnectToKey();

            _key = key.Raw = authSession.Key;

            _connectType = key.connectionType;
            if (_connectType != ConnectionType.Instance)
            {
                SendAuthResponseError(BattlenetRpcErrorCode.Denied);
                CloseSocket();
                return;
            }

            uint accountId         = key.AccountId;
            PreparedStatement stmt = DB.Login.GetPreparedStatement(LoginStatements.SEL_ACCOUNT_INFO_CONTINUED_SESSION);

            stmt.AddValue(0, accountId);

            _queryProcessor.AddQuery(DB.Login.AsyncQuery(stmt).WithCallback(HandleAuthContinuedSessionCallback, authSession));
        }
Beispiel #5
0
        public static async void HandleAuthContinuedSession(AuthContinuedSession authContinuedSession, NodeSession session)
        {
            var accountInfo = Manager.Redirect.GetAccountInfo(authContinuedSession.Key);

            // Delete redirect key
            Manager.Redirect.DeleteCharacterRedirect(authContinuedSession.Key);

            if (accountInfo != null)
            {
                var sha1 = new SHA1Managed();

                var emailBytes      = Encoding.UTF8.GetBytes(accountInfo.Item1.AccountId + "#" + accountInfo.Item1.Index);
                var sessionKeyBytes = accountInfo.Item1.SessionKey.ToByteArray();
                var challengeBytes  = BitConverter.GetBytes(session.Challenge);

                sha1.TransformBlock(emailBytes, 0, emailBytes.Length, emailBytes, 0);
                sha1.TransformBlock(sessionKeyBytes, 0, 40, sessionKeyBytes, 0);
                sha1.TransformFinalBlock(challengeBytes, 0, 4);

                if (sha1.Hash.Compare(authContinuedSession.Digest))
                {
                    session.State = SessionState.Authenticated;

                    session.Account     = DB.Auth.Single <Account>(a => a.Id == accountInfo.Item1.AccountId);
                    session.GameAccount = accountInfo.Item1;

                    session.Crypt = new Framework.Cryptography.WoW.WoWCrypt();
                    session.Crypt.Initialize(accountInfo.Item1.SessionKey.ToByteArray(), session.ClientSeed, session.ServerSeed);

                    // Resume on the new connection
                    await session.Send(new ResumeComms());

                    return;
                }
            }

            session.Dispose();
        }
Beispiel #6
0
        bool ProcessPacket(WorldPacket packet)
        {
            ClientOpcodes opcode = (ClientOpcodes)packet.GetOpcode();

            PacketLog.Write(packet.GetData(), opcode, GetRemoteIpAddress(), GetRemotePort(), _connectType);

            try
            {
                switch (opcode)
                {
                case ClientOpcodes.Ping:
                    Ping ping = new Ping(packet);
                    ping.Read();
                    return(HandlePing(ping));

                case ClientOpcodes.AuthSession:
                    if (_worldSession != null)
                    {
                        Log.outError(LogFilter.Network, "WorldSocket.ProcessPacket: received duplicate CMSG_AUTH_SESSION from {0}", _worldSession.GetPlayerInfo());
                        return(false);
                    }

                    AuthSession authSession = new AuthSession(packet);
                    authSession.Read();
                    HandleAuthSession(authSession);
                    break;

                case ClientOpcodes.AuthContinuedSession:
                    if (_worldSession != null)
                    {
                        Log.outError(LogFilter.Network, "WorldSocket.ProcessPacket: received duplicate CMSG_AUTH_CONTINUED_SESSION from {0}", _worldSession.GetPlayerInfo());
                        return(false);
                    }

                    AuthContinuedSession authContinuedSession = new AuthContinuedSession(packet);
                    authContinuedSession.Read();
                    HandleAuthContinuedSession(authContinuedSession);
                    break;

                case ClientOpcodes.LogDisconnect:
                    break;

                case ClientOpcodes.EnableNagle:
                    Log.outDebug(LogFilter.Network, "Client {0} requested enabling nagle algorithm", GetRemoteIpAddress().ToString());
                    SetNoDelay(false);
                    break;

                case ClientOpcodes.ConnectToFailed:
                    ConnectToFailed connectToFailed = new ConnectToFailed(packet);
                    connectToFailed.Read();
                    HandleConnectToFailed(connectToFailed);
                    break;

                case ClientOpcodes.EnableEncryptionAck:
                    HandleEnableEncryptionAck();
                    break;

                default:
                    if (_worldSession == null)
                    {
                        Log.outError(LogFilter.Network, "ProcessIncoming: Client not authed opcode = {0}", opcode);
                        return(false);
                    }

                    if (!PacketManager.ContainsHandler(opcode))
                    {
                        Log.outError(LogFilter.Network, "No defined handler for opcode {0} sent by {1}", opcode, _worldSession.GetPlayerInfo());
                        break;
                    }

                    // Our Idle timer will reset on any non PING opcodes.
                    // Catches people idling on the login screen and any lingering ingame connections.
                    _worldSession.ResetTimeOutTime();
                    _worldSession.QueuePacket(packet);
                    break;
                }
            }
            catch (IOException)
            {
                Log.outError(LogFilter.Network, "WorldSocket.ProcessPacket(): client {0} sent malformed {1}", GetRemoteIpAddress().ToString(), opcode);
                return(false);
            }

            return(true);
        }
Beispiel #7
0
        ReadDataHandlerResult ReadData()
        {
            PacketHeader header = new PacketHeader();

            header.Read(_headerBuffer.GetData());

            if (!_worldCrypt.Decrypt(_packetBuffer.GetData(), header.Tag))
            {
                Log.outError(LogFilter.Network, $"WorldSocket.ReadData(): client {GetRemoteIpAddress()} failed to decrypt packet (size: {header.Size})");
                return(ReadDataHandlerResult.Error);
            }

            WorldPacket packet = new WorldPacket(_packetBuffer.GetData());

            _packetBuffer.Reset();

            if (packet.GetOpcode() >= (int)ClientOpcodes.Max)
            {
                Log.outError(LogFilter.Network, $"WorldSocket.ReadData(): client {GetRemoteIpAddress()} sent wrong opcode (opcode: {packet.GetOpcode()})");
                return(ReadDataHandlerResult.Error);
            }

            PacketLog.Write(packet.GetData(), packet.GetOpcode(), GetRemoteIpAddress(), _connectType, true);

            ClientOpcodes opcode = (ClientOpcodes)packet.GetOpcode();

            switch (opcode)
            {
            case ClientOpcodes.Ping:
                Ping ping = new Ping(packet);
                ping.Read();
                if (!HandlePing(ping))
                {
                    return(ReadDataHandlerResult.Error);
                }
                break;

            case ClientOpcodes.AuthSession:
                if (_worldSession != null)
                {
                    Log.outError(LogFilter.Network, $"WorldSocket.ReadData(): received duplicate CMSG_AUTH_SESSION from {_worldSession.GetPlayerInfo()}");
                    return(ReadDataHandlerResult.Error);
                }

                AuthSession authSession = new AuthSession(packet);
                authSession.Read();
                HandleAuthSession(authSession);
                return(ReadDataHandlerResult.WaitingForQuery);

            case ClientOpcodes.AuthContinuedSession:
                if (_worldSession != null)
                {
                    Log.outError(LogFilter.Network, $"WorldSocket.ReadData(): received duplicate CMSG_AUTH_CONTINUED_SESSION from {_worldSession.GetPlayerInfo()}");
                    return(ReadDataHandlerResult.Error);
                }

                AuthContinuedSession authContinuedSession = new AuthContinuedSession(packet);
                authContinuedSession.Read();
                HandleAuthContinuedSession(authContinuedSession);
                return(ReadDataHandlerResult.WaitingForQuery);

            case ClientOpcodes.KeepAlive:
                if (_worldSession != null)
                {
                    _worldSession.ResetTimeOutTime(true);
                }
                break;

            case ClientOpcodes.LogDisconnect:
                break;

            case ClientOpcodes.EnableNagle:
                SetNoDelay(false);
                break;

            case ClientOpcodes.ConnectToFailed:
                ConnectToFailed connectToFailed = new ConnectToFailed(packet);
                connectToFailed.Read();
                HandleConnectToFailed(connectToFailed);
                break;

            case ClientOpcodes.EnterEncryptedModeAck:
                HandleEnterEncryptedModeAck();
                break;

            default:
                if (_worldSession == null)
                {
                    Log.outError(LogFilter.Network, $"ProcessIncoming: Client not authed opcode = {opcode}");
                    return(ReadDataHandlerResult.Error);
                }

                if (!PacketManager.ContainsHandler(opcode))
                {
                    Log.outError(LogFilter.Network, $"No defined handler for opcode {opcode} sent by {_worldSession.GetPlayerInfo()}");
                    break;
                }

                // Our Idle timer will reset on any non PING opcodes on login screen, allowing us to catch people idling.
                _worldSession.ResetTimeOutTime(false);

                // Copy the packet to the heap before enqueuing
                _worldSession.QueuePacket(packet);
                break;
            }

            return(ReadDataHandlerResult.Ok);
        }