Exemplo n.º 1
0
        public override void ExecuteCommand(ShardSession session, ShardRequest request, ClientPacketHeader header)
        {
            int    clientBuild = BitConverter.ToInt32(request.Packet, 6);
            int    identityLength;
            string identity   = Strings.FromNullTerminated(request.Packet, 14, Encoding.UTF8, out identityLength);
            int    clientSeed = BitConverter.ToInt32(request.Packet, 14 + identityLength + 1); // + 1 for null terminator

            byte[] clientDigest = new byte[20];
            Array.Copy(request.Packet, 14 + identityLength + 1 + 4, clientDigest, 0, 20);

            log.DebugFormat("read {0} packet. client build = {1}, identity = {2}, client seed = {3:X}, packet size = {4}", header.Opcode, clientBuild, identity, clientSeed, request.Size);

            int    accountId  = -1;
            string sessionKey = null;

            if (!session.Server.AuthDB.ExecuteQuery("select name, session_key, id from account where name = ? and enabled = true", identity, result =>
            {
                if (result.Read())
                {
                    identity = result.GetString(0);
                    sessionKey = result.GetString(1);
                    accountId = result.GetInt32(2);
                    return(true);
                }
                return(false);
            }))
            {
                // no identity match
                log.DebugFormat("account {0} not found. sending {1} response", identity, AuthResponse.UnknownAccount);
                session.Send(ShardServerOpcode.AuthResponse, (byte)AuthResponse.UnknownAccount);
                return;
            }

            BigInteger sessionKeyInt = BigInteger.Parse(sessionKey, NumberStyles.AllowHexSpecifier);

            // verify client/server identity and session key match
            using (Digester sha1 = new Digester(new SHA1CryptoServiceProvider()))
            {
                byte[] serverDigest = sha1.CalculateDigest(new byte[][]
                {
                    Encoding.UTF8.GetBytes(identity),
                    new byte[4],
                    BitConverter.GetBytes(clientSeed),
                    BitConverter.GetBytes(session.Seed),
                    Arrays.Left(sessionKeyInt.ToByteArray(), 40)
                });

                log.DebugFormat("client digest = {0}", Strings.HexOf(clientDigest));
                log.DebugFormat("server digest = {0}", Strings.HexOf(serverDigest));

                if (Arrays.AreEqual(clientDigest, serverDigest))
                {
                    log.InfoFormat("client {0} successfully authenticated from {1}", identity, session.RemoteEndPoint.Address.ToString());

                    session.AccountID = accountId;
                    session.Status    = SessionStatus.Authenticated;
                    session.InitializeCipher(sessionKeyInt);

                    using (ByteBuffer authPacket = new ByteBuffer())
                    {
                        authPacket.Append((byte)AuthResponse.Success);
                        authPacket.Append(0);
                        authPacket.Append((byte)0);
                        authPacket.Append(0);

                        session.Send(ShardServerOpcode.AuthResponse, authPacket);
                    }

                    using (ByteBuffer addonPacket = BuildAddonPacket(new ArraySegment <byte>(request.Packet, 14 + identityLength + 1 + 4 + 20, request.Size - (14 + identityLength + 1 + 4 + 20))))
                        session.Send(ShardServerOpcode.AddonInfo, addonPacket);
                }
                else
                {
                    // digest mismatch
                    log.DebugFormat("client digest did not match server digest for account {0}. sending {1} response", identity, AuthResponse.Failed);
                    session.Send(ShardServerOpcode.AuthResponse, (byte)AuthResponse.Failed);
                    return;
                }
            }
        }