Example #1
0
        public static byte[] GetAddonInfoData(CharacterSession session, byte[] packedData, int packedSize, int unpackedSize)
        {
            // Check ZLib header (normal mode)
            if (packedData[0] == 0x78 && packedData[1] == 0x9C)
            {
                var unpackedAddonData = new byte[unpackedSize];

                if (packedSize > 0)
                {
                    using (var inflate = new DeflateStream(new MemoryStream(packedData, 2, packedSize - 6), CompressionMode.Decompress))
                    {
                        var decompressed = new MemoryStream();
                        inflate.CopyTo(decompressed);

                        decompressed.Seek(0, SeekOrigin.Begin);

                        for (int i = 0; i < unpackedSize; i++)
                        {
                            unpackedAddonData[i] = (byte)decompressed.ReadByte();
                        }
                    }
                }

                return(unpackedAddonData);
            }
            else
            {
                Log.Message(LogType.Error, "Wrong AddonInfo for Client '{0}'.", session.GetClientInfo());

                session.Dispose();
            }

            return(null);
        }
Example #2
0
        public static void LoadAddonInfoData(CharacterSession session, byte[] packedData, int packedSize, int unpackedSize)
        {
            // Check ZLib header (normal mode)
            if (packedData[0] == 0x78 && packedData[1] == 0x9C)
            {
                var unpackedAddonData = new byte[unpackedSize];

                if (packedSize > 0)
                {
                    using (var inflate = new DeflateStream(new MemoryStream(packedData, 2, packedSize - 6), CompressionMode.Decompress))
                    {
                        var decompressed = new MemoryStream();
                        inflate.CopyTo(decompressed);

                        decompressed.Seek(0, SeekOrigin.Begin);

                        for (int i = 0; i < unpackedSize; i++)
                            unpackedAddonData[i] = (byte)decompressed.ReadByte();
                    }
                }

                HandleAddonInfo(session, unpackedAddonData);
            }
            else
            {
                Log.Message(LogType.Error, "Wrong AddonInfo for Client '{0}'.", session.GetClientIP());

                session.Dispose();
            }
        }
Example #3
0
        public static async Task InvokeHandler <T>(Packet reader, CharacterSession session)
        {
            var message = reader.Header.Message;

            Tuple <MethodInfo, Type, SessionState> data;

            if (MessageHandlers.TryGetValue(message, out data))
            {
                if ((session.State & data.Item3) == SessionState.None)
                {
                    var clientInfo = session.GetClientInfo();

                    Log.Debug($"Client '{clientInfo}': Received not allowed packet for state '{session.State}'.");
                    Log.Debug($"Disconnecting '{clientInfo}'.");

                    session.Dispose();

                    return;
                }

                var handlerObj = Activator.CreateInstance(data.Item2) as ClientPacket;

                handlerObj.Packet = reader;

                await Task.Run(() => handlerObj.Read());

                if (handlerObj.IsReadComplete)
                {
                    data.Item1.Invoke(null, new object[] { handlerObj, session });
                }
                else
                {
                    Log.Error($"Packet read for '{data.Item2.Name}' failed.");
                }
            }
            else
            {
                var msgName = Enum.GetName(typeof(ClientMessage), message) ?? Enum.GetName(typeof(GlobalClientMessage), message);

                if (msgName == null)
                {
                    Log.Error($"Received unknown opcode '0x{message:X}, Length: {reader.Data.Length}'.");
                }
                else
                {
                    Log.Error($"Packet handler for '{msgName} (0x{message:X}), Length: {reader.Data.Length}' not implemented.");
                }
            }
        }
        public static void HandleCharDelete(CharDelete charDelete, CharacterSession session)
        {
            if (charDelete.Guid.CreationBits > 0 && charDelete.Guid.Type == GuidType.Player)
            {
                var deleteChar  = new DeleteChar();
                var guid        = charDelete.Guid;
                var gameAccount = session.GameAccount;

                if (DB.Character.Delete <Character>(c => c.Guid == guid.Low && c.GameAccountId == gameAccount.Id))
                {
                    deleteChar.Code = CharDeleteCode.Success;
                }
                else
                {
                    deleteChar.Code = CharDeleteCode.Failed;
                }

                session.Send(deleteChar);
            }
            else
            {
                session.Dispose();
            }
        }
Example #5
0
        public static async void AuthSessionHandler(AuthSession authSession, CharacterSession session)
        {
            var accountParts = authSession.Account.Split(new[] { '#' });
            var authResult   = AuthResult.Ok;

            if (accountParts.Length == 2)
            {
                var accountId = int.Parse(accountParts[0]);
                var gameIndex = byte.Parse(accountParts[1]);

                session.Account = DB.Auth.Single <Account>(a => a.Id == accountId);

                if (session.Account != null)
                {
                    session.GameAccount = session.Account.GameAccounts.SingleOrDefault(ga => ga.Index == gameIndex);
                }

                if (session.GameAccount != null)
                {
                    session.Crypt = new WoWCrypt(session.GameAccount.SessionKey.ToByteArray());
                }
                else
                {
                    authResult = AuthResult.Failed;
                }
            }

            session.Realm = DB.Auth.Single <Realm>(r => r.Id == authSession.RealmID);

            if (authSession.LoginServerType != (sbyte)LoginServerTypes.Battlenet || session.Realm == null)
            {
                authResult = AuthResult.Reject;
            }

            if (authResult == AuthResult.Ok)
            {
                var sha1 = new Sha1();

                sha1.Process(authSession.Account);
                sha1.Process(0u);
                sha1.Process(authSession.LocalChallenge);
                sha1.Process(session.Challenge);
                sha1.Finish(session.GameAccount.SessionKey.ToByteArray(), 40);

                // Check the password digest.
                if (!sha1.Digest.Compare(authSession.Digest))
                {
                    authResult = AuthResult.Failed;
                }
            }

            var authResponse = new AuthResponse
            {
                Result         = authResult,
                HasSuccessInfo = authResult == AuthResult.Ok,
            };

            if (authResponse.HasSuccessInfo)
            {
                session.State = SessionState.Authenticated;

                var addonData = AddonHandler.GetAddonInfoData(session, authSession.AddonInfo, authSession.CompressedAddonInfoSize, authSession.UncompressedAddonInfoSize);

                if (addonData != null && addonData.Length != authSession.UncompressedAddonInfoSize)
                {
                    Log.Error("Addon Info data size mismatch.");

                    session.Dispose();

                    return;
                }

                authResponse.SuccessInfo.ActiveExpansionLevel  = session.GameAccount.BoxLevel;
                authResponse.SuccessInfo.AccountExpansionLevel = session.GameAccount.BoxLevel;
                authResponse.SuccessInfo.AvailableRaces        = Manager.GameAccount.GetAvailableRaces(session.GameAccount, session.Realm);
                authResponse.SuccessInfo.AvailableClasses      = Manager.GameAccount.GetAvailableClasses(session.GameAccount, session.Realm);
                authResponse.SuccessInfo.Templates             = Manager.GameAccount.GetAvailableCharacterTemplates(session.GameAccount, session.Realm);

                await session.Send(authResponse);

                AddonHandler.HandleAddonInfo(session, addonData);

                await session.Send(new TutorialFlags());
            }
            else
            {
                await session.Send(authResponse);
            }
        }
Example #6
0
        public static async void SendConnectTo(CharacterSession session, string ip, ushort port, byte connection = 0)
        {
            var connectTo = new ConnectTo
            {
                Key    = Manager.Redirect.CreateRedirectKey(session.GameAccount.Id),
                Serial = 0xE,
                Con    = connection
            };

            // Fail
            if (connectTo.Key == 0)
            {
                session.Dispose();

                return;
            }

            var payloadData = new byte[0xFF];
            var ipBytes     = IPAddress.Parse(ip).GetAddressBytes();

            // 0 - 15, Address, IPv6 not supported for now
            payloadData[0] = ipBytes[0];
            payloadData[1] = ipBytes[1];
            payloadData[2] = ipBytes[2];
            payloadData[3] = ipBytes[3];

            // 16
            payloadData[16] = 0x01;

            // 17 - 20, adler32, changes with compression seed.
            // Let's use a static one for now
            payloadData[17] = 0x43;
            payloadData[18] = 0xfd;
            payloadData[19] = 0xb8;
            payloadData[20] = 0x22;

            // 21
            payloadData[21] = 0x2A;

            var portBytes = BitConverter.GetBytes(port);

            // 22 - 23, Port
            payloadData[22] = portBytes[0];
            payloadData[23] = portBytes[1];

            var msg = "Blossom opens above\nSpines rising to the air\nArctium grows stronger\n\0\0\0\0";

            // 24 - 94, Haiku
            Array.Copy(Encoding.ASCII.GetBytes(msg), 0, payloadData, 24, 71);

            // 94 - 125, static for now...
            Array.Copy(new byte[] { 0xD6, 0xAC, 0x21, 0xE6, 0xB2, 0x7B, 0x06, 0x3D, 0xA9, 0x9C, 0x09, 0x4B, 0xC7, 0x30, 0x48, 0x34, 0xD4, 0xF0, 0x55, 0x3B, 0x1B, 0x1D, 0xC9, 0x5B, 0xFD, 0x3C, 0xB9, 0x30, 0x9D, 0xF5, 0x40, 0xC0 }, 0, payloadData, 94, 32);

            // 126 - 233, 0 for now
            Array.Copy(new byte[108], 0, payloadData, 126, 108);

            // 234 - 253, ranodm for now
            Array.Copy(new byte[0].GenerateRandomKey(20), 0, payloadData, 234, 20);

            var dataOrder = new byte[payloadData.Length];

            for (var i = 0; i < payloadData.Length; i++)
            {
                dataOrder[i] = payloadData[ConnectTo.PayloadOrder[i]];
            }

            var encrypted = Manager.Redirect.Crypt.Encrypt(dataOrder);

            Array.Copy(encrypted, connectTo.Where, 0x100);

            await session.Send(connectTo);
        }