/// <summary>
        /// Client wanted to transfer to a city server.
        /// </summary>
        public static void HandleCityTokenRequest(NetworkClient Client, ProcessedPacket P)
        {
            string AccountName = P.ReadString();
            string CityGUID    = P.ReadString();
            string CharGUID    = P.ReadString();

            if (AccountName == string.Empty || CityGUID == string.Empty || CharGUID == string.Empty)
            {
                return;
            }

            Guid     Token   = Guid.NewGuid();
            CityInfo CServer = NetworkFacade.CServerListener.GetCityServer(CityGUID);

            using (var db = DataAccess.Get())
            {
                Account Acc = db.Accounts.GetByUsername(AccountName);

                PacketStream CServerPacket = new PacketStream(0x01, 0);
                CServerPacket.WriteHeader();

                ushort PacketLength = (ushort)(PacketHeaders.UNENCRYPTED + 1 + 4 + (Client.RemoteIP.Length + 1)
                                               + 4 + (CharGUID.ToString().Length + 1) + (Token.ToString().Length + 1));
                CServerPacket.WriteUInt16(PacketLength);

                CServerPacket.WriteByte(0);                 //CharacterCreate = false.
                CServerPacket.WriteInt32(Acc.AccountID);
                CServerPacket.WriteString(Client.RemoteIP);
                CServerPacket.WriteInt32(Client.RemotePort);
                CServerPacket.WriteString(CharGUID.ToString());
                CServerPacket.WriteString(Token.ToString(""));
                CServer.Client.Send(CServerPacket.ToArray());
            }
        }
        /// <summary>
        /// Client wanted to retire a character.
        /// </summary>
        public static void HandleCharacterRetirement(NetworkClient Client, ProcessedPacket P)
        {
            PacketStream Packet;

            string AccountName = P.ReadString();
            string GUID        = P.ReadString();

            if (AccountName == string.Empty || GUID == string.Empty)
            {
                return;
            }

            using (var db = DataAccess.Get())
            {
                Account Acc = db.Accounts.GetByUsername(AccountName);
                IQueryable <Character> Query = db.Characters.GetForAccount(Acc.AccountID);

                //F**K, I hate LINQ.
                Guid      CharGUID = new Guid(GUID);
                Character Char     = Query.Where(x => x.GUID == CharGUID).SingleOrDefault();

                if (Char != null)
                {
                    db.Characters.RetireCharacter(Char);
                }
                else
                {
                    return;
                }

                //This actually updates the record, not sure how.
                Acc.NumCharacters--;

                if (Char != null)
                {
                    CityInfo CInfo = NetworkFacade.CServerListener.GetCityServer(Char.City);

                    //Just in case...
                    if (CInfo != null)
                    {
                        Packet = new PacketStream(0x02, 0);
                        Packet.WriteHeader();

                        ushort PacketLength = (ushort)(PacketHeaders.UNENCRYPTED + 4 + GUID.Length + 1);

                        Packet.WriteUInt16(PacketLength);
                        Packet.WriteInt32(Acc.AccountID);
                        Packet.WriteString(GUID);
                        CInfo.Client.Send(Packet.ToArray());
                    }
                }
            }

            Packet = new PacketStream((byte)PacketType.RETIRE_CHARACTER_STATUS, 0);
            Packet.WriteString(GUID);
            Client.SendEncrypted((byte)PacketType.RETIRE_CHARACTER_STATUS, Packet.ToArray());
        }
        /// <summary>
        /// Client wanted to retire a character.
        /// </summary>
        public static void HandleCharacterRetirement(NetworkClient Client, ProcessedPacket P)
        {
            PacketStream Packet;

            string AccountName = P.ReadPascalString();
            string GUID        = P.ReadPascalString();

            using (var db = DataAccess.Get())
            {
                Account Acc = db.Accounts.GetByUsername(AccountName);
                IQueryable <Character> Query = db.Characters.GetForAccount(Acc.AccountID);

                //F**K, I hate LINQ.
                Guid      CharGUID = new Guid(GUID);
                Character Char     = Query.Where(x => x.GUID == CharGUID).SingleOrDefault();

                //If this is the case, char likely didn't exist in DB, so proceed as normal, client will delete cache.
                if (Char != null)
                {
                    db.Characters.RetireCharacter(Char);
                }

                //This actually updates the record, not sure how.
                Acc.NumCharacters--;

                for (int i = 0; i < NetworkFacade.CServerListener.CityServers.Count; i++)
                {
                    if (Char != null) //Assume char didn't exist in city either.
                    {
                        if (NetworkFacade.CServerListener.CityServers[i].ServerInfo.Name == Char.CityName)
                        {
                            Packet = new PacketStream(0x02, 0);
                            Packet.WriteHeader();

                            ushort PacketLength = (ushort)(PacketHeaders.UNENCRYPTED + 4 + GUID.Length + 1);

                            Packet.WriteUInt16(PacketLength);
                            Packet.WriteInt32(Acc.AccountID);
                            Packet.WritePascalString(GUID);
                            NetworkFacade.CServerListener.CityServers[i].Send(Packet.ToArray());

                            break;
                        }
                    }
                }
            }

            Packet = new PacketStream((byte)PacketType.RETIRE_CHARACTER_STATUS, 0);
            Packet.WritePascalString(GUID);
            Client.SendEncrypted((byte)PacketType.RETIRE_CHARACTER_STATUS, Packet.ToArray());
        }
Esempio n. 4
0
        public static void HandleCityTokenRequest(NetworkClient Client, ProcessedPacket P)
        {
            string AccountName = P.ReadPascalString();
            string CityGUID    = P.ReadPascalString();
            string CharGUID    = P.ReadPascalString();
            string Token       = new Guid().ToString();

            foreach (CityServerClient CServer in NetworkFacade.CServerListener.CityServers)
            {
                if (CityGUID == CServer.ServerInfo.UUID)
                {
                    using (var db = DataAccess.Get())
                    {
                        Account Acc = db.Accounts.GetByUsername(AccountName);

                        PacketStream CServerPacket = new PacketStream(0x01, 0);
                        CServerPacket.WriteHeader();

                        ushort PacketLength = (ushort)(PacketHeaders.UNENCRYPTED + 4 + (Client.RemoteIP.Length + 1)
                                                       + (CharGUID.ToString().Length + 1) + (Token.ToString().Length + 1));
                        CServerPacket.WriteUInt16(PacketLength);

                        CServerPacket.WriteInt32(Acc.AccountID);
                        CServerPacket.WritePascalString(Client.RemoteIP);
                        CServerPacket.WritePascalString(CharGUID.ToString());
                        CServerPacket.WritePascalString(Token.ToString());
                        CServer.Send(CServerPacket.ToArray());

                        break;
                    }
                }
            }

            PacketStream Packet = new PacketStream((byte)PacketType.REQUEST_CITY_TOKEN, 0);

            Packet.WritePascalString(Token);
            Client.SendEncrypted((byte)PacketType.REQUEST_CITY_TOKEN, Packet.ToArray());
        }
Esempio n. 5
0
        public static void HandleCharacterCreate(NetworkClient Client, ProcessedPacket P)
        {
            Logger.LogInfo("Received CharacterCreate!");

            string AccountName = SanitizeAccount(P.ReadPascalString());

            using (var db = DataAccess.Get())
            {
                Account Acc = db.Accounts.GetByUsername(AccountName);

                //TODO: Send GUID to client...
                Sim Char = new Sim(Guid.NewGuid());
                Char.Timestamp    = P.ReadPascalString();
                Char.Name         = P.ReadPascalString();
                Char.Sex          = P.ReadPascalString();
                Char.Description  = P.ReadPascalString();
                Char.HeadOutfitID = P.ReadUInt64();
                Char.BodyOutfitID = P.ReadUInt64();
                Char.Appearance   = (AppearanceType)P.ReadByte();
                Char.ResidingCity = new CityInfo(P.ReadPascalString(), "", P.ReadUInt64(), P.ReadPascalString(),
                                                 P.ReadUInt64(), P.ReadPascalString(), P.ReadInt32());
                Char.CreatedThisSession = true;

                var characterModel = new Character();
                characterModel.Name           = Char.Name;
                characterModel.Sex            = Char.Sex;
                characterModel.Description    = Char.Description;
                characterModel.LastCached     = Char.Timestamp;
                characterModel.GUID           = Char.GUID;
                characterModel.HeadOutfitID   = (long)Char.HeadOutfitID;
                characterModel.BodyOutfitID   = (long)Char.BodyOutfitID;
                characterModel.AccountID      = Acc.AccountID;
                characterModel.AppearanceType = (int)Char.Appearance;
                characterModel.City           = Char.ResidingCity.UUID;
                characterModel.CityName       = Char.ResidingCity.Name;
                characterModel.CityThumb      = (long)Char.ResidingCity.Thumbnail;
                characterModel.CityMap        = (long)Char.ResidingCity.Map;
                characterModel.CityIp         = Char.ResidingCity.IP;
                characterModel.CityPort       = Char.ResidingCity.Port;

                var status = db.Characters.CreateCharacter(characterModel);
                //Need to be variable length, because the success packet contains a token.
                PacketStream CCStatusPacket = new PacketStream((byte)PacketType.CHARACTER_CREATION_STATUS, 0);

                switch (status)
                {
                case LoginDataModel.Entities.CharacterCreationStatus.NameAlreadyExisted:
                    CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.NameAlreadyExisted);
                    Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray());
                    break;

                case LoginDataModel.Entities.CharacterCreationStatus.ExceededCharacterLimit:
                    CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.ExceededCharacterLimit);
                    Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray());
                    break;

                case LoginDataModel.Entities.CharacterCreationStatus.Success:
                    CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.Success);
                    CCStatusPacket.WritePascalString(Char.GUID.ToString());
                    Guid Token = Guid.NewGuid();
                    CCStatusPacket.WritePascalString(Token.ToString());
                    Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray());

                    foreach (CityServerClient CServer in NetworkFacade.CServerListener.CityServers)
                    {
                        if (CServer.ServerInfo.UUID == Char.ResidingCity.UUID)
                        {
                            PacketStream CServerPacket = new PacketStream(0x01, 0);
                            CServerPacket.WriteHeader();

                            ushort PacketLength = (ushort)(PacketHeaders.UNENCRYPTED + 4 + (Client.RemoteIP.Length + 1)
                                                           + (Char.GUID.ToString().Length + 1) + (Token.ToString().Length + 1));
                            CServerPacket.WriteUInt16(PacketLength);

                            CServerPacket.WriteInt32(Acc.AccountID);
                            CServerPacket.WritePascalString(Client.RemoteIP);
                            CServerPacket.WritePascalString(Char.GUID.ToString());
                            CServerPacket.WritePascalString(Token.ToString());
                            CServer.Send(CServerPacket.ToArray());

                            break;
                        }
                    }

                    break;
                }
            }

            //Client was modified, so update it.
            NetworkFacade.ClientListener.UpdateClient(Client);
        }
        /// <summary>
        /// Client sent a response to our challenge, as well as account name and password.
        /// </summary>
        public static void HandleChallengeResponse(NetworkClient Client, ProcessedPacket P)
        {
            PacketStream OutPacket;

            if (P.BufferLength <= 1)
            {
                OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 0);
                OutPacket.WriteByte(0x03);                 //Bad challenge response.
                Client.Send(OutPacket.ToArray());

                Logger.LogInfo("Bad challenge response - sent SLoginFailResponse!\r\n");
                return;                 //How does this even happen?!
            }

            int Length = P.ReadByte();

            byte[] CResponse;

            if (P.BufferLength >= Length)
            {
                CResponse = P.ReadBytes(Length);
            }
            else
            {
                return;
            }

            AESDecryptionArgs DecryptionArgs = Client.ClientEncryptor.GetDecryptionArgsContainer().AESDecryptArgs;

            if (DecryptionArgs.Challenge.SequenceEqual(CResponse))
            {
                string AccountName = SanitizeAccount(P.ReadString());

                Length = P.ReadByte();
                byte[] PasswordHash;

                if (P.BufferLength >= Length)
                {
                    PasswordHash = P.ReadBytes(Length);
                }
                else
                {
                    return;
                }

                // Check whether the accountname is empty or is/contains "username"
                if (AccountName == string.Empty || AccountName.ToLower().Equals("username") || AccountName.ToLower().Contains("username"))
                {
                    OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 0);
                    OutPacket.WriteHeader();
                    OutPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + 1));
                    OutPacket.WriteByte(0x01);
                    Client.Send(OutPacket.ToArray());

                    Logger.LogInfo(@"Bad accountname (""" + AccountName + @""") - sent SLoginFailResponse!\r\n");
                    Client.Disconnect();
                    return;
                }

                using (var db = DataAccess.Get())
                {
                    var account = db.Accounts.GetByUsername(AccountName);

                    if (!GlobalSettings.Default.CreateAccountsOnLogin)
                    {
                        Logger.LogInfo("Done reading LoginRequest, checking account...\r\n");

                        if (account == null)
                        {
                            OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 0);
                            OutPacket.WriteHeader();
                            OutPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + 1));
                            OutPacket.WriteByte(0x01);
                            Client.Send(OutPacket.ToArray());

                            Logger.LogInfo(@"Bad accountname (""" + AccountName + @""") - sent SLoginFailResponse!\r\n");
                            Client.Disconnect();
                            return;
                        }
                    }
                    else
                    {
                        if (account == null)
                        {
                            try
                            {
                                if (!AccountName.ToLower().Equals("username") || !AccountName.ToLower().Contains("username"))
                                {
                                    db.Accounts.Create(new Account
                                    {
                                        AccountName = AccountName.ToLower(),
                                        Password    = Convert.ToBase64String(PasswordHash)
                                    });
                                }
                            }
                            catch (Exception)
                            {
                                OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 0);
                                OutPacket.WriteHeader();
                                OutPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + 1));
                                OutPacket.WriteByte(0x01);
                                Client.Send(OutPacket.ToArray());

                                Logger.LogInfo(@"Bad accountname (""" + AccountName + @""") - sent SLoginFailResponse!\r\n");
                                Client.Disconnect();
                                return;
                            }

                            account = db.Accounts.GetByUsername(AccountName);
                        }
                    }

                    if (account.IsCorrectPassword(AccountName, PasswordHash))
                    {
                        OutPacket = new PacketStream((byte)PacketType.LOGIN_SUCCESS, 0);
                        OutPacket.WriteByte(0x01);
                        Client.ClientEncryptor.Username = AccountName;
                        Client.SendEncrypted((byte)PacketType.LOGIN_SUCCESS, OutPacket.ToArray());

                        Logger.LogInfo("Sent SLoginSuccessResponse!\r\n");
                        return;
                    }
                    else
                    {
                        OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 0);
                        OutPacket.WriteHeader();
                        OutPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + 1));
                        OutPacket.WriteByte(0x02);
                        Client.Send(OutPacket.ToArray());

                        Logger.LogInfo("Bad password - sent SLoginFailResponse!\r\n");
                        Client.Disconnect();
                        return;
                    }
                }
            }

            OutPacket = new PacketStream((byte)PacketType.LOGIN_FAILURE, 0);
            OutPacket.WriteHeader();
            OutPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED + 1));
            OutPacket.WriteByte(0x03);             //Bad challenge response.
            Client.Send(OutPacket.ToArray());

            Logger.LogInfo("Bad challenge response - sent SLoginFailResponse!\r\n");
            return;
        }
        /// <summary>
        /// Client created a character!
        /// </summary>
        public static void HandleCharacterCreate(NetworkClient Client, ProcessedPacket P)
        {
            Logger.LogInfo("Received CharacterCreate!");

            string AccountName = SanitizeAccount(P.ReadString());
            //Need to be variable length, because the success packet contains a token.
            PacketStream CCStatusPacket = new PacketStream((byte)PacketType.CHARACTER_CREATION_STATUS, 0);

            using (var db = DataAccess.Get())
            {
                Account Acc = db.Accounts.GetByUsername(AccountName);

                if (Acc.NumCharacters >= 3)
                {
                    CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.ExceededCharacterLimit);
                    Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray());

                    return;
                }

                //TODO: Send GUID to client...
                var    Char       = new Character();
                string LastCached = P.ReadString();
                if (LastCached == string.Empty)
                {
                    //TODO: Proper error...
                    CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.NameAlreadyExisted);
                    Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray());
                    return;
                }

                Char.LastCached     = ProtoHelpers.ParseDateTime(LastCached);
                Char.Name           = P.ReadString();
                Char.Sex            = P.ReadString();
                Char.Description    = P.ReadString();
                Char.GUID           = Guid.NewGuid();
                Char.HeadOutfitID   = (long)P.ReadUInt64();
                Char.BodyOutfitID   = (long)P.ReadUInt64();
                Char.AccountID      = Acc.AccountID;
                Char.AppearanceType = P.ReadByte();
                Char.CityName       = P.ReadString();
                Char.CityThumb      = (long)P.ReadUInt64();
                Char.City           = P.ReadString();
                Char.CityMap        = (long)P.ReadUInt64();
                Char.CityIp         = P.ReadString();
                Char.CityPort       = P.ReadInt32();
                Char.Money          = NetworkFacade.INITIAL_MONEY;

                //These are going into DB, so be nazi. Sieg heil!
                if (Char.Name == string.Empty || Char.Sex == string.Empty ||
                    Char.Description == string.Empty)
                {
                    CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.NameAlreadyExisted);
                    Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray());
                    return;
                }

                var status = db.Characters.CreateCharacter(Char);

                switch (status)
                {
                case LoginDataModel.Entities.CharacterCreationStatus.NameAlreadyExisted:
                    CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.NameAlreadyExisted);
                    Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray());
                    break;

                case LoginDataModel.Entities.CharacterCreationStatus.NameTooLong:
                    CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.NameTooLong);
                    Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray());
                    break;

                case LoginDataModel.Entities.CharacterCreationStatus.Success:
                    Guid Token = Guid.NewGuid();

                    //This actually updates the record, not sure how.
                    Acc.NumCharacters++;

                    //THIS NEEDS TO HAPPEN FIRST FOR CITY SERVER AUTHENTICATION TO WORK!
                    CityInfo CServer = NetworkFacade.CServerListener.GetCityServer(Char.City);

                    //Just in case...
                    if (CServer != null)
                    {
                        PacketStream CServerPacket = new PacketStream(0x01, 0);
                        CServerPacket.WriteHeader();

                        ushort PacketLength = (ushort)(PacketHeaders.UNENCRYPTED + 1 + 4 + (Client.RemoteIP.Length + 1)
                                                       + 4 + (Char.GUID.ToString().Length + 1) + (Token.ToString().Length + 1));
                        CServerPacket.WriteUInt16(PacketLength);

                        CServerPacket.WriteByte(1);                                 //CharacterCreate = true
                        CServerPacket.WriteInt32(Acc.AccountID);
                        CServerPacket.WriteString(Client.RemoteIP);
                        CServerPacket.WriteInt32(Client.RemotePort);
                        CServerPacket.WriteString(Char.GUID.ToString());
                        CServerPacket.WriteString(Token.ToString(""));
                        CServer.Client.Send(CServerPacket.ToArray());
                    }

                    CCStatusPacket.WriteByte((int)LoginDataModel.Entities.CharacterCreationStatus.Success);
                    CCStatusPacket.WriteString(Char.GUID.ToString());
                    CCStatusPacket.WriteString(Token.ToString());
                    Client.SendEncrypted(CCStatusPacket.PacketID, CCStatusPacket.ToArray());

                    break;
                }
            }
        }
        /// <summary>
        /// Client wanted to log in!
        /// </summary>
        public static void HandleLoginRequest(NetworkClient Client, ProcessedPacket P)
        {
            try
            {
                Logger.LogInfo("Received LoginRequest!\r\n");

                byte Version1 = (byte)P.ReadByte();
                byte Version2 = (byte)P.ReadByte();
                byte Version3 = (byte)P.ReadByte();
                byte Version4 = (byte)P.ReadByte();

                string ClientVersion = Version1.ToString() + "." + Version2.ToString() + "." + Version3.ToString() +
                                       "." + Version4.ToString();

                if (ClientVersion != GlobalSettings.Default.ClientVersion)
                {
                    PacketStream OutPacket = new PacketStream((byte)PacketType.INVALID_VERSION, 2);
                    OutPacket.WriteHeader();
                    OutPacket.WriteByte(0x01);
                    Client.Send(OutPacket.ToArray());

                    Logger.LogInfo("Bad version - sent SInvalidVersion!\r\n");
                    Client.Disconnect();
                    return;
                }

                PacketStream EncryptedPacket = new PacketStream((byte)PacketType.LOGIN_NOTIFY, 0);
                EncryptedPacket.WriteHeader();

                AESEncryptor Enc = (AESEncryptor)Client.ClientEncryptor;

                if (Enc == null)
                {
                    Enc = new AESEncryptor("");
                }

                Enc.PublicKey          = P.ReadBytes((P.ReadByte()));
                Enc.NOnce              = P.ReadBytes((P.ReadByte()));
                Enc.PrivateKey         = NetworkFacade.ServerKey;
                Client.ClientEncryptor = Enc;

                MemoryStream StreamToEncrypt = new MemoryStream();
                BinaryWriter Writer          = new BinaryWriter(StreamToEncrypt);
                Writer.Write(Enc.Challenge, 0, Enc.Challenge.Length);
                Writer.Flush();

                byte[] EncryptedData = StaticStaticDiffieHellman.Encrypt(NetworkFacade.ServerKey,
                                                                         System.Security.Cryptography.ECDiffieHellmanCngPublicKey.FromByteArray(Enc.PublicKey,
                                                                                                                                                System.Security.Cryptography.CngKeyBlobFormat.EccPublicBlob), Enc.NOnce, StreamToEncrypt.ToArray());

                EncryptedPacket.WriteUInt16((ushort)(PacketHeaders.UNENCRYPTED +
                                                     (1 + NetworkFacade.ServerPublicKey.Length) +
                                                     (1 + EncryptedData.Length)));

                EncryptedPacket.WriteByte((byte)NetworkFacade.ServerPublicKey.Length);
                EncryptedPacket.WriteBytes(NetworkFacade.ServerPublicKey);
                EncryptedPacket.WriteByte((byte)EncryptedData.Length);
                EncryptedPacket.WriteBytes(EncryptedData);

                Client.Send(EncryptedPacket.ToArray());
            }
            //This should HOPEFULLY wade off clients sending unreadable (I.E old protocol) packets...
            catch (Exception E)
            {
                Logger.LogDebug("Error while handling login request, disconnecting client: " +
                                E.ToString());
                Client.Disconnect();
                return;
            }
        }