/// <summary>
        /// Loads an account from the mysql database using the given character details.
        /// </summary>
        /// <param name="details">The details used to load the account.</param>
        /// <returns>Returns the account load result.</returns>
        public AccountLoadResult Load(Details details, LoginConnectionType loginType)
        {
            AccountLoadResult result = new AccountLoadResult();

            if (GameEngine.World.SystemUpdate)
            {
                result.Character  = new Character(details, 0);
                result.ReturnCode = LoginReturnCode.SystemUpdate;
            }
            try
            {
                DataRow data = null;
                using (SqlDatabaseClient client = GameServer.Database.GetClient())
                {
                    /*
                     * Checks if the character exists in the database. It also
                     * checks if the given password matches the stored password.
                     */
                    client.AddParameter("username", details.Username);
                    client.AddParameter("password", details.Password);
                    data = client.ReadDataRow("SELECT * FROM characters LEFT JOIN (character_preferences) ON (characters.id = character_preferences.master_id) WHERE username = @username AND password = @password LIMIT 1;");
                }

                if (data != null) // Meaning the character exists, and the password is correct.
                {
                    result.Character = new Character(details, (uint)data[0]);

                    // If a character is offensive, set the proper penalties.
                    OffenceType offence = (OffenceType)GameEngine.World.OffenseManager.GetOffence(result.Character.MasterId);
                    if (offence == OffenceType.Banned) // If the character is banned, flag and end this request.
                    {
                        result.ReturnCode = LoginReturnCode.AccountDisabled;
                    }
                    if (offence == OffenceType.Muted) // If the character is muted, we will mute this character.
                    {
                        result.Character.Muted = true;
                    }

                    /*
                     * Only check if it's a new connection, as reconnections try
                     * connnecting to the server before the older session is removed,
                     * so we must ignore whether or not the character is online.
                     */
                    if (loginType != LoginConnectionType.Reconnection && (bool)data[5])
                    {
                        result.ReturnCode = LoginReturnCode.AlreadyOnline;
                    }

                    /*
                     * We only want to assign the character details loaded from
                     * the database if the player has passed though security.
                     */
                    if (result.ReturnCode == LoginReturnCode.Successful)
                    {
                        // Core info.
                        result.Character.ClientRights = (ClientRights)data[3];
                        result.Character.ServerRights = (ServerRights)data[4];
                        result.Active = (bool)data[6];

                        // Appearance.
                        result.Character.Appearance.Gender     = (Gender)data[14];
                        result.Character.Appearance.Head       = (short)data[15];
                        result.Character.Appearance.Torso      = (short)data[16];
                        result.Character.Appearance.Arms       = (short)data[17];
                        result.Character.Appearance.Wrist      = (short)data[18];
                        result.Character.Appearance.Legs       = (short)data[19];
                        result.Character.Appearance.Feet       = (short)data[20];
                        result.Character.Appearance.Beard      = (short)data[21];
                        result.Character.Appearance.HairColor  = (byte)data[22];
                        result.Character.Appearance.TorsoColor = (byte)data[23];
                        result.Character.Appearance.LegColor   = (byte)data[24];
                        result.Character.Appearance.FeetColor  = (byte)data[25];
                        result.Character.Appearance.SkinColor  = (byte)data[26];

                        // Location.
                        result.Character.Location = Location.Create((short)data[27], (short)data[28], (byte)data[29]);

                        // Energy.
                        result.Character.WalkingQueue.RunEnergy = (byte)data[30];

                        // Containers.
                        if (data[31] is string)
                        {
                            result.Character.Inventory.Deserialize((string)data[31]);
                        }
                        if (data[32] is string)
                        {
                            result.Character.Equipment.Deserialize((string)data[32]);
                        }
                        if (data[33] is string)
                        {
                            result.Character.Bank.Deserialize((string)data[33]);
                        }

                        // Friends and ignores
                        if (data[34] is string)
                        {
                            string friends = (string)data[34];
                            if (friends != string.Empty)
                            {
                                result.Character.Contacts.DeserializeFriends(friends);
                            }
                        }
                        if (data[35] is string)
                        {
                            string ignores = (string)data[35];
                            if (ignores != string.Empty)
                            {
                                result.Character.Contacts.DeserializeIgnores((string)data[35]);
                            }
                        }

                        // Preferences.
                        result.Character.Preferences.SingleMouse        = (bool)data[37];
                        result.Character.Preferences.DisableChatEffects = (bool)data[38];
                        result.Character.Preferences.SplitChat          = (bool)data[39];
                        result.Character.Preferences.AcceptAid          = (bool)data[40];
                    }
                }
                else // User doesn't exist or password is wrong.
                {
                    result.Character  = new Character(details, 0);
                    result.ReturnCode = LoginReturnCode.WrongPassword;
                }
            }
            catch (Exception ex)
            {
                Program.Logger.WriteException(ex);
                result.Character  = new Character(details, 0);
                result.ReturnCode = LoginReturnCode.BadSession;
            }
            return(result);
        }
Exemple #2
0
        /// <summary>
        /// Loads an account from the database.
        /// </summary>
        /// <param name="details">The character details to look at when loading.</param>
        public void LoadAccount(Details details, LoginConnectionType loginType)
        {
            StringBuilder         sbQuery  = new StringBuilder();
            AccountLoadResult     result   = this.accountLoader.Load(details, loginType); // Try to load the account.
            GenericPacketComposer composer = new GenericPacketComposer();                 // The packet going to be sent.

            // Try registering the user if return code is successful so far.
            if (result.ReturnCode == LoginReturnCode.Successful)
            {
                // The world is full.
                if (!Register(result.Character))
                {
                    result.ReturnCode = LoginReturnCode.WorldFull;
                }
            }

            composer.AppendByte((byte)result.ReturnCode);

            // We only need to send this if the login was successful.
            if (result.ReturnCode == LoginReturnCode.Successful)
            {
                composer.AppendByte((byte)result.Character.ClientRights);
                composer.AppendByte((byte)0);
                composer.AppendByte((byte)0);
                composer.AppendByte((byte)0);
                composer.AppendByte((byte)1);
                composer.AppendShort((short)result.Character.Index);
                composer.AppendByte((byte)1);

                if (this.logSessions)
                {
                    sbQuery.Append("UPDATE characters SET last_ip=@ip, last_signin=NOW() WHERE id = @id;");
                }
            }

            if (this.logAttempts)
            {
                sbQuery.Append("INSERT INTO login_attempts (username,date,ip,attempt) VALUES (@name, NOW(), @ip, @attempt);");
            }
            if (!result.Active)
            {
                sbQuery.Append("UPDATE characters SET active = '1' WHERE id = @id;");
            }
            if (sbQuery.Length != 0)
            {
                // Log the user's login attempt. This is useful for tracking hacking, ddos, etc.
                using (SqlDatabaseClient client = GameServer.Database.GetClient())
                {
                    client.AddParameter("id", result.Character.MasterId);
                    client.AddParameter("name", details.Username);
                    client.AddParameter("ip", details.Session.Connection.IPAddress);
                    client.AddParameter("attempt", result.ReturnCode.ToString());
                    client.ExecuteUpdate(sbQuery.ToString());
                }
            }

            // Send results to the client.
            result.Character.Session.SendData(composer.SerializeBuffer());

            // We can now welcome the player and send nessesary packets.
            if (result.ReturnCode == LoginReturnCode.Successful)
            {
                result.Character.Session.StartConnection();
                if (!result.Active)
                {
                    result.Character.Preferences.Add("just_started", true);
                }
                Frames.SendLoginWelcome(result.Character);
                result.Character.Contacts.OnLogin();
            }

            Program.Logger.WriteDebug(result.Character.Name + " returned " + result.ReturnCode + " at login attempt.");
        }
Exemple #3
0
        /// <summary>
        /// Processes the login verification.
        /// </summary>
        /// <param name="request">The request to process and verify.</param>
        /// <param name="type">The login connection type.</param>
        public static void Process(LoginRequest request, LoginConnectionType type)
        {
            short packetSize = -1;

            if (request.Buffer.RemainingAmount >= 2)
            {
                packetSize = request.Buffer.ReadShort(); // The size will vary depending on user's inputted username and password.
            }
            else
            {
                return;
            }

            if (request.Buffer.RemainingAmount >= packetSize)
            {
                Packet p = new Packet(request.Buffer.GetRemainingData());
                int    encryptedPacketSize = packetSize - packetSize - (36 + 1 + 1 + 2); // Shouldn't be under 0.

                int clientVersion = p.ReadInt();
                if (clientVersion != 508) // Check to make sure the client is 508.
                {
                    request.LoginStage = -3;
                    return;
                }

                // Client preferences.
                bool  lowMemory = p.ReadByte() == 1 ? true : false;
                bool  hd        = p.ReadByte() == 1 ? true : false;
                bool  resized   = p.ReadByte() == 1 ? true : false;
                short width     = p.ReadShort();
                short height    = p.ReadShort();

                p.Skip(141);

                int tmpEncryptPacketSize = p.ReadByte();
                if (tmpEncryptPacketSize != 10)
                {
                    int encryptPacketId = p.ReadByte();
                }

                // Session data.
                long clientKey = p.ReadLong(); // The client's session key.
                long serverKey = p.ReadLong(); // The client's server session key.

                // Hash verification.
                long longName = p.ReadLong();
                int  hash     = (int)(31 & longName >> 16); // Verify client session hash.
                if (hash != request.NameHash)               // Possibly a bot attack.
                {
                    request.LoginStage = -3;
                    return;
                }

                // User data.
                string username = longName.LongToString();
                string password = Hash.GetHash(username + Hash.GetHash(
                                                   p.ReadString(), HashType.SHA1), HashType.SHA1);

                // Try to load the account with the given details.
                Details details = new Details(request.Connection, username, password, hd, resized, clientKey, serverKey);
                Program.Logger.WriteDebug("Login request: " + details.ToString());
                GameEngine.World.CharacterManager.LoadAccount(details, type);
                request.Finished = true;
            }
            return;
        }