using System; using System.Net; using System.Text; using System.Linq; using System.Threading; using System.Net.Sockets; using System.Collections.Generic; using FilterAPI; using FilterAPI.Networking; using FilterAPI.CustomCurrency; namespace FilterLauncher.LauncherNetworking { internal class LauncherClient : IDisposable { private Socket ClientSocket; private IPEndPoint ClientEndPoint; private Byte[] ClientBuffer; private Int32 IsConnected; public LauncherClient(Socket AcceptedSocket, IPEndPoint AcceptedEndPoint) { ClientSocket = AcceptedSocket; ClientEndPoint = AcceptedEndPoint; if (Program.SQL.GetbBlockForsIP(Convert.ToString(ClientEndPoint.Address)) || Program.SQL.GetnAmountForsIP(Convert.ToString(ClientEndPoint.Address)) >= Convert.ToInt64(Program.Auth.ConfigValues["MaximumCPIP"])) { Disconnect(); return; } ClientBuffer = new Byte[1024]; try { ClientSocket.BeginReceive(ClientBuffer, 0, ClientBuffer.Length, SocketFlags.None, new AsyncCallback(TokenReceived), null); } catch { Disconnect(); } } private void TokenReceived(IAsyncResult Result) { if (IsConnected != 0) { return; } Int32 ReceivedLength = 0; try { ReceivedLength = ClientSocket.EndReceive(Result); } catch { Disconnect(); return; } if (ReceivedLength >= 1) { try { Array.Resize(ref ClientBuffer, ReceivedLength); String HTTPRequest = Encoding.ASCII.GetString(ClientBuffer).Split(new String[] { " HTTP/1.1" }, StringSplitOptions.None)[0].Replace("GET /", "").Replace("?", "").Split('\n')[0]; String[] HTTPRequestSplit = HTTPRequest.Split('&'); Dictionary HTTPParameters = new Dictionary(); foreach (String HTTPParameter in HTTPRequestSplit) { HTTPParameters.Add(HTTPParameter.Split('=')[0], HTTPParameter.Split('=')[1]); } if (HTTPParameters.ContainsKey("Type")) { if (HTTPParameters["Type"] == "Ping") { SendResponse("Pong"); } else if (HTTPParameters["Type"] == "Login" && HTTPParameters.ContainsKey("Username") && HTTPParameters.ContainsKey("Password")) { String Username = HTTPParameters["Username"]; String Password = HTTPParameters["Password"]; if (Injection.ContainsOnlyLetterOrDigit(Username) && Injection.ContainsOnlyLetterOrDigit(Password)) { if (Username.Length <= 16 || Password.Length <= 32) { if (!Program.SQL.sUsernameExists(Username) || !Program.SQL.sUserPassMatchsUsername(Username, Password)) { SendResponse("Usernamme/Password is incorrect."); Program.SendConsoleText(ConsoleColor.Gray, "Username/Password was entered incorrectly with {0} as username.", Username); } else { Int32 nEMID = Program.SQL.GetnEMIDFromsUsername(Username); String sToken = Program.SQL.CreateAndInsertsTokenFornEMID(Program.SQL.GetnEMIDFromsUsername(Username)); Currency MallCurrency = Program.Currencies.Currencies.Where(CurrencyID => CurrencyID.CurrencyID == Convert.ToByte(Program.Auth.ConfigValues["PaymentMCID"])).FirstOrDefault(); Boolean ShowMessage; String sRecoveryKey = Program.SQL.GetsRecoveryKeyFornUserNo(nEMID, out ShowMessage); SendResponse(String.Format("Success#{0}#{1}#{2}#{3}#{4}", sToken, nEMID, Program.SQL.GetAmountForCC(MallCurrency.TableName, "nUserNo", nEMID), ShowMessage, sRecoveryKey)); Program.SendConsoleText(ConsoleColor.Gray, "Successful login. sUsername: {0}. nEMID: {1}. sToken: {2}. Mall Points: {3}. sReceoveryKey: {4}.", Username, nEMID, sToken, Program.SQL.GetAmountForCC(MallCurrency.TableName, "nUserNo", nEMID), sRecoveryKey); } } } } else if (HTTPParameters["Type"] == "Register" && HTTPParameters.ContainsKey("Username") && HTTPParameters.ContainsKey("Password")) { String Username = HTTPParameters["Username"]; String Password = HTTPParameters["Password"]; if (Injection.ContainsOnlyLetterOrDigit(Username) && Injection.ContainsOnlyLetterOrDigit(Password)) { if (Username.Length <= 16 || Password.Length <= 32) { if (Program.SQL.sUsernameExists(Username)) { SendResponse("The username already exists. Please try another one."); Program.SendConsoleText(ConsoleColor.Gray, "New register from {0}, but username was taken.", Username); } else { Program.SQL.InsertNewtAccount(Username, Password); SendResponse(String.Format("Success#The account has been registered. Username: {0}. Password: {1}.", Username, Password)); Program.SendConsoleText(ConsoleColor.Gray, "New account registered. sUsername: {0}.", Username); } } } } else if (HTTPParameters["Type"] == "PasswordChange" && HTTPParameters.ContainsKey("Username") && HTTPParameters.ContainsKey("OldPassword") && HTTPParameters.ContainsKey("NewPassword")) { String Username = HTTPParameters["Username"]; String OldPassword = HTTPParameters["OldPassword"]; String NewPassword = HTTPParameters["NewPassword"]; if (Injection.ContainsOnlyLetterOrDigit(Username) && Injection.ContainsOnlyLetterOrDigit(OldPassword) && Injection.ContainsOnlyLetterOrDigit(NewPassword)) { if (Username.Length <= 16 || OldPassword.Length <= 32 || NewPassword.Length <= 32) { if (!Program.SQL.sUsernameExists(Username) || !Program.SQL.sUserPassMatchsUsername(Username, OldPassword)) { SendResponse("Usernamme/Old-Password is incorrect."); Program.SendConsoleText(ConsoleColor.Gray, "Someone tried to change their password but entered incorrect old information. This could be some kind of attempt at injection. sUsername: {0}", Username); } else if (Program.SQL.ChecksPassword(Program.SQL.GetnEMIDFromsUsername(Username), NewPassword)) { SendResponse(String.Format("You have previously used the password {0}. Please use another one (this is to try and help protect your account C:).", NewPassword)); Program.SendConsoleText(ConsoleColor.Gray, "Someone tried to change their password but used a password they have used in the past. sUsername: {0}.", Username); } else { Program.SQL.SetsUserPassForsUsername(Username, NewPassword); Program.SQL.InsertIntotPasswordChange(Program.SQL.GetnEMIDFromsUsername(Username), OldPassword); SendResponse(String.Format("Success#Password for {0} has been updated to {1}.", Username, NewPassword)); Program.SendConsoleText(ConsoleColor.Gray, "Password updated. Username: {0}.", Username); } } } } else if (HTTPParameters["Type"] == "InformationRequest" && HTTPParameters.ContainsKey("ServerID") && HTTPParameters.ContainsKey("InformationType")) { if (Injection.IsInt32(HTTPParameters["ServerID"])) { Byte ServerID = Convert.ToByte(HTTPParameters["ServerID"]); String InformationType = Convert.ToString(HTTPParameters["InformationType"]); if (InformationType == "LauncherTitle") { SendResponse(Program.Auth.ConfigValues["LauncherTitle"]); } else if (InformationType == "LauncherVURL") { SendResponse(Program.Auth.ConfigValues["LauncherVURL"]); } else if (InformationType == "LauncherUURL") { SendResponse(Program.Auth.ConfigValues["LauncherUURL"]); } else if (InformationType == "LauncherSIPURL") { SendResponse(Program.Auth.ConfigValues["LauncherSIPURL"]); } else if (InformationType == "LauncherVGURL") { SendResponse(Program.Auth.ConfigValues["LauncherVGURL"]); } else if (InformationType == "LauncherVURL") { SendResponse(Program.Auth.ConfigValues["LauncherVURL"]); } else if (InformationType == "LauncherMGURL") { SendResponse(Program.Auth.ConfigValues["LauncherMGURL"]); } else if (InformationType == "LauncherMURL") { SendResponse(Program.Auth.ConfigValues["LauncherMURL"]); } else if (InformationType == "ServerCount") { SendResponse(Program.Auth.ConfigValues["LauncherSC"]); } else if (InformationType == "Donate") { SendResponse(Program.Auth.ConfigValues["SuperRewardsURL"]); } else if (InformationType == "ServerName") { SendResponse(Program.Auth.ConfigValues[String.Format("LauncherS{0}SN", ServerID)]); } else if (InformationType == "FolderName") { SendResponse(Program.Auth.ConfigValues[String.Format("LauncherS{0}FN", ServerID)]); } else if (InformationType == "VersionURL") { SendResponse(Program.Auth.ConfigValues[String.Format("LauncherS{0}VURL", ServerID)]); } else if (InformationType == "PatchesURL") { SendResponse(Program.Auth.ConfigValues[String.Format("LauncherS{0}PURL", ServerID)]); } else if (InformationType == "PatchLogURL") { SendResponse(Program.Auth.ConfigValues[String.Format("LauncherS{0}PLURL", ServerID)]); } else if (InformationType == "VersionFile") { SendResponse(Program.Auth.ConfigValues[String.Format("LauncherS{0}VF", ServerID)]); } else if (InformationType == "StartupParameter") { SendResponse(Program.Auth.ConfigValues[String.Format("LauncherS{0}SUP", ServerID)]); } } } else if (HTTPParameters["Type"] == "MaintenanceStatus" && HTTPParameters.ContainsKey("ServerID") && HTTPParameters.ContainsKey("Username")) { Byte ServerID = Convert.ToByte(HTTPParameters["ServerID"]); String Username = Convert.ToString(HTTPParameters["Username"]); if (Injection.ContainsOnlyLetterOrDigit(Username)) { if (Username.Length <= 16) { Boolean bInMaintenance = Program.SQL.GetbInMaintenanceFornServerID(ServerID); Byte nAuthID = Program.SQL.GetnAuthIDFromnEMID(Program.SQL.GetnEMIDFromsUsername(Username)); Boolean nLoginable; Byte nTypeID = Program.SQL.GetnTypeIDfromnAuthID(nAuthID, out nLoginable); if (bInMaintenance) { if (nLoginable) { SendResponse("True"); } else { SendResponse("False"); } } else { SendResponse("True"); } } } } else if (HTTPParameters["Type"] == "PasswordStatus" && HTTPParameters.ContainsKey("Username") && HTTPParameters.ContainsKey("Password")) { String Username = HTTPParameters["Username"]; String Password = HTTPParameters["Password"]; if (Injection.ContainsOnlyLetterOrDigit(Username) && Injection.ContainsOnlyLetterOrDigit(Password) && Username.Length <= 16 && Password.Length <= 32 && Program.SQL.sUsernameExists(Username) && Program.SQL.sUserPassMatchsUsername(Username, Password)) { String sMessage; DateTime dResetDate; Boolean HasRows = Program.SQL.GettForcePasswordRest(out sMessage, out dResetDate); if (HasRows) { DateTime dChangeDate = Program.SQL.GetLasttPasswordChange(Program.SQL.GetnEMIDFromsUsername(Username)); if (dResetDate > dChangeDate) { SendResponse(String.Concat("True#", sMessage)); } else { SendResponse("False#"); } } else { SendResponse("False#"); } } } //else if (Convert.ToBoolean(Program.Auth.ConfigValues["LauncherRE"]) && HTTPParameters["Type"] == "Rebirth" && HTTPParameters.ContainsKey("RType") && HTTPParameters.ContainsKey("Username") && HTTPParameters.ContainsKey("Password")) //{ // String Username = HTTPParameters["Username"]; // String Password = HTTPParameters["Password"]; // if (Injection.ContainsOnlyLetterOrDigit(Username) && Injection.ContainsOnlyLetterOrDigit(Password) && Username.Length <= 16 && Password.Length <= 32 && Program.SQL.sUsernameExists(Username) && Program.SQL.sUserPassMatchsUsername(Username, Password)) // { // Int32 nEMID = Program.SQL.GetnEMIDFromsUsername(Username); // if (HTTPParameters["RType"] == "LEC") // { // List RebirthablesIDs = Program.SQL.LoadRebirthablesIDs(nEMID); // String RebirthableString = String.Empty; // if (Program.SQL.GetLoginQueries(nEMID).Count == 0) // { // foreach (String RebirthablesID in RebirthablesIDs) { RebirthableString += String.Concat(RebirthablesID, "#"); } // } // SendResponse(RebirthableString.TrimEnd('#')); // } // else if (HTTPParameters["RType"] == "RC" && HTTPParameters.ContainsKey("Name")) // { // String Name = HTTPParameters["Name"]; // if (Name.Length <= 16 && Injection.ContainsOnlyLetterOrDigit(HTTPParameters["Name"]) && Program.SQL.sIDOwnedBynUserNo(Name, nEMID) && Program.SQL.GetnLevelFromsID(Name) == Convert.ToByte(Program.Auth.ConfigValues["RebirthLevel"])) // { // Int32 nUserNo = Program.SQL.GetnEMIDFromsUsername(HTTPParameters["Username"]); // Int32 nCharNo = Program.SQL.GetnCharNoFromsID(Name); // if (Program.SQL.nCharNoReachedMaxRebirth(nCharNo)) { SendResponse(String.Format("This character has reached its maximum amount of rebirths. Maximum rebirths: {0}.", Program.Auth.ConfigValues["RebirthMaximum"])); } // else if (Program.SQL.GetnMoneyFornCharNo(nCharNo) < Convert.ToInt64(Program.Auth.ConfigValues["RebirthMoney"])) { SendResponse(String.Format("You do not have enough money on the character {0}. You need to have atleast {1} to rebirth.", Name, Money.ConvertMoney(Convert.ToInt64(Program.Auth.ConfigValues["RebirthMoney"])))); } // //else if (Program.SQL.GetItemsFromnStorageType(nCharNo, 8).Count != 0) { SendResponse("Please unequip everything from your character before trying to rebirth again."); } // //else if (Program.SQL.GetOnlinesIDs().Contains(Name)) { SendResponse("Your character is currently on the server please either go to character select or close your game."); } // else // { // using (var LocalPacket = new Packet(4, 7)) // { // LocalPacket.PacketWriter.Write(Name); // LocalPacket.PacketWriter.Write(true); // LocalPacket.PacketWriter.Write("Server"); // LocalPacket.PacketWriter.Write("You have been disconnected from the server by the rebirth system, this is to prevent your level from bugging when it is set! C:"); // Program.LocalClient.SendPacket(LocalPacket); // } // Program.SQL.DecreasenMoneyFornCharNo(nCharNo, Convert.ToInt64(Program.Auth.ConfigValues["RebirthMoney"])); // Program.SQL.DeletenStorageTypeFornCharNo(nCharNo, 2); // Program.SQL.InserttLoginQuery(nUserNo, String.Format("UPDATE {0}..tCharacter SET nLevel = '{1}', nExp = '{2}' WHERE nCharNo = '{3}'", Program.Auth.ConfigValues["CharacterDB"], Program.Auth.ConfigValues["RebirthSetLevel"], Program.Auth.ConfigValues["RebirthSetExp"], nCharNo)); // Program.SQL.InserttRebirth(nCharNo); // SendResponse("Success#The character has been rebirthed successfully!"); // } // } // } // } //} //else if (Convert.ToBoolean(Program.Auth.ConfigValues["LauncherCCE"]) && HTTPParameters["Type"] == "ClickCookie" && HTTPParameters.ContainsKey("Username") && HTTPParameters.ContainsKey("Password")) //{ // String Username = HTTPParameters["Username"]; // String Password = HTTPParameters["Password"]; // if (Injection.ContainsOnlyLetterOrDigit(Username) && Injection.ContainsOnlyLetterOrDigit(Password) && Username.Length <= 16 && Password.Length <= 32 && Program.SQL.sUsernameExists(Username) && Program.SQL.sUserPassMatchsUsername(Username, Password)) // { // if (!Program.CCInfo.ContainsKey(Username)) { Program.CCInfo.Add(Username, DateTime.Now.AddSeconds(1).AddMilliseconds(500)); } // else if (Program.CCInfo[Username] > DateTime.Now) // { // SendResponse("TOO FAST SLOW DOWN"); // Disconnect(); // return; // } // else if (Program.CCInfo[Username] < DateTime.Now) { Program.CCInfo[Username] = DateTime.Now; } // Int32 nEMID = Program.SQL.GetnEMIDFromsUsername(Username); // Program.SQL.InserttCookieClicker(nEMID); // Program.SQL.PutMoneyInStorage(nEMID, 100000); // SendResponse(Program.SQL.GetnTotalClicksFornUserNo(nEMID)); // Program.CCInfo[Username] = DateTime.Now.AddSeconds(1).AddMilliseconds(500); // } //} else if (HTTPParameters["Type"] == "GiveCoins" && HTTPParameters.ContainsKey("Username") && HTTPParameters.ContainsKey("Password") && HTTPParameters.ContainsKey("GiveUsername") && HTTPParameters.ContainsKey("Amount")) { String Username = HTTPParameters["Username"]; String Password = HTTPParameters["Password"]; String GiveUsername = HTTPParameters["GiveUsername"]; if (Injection.ContainsOnlyLetterOrDigit(Username) && Injection.ContainsOnlyLetterOrDigit(Password) && Username.Length <= 16 && Password.Length <= 32 && Program.SQL.sUsernameExists(Username) && Program.SQL.sUserPassMatchsUsername(Username, Password) && Injection.ContainsOnlyLetterOrDigit(GiveUsername) && GiveUsername.Length <= 16) { Boolean AmountIsInt = false; Int32 Amount = 0; try { Amount = Convert.ToInt32(HTTPParameters["Amount"]); AmountIsInt = true; } catch { } if (AmountIsInt) { if (Amount <= 0) { SendResponse(String.Format("{0} is not a valid amount to give.", Amount)); } else { Int32 nEMID = Program.SQL.GetnEMIDFromsUsername(Username); Currency MallCurrency = Program.Currencies.Currencies.Where(CurrencyID => CurrencyID.CurrencyID == Convert.ToByte(Program.Auth.ConfigValues["PaymentMCID"])).FirstOrDefault(); Int64 CurrentAmount = Program.SQL.GetAmountForCC(MallCurrency.TableName, "nUserNo", nEMID); if (Amount > CurrentAmount) { SendResponse(String.Format("You cannot give {0} coins as you only have {1}.", Amount, CurrentAmount)); } else if (!Program.SQL.sUsernameExists(GiveUsername)) { SendResponse(String.Format("{0} does not exist in our database.", GiveUsername)); } else { Program.SQL.MinusAmountForCC(MallCurrency.TableName, Amount, "nUserNo", nEMID); Program.SQL.AddAmountForCC(MallCurrency.TableName, Amount, "nUserNo", Program.SQL.GetnEMIDFromsUsername(GiveUsername)); SendResponse(String.Format("Success#{0}#{1} coins have been given to {2} you now have {0} coins left.", CurrentAmount - Amount, Amount, GiveUsername)); } } } } } else if (HTTPParameters["Type"] == "PSCKey" && HTTPParameters.ContainsKey("Username") && HTTPParameters.ContainsKey("Key") && HTTPParameters.ContainsKey("Amount")) { String Username = HTTPParameters["Username"]; String Key = HTTPParameters["Key"]; if (Injection.ContainsOnlyLetterOrDigit(Username) && Injection.ContainsOnlyLetterOrDigit(Username) && Username.Length <= 16) { if (Injection.CheckPSC(Key) || Key.Length != 19) { SendResponse("The PSC you tried to send to the server is invalid. PSC are 19 in length and they look like this: \"1234-1234-1234-1234\" or \"1234 1234 1234 1234\"."); } else if (Program.SQL.tPSCRowExists(Program.SQL.GetnEMIDFromsUsername(Username), Key)) { SendResponse("You have already sent this key to our server."); } else { Boolean AmountIsDouble = false; Double Amount = 0; try { Amount = Convert.ToDouble(HTTPParameters["Amount"]); AmountIsDouble = true; } catch { } if (AmountIsDouble) { if (Amount <= 0) { SendResponse(String.Format("{0} is not a valid amount for PSC.", Amount)); } //else if (Amount > 25) { SendResponse(String.Format("{0} we can no longer accept cards that have more than 25 EUR on them, as PSC believe that it is a security risk since it is being used from a different country. Sorry for the inconvience. Please do not send the code with amount 25 as if we cannot use it we will no longer accept it. Thanks for understanding!")); } else if (Amount > 500) { SendResponse(String.Format("{0} is too high of an amount for PSC.", Amount)); } else { Program.SQL.InserttPSC(Program.SQL.GetnEMIDFromsUsername(Username), Key, Amount); SendResponse("Success#The key has been saved to the server and will be processed soon!"); } } } } } else if (HTTPParameters["Type"] == "Unstuck" && HTTPParameters.ContainsKey("UType") && HTTPParameters.ContainsKey("Username") && HTTPParameters.ContainsKey("Password")) { String Username = HTTPParameters["Username"]; String Password = HTTPParameters["Password"]; if (Injection.ContainsOnlyLetterOrDigit(Username) && Injection.ContainsOnlyLetterOrDigit(Password) && Username.Length <= 16 && Password.Length <= 32 && Program.SQL.sUsernameExists(Username) && Program.SQL.sUserPassMatchsUsername(Username, Password)) { Int32 nEMID = Program.SQL.GetnEMIDFromsUsername(Username); if (HTTPParameters["UType"] == "LUC") { List UnstucksIDs = Program.SQL.GetsIDsFornUserNo(nEMID); String UnstuckString = String.Empty; foreach (String UnstucksID in UnstucksIDs) { UnstuckString += String.Concat(UnstucksID, "#"); } SendResponse(UnstuckString.TrimEnd('#')); } else if (HTTPParameters["UType"] == "UC" && HTTPParameters.ContainsKey("Name")) { String Name = HTTPParameters["Name"]; if (Name.Length <= 16 && Injection.ContainsOnlyLetterOrDigit(HTTPParameters["Name"]) && Program.SQL.sIDOwnedBynUserNo(Name, nEMID) && Program.SQL.GetnLevelFromsID(Name) == Convert.ToByte(Program.Auth.ConfigValues["RebirthLevel"])) { Int32 nUserNo = Program.SQL.GetnEMIDFromsUsername(HTTPParameters["Username"]); Int32 nCharNo = Program.SQL.GetnCharNoFromsID(Name); using (var LocalPacket = new Packet(4, 7)) { LocalPacket.PacketWriter.Write(Name); LocalPacket.PacketWriter.Write(true); LocalPacket.PacketWriter.Write("Server"); LocalPacket.PacketWriter.Write("You have been disconnected from the server by the unstuck system, this is to prevent your location from bugging when it is set!"); Program.LocalClient.SendPacket(LocalPacket); } Program.SQL.InserttLoginQuery(nUserNo, String.Format("UPDATE {0}..tCharacter SET sLoginZone = '{1}' WHERE nCharNo = '{2}'", Program.Auth.ConfigValues["CharacterDB"], Program.Auth.ConfigValues["LauncherUMI"], nCharNo)); SendResponse("Success#The character has been moved successfully!"); } } } } Disconnect(); } } catch { } } else { Disconnect(); } } private void SendResponse(String Text) { String ResponseData = String.Empty; ResponseData = String.Concat(ResponseData, "HTTP/1.1 200 OK", Environment.NewLine); ResponseData = String.Concat(ResponseData, "Date: ", String.Format("{0:r}", DateTime.Now), Environment.NewLine); ResponseData = String.Concat(ResponseData, "Server: Kobalts Web Server.", Environment.NewLine); ResponseData = String.Concat(ResponseData, "Content-Length: ", Text.Length, Environment.NewLine); ResponseData = String.Concat(ResponseData, "Content-Type: text/html", Environment.NewLine); ResponseData = String.Concat(ResponseData, Environment.NewLine); ResponseData = String.Concat(ResponseData, Text); ClientSocket.Send(Encoding.ASCII.GetBytes(ResponseData)); } private void Disconnect() { if (IsConnected == 0 && Interlocked.CompareExchange(ref IsConnected, 1, 0) == 0) { try { ClientSocket.Dispose(); } catch { } ClientEndPoint = null; ClientBuffer = new Byte[0]; } } ~LauncherClient() { Dispose(); } public void Dispose() { Disconnect(); } } }