/// <summary> /// /// </summary> /// <param name="client"></param> /// <param name="packet"></param> /// <param name="messageNumber"></param> public void Parse(Client client, ref byte[] packet, uint messageNumber) { #region Setup... MemoryStream m_stream = new MemoryStream(packet); BinaryReader m_reader = new BinaryReader(m_stream); string encryptedPassword; int encPasswordLength; LoginWrong nb = new LoginWrong(); CheckLogin cbl = new CheckLogin(); CharacterName char_name = new CharacterName(); #endregion switch (messageNumber) { case 0x22: SaltAuthentication salt = new SaltAuthentication(); // Username and version info m_stream.Position = 24; client.accountName = Encoding.ASCII.GetString(m_reader.ReadBytes(40)).TrimEnd(char.MinValue); client.clientVersion = Encoding.ASCII.GetString(m_reader.ReadBytes(20)).TrimEnd(char.MinValue); m_reader.Close(); m_stream.Dispose(); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Client '" + client.accountName + "' connected using version '" + client.clientVersion + "'"); Console.ResetColor(); // Send Authentication Salt to client salt.SendPacket(client, out client.serverSalt); break; case 0x25: // Username and encrypted password m_stream.Position = 20; string loginAccountName = Encoding.ASCII.GetString(m_reader.ReadBytes(40)).TrimEnd(char.MinValue); encPasswordLength = IPAddress.NetworkToHostOrder(m_reader.ReadInt32()) - 1; // Login Key is Null Terminated. We do not need this Null Terminator. encryptedPassword = Encoding.ASCII.GetString(m_reader.ReadBytes(encPasswordLength)); m_reader.Close(); m_stream.Dispose(); if (cbl.IsLoginAllowed(client, loginAccountName) == false) { /* * Account name not found or client banned/otherwise not permitted on the server * Note, this is done here not in the above packet (0x22), even though we have * the username or the client will complain. Also a security measure as you can * not tell if an account name is correct or not, only if both the username and * password are correct. * * We also double check that the Account Name is the same as origionally sent * or there could be a possibility to log in with someone elses account. * */ Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Client '" + client.accountName + "' banned, not a valid username, or sent a malformed Authentication Packet"); Console.ResetColor(); client.Send(ref nb.wrongbyte); client.Server.DisconnectClient(client); break; } if (cbl.IsLoginCorrect(client, encryptedPassword) == false) { // Username/Password Incorrect Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Client '" + client.accountName + "' failed Authentication."); Console.ResetColor(); client.Send(ref nb.wrongbyte); client.Server.DisconnectClient(client); break; } else { // All's well, send CharacterList Packet CharacterListPacket charlist = new CharacterListPacket(); charlist.SendPacket(client, client.accountName); } break; case 0x16: // Player selected a character and client sends us selected characters ID m_stream.Position = 20; int selectedCharID = IPAddress.NetworkToHostOrder(m_reader.ReadInt32()); m_reader.Close(); m_stream.Dispose(); if (cbl.IsCharacterOnAccount(client, selectedCharID) == false) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Client '" + client.accountName + "' tried to log in as CharID " + selectedCharID + " but it is not on their account!"); Console.ResetColor(); // NV: Is this really what we want to send? Should find out sometime... client.Send(ref nb.wrongbyte); client.Server.DisconnectClient(client); break; } if (OnlineChars.IsOnline(selectedCharID) == true) { Console.WriteLine("Client '" + client.accountName + "' is trying to login, but the requested character is already logged in."); client.Send(ref nb.wrongbyte); client.Server.DisconnectClient(client); break; } OnlineChars.SetOnline(selectedCharID); IPAddress tempIP; if (IPAddress.TryParse(ConfigReadWrite.Instance.CurrentConfig.ZoneIP, out tempIP) == false) { IPHostEntry zoneHost = Dns.GetHostEntry(ConfigReadWrite.Instance.CurrentConfig.ZoneIP); foreach (IPAddress ip in zoneHost.AddressList) { if (ip.AddressFamily == AddressFamily.InterNetwork) { tempIP = ip; break; } } } byte[] ZoneIP = tempIP.GetAddressBytes(); byte[] ZonePort = BitConverter.GetBytes(Convert.ToInt32(ConfigReadWrite.Instance.CurrentConfig.ZonePort)); Byte[] pkt = new byte[] { 0xDF, 0xDF, 0x00, 0x01, 0x00, 0x01, 0x00, 0x26, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x61, 0x5B, // Server ID 0x00, 0x00, 0x00, 0x17, packet[20], packet[21], packet[22], packet[23], // character ID ZoneIP[0], ZoneIP[1], ZoneIP[2], ZoneIP[3], ZonePort[1], ZonePort[0], 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; client.Send(ref pkt); break; case 0x55: /* player ask for 'suggest name'; server sends 'random' name. */ m_stream.Position = 28; char_name.GetRandomName(client, IPAddress.NetworkToHostOrder(m_reader.ReadInt32())); break; case 0xf: /* client created new character */ Int32 character_id; bool start_in_sl = false; char_name.m_accountName = client.accountName; /* start reading packet */ m_stream.Position = 65; /* name length */ int m_name_len = IPAddress.NetworkToHostOrder(m_reader.ReadInt32()); /* name (as byte array) */ char_name.m_name = Encoding.ASCII.GetString(m_reader.ReadBytes(m_name_len)); /* breed */ char_name.m_breed = IPAddress.NetworkToHostOrder(m_reader.ReadInt32()); /* gender */ char_name.m_gender = IPAddress.NetworkToHostOrder(m_reader.ReadInt32()); /* profession */ char_name.m_profession = IPAddress.NetworkToHostOrder(m_reader.ReadInt32()); /* level (should always be 0 )*/ char_name.m_level = IPAddress.NetworkToHostOrder(m_reader.ReadInt32()); /* lets skip some stuff */ int skip_len = IPAddress.NetworkToHostOrder(m_reader.ReadInt32()); m_stream.Position += (skip_len + 8); /* head mesh */ char_name.m_headmesh = IPAddress.NetworkToHostOrder(m_reader.ReadInt32()); /* monster scale */ char_name.m_monsterscale = IPAddress.NetworkToHostOrder(m_reader.ReadInt32()); /* fatness */ char_name.m_fatness = IPAddress.NetworkToHostOrder(m_reader.ReadInt32()); /* start in SL? */ int sl = IPAddress.NetworkToHostOrder(m_reader.ReadInt32()); if (sl == 1) { start_in_sl = true; } /* close reader and stream */ m_reader.Close(); m_stream.Dispose(); /* now you got the data.. * do whatever you have to do with it * but please.. in some other class :) */ /* check name against database * * if name exist, return 0. * if name doesnt exist, creates default char setup and returns character_id * */ character_id = char_name.CheckAgainstDB(); if (character_id < 1) { char_name.SendNameInUse(client); } else { char_name.SendNameToStartPF(client, start_in_sl, character_id); } /* reply will work only if character creation * works, so its disabled for now and should be * handled in other class in /Packets/<class name> */ break; case 0x14: /* client deletes char */ Int32 uid; /* start reading packet */ m_stream.Position = 20; uid = IPAddress.NetworkToHostOrder(m_reader.ReadInt32()); char_name.DeleteChar(client, uid); break; default: client.Server.Warning(client, "Client sent unknown message {0}", messageNumber.ToString()); break; } }
/// <summary> /// /// </summary> /// <param name="client"></param> /// <param name="packet"></param> /// <param name="messageNumber"></param> public void Parse(Client client, byte[] packet, uint messageNumber) { #region Setup... PacketReader packetReader = new PacketReader(packet); string encryptedPassword; int encPasswordLength; byte[] wrongLogin = LoginWrong.GetPacket(); CheckLogin cbl = new CheckLogin(); CharacterName characterName = new CharacterName(); #endregion switch (messageNumber) { case 0x22: SaltAuthentication salt = new SaltAuthentication(); // Username and version info packetReader.ReadBytes(24); client.AccountName = Encoding.ASCII.GetString(packetReader.ReadBytes(40)).TrimEnd(char.MinValue); client.ClientVersion = Encoding.ASCII.GetString(packetReader.ReadBytes(20)).TrimEnd(char.MinValue); packetReader.Finish(); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine( "Client '" + client.AccountName + "' connected using version '" + client.ClientVersion + "'"); Console.ResetColor(); // Send Authentication Salt to client client.ServerSalt = salt.SendPacket(client); break; case 0x25: // Username and encrypted password // m_stream.Position = 20; packetReader.ReadBytes(20); string loginAccountName = packetReader.PopString(40).TrimEnd(char.MinValue); encPasswordLength = packetReader.PopInt(); encryptedPassword = packetReader.PopString(encPasswordLength).TrimEnd(char.MinValue); packetReader.Finish(); if (cbl.IsLoginAllowed(client, loginAccountName) == false) { /* * Account name not found or client banned/otherwise not permitted on the server * Note, this is done here not in the above packet (0x22), even though we have * the username or the client will complain. Also a security measure as you can * not tell if an account name is correct or not, only if both the username and * password are correct. * * We also double check that the Account Name is the same as origionally sent * or there could be a possibility to log in with someone elses account. * */ Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine( "Client '" + client.AccountName + "' banned, not a valid username, or sent a malformed Authentication Packet"); Console.ResetColor(); client.Send(wrongLogin); client.Server.DisconnectClient(client); break; } if (cbl.IsLoginCorrect(client, encryptedPassword) == false) { // Username/Password Incorrect Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Client '" + client.AccountName + "' failed Authentication."); Console.ResetColor(); client.Send(wrongLogin); client.Server.DisconnectClient(client); break; } else { // All's well, send CharacterList Packet CharacterListPacket charlist = new CharacterListPacket(); charlist.SendPacket(client, client.AccountName); } break; case 0x16: // Player selected a character and client sends us selected characters ID packetReader.ReadBytes(20); int selectedCharID = packetReader.PopInt(); packetReader.Finish(); if (cbl.IsCharacterOnAccount(client, selectedCharID) == false) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine( "Client '" + client.AccountName + "' tried to log in as CharID " + selectedCharID + " but it is not on their account!"); Console.ResetColor(); // NV: Is this really what we want to send? Should find out sometime... client.Send(wrongLogin); client.Server.DisconnectClient(client); break; } if (OnlineChars.IsOnline(selectedCharID)) { Console.WriteLine( "Client '" + client.AccountName + "' is trying to login, but the requested character is already logged in."); client.Send(wrongLogin); client.Server.DisconnectClient(client); break; } OnlineChars.SetOnline(selectedCharID); IPAddress tempIP; if (IPAddress.TryParse(ConfigReadWrite.Instance.CurrentConfig.ZoneIP, out tempIP) == false) { IPHostEntry zoneHost = Dns.GetHostEntry(ConfigReadWrite.Instance.CurrentConfig.ZoneIP); foreach (IPAddress ip in zoneHost.AddressList) { if (ip.AddressFamily == AddressFamily.InterNetwork) { tempIP = ip; break; } } } byte[] ZoneIP = tempIP.GetAddressBytes(); byte[] ZonePort = BitConverter.GetBytes(Convert.ToInt32(ConfigReadWrite.Instance.CurrentConfig.ZonePort)); PacketWriter writer = new PacketWriter(); writer.PushByte(0xDF); writer.PushByte(0xDF); writer.PushShort(1); // Packet type writer.PushShort(1); writer.PushShort(0); // Packet length (will be set in packet writer) writer.PushInt(1); writer.PushInt(0x615B); // Server ID writer.PushInt(23); // Packet ID writer.PushInt(selectedCharID); writer.PushBytes(ZoneIP); writer.PushByte(ZonePort[1]); writer.PushByte(ZonePort[0]); writer.PushShort(0); writer.PushInt(0); writer.PushInt(0); Byte[] pkt = writer.Finish(); client.Send(pkt); break; case 0x55: /* player ask for 'suggest name'; server sends 'random' name. */ characterName.GetRandomName(client, packetReader.PopInt()); packetReader.Finish(); break; case 0xf: /* client created new character */ Int32 characterId; bool startInShadowLands = false; characterName.AccountName = client.AccountName; /* start reading packet */ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // As of 18.5.1 heading for this packet is 69 bytes (65 bytes for lower versions) // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! packetReader.ReadBytes(69); /* name length */ int nameLen = packetReader.PopInt(); /* name */ characterName.Name = packetReader.PopString(nameLen); /* breed */ characterName.Breed = packetReader.PopInt(); /* gender */ characterName.Gender = packetReader.PopInt(); /* profession */ characterName.Profession = packetReader.PopInt(); /* level (should always be 0 )*/ characterName.Level = packetReader.PopInt(); /* lets skip some stuff */ int skipLen = packetReader.PopInt(); packetReader.ReadBytes(skipLen + 8); /* head mesh */ characterName.HeadMesh = packetReader.PopInt(); /* monster scale */ characterName.MonsterScale = packetReader.PopInt(); /* fatness */ characterName.Fatness = packetReader.PopInt(); /* start in SL? */ int sl = packetReader.PopInt(); if (sl == 1) { startInShadowLands = true; } /* close reader and stream */ packetReader.Finish(); /* now you got the data.. * do whatever you have to do with it * but please.. in some other class :) */ /* check name against database * * if name exist, return 0. * if name doesnt exist, creates default char setup and returns character_id * */ characterId = characterName.CheckAgainstDatabase(); if (characterId < 1) { characterName.SendNameInUse(client); } else { characterName.SendNameToStartPlayfield(client, startInShadowLands, characterId); } /* reply will work only if character creation * works, so its disabled for now and should be * handled in other class in /Packets/<class name> */ break; case 0x14: /* client deletes char */ Int32 uid; /* start reading packet */ packetReader.ReadBytes(20); uid = packetReader.PopInt(); characterName.DeleteChar(client, uid); packetReader.Finish(); break; default: packetReader.Finish(); client.Server.Warning(client, "Client sent unknown message {0}", messageNumber.ToString()); break; } }