[Loginserver] Identify unknown login client packet fields (#1680)

* Add player login reply struct

* Use player login reply struct for failed logins

* Use base message struct for login requests

* Refactor server list reply serialization

Use BaseMessage and BaseReplyMessage structs for server list
and add flags for server type and status

* Use reply message struct for login handshake

Remove client version checks, the packets are the same for titanium and rof2

* Use base headers for join server requests

* Log correct server list ip

* Add compressed flag to base message header

Document encrypt type flag more
This commit is contained in:
hg
2021-11-11 21:13:30 -05:00
committed by GitHub
parent 099759c477
commit cbea7045fa
7 changed files with 290 additions and 310 deletions
+45 -130
View File
@@ -97,9 +97,8 @@ WorldServer *ServerManager::GetServerByAddress(const std::string &ip_address, in
* @param sequence
* @return
*/
EQApplicationPacket *ServerManager::CreateServerListPacket(Client *client, uint32 sequence)
std::unique_ptr<EQApplicationPacket> ServerManager::CreateServerListPacket(Client *client, uint32 sequence)
{
unsigned int packet_size = sizeof(ServerListHeader_Struct);
unsigned int server_count = 0;
in_addr in{};
in.s_addr = client->GetConnection()->GetRemoteIP();
@@ -107,144 +106,60 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *client, uint3
LogDebug("ServerManager::CreateServerListPacket via client address [{0}]", client_ip);
auto iter = m_world_servers.begin();
while (iter != m_world_servers.end()) {
if (!(*iter)->IsAuthorized()) {
for (const auto& world_server : m_world_servers)
{
if (world_server->IsAuthorized()) {
++server_count;
}
}
SerializeBuffer buf;
// LoginBaseMessage_Struct header
buf.WriteInt32(sequence);
buf.WriteInt8(0);
buf.WriteInt8(0);
buf.WriteInt32(0);
// LoginBaseReplyMessage_Struct
buf.WriteInt8(true); // success (no error)
buf.WriteInt32(0x65); // 101 "No Error" eqlsstr
buf.WriteString("");
// ServerListReply_Struct
buf.WriteInt32(server_count);
for (const auto& world_server : m_world_servers)
{
if (!world_server->IsAuthorized()) {
LogDebug(
"ServerManager::CreateServerListPacket | Server [{0}] via IP [{1}] is not authorized to be listed",
(*iter)->GetServerLongName(),
(*iter)->GetConnection()->Handle()->RemoteIP()
"ServerManager::CreateServerListPacket | Server [{}] via IP [{}] is not authorized to be listed",
world_server->GetServerLongName(),
world_server->GetConnection()->Handle()->RemoteIP()
);
++iter;
continue;
}
std::string world_ip = (*iter)->GetConnection()->Handle()->RemoteIP();
if (world_ip == client_ip) {
packet_size += (*iter)->GetServerLongName().size() + (*iter)->GetLocalIP().size() + 24;
bool use_local_ip = false;
LogDebug(
"CreateServerListPacket | Building list entry | Client [{0}] IP [{1}] Server Long Name [{2}] Server IP [{3}] (Local)",
client->GetAccountName(),
client_ip,
(*iter)->GetServerLongName(),
(*iter)->GetLocalIP()
);
}
else if (IpUtil::IsIpInPrivateRfc1918(client_ip)) {
packet_size += (*iter)->GetServerLongName().size() + (*iter)->GetLocalIP().size() + 24;
LogDebug(
"CreateServerListPacket | Building list entry | Client [{0}] IP [{1}] Server Long Name [{2}] Server IP [{3}] (Local)",
client->GetAccountName(),
client_ip,
(*iter)->GetServerLongName(),
(*iter)->GetLocalIP()
);
}
else {
packet_size += (*iter)->GetServerLongName().size() + (*iter)->GetRemoteIP().size() + 24;
LogDebug(
"CreateServerListPacket | Building list entry | Client [{0}] IP [{1}] Server Long Name [{2}] Server IP [{3}] (Remote)",
client->GetAccountName(),
client_ip,
(*iter)->GetServerLongName(),
(*iter)->GetRemoteIP()
);
std::string world_ip = world_server->GetConnection()->Handle()->RemoteIP();
if (world_ip == client_ip || IpUtil::IsIpInPrivateRfc1918(client_ip)) {
use_local_ip = true;
}
server_count++;
++iter;
LogDebug(
"CreateServerListPacket | Building list entry | Client [{}] IP [{}] Server Long Name [{}] Server IP [{}] ({})",
client->GetAccountName(),
client_ip,
world_server->GetServerLongName(),
use_local_ip ? world_server->GetLocalIP() : world_server->GetRemoteIP(),
use_local_ip ? "Local" : "Remote"
);
world_server->SerializeForClientServerList(buf, use_local_ip);
}
auto *outapp = new EQApplicationPacket(OP_ServerListResponse, packet_size);
auto *server_list = (ServerListHeader_Struct *) outapp->pBuffer;
server_list->Unknown1 = sequence;
server_list->Unknown2 = 0x00000000;
server_list->Unknown3 = 0x01650000;
/**
* Not sure what this is but it should be noted setting it to
* 0xFFFFFFFF crashes the client so: don't do that.
*/
server_list->Unknown4 = 0x00000000;
server_list->NumberOfServers = server_count;
unsigned char *data_pointer = outapp->pBuffer;
data_pointer += sizeof(ServerListHeader_Struct);
iter = m_world_servers.begin();
while (iter != m_world_servers.end()) {
if (!(*iter)->IsAuthorized()) {
++iter;
continue;
}
std::string world_ip = (*iter)->GetConnection()->Handle()->RemoteIP();
if (world_ip == client_ip) {
memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
data_pointer += ((*iter)->GetLocalIP().size() + 1);
}
else if (IpUtil::IsIpInPrivateRfc1918(client_ip)) {
memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
data_pointer += ((*iter)->GetLocalIP().size() + 1);
}
else {
memcpy(data_pointer, (*iter)->GetRemoteIP().c_str(), (*iter)->GetRemoteIP().size());
data_pointer += ((*iter)->GetRemoteIP().size() + 1);
}
switch ((*iter)->GetServerListID()) {
case 1: {
*(unsigned int *) data_pointer = 0x00000030;
break;
}
case 2: {
*(unsigned int *) data_pointer = 0x00000009;
break;
}
default: {
*(unsigned int *) data_pointer = 0x00000001;
}
}
data_pointer += 4;
*(unsigned int *) data_pointer = (*iter)->GetServerId();
data_pointer += 4;
memcpy(data_pointer, (*iter)->GetServerLongName().c_str(), (*iter)->GetServerLongName().size());
data_pointer += ((*iter)->GetServerLongName().size() + 1);
memcpy(data_pointer, "EN", 2);
data_pointer += 3;
memcpy(data_pointer, "US", 2);
data_pointer += 3;
// 0 = Up, 1 = Down, 2 = Up, 3 = down, 4 = locked, 5 = locked(down)
if ((*iter)->GetStatus() < 0) {
if ((*iter)->GetZonesBooted() == 0) {
*(uint32 *) data_pointer = 0x01;
}
else {
*(uint32 *) data_pointer = 0x04;
}
}
else {
*(uint32 *) data_pointer = 0x02;
}
data_pointer += 4;
*(uint32 *) data_pointer = (*iter)->GetPlayersOnline();
data_pointer += 4;
++iter;
}
return outapp;
return std::make_unique<EQApplicationPacket>(OP_ServerListResponse, buf);
}
/**