Working on login / world connection mostly there, fixed a few crashes with encryption on 0 length packets

This commit is contained in:
KimLS
2016-10-29 23:23:04 -07:00
parent 0b8b41d91f
commit f3e2af7e42
19 changed files with 441 additions and 412 deletions
+199 -182
View File
@@ -38,10 +38,10 @@ WorldServer::WorldServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> c)
is_server_trusted = false;
is_server_logged_in = false;
c->OnMessage(ServerOP_NewLSInfo, std::bind(&WorldServer::ProcessPacket, this, std::placeholders::_1, std::placeholders::_2));
c->OnMessage(ServerOP_LSStatus, std::bind(&WorldServer::ProcessPacket, this, std::placeholders::_1, std::placeholders::_2));
c->OnMessage(ServerOP_UsertoWorldResp, std::bind(&WorldServer::ProcessPacket, this, std::placeholders::_1, std::placeholders::_2));
c->OnMessage(ServerOP_LSAccountUpdate, std::bind(&WorldServer::ProcessPacket, this, std::placeholders::_1, std::placeholders::_2));
c->OnMessage(ServerOP_NewLSInfo, std::bind(&WorldServer::ProcessNewLSInfo, this, std::placeholders::_1, std::placeholders::_2));
c->OnMessage(ServerOP_LSStatus, std::bind(&WorldServer::ProcessLSStatus, this, std::placeholders::_1, std::placeholders::_2));
c->OnMessage(ServerOP_UsertoWorldResp, std::bind(&WorldServer::ProcessUsertoWorldResp, this, std::placeholders::_1, std::placeholders::_2));
c->OnMessage(ServerOP_LSAccountUpdate, std::bind(&WorldServer::ProcessLSAccountUpdate, this, std::placeholders::_1, std::placeholders::_2));
}
WorldServer::~WorldServer()
@@ -61,161 +61,180 @@ void WorldServer::Reset()
is_server_logged_in = false;
}
void WorldServer::ProcessPacket(uint16_t opcode, const EQ::Net::Packet &p)
void WorldServer::ProcessNewLSInfo(uint16_t opcode, const EQ::Net::Packet &p)
{
if(server.options.IsWorldTraceOn())
if (server.options.IsWorldTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "Application packet received from server: 0x%.4X, (size %u)", opcode, p.Length());
}
if(server.options.IsDumpInPacketsOn())
if (server.options.IsDumpInPacketsOn())
{
Log.OutF(Logs::General, Logs::Login_Server, "{0}", p.ToString());
DumpPacket(opcode, p);
}
switch(opcode)
if (p.Length() < sizeof(ServerNewLSInfo_Struct))
{
case ServerOP_NewLSInfo:
Log.Out(Logs::General, Logs::Error, "Received application packet from server that had opcode ServerOP_NewLSInfo, "
"but was too small. Discarded to avoid buffer overrun.");
return;
}
if (server.options.IsWorldTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "New Login Info Recieved.");
}
ServerNewLSInfo_Struct *info = (ServerNewLSInfo_Struct*)p.Data();
Handle_NewLSInfo(info);
}
void WorldServer::ProcessLSStatus(uint16_t opcode, const EQ::Net::Packet &p)
{
if (server.options.IsWorldTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "Application packet received from server: 0x%.4X, (size %u)", opcode, p.Length());
}
if (server.options.IsDumpInPacketsOn())
{
DumpPacket(opcode, p);
}
if (p.Length() < sizeof(ServerLSStatus_Struct))
{
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerOP_LSStatus, "
"but was too small. Discarded to avoid buffer overrun.");
return;
}
if (server.options.IsWorldTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "World Server Status Recieved.");
}
ServerLSStatus_Struct *ls_status = (ServerLSStatus_Struct*)p.Data();
Handle_LSStatus(ls_status);
}
void WorldServer::ProcessUsertoWorldResp(uint16_t opcode, const EQ::Net::Packet &p)
{
if (server.options.IsWorldTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "Application packet received from server: 0x%.4X, (size %u)", opcode, p.Length());
}
if (server.options.IsDumpInPacketsOn())
{
DumpPacket(opcode, p);
}
if (p.Length() < sizeof(UsertoWorldResponse_Struct))
{
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerOP_UsertoWorldResp, "
"but was too small. Discarded to avoid buffer overrun.");
return;
}
//I don't use world trace for this and here is why:
//Because this is a part of the client login procedure it makes tracking client errors
//While keeping world server spam with multiple servers connected almost impossible.
if (server.options.IsTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "User-To-World Response received.");
}
UsertoWorldResponse_Struct *utwr = (UsertoWorldResponse_Struct*)p.Data();
Log.Out(Logs::General, Logs::Debug, "Trying to find client with user id of %u.", utwr->lsaccountid);
Client *c = server.client_manager->GetClient(utwr->lsaccountid);
if (c)
{
Log.Out(Logs::General, Logs::Debug, "Found client with user id of %u and account name of %s.", utwr->lsaccountid, c->GetAccountName().c_str());
EQApplicationPacket *outapp = new EQApplicationPacket(OP_PlayEverquestResponse, sizeof(PlayEverquestResponse_Struct));
PlayEverquestResponse_Struct *per = (PlayEverquestResponse_Struct*)outapp->pBuffer;
per->Sequence = c->GetPlaySequence();
per->ServerNumber = c->GetPlayServerID();
Log.Out(Logs::General, Logs::Debug, "Found sequence and play of %u %u", c->GetPlaySequence(), c->GetPlayServerID());
Log.Out(Logs::General, Logs::Netcode, "[Size: %u] %s", outapp->size, DumpPacketToString(outapp).c_str());
if (utwr->response > 0)
{
if(p.Length() < sizeof(ServerNewLSInfo_Struct))
{
Log.Out(Logs::General, Logs::Error, "Received application packet from server that had opcode ServerOP_NewLSInfo, "
"but was too small. Discarded to avoid buffer overrun.");
break;
}
if(server.options.IsWorldTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "New Login Info Recieved.");
}
ServerNewLSInfo_Struct *info = (ServerNewLSInfo_Struct*)p.Data();
Handle_NewLSInfo(info);
per->Allowed = 1;
SendClientAuth(c->GetConnection()->GetRemoteAddr(), c->GetAccountName(), c->GetKey(), c->GetAccountID());
}
switch (utwr->response)
{
case 1:
per->Message = 101;
break;
case 0:
per->Message = 326;
break;
case -1:
per->Message = 337;
break;
case -2:
per->Message = 338;
break;
case -3:
per->Message = 303;
break;
}
case ServerOP_LSStatus:
if (server.options.IsTraceOn())
{
if(p.Length() < sizeof(ServerLSStatus_Struct))
{
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerOP_LSStatus, "
"but was too small. Discarded to avoid buffer overrun.");
break;
}
if(server.options.IsWorldTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "World Server Status Recieved.");
}
ServerLSStatus_Struct *ls_status = (ServerLSStatus_Struct*)p.Data();
Handle_LSStatus(ls_status);
break;
Log.Out(Logs::General, Logs::Netcode, "Sending play response with following data, allowed %u, sequence %u, server number %u, message %u",
per->Allowed, per->Sequence, per->ServerNumber, per->Message);
Log.Out(Logs::General, Logs::Netcode, "[Size: %u] %s", outapp->size, DumpPacketToString(outapp).c_str());
}
case ServerOP_UsertoWorldResp:
if (server.options.IsDumpOutPacketsOn())
{
if(p.Length() < sizeof(UsertoWorldResponse_Struct))
{
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerOP_UsertoWorldResp, "
"but was too small. Discarded to avoid buffer overrun.");
break;
}
//I don't use world trace for this and here is why:
//Because this is a part of the client login procedure it makes tracking client errors
//While keeping world server spam with multiple servers connected almost impossible.
if(server.options.IsTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "User-To-World Response received.");
}
UsertoWorldResponse_Struct *utwr = (UsertoWorldResponse_Struct*)p.Data();
Log.Out(Logs::General, Logs::Debug, "Trying to find client with user id of %u.", utwr->lsaccountid);
Client *c = server.client_manager->GetClient(utwr->lsaccountid);
if(c)
{
Log.Out(Logs::General, Logs::Debug, "Found client with user id of %u and account name of %s.", utwr->lsaccountid, c->GetAccountName().c_str());
EQApplicationPacket *outapp = new EQApplicationPacket(OP_PlayEverquestResponse, sizeof(PlayEverquestResponse_Struct));
PlayEverquestResponse_Struct *per = (PlayEverquestResponse_Struct*)outapp->pBuffer;
per->Sequence = c->GetPlaySequence();
per->ServerNumber = c->GetPlayServerID();
Log.Out(Logs::General, Logs::Debug, "Found sequence and play of %u %u", c->GetPlaySequence(), c->GetPlayServerID());
Log.Out(Logs::General, Logs::Netcode, "[Size: %u] %s", outapp->size, DumpPacketToString(outapp).c_str());
if(utwr->response > 0)
{
per->Allowed = 1;
SendClientAuth(c->GetConnection()->GetRemoteAddr(), c->GetAccountName(), c->GetKey(), c->GetAccountID());
}
switch(utwr->response)
{
case 1:
per->Message = 101;
break;
case 0:
per->Message = 326;
break;
case -1:
per->Message = 337;
break;
case -2:
per->Message = 338;
break;
case -3:
per->Message = 303;
break;
}
if(server.options.IsTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "Sending play response with following data, allowed %u, sequence %u, server number %u, message %u",
per->Allowed, per->Sequence, per->ServerNumber, per->Message);
Log.Out(Logs::General, Logs::Netcode, "[Size: %u] %s", outapp->size, DumpPacketToString(outapp).c_str());
}
if(server.options.IsDumpOutPacketsOn())
{
DumpPacket(outapp);
}
c->SendPlayResponse(outapp);
delete outapp;
}
else
{
Log.Out(Logs::General, Logs::Error, "Recieved User-To-World Response for %u but could not find the client referenced!.", utwr->lsaccountid);
}
break;
}
case ServerOP_LSAccountUpdate:
{
if(p.Length() < sizeof(ServerLSAccountUpdate_Struct))
{
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerLSAccountUpdate_Struct, "
"but was too small. Discarded to avoid buffer overrun.");
break;
}
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate packet received from: %s", short_name.c_str());
ServerLSAccountUpdate_Struct *lsau = (ServerLSAccountUpdate_Struct*)p.Data();
if(is_server_trusted)
{
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate update processed for: %s", lsau->useraccount);
string name;
string password;
string email;
name.assign(lsau->useraccount);
password.assign(lsau->userpassword);
email.assign(lsau->useremail);
server.db->UpdateLSAccountInfo(lsau->useraccountid, name, password, email);
}
break;
}
default:
{
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had an unknown operation code 0x%.4X.", opcode);
DumpPacket(outapp);
}
c->SendPlayResponse(outapp);
delete outapp;
}
else
{
Log.Out(Logs::General, Logs::Error, "Recieved User-To-World Response for %u but could not find the client referenced!.", utwr->lsaccountid);
}
}
void WorldServer::ProcessLSAccountUpdate(uint16_t opcode, const EQ::Net::Packet &p)
{
if (server.options.IsWorldTraceOn())
{
Log.Out(Logs::General, Logs::Netcode, "Application packet received from server: 0x%.4X, (size %u)", opcode, p.Length());
}
if (server.options.IsDumpInPacketsOn())
{
DumpPacket(opcode, p);
}
if (p.Length() < sizeof(ServerLSAccountUpdate_Struct))
{
Log.Out(Logs::General, Logs::Error, "Recieved application packet from server that had opcode ServerLSAccountUpdate_Struct, "
"but was too small. Discarded to avoid buffer overrun.");
return;
}
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate packet received from: %s", short_name.c_str());
ServerLSAccountUpdate_Struct *lsau = (ServerLSAccountUpdate_Struct*)p.Data();
if (is_server_trusted)
{
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate update processed for: %s", lsau->useraccount);
std::string name;
std::string password;
std::string email;
name.assign(lsau->useraccount);
password.assign(lsau->userpassword);
email.assign(lsau->useremail);
server.db->UpdateLSAccountInfo(lsau->useraccountid, name, password, email);
}
}
@@ -289,7 +308,6 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
{
if(strlen(i->remote_address) == 0)
{
in_addr in;
remote_ip = GetConnection()->Handle()->RemoteIP();
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, remote address was null, defaulting to stream address %s.", remote_ip.c_str());
}
@@ -300,7 +318,6 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
}
else
{
in_addr in;
remote_ip = GetConnection()->Handle()->RemoteIP();
Log.Out(Logs::General, Logs::Error, "Handle_NewLSInfo error, remote address was too long, defaulting to stream address %s.", remote_ip.c_str());
}
@@ -352,10 +369,10 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
unsigned int s_id = 0;
unsigned int s_list_type = 0;
unsigned int s_trusted = 0;
string s_desc;
string s_list_desc;
string s_acct_name;
string s_acct_pass;
std::string s_desc;
std::string s_list_desc;
std::string s_acct_name;
std::string s_acct_pass;
if(server.db->GetWorldRegistration(long_name, short_name, s_id, s_desc, s_list_type, s_trusted, s_list_desc, s_acct_name, s_acct_pass))
{
if(s_acct_name.size() == 0 || s_acct_pass.size() == 0)
@@ -378,8 +395,9 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
if(s_trusted) {
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate sent to world");
is_server_trusted = true;
ServerPacket *outapp = new ServerPacket(ServerOP_LSAccountUpdate, 0);
connection->SendPacket(outapp);
EQ::Net::WritablePacket outapp;
connection->Send(ServerOP_LSAccountUpdate, outapp);
}
}
else {
@@ -404,10 +422,10 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
unsigned int server_id = 0;
unsigned int server_list_type = 0;
unsigned int is_server_trusted = 0;
string server_description;
string server_list_description;
string server_account_name;
string server_account_password;
std::string server_description;
std::string server_list_description;
std::string server_account_name;
std::string server_account_password;
if(server.db->GetWorldRegistration(
@@ -434,8 +452,8 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct* i)
if(is_server_trusted) {
Log.Out(Logs::General, Logs::Netcode, "ServerOP_LSAccountUpdate sent to world");
is_server_trusted = true;
ServerPacket *outapp = new ServerPacket(ServerOP_LSAccountUpdate, 0);
connection->SendPacket(outapp);
EQ::Net::WritablePacket outapp;
connection->Send(ServerOP_LSAccountUpdate, outapp);
}
}
else {
@@ -486,37 +504,36 @@ void WorldServer::Handle_LSStatus(ServerLSStatus_Struct *s)
server_status = s->status;
}
void WorldServer::SendClientAuth(std::string ip, string account, string key, unsigned int account_id)
void WorldServer::SendClientAuth(std::string ip, std::string account, std::string key, unsigned int account_id)
{
ServerPacket *outapp = new ServerPacket(ServerOP_LSClientAuth, sizeof(ClientAuth_Struct));
ClientAuth_Struct* client_auth = (ClientAuth_Struct*)outapp->pBuffer;
client_auth->lsaccount_id = account_id;
strncpy(client_auth->name, account.c_str(), account.size() > 30 ? 30 : account.size());
strncpy(client_auth->key, key.c_str(), 10);
client_auth->lsadmin = 0;
client_auth->worldadmin = 0;
strcpy(client_auth->ip, ip.c_str());
string client_address(ip);
string world_address(connection->Handle()->RemoteIP());
EQ::Net::WritablePacket outapp;
ClientAuth_Struct client_auth;
client_auth.lsaccount_id = account_id;
client_auth.name = account;
client_auth.key = key;
client_auth.lsadmin = 0;
client_auth.worldadmin = 0;
client_auth.ip = ip;
std::string client_address(ip);
std::string world_address(connection->Handle()->RemoteIP());
if (client_address.compare(world_address) == 0) {
client_auth->local = 1;
client_auth.local = 1;
}
else if (client_address.find(server.options.GetLocalNetwork()) != string::npos) {
client_auth->local = 1;
else if (client_address.find(server.options.GetLocalNetwork()) != std::string::npos) {
client_auth.local = 1;
}
else {
client_auth->local = 0;
client_auth.local = 0;
}
connection->SendPacket(outapp);
outapp.PutSerialize(0, client_auth);
connection->Send(ServerOP_LSClientAuth, outapp);
if (server.options.IsDumpInPacketsOn())
{
DumpPacket(outapp);
DumpPacket(ServerOP_LSClientAuth, outapp);
}
delete outapp;
}