Fix some edge case with account name not being passed to world

This commit is contained in:
Akkadius 2019-07-06 03:19:50 -05:00
parent a9969e500b
commit 0668f41de2
14 changed files with 718 additions and 382 deletions

View File

@ -198,23 +198,52 @@ int16 Database::CheckStatus(uint32 account_id)
return status;
}
uint32 Database::CreateAccount(const char* name, const char* password, int16 status, const char* loginserver, uint32 lsaccount_id) {
/**
* @param name
* @param password
* @param status
* @param loginserver
* @param lsaccount_id
* @return
*/
uint32 Database::CreateAccount(
const char *name,
const char *password,
int16 status,
const char *loginserver,
uint32 lsaccount_id
)
{
std::string query;
if (password)
query = StringFormat("INSERT INTO account SET name='%s', password='%s', status=%i, ls_id='%s', lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();", name, password, status, loginserver, lsaccount_id);
else
query = StringFormat("INSERT INTO account SET name='%s', status=%i, ls_id='%s', lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",name, status, loginserver, lsaccount_id);
if (password) {
query = StringFormat(
"INSERT INTO account SET name='%s', password='%s', status=%i, ls_id='%s', lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",
name,
password,
status,
loginserver,
lsaccount_id
);
}
else {
query = StringFormat(
"INSERT INTO account SET name='%s', status=%i, ls_id='%s', lsaccount_id=%i, time_creation=UNIX_TIMESTAMP();",
name,
status,
loginserver,
lsaccount_id
);
}
Log(Logs::General, Logs::World_Server, "Account Attempting to be created: '%s:%s' status: %i", loginserver, name, status);
LogInfo("Account Attempting to be created: [{0}:{1}] status: {2}", loginserver, name, status);
auto results = QueryDatabase(query);
if (!results.Success()) {
return 0;
}
if (results.LastInsertedID() == 0)
{
if (results.LastInsertedID() == 0) {
return 0;
}
@ -1181,27 +1210,41 @@ bool Database::AddToNameFilter(const char* name) {
return true;
}
uint32 Database::GetAccountIDFromLSID(const std::string& iLoginServer, uint32 iLSID, char* oAccountName, int16* oStatus) {
uint32 Database::GetAccountIDFromLSID(
const std::string &iLoginServer,
uint32 iLSID, char *oAccountName,
int16 *oStatus
)
{
uint32 account_id = 0;
//iLoginServer is set by config so don't need to worry about escaping it.
std::string query = StringFormat("SELECT id, name, status FROM account WHERE lsaccount_id=%i AND ls_id='%s'", iLSID, iLoginServer.c_str());
auto query = fmt::format(
"SELECT id, name, status FROM account WHERE lsaccount_id = {0} AND ls_id = '{1}'",
iLSID,
iLoginServer
);
auto results = QueryDatabase(query);
if (!results.Success()) {
return 0;
}
if (results.RowCount() != 1)
if (results.RowCount() != 1) {
return 0;
}
for (auto row = results.begin(); row != results.end(); ++row) {
account_id = atoi(row[0]);
if (oAccountName)
if (oAccountName) {
strcpy(oAccountName, row[1]);
if (oStatus)
}
if (oStatus) {
*oStatus = atoi(row[2]);
}
}
return account_id;
}

View File

@ -519,35 +519,35 @@ struct ServerLSPlayerZoneChange_Struct {
};
struct ClientAuth_Struct {
uint32 lsaccount_id; // ID# in login server's db
char lsname[64];
char name[30]; // username in login server's db
uint32 loginserver_account_id; // ID# in login server's db
char loginserver_name[64];
char account_name[30]; // username in login server's db
char key[30]; // the Key the client will present
uint8 lsadmin; // login server admin level
int16 worldadmin; // login's suggested worldadmin level setting for this user, up to the world if they want to obey it
int16 is_world_admin; // login's suggested worldadmin level setting for this user, up to the world if they want to obey it
uint32 ip;
uint8 local; // 1 if the client is from the local network
uint8 is_client_from_local_network; // 1 if the client is from the local network
template <class Archive>
void serialize(Archive &ar)
{
ar(lsaccount_id, lsname, name, key, lsadmin, worldadmin, ip, local);
ar(loginserver_account_id, loginserver_name, account_name, key, lsadmin, is_world_admin, ip, is_client_from_local_network);
}
};
struct ClientAuthLegacy_Struct {
uint32 lsaccount_id; // ID# in login server's db
char name[30]; // username in login server's db
uint32 loginserver_account_id; // ID# in login server's db
char loginserver_account_name[30]; // username in login server's db
char key[30]; // the Key the client will present
uint8 lsadmin; // login server admin level
int16 worldadmin; // login's suggested worldadmin level setting for this user, up to the world if they want to obey it
uint8 loginserver_admin_level; // login server admin level
int16 is_world_admin; // login's suggested worldadmin level setting for this user, up to the world if they want to obey it
uint32 ip;
uint8 local; // 1 if the client is from the local network
uint8 is_client_from_local_network; // 1 if the client is from the local network
template <class Archive>
void serialize(Archive &ar)
{
ar(lsaccount_id, name, key, lsadmin, worldadmin, ip, local);
ar(loginserver_account_id, loginserver_account_name, key, loginserver_admin_level, is_world_admin, ip, is_client_from_local_network);
}
};

View File

@ -560,11 +560,15 @@ bool Client::VerifyLoginHash(
}
/**
* @param user
* @param in_account_name
* @param db_account_id
* @param db_loginserver
*/
void Client::DoSuccessfulLogin(const std::string &user, int db_account_id, const std::string &db_loginserver)
void Client::DoSuccessfulLogin(
const std::string in_account_name,
int db_account_id,
const std::string &db_loginserver
)
{
stored_user.clear();
stored_pass.clear();
@ -578,7 +582,7 @@ void Client::DoSuccessfulLogin(const std::string &user, int db_account_id, const
GenerateKey();
account_id = db_account_id;
account_name = user;
account_name = in_account_name;
loginserver_name = db_loginserver;
auto *outapp = new EQApplicationPacket(OP_LoginAccepted, 10 + 80);
@ -650,25 +654,29 @@ void Client::CreateLocalAccount(const std::string &user, const std::string &pass
}
/**
* @param user
* @param pass
* @param id
* @param in_account_name
* @param in_account_password
* @param loginserver_account_id
*/
void Client::CreateEQEmuAccount(const std::string &user, const std::string &pass, unsigned int id)
void Client::CreateEQEmuAccount(
const std::string &in_account_name,
const std::string &in_account_password,
unsigned int loginserver_account_id
)
{
auto mode = server.options.GetEncryptionMode();
auto hash = eqcrypt_hash(user, pass, mode);
auto hash = eqcrypt_hash(in_account_name, in_account_password, mode);
if (server.db->DoesLoginServerAccountExist(user, hash, "eqemu", id)) {
DoSuccessfulLogin(user, id, "eqemu");
if (server.db->DoesLoginServerAccountExist(in_account_name, hash, "eqemu", loginserver_account_id)) {
DoSuccessfulLogin(in_account_name, loginserver_account_id, "eqemu");
return;
}
if (!server.db->CreateLoginDataWithID(user, hash, "eqemu", id)) {
if (!server.db->CreateLoginDataWithID(in_account_name, hash, "eqemu", loginserver_account_id)) {
DoFailedLogin();
}
else {
DoSuccessfulLogin(user, id, "eqemu");
DoSuccessfulLogin(in_account_name, loginserver_account_id, "eqemu");
}
}

View File

@ -190,9 +190,9 @@ public:
const std::string &hash
);
void DoSuccessfulLogin(const std::string &user, int db_account_id, const std::string &db_loginserver);
void DoSuccessfulLogin(const std::string in_account_name, int db_account_id, const std::string &db_loginserver);
void CreateLocalAccount(const std::string &user, const std::string &pass);
void CreateEQEmuAccount(const std::string &user, const std::string &pass, unsigned int id);
void CreateEQEmuAccount(const std::string &in_account_name, const std::string &in_account_password, unsigned int loginserver_account_id);
private:
EQEmu::Random random;

View File

@ -225,15 +225,15 @@ bool Database::CreateLoginData(
}
/**
* @param name
* @param password
* @param in_account_name
* @param in_account_password
* @param loginserver
* @param id
* @return
*/
bool Database::CreateLoginDataWithID(
const std::string &name,
const std::string &password,
const std::string &in_account_name,
const std::string &in_account_password,
const std::string &loginserver,
unsigned int id
)
@ -248,8 +248,8 @@ bool Database::CreateLoginDataWithID(
server.options.GetAccountTable(),
id,
EscapeString(loginserver),
EscapeString(name),
EscapeString(password)
EscapeString(in_account_name),
EscapeString(in_account_password)
);
auto results = QueryDatabase(query);

View File

@ -80,8 +80,8 @@ public:
unsigned int &id
);
bool CreateLoginDataWithID(
const std::string &name,
const std::string &password,
const std::string &in_account_name,
const std::string &in_account_password,
const std::string &loginserver,
unsigned int id
);

View File

@ -56,7 +56,7 @@ WorldServer::WorldServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> wo
worldserver_connection->OnMessage(
ServerOP_UsertoWorldRespLeg,
std::bind(
&WorldServer::ProcessUsertoWorldRespLeg,
&WorldServer::ProcessUserToWorldResponseLegacy,
this,
std::placeholders::_1,
std::placeholders::_2
@ -186,7 +186,7 @@ void WorldServer::ProcessLSStatus(uint16_t opcode, const EQ::Net::Packet &packet
* @param opcode
* @param packet
*/
void WorldServer::ProcessUsertoWorldRespLeg(uint16_t opcode, const EQ::Net::Packet &packet)
void WorldServer::ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Net::Packet &packet)
{
if (server.options.IsWorldTraceOn()) {
Log(Logs::General,
@ -205,6 +205,7 @@ void WorldServer::ProcessUsertoWorldRespLeg(uint16_t opcode, const EQ::Net::Pack
"Received application packet from server that had opcode ServerOP_UsertoWorldResp, "
"but was too small. Discarded to avoid buffer overrun"
);
return;
}
@ -216,15 +217,15 @@ void WorldServer::ProcessUsertoWorldRespLeg(uint16_t opcode, const EQ::Net::Pack
}
auto *user_to_world_response = (UsertoWorldResponseLegacy_Struct *) packet.Data();
Log(Logs::General, Logs::Debug, "Trying to find client with user id of %u.", user_to_world_response->lsaccountid);
LogDebug("Trying to find client with user id of [{0}]", user_to_world_response->lsaccountid);
Client *c = server.client_manager->GetClient(user_to_world_response->lsaccountid, "eqemu");
if (c) {
Log(Logs::General,
Logs::Debug,
"Found client with user id of %u and account name of %s.",
LogDebug(
"Found client with user id of [{0}] and account name of [{1}]",
user_to_world_response->lsaccountid,
c->GetAccountName().c_str()
c->GetAccountName()
);
auto *outapp = new EQApplicationPacket(
@ -763,28 +764,28 @@ void WorldServer::SendClientAuth(
EQ::Net::DynamicPacket outapp;
ClientAuth_Struct client_auth{};
client_auth.lsaccount_id = account_id;
client_auth.loginserver_account_id = account_id;
strncpy(client_auth.name, account.c_str(), 30);
strncpy(client_auth.account_name, account.c_str(), 30);
strncpy(client_auth.key, key.c_str(), 30);
client_auth.lsadmin = 0;
client_auth.worldadmin = 0;
client_auth.is_world_admin = 0;
client_auth.ip = inet_addr(ip.c_str());
strncpy(client_auth.lsname, &loginserver_name[0], 64);
strncpy(client_auth.loginserver_name, &loginserver_name[0], 64);
const 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.is_client_from_local_network = 1;
}
else if (IpUtil::IsIpInPrivateRfc1918(client_address)) {
LogInfo("Client is authenticating from a local address [{0}]", client_address);
client_auth.local = 1;
client_auth.is_client_from_local_network = 1;
}
else {
client_auth.local = 0;
client_auth.is_client_from_local_network = 0;
}
struct in_addr ip_addr{};
@ -799,14 +800,14 @@ void WorldServer::SendClientAuth(
LogInfo(
"Sending Client Authentication Response ls_account_id [{0}] ls_name [{1}] name [{2}] key [{3}] ls_admin [{4}] "
"world_admin [{5}] ip [{6}] local [{7}]",
client_auth.lsaccount_id,
client_auth.lsname,
client_auth.name,
client_auth.loginserver_account_id,
client_auth.loginserver_name,
client_auth.account_name,
client_auth.key,
client_auth.lsadmin,
client_auth.worldadmin,
client_auth.is_world_admin,
inet_ntoa(ip_addr),
client_auth.local
client_auth.is_client_from_local_network
);
outapp.PutSerialize(0, client_auth);

View File

@ -109,7 +109,7 @@ private:
*/
void ProcessNewLSInfo(uint16_t opcode, const EQ::Net::Packet &packet);
void ProcessLSStatus(uint16_t opcode, const EQ::Net::Packet &packet);
void ProcessUsertoWorldRespLeg(uint16_t opcode, const EQ::Net::Packet &packet);
void ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Net::Packet &packet);
void ProcessUserToWorldResponse(uint16_t opcode, const EQ::Net::Packet &packet);
void ProcessLSAccountUpdate(uint16_t opcode, const EQ::Net::Packet &packet);

View File

@ -414,10 +414,11 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) {
is_player_zoning = (li->zoning == 1);
uint32 id = atoi(name);
LogDebug("Receiving Login Info Packet from Client | name [{0}] password [{1}]", name, password);
uint32 id = atoi(name);
if (id == 0) {
Log(Logs::General, Logs::World_Server, "Login ID is 0, disconnecting.");
LogWarning("Receiving Login Info Packet from Client | account_id is 0 - disconnecting");
return false;
}

View File

@ -31,7 +31,16 @@ extern LoginServerList loginserverlist;
extern ClientList client_list;
extern volatile bool RunLoops;
ClientListEntry::ClientListEntry(uint32 in_id, uint32 iLSID, const char *iLoginServerName, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin, uint32 ip, uint8 local)
ClientListEntry::ClientListEntry(
uint32 in_id,
uint32 iLSID,
const char *iLoginServerName,
const char *iLoginName,
const char *iLoginKey,
int16 iWorldAdmin,
uint32 ip,
uint8 local
)
: id(in_id)
{
ClearVars(true);
@ -43,9 +52,9 @@ ClientListEntry::ClientListEntry(uint32 in_id, uint32 iLSID, const char *iLoginS
paccountid = database.GetAccountIDFromLSID(iLoginServerName, iLSID, paccountname, &padmin);
}
strn0cpy(plsname, iLoginName, sizeof(plsname));
strn0cpy(loginserver_account_name, iLoginName, sizeof(loginserver_account_name));
strn0cpy(plskey, iLoginKey, sizeof(plskey));
strn0cpy(pLoginServer, iLoginServerName, sizeof(pLoginServer));
strn0cpy(source_loginserver, iLoginServerName, sizeof(source_loginserver));
pworldadmin = iWorldAdmin;
plocal = (local == 1);
@ -63,7 +72,7 @@ ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList
pIP = 0;
pLSID = scl->LSAccountID;
strn0cpy(plsname, scl->name, sizeof(plsname));
strn0cpy(loginserver_account_name, scl->name, sizeof(loginserver_account_name));
strn0cpy(plskey, scl->lskey, sizeof(plskey));
pworldadmin = 0;
@ -77,13 +86,16 @@ ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList
pLFGMatchFilter = false;
memset(pLFGComments, 0, 64);
if (iOnline >= CLE_Status_Zoning)
if (iOnline >= CLE_Status_Zoning) {
Update(iZS, scl, iOnline);
else
}
else {
SetOnline(iOnline);
}
}
ClientListEntry::~ClientListEntry() {
ClientListEntry::~ClientListEntry()
{
if (RunLoops) {
Camp(); // updates zoneserver's numplayers
client_list.RemoveCLEReferances(this);
@ -93,30 +105,39 @@ ClientListEntry::~ClientListEntry() {
tell_queue.clear();
}
void ClientListEntry::SetChar(uint32 iCharID, const char* iCharName) {
void ClientListEntry::SetChar(uint32 iCharID, const char *iCharName)
{
pcharid = iCharID;
strn0cpy(pname, iCharName, sizeof(pname));
}
void ClientListEntry::SetOnline(ZoneServer* iZS, int8 iOnline) {
if (iZS == this->Server())
void ClientListEntry::SetOnline(ZoneServer *iZS, int8 iOnline)
{
if (iZS == this->Server()) {
SetOnline(iOnline);
}
}
void ClientListEntry::SetOnline(int8 iOnline) {
if (iOnline >= CLE_Status_Online && pOnline < CLE_Status_Online)
void ClientListEntry::SetOnline(int8 iOnline)
{
if (iOnline >= CLE_Status_Online && pOnline < CLE_Status_Online) {
numplayers++;
}
else if (iOnline < CLE_Status_Online && pOnline >= CLE_Status_Online) {
numplayers--;
}
if (iOnline != CLE_Status_Online || pOnline < CLE_Status_Online)
if (iOnline != CLE_Status_Online || pOnline < CLE_Status_Online) {
pOnline = iOnline;
if (iOnline < CLE_Status_Zoning)
}
if (iOnline < CLE_Status_Zoning) {
Camp();
if (pOnline >= CLE_Status_Online)
}
if (pOnline >= CLE_Status_Online) {
stale = 0;
}
void ClientListEntry::LSUpdate(ZoneServer* iZS){
}
void ClientListEntry::LSUpdate(ZoneServer *iZS)
{
if (WorldConfig::get()->UpdateStats) {
auto pack = new ServerPacket;
pack->opcode = ServerOP_LSZoneInfo;
@ -130,7 +151,8 @@ void ClientListEntry::LSUpdate(ZoneServer* iZS){
safe_delete(pack);
}
}
void ClientListEntry::LSZoneChange(ZoneToZone_Struct* ztz){
void ClientListEntry::LSZoneChange(ZoneToZone_Struct *ztz)
{
if (WorldConfig::get()->UpdateStats) {
auto pack = new ServerPacket;
pack->opcode = ServerOP_LSPlayerZoneChange;
@ -144,7 +166,8 @@ void ClientListEntry::LSZoneChange(ZoneToZone_Struct* ztz){
safe_delete(pack);
}
}
void ClientListEntry::Update(ZoneServer* iZS, ServerClientList_Struct* scl, int8 iOnline) {
void ClientListEntry::Update(ZoneServer *iZS, ServerClientList_Struct *scl, int8 iOnline)
{
if (pzoneserver != iZS) {
if (pzoneserver) {
pzoneserver->RemovePlayer();
@ -164,7 +187,7 @@ void ClientListEntry::Update(ZoneServer* iZS, ServerClientList_Struct* scl, int8
if (paccountid == 0) {
paccountid = scl->AccountID;
strcpy(paccountname, scl->AccountName);
strcpy(plsname, scl->AccountName);
strcpy(loginserver_account_name, scl->AccountName);
pIP = scl->IP;
pLSID = scl->LSAccountID;
strn0cpy(plskey, scl->lskey, sizeof(plskey));
@ -191,9 +214,11 @@ void ClientListEntry::Update(ZoneServer* iZS, ServerClientList_Struct* scl, int8
SetOnline(iOnline);
}
void ClientListEntry::LeavingZone(ZoneServer* iZS, int8 iOnline) {
if (iZS != 0 && iZS != pzoneserver)
void ClientListEntry::LeavingZone(ZoneServer *iZS, int8 iOnline)
{
if (iZS != 0 && iZS != pzoneserver) {
return;
}
SetOnline(iOnline);
if (pzoneserver) {
@ -204,13 +229,14 @@ void ClientListEntry::LeavingZone(ZoneServer* iZS, int8 iOnline) {
pzone = 0;
}
void ClientListEntry::ClearVars(bool iAll) {
void ClientListEntry::ClearVars(bool iAll)
{
if (iAll) {
pOnline = CLE_Status_Never;
stale = 0;
pLSID = 0;
memset(plsname, 0, sizeof(plsname));
memset(loginserver_account_name, 0, sizeof(loginserver_account_name));
memset(plskey, 0, sizeof(plskey));
pworldadmin = 0;
@ -236,9 +262,11 @@ void ClientListEntry::ClearVars(bool iAll) {
tell_queue.clear();
}
void ClientListEntry::Camp(ZoneServer* iZS) {
if (iZS != 0 && iZS != pzoneserver)
void ClientListEntry::Camp(ZoneServer *iZS)
{
if (iZS != 0 && iZS != pzoneserver) {
return;
}
if (pzoneserver) {
pzoneserver->RemovePlayer();
LSUpdate(pzoneserver);
@ -249,33 +277,51 @@ void ClientListEntry::Camp(ZoneServer* iZS) {
stale = 0;
}
bool ClientListEntry::CheckStale() {
bool ClientListEntry::CheckStale()
{
stale++;
if (stale > 20) {
if (pOnline > CLE_Status_Offline)
if (pOnline > CLE_Status_Offline) {
SetOnline(CLE_Status_Offline);
else
}
else {
return true;
}
}
return false;
}
bool ClientListEntry::CheckAuth(uint32 iLSID, const char* iKey) {
if (pLSID == iLSID && strncmp(plskey, iKey, 10) == 0) {
bool ClientListEntry::CheckAuth(uint32 loginserver_account_id, const char *key_password)
{
if (pLSID == loginserver_account_id && strncmp(plskey, key_password, 10) == 0) {
if (paccountid == 0 && LSID() > 0) {
int16 tmpStatus = WorldConfig::get()->DefaultStatus;
paccountid = database.CreateAccount(plsname, 0, tmpStatus, pLoginServer, LSID());
int16 default_account_status = WorldConfig::get()->DefaultStatus;
paccountid = database.CreateAccount(
loginserver_account_name,
0,
default_account_status,
source_loginserver,
LSID()
);
if (!paccountid) {
Log(Logs::Detail, Logs::World_Server,"Error adding local account for LS login: '%s:%s', duplicate name?", pLoginServer, plsname);
LogInfo(
"Error adding local account for LS login: [{0}:{1}], duplicate name",
source_loginserver,
loginserver_account_name
);
return false;
}
strn0cpy(paccountname, plsname, sizeof(paccountname));
padmin = tmpStatus;
strn0cpy(paccountname, loginserver_account_name, sizeof(paccountname));
padmin = default_account_status;
}
std::string lsworldadmin;
if (database.GetVariable("honorlsworldadmin", lsworldadmin))
if (atoi(lsworldadmin.c_str()) == 1 && pworldadmin != 0 && (padmin < pworldadmin || padmin == 0))
if (database.GetVariable("honorlsworldadmin", lsworldadmin)) {
if (atoi(lsworldadmin.c_str()) == 1 && pworldadmin != 0 && (padmin < pworldadmin || padmin == 0)) {
padmin = pworldadmin;
}
}
return true;
}
return false;
@ -283,13 +329,17 @@ bool ClientListEntry::CheckAuth(uint32 iLSID, const char* iKey) {
void ClientListEntry::ProcessTellQueue()
{
if (!Server())
if (!Server()) {
return;
}
ServerPacket *pack;
auto it = tell_queue.begin();
while (it != tell_queue.end()) {
pack = new ServerPacket(ServerOP_ChannelMessage, sizeof(ServerChannelMessage_Struct) + strlen((*it)->message) + 1);
pack = new ServerPacket(
ServerOP_ChannelMessage,
sizeof(ServerChannelMessage_Struct) + strlen((*it)->message) + 1
);
memcpy(pack->pBuffer, *it, pack->size);
Server()->SendPacket(pack);
safe_delete(pack);

View File

@ -28,7 +28,7 @@ public:
void Update(ZoneServer* zoneserver, ServerClientList_Struct* scl, int8 iOnline = CLE_Status_InZone);
void LSUpdate(ZoneServer* zoneserver);
void LSZoneChange(ZoneToZone_Struct* ztz);
bool CheckAuth(uint32 iLSID, const char* key);
bool CheckAuth(uint32 loginserver_account_id, const char* key_password);
void SetOnline(ZoneServer* iZS, int8 iOnline);
void SetOnline(int8 iOnline = CLE_Status_Online);
void SetChar(uint32 iCharID, const char* iCharName);
@ -42,10 +42,10 @@ public:
void Camp(ZoneServer* iZS = 0);
// Login Server stuff
inline const char* LoginServer() const { return pLoginServer; }
inline const char* LoginServer() const { return source_loginserver; }
inline uint32 LSID() const { return pLSID; }
inline uint32 LSAccountID() const { return pLSID; }
inline const char* LSName() const { return plsname; }
inline const char* LSName() const { return loginserver_account_name; }
inline int16 WorldAdmin() const { return pworldadmin; }
inline const char* GetLSKey() const { return plskey; }
inline const int8 GetOnline() const { return pOnline; }
@ -95,9 +95,9 @@ private:
uint8 stale;
// Login Server stuff
char pLoginServer[64]; //Loginserver we came from.
char source_loginserver[64]; //Loginserver we came from.
uint32 pLSID;
char plsname[32];
char loginserver_account_name[32];
char plskey[16];
int16 pworldadmin; // Login server's suggested admin status setting
bool plocal;

View File

@ -410,15 +410,18 @@ void ClientList::CLEKeepAlive(uint32 numupdates, uint32* wid) {
}
}
ClientListEntry* ClientList::CheckAuth(uint32 iLSID, const char* iKey) {
ClientListEntry *ClientList::CheckAuth(uint32 iLSID, const char *iKey)
{
LinkedListIterator<ClientListEntry *> iterator(clientlist);
iterator.Reset();
while (iterator.MoreElements()) {
if (iterator.GetData()->CheckAuth(iLSID, iKey))
if (iterator.GetData()->CheckAuth(iLSID, iKey)) {
return iterator.GetData();
}
iterator.Advance();
}
return 0;
}

View File

@ -53,10 +53,12 @@ LoginServer::LoginServer(const char* iAddress, uint16 iPort, const char* Account
Connect();
}
LoginServer::~LoginServer() {
LoginServer::~LoginServer()
{
}
void LoginServer::ProcessUsertoWorldReqLeg(uint16_t opcode, EQ::Net::Packet &p) {
void LoginServer::ProcessUsertoWorldReqLeg(uint16_t opcode, EQ::Net::Packet &p)
{
const WorldConfig *Config = WorldConfig::get();
Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
@ -73,32 +75,37 @@ void LoginServer::ProcessUsertoWorldReqLeg(uint16_t opcode, EQ::Net::Packet &p)
utwrs->lsaccountid = utwr->lsaccountid;
utwrs->ToID = utwr->FromID;
if (Config->Locked == true)
{
if ((status == 0 || status < 100) && (status != -2 || status != -1))
if (Config->Locked == true) {
if ((status == 0 || status < 100) && (status != -2 || status != -1)) {
utwrs->response = 0;
if (status >= 100)
}
if (status >= 100) {
utwrs->response = 1;
}
}
else {
utwrs->response = 1;
}
int32 x = Config->MaxClients;
if ((int32)numplayers >= x && x != -1 && x != 255 && status < 80)
if ((int32) numplayers >= x && x != -1 && x != 255 && status < 80) {
utwrs->response = -3;
}
if (status == -1)
if (status == -1) {
utwrs->response = -1;
if (status == -2)
}
if (status == -2) {
utwrs->response = -2;
}
utwrs->worldid = utwr->worldid;
SendPacket(outpack);
delete outpack;
}
void LoginServer::ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p) {
void LoginServer::ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p)
{
const WorldConfig *Config = WorldConfig::get();
Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
@ -116,72 +123,118 @@ void LoginServer::ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p) {
utwrs->ToID = utwr->FromID;
strn0cpy(utwrs->login, utwr->login, 64);
if (Config->Locked == true)
{
if ((status == 0 || status < 100) && (status != -2 || status != -1))
if (Config->Locked == true) {
if ((status == 0 || status < 100) && (status != -2 || status != -1)) {
utwrs->response = 0;
if (status >= 100)
}
if (status >= 100) {
utwrs->response = 1;
}
}
else {
utwrs->response = 1;
}
int32 x = Config->MaxClients;
if ((int32)numplayers >= x && x != -1 && x != 255 && status < 80)
if ((int32) numplayers >= x && x != -1 && x != 255 && status < 80) {
utwrs->response = -3;
}
if (status == -1)
if (status == -1) {
utwrs->response = -1;
if (status == -2)
}
if (status == -2) {
utwrs->response = -2;
}
utwrs->worldid = utwr->worldid;
SendPacket(outpack);
delete outpack;
}
void LoginServer::ProcessLSClientAuthLeg(uint16_t opcode, EQ::Net::Packet &p) {
void LoginServer::ProcessLSClientAuthLegacy(uint16_t opcode, EQ::Net::Packet &p)
{
const WorldConfig *Config = WorldConfig::get();
Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
Log(Logs::Detail, Logs::World_Server, "Received ServerPacket from LS OpCode 0x04x", opcode);
try {
auto slsca = p.GetSerialize<ClientAuthLegacy_Struct>(0);
auto client_authentication_request = p.GetSerialize<ClientAuthLegacy_Struct>(0);
if (RuleI(World, AccountSessionLimit) >= 0) {
// Enforce the limit on the number of characters on the same account that can be
// online at the same time.
client_list.EnforceSessionLimit(slsca.lsaccount_id);
client_list.EnforceSessionLimit(client_authentication_request.loginserver_account_id);
}
client_list.CLEAdd(slsca.lsaccount_id, "eqemu", slsca.name, slsca.key, slsca.worldadmin, slsca.ip, slsca.local);
LogDebug(
"Processing Loginserver Auth Legacy | account_id [{0}] account_name [{1}] key [{2}] admin [{3}] ip [{4}] "
"local_network [{5}]",
client_authentication_request.loginserver_account_id,
client_authentication_request.loginserver_account_name,
client_authentication_request.key,
client_authentication_request.is_world_admin,
client_authentication_request.ip,
client_authentication_request.is_client_from_local_network
);
client_list.CLEAdd(
client_authentication_request.loginserver_account_id,
"eqemu",
client_authentication_request.loginserver_account_name,
client_authentication_request.key,
client_authentication_request.is_world_admin,
client_authentication_request.ip,
client_authentication_request.is_client_from_local_network
);
}
catch (std::exception &ex) {
LogF(Logs::General, Logs::Error, "Error parsing LSClientAuth packet from world.\n{0}", ex.what());
LogError("Error parsing ClientAuthLegacy packet from world\nReason [{0}]", ex.what());
}
}
void LoginServer::ProcessLSClientAuth(uint16_t opcode, EQ::Net::Packet &p) {
void LoginServer::ProcessLSClientAuth(uint16_t opcode, EQ::Net::Packet &p)
{
const WorldConfig *Config = WorldConfig::get();
Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
Log(Logs::Detail, Logs::World_Server, "Received ServerPacket from LS OpCode 0x04x", opcode);
try {
auto slsca = p.GetSerialize<ClientAuth_Struct>(0);
auto client_authentication_request = p.GetSerialize<ClientAuth_Struct>(0);
if (RuleI(World, AccountSessionLimit) >= 0) {
// Enforce the limit on the number of characters on the same account that can be
// online at the same time.
client_list.EnforceSessionLimit(slsca.lsaccount_id);
client_list.EnforceSessionLimit(client_authentication_request.loginserver_account_id);
}
client_list.CLEAdd(slsca.lsaccount_id, slsca.lsname, slsca.name, slsca.key, slsca.worldadmin, slsca.ip, slsca.local);
LogDebug(
"Processing Loginserver Auth | account_id [{0}] account_name [{1}] loginserver_name [{2}] key [{3}] "
"admin [{4}] ip [{5}] local_network [{6}]",
client_authentication_request.loginserver_account_id,
client_authentication_request.account_name,
client_authentication_request.loginserver_name,
client_authentication_request.key,
client_authentication_request.is_world_admin,
client_authentication_request.ip,
client_authentication_request.is_client_from_local_network
);
client_list.CLEAdd(
client_authentication_request.loginserver_account_id,
client_authentication_request.loginserver_name,
client_authentication_request.account_name,
client_authentication_request.key,
client_authentication_request.is_world_admin,
client_authentication_request.ip,
client_authentication_request.is_client_from_local_network
);
}
catch (std::exception &ex) {
LogF(Logs::General, Logs::Error, "Error parsing LSClientAuth packet from world.\n{0}", ex.what());
LogError("Error parsing ClientAuth packet from world\nReason [{0}]", ex.what());
}
}
void LoginServer::ProcessLSFatalError(uint16_t opcode, EQ::Net::Packet &p) {
void LoginServer::ProcessLSFatalError(uint16_t opcode, EQ::Net::Packet &p)
{
const WorldConfig *Config = WorldConfig::get();
Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
@ -191,7 +244,8 @@ void LoginServer::ProcessLSFatalError(uint16_t opcode, EQ::Net::Packet &p) {
}
}
void LoginServer::ProcessSystemwideMessage(uint16_t opcode, EQ::Net::Packet &p) {
void LoginServer::ProcessSystemwideMessage(uint16_t opcode, EQ::Net::Packet &p)
{
const WorldConfig *Config = WorldConfig::get();
Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
@ -199,7 +253,8 @@ void LoginServer::ProcessSystemwideMessage(uint16_t opcode, EQ::Net::Packet &p)
zoneserver_list.SendEmoteMessageRaw(0, 0, 0, swm->type, swm->message);
}
void LoginServer::ProcessLSRemoteAddr(uint16_t opcode, EQ::Net::Packet &p) {
void LoginServer::ProcessLSRemoteAddr(uint16_t opcode, EQ::Net::Packet &p)
{
const WorldConfig *Config = WorldConfig::get();
Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
@ -209,7 +264,8 @@ void LoginServer::ProcessLSRemoteAddr(uint16_t opcode, EQ::Net::Packet &p) {
}
}
void LoginServer::ProcessLSAccountUpdate(uint16_t opcode, EQ::Net::Packet &p) {
void LoginServer::ProcessLSAccountUpdate(uint16_t opcode, EQ::Net::Packet &p)
{
const WorldConfig *Config = WorldConfig::get();
Log(Logs::Detail, Logs::World_Server, "Recevied ServerPacket from LS OpCode 0x04x", opcode);
@ -217,7 +273,8 @@ void LoginServer::ProcessLSAccountUpdate(uint16_t opcode, EQ::Net::Packet &p) {
CanAccountUpdate = true;
}
bool LoginServer::Connect() {
bool LoginServer::Connect()
{
char errbuf[1024];
if ((LoginServerIP = ResolveIP(LoginServerAddress, errbuf)) == 0) {
Log(Logs::Detail, Logs::World_Server, "Unable to resolve '%s' to an IP.", LoginServerAddress);
@ -225,70 +282,232 @@ bool LoginServer::Connect() {
}
if (LoginServerIP == 0 || LoginServerPort == 0) {
Log(Logs::Detail, Logs::World_Server, "Connect info incomplete, cannot connect: %s:%d", LoginServerAddress, LoginServerPort);
LogInfo(
"Connect info incomplete, cannot connect: [{0}:{1}]",
LoginServerAddress,
LoginServerPort
);
return false;
}
if (IsLegacy) {
legacy_client.reset(new EQ::Net::ServertalkLegacyClient(LoginServerAddress, LoginServerPort, false));
legacy_client->OnConnect([this](EQ::Net::ServertalkLegacyClient *client) {
legacy_client->OnConnect(
[this](EQ::Net::ServertalkLegacyClient *client) {
if (client) {
Log(Logs::Detail, Logs::World_Server, "Connected to Legacy Loginserver: %s:%d", LoginServerAddress, LoginServerPort);
LogInfo(
"Connected to Legacy Loginserver: [{0}:{1}]",
LoginServerAddress,
LoginServerPort
);
SendInfo();
SendStatus();
zoneserver_list.SendLSZones();
statusupdate_timer.reset(new EQ::Timer(LoginServer_StatusUpdateInterval, true, [this](EQ::Timer *t) {
statusupdate_timer.reset(
new EQ::Timer(
LoginServer_StatusUpdateInterval, true, [this](EQ::Timer *t) {
SendStatus();
}));
}
)
);
}
else {
Log(Logs::Detail, Logs::World_Server, "Could not connect to Legacy Loginserver: %s:%d", LoginServerAddress, LoginServerPort);
LogInfo(
"Could not connect to Legacy Loginserver: [{0}:{1}]",
LoginServerAddress,
LoginServerPort
);
}
});
}
);
legacy_client->OnMessage(ServerOP_UsertoWorldReqLeg, std::bind(&LoginServer::ProcessUsertoWorldReqLeg, this, std::placeholders::_1, std::placeholders::_2));
legacy_client->OnMessage(ServerOP_UsertoWorldReq, std::bind(&LoginServer::ProcessUsertoWorldReq, this, std::placeholders::_1, std::placeholders::_2));
legacy_client->OnMessage(ServerOP_LSClientAuthLeg, std::bind(&LoginServer::ProcessLSClientAuthLeg, this, std::placeholders::_1, std::placeholders::_2));
legacy_client->OnMessage(ServerOP_LSClientAuth, std::bind(&LoginServer::ProcessLSClientAuth, this, std::placeholders::_1, std::placeholders::_2));
legacy_client->OnMessage(ServerOP_LSFatalError, std::bind(&LoginServer::ProcessLSFatalError, this, std::placeholders::_1, std::placeholders::_2));
legacy_client->OnMessage(ServerOP_SystemwideMessage, std::bind(&LoginServer::ProcessSystemwideMessage, this, std::placeholders::_1, std::placeholders::_2));
legacy_client->OnMessage(ServerOP_LSRemoteAddr, std::bind(&LoginServer::ProcessLSRemoteAddr, this, std::placeholders::_1, std::placeholders::_2));
legacy_client->OnMessage(ServerOP_LSAccountUpdate, std::bind(&LoginServer::ProcessLSAccountUpdate, this, std::placeholders::_1, std::placeholders::_2));
legacy_client->OnMessage(
ServerOP_UsertoWorldReqLeg,
std::bind(
&LoginServer::ProcessUsertoWorldReqLeg,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
legacy_client->OnMessage(
ServerOP_UsertoWorldReq,
std::bind(
&LoginServer::ProcessUsertoWorldReq,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
legacy_client->OnMessage(
ServerOP_LSClientAuthLeg,
std::bind(
&LoginServer::ProcessLSClientAuthLegacy,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
legacy_client->OnMessage(
ServerOP_LSClientAuth,
std::bind(
&LoginServer::ProcessLSClientAuth,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
legacy_client->OnMessage(
ServerOP_LSFatalError,
std::bind(
&LoginServer::ProcessLSFatalError,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
legacy_client->OnMessage(
ServerOP_SystemwideMessage,
std::bind(
&LoginServer::ProcessSystemwideMessage,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
legacy_client->OnMessage(
ServerOP_LSRemoteAddr,
std::bind(
&LoginServer::ProcessLSRemoteAddr,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
legacy_client->OnMessage(
ServerOP_LSAccountUpdate,
std::bind(
&LoginServer::ProcessLSAccountUpdate,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
}
else {
client.reset(new EQ::Net::ServertalkClient(LoginServerAddress, LoginServerPort, false, "World", ""));
client->OnConnect([this](EQ::Net::ServertalkClient *client) {
client->OnConnect(
[this](EQ::Net::ServertalkClient *client) {
if (client) {
Log(Logs::Detail, Logs::World_Server, "Connected to Loginserver: %s:%d", LoginServerAddress, LoginServerPort);
LogInfo(
"Connected to Loginserver: {0}:{1}",
LoginServerAddress,
LoginServerPort
);
SendInfo();
SendStatus();
zoneserver_list.SendLSZones();
statusupdate_timer.reset(new EQ::Timer(LoginServer_StatusUpdateInterval, true, [this](EQ::Timer *t) {
statusupdate_timer.reset(
new EQ::Timer(
LoginServer_StatusUpdateInterval, true, [this](EQ::Timer *t) {
SendStatus();
}));
}
));
}
else {
Log(Logs::Detail, Logs::World_Server, "Could not connect to Loginserver: %s:%d", LoginServerAddress, LoginServerPort);
LogInfo(
"Could not connect to Loginserver: {0}:{1}",
LoginServerAddress,
LoginServerPort
);
}
});
}
);
client->OnMessage(ServerOP_UsertoWorldReqLeg, std::bind(&LoginServer::ProcessUsertoWorldReqLeg, this, std::placeholders::_1, std::placeholders::_2));
client->OnMessage(ServerOP_UsertoWorldReq, std::bind(&LoginServer::ProcessUsertoWorldReq, this, std::placeholders::_1, std::placeholders::_2));
client->OnMessage(ServerOP_LSClientAuthLeg, std::bind(&LoginServer::ProcessLSClientAuthLeg, this, std::placeholders::_1, std::placeholders::_2));
client->OnMessage(ServerOP_LSClientAuth, std::bind(&LoginServer::ProcessLSClientAuth, this, std::placeholders::_1, std::placeholders::_2));
client->OnMessage(ServerOP_LSFatalError, std::bind(&LoginServer::ProcessLSFatalError, this, std::placeholders::_1, std::placeholders::_2));
client->OnMessage(ServerOP_SystemwideMessage, std::bind(&LoginServer::ProcessSystemwideMessage, this, std::placeholders::_1, std::placeholders::_2));
client->OnMessage(ServerOP_LSRemoteAddr, std::bind(&LoginServer::ProcessLSRemoteAddr, this, std::placeholders::_1, std::placeholders::_2));
client->OnMessage(ServerOP_LSAccountUpdate, std::bind(&LoginServer::ProcessLSAccountUpdate, this, std::placeholders::_1, std::placeholders::_2));
client->OnMessage(
ServerOP_UsertoWorldReqLeg,
std::bind(
&LoginServer::ProcessUsertoWorldReqLeg,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
client->OnMessage(
ServerOP_UsertoWorldReq,
std::bind(
&LoginServer::ProcessUsertoWorldReq,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
client->OnMessage(
ServerOP_LSClientAuthLeg,
std::bind(
&LoginServer::ProcessLSClientAuthLegacy,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
client->OnMessage(
ServerOP_LSClientAuth,
std::bind(
&LoginServer::ProcessLSClientAuth,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
client->OnMessage(
ServerOP_LSFatalError,
std::bind(
&LoginServer::ProcessLSFatalError,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
client->OnMessage(
ServerOP_SystemwideMessage,
std::bind(
&LoginServer::ProcessSystemwideMessage,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
client->OnMessage(
ServerOP_LSRemoteAddr,
std::bind(
&LoginServer::ProcessLSRemoteAddr,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
client->OnMessage(
ServerOP_LSAccountUpdate,
std::bind(
&LoginServer::ProcessLSAccountUpdate,
this,
std::placeholders::_1,
std::placeholders::_2
)
);
}
return true;
}
void LoginServer::SendInfo() {
void LoginServer::SendInfo()
{
const WorldConfig *Config = WorldConfig::get();
auto pack = new ServerPacket;
@ -303,10 +522,12 @@ void LoginServer::SendInfo() {
strcpy(lsi->shortname, Config->ShortName.c_str());
strn0cpy(lsi->account, LoginAccount.c_str(), 30);
strn0cpy(lsi->password, LoginPassword.c_str(), 30);
if (Config->WorldAddress.length())
if (Config->WorldAddress.length()) {
strcpy(lsi->remote_address, Config->WorldAddress.c_str());
if (Config->LocalAddress.length())
}
if (Config->LocalAddress.length()) {
strcpy(lsi->local_address, Config->LocalAddress.c_str());
}
else {
auto local_addr = IsLegacy ? legacy_client->Handle()->LocalIP() : client->Handle()->LocalIP();
strcpy(lsi->local_address, local_addr.c_str());
@ -316,7 +537,8 @@ void LoginServer::SendInfo() {
delete pack;
}
void LoginServer::SendStatus() {
void LoginServer::SendStatus()
{
auto pack = new ServerPacket;
pack->opcode = ServerOP_LSStatus;
pack->size = sizeof(ServerLSStatus_Struct);
@ -324,12 +546,15 @@ void LoginServer::SendStatus() {
memset(pack->pBuffer, 0, pack->size);
ServerLSStatus_Struct *lss = (ServerLSStatus_Struct *) pack->pBuffer;
if (WorldConfig::get()->Locked)
if (WorldConfig::get()->Locked) {
lss->status = -2;
else if (numzones <= 0)
}
else if (numzones <= 0) {
lss->status = -2;
else
}
else {
lss->status = numplayers;
}
lss->num_zones = numzones;
lss->num_players = numplayers;
@ -351,10 +576,15 @@ void LoginServer::SendPacket(ServerPacket *pack)
}
}
void LoginServer::SendAccountUpdate(ServerPacket* pack) {
void LoginServer::SendAccountUpdate(ServerPacket *pack)
{
ServerLSAccountUpdate_Struct *s = (ServerLSAccountUpdate_Struct *) pack->pBuffer;
if (CanUpdate()) {
Log(Logs::Detail, Logs::World_Server, "Sending ServerOP_LSAccountUpdate packet to loginserver: %s:%d", LoginServerAddress, LoginServerPort);
Log(Logs::Detail,
Logs::World_Server,
"Sending ServerOP_LSAccountUpdate packet to loginserver: %s:%d",
LoginServerAddress,
LoginServerPort);
strn0cpy(s->worldaccount, LoginAccount.c_str(), 30);
strn0cpy(s->worldpassword, LoginPassword.c_str(), 30);
SendPacket(pack);

View File

@ -47,7 +47,7 @@ private:
void ProcessUsertoWorldReqLeg(uint16_t opcode, EQ::Net::Packet &p);
void ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p);
void ProcessLSClientAuth(uint16_t opcode, EQ::Net::Packet &p);
void ProcessLSClientAuthLeg(uint16_t opcode, EQ::Net::Packet &p);
void ProcessLSClientAuthLegacy(uint16_t opcode, EQ::Net::Packet &p);
void ProcessLSFatalError(uint16_t opcode, EQ::Net::Packet &p);
void ProcessSystemwideMessage(uint16_t opcode, EQ::Net::Packet &p);
void ProcessLSRemoteAddr(uint16_t opcode, EQ::Net::Packet &p);