diff --git a/loginserver/client.cpp b/loginserver/client.cpp index ea2951d5f..52b050495 100644 --- a/loginserver/client.cpp +++ b/loginserver/client.cpp @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "login_structures.h" #include "../common/misc_functions.h" #include "../common/eqemu_logsys.h" +#include "../common/string_util.h" extern LoginServer server; @@ -194,6 +195,7 @@ void Client::Handle_Login(const char* data, unsigned int size) char *login_packet_buffer = nullptr; unsigned int db_account_id = 0; + std::string db_loginserver = "eqemu"; std::string db_account_password_hash; std::string outbuffer; @@ -219,54 +221,49 @@ void Client::Handle_Login(const char* data, unsigned int size) bool result = false; if (outbuffer[0] == 0 && outbuffer[1] == 0) { - //if (server.options.IsTokenLoginAllowed()) { - // cred = (&outbuffer[2 + user.length()]); - // result = server.db->GetLoginTokenDataFromToken(cred, connection->GetRemoteAddr(), db_account_id, user); - //} + if (server.options.IsTokenLoginAllowed()) { + cred = (&outbuffer[2 + user.length()]); + result = server.db->GetLoginTokenDataFromToken(cred, connection->GetRemoteAddr(), db_account_id, db_loginserver, user); + } } else { - //if (server.options.IsPasswordLoginAllowed()) { - // result = false; - // //cred = (&outbuffer[1 + user.length()]); - // //if (server.db->GetLoginDataFromAccountName(user, db_account_password_hash, db_account_id) == false) { - // // /* If we have auto_create_accounts enabled in the login.ini, we will process the creation of an account on our own*/ - // // if ( - // // server.options.CanAutoCreateAccounts() && - // // server.db->CreateLoginData(user, eqcrypt_hash(user, cred, mode), db_account_id) == true - // // ) { - // // LogF(Logs::General, Logs::Error, "User {0} does not exist in the database, so we created it...", user); - // // result = true; - // // } - // // else { - // // LogF(Logs::General, Logs::Error, "Error logging in, user {0} does not exist in the database.", user); - // // result = false; - // // } - // //} - // //else { - // // if (eqcrypt_verify_hash(user, cred, db_account_password_hash, mode)) { - // // result = true; - // // } - // // else { - // // result = false; - // // } - // //} - //} + if (server.options.IsPasswordLoginAllowed()) { + cred = (&outbuffer[1 + user.length()]); + auto components = SplitString(user, '.'); + if (components.size() == 2) { + db_loginserver = components[0]; + user = components[1]; + } + + if (server.db->GetLoginDataFromAccountInfo(user, db_loginserver, db_account_password_hash, db_account_id) == false) { + + } + else { + if (eqcrypt_verify_hash(user, cred, db_account_password_hash, mode)) { + result = true; + } + else { + result = false; + } + } + } } /* Login Accepted */ if (result) { - server.client_manager->RemoveExistingClient(db_account_id); - + server.client_manager->RemoveExistingClient(db_account_id, db_loginserver); + in_addr in; in.s_addr = connection->GetRemoteIP(); - + server.db->UpdateLSAccountData(db_account_id, std::string(inet_ntoa(in))); GenerateKey(); - + account_id = db_account_id; account_name = user; - + loginserver_name = db_loginserver; + EQApplicationPacket *outapp = new EQApplicationPacket(OP_LoginAccepted, 10 + 80); const LoginLoginRequest_Struct* llrs = (const LoginLoginRequest_Struct *)data; LoginAccepted_Struct* login_accepted = (LoginAccepted_Struct *)outapp->pBuffer; @@ -275,10 +272,10 @@ void Client::Handle_Login(const char* data, unsigned int size) login_accepted->unknown3 = llrs->unknown3; login_accepted->unknown4 = llrs->unknown4; login_accepted->unknown5 = llrs->unknown5; - + LoginFailedAttempts_Struct * login_failed_attempts = new LoginFailedAttempts_Struct; memset(login_failed_attempts, 0, sizeof(LoginFailedAttempts_Struct)); - + login_failed_attempts->failed_attempts = 0; login_failed_attempts->message = 0x01; login_failed_attempts->lsid = db_account_id; @@ -298,22 +295,22 @@ void Client::Handle_Login(const char* data, unsigned int size) login_failed_attempts->unknown11[0] = 0x63; login_failed_attempts->unknown12[0] = 0x01; memcpy(login_failed_attempts->key, key.c_str(), key.size()); - + char encrypted_buffer[80] = { 0 }; auto rc = eqcrypt_block((const char*)login_failed_attempts, 75, encrypted_buffer, 1); if (rc == nullptr) { LogF(Logs::General, Logs::Debug, "Failed to encrypt eqcrypt block"); } - + memcpy(login_accepted->encrypt, encrypted_buffer, 80); - + if (server.options.IsDumpOutPacketsOn()) { DumpPacket(outapp); } - + connection->QueuePacket(outapp); delete outapp; - + status = cs_logged_in; } else { @@ -358,7 +355,7 @@ void Client::Handle_Play(const char* data) this->play_server_id = (unsigned int)play->ServerNumber; play_sequence_id = sequence_in; play_server_id = server_id_in; - server.server_manager->SendUserToWorldRequest(server_id_in, account_id); + server.server_manager->SendUserToWorldRequest(server_id_in, account_id, loginserver_name); } void Client::SendServerListPacket(uint32 seq) diff --git a/loginserver/client.h b/loginserver/client.h index 35ba3a1f0..bd8547d9a 100644 --- a/loginserver/client.h +++ b/loginserver/client.h @@ -96,6 +96,11 @@ public: */ unsigned int GetAccountID() const { return account_id; } + /** + * Gets the loginserver name of this client. + */ + std::string GetLoginServerName() const { return loginserver_name; } + /** * Gets the account name of this client. */ diff --git a/loginserver/client_manager.cpp b/loginserver/client_manager.cpp index 04de69e53..569f8c27d 100644 --- a/loginserver/client_manager.cpp +++ b/loginserver/client_manager.cpp @@ -124,12 +124,12 @@ void ClientManager::ProcessDisconnect() } } -void ClientManager::RemoveExistingClient(unsigned int account_id) +void ClientManager::RemoveExistingClient(unsigned int account_id, const std::string &loginserver) { auto iter = clients.begin(); while (iter != clients.end()) { - if ((*iter)->GetAccountID() == account_id) + if ((*iter)->GetAccountID() == account_id && (*iter)->GetLoginServerName().compare(loginserver) == 0) { Log(Logs::General, Logs::Login_Server, "Client attempting to log in and existing client already logged in, removing existing client."); delete (*iter); @@ -142,24 +142,17 @@ void ClientManager::RemoveExistingClient(unsigned int account_id) } } -Client *ClientManager::GetClient(unsigned int account_id) +Client *ClientManager::GetClient(unsigned int account_id, const std::string &loginserver) { - Client *cur = nullptr; - int count = 0; auto iter = clients.begin(); while (iter != clients.end()) { - if ((*iter)->GetAccountID() == account_id) + if ((*iter)->GetAccountID() == account_id && (*iter)->GetLoginServerName().compare(loginserver) == 0) { - cur = (*iter); - count++; + return (*iter); } ++iter; } - if (count > 1) - { - Log(Logs::General, Logs::Error, "More than one client with a given account_id existed in the client list."); - } - return cur; + return nullptr; } diff --git a/loginserver/client_manager.h b/loginserver/client_manager.h index 7e05737a2..08b1f1b98 100644 --- a/loginserver/client_manager.h +++ b/loginserver/client_manager.h @@ -48,12 +48,12 @@ public: /** * Removes a client with a certain account id. */ - void RemoveExistingClient(unsigned int account_id); + void RemoveExistingClient(unsigned int account_id, const std::string &loginserver); /** * Gets a client (if exists) by their account id. */ - Client *GetClient(unsigned int account_id); + Client *GetClient(unsigned int account_id, const std::string &loginserver); private: /** diff --git a/loginserver/database.h b/loginserver/database.h index 26eb45623..5edfbcbde 100644 --- a/loginserver/database.h +++ b/loginserver/database.h @@ -41,7 +41,7 @@ public: * Needed for client login procedure. * Returns true if the record was found, false otherwise. */ - virtual bool GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id, std::string &loginserver) { return false; } + virtual bool GetLoginDataFromAccountInfo(const std::string &name, const std::string &loginserver, std::string &password, unsigned int &id) { return false; } virtual bool GetLoginTokenDataFromToken(const std::string &token, const std::string &ip, unsigned int &db_account_id, std::string &db_loginserver, std::string &user) { return false; } diff --git a/loginserver/database_mysql.cpp b/loginserver/database_mysql.cpp index 6e1b2cf12..913468245 100644 --- a/loginserver/database_mysql.cpp +++ b/loginserver/database_mysql.cpp @@ -59,7 +59,7 @@ DatabaseMySQL::~DatabaseMySQL() } } -bool DatabaseMySQL::GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id, std::string &loginserver) +bool DatabaseMySQL::GetLoginDataFromAccountInfo(const std::string &name, const std::string &loginserver, std::string &password, unsigned int &id) { if (!database) { @@ -70,7 +70,9 @@ bool DatabaseMySQL::GetLoginDataFromAccountName(std::string name, std::string &p MYSQL_ROW row; std::stringstream query(std::stringstream::in | std::stringstream::out); query << "SELECT LoginServerID, AccountPassword FROM " << server.options.GetAccountTable() << " WHERE AccountName = '"; - query << name; + query << EscapeString(name); + query << "' AND AccountLoginserver='"; + query << EscapeString(loginserver); query << "'"; if (mysql_query(database, query.str().c_str()) != 0) diff --git a/loginserver/database_mysql.h b/loginserver/database_mysql.h index 6edf0f1ce..42eb9b304 100644 --- a/loginserver/database_mysql.h +++ b/loginserver/database_mysql.h @@ -57,7 +57,7 @@ public: * Needed for client login procedure. * Returns true if the record was found, false otherwise. */ - virtual bool GetLoginDataFromAccountName(std::string name, std::string &password, unsigned int &id, std::string &loginserver); + virtual bool GetLoginDataFromAccountInfo(const std::string &name, const std::string &loginserver, std::string &password, unsigned int &id); virtual bool GetLoginTokenDataFromToken(const std::string &token, const std::string &ip, unsigned int &db_account_id, std::string &db_loginserver, std::string &user); diff --git a/loginserver/server_manager.cpp b/loginserver/server_manager.cpp index 0a059ec93..4be55ac98 100644 --- a/loginserver/server_manager.cpp +++ b/loginserver/server_manager.cpp @@ -206,18 +206,19 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *c, uint32 seq return outapp; } -void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int client_account_id) +void ServerManager::SendUserToWorldRequest(unsigned int server_id, unsigned int client_account_id, const std::string &client_loginserver) { auto iter = world_servers.begin(); bool found = false; while (iter != world_servers.end()) { if ((*iter)->GetRuntimeID() == server_id) { EQ::Net::DynamicPacket outapp; - outapp.Resize(sizeof(UsertoWorldRequestLegacy_Struct)); - UsertoWorldRequestLegacy_Struct *utwr = (UsertoWorldRequestLegacy_Struct*)outapp.Data(); + outapp.Resize(sizeof(UsertoWorldRequest_Struct)); + UsertoWorldRequest_Struct *utwr = (UsertoWorldRequest_Struct*)outapp.Data(); utwr->worldid = server_id; utwr->lsaccountid = client_account_id; - (*iter)->GetConnection()->Send(ServerOP_UsertoWorldReqLeg, outapp); + strncpy(utwr->login, &client_loginserver[0], 64); + (*iter)->GetConnection()->Send(ServerOP_UsertoWorldReq, outapp); found = true; if (server.options.IsDumpInPacketsOn()) { diff --git a/loginserver/server_manager.h b/loginserver/server_manager.h index f9a1f66e1..220f40be3 100644 --- a/loginserver/server_manager.h +++ b/loginserver/server_manager.h @@ -45,7 +45,7 @@ public: /** * Sends a request to world to see if the client is banned or suspended. */ - void SendUserToWorldRequest(unsigned int server_id, unsigned int client_account_id); + void SendUserToWorldRequest(unsigned int server_id, unsigned int client_account_id, const std::string &client_loginserver); /** * Creates a server list packet for the client. diff --git a/loginserver/world_server.cpp b/loginserver/world_server.cpp index 02254f223..5561b1964 100644 --- a/loginserver/world_server.cpp +++ b/loginserver/world_server.cpp @@ -146,7 +146,7 @@ void WorldServer::ProcessUsertoWorldRespLeg(uint16_t opcode, const EQ::Net::Pack UsertoWorldResponseLegacy_Struct *utwr = (UsertoWorldResponseLegacy_Struct*)p.Data(); Log(Logs::General, Logs::Debug, "Trying to find client with user id of %u.", utwr->lsaccountid); - Client *c = server.client_manager->GetClient(utwr->lsaccountid); + Client *c = server.client_manager->GetClient(utwr->lsaccountid, "eqemu"); if (c) { Log(Logs::General, Logs::Debug, "Found client with user id of %u and account name of %s.", utwr->lsaccountid, c->GetAccountName().c_str()); @@ -161,7 +161,7 @@ void WorldServer::ProcessUsertoWorldRespLeg(uint16_t opcode, const EQ::Net::Pack if (utwr->response > 0) { per->Allowed = 1; - SendClientAuth(c->GetConnection()->GetRemoteAddr(), c->GetAccountName(), c->GetKey(), c->GetAccountID()); + SendClientAuth(c->GetConnection()->GetRemoteAddr(), c->GetAccountName(), c->GetKey(), c->GetAccountID(), c->GetLoginServerName()); } switch (utwr->response) @@ -233,7 +233,7 @@ void WorldServer::ProcessUsertoWorldResp(uint16_t opcode, const EQ::Net::Packet UsertoWorldResponse_Struct *utwr = (UsertoWorldResponse_Struct*)p.Data(); Log(Logs::General, Logs::Debug, "Trying to find client with user id of %u.", utwr->lsaccountid); - Client *c = server.client_manager->GetClient(utwr->lsaccountid); + Client *c = server.client_manager->GetClient(utwr->lsaccountid, utwr->login); if (c) { Log(Logs::General, Logs::Debug, "Found client with user id of %u and account name of %s.", utwr->lsaccountid, c->GetAccountName().c_str()); @@ -248,7 +248,7 @@ void WorldServer::ProcessUsertoWorldResp(uint16_t opcode, const EQ::Net::Packet if (utwr->response > 0) { per->Allowed = 1; - SendClientAuth(c->GetConnection()->GetRemoteAddr(), c->GetAccountName(), c->GetKey(), c->GetAccountID()); + SendClientAuth(c->GetConnection()->GetRemoteAddr(), c->GetAccountName(), c->GetKey(), c->GetAccountID(), c->GetLoginServerName()); } switch (utwr->response) @@ -586,16 +586,17 @@ void WorldServer::Handle_LSStatus(ServerLSStatus_Struct *s) server_status = s->status; } -void WorldServer::SendClientAuth(std::string ip, std::string account, std::string key, unsigned int account_id) +void WorldServer::SendClientAuth(std::string ip, std::string account, std::string key, unsigned int account_id, const std::string &loginserver_name) { EQ::Net::DynamicPacket outapp; - ClientAuthLegacy_Struct client_auth; + ClientAuth_Struct client_auth; client_auth.lsaccount_id = account_id; strncpy(client_auth.name, account.c_str(), 30); strncpy(client_auth.key, key.c_str(), 30); client_auth.lsadmin = 0; client_auth.worldadmin = 0; client_auth.ip = inet_addr(ip.c_str()); + strncpy(client_auth.lsname, &loginserver_name[0], 64); std::string client_address(ip); std::string world_address(connection->Handle()->RemoteIP()); @@ -611,10 +612,10 @@ void WorldServer::SendClientAuth(std::string ip, std::string account, std::strin } outapp.PutSerialize(0, client_auth); - connection->Send(ServerOP_LSClientAuthLeg, outapp); + connection->Send(ServerOP_LSClientAuth, outapp); if (server.options.IsDumpInPacketsOn()) { - DumpPacket(ServerOP_LSClientAuthLeg, outapp); + DumpPacket(ServerOP_LSClientAuth, outapp); } } diff --git a/loginserver/world_server.h b/loginserver/world_server.h index 83c42d27f..9e295a5fd 100644 --- a/loginserver/world_server.h +++ b/loginserver/world_server.h @@ -124,7 +124,7 @@ public: /** * Informs world that there is a client incoming with the following data. */ - void SendClientAuth(std::string ip, std::string account, std::string key, unsigned int account_id); + void SendClientAuth(std::string ip, std::string account, std::string key, unsigned int account_id, const std::string &loginserver_name); private: