diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp index c5f1747f..073da87f 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.cpp @@ -363,19 +363,20 @@ void ClientConnection::handleClientIdMessage(const ClientIdMsg &msg) { } } } else { - // test mode only + // should be used for test mode only, SOE's shitty stationID generation is dangerous and spoofable + // meaning people can impersonate elevated users if (!m_suid && !ConfigConnectionServer::getValidateStationKey()) { WARNING(true, ("Generating suid from username. This is not safe or secure.")); - m_suid = atoi(m_accountName.c_str()); - - if (m_suid == 0) { - m_suid = std::hash < std::string > {}(m_accountName.c_str()); + if (m_accountName.length() > 15) { + parentAccount.resize(15); } + + parentAccount = trim(parentAccount); + m_suid = std::hash < std::string > {}(parentAccount.c_str()); } } - static const std::string loginTrace("TRACE_LOGIN"); LOG(loginTrace, ("ClientConnection SUID = %d", m_suid)); diff --git a/engine/server/application/ConnectionServer/src/shared/ClientConnection.h b/engine/server/application/ConnectionServer/src/shared/ClientConnection.h index 384f41b6..68bf4448 100755 --- a/engine/server/application/ConnectionServer/src/shared/ClientConnection.h +++ b/engine/server/application/ConnectionServer/src/shared/ClientConnection.h @@ -195,6 +195,18 @@ private: bool sendToGameServer(GameConnection *c); }; +// stolen from http://www.codeproject.com/Articles/10880/A-trim-implementation-for-std-string +// i'm rusty and haven't gotten to lambdas yet +inline const std::string trim(std::string str) +{ + + str.erase(str.begin(), std::find_if(str.begin(), str.end(), + [](char& ch)->bool { return !isspace(ch); })); + str.erase(std::find_if(str.rbegin(), str.rend(), + [](char& ch)->bool { return !isspace(ch); }).base(), str.end()); + return str; +} + //----------------------------------------------------------------------- inline const std::string & ClientConnection::getAccountName() const diff --git a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp index d955e5eb..2f5342ca 100755 --- a/engine/server/application/LoginServer/src/shared/ClientConnection.cpp +++ b/engine/server/application/LoginServer/src/shared/ClientConnection.cpp @@ -154,6 +154,7 @@ void ClientConnection::validateClient(const std::string &id, const std::string & bool authOK = false; bool testMode = false; static const std::string authURL(ConfigLoginServer::getExternalAuthUrl()); + static const bool useSimpleAuth = ConfigLoginServer::getUseSimpleAuth(); std::string uname; std::string parentAccount; @@ -167,49 +168,74 @@ void ClientConnection::validateClient(const std::string &id, const std::string & // create the object webAPI api(authURL); - // add our data - api.addJsonData("user_name", id); - api.addJsonData("user_password", key); - api.addJsonData("ip", getRemoteAddress()); + if (useSimpleAuth) { + if (!user_id) { + uname = id; - if (api.submit()) { - bool status = api.getNullableValue("status"); - uname = api.getString("username"); - sessionID = api.getString("session_key"); + if (uname.length() > MAX_ACCOUNT_NAME_LENGTH) { + uname.resize(MAX_ACCOUNT_NAME_LENGTH); + } - if (status && !sessionID.empty() && !uname.empty()) { + uname = trim(uname); + user_id = std::hash < std::string > {}(uname.c_str()); + } + + std::ostringstream postBuf; + postBuf << "user_name=" << id << "&user_password=" << key << "&stationID=" << user_id << "&ip=" << getRemoteAddress(); + + std::string response = webAPI::simplePost(authURL, std::string(postBuf.str()), ""); + if (response == "success") + { authOK = true; - - parentAccount = api.getString("mainAccount"); - childAccounts = api.getStringMap("subAccounts"); - - if (!ConfigLoginServer::getUseOldSuidGenerator()) { - user_id = static_cast(api.getNullableValue("user_id")); - parent_id = static_cast(api.getNullableValue("parent_id")); - } else { - if (parentAccount.length() > MAX_ACCOUNT_NAME_LENGTH) { - parentAccount.resize(MAX_ACCOUNT_NAME_LENGTH); - } - - if (uname.length() > MAX_ACCOUNT_NAME_LENGTH) { - uname.resize(MAX_ACCOUNT_NAME_LENGTH); - } - - parent_id = std::hash < std::string > {}(parentAccount.c_str()); - user_id = std::hash < std::string > {}(uname.c_str()); - } } else { - std::string msg(api.getString("message")); - if (msg.empty()) { - msg = "Invalid username or password."; - } - - ErrorMessage err("Login Failed", msg); + ErrorMessage err("Login Failed", response); this->send(err, true); } } else { - ErrorMessage err("Login Failed", "Could not connect to remote."); - this->send(err, true); + // add our data + api.addJsonData("user_name", id); + api.addJsonData("user_password", key); + api.addJsonData("ip", getRemoteAddress()); + + if (api.submit()) { + bool status = api.getNullableValue("status"); + uname = api.getString("username"); + sessionID = api.getString("session_key"); + + if (status && !sessionID.empty() && !uname.empty()) { + authOK = true; + + parentAccount = api.getString("mainAccount"); + childAccounts = api.getStringMap64("subAccounts"); + + if (!ConfigLoginServer::getUseOldSuidGenerator()) { + user_id = static_cast(api.getNullableValue("user_id")); + parent_id = static_cast(api.getNullableValue("parent_id")); + } else { + if (parentAccount.length() > MAX_ACCOUNT_NAME_LENGTH) { + parentAccount.resize(MAX_ACCOUNT_NAME_LENGTH); + } + + if (uname.length() > MAX_ACCOUNT_NAME_LENGTH) { + uname.resize(MAX_ACCOUNT_NAME_LENGTH); + } + + parent_id = std::hash < std::string > {}(parentAccount.c_str()); + user_id = std::hash < std::string > {}(uname.c_str()); + } + } else { + std::string msg(api.getString("message")); + if (msg.empty()) { + msg = "Invalid username or password."; + } + + ErrorMessage err("Login Failed", msg); + this->send(err, true); + } + } else { + ErrorMessage err("Login Failed", "Could not connect to remote."); + this->send(err, true); + } } } else { // test mode @@ -221,6 +247,7 @@ void ClientConnection::validateClient(const std::string &id, const std::string & uname.resize(MAX_ACCOUNT_NAME_LENGTH); } + uname = trim(uname); user_id = std::hash < std::string > {}(uname.c_str()); } @@ -230,36 +257,41 @@ void ClientConnection::validateClient(const std::string &id, const std::string & if (!testMode) { REPORT_LOG(true, ("Client connected. Username: %s (%i) \n", uname.c_str(), user_id)); - if (!parentAccount.empty()) { - if (parentAccount != uname) { - REPORT_LOG(true, ("\t%s's parent is %s (%i) \n", uname.c_str(), parentAccount.c_str(), parent_id)); - } - } else { - parentAccount = "(Empty Parent!) " + uname; - } - - for (auto i : childAccounts) { - StationId child_id = static_cast(i.first); - std::string child(i.second); - - if (!child.empty() && i.first > 0) { - if (ConfigLoginServer::getUseOldSuidGenerator()) { - if (child.length() > MAX_ACCOUNT_NAME_LENGTH) { - child.resize(MAX_ACCOUNT_NAME_LENGTH); - } - - child_id = std::hash < std::string > {}(child.c_str()); - } - - REPORT_LOG((parent_id != - child_id), ("\tchild of %s (%i) is %s (%i) \n", parentAccount.c_str(), parent_id, child.c_str(), child_id)); - - // insert all related accounts, if not already there, into the db - if (parent_id != child_id) { - DatabaseConnection::getInstance().upsertAccountRelationship(parent_id, child_id); + if (!useSimpleAuth) { + if (!parentAccount.empty()) { + if (parentAccount != uname) { + REPORT_LOG(true, + ("\t%s's parent is %s (%i) \n", uname.c_str(), parentAccount.c_str(), parent_id)); } } else { - WARNING(true, ("Login API returned empty child account(s).")); + parentAccount = "(Empty Parent!) " + uname; + } + + + for (auto i : childAccounts) { + StationId child_id = static_cast(i.first); + std::string child(i.second); + + if (!child.empty() && i.first > 0) { + if (ConfigLoginServer::getUseOldSuidGenerator()) { + if (child.length() > MAX_ACCOUNT_NAME_LENGTH) { + child.resize(MAX_ACCOUNT_NAME_LENGTH); + } + + child_id = std::hash < std::string > {}(child.c_str()); + } + + REPORT_LOG((parent_id != + child_id), + ("\tchild of %s (%i) is %s (%i) \n", parentAccount.c_str(), parent_id, child.c_str(), child_id)); + + // insert all related accounts, if not already there, into the db + if (parent_id != child_id) { + DatabaseConnection::getInstance().upsertAccountRelationship(parent_id, child_id); + } + } else { + WARNING(true, ("Login API returned empty child account(s).")); + } } } diff --git a/engine/server/application/LoginServer/src/shared/ConfigLoginServer.cpp b/engine/server/application/LoginServer/src/shared/ConfigLoginServer.cpp index 6279494e..b562efa9 100755 --- a/engine/server/application/LoginServer/src/shared/ConfigLoginServer.cpp +++ b/engine/server/application/LoginServer/src/shared/ConfigLoginServer.cpp @@ -116,6 +116,7 @@ void ConfigLoginServer::install(void) KEY_BOOL(requireSecureLoginForCsTool, true); KEY_BOOL(useExternalAuth, false); KEY_STRING(externalAuthURL, ""); + KEY_BOOL(useSimpleAuth, true); KEY_BOOL(useOldSuidGenerator, false); int index = 0; diff --git a/engine/server/application/LoginServer/src/shared/ConfigLoginServer.h b/engine/server/application/LoginServer/src/shared/ConfigLoginServer.h index 484071f6..3b9c8829 100755 --- a/engine/server/application/LoginServer/src/shared/ConfigLoginServer.h +++ b/engine/server/application/LoginServer/src/shared/ConfigLoginServer.h @@ -64,12 +64,13 @@ class ConfigLoginServer int populationLightThresholdPercent; int csToolPort; - bool requireSecureLoginForCsTool; - bool useExternalAuth; + bool requireSecureLoginForCsTool; + bool useExternalAuth; + bool useSimpleAuth; const char * externalAuthURL; - bool useOldSuidGenerator; + bool useOldSuidGenerator; }; static const uint16 getCentralServicePort(); @@ -132,8 +133,9 @@ class ConfigLoginServer static int getPopulationMediumThresholdPercent(); static int getPopulationLightThresholdPercent(); - static bool getUseExternalAuth(); + static bool getUseExternalAuth(); static const char * getExternalAuthUrl(); + static const bool getUseSimpleAuth(); static bool getUseOldSuidGenerator(); // has character creation for this cluster been disabled through config option @@ -487,6 +489,10 @@ inline const char * ConfigLoginServer::getExternalAuthUrl() return data->externalAuthURL; } +inline const bool ConfigLoginServer::getUseSimpleAuth() +{ + return data->useSimpleAuth; +} inline bool ConfigLoginServer::getUseOldSuidGenerator() {