From 7a778c549fa58e00457f38351397ee874b0c7252 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 16 Dec 2017 23:08:21 -0800 Subject: [PATCH] convert login.ini to login.json, stole jumber's idea about auto-updating old passwords (wip still) --- common/json_config.cpp | 1 + common/json_config.h | 2 +- loginserver/CMakeLists.txt | 2 - loginserver/client.cpp | 35 +++++++++- loginserver/client_manager.cpp | 12 ++-- loginserver/database.h | 2 + loginserver/database_mysql.cpp | 19 ++++++ loginserver/database_mysql.h | 2 + loginserver/encryption.cpp | 16 ++--- loginserver/login_server.h | 6 +- loginserver/main.cpp | 115 +++++++++------------------------ loginserver/options.h | 4 ++ loginserver/server_manager.cpp | 2 +- world/console.cpp | 4 +- 14 files changed, 110 insertions(+), 112 deletions(-) diff --git a/common/json_config.cpp b/common/json_config.cpp index d677fc452..c9599b99d 100644 --- a/common/json_config.cpp +++ b/common/json_config.cpp @@ -3,6 +3,7 @@ EQ::JsonConfigFile::JsonConfigFile() { + } EQ::JsonConfigFile::JsonConfigFile(const Json::Value &value) diff --git a/common/json_config.h b/common/json_config.h index 279fb64d9..ba1051970 100644 --- a/common/json_config.h +++ b/common/json_config.h @@ -7,6 +7,7 @@ namespace EQ class JsonConfigFile { public: + JsonConfigFile(); JsonConfigFile(const Json::Value &value); ~JsonConfigFile(); @@ -19,7 +20,6 @@ namespace EQ Json::Value& RawHandle() { return m_root; } private: - JsonConfigFile(); Json::Value m_root; }; diff --git a/loginserver/CMakeLists.txt b/loginserver/CMakeLists.txt index 1561aa537..3af0c7e66 100644 --- a/loginserver/CMakeLists.txt +++ b/loginserver/CMakeLists.txt @@ -3,7 +3,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) SET(eqlogin_sources client.cpp client_manager.cpp - config.cpp database_mysql.cpp encryption.cpp main.cpp @@ -14,7 +13,6 @@ SET(eqlogin_sources SET(eqlogin_headers client.h client_manager.h - config.h database.h database_mysql.h encryption.h diff --git a/loginserver/client.cpp b/loginserver/client.cpp index 3e7c282b9..0db9c1600 100644 --- a/loginserver/client.cpp +++ b/loginserver/client.cpp @@ -251,8 +251,37 @@ void Client::Handle_Login(const char* data, unsigned int size) if (eqcrypt_verify_hash(user, cred, db_account_password_hash, mode)) { result = true; } - else { - result = false; + else + { + if (server.options.IsUpdatingInsecurePasswords()) { + auto len = db_account_password_hash.length(); + int start = 0; + int end = 0; + switch (len) { + case 32: + start = 1; + end = 4; + break; + case 40: + start = 5; + end = 8; + break; + case 128: + start = 9; + end = 12; + break; + } + + if (start != 0) { + for (int i = start; i <= end; ++i) { + if (eqcrypt_verify_hash(user, cred, db_account_password_hash, i)) { + result = true; + server.db->UpdateLoginHash(user, db_loginserver, eqcrypt_hash(user, cred, mode)); + break; + } + } + } + } } } } @@ -336,7 +365,7 @@ void Client::GenerateKey() void Client::AttemptLoginAccountCreation(const std::string &user, const std::string &pass, const std::string &loginserver) { if (loginserver == "eqemu") { - if (!server.options.CanAutoCreateAccounts()) { + if (!server.options.CanAutoLinkAccounts()) { DoFailedLogin(); return; } diff --git a/loginserver/client_manager.cpp b/loginserver/client_manager.cpp index 569f8c27d..532f65032 100644 --- a/loginserver/client_manager.cpp +++ b/loginserver/client_manager.cpp @@ -25,14 +25,14 @@ extern bool run_server; ClientManager::ClientManager() { - int titanium_port = atoi(server.config->GetVariable("Titanium", "port").c_str()); + int titanium_port = server.config.GetVariableInt("Titanium", "port", 5998); EQ::Net::EQStreamManagerOptions titanium_opts(titanium_port, false, false); titanium_stream = new EQ::Net::EQStreamManager(titanium_opts); titanium_ops = new RegularOpcodeManager; - if (!titanium_ops->LoadOpcodes(server.config->GetVariable("Titanium", "opcodes").c_str())) + if (!titanium_ops->LoadOpcodes(server.config.GetVariableString("Titanium", "opcodes", "login_opcodes.conf").c_str())) { Log(Logs::General, Logs::Error, "ClientManager fatal error: couldn't load opcodes for Titanium file %s.", - server.config->GetVariable("Titanium", "opcodes").c_str()); + server.config.GetVariableString("Titanium", "opcodes", "login_opcodes.conf").c_str()); run_server = false; } @@ -43,14 +43,14 @@ ClientManager::ClientManager() clients.push_back(c); }); - int sod_port = atoi(server.config->GetVariable("SoD", "port").c_str()); + int sod_port = server.config.GetVariableInt("SoD", "port", 5999); EQ::Net::EQStreamManagerOptions sod_opts(sod_port, false, false); sod_stream = new EQ::Net::EQStreamManager(sod_opts); sod_ops = new RegularOpcodeManager; - if (!sod_ops->LoadOpcodes(server.config->GetVariable("SoD", "opcodes").c_str())) + if (!sod_ops->LoadOpcodes(server.config.GetVariableString("SoD", "opcodes", "login_opcodes.conf").c_str())) { Log(Logs::General, Logs::Error, "ClientManager fatal error: couldn't load opcodes for SoD file %s.", - server.config->GetVariable("SoD", "opcodes").c_str()); + server.config.GetVariableString("SoD", "opcodes", "login_opcodes.conf").c_str()); run_server = false; } diff --git a/loginserver/database.h b/loginserver/database.h index 0025cd476..00a76b099 100644 --- a/loginserver/database.h +++ b/loginserver/database.h @@ -49,6 +49,8 @@ public: virtual bool CreateLoginDataWithID(const std::string &name, const std::string &password, const std::string &loginserver, unsigned int id) { return false; } + virtual void UpdateLoginHash(const std::string &name, const std::string &loginserver, const std::string &hash) { } + /** * Retrieves the world registration from the long and short names provided. * Needed for world login procedure. diff --git a/loginserver/database_mysql.cpp b/loginserver/database_mysql.cpp index 9781ec4df..0787110a9 100644 --- a/loginserver/database_mysql.cpp +++ b/loginserver/database_mysql.cpp @@ -223,6 +223,25 @@ bool DatabaseMySQL::CreateLoginDataWithID(const std::string & name, const std::s return true; } +void DatabaseMySQL::UpdateLoginHash(const std::string &name, const std::string &loginserver, const std::string &hash) +{ + if (!database) + { + return; + } + + auto query = fmt::format("UPDATE {0} SET AccountPassword='{1}' WHERE AccountName='{2}' AND AccountLoginserver='{3}'", + server.options.GetAccountTable(), + hash, + EscapeString(name), + EscapeString(loginserver)); + + if (mysql_query(database, query.c_str()) != 0) + { + Log(Logs::General, Logs::Error, "Mysql query failed: %s", query.c_str()); + } +} + bool DatabaseMySQL::GetWorldRegistration(std::string long_name, std::string short_name, unsigned int &id, std::string &desc, unsigned int &list_id, unsigned int &trusted, std::string &list_desc, std::string &account, std::string &password) { diff --git a/loginserver/database_mysql.h b/loginserver/database_mysql.h index 41eac0eb5..60e8290cf 100644 --- a/loginserver/database_mysql.h +++ b/loginserver/database_mysql.h @@ -67,6 +67,8 @@ public: virtual bool CreateLoginDataWithID(const std::string &name, const std::string &password, const std::string &loginserver, unsigned int id); + virtual void UpdateLoginHash(const std::string &name, const std::string &loginserver, const std::string &hash); + /** * Retrieves the world registration from the long and short names provided. * Needed for world login procedure. diff --git a/loginserver/encryption.cpp b/loginserver/encryption.cpp index c8e688e5f..bdbab2fbf 100644 --- a/loginserver/encryption.cpp +++ b/loginserver/encryption.cpp @@ -74,27 +74,25 @@ std::string eqcrypt_sha512(const std::string &msg) { std::string eqcrypt_argon2(const std::string &msg) { - std::string ret; - ret.resize(crypto_pwhash_STRBYTES); + char buffer[crypto_pwhash_STRBYTES]; - if (crypto_pwhash_str(&ret[0], &msg[0], msg.length(), crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE) != 0) { + if (crypto_pwhash_str(&buffer[0], &msg[0], msg.length(), crypto_pwhash_OPSLIMIT_INTERACTIVE, crypto_pwhash_MEMLIMIT_INTERACTIVE) != 0) { return ""; } - return ret; + return buffer; } std::string eqcrypt_scrypt(const std::string &msg) { - std::string ret; - ret.resize(crypto_pwhash_scryptsalsa208sha256_STRBYTES); + char buffer[crypto_pwhash_scryptsalsa208sha256_STRBYTES]; - if (crypto_pwhash_scryptsalsa208sha256_str(&ret[0], &msg[0], msg.length(), - crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE) != 0) { + if (crypto_pwhash_scryptsalsa208sha256_str(&buffer[0], &msg[0], msg.length(), + crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { return ""; } - return ret; + return buffer; } #endif diff --git a/loginserver/login_server.h b/loginserver/login_server.h index a5d780ebb..111565dbb 100644 --- a/loginserver/login_server.h +++ b/loginserver/login_server.h @@ -18,7 +18,7 @@ #ifndef EQEMU_LOGINSERVER_H #define EQEMU_LOGINSERVER_H -#include "config.h" +#include "../common/json_config.h" #include "database.h" #include "database_mysql.h" #include "encryption.h" @@ -33,9 +33,9 @@ struct LoginServer { public: - LoginServer() : config(nullptr), db(nullptr), server_manager(nullptr) { } + LoginServer() : db(nullptr), server_manager(nullptr) { } - Config *config; + EQ::JsonConfigFile config; Database *db; Options options; ServerManager *server_manager; diff --git a/loginserver/main.cpp b/loginserver/main.cpp index 17cc179e5..b2603056a 100644 --- a/loginserver/main.cpp +++ b/loginserver/main.cpp @@ -48,99 +48,51 @@ int main() Log(Logs::General, Logs::Login_Server, "Logging System Init."); - /* Parse out login.ini */ - server.config = new Config(); + server.config = EQ::JsonConfigFile::Load("login.json"); Log(Logs::General, Logs::Login_Server, "Config System Init."); - server.config->Parse("login.ini"); - if (server.config->GetVariable("options", "unregistered_allowed").compare("FALSE") == 0) - server.options.AllowUnregistered(false); + server.options.Trace(server.config.GetVariableBool("general", "trace", false)); + server.options.WorldTrace(server.config.GetVariableBool("general", "world_trace", false)); + server.options.DumpInPackets(server.config.GetVariableBool("general", "dump_packets_in", false)); + server.options.DumpOutPackets(server.config.GetVariableBool("general", "dump_packets_out", false)); + server.options.LocalNetwork(server.config.GetVariableString("general", "local_network", "192.168.1.")); + server.options.RejectDuplicateServers(server.config.GetVariableBool("general", "reject_duplicate_servers", false)); + server.options.AutoCreateAccounts(server.config.GetVariableBool("general", "auto_create_accounts", true)); + server.options.AutoLinkAccounts(server.config.GetVariableBool("general", "auto_link_accounts", true)); + server.options.EQEmuLoginServerAddress(server.config.GetVariableString("general", "eqemu_loginserver_address", "login.eqemulator.net:5999")); + server.options.DefaultLoginServerName(server.config.GetVariableString("general", "default_loginserver_name", "peq")); - if (server.config->GetVariable("options", "trace").compare("TRUE") == 0) - server.options.Trace(true); +#ifdef ENABLE_SECURITY + server.options.EncryptionMode(server.config.GetVariableInt("security", "mode", 13)); +#else + server.options.EncryptionMode(server.config.GetVariableInt("security", "mode", 6)); +#endif + server.options.AllowUnregistered(server.config.GetVariableBool("security", "unregistered_allowed", true)); + server.options.AllowTokenLogin(server.config.GetVariableBool("security", "allow_token_login", false)); + server.options.AllowPasswordLogin(server.config.GetVariableBool("security", "allow_password_login", true)); + server.options.UpdateInsecurePasswords(server.config.GetVariableBool("security", "update_insecure_passwords", true)); - if (server.config->GetVariable("options", "world_trace").compare("TRUE") == 0) - server.options.WorldTrace(true); - - if (server.config->GetVariable("options", "dump_packets_in").compare("TRUE") == 0) - server.options.DumpInPackets(true); - - if (server.config->GetVariable("options", "dump_packets_out").compare("TRUE") == 0) - server.options.DumpOutPackets(true); - - if (server.config->GetVariable("security", "allow_token_login").compare("TRUE") == 0) - server.options.AllowTokenLogin(true); - - auto eqemu_loginserver_addr = server.config->GetVariable("options", "eqemu_loginserver_address"); - if (eqemu_loginserver_addr.size() > 0) { - server.options.EQEmuLoginServerAddress(eqemu_loginserver_addr); - } - else { - server.options.EQEmuLoginServerAddress("login.eqemulator.net:5999"); - } - - auto default_loginserver_name = server.config->GetVariable("options", "default_loginserver_name"); - if (default_loginserver_name.size() > 0) { - server.options.DefaultLoginServerName(default_loginserver_name); - } - else { - server.options.DefaultLoginServerName("peq"); - } - - if (server.config->GetVariable("security", "allow_password_login").compare("FALSE") == 0) - server.options.AllowPasswordLogin(false); - - if (server.config->GetVariable("options", "auto_create_accounts").compare("TRUE") == 0) - server.options.AutoCreateAccounts(true); - - if (server.config->GetVariable("options", "auto_link_accounts").compare("TRUE") == 0) - server.options.AutoLinkAccounts(true); - - std::string mode = server.config->GetVariable("security", "mode"); - if (mode.size() > 0) - server.options.EncryptionMode(atoi(mode.c_str())); - - std::string local_network = server.config->GetVariable("options", "local_network"); - if (local_network.size() > 0) - server.options.LocalNetwork(local_network); - - if (server.config->GetVariable("options", "reject_duplicate_servers").compare("TRUE") == 0) - server.options.RejectDuplicateServers(true); - - local_network = server.config->GetVariable("schema", "account_table"); - if (local_network.size() > 0) - server.options.AccountTable(local_network); - - local_network = server.config->GetVariable("schema", "world_registration_table"); - if (local_network.size() > 0) - server.options.WorldRegistrationTable(local_network); - - local_network = server.config->GetVariable("schema", "world_admin_registration_table"); - if (local_network.size() > 0) - server.options.WorldAdminRegistrationTable(local_network); - - local_network = server.config->GetVariable("schema", "world_server_type_table"); - if (local_network.size() > 0) - server.options.WorldServerTypeTable(local_network); + server.options.AccountTable(server.config.GetVariableString("schema", "account_table", "tblLoginServerAccounts")); + server.options.WorldRegistrationTable(server.config.GetVariableString("schema", "account_table", "tblWorldServerRegistration")); + server.options.WorldAdminRegistrationTable(server.config.GetVariableString("schema", "account_table", "tblServerAdminRegistration")); + server.options.WorldServerTypeTable(server.config.GetVariableString("schema", "account_table", "tblServerListType")); /* Create database connection */ - if (server.config->GetVariable("database", "subsystem").compare("MySQL") == 0) { + if (server.config.GetVariableString("database", "subsystem", "MySQL").compare("MySQL") == 0) { #ifdef EQEMU_MYSQL_ENABLED Log(Logs::General, Logs::Login_Server, "MySQL Database Init."); server.db = (Database*)new DatabaseMySQL( - server.config->GetVariable("database", "user"), - server.config->GetVariable("database", "password"), - server.config->GetVariable("database", "host"), - server.config->GetVariable("database", "port"), - server.config->GetVariable("database", "db")); + server.config.GetVariableString("database", "user", "root"), + server.config.GetVariableString("database", "password", ""), + server.config.GetVariableString("database", "host", "localhost"), + server.config.GetVariableString("database", "port", "3306"), + server.config.GetVariableString("database", "db", "peq")); #endif } /* Make sure our database got created okay, otherwise cleanup and exit. */ if (!server.db) { Log(Logs::General, Logs::Error, "Database Initialization Failure."); - Log(Logs::General, Logs::Login_Server, "Config System Shutdown."); - delete server.config; Log(Logs::General, Logs::Login_Server, "Log System Shutdown."); return 1; } @@ -151,11 +103,8 @@ int main() if (!server.server_manager) { //We can't run without a server manager, cleanup and exit. Log(Logs::General, Logs::Error, "Server Manager Failed to Start."); - Log(Logs::General, Logs::Login_Server, "Database System Shutdown."); delete server.db; - Log(Logs::General, Logs::Login_Server, "Config System Shutdown."); - delete server.config; return 1; } @@ -170,8 +119,6 @@ int main() Log(Logs::General, Logs::Login_Server, "Database System Shutdown."); delete server.db; - Log(Logs::General, Logs::Login_Server, "Config System Shutdown."); - delete server.config; return 1; } @@ -199,7 +146,5 @@ int main() Log(Logs::General, Logs::Login_Server, "Database System Shutdown."); delete server.db; - Log(Logs::General, Logs::Login_Server, "Config System Shutdown."); - delete server.config; return 0; } diff --git a/loginserver/options.h b/loginserver/options.h index a89d3f760..067c911ec 100644 --- a/loginserver/options.h +++ b/loginserver/options.h @@ -178,6 +178,9 @@ public: inline void DefaultLoginServerName(std::string v) { default_loginserver_name = v; } inline std::string GetDefaultLoginServerName() const { return default_loginserver_name; } + inline void UpdateInsecurePasswords(bool b) { update_insecure_passwords = b; } + inline bool IsUpdatingInsecurePasswords() const { return update_insecure_passwords; } + private: bool allow_unregistered; bool trace; @@ -189,6 +192,7 @@ private: bool allow_password_login; bool auto_create_accounts; bool auto_link_accounts; + bool update_insecure_passwords; int encryption_mode; std::string local_network; std::string account_table; diff --git a/loginserver/server_manager.cpp b/loginserver/server_manager.cpp index 4be55ac98..94c7705fc 100644 --- a/loginserver/server_manager.cpp +++ b/loginserver/server_manager.cpp @@ -27,7 +27,7 @@ extern bool run_server; ServerManager::ServerManager() { - int listen_port = atoi(server.config->GetVariable("options", "listen_port").c_str()); + int listen_port = server.config.GetVariableInt("general", "listen_port", 5998); server_connection.reset(new EQ::Net::ServertalkServer()); EQ::Net::ServertalkServerOptions opts; diff --git a/world/console.cpp b/world/console.cpp index ab7097244..8342b2e3c 100644 --- a/world/console.cpp +++ b/world/console.cpp @@ -19,7 +19,7 @@ struct EQ::Net::ConsoleLoginStatus CheckLogin(const std::string& username, const std::string prefix = "eqemu"; std::string raw_user = ""; - auto split = SplitString(username, ':'); + auto split = SplitString(username, '.'); if (split.size() == 2) { prefix = split[0]; raw_user = split[1]; @@ -399,7 +399,7 @@ void ConsoleSetPass(EQ::Net::ConsoleServerConnection* connection, const std::str std::string prefix = "eqemu"; std::string raw_user = ""; - auto split = SplitString(args[0], ':'); + auto split = SplitString(args[0], '.'); if (split.size() == 2) { prefix = split[0]; raw_user = split[1];