convert login.ini to login.json, stole jumber's idea about auto-updating old passwords (wip still)

This commit is contained in:
KimLS 2017-12-16 23:08:21 -08:00
parent 3ee5730890
commit 7a778c549f
14 changed files with 110 additions and 112 deletions

View File

@ -3,6 +3,7 @@
EQ::JsonConfigFile::JsonConfigFile() EQ::JsonConfigFile::JsonConfigFile()
{ {
} }
EQ::JsonConfigFile::JsonConfigFile(const Json::Value &value) EQ::JsonConfigFile::JsonConfigFile(const Json::Value &value)

View File

@ -7,6 +7,7 @@ namespace EQ
class JsonConfigFile class JsonConfigFile
{ {
public: public:
JsonConfigFile();
JsonConfigFile(const Json::Value &value); JsonConfigFile(const Json::Value &value);
~JsonConfigFile(); ~JsonConfigFile();
@ -19,7 +20,6 @@ namespace EQ
Json::Value& RawHandle() { return m_root; } Json::Value& RawHandle() { return m_root; }
private: private:
JsonConfigFile();
Json::Value m_root; Json::Value m_root;
}; };

View File

@ -3,7 +3,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
SET(eqlogin_sources SET(eqlogin_sources
client.cpp client.cpp
client_manager.cpp client_manager.cpp
config.cpp
database_mysql.cpp database_mysql.cpp
encryption.cpp encryption.cpp
main.cpp main.cpp
@ -14,7 +13,6 @@ SET(eqlogin_sources
SET(eqlogin_headers SET(eqlogin_headers
client.h client.h
client_manager.h client_manager.h
config.h
database.h database.h
database_mysql.h database_mysql.h
encryption.h encryption.h

View File

@ -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)) { if (eqcrypt_verify_hash(user, cred, db_account_password_hash, mode)) {
result = true; result = true;
} }
else { else
result = false; {
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) void Client::AttemptLoginAccountCreation(const std::string &user, const std::string &pass, const std::string &loginserver)
{ {
if (loginserver == "eqemu") { if (loginserver == "eqemu") {
if (!server.options.CanAutoCreateAccounts()) { if (!server.options.CanAutoLinkAccounts()) {
DoFailedLogin(); DoFailedLogin();
return; return;
} }

View File

@ -25,14 +25,14 @@ extern bool run_server;
ClientManager::ClientManager() 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); EQ::Net::EQStreamManagerOptions titanium_opts(titanium_port, false, false);
titanium_stream = new EQ::Net::EQStreamManager(titanium_opts); titanium_stream = new EQ::Net::EQStreamManager(titanium_opts);
titanium_ops = new RegularOpcodeManager; 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.", 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; run_server = false;
} }
@ -43,14 +43,14 @@ ClientManager::ClientManager()
clients.push_back(c); 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); EQ::Net::EQStreamManagerOptions sod_opts(sod_port, false, false);
sod_stream = new EQ::Net::EQStreamManager(sod_opts); sod_stream = new EQ::Net::EQStreamManager(sod_opts);
sod_ops = new RegularOpcodeManager; 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.", 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; run_server = false;
} }

View File

@ -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 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. * Retrieves the world registration from the long and short names provided.
* Needed for world login procedure. * Needed for world login procedure.

View File

@ -223,6 +223,25 @@ bool DatabaseMySQL::CreateLoginDataWithID(const std::string & name, const std::s
return true; 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, 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) unsigned int &trusted, std::string &list_desc, std::string &account, std::string &password)
{ {

View File

@ -67,6 +67,8 @@ public:
virtual bool CreateLoginDataWithID(const std::string &name, const std::string &password, const std::string &loginserver, unsigned int id); 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. * Retrieves the world registration from the long and short names provided.
* Needed for world login procedure. * Needed for world login procedure.

View File

@ -74,27 +74,25 @@ std::string eqcrypt_sha512(const std::string &msg) {
std::string eqcrypt_argon2(const std::string &msg) std::string eqcrypt_argon2(const std::string &msg)
{ {
std::string ret; char buffer[crypto_pwhash_STRBYTES];
ret.resize(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 "";
} }
return ret; return buffer;
} }
std::string eqcrypt_scrypt(const std::string &msg) std::string eqcrypt_scrypt(const std::string &msg)
{ {
std::string ret; char buffer[crypto_pwhash_scryptsalsa208sha256_STRBYTES];
ret.resize(crypto_pwhash_scryptsalsa208sha256_STRBYTES);
if (crypto_pwhash_scryptsalsa208sha256_str(&ret[0], &msg[0], msg.length(), if (crypto_pwhash_scryptsalsa208sha256_str(&buffer[0], &msg[0], msg.length(),
crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE) != 0) { crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) {
return ""; return "";
} }
return ret; return buffer;
} }
#endif #endif

View File

@ -18,7 +18,7 @@
#ifndef EQEMU_LOGINSERVER_H #ifndef EQEMU_LOGINSERVER_H
#define EQEMU_LOGINSERVER_H #define EQEMU_LOGINSERVER_H
#include "config.h" #include "../common/json_config.h"
#include "database.h" #include "database.h"
#include "database_mysql.h" #include "database_mysql.h"
#include "encryption.h" #include "encryption.h"
@ -33,9 +33,9 @@
struct LoginServer struct LoginServer
{ {
public: public:
LoginServer() : config(nullptr), db(nullptr), server_manager(nullptr) { } LoginServer() : db(nullptr), server_manager(nullptr) { }
Config *config; EQ::JsonConfigFile config;
Database *db; Database *db;
Options options; Options options;
ServerManager *server_manager; ServerManager *server_manager;

View File

@ -48,99 +48,51 @@ int main()
Log(Logs::General, Logs::Login_Server, "Logging System Init."); Log(Logs::General, Logs::Login_Server, "Logging System Init.");
/* Parse out login.ini */ server.config = EQ::JsonConfigFile::Load("login.json");
server.config = new Config();
Log(Logs::General, Logs::Login_Server, "Config System Init."); 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.Trace(server.config.GetVariableBool("general", "trace", false));
server.options.AllowUnregistered(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) #ifdef ENABLE_SECURITY
server.options.Trace(true); 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.AccountTable(server.config.GetVariableString("schema", "account_table", "tblLoginServerAccounts"));
server.options.WorldTrace(true); server.options.WorldRegistrationTable(server.config.GetVariableString("schema", "account_table", "tblWorldServerRegistration"));
server.options.WorldAdminRegistrationTable(server.config.GetVariableString("schema", "account_table", "tblServerAdminRegistration"));
if (server.config->GetVariable("options", "dump_packets_in").compare("TRUE") == 0) server.options.WorldServerTypeTable(server.config.GetVariableString("schema", "account_table", "tblServerListType"));
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);
/* Create database connection */ /* 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 #ifdef EQEMU_MYSQL_ENABLED
Log(Logs::General, Logs::Login_Server, "MySQL Database Init."); Log(Logs::General, Logs::Login_Server, "MySQL Database Init.");
server.db = (Database*)new DatabaseMySQL( server.db = (Database*)new DatabaseMySQL(
server.config->GetVariable("database", "user"), server.config.GetVariableString("database", "user", "root"),
server.config->GetVariable("database", "password"), server.config.GetVariableString("database", "password", ""),
server.config->GetVariable("database", "host"), server.config.GetVariableString("database", "host", "localhost"),
server.config->GetVariable("database", "port"), server.config.GetVariableString("database", "port", "3306"),
server.config->GetVariable("database", "db")); server.config.GetVariableString("database", "db", "peq"));
#endif #endif
} }
/* Make sure our database got created okay, otherwise cleanup and exit. */ /* Make sure our database got created okay, otherwise cleanup and exit. */
if (!server.db) { if (!server.db) {
Log(Logs::General, Logs::Error, "Database Initialization Failure."); 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."); Log(Logs::General, Logs::Login_Server, "Log System Shutdown.");
return 1; return 1;
} }
@ -151,11 +103,8 @@ int main()
if (!server.server_manager) { if (!server.server_manager) {
//We can't run without a server manager, cleanup and exit. //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::Error, "Server Manager Failed to Start.");
Log(Logs::General, Logs::Login_Server, "Database System Shutdown."); Log(Logs::General, Logs::Login_Server, "Database System Shutdown.");
delete server.db; delete server.db;
Log(Logs::General, Logs::Login_Server, "Config System Shutdown.");
delete server.config;
return 1; return 1;
} }
@ -170,8 +119,6 @@ int main()
Log(Logs::General, Logs::Login_Server, "Database System Shutdown."); Log(Logs::General, Logs::Login_Server, "Database System Shutdown.");
delete server.db; delete server.db;
Log(Logs::General, Logs::Login_Server, "Config System Shutdown.");
delete server.config;
return 1; return 1;
} }
@ -199,7 +146,5 @@ int main()
Log(Logs::General, Logs::Login_Server, "Database System Shutdown."); Log(Logs::General, Logs::Login_Server, "Database System Shutdown.");
delete server.db; delete server.db;
Log(Logs::General, Logs::Login_Server, "Config System Shutdown.");
delete server.config;
return 0; return 0;
} }

View File

@ -178,6 +178,9 @@ public:
inline void DefaultLoginServerName(std::string v) { default_loginserver_name = v; } inline void DefaultLoginServerName(std::string v) { default_loginserver_name = v; }
inline std::string GetDefaultLoginServerName() const { return default_loginserver_name; } 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: private:
bool allow_unregistered; bool allow_unregistered;
bool trace; bool trace;
@ -189,6 +192,7 @@ private:
bool allow_password_login; bool allow_password_login;
bool auto_create_accounts; bool auto_create_accounts;
bool auto_link_accounts; bool auto_link_accounts;
bool update_insecure_passwords;
int encryption_mode; int encryption_mode;
std::string local_network; std::string local_network;
std::string account_table; std::string account_table;

View File

@ -27,7 +27,7 @@ extern bool run_server;
ServerManager::ServerManager() 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()); server_connection.reset(new EQ::Net::ServertalkServer());
EQ::Net::ServertalkServerOptions opts; EQ::Net::ServertalkServerOptions opts;

View File

@ -19,7 +19,7 @@ struct EQ::Net::ConsoleLoginStatus CheckLogin(const std::string& username, const
std::string prefix = "eqemu"; std::string prefix = "eqemu";
std::string raw_user = ""; std::string raw_user = "";
auto split = SplitString(username, ':'); auto split = SplitString(username, '.');
if (split.size() == 2) { if (split.size() == 2) {
prefix = split[0]; prefix = split[0];
raw_user = split[1]; raw_user = split[1];
@ -399,7 +399,7 @@ void ConsoleSetPass(EQ::Net::ConsoleServerConnection* connection, const std::str
std::string prefix = "eqemu"; std::string prefix = "eqemu";
std::string raw_user = ""; std::string raw_user = "";
auto split = SplitString(args[0], ':'); auto split = SplitString(args[0], '.');
if (split.size() == 2) { if (split.size() == 2) {
prefix = split[0]; prefix = split[0];
raw_user = split[1]; raw_user = split[1];