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(const Json::Value &value)

View File

@ -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;
};

View File

@ -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

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)) {
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;
}

View File

@ -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;
}

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 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.

View File

@ -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)
{

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 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.

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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];