Add CLI and Web endpoints to change local login account password

This commit is contained in:
Akkadius 2019-08-04 05:04:34 -05:00
parent b0d33f094d
commit ba6009730b
11 changed files with 204 additions and 44 deletions

View File

@ -143,7 +143,6 @@ void EQEmuLogSys::LoadLogSettingsDefaults()
log_settings[Logs::Warning].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Notice].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Info].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Debug].log_to_console = static_cast<uint8>(Logs::General);
/**
* Set Category enabled status on defaults

View File

@ -189,3 +189,52 @@ bool AccountManagement::CheckLoginserverUserCredentials(
return validated_credentials;
}
/**
* @param in_account_username
* @param in_account_password
* @return
*/
bool AccountManagement::UpdateLoginserverUserCredentials(
const std::string &in_account_username,
const std::string &in_account_password,
const std::string &source_loginserver
)
{
auto mode = server.options.GetEncryptionMode();
Database::DbLoginServerAccount
login_server_account = server.db->GetLoginServerAccountByAccountName(
in_account_username,
source_loginserver
);
if (!login_server_account.loaded) {
LogError(
"ChangeLoginserverUserCredentials account [{0}] source_loginserver [{1}] not found!",
in_account_username,
source_loginserver
);
return false;
}
server.db->UpdateLoginserverAccountPasswordHash(
in_account_username,
source_loginserver,
eqcrypt_hash(
in_account_username,
in_account_password,
mode
)
);
LogDebug(
"ChangeLoginserverUserCredentials account [{0}] source_loginserver [{1}] credentials updated!",
in_account_username,
source_loginserver
);
return true;
}

View File

@ -59,6 +59,17 @@ public:
const std::string &in_account_password,
const std::string &source_loginserver = "local"
);
/**
* @param in_account_username
* @param in_account_password
* @return
*/
static bool UpdateLoginserverUserCredentials(
const std::string &in_account_username,
const std::string &in_account_password,
const std::string &source_loginserver = "local"
);
};

View File

@ -486,21 +486,21 @@ void Client::DoFailedLogin()
/**
* Verifies a login hash, will also attempt to update a login hash if needed
*
* @param user
* @param loginserver
* @param cred
* @param hash
* @param account_username
* @param source_loginserver
* @param account_password
* @param password_hash
* @return
*/
bool Client::VerifyLoginHash(
const std::string &user,
const std::string &loginserver,
const std::string &cred,
const std::string &hash
const std::string &account_username,
const std::string &source_loginserver,
const std::string &account_password,
const std::string &password_hash
)
{
auto mode = server.options.GetEncryptionMode();
if (eqcrypt_verify_hash(user, cred, hash, mode)) {
if (eqcrypt_verify_hash(account_username, account_password, password_hash, mode)) {
return true;
}
else {
@ -509,46 +509,67 @@ bool Client::VerifyLoginHash(
mode = EncryptionModeArgon2;
}
if (hash.length() == 32) { //md5 is insecure
if (password_hash.length() == 32) { //md5 is insecure
for (int i = EncryptionModeMD5; i <= EncryptionModeMD5Triple; ++i) {
if (i != mode && eqcrypt_verify_hash(user, cred, hash, i)) {
if (i != mode && eqcrypt_verify_hash(account_username, account_password, password_hash, i)) {
LogDebug(
"user [{0}] loginserver [{1}] mode [{2}]",
user,
loginserver,
account_username,
source_loginserver,
mode
);
server.db->UpdateLoginHash(user, loginserver, eqcrypt_hash(user, cred, mode));
server.db->UpdateLoginserverAccountPasswordHash(
account_username,
source_loginserver,
eqcrypt_hash(
account_username,
account_password,
mode
));
return true;
}
}
}
else if (hash.length() == 40) { //sha1 is insecure
else if (password_hash.length() == 40) { //sha1 is insecure
for (int i = EncryptionModeSHA; i <= EncryptionModeSHATriple; ++i) {
if (i != mode && eqcrypt_verify_hash(user, cred, hash, i)) {
if (i != mode && eqcrypt_verify_hash(account_username, account_password, password_hash, i)) {
LogDebug(
"user [{0}] loginserver [{1}] mode [{2}]",
user,
loginserver,
account_username,
source_loginserver,
mode
);
server.db->UpdateLoginHash(user, loginserver, eqcrypt_hash(user, cred, mode));
server.db->UpdateLoginserverAccountPasswordHash(
account_username,
source_loginserver,
eqcrypt_hash(
account_username,
account_password,
mode
));
return true;
}
}
}
else if (hash.length() == 128) { //sha2-512 is insecure
else if (password_hash.length() == 128) { //sha2-512 is insecure
for (int i = EncryptionModeSHA512; i <= EncryptionModeSHA512Triple; ++i) {
if (i != mode && eqcrypt_verify_hash(user, cred, hash, i)) {
if (i != mode && eqcrypt_verify_hash(account_username, account_password, password_hash, i)) {
LogDebug(
"user [{0}] loginserver [{1}] mode [{2}]",
user,
loginserver,
account_username,
source_loginserver,
mode
);
server.db->UpdateLoginHash(user, loginserver, eqcrypt_hash(user, cred, mode));
server.db->UpdateLoginserverAccountPasswordHash(
account_username,
source_loginserver,
eqcrypt_hash(
account_username,
account_password,
mode
));
return true;
}
}

View File

@ -177,17 +177,17 @@ public:
/**
* Verifies a login hash, will also attempt to update a login hash if needed
*
* @param user
* @param loginserver
* @param cred
* @param hash
* @param account_username
* @param source_loginserver
* @param account_password
* @param password_hash
* @return
*/
bool VerifyLoginHash(
const std::string &user,
const std::string &loginserver,
const std::string &cred,
const std::string &hash
const std::string &account_username,
const std::string &source_loginserver,
const std::string &account_password,
const std::string &password_hash
);
void DoSuccessfulLogin(const std::string in_account_name, int db_account_id, const std::string &db_loginserver);

View File

@ -330,7 +330,7 @@ bool Database::DoesLoginServerAccountExist(
* @param loginserver
* @param hash
*/
void Database::UpdateLoginHash(
void Database::UpdateLoginserverAccountPasswordHash(
const std::string &name,
const std::string &loginserver,
const std::string &hash

View File

@ -121,7 +121,10 @@ public:
* @param loginserver
* @param hash
*/
void UpdateLoginHash(const std::string &name, const std::string &loginserver, const std::string &hash);
void UpdateLoginserverAccountPasswordHash(
const std::string &name,
const std::string &loginserver,
const std::string &hash);
/**
* @param name

View File

@ -50,11 +50,12 @@ namespace LoginserverCommandHandler {
/**
* Register commands
*/
function_map["login-user:create"] = &LoginserverCommandHandler::CreateLocalLoginserverAccount;
function_map["login-user:check-credentials"] = &LoginserverCommandHandler::CheckLoginserverUserCredentials;
function_map["web-api-token:create"] = &LoginserverCommandHandler::CreateLoginserverApiToken;
function_map["web-api-token:list"] = &LoginserverCommandHandler::ListLoginserverApiTokens;
function_map["world-admin:create"] = &LoginserverCommandHandler::CreateLoginserverWorldAdminAccount;
function_map["login-user:check-credentials"] = &LoginserverCommandHandler::CheckLoginserverUserCredentials;
function_map["login-user:create"] = &LoginserverCommandHandler::CreateLocalLoginserverAccount;
function_map["login-user:update-credentials"] = &LoginserverCommandHandler::UpdateLoginserverUserCredentials;
function_map["web-api-token:create"] = &LoginserverCommandHandler::CreateLoginserverApiToken;
function_map["web-api-token:list"] = &LoginserverCommandHandler::ListLoginserverApiTokens;
function_map["world-admin:create"] = &LoginserverCommandHandler::CreateLoginserverWorldAdminAccount;
EQEmuCommand::HandleMenu(function_map, cmd, argc, argv);
}
@ -207,4 +208,31 @@ namespace LoginserverCommandHandler {
cmd("--password").str()
);
}
/**
* @param argc
* @param argv
* @param cmd
* @param description
void UpdateLoginserverUserCredentials(int argc, char **argv, argh::parser &cmd, std::string &description)
{
description = "Change user login credentials";
std::vector<std::string> arguments = {
"--username",
"--password"
};
std::vector<std::string> options = {};
if (cmd[{"-h", "--help"}]) {
return;
}
EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv);
AccountManagement::UpdateLoginserverUserCredentials(
cmd("--username").str(),
cmd("--password").str()
);
}
}

View File

@ -31,6 +31,7 @@ namespace LoginserverCommandHandler {
void CreateLocalLoginserverAccount(int argc, char **argv, argh::parser &cmd, std::string &description);
void CreateLoginserverWorldAdminAccount(int argc, char **argv, argh::parser &cmd, std::string &description);
void CheckLoginserverUserCredentials(int argc, char **argv, argh::parser &cmd, std::string &description);
void UpdateLoginserverUserCredentials(int argc, char **argv, argh::parser &cmd, std::string &description);
};

View File

@ -94,7 +94,6 @@ namespace LoginserverWebserver {
Json::Value request_body = LoginserverWebserver::ParseRequestBody(request);
std::string username = request_body.get("username", "").asString();
std::string password = request_body.get("password", "").asString();
std::string email = request_body.get("email", "").asString();
Json::Value response;
if (username.empty() || password.empty()) {
@ -118,6 +117,47 @@ namespace LoginserverWebserver {
LoginserverWebserver::SendResponse(response, res);
}
);
api.Post(
"/account/credentials/update/local", [](const httplib::Request &request, httplib::Response &res) {
LoginserverWebserver::TokenManager::AuthCanWrite(request, res);
Json::Value request_body = LoginserverWebserver::ParseRequestBody(request);
std::string username = request_body.get("username", "").asString();
std::string password = request_body.get("password", "").asString();
Json::Value response;
if (username.empty() || password.empty()) {
response["message"] = "Username or password not set";
LoginserverWebserver::SendResponse(response, res);
return;
}
Database::DbLoginServerAccount
login_server_account = server.db->GetLoginServerAccountByAccountName(
username
);
if (!login_server_account.loaded) {
response["error"] = "Failed to find associated loginserver account!";
LoginserverWebserver::SendResponse(response, res);
return;
}
bool credentials_valid = AccountManagement::UpdateLoginserverUserCredentials(
username,
password
);
if (credentials_valid) {
response["message"] = "Loginserver account credentials updated!";
}
else {
response["error"] = "Failed to update loginserver account credentials!";
}
LoginserverWebserver::SendResponse(response, res);
}
);
}
/**

View File

@ -43,7 +43,7 @@ void CatchSignal(int sig_num)
{
}
int main(int argc, char** argv)
int main(int argc, char **argv)
{
RegisterExecutablePlatform(ExePlatformLogin);
set_exception_handler();
@ -68,7 +68,12 @@ int main(int argc, char** argv)
/**
* options: worldservers
*/
server.options.RejectDuplicateServers(server.config.GetVariableBool("worldservers", "reject_duplicate_servers", false));
server.options.RejectDuplicateServers(
server.config.GetVariableBool(
"worldservers",
"reject_duplicate_servers",
false
));
server.options.AllowUnregistered(server.config.GetVariableBool("worldservers", "unregistered_allowed", true));
/**
@ -154,7 +159,7 @@ int main(int argc, char** argv)
* create client manager
*/
LogInfo("Client Manager Init");
server.client_manager = new ClientManager();
server.client_manager = new ClientManager();
if (!server.client_manager) {
LogError("Client Manager Failed to Start");
LogInfo("Server Manager Shutdown");
@ -192,6 +197,9 @@ int main(int argc, char** argv)
if (argc > 1) {
LogSys.LoadLogSettingsDefaults();
LogSys.log_settings[Logs::Debug].log_to_console = static_cast<uint8>(Logs::General);
LogSys.log_settings[Logs::Debug].is_category_enabled = 1;
LoginserverCommandHandler::CommandHandler(argc, argv);
}