Add local credential validation logic

This commit is contained in:
Akkadius 2019-08-04 04:16:14 -05:00
parent 5ff0f4851e
commit b0d33f094d
8 changed files with 189 additions and 9 deletions

View File

@ -143,6 +143,7 @@ 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
@ -470,7 +471,7 @@ void EQEmuLogSys::Out(
prefix = fmt::format("[{0}::{1}:{2}] ", base_file_name(file), func, line);
}
auto msg_cstr = message.c_str();
auto msg_cstr = message.c_str();
va_list args;
va_start(args, msg_cstr);
std::string output_message = vStringFormat(msg_cstr, args);

View File

@ -134,3 +134,58 @@ bool AccountManagement::CreateLoginserverWorldAdminAccount(
return false;
}
/**
* @param in_account_username
* @param in_account_password
* @return
*/
bool AccountManagement::CheckLoginserverUserCredentials(
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_admin = server.db->GetLoginServerAccountByAccountName(
in_account_username,
source_loginserver
);
if (!login_server_admin.loaded) {
LogError(
"CheckLoginUserCredentials account [{0}] source_loginserver [{1}] not found!",
in_account_username,
source_loginserver
);
return false;
}
bool validated_credentials = eqcrypt_verify_hash(
in_account_username,
in_account_password,
login_server_admin.account_password,
mode
);
if (!validated_credentials) {
LogError(
"CheckLoginUserCredentials account [{0}] source_loginserver [{1}] invalid credentials!",
in_account_username,
source_loginserver
);
return false;
}
LogDebug(
"CheckLoginUserCredentials account [{0}] source_loginserver [{1}] credentials validated success!",
in_account_username,
source_loginserver
);
return validated_credentials;
}

View File

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

View File

@ -730,3 +730,40 @@ Database::DbLoginServerAdmin Database::GetLoginServerAdmin(const std::string &ac
return login_server_admin;
}
/**
* @param account_name
* @return
*/
Database::DbLoginServerAccount Database::GetLoginServerAccountByAccountName(
const std::string &account_name,
const std::string &source_loginserver
)
{
auto query = fmt::format(
"SELECT id, account_name, account_password, account_email, source_loginserver, last_ip_address, last_login_date, "
"created_at, updated_at"
" FROM login_accounts WHERE account_name = '{0}' and source_loginserver = '{1}' LIMIT 1",
EscapeString(account_name),
EscapeString(source_loginserver)
);
auto results = QueryDatabase(query);
Database::DbLoginServerAccount login_server_account{};
if (results.RowCount() == 1) {
auto row = results.begin();
login_server_account.loaded = true;
login_server_account.id = std::stoi(row[0]);
login_server_account.account_name = row[1];
login_server_account.account_password = row[2];
login_server_account.account_email = row[3];
login_server_account.source_loginserver = row[4];
login_server_account.last_ip_address = row[5];
login_server_account.last_login_date = row[6];
login_server_account.created_at = row[7];
login_server_account.updated_at = row[8];
}
return login_server_account;
}

View File

@ -248,6 +248,24 @@ public:
Database::DbLoginServerAdmin GetLoginServerAdmin(const std::string &account_name);
struct DbLoginServerAccount {
bool loaded = false;
uint32 id;
std::string account_name;
std::string account_password;
std::string account_email;
std::string source_loginserver;
std::string last_login_date;
std::string last_ip_address;
std::string created_at;
std::string updated_at;
};
Database::DbLoginServerAccount GetLoginServerAccountByAccountName(
const std::string &account_name,
const std::string &source_loginserver = "local"
);
/**
* @param name
* @param password

View File

@ -50,10 +50,11 @@ namespace LoginserverCommandHandler {
/**
* Register commands
*/
function_map["login-user:create"] = &LoginserverCommandHandler::CreateLocalLoginserverAccount;
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: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;
EQEmuCommand::HandleMenu(function_map, cmd, argc, argv);
}
@ -179,4 +180,31 @@ namespace LoginserverCommandHandler {
);
}
/**
* @param argc
* @param argv
* @param cmd
* @param description
*/
void CheckLoginserverUserCredentials(int argc, char **argv, argh::parser &cmd, std::string &description)
{
description = "Check 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::CheckLoginserverUserCredentials(
cmd("--username").str(),
cmd("--password").str()
);
}
}

View File

@ -30,6 +30,7 @@ namespace LoginserverCommandHandler {
void ListLoginserverApiTokens(int argc, char **argv, argh::parser &cmd, std::string &description);
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);
};

View File

@ -87,6 +87,37 @@ namespace LoginserverWebserver {
LoginserverWebserver::SendResponse(response, res);
}
);
api.Post(
"/account/credentials/validate/local", [](const httplib::Request &request, httplib::Response &res) {
LoginserverWebserver::TokenManager::AuthCanRead(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();
std::string email = request_body.get("email", "").asString();
Json::Value response;
if (username.empty() || password.empty()) {
response["message"] = "Username or password not set";
LoginserverWebserver::SendResponse(response, res);
return;
}
bool credentials_valid = AccountManagement::CheckLoginserverUserCredentials(
username,
password
);
if (credentials_valid) {
response["message"] = "Credentials valid!";
}
else {
response["error"] = "Credentials invalid!";
}
LoginserverWebserver::SendResponse(response, res);
}
);
}
/**
@ -146,8 +177,7 @@ namespace LoginserverWebserver {
res.set_header("response_set", "true");
LogWarning(
"AuthCanRead access failure | token [{0}] remote_address [{1}] user_agent [{2}]",
user_token.token,
"AuthCanRead access failure remote_address [{0}] user_agent [{1}]",
user_token.remote_address,
user_token.user_agent
);
@ -174,8 +204,7 @@ namespace LoginserverWebserver {
res.set_header("response_set", "true");
LogWarning(
"AuthCanWrite access failure | token [{0}] remote_address [{1}] user_agent [{2}]",
user_token.token,
"AuthCanWrite access failure remote_address [{0}] user_agent [{1}]",
user_token.remote_address,
user_token.user_agent
);