mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 10:31:29 +00:00
[Loginserver] Modernize codebase (#4647)
* Beginning of cleanup * More cleanup * More cleanup * Enc cleanup * client manager cleanup * client cleanup * More cleanup * More cleanup * Cleanup * More cleanup, account context, account management * Remove positional fmt bindings * Use LoginAccountContext * Update loginserver_webserver.cpp * Remove comments * Port CreateLoginServerAccount to repositories * More cleanup * More cleanup * More cleanup * More cleanup * Remove a ton of functions * More cleanup * More cleanup * More cleanup * Cleanup SendClientAuthToWorld * Consolidate world server logic * Update login_accounts_repository.h * Update login_accounts_repository.h * Move api tokens to repositories * Cleanup options * Move everything else to repositories * Update account_management.cpp * uint64 account * Update login_schema.sql * Fix * Update world_server.cpp * auto
This commit is contained in:
parent
1650efa787
commit
1a48add20e
@ -123,7 +123,7 @@ void EQ::Net::ServertalkServerConnection::ProcessReadBuffer()
|
|||||||
{
|
{
|
||||||
size_t current = 0;
|
size_t current = 0;
|
||||||
size_t total = m_buffer.size();
|
size_t total = m_buffer.size();
|
||||||
constexpr size_t ls_info_size = sizeof(ServerNewLSInfo_Struct);
|
constexpr size_t ls_info_size = sizeof(LoginserverNewWorldRequest);
|
||||||
|
|
||||||
while (current < total) {
|
while (current < total) {
|
||||||
auto left = total - current;
|
auto left = total - current;
|
||||||
@ -138,7 +138,7 @@ void EQ::Net::ServertalkServerConnection::ProcessReadBuffer()
|
|||||||
//this creates a small edge case where the exact size of a
|
//this creates a small edge case where the exact size of a
|
||||||
//packet from the modern protocol can't be "43061256"
|
//packet from the modern protocol can't be "43061256"
|
||||||
//so in send we pad it one byte if that's the case
|
//so in send we pad it one byte if that's the case
|
||||||
if (leg_opcode == ServerOP_NewLSInfo && leg_size == sizeof(ServerNewLSInfo_Struct)) {
|
if (leg_opcode == ServerOP_NewLSInfo && leg_size == sizeof(LoginserverNewWorldRequest)) {
|
||||||
m_legacy_mode = true;
|
m_legacy_mode = true;
|
||||||
m_identifier = "World";
|
m_identifier = "World";
|
||||||
m_parent->ConnectionIdentified(this);
|
m_parent->ConnectionIdentified(this);
|
||||||
|
|||||||
@ -4,47 +4,94 @@
|
|||||||
#include "../database.h"
|
#include "../database.h"
|
||||||
#include "../strings.h"
|
#include "../strings.h"
|
||||||
#include "base/base_login_accounts_repository.h"
|
#include "base/base_login_accounts_repository.h"
|
||||||
|
#include "../../loginserver/encryption.h"
|
||||||
|
#include "../../loginserver/login_types.h"
|
||||||
|
|
||||||
class LoginAccountsRepository: public BaseLoginAccountsRepository {
|
class LoginAccountsRepository : public BaseLoginAccountsRepository {
|
||||||
public:
|
public:
|
||||||
|
static int64 GetFreeID(Database &db, const std::string &loginserver)
|
||||||
|
{
|
||||||
|
auto query = fmt::format(
|
||||||
|
"SELECT IFNULL(MAX(id), 0) + 1 FROM login_accounts WHERE source_loginserver = '{}'",
|
||||||
|
Strings::Escape(loginserver)
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
auto results = db.QueryDatabase(query);
|
||||||
* This file was auto generated and can be modified and extended upon
|
if (!results.Success() || results.RowCount() != 1) {
|
||||||
*
|
return 0;
|
||||||
* Base repository methods are automatically
|
}
|
||||||
* generated in the "base" version of this repository. The base repository
|
|
||||||
* is immutable and to be left untouched, while methods in this class
|
|
||||||
* are used as extension methods for more specific persistence-layer
|
|
||||||
* accessors or mutators.
|
|
||||||
*
|
|
||||||
* Base Methods (Subject to be expanded upon in time)
|
|
||||||
*
|
|
||||||
* Note: Not all tables are designed appropriately to fit functionality with all base methods
|
|
||||||
*
|
|
||||||
* InsertOne
|
|
||||||
* UpdateOne
|
|
||||||
* DeleteOne
|
|
||||||
* FindOne
|
|
||||||
* GetWhere(std::string where_filter)
|
|
||||||
* DeleteWhere(std::string where_filter)
|
|
||||||
* InsertMany
|
|
||||||
* All
|
|
||||||
*
|
|
||||||
* Example custom methods in a repository
|
|
||||||
*
|
|
||||||
* LoginAccountsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
|
||||||
* LoginAccountsRepository::GetWhereNeverExpires()
|
|
||||||
* LoginAccountsRepository::GetWhereXAndY()
|
|
||||||
* LoginAccountsRepository::DeleteWhereXAndY()
|
|
||||||
*
|
|
||||||
* Most of the above could be covered by base methods, but if you as a developer
|
|
||||||
* find yourself re-using logic for other parts of the code, its best to just make a
|
|
||||||
* method that can be re-used easily elsewhere especially if it can use a base repository
|
|
||||||
* method and encapsulate filters there
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Custom extended repository methods here
|
auto row = results.begin();
|
||||||
|
|
||||||
|
return Strings::ToUnsignedInt(row[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static LoginAccountsRepository::LoginAccounts CreateAccountFromContext(
|
||||||
|
Database &db,
|
||||||
|
LoginAccountContext c
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto a = LoginAccountsRepository::NewEntity();
|
||||||
|
|
||||||
|
if (!c.password_is_encrypted) {
|
||||||
|
auto e = EncryptPasswordFromContext(c);
|
||||||
|
a.account_password = e.password;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.id = c.login_account_id > 0 ? c.login_account_id : GetFreeID(db, c.source_loginserver);
|
||||||
|
a.account_name = c.username;
|
||||||
|
a.account_email = !c.email.empty() ? c.email : "local_creation";
|
||||||
|
a.source_loginserver = c.source_loginserver;
|
||||||
|
a.last_ip_address = "127.0.0.1";
|
||||||
|
a.last_login_date = std::time(nullptr);
|
||||||
|
a.created_at = std::time(nullptr);
|
||||||
|
LoginAccountsRepository::InsertOne(db, a);
|
||||||
|
|
||||||
|
return GetAccountFromContext(db, c).id > 0 ? a : NewEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
static LoginAccountsRepository::LoginAccounts GetAccountFromContext(
|
||||||
|
Database &db,
|
||||||
|
LoginAccountContext c
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::string where = fmt::format(
|
||||||
|
"account_name = '{}' AND source_loginserver = '{}'",
|
||||||
|
Strings::Escape(c.username),
|
||||||
|
Strings::Escape(c.source_loginserver)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!c.email.empty()) {
|
||||||
|
where += fmt::format(" AND account_email = '{}'", Strings::Escape(c.email));
|
||||||
|
}
|
||||||
|
if (c.login_account_id > 0) {
|
||||||
|
where += fmt::format(" AND id = {}", c.login_account_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
where += " LIMIT 1";
|
||||||
|
|
||||||
|
auto results = LoginAccountsRepository::GetWhere(db, where);
|
||||||
|
|
||||||
|
auto e = LoginAccountsRepository::NewEntity();
|
||||||
|
if (results.size() == 1) {
|
||||||
|
e = results.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LoginAccounts UpdateAccountPassword(Database &db, LoginAccounts a, std::string password)
|
||||||
|
{
|
||||||
|
LoginAccountContext c;
|
||||||
|
c.username = a.account_name;
|
||||||
|
c.password = password;
|
||||||
|
auto e = EncryptPasswordFromContext(c);
|
||||||
|
a.account_password = e.password;
|
||||||
|
|
||||||
|
int success = LoginAccountsRepository::UpdateOne(db, a);
|
||||||
|
|
||||||
|
return success ? a : NewEntity();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_LOGIN_ACCOUNTS_REPOSITORY_H
|
#endif //EQEMU_LOGIN_ACCOUNTS_REPOSITORY_H
|
||||||
|
|||||||
@ -5,46 +5,24 @@
|
|||||||
#include "../strings.h"
|
#include "../strings.h"
|
||||||
#include "base/base_login_server_admins_repository.h"
|
#include "base/base_login_server_admins_repository.h"
|
||||||
|
|
||||||
class LoginServerAdminsRepository: public BaseLoginServerAdminsRepository {
|
class LoginServerAdminsRepository : public BaseLoginServerAdminsRepository {
|
||||||
public:
|
public:
|
||||||
|
static LoginServerAdmins GetByName(Database &db, std::string account_name)
|
||||||
|
{
|
||||||
|
auto admins = GetWhere(
|
||||||
|
db,
|
||||||
|
fmt::format(
|
||||||
|
"account_name = '{}' LIMIT 1",
|
||||||
|
Strings::Escape(account_name)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
if (admins.size() == 1) {
|
||||||
* This file was auto generated and can be modified and extended upon
|
return admins.front();
|
||||||
*
|
}
|
||||||
* Base repository methods are automatically
|
|
||||||
* generated in the "base" version of this repository. The base repository
|
|
||||||
* is immutable and to be left untouched, while methods in this class
|
|
||||||
* are used as extension methods for more specific persistence-layer
|
|
||||||
* accessors or mutators.
|
|
||||||
*
|
|
||||||
* Base Methods (Subject to be expanded upon in time)
|
|
||||||
*
|
|
||||||
* Note: Not all tables are designed appropriately to fit functionality with all base methods
|
|
||||||
*
|
|
||||||
* InsertOne
|
|
||||||
* UpdateOne
|
|
||||||
* DeleteOne
|
|
||||||
* FindOne
|
|
||||||
* GetWhere(std::string where_filter)
|
|
||||||
* DeleteWhere(std::string where_filter)
|
|
||||||
* InsertMany
|
|
||||||
* All
|
|
||||||
*
|
|
||||||
* Example custom methods in a repository
|
|
||||||
*
|
|
||||||
* LoginServerAdminsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
|
||||||
* LoginServerAdminsRepository::GetWhereNeverExpires()
|
|
||||||
* LoginServerAdminsRepository::GetWhereXAndY()
|
|
||||||
* LoginServerAdminsRepository::DeleteWhereXAndY()
|
|
||||||
*
|
|
||||||
* Most of the above could be covered by base methods, but if you as a developer
|
|
||||||
* find yourself re-using logic for other parts of the code, its best to just make a
|
|
||||||
* method that can be re-used easily elsewhere especially if it can use a base repository
|
|
||||||
* method and encapsulate filters there
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Custom extended repository methods here
|
|
||||||
|
|
||||||
|
return NewEntity();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_LOGIN_SERVER_ADMINS_REPOSITORY_H
|
#endif //EQEMU_LOGIN_SERVER_ADMINS_REPOSITORY_H
|
||||||
|
|||||||
@ -7,44 +7,27 @@
|
|||||||
|
|
||||||
class LoginWorldServersRepository: public BaseLoginWorldServersRepository {
|
class LoginWorldServersRepository: public BaseLoginWorldServersRepository {
|
||||||
public:
|
public:
|
||||||
|
static LoginWorldServers GetFromWorldContext(Database &db, LoginWorldContext c) {
|
||||||
|
std::string where = fmt::format(
|
||||||
|
"short_name = '{}' AND long_name = '{}'",
|
||||||
|
Strings::Escape(c.short_name),
|
||||||
|
Strings::Escape(c.long_name)
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
if (c.admin_id > 0) {
|
||||||
* This file was auto generated and can be modified and extended upon
|
where += fmt::format(" AND login_server_admin_id = {}", c.admin_id);
|
||||||
*
|
}
|
||||||
* Base repository methods are automatically
|
|
||||||
* generated in the "base" version of this repository. The base repository
|
|
||||||
* is immutable and to be left untouched, while methods in this class
|
|
||||||
* are used as extension methods for more specific persistence-layer
|
|
||||||
* accessors or mutators.
|
|
||||||
*
|
|
||||||
* Base Methods (Subject to be expanded upon in time)
|
|
||||||
*
|
|
||||||
* Note: Not all tables are designed appropriately to fit functionality with all base methods
|
|
||||||
*
|
|
||||||
* InsertOne
|
|
||||||
* UpdateOne
|
|
||||||
* DeleteOne
|
|
||||||
* FindOne
|
|
||||||
* GetWhere(std::string where_filter)
|
|
||||||
* DeleteWhere(std::string where_filter)
|
|
||||||
* InsertMany
|
|
||||||
* All
|
|
||||||
*
|
|
||||||
* Example custom methods in a repository
|
|
||||||
*
|
|
||||||
* LoginWorldServersRepository::GetByZoneAndVersion(int zone_id, int zone_version)
|
|
||||||
* LoginWorldServersRepository::GetWhereNeverExpires()
|
|
||||||
* LoginWorldServersRepository::GetWhereXAndY()
|
|
||||||
* LoginWorldServersRepository::DeleteWhereXAndY()
|
|
||||||
*
|
|
||||||
* Most of the above could be covered by base methods, but if you as a developer
|
|
||||||
* find yourself re-using logic for other parts of the code, its best to just make a
|
|
||||||
* method that can be re-used easily elsewhere especially if it can use a base repository
|
|
||||||
* method and encapsulate filters there
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Custom extended repository methods here
|
where += " LIMIT 1";
|
||||||
|
|
||||||
|
auto results = GetWhere(db, where);
|
||||||
|
auto e = NewEntity();
|
||||||
|
if (results.size() == 1) {
|
||||||
|
e = results.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //EQEMU_LOGIN_WORLD_SERVERS_REPOSITORY_H
|
#endif //EQEMU_LOGIN_WORLD_SERVERS_REPOSITORY_H
|
||||||
|
|||||||
@ -646,7 +646,7 @@ struct ServerLSInfo_Struct {
|
|||||||
uint8 servertype; // 0=world, 1=chat, 2=login, 3=MeshLogin
|
uint8 servertype; // 0=world, 1=chat, 2=login, 3=MeshLogin
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ServerNewLSInfo_Struct {
|
struct LoginserverNewWorldRequest {
|
||||||
char server_long_name[201]; // name the worldserver wants
|
char server_long_name[201]; // name the worldserver wants
|
||||||
char server_short_name[50]; // shortname the worldserver wants
|
char server_short_name[50]; // shortname the worldserver wants
|
||||||
char remote_ip_address[125]; // DNS address of the server
|
char remote_ip_address[125]; // DNS address of the server
|
||||||
@ -658,21 +658,21 @@ struct ServerNewLSInfo_Struct {
|
|||||||
uint8 server_process_type; // 0=world, 1=chat, 2=login, 3=MeshLogin
|
uint8 server_process_type; // 0=world, 1=chat, 2=login, 3=MeshLogin
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ServerLSAccountUpdate_Struct { // for updating info on login server
|
struct LoginserverAccountUpdate { // for updating info on login server
|
||||||
char worldaccount[31]; // account name for the worldserver
|
char world_account[31]; // account name for the worldserver
|
||||||
char worldpassword[31]; // password for the name
|
char world_password[31]; // password for the name
|
||||||
uint32 useraccountid; // player account ID
|
uint32 user_account_id; // player account ID
|
||||||
char useraccount[31]; // player account name
|
char user_account_name[31]; // player account name
|
||||||
char userpassword[51]; // player account password
|
char user_account_password[51]; // player account password
|
||||||
char user_email[101]; // player account email address
|
char user_email[101]; // player account email address
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ServerLSStatus_Struct {
|
struct LoginserverWorldStatusUpdate {
|
||||||
int32 status;
|
int32 status;
|
||||||
int32 num_players;
|
int32 num_players;
|
||||||
int32 num_zones;
|
int32 num_zones;
|
||||||
};
|
};
|
||||||
struct ZoneInfo_Struct {
|
struct LoginserverZoneInfoUpdate {
|
||||||
uint32 zone;
|
uint32 zone;
|
||||||
uint16 count;
|
uint16 count;
|
||||||
uint32 zone_wid;
|
uint32 zone_wid;
|
||||||
|
|||||||
@ -4,12 +4,11 @@ SET(eqlogin_sources
|
|||||||
account_management.cpp
|
account_management.cpp
|
||||||
client.cpp
|
client.cpp
|
||||||
client_manager.cpp
|
client_manager.cpp
|
||||||
database.cpp
|
|
||||||
encryption.cpp
|
encryption.cpp
|
||||||
loginserver_command_handler.cpp
|
loginserver_command_handler.cpp
|
||||||
loginserver_webserver.cpp
|
loginserver_webserver.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
server_manager.cpp
|
world_server_manager.cpp
|
||||||
world_server.cpp
|
world_server.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,14 +16,13 @@ SET(eqlogin_headers
|
|||||||
account_management.h
|
account_management.h
|
||||||
client.h
|
client.h
|
||||||
client_manager.h
|
client_manager.h
|
||||||
database.h
|
|
||||||
encryption.h
|
encryption.h
|
||||||
loginserver_command_handler.h
|
loginserver_command_handler.h
|
||||||
loginserver_webserver.h
|
loginserver_webserver.h
|
||||||
login_server.h
|
login_server.h
|
||||||
login_types.h
|
login_types.h
|
||||||
options.h
|
options.h
|
||||||
server_manager.h
|
world_server_manager.h
|
||||||
world_server.h
|
world_server.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -1,259 +1,114 @@
|
|||||||
#include "account_management.h"
|
#include "account_management.h"
|
||||||
#include "login_server.h"
|
#include "login_server.h"
|
||||||
#include "../common/event/task_scheduler.h"
|
#include "../common/event/task_scheduler.h"
|
||||||
#include "../common/event/event_loop.h"
|
#include "../common/repositories/login_accounts_repository.h"
|
||||||
#include "../common/net/dns.h"
|
|
||||||
#include "../common/strings.h"
|
|
||||||
|
|
||||||
extern LoginServer server;
|
|
||||||
EQ::Event::TaskScheduler task_runner;
|
EQ::Event::TaskScheduler task_runner;
|
||||||
|
|
||||||
/**
|
uint64 AccountManagement::CreateLoginServerAccount(LoginAccountContext c)
|
||||||
* @param username
|
|
||||||
* @param password
|
|
||||||
* @param email
|
|
||||||
* @param source_loginserver
|
|
||||||
* @param login_account_id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
int32 AccountManagement::CreateLoginServerAccount(
|
|
||||||
std::string username,
|
|
||||||
std::string password,
|
|
||||||
std::string email,
|
|
||||||
const std::string &source_loginserver,
|
|
||||||
uint32 login_account_id
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
auto mode = server.options.GetEncryptionMode();
|
if (LoginAccountsRepository::GetAccountFromContext(database, c).id > 0) {
|
||||||
auto hash = eqcrypt_hash(username, password, mode);
|
|
||||||
|
|
||||||
LogInfo(
|
|
||||||
"Attempting to create local login account for user [{0}] encryption algorithm [{1}] ({2})",
|
|
||||||
username,
|
|
||||||
GetEncryptionByModeId(mode),
|
|
||||||
mode
|
|
||||||
);
|
|
||||||
|
|
||||||
unsigned int db_id = 0;
|
|
||||||
if (server.db->DoesLoginServerAccountExist(username, hash, source_loginserver, 1)) {
|
|
||||||
LogWarning(
|
LogWarning(
|
||||||
"Attempting to create local login account for user [{0}] login [{1}] but already exists!",
|
"Attempting to create local login account for user [{}] but already exists!",
|
||||||
username,
|
c.username
|
||||||
source_loginserver
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 created_account_id = 0;
|
auto a = LoginAccountsRepository::CreateAccountFromContext(database, c);
|
||||||
if (login_account_id > 0) {
|
if (a.id > 0) {
|
||||||
created_account_id = server.db->CreateLoginDataWithID(username, hash, source_loginserver, login_account_id);
|
return (int64) a.id;
|
||||||
}
|
|
||||||
else {
|
|
||||||
created_account_id = server.db->CreateLoginAccount(username, hash, source_loginserver, email);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (created_account_id > 0) {
|
LogError("Failed to create local login account for user [{}] !", c.username);
|
||||||
LogInfo(
|
|
||||||
"Account creation success for user [{0}] encryption algorithm [{1}] ({2}) id: [{3}]",
|
|
||||||
username,
|
|
||||||
GetEncryptionByModeId(mode),
|
|
||||||
mode,
|
|
||||||
created_account_id
|
|
||||||
);
|
|
||||||
|
|
||||||
return (int32) created_account_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
LogError("Failed to create local login account for user [{0}]!", username);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
uint64 AccountManagement::CheckLoginserverUserCredentials(LoginAccountContext c)
|
||||||
* @param username
|
|
||||||
* @param password
|
|
||||||
* @param email
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool AccountManagement::CreateLoginserverWorldAdminAccount(
|
|
||||||
const std::string &username,
|
|
||||||
const std::string &password,
|
|
||||||
const std::string &email,
|
|
||||||
const std::string &first_name,
|
|
||||||
const std::string &last_name,
|
|
||||||
const std::string &ip_address
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
auto mode = server.options.GetEncryptionMode();
|
auto mode = server.options.GetEncryptionMode();
|
||||||
auto hash = eqcrypt_hash(username, password, mode);
|
auto a = LoginAccountsRepository::GetAccountFromContext(database, c);
|
||||||
|
if (!a.id) {
|
||||||
LogInfo(
|
|
||||||
"Attempting to create world admin account | username [{0}] encryption algorithm [{1}] ({2})",
|
|
||||||
username,
|
|
||||||
GetEncryptionByModeId(mode),
|
|
||||||
mode
|
|
||||||
);
|
|
||||||
|
|
||||||
if (server.db->DoesLoginserverWorldAdminAccountExist(username)) {
|
|
||||||
LogWarning(
|
|
||||||
"Attempting to create world admin account for user [{0}] but already exists!",
|
|
||||||
username
|
|
||||||
);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 created_world_admin_id = server.db->CreateLoginserverWorldAdminAccount(
|
|
||||||
username,
|
|
||||||
hash,
|
|
||||||
first_name,
|
|
||||||
last_name,
|
|
||||||
email,
|
|
||||||
ip_address
|
|
||||||
);
|
|
||||||
|
|
||||||
if (created_world_admin_id > 0) {
|
|
||||||
LogInfo(
|
|
||||||
"Account creation success for user [{0}] encryption algorithm [{1}] ({2}) new admin id [{3}]",
|
|
||||||
username,
|
|
||||||
GetEncryptionByModeId(mode),
|
|
||||||
mode,
|
|
||||||
created_world_admin_id
|
|
||||||
);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
LogError("Failed to create world admin account account for user [{0}]!", username);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param in_account_username
|
|
||||||
* @param in_account_password
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
uint32 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(
|
LogError(
|
||||||
"account [{0}] source_loginserver [{1}] not found!",
|
"account [{}] source_loginserver [{}] not found!",
|
||||||
in_account_username,
|
c.username,
|
||||||
source_loginserver
|
c.source_loginserver
|
||||||
);
|
);
|
||||||
|
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool validated_credentials = eqcrypt_verify_hash(
|
bool validated_credentials = eqcrypt_verify_hash(c.username, c.password, a.account_password, mode);
|
||||||
in_account_username,
|
|
||||||
in_account_password,
|
|
||||||
login_server_admin.account_password,
|
|
||||||
mode
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!validated_credentials) {
|
if (!validated_credentials) {
|
||||||
LogError(
|
LogError(
|
||||||
"account [{0}] source_loginserver [{1}] invalid credentials!",
|
"account [{}] source_loginserver [{}] invalid credentials!",
|
||||||
in_account_username,
|
c.username,
|
||||||
source_loginserver
|
c.source_loginserver
|
||||||
);
|
);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogInfo(
|
LogInfo(
|
||||||
"account [{0}] source_loginserver [{1}] credentials validated success!",
|
"account [{}] source_loginserver [{}] credentials validated success!",
|
||||||
in_account_username,
|
c.username,
|
||||||
source_loginserver
|
c.source_loginserver
|
||||||
);
|
);
|
||||||
|
|
||||||
return login_server_admin.id;
|
return a.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AccountManagement::UpdateLoginserverUserCredentials(LoginAccountContext c)
|
||||||
/**
|
|
||||||
* @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();
|
auto a = LoginAccountsRepository::GetAccountFromContext(database, c);
|
||||||
|
if (!a.id) {
|
||||||
Database::DbLoginServerAccount
|
|
||||||
login_server_account = server.db->GetLoginServerAccountByAccountName(
|
|
||||||
in_account_username,
|
|
||||||
source_loginserver
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!login_server_account.loaded) {
|
|
||||||
LogError(
|
LogError(
|
||||||
"account [{0}] source_loginserver [{1}] not found!",
|
"account [{}] source_loginserver [{}] not found!",
|
||||||
in_account_username,
|
c.username,
|
||||||
source_loginserver
|
c.source_loginserver
|
||||||
);
|
);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
server.db->UpdateLoginserverAccountPasswordHash(
|
LoginAccountsRepository::UpdateAccountPassword(database, a, c.password);
|
||||||
in_account_username,
|
|
||||||
source_loginserver,
|
|
||||||
eqcrypt_hash(
|
|
||||||
in_account_username,
|
|
||||||
in_account_password,
|
|
||||||
mode
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
LogInfo(
|
LogInfo(
|
||||||
"account [{0}] source_loginserver [{1}] credentials updated!",
|
"account [{}] source_loginserver [{}] credentials updated!",
|
||||||
in_account_username,
|
c.username,
|
||||||
source_loginserver
|
c.source_loginserver
|
||||||
);
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
bool AccountManagement::UpdateLoginserverWorldAdminAccountPasswordByName(LoginAccountContext c)
|
||||||
* @param in_account_username
|
|
||||||
* @param in_account_password
|
|
||||||
*/
|
|
||||||
bool AccountManagement::UpdateLoginserverWorldAdminAccountPasswordByName(
|
|
||||||
const std::string &in_account_username,
|
|
||||||
const std::string &in_account_password
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
auto mode = server.options.GetEncryptionMode();
|
auto mode = server.options.GetEncryptionMode();
|
||||||
auto hash = eqcrypt_hash(in_account_username, in_account_password, mode);
|
auto hash = eqcrypt_hash(
|
||||||
|
c.username,
|
||||||
bool updated_account = server.db->UpdateLoginWorldAdminAccountPasswordByUsername(
|
c.password,
|
||||||
in_account_username,
|
mode
|
||||||
hash
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
auto a = LoginServerAdminsRepository::GetByName(database, c.username);
|
||||||
|
if (!a.id) {
|
||||||
|
LogError(
|
||||||
|
"account_name [{}] not found!",
|
||||||
|
c.username
|
||||||
|
);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.account_password = hash;
|
||||||
|
auto updated_account = LoginServerAdminsRepository::UpdateOne(database, a);
|
||||||
|
|
||||||
LogInfo(
|
LogInfo(
|
||||||
"[{}] account_name [{}] status [{}]",
|
"account_name [{}] status [{}]",
|
||||||
__func__,
|
c.username,
|
||||||
in_account_username,
|
|
||||||
(updated_account ? "success" : "failed")
|
(updated_account ? "success" : "failed")
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -262,15 +117,7 @@ bool AccountManagement::UpdateLoginserverWorldAdminAccountPasswordByName(
|
|||||||
|
|
||||||
constexpr int REQUEST_TIMEOUT_MS = 1500;
|
constexpr int REQUEST_TIMEOUT_MS = 1500;
|
||||||
|
|
||||||
/**
|
uint64 AccountManagement::CheckExternalLoginserverUserCredentials(LoginAccountContext c)
|
||||||
* @param in_account_username
|
|
||||||
* @param in_account_password
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
uint32 AccountManagement::CheckExternalLoginserverUserCredentials(
|
|
||||||
const std::string &in_account_username,
|
|
||||||
const std::string &in_account_password
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
auto res = task_runner.Enqueue(
|
auto res = task_runner.Enqueue(
|
||||||
[&]() -> uint32 {
|
[&]() -> uint32 {
|
||||||
@ -278,11 +125,11 @@ uint32 AccountManagement::CheckExternalLoginserverUserCredentials(
|
|||||||
uint32 ret = 0;
|
uint32 ret = 0;
|
||||||
|
|
||||||
EQ::Net::DaybreakConnectionManager mgr;
|
EQ::Net::DaybreakConnectionManager mgr;
|
||||||
std::shared_ptr<EQ::Net::DaybreakConnection> c;
|
std::shared_ptr<EQ::Net::DaybreakConnection> conn;
|
||||||
|
|
||||||
mgr.OnNewConnection(
|
mgr.OnNewConnection(
|
||||||
[&](std::shared_ptr<EQ::Net::DaybreakConnection> connection) {
|
[&](std::shared_ptr<EQ::Net::DaybreakConnection> connection) {
|
||||||
c = connection;
|
conn = connection;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -296,7 +143,7 @@ uint32 AccountManagement::CheckExternalLoginserverUserCredentials(
|
|||||||
EQ::Net::DynamicPacket p;
|
EQ::Net::DynamicPacket p;
|
||||||
p.PutUInt16(0, 1); //OP_SessionReady
|
p.PutUInt16(0, 1); //OP_SessionReady
|
||||||
p.PutUInt32(2, 2);
|
p.PutUInt32(2, 2);
|
||||||
c->QueuePacket(p);
|
conn->QueuePacket(p);
|
||||||
}
|
}
|
||||||
else if (EQ::Net::StatusDisconnected == to) {
|
else if (EQ::Net::StatusDisconnected == to) {
|
||||||
running = false;
|
running = false;
|
||||||
@ -310,13 +157,12 @@ uint32 AccountManagement::CheckExternalLoginserverUserCredentials(
|
|||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case 0x0017: //OP_ChatMessage
|
case 0x0017: //OP_ChatMessage
|
||||||
{
|
{
|
||||||
size_t buffer_len =
|
size_t buffer_len = c.username.length() + c.password.length() + 2;
|
||||||
in_account_username.length() + in_account_password.length() + 2;
|
|
||||||
|
|
||||||
std::unique_ptr<char[]> buffer(new char[buffer_len]);
|
std::unique_ptr<char[]> buffer(new char[buffer_len]);
|
||||||
|
|
||||||
strcpy(&buffer[0], in_account_username.c_str());
|
strcpy(&buffer[0], c.username.c_str());
|
||||||
strcpy(&buffer[in_account_username.length() + 1], in_account_password.c_str());
|
strcpy(&buffer[c.username.length() + 1], c.password.c_str());
|
||||||
|
|
||||||
size_t encrypted_len = buffer_len;
|
size_t encrypted_len = buffer_len;
|
||||||
|
|
||||||
@ -330,11 +176,11 @@ uint32 AccountManagement::CheckExternalLoginserverUserCredentials(
|
|||||||
p.PutUInt32(2, 3);
|
p.PutUInt32(2, 3);
|
||||||
|
|
||||||
eqcrypt_block(&buffer[0], buffer_len, (char *) p.Data() + 12, true);
|
eqcrypt_block(&buffer[0], buffer_len, (char *) p.Data() + 12, true);
|
||||||
c->QueuePacket(p);
|
conn->QueuePacket(p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x0018: {
|
case 0x0018: {
|
||||||
auto encrypt_size = p.Length() - 12;
|
auto encrypt_size = p.Length() - 12;
|
||||||
if (encrypt_size % 8 > 0) {
|
if (encrypt_size % 8 > 0) {
|
||||||
encrypt_size = (encrypt_size / 8) * 8;
|
encrypt_size = (encrypt_size / 8) * 8;
|
||||||
}
|
}
|
||||||
@ -394,15 +240,15 @@ uint32 AccountManagement::CheckExternalLoginserverUserCredentials(
|
|||||||
return res.get();
|
return res.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 AccountManagement::HealthCheckUserLogin()
|
uint64 AccountManagement::HealthCheckUserLogin()
|
||||||
{
|
{
|
||||||
std::string in_account_username = "healthcheckuser";
|
std::string in_account_username = "healthcheckuser";
|
||||||
std::string in_account_password = "healthcheckpassword";
|
std::string in_account_password = "healthcheckpassword";
|
||||||
|
|
||||||
auto res = task_runner.Enqueue(
|
auto res = task_runner.Enqueue(
|
||||||
[&]() -> uint32 {
|
[&]() -> uint64 {
|
||||||
bool running = true;
|
bool running = true;
|
||||||
uint32 ret = 0;
|
uint64 ret = 0;
|
||||||
|
|
||||||
EQ::Net::DaybreakConnectionManager mgr;
|
EQ::Net::DaybreakConnectionManager mgr;
|
||||||
std::shared_ptr<EQ::Net::DaybreakConnection> c;
|
std::shared_ptr<EQ::Net::DaybreakConnection> c;
|
||||||
@ -461,7 +307,7 @@ uint32 AccountManagement::HealthCheckUserLogin()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x0018: {
|
case 0x0018: {
|
||||||
auto encrypt_size = p.Length() - 12;
|
auto encrypt_size = p.Length() - 12;
|
||||||
if (encrypt_size % 8 > 0) {
|
if (encrypt_size % 8 > 0) {
|
||||||
encrypt_size = (encrypt_size / 8) * 8;
|
encrypt_size = (encrypt_size / 8) * 8;
|
||||||
}
|
}
|
||||||
@ -487,11 +333,11 @@ uint32 AccountManagement::HealthCheckUserLogin()
|
|||||||
mgr.Connect("127.0.0.1", 5999);
|
mgr.Connect("127.0.0.1", 5999);
|
||||||
|
|
||||||
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
|
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
|
||||||
auto &loop = EQ::EventLoop::Get();
|
auto &loop = EQ::EventLoop::Get();
|
||||||
while (running) {
|
while (running) {
|
||||||
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
|
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
|
||||||
if (std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() > 2000) {
|
if (std::chrono::duration_cast<std::chrono::milliseconds>(end - begin).count() > 2000) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,3 +350,59 @@ uint32 AccountManagement::HealthCheckUserLogin()
|
|||||||
|
|
||||||
return res.get();
|
return res.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AccountManagement::CreateLoginserverWorldAdminAccount(
|
||||||
|
const std::string &username,
|
||||||
|
const std::string &password,
|
||||||
|
const std::string &email,
|
||||||
|
const std::string &first_name,
|
||||||
|
const std::string &last_name,
|
||||||
|
const std::string &ip_address
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto mode = server.options.GetEncryptionMode();
|
||||||
|
auto hash = eqcrypt_hash(username, password, mode);
|
||||||
|
|
||||||
|
LogInfo(
|
||||||
|
"Attempting to create world admin account | username [{}] encryption algorithm [{}] ({})",
|
||||||
|
username,
|
||||||
|
GetEncryptionByModeId(mode),
|
||||||
|
mode
|
||||||
|
);
|
||||||
|
|
||||||
|
auto a = LoginServerAdminsRepository::GetByName(database, username);
|
||||||
|
if (a.id > 0) {
|
||||||
|
LogWarning(
|
||||||
|
"Attempting to create world admin account for user [{}] but already exists!",
|
||||||
|
username
|
||||||
|
);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
a = LoginServerAdminsRepository::NewEntity();
|
||||||
|
a.account_name = username;
|
||||||
|
a.account_password = hash;
|
||||||
|
a.first_name = first_name;
|
||||||
|
a.last_name = last_name;
|
||||||
|
a.email = email;
|
||||||
|
a.registration_ip_address = ip_address;
|
||||||
|
a.registration_date = std::time(nullptr);
|
||||||
|
|
||||||
|
a = LoginServerAdminsRepository::InsertOne(database, a);
|
||||||
|
|
||||||
|
if (a.id > 0) {
|
||||||
|
LogInfo(
|
||||||
|
"Account creation success for user [{}] encryption algorithm [{}] ({}) new admin id [{}]",
|
||||||
|
username,
|
||||||
|
GetEncryptionByModeId(mode),
|
||||||
|
mode,
|
||||||
|
a.id
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogError("Failed to create world admin account account for user [{}] !", username);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@ -3,32 +3,22 @@
|
|||||||
|
|
||||||
#include "iostream"
|
#include "iostream"
|
||||||
#include "../common/types.h"
|
#include "../common/types.h"
|
||||||
|
#include "login_types.h"
|
||||||
|
#include "encryption.h"
|
||||||
|
#include "login_server.h"
|
||||||
|
|
||||||
|
extern LoginServer server;
|
||||||
|
extern Database database;
|
||||||
|
|
||||||
class AccountManagement {
|
class AccountManagement {
|
||||||
public:
|
public:
|
||||||
|
static uint64 CreateLoginServerAccount(LoginAccountContext c);
|
||||||
|
static uint64 CheckLoginserverUserCredentials(LoginAccountContext c);
|
||||||
|
static bool UpdateLoginserverUserCredentials(LoginAccountContext c);
|
||||||
|
static uint64 CheckExternalLoginserverUserCredentials(LoginAccountContext c);
|
||||||
|
static bool UpdateLoginserverWorldAdminAccountPasswordByName(LoginAccountContext c);
|
||||||
|
static uint64 HealthCheckUserLogin();
|
||||||
|
|
||||||
/**
|
|
||||||
* @param username
|
|
||||||
* @param password
|
|
||||||
* @param email
|
|
||||||
* @param source_loginserver
|
|
||||||
* @param login_account_id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
static int32 CreateLoginServerAccount(
|
|
||||||
std::string username,
|
|
||||||
std::string password,
|
|
||||||
std::string email = "",
|
|
||||||
const std::string &source_loginserver = "local",
|
|
||||||
uint32 login_account_id = 0
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param username
|
|
||||||
* @param password
|
|
||||||
* @param email
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
static bool CreateLoginserverWorldAdminAccount(
|
static bool CreateLoginserverWorldAdminAccount(
|
||||||
const std::string &username,
|
const std::string &username,
|
||||||
const std::string &password,
|
const std::string &password,
|
||||||
@ -37,50 +27,6 @@ public:
|
|||||||
const std::string &last_name = "",
|
const std::string &last_name = "",
|
||||||
const std::string &ip_address = ""
|
const std::string &ip_address = ""
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
* @param in_account_username
|
|
||||||
* @param in_account_password
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
static uint32 CheckLoginserverUserCredentials(
|
|
||||||
const std::string &in_account_username,
|
|
||||||
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"
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param in_account_username
|
|
||||||
* @param in_account_password
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
static uint32 CheckExternalLoginserverUserCredentials(
|
|
||||||
const std::string &in_account_username,
|
|
||||||
const std::string &in_account_password
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param in_account_username
|
|
||||||
* @param in_account_password
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
static bool UpdateLoginserverWorldAdminAccountPasswordByName(
|
|
||||||
const std::string &in_account_username,
|
|
||||||
const std::string &in_account_password
|
|
||||||
);
|
|
||||||
|
|
||||||
static uint32 HealthCheckUserLogin();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,25 +1,18 @@
|
|||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "login_server.h"
|
#include "login_server.h"
|
||||||
#include "../common/misc_functions.h"
|
|
||||||
#include "../common/eqemu_logsys.h"
|
|
||||||
#include "../common/strings.h"
|
|
||||||
#include "encryption.h"
|
#include "encryption.h"
|
||||||
#include "account_management.h"
|
#include "account_management.h"
|
||||||
|
|
||||||
extern LoginServer server;
|
extern LoginServer server;
|
||||||
|
|
||||||
/**
|
|
||||||
* @param c
|
|
||||||
* @param v
|
|
||||||
*/
|
|
||||||
Client::Client(std::shared_ptr<EQStreamInterface> c, LSClientVersion v)
|
Client::Client(std::shared_ptr<EQStreamInterface> c, LSClientVersion v)
|
||||||
{
|
{
|
||||||
m_connection = c;
|
m_connection = c;
|
||||||
m_client_version = v;
|
m_client_version = v;
|
||||||
m_client_status = cs_not_sent_session_ready;
|
m_client_status = cs_not_sent_session_ready;
|
||||||
m_account_id = 0;
|
m_account_id = 0;
|
||||||
m_play_server_id = 0;
|
m_selected_play_server_id = 0;
|
||||||
m_play_sequence_id = 0;
|
m_play_sequence_id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Client::Process()
|
bool Client::Process()
|
||||||
@ -43,8 +36,8 @@ bool Client::Process()
|
|||||||
|
|
||||||
switch (app->GetOpcode()) {
|
switch (app->GetOpcode()) {
|
||||||
case OP_SessionReady: {
|
case OP_SessionReady: {
|
||||||
LogInfo("Session ready received from client account {}", GetClientDescription());
|
LogInfo("Session ready received from client account {}", GetClientLoggingDescription());
|
||||||
Handle_SessionReady((const char *) app->pBuffer, app->Size());
|
HandleSessionReady((const char *) app->pBuffer, app->Size());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_Login: {
|
case OP_Login: {
|
||||||
@ -53,9 +46,9 @@ bool Client::Process()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogInfo("Login received from client {}", GetClientDescription());
|
LogInfo("Login received from client {}", GetClientLoggingDescription());
|
||||||
|
|
||||||
Handle_Login((const char *) app->pBuffer, app->Size());
|
HandleLogin((const char *) app->pBuffer, app->Size());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_ServerListRequest: {
|
case OP_ServerListRequest: {
|
||||||
@ -64,18 +57,18 @@ bool Client::Process()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogInfo("Server list request received from client {}", GetClientDescription());
|
LogInfo("Server list request received from client {}", GetClientLoggingDescription());
|
||||||
|
|
||||||
SendServerListPacket(*(uint32_t *) app->pBuffer);
|
SendServerListPacket(*(uint32_t *) app->pBuffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_PlayEverquestRequest: {
|
case OP_PlayEverquestRequest: {
|
||||||
if (app->Size() < sizeof(PlayEverquestRequest_Struct)) {
|
if (app->Size() < sizeof(PlayEverquestRequest)) {
|
||||||
LogError("Play received but it is too small, discarding");
|
LogError("Play received but it is too small, discarding");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle_Play((const char *) app->pBuffer);
|
SendPlayToWorld((const char *) app->pBuffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,13 +80,7 @@ bool Client::Process()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void Client::HandleSessionReady(const char *data, unsigned int size)
|
||||||
* Sends our reply to session ready packet
|
|
||||||
*
|
|
||||||
* @param data
|
|
||||||
* @param size
|
|
||||||
*/
|
|
||||||
void Client::Handle_SessionReady(const char *data, unsigned int size)
|
|
||||||
{
|
{
|
||||||
if (m_client_status != cs_not_sent_session_ready) {
|
if (m_client_status != cs_not_sent_session_ready) {
|
||||||
LogError("Session ready received again after already being received");
|
LogError("Session ready received again after already being received");
|
||||||
@ -107,11 +94,8 @@ void Client::Handle_SessionReady(const char *data, unsigned int size)
|
|||||||
|
|
||||||
m_client_status = cs_waiting_for_login;
|
m_client_status = cs_waiting_for_login;
|
||||||
|
|
||||||
/**
|
auto *outapp = new EQApplicationPacket(OP_ChatMessage, sizeof(LoginHandShakeReply));
|
||||||
* The packets are identical between the two versions
|
auto buf = reinterpret_cast<LoginHandShakeReply *>(outapp->pBuffer);
|
||||||
*/
|
|
||||||
auto *outapp = new EQApplicationPacket(OP_ChatMessage, sizeof(LoginHandShakeReply_Struct));
|
|
||||||
auto buf = reinterpret_cast<LoginHandShakeReply_Struct*>(outapp->pBuffer);
|
|
||||||
buf->base_header.sequence = 0x02;
|
buf->base_header.sequence = 0x02;
|
||||||
buf->base_reply.success = true;
|
buf->base_reply.success = true;
|
||||||
buf->base_reply.error_str_id = 0x65; // 101 "No Error"
|
buf->base_reply.error_str_id = 0x65; // 101 "No Error"
|
||||||
@ -120,13 +104,7 @@ void Client::Handle_SessionReady(const char *data, unsigned int size)
|
|||||||
delete outapp;
|
delete outapp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void Client::HandleLogin(const char *data, unsigned int size)
|
||||||
* Verifies login and send a reply
|
|
||||||
*
|
|
||||||
* @param data
|
|
||||||
* @param size
|
|
||||||
*/
|
|
||||||
void Client::Handle_Login(const char *data, unsigned int size)
|
|
||||||
{
|
{
|
||||||
if (m_client_status != cs_waiting_for_login) {
|
if (m_client_status != cs_waiting_for_login) {
|
||||||
LogError("Login received after already having logged in");
|
LogError("Login received after already having logged in");
|
||||||
@ -134,41 +112,37 @@ void Client::Handle_Login(const char *data, unsigned int size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// login user/pass are variable length after unencrypted opcode and base message header (size includes opcode)
|
// login user/pass are variable length after unencrypted opcode and base message header (size includes opcode)
|
||||||
constexpr int header_size = sizeof(uint16_t) + sizeof(LoginBaseMessage_Struct);
|
constexpr int header_size = sizeof(uint16_t) + sizeof(LoginBaseMessage);
|
||||||
int data_size = size - header_size;
|
int data_size = size - header_size;
|
||||||
|
|
||||||
if (size <= header_size) {
|
if (size <= header_size) {
|
||||||
LogError("Login received packet of size: {0}, this would cause a buffer overflow, discarding", size);
|
LogError("Login received packet of size: {}, this would cause a buffer overflow, discarding", size);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data_size % 8 != 0) {
|
if (data_size % 8 != 0) {
|
||||||
LogError("Login received packet of size: {0}, this would cause a block corruption, discarding", size);
|
LogError("Login received packet of size: {}, this would cause a block corruption, discarding", size);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *login_packet_buffer = nullptr;
|
|
||||||
|
|
||||||
unsigned int db_account_id = 0;
|
unsigned int db_account_id = 0;
|
||||||
|
|
||||||
std::string db_loginserver = "local";
|
std::string db_loginserver = "local";
|
||||||
if (server.options.CanAutoLinkAccounts()) {
|
if (std::getenv("LSPX")) {
|
||||||
db_loginserver = "eqemu";
|
db_loginserver = "eqemu";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string db_account_password_hash;
|
|
||||||
|
|
||||||
std::string outbuffer;
|
std::string outbuffer;
|
||||||
outbuffer.resize(data_size);
|
outbuffer.resize(data_size);
|
||||||
if (outbuffer.length() == 0) {
|
if (outbuffer.empty()) {
|
||||||
LogError("Corrupt buffer sent to server, no length");
|
LogError("Corrupt buffer sent to server, no length");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// data starts at base message header (opcode not included)
|
// data starts at base message header (opcode not included)
|
||||||
auto r = eqcrypt_block(data + sizeof(LoginBaseMessage_Struct), data_size, &outbuffer[0], 0);
|
auto r = eqcrypt_block(data + sizeof(LoginBaseMessage), data_size, &outbuffer[0], false);
|
||||||
if (r == nullptr) {
|
if (r == nullptr) {
|
||||||
LogError("Failed to decrypt eqcrypt block");
|
LogError("Failed to decrypt eqcrypt block");
|
||||||
return;
|
return;
|
||||||
@ -182,131 +156,114 @@ void Client::Handle_Login(const char *data, unsigned int size)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// std::cout << "User: " << user << std::endl;
|
||||||
|
|
||||||
// only need to copy the base header for reply options, ignore login info
|
// only need to copy the base header for reply options, ignore login info
|
||||||
memcpy(&m_llrs, data, sizeof(LoginBaseMessage_Struct));
|
memcpy(&m_login_base_message, data, sizeof(LoginBaseMessage));
|
||||||
|
|
||||||
bool result = false;
|
// std::cout << "Seq: " << m_login_base_message.sequence << std::endl;
|
||||||
if (outbuffer[0] == 0 && outbuffer[1] == 0) {
|
// std::cout << "compressed: " << m_login_base_message.compressed << std::endl;
|
||||||
|
// std::cout << "encrypt_type: " << m_login_base_message.encrypt_type << std::endl;
|
||||||
|
// std::cout << "unk3: " << m_login_base_message.unk3 << std::endl;
|
||||||
|
|
||||||
|
bool login_success = false;
|
||||||
|
bool token_login = outbuffer[0] == 0 && outbuffer[1] == 0;
|
||||||
|
if (token_login) {
|
||||||
if (server.options.IsTokenLoginAllowed()) {
|
if (server.options.IsTokenLoginAllowed()) {
|
||||||
cred = (&outbuffer[2 + user.length()]);
|
cred = (&outbuffer[2 + user.length()]);
|
||||||
result = server.db->GetLoginTokenDataFromToken(
|
// todo: implement token login
|
||||||
cred,
|
// SELECT login_server, username, account_id FROM login_tickets WHERE expires > NOW() AND id='{}' AND ip_address='{}' LIMIT 1
|
||||||
m_connection->GetRemoteAddr(),
|
// login_success ? DoSuccessfulLogin(user, db_account_id, db_loginserver) : SendFailedLogin();
|
||||||
db_account_id,
|
SendFailedLogin();
|
||||||
db_loginserver,
|
|
||||||
user
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if (server.options.IsPasswordLoginAllowed()) {
|
|
||||||
cred = (&outbuffer[1 + user.length()]);
|
|
||||||
auto components = Strings::Split(user, ':');
|
|
||||||
if (components.size() == 2) {
|
|
||||||
db_loginserver = components[0];
|
|
||||||
user = components[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
// health checks
|
// normal login
|
||||||
if (ProcessHealthCheck(user)) {
|
cred = (&outbuffer[1 + user.length()]);
|
||||||
DoFailedLogin();
|
auto components = Strings::Split(user, ':');
|
||||||
return;
|
if (components.size() == 2) {
|
||||||
}
|
db_loginserver = components[0];
|
||||||
|
user = components[1];
|
||||||
|
}
|
||||||
|
|
||||||
LogInfo(
|
// health checks
|
||||||
"Attempting password based login [{0}] login [{1}]",
|
if (ProcessHealthCheck(user)) {
|
||||||
user,
|
SendFailedLogin();
|
||||||
db_loginserver
|
return;
|
||||||
);
|
}
|
||||||
|
|
||||||
ParseAccountString(user, user, db_loginserver);
|
LogInfo(
|
||||||
|
"Attempting password based login [{}] login [{}]",
|
||||||
|
user,
|
||||||
|
db_loginserver
|
||||||
|
);
|
||||||
|
|
||||||
if (server.db->GetLoginDataFromAccountInfo(user, db_loginserver, db_account_password_hash, db_account_id)) {
|
ParseAccountString(user, user, db_loginserver);
|
||||||
result = VerifyLoginHash(user, db_loginserver, cred, db_account_password_hash);
|
|
||||||
|
|
||||||
#ifdef LSPX
|
LoginAccountContext c = {};
|
||||||
// if user updated their password on the login server, update it here by validating their credentials with the login server
|
c.username = user;
|
||||||
if (!result && db_loginserver == "eqemu") {
|
c.password = cred;
|
||||||
uint32 account_id = AccountManagement::CheckExternalLoginserverUserCredentials(user, cred);
|
c.source_loginserver = db_loginserver;
|
||||||
if (account_id > 0) {
|
|
||||||
auto encryption_mode = server.options.GetEncryptionMode();
|
auto a = LoginAccountsRepository::GetAccountFromContext(database, c);
|
||||||
server.db->UpdateLoginserverAccountPasswordHash(
|
if (a.id > 0) {
|
||||||
user,
|
login_success = VerifyAndUpdateLoginHash(c, a);
|
||||||
db_loginserver,
|
|
||||||
eqcrypt_hash(user, cred, encryption_mode)
|
// if user updated their password on the login server, update it here by validating their credentials with the login server
|
||||||
);
|
if (std::getenv("LSPX") && !login_success && db_loginserver == "eqemu") {
|
||||||
LogInfo("Updating eqemu account [{}] password hash", account_id);
|
LogInfo("LSPX | Attempting login account via [{}]", db_loginserver);
|
||||||
result = true;
|
uint32 account_id = AccountManagement::CheckExternalLoginserverUserCredentials(c);
|
||||||
}
|
LogInfo("LSPX | External login account id [{}]", account_id);
|
||||||
|
if (account_id > 0) {
|
||||||
|
auto updated_account = LoginAccountsRepository::UpdateAccountPassword(database, a, cred);
|
||||||
|
if (!updated_account.id) {
|
||||||
|
LogError("Failed to update eqemu account [{}] password hash", account_id);
|
||||||
|
SendFailedLogin();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
LogDebug("Success [{0}]", (result ? "true" : "false"));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_client_status = cs_creating_account;
|
|
||||||
AttemptLoginAccountCreation(user, cred, db_loginserver);
|
|
||||||
|
|
||||||
|
LogInfo("Updating eqemu account [{}] password hash", account_id);
|
||||||
|
DoSuccessfulLogin(updated_account);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LogInfo("Successful login [{}]", (login_success ? "true" : "false"));
|
||||||
|
login_success ? DoSuccessfulLogin(a) : SendFailedLogin();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// if we are here, the account does not exist
|
||||||
* Login accepted
|
m_client_status = cs_creating_account;
|
||||||
*/
|
AttemptLoginAccountCreation(c);
|
||||||
if (result) {
|
|
||||||
LogInfo(
|
|
||||||
"login [{0}] user [{1}] Login succeeded",
|
|
||||||
db_loginserver,
|
|
||||||
user
|
|
||||||
);
|
|
||||||
|
|
||||||
DoSuccessfulLogin(user, db_account_id, db_loginserver);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LogInfo(
|
|
||||||
"login [{0}] user [{1}] Login failed",
|
|
||||||
db_loginserver,
|
|
||||||
user
|
|
||||||
);
|
|
||||||
|
|
||||||
DoFailedLogin();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void Client::SendPlayToWorld(const char *data)
|
||||||
* Sends a packet to the requested server to see if the client is allowed or not
|
|
||||||
*
|
|
||||||
* @param data
|
|
||||||
*/
|
|
||||||
void Client::Handle_Play(const char *data)
|
|
||||||
{
|
{
|
||||||
if (m_client_status != cs_logged_in) {
|
if (m_client_status != cs_logged_in) {
|
||||||
LogError("Client sent a play request when they were not logged in, discarding");
|
LogError("Client sent a play request when they were not logged in, discarding");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto *play = (const PlayEverquestRequest_Struct *) data;
|
const auto *play = (const PlayEverquestRequest *) data;
|
||||||
auto server_id_in = (unsigned int) play->server_number;
|
auto server_id_in = (unsigned int) play->server_number;
|
||||||
auto sequence_in = (unsigned int) play->base_header.sequence;
|
auto sequence_in = (unsigned int) play->base_header.sequence;
|
||||||
|
|
||||||
LogInfo(
|
LogInfo(
|
||||||
"[Handle_Play] Play received from client [{}] server number [{}] sequence [{}]",
|
"[SendPlayToWorld] Play received from client [{}] server number [{}] sequence [{}]",
|
||||||
GetAccountName(),
|
GetAccountName(),
|
||||||
server_id_in,
|
server_id_in,
|
||||||
sequence_in
|
sequence_in
|
||||||
);
|
);
|
||||||
|
|
||||||
m_play_server_id = (unsigned int) play->server_number;
|
m_selected_play_server_id = (unsigned int) play->server_number;
|
||||||
m_play_sequence_id = sequence_in;
|
m_play_sequence_id = sequence_in;
|
||||||
m_play_server_id = server_id_in;
|
m_selected_play_server_id = server_id_in;
|
||||||
server.server_manager->SendUserToWorldRequest(server_id_in, m_account_id, m_loginserver_name);
|
server.server_manager->SendUserLoginToWorldRequest(server_id_in, m_account_id, m_loginserver_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param seq
|
|
||||||
*/
|
|
||||||
void Client::SendServerListPacket(uint32 seq)
|
void Client::SendServerListPacket(uint32 seq)
|
||||||
{
|
{
|
||||||
auto app = server.server_manager->CreateServerListPacket(this, seq);
|
auto app = server.server_manager->CreateServerListPacket(this, seq);
|
||||||
@ -316,11 +273,11 @@ void Client::SendServerListPacket(uint32 seq)
|
|||||||
|
|
||||||
void Client::SendPlayResponse(EQApplicationPacket *outapp)
|
void Client::SendPlayResponse(EQApplicationPacket *outapp)
|
||||||
{
|
{
|
||||||
LogInfo("Sending play response for {}", GetClientDescription());
|
LogInfo("Sending play response for {}", GetClientLoggingDescription());
|
||||||
m_connection->QueuePacket(outapp);
|
m_connection->QueuePacket(outapp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::GenerateKey()
|
void Client::GenerateRandomLoginKey()
|
||||||
{
|
{
|
||||||
m_key.clear();
|
m_key.clear();
|
||||||
int count = 0;
|
int count = 0;
|
||||||
@ -339,229 +296,193 @@ void Client::GenerateKey()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void Client::AttemptLoginAccountCreation(LoginAccountContext c)
|
||||||
* @param user
|
|
||||||
* @param pass
|
|
||||||
* @param loginserver
|
|
||||||
*/
|
|
||||||
void Client::AttemptLoginAccountCreation(
|
|
||||||
const std::string &user,
|
|
||||||
const std::string &pass,
|
|
||||||
const std::string &loginserver
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
LogInfo("user [{}] loginserver [{}]", user, loginserver);
|
LogInfo("user [{}] loginserver [{}]", c.username, c.source_loginserver);
|
||||||
|
|
||||||
#ifdef LSPX
|
if (std::getenv("LSPX") && c.source_loginserver == "eqemu") {
|
||||||
if (loginserver == "eqemu") {
|
LogInfo("LSPX | Attempting login account creation via [{}]", c.source_loginserver);
|
||||||
LogInfo("Attempting login account creation via '{0}'", loginserver);
|
|
||||||
|
|
||||||
if (!server.options.CanAutoLinkAccounts()) {
|
|
||||||
LogInfo("CanAutoLinkAccounts disabled - sending failed login");
|
|
||||||
DoFailedLogin();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32 account_id = AccountManagement::CheckExternalLoginserverUserCredentials(
|
|
||||||
user,
|
|
||||||
pass
|
|
||||||
);
|
|
||||||
|
|
||||||
|
uint32 account_id = AccountManagement::CheckExternalLoginserverUserCredentials(c);
|
||||||
|
c.login_account_id = account_id;
|
||||||
if (account_id > 0) {
|
if (account_id > 0) {
|
||||||
LogInfo("Found and creating eqemu account [{}]", account_id);
|
LogInfo("LSPX | Found and creating eqemu account [{}]", account_id);
|
||||||
CreateEQEmuAccount(user, pass, account_id);
|
auto a = LoginAccountsRepository::CreateAccountFromContext(database, c);
|
||||||
|
if (a.id > 0) {
|
||||||
|
DoSuccessfulLogin(a);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LogInfo("LSPX | External authentication failed for user [{}]", c.username);
|
||||||
|
|
||||||
|
SendFailedLogin();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server.options.CanAutoCreateAccounts() && c.source_loginserver == "local") {
|
||||||
|
LogInfo("CanAutoCreateAccounts enabled, attempting to crate account [{}]", c.username);
|
||||||
|
auto a = LoginAccountsRepository::CreateAccountFromContext(database, c);
|
||||||
|
if (a.id > 0) {
|
||||||
|
DoSuccessfulLogin(a);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DoFailedLogin();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (server.options.CanAutoCreateAccounts() && loginserver == "local") {
|
|
||||||
LogInfo("CanAutoCreateAccounts enabled, attempting to creating account [{0}]", user);
|
|
||||||
CreateLocalAccount(user, pass);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DoFailedLogin();
|
SendFailedLogin();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::DoFailedLogin()
|
void Client::SendFailedLogin()
|
||||||
{
|
{
|
||||||
m_stored_user.clear();
|
m_stored_username.clear();
|
||||||
m_stored_pass.clear();
|
m_stored_password.clear();
|
||||||
|
|
||||||
// unencrypted
|
// unencrypted
|
||||||
LoginBaseMessage_Struct base_header{};
|
LoginBaseMessage h{};
|
||||||
base_header.sequence = m_llrs.sequence; // login (3)
|
h.sequence = m_login_base_message.sequence; // login (3)
|
||||||
base_header.encrypt_type = m_llrs.encrypt_type;
|
h.encrypt_type = m_login_base_message.encrypt_type;
|
||||||
|
|
||||||
// encrypted
|
// encrypted
|
||||||
PlayerLoginReply_Struct login_reply{};
|
PlayerLoginReply r{};
|
||||||
login_reply.base_reply.success = false;
|
r.base_reply.success = false;
|
||||||
login_reply.base_reply.error_str_id = 105; // Error - The username and/or password were not valid
|
r.base_reply.error_str_id = 105; // Error - The username and/or password were not valid
|
||||||
|
|
||||||
char encrypted_buffer[80] = {0};
|
char encrypted_buffer[80] = {0};
|
||||||
auto rc = eqcrypt_block((const char*)&login_reply, sizeof(login_reply), encrypted_buffer, 1);
|
auto rc = eqcrypt_block((const char *) &r, sizeof(r), encrypted_buffer, 1);
|
||||||
if (rc == nullptr) {
|
if (rc == nullptr) {
|
||||||
LogDebug("Failed to encrypt eqcrypt block for failed login");
|
LogDebug("Failed to encrypt eqcrypt block for failed login");
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr int outsize = sizeof(LoginBaseMessage_Struct) + sizeof(encrypted_buffer);
|
constexpr int outsize = sizeof(LoginBaseMessage) + sizeof(encrypted_buffer);
|
||||||
EQApplicationPacket outapp(OP_LoginAccepted, outsize);
|
EQApplicationPacket outapp(OP_LoginAccepted, outsize);
|
||||||
outapp.WriteData(&base_header, sizeof(base_header));
|
outapp.WriteData(&h, sizeof(h));
|
||||||
outapp.WriteData(&encrypted_buffer, sizeof(encrypted_buffer));
|
outapp.WriteData(&encrypted_buffer, sizeof(encrypted_buffer));
|
||||||
|
|
||||||
m_connection->QueuePacket(&outapp);
|
m_connection->QueuePacket(&outapp);
|
||||||
m_client_status = cs_failed_to_login;
|
m_client_status = cs_failed_to_login;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
bool Client::VerifyAndUpdateLoginHash(LoginAccountContext c, const LoginAccountsRepository::LoginAccounts &a)
|
||||||
* Verifies a login hash, will also attempt to update a login hash if needed
|
|
||||||
*
|
|
||||||
* @param account_username
|
|
||||||
* @param source_loginserver
|
|
||||||
* @param account_password
|
|
||||||
* @param password_hash
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool Client::VerifyLoginHash(
|
|
||||||
const std::string &account_username,
|
|
||||||
const std::string &source_loginserver,
|
|
||||||
const std::string &account_password,
|
|
||||||
const std::string &password_hash
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
auto encryption_mode = server.options.GetEncryptionMode();
|
auto encryption_mode = server.options.GetEncryptionMode();
|
||||||
if (eqcrypt_verify_hash(account_username, account_password, password_hash, encryption_mode)) {
|
if (eqcrypt_verify_hash(a.account_name, c.password, a.account_password, encryption_mode)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if (server.options.IsUpdatingInsecurePasswords()) {
|
|
||||||
if (encryption_mode < EncryptionModeArgon2) {
|
|
||||||
encryption_mode = EncryptionModeArgon2;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 insecure_source_encryption_mode = 0;
|
if (encryption_mode < EncryptionModeArgon2) {
|
||||||
if (password_hash.length() == CryptoHash::md5_hash_length) {
|
encryption_mode = EncryptionModeArgon2;
|
||||||
for (int i = EncryptionModeMD5; i <= EncryptionModeMD5Triple; ++i) {
|
}
|
||||||
if (i != encryption_mode &&
|
|
||||||
eqcrypt_verify_hash(account_username, account_password, password_hash, i)) {
|
|
||||||
insecure_source_encryption_mode = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (password_hash.length() == CryptoHash::sha1_hash_length && insecure_source_encryption_mode == 0) {
|
|
||||||
for (int i = EncryptionModeSHA; i <= EncryptionModeSHATriple; ++i) {
|
|
||||||
if (i != encryption_mode &&
|
|
||||||
eqcrypt_verify_hash(account_username, account_password, password_hash, i)) {
|
|
||||||
insecure_source_encryption_mode = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (password_hash.length() == CryptoHash::sha512_hash_length && insecure_source_encryption_mode == 0) {
|
|
||||||
for (int i = EncryptionModeSHA512; i <= EncryptionModeSHA512Triple; ++i) {
|
|
||||||
if (i != encryption_mode &&
|
|
||||||
eqcrypt_verify_hash(account_username, account_password, password_hash, i)) {
|
|
||||||
insecure_source_encryption_mode = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (insecure_source_encryption_mode > 0) {
|
uint32 insecure_source_encryption_mode = 0;
|
||||||
LogInfo(
|
|
||||||
"[{}] Updated insecure password user [{}] loginserver [{}] from mode [{}] ({}) to mode [{}] ({})",
|
|
||||||
__func__,
|
|
||||||
account_username,
|
|
||||||
source_loginserver,
|
|
||||||
GetEncryptionByModeId(insecure_source_encryption_mode),
|
|
||||||
insecure_source_encryption_mode,
|
|
||||||
GetEncryptionByModeId(encryption_mode),
|
|
||||||
encryption_mode
|
|
||||||
);
|
|
||||||
|
|
||||||
server.db->UpdateLoginserverAccountPasswordHash(
|
auto verify_encryption_mode = [&](int start, int end) {
|
||||||
account_username,
|
for (int i = start; i <= end; ++i) {
|
||||||
source_loginserver,
|
if (i != encryption_mode && eqcrypt_verify_hash(a.account_name, c.password, a.account_password, i)) {
|
||||||
eqcrypt_hash(
|
insecure_source_encryption_mode = i;
|
||||||
account_username,
|
|
||||||
account_password,
|
|
||||||
encryption_mode
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (a.account_password.length()) {
|
||||||
|
case CryptoHash::md5_hash_length:
|
||||||
|
verify_encryption_mode(EncryptionModeMD5, EncryptionModeMD5Triple);
|
||||||
|
break;
|
||||||
|
case CryptoHash::sha1_hash_length:
|
||||||
|
if (insecure_source_encryption_mode == 0) {
|
||||||
|
verify_encryption_mode(EncryptionModeSHA, EncryptionModeSHATriple);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CryptoHash::sha512_hash_length:
|
||||||
|
if (insecure_source_encryption_mode == 0) {
|
||||||
|
verify_encryption_mode(EncryptionModeSHA512, EncryptionModeSHA512Triple);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (insecure_source_encryption_mode > 0) {
|
||||||
|
LogInfo(
|
||||||
|
"Updated insecure password user [{}] loginserver [{}] from mode [{}] ({}) to mode [{}] ({})",
|
||||||
|
c.username,
|
||||||
|
c.source_loginserver,
|
||||||
|
GetEncryptionByModeId(insecure_source_encryption_mode),
|
||||||
|
insecure_source_encryption_mode,
|
||||||
|
GetEncryptionByModeId(encryption_mode),
|
||||||
|
encryption_mode
|
||||||
|
);
|
||||||
|
|
||||||
|
LoginAccountsRepository::UpdateAccountPassword(database, a, c.password);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void Client::DoSuccessfulLogin(LoginAccountsRepository::LoginAccounts &a)
|
||||||
* @param in_account_name
|
|
||||||
* @param db_account_id
|
|
||||||
* @param db_loginserver
|
|
||||||
*/
|
|
||||||
void Client::DoSuccessfulLogin(
|
|
||||||
const std::string& in_account_name,
|
|
||||||
int db_account_id,
|
|
||||||
const std::string &db_loginserver
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
m_stored_user.clear();
|
m_stored_username.clear();
|
||||||
m_stored_pass.clear();
|
m_stored_password.clear();
|
||||||
|
|
||||||
server.client_manager->RemoveExistingClient(db_account_id, db_loginserver);
|
LogInfo(
|
||||||
|
"Successful login for user id [{}] account name [{}] login server [{}]",
|
||||||
|
a.id,
|
||||||
|
a.account_name,
|
||||||
|
a.source_loginserver
|
||||||
|
);
|
||||||
|
|
||||||
|
server.client_manager->RemoveExistingClient(a.id, a.source_loginserver);
|
||||||
|
|
||||||
in_addr in{};
|
in_addr in{};
|
||||||
in.s_addr = m_connection->GetRemoteIP();
|
in.s_addr = m_connection->GetRemoteIP();
|
||||||
|
|
||||||
server.db->UpdateLSAccountData(db_account_id, std::string(inet_ntoa(in)));
|
a.last_ip_address = std::string(inet_ntoa(in));
|
||||||
GenerateKey();
|
LoginAccountsRepository::UpdateOne(database, a);
|
||||||
|
|
||||||
m_account_id = db_account_id;
|
GenerateRandomLoginKey();
|
||||||
m_account_name = in_account_name;
|
|
||||||
m_loginserver_name = db_loginserver;
|
m_account_id = a.id;
|
||||||
|
m_account_name = a.account_name;
|
||||||
|
m_loginserver_name = a.source_loginserver;
|
||||||
|
|
||||||
// unencrypted
|
// unencrypted
|
||||||
LoginBaseMessage_Struct base_header{};
|
LoginBaseMessage h{};
|
||||||
base_header.sequence = m_llrs.sequence;
|
h.sequence = m_login_base_message.sequence;
|
||||||
base_header.compressed = false;
|
h.compressed = false;
|
||||||
base_header.encrypt_type = m_llrs.encrypt_type;
|
h.encrypt_type = m_login_base_message.encrypt_type;
|
||||||
base_header.unk3 = m_llrs.unk3;
|
h.unk3 = m_login_base_message.unk3;
|
||||||
|
|
||||||
// not serializing any of the variable length strings so just use struct directly
|
// not serializing any of the variable length strings so just use struct directly
|
||||||
PlayerLoginReply_Struct login_reply{};
|
PlayerLoginReply r{};
|
||||||
login_reply.base_reply.success = true;
|
r.base_reply.success = true;
|
||||||
login_reply.base_reply.error_str_id = 101; // No Error
|
r.base_reply.error_str_id = 101; // No Error
|
||||||
login_reply.unk1 = 0;
|
r.unk1 = 0;
|
||||||
login_reply.unk2 = 0;
|
r.unk2 = 0;
|
||||||
login_reply.lsid = db_account_id;
|
r.lsid = a.id;
|
||||||
login_reply.failed_attempts = 0;
|
r.failed_attempts = 0;
|
||||||
login_reply.show_player_count = server.options.IsShowPlayerCountEnabled();
|
r.show_player_count = server.options.IsShowPlayerCountEnabled();
|
||||||
login_reply.offer_min_days = 99;
|
r.offer_min_days = 99;
|
||||||
login_reply.offer_min_views = -1;
|
r.offer_min_views = -1;
|
||||||
login_reply.offer_cooldown_minutes = 0;
|
r.offer_cooldown_minutes = 0;
|
||||||
login_reply.web_offer_number = 0;
|
r.web_offer_number = 0;
|
||||||
login_reply.web_offer_min_days = 99;
|
r.web_offer_min_days = 99;
|
||||||
login_reply.web_offer_min_views = -1;
|
r.web_offer_min_views = -1;
|
||||||
login_reply.web_offer_cooldown_minutes = 0;
|
r.web_offer_cooldown_minutes = 0;
|
||||||
memcpy(login_reply.key, m_key.c_str(), m_key.size());
|
memcpy(r.key, m_key.c_str(), m_key.size());
|
||||||
|
|
||||||
SendExpansionPacketData(login_reply);
|
SendExpansionPacketData(r);
|
||||||
|
|
||||||
char encrypted_buffer[80] = {0};
|
char encrypted_buffer[80] = {0};
|
||||||
auto rc = eqcrypt_block((const char*)&login_reply, sizeof(login_reply), encrypted_buffer, 1);
|
|
||||||
|
auto rc = eqcrypt_block((const char *) &r, sizeof(r), encrypted_buffer, 1);
|
||||||
if (rc == nullptr) {
|
if (rc == nullptr) {
|
||||||
LogDebug("Failed to encrypt eqcrypt block");
|
LogDebug("Failed to encrypt eqcrypt block");
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr int outsize = sizeof(LoginBaseMessage_Struct) + sizeof(encrypted_buffer);
|
constexpr int outsize = sizeof(LoginBaseMessage) + sizeof(encrypted_buffer);
|
||||||
auto outapp = std::make_unique<EQApplicationPacket>(OP_LoginAccepted, outsize);
|
auto outapp = std::make_unique<EQApplicationPacket>(OP_LoginAccepted, outsize);
|
||||||
outapp->WriteData(&base_header, sizeof(base_header));
|
outapp->WriteData(&h, sizeof(h));
|
||||||
outapp->WriteData(&encrypted_buffer, sizeof(encrypted_buffer));
|
outapp->WriteData(&encrypted_buffer, sizeof(encrypted_buffer));
|
||||||
|
|
||||||
m_connection->QueuePacket(outapp.get());
|
m_connection->QueuePacket(outapp.get());
|
||||||
@ -569,19 +490,21 @@ void Client::DoSuccessfulLogin(
|
|||||||
m_client_status = cs_logged_in;
|
m_client_status = cs_logged_in;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::SendExpansionPacketData(PlayerLoginReply_Struct& plrs)
|
void Client::SendExpansionPacketData(PlayerLoginReply &plrs)
|
||||||
{
|
{
|
||||||
SerializeBuffer buf;
|
SerializeBuffer buf;
|
||||||
//from eqlsstr_us.txt id of each expansion, excluding 'Everquest'
|
//from eqlsstr_us.txt id of each expansion, excluding 'Everquest'
|
||||||
int ExpansionLookup[20] = { 3007, 3008, 3009, 3010, 3012,
|
|
||||||
3014, 3031, 3033, 3036, 3040,
|
|
||||||
3045, 3046, 3047, 3514, 3516,
|
|
||||||
3518, 3520, 3522, 3524 };
|
|
||||||
|
|
||||||
|
int ExpansionLookup[20] = {
|
||||||
|
3007, 3008, 3009, 3010, 3012,
|
||||||
|
3014, 3031, 3033, 3036, 3040,
|
||||||
|
3045, 3046, 3047, 3514, 3516,
|
||||||
|
3518, 3520, 3522, 3524
|
||||||
|
};
|
||||||
|
|
||||||
if (server.options.IsDisplayExpansions()) {
|
if (server.options.IsDisplayExpansions()) {
|
||||||
|
|
||||||
int32_t expansion = server.options.GetMaxExpansions();
|
int32_t expansion = server.options.GetMaxExpansions();
|
||||||
int32_t owned_expansion = (expansion << 1) | 1;
|
int32_t owned_expansion = (expansion << 1) | 1;
|
||||||
|
|
||||||
if (m_client_version == cv_sod) {
|
if (m_client_version == cv_sod) {
|
||||||
@ -593,15 +516,14 @@ void Client::SendExpansionPacketData(PlayerLoginReply_Struct& plrs)
|
|||||||
buf.WriteInt32(19); //number of expansions to include in packet
|
buf.WriteInt32(19); //number of expansions to include in packet
|
||||||
|
|
||||||
//generate expansion data
|
//generate expansion data
|
||||||
for (int i = 0; i < 19; i++)
|
for (int i = 0; i < 19; i++) {
|
||||||
{
|
buf.WriteInt32(i); //sequenctial number
|
||||||
buf.WriteInt32(i); //sequenctial number
|
buf.WriteInt32((expansion & (1 << i)) == (1 << i) ? 0x01 : 0x00); //1 own 0 not own
|
||||||
buf.WriteInt32((expansion & (1 << i)) == (1 << i) ? 0x01 : 0x00); //1 own 0 not own
|
|
||||||
buf.WriteInt8(0x00);
|
buf.WriteInt8(0x00);
|
||||||
buf.WriteInt32(ExpansionLookup[i]); //from eqlsstr_us.txt
|
buf.WriteInt32(ExpansionLookup[i]); //from eqlsstr_us.txt
|
||||||
buf.WriteInt32(0x179E); //from eqlsstr_us.txt for buttons/order
|
buf.WriteInt32(0x179E); //from eqlsstr_us.txt for buttons/order
|
||||||
buf.WriteInt32(0xFFFFFFFF); //end identification
|
buf.WriteInt32(0xFFFFFFFF); //end identification
|
||||||
buf.WriteInt8(0x0); //force order window to appear 1 appear 0 not appear
|
buf.WriteInt8(0x0); //force order window to appear 1 appear 0 not appear
|
||||||
buf.WriteInt8(0x0);
|
buf.WriteInt8(0x0);
|
||||||
buf.WriteInt32(0x0000);
|
buf.WriteInt32(0x0000);
|
||||||
buf.WriteInt32(0x0000);
|
buf.WriteInt32(0x0000);
|
||||||
@ -612,79 +534,21 @@ void Client::SendExpansionPacketData(PlayerLoginReply_Struct& plrs)
|
|||||||
m_connection->QueuePacket(out.get());
|
m_connection->QueuePacket(out.get());
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (m_client_version == cv_titanium)
|
else if (m_client_version == cv_titanium) {
|
||||||
{
|
if (expansion >= EQ::expansions::bitPoR) {
|
||||||
if (expansion >= EQ::expansions::bitPoR)
|
|
||||||
{
|
|
||||||
// Titanium shipped with 10 expansions. Set owned expansions to be max 10.
|
// Titanium shipped with 10 expansions. Set owned expansions to be max 10.
|
||||||
plrs.offer_min_days = ((EQ::expansions::bitDoD << 2) | 1) - 2;
|
plrs.offer_min_days = ((EQ::expansions::bitDoD << 2) | 1) - 2;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
plrs.offer_min_days = owned_expansion;
|
plrs.offer_min_days = owned_expansion;
|
||||||
}
|
}
|
||||||
// Titanium shipped with 10 expansions. Set owned expansions to be max 10.
|
// Titanium shipped with 10 expansions. Set owned expansions to be max 10.
|
||||||
plrs.web_offer_min_views = ((EQ::expansions::bitDoD << 2) | 1) - 2;
|
plrs.web_offer_min_views = ((EQ::expansions::bitDoD << 2) | 1) - 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param username
|
|
||||||
* @param password
|
|
||||||
*/
|
|
||||||
void Client::CreateLocalAccount(const std::string &username, const std::string &password)
|
|
||||||
{
|
|
||||||
auto mode = server.options.GetEncryptionMode();
|
|
||||||
auto hash = eqcrypt_hash(username, password, mode);
|
|
||||||
unsigned int db_id = 0;
|
|
||||||
if (!server.db->CreateLoginData(username, hash, "local", db_id)) {
|
|
||||||
DoFailedLogin();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
DoSuccessfulLogin(username, db_id, "local");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
std::string Client::GetClientLoggingDescription()
|
||||||
* @param in_account_name
|
|
||||||
* @param in_account_password
|
|
||||||
* @param loginserver_account_id
|
|
||||||
*/
|
|
||||||
void Client::CreateEQEmuAccount(
|
|
||||||
const std::string &in_account_name,
|
|
||||||
const std::string &in_account_password,
|
|
||||||
unsigned int loginserver_account_id
|
|
||||||
)
|
|
||||||
{
|
|
||||||
auto mode = server.options.GetEncryptionMode();
|
|
||||||
auto hash = eqcrypt_hash(in_account_name, in_account_password, mode);
|
|
||||||
|
|
||||||
if (server.db->DoesLoginServerAccountExist(in_account_name, hash, "eqemu", loginserver_account_id)) {
|
|
||||||
DoSuccessfulLogin(in_account_name, loginserver_account_id, "eqemu");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!server.db->CreateLoginDataWithID(in_account_name, hash, "eqemu", loginserver_account_id)) {
|
|
||||||
DoFailedLogin();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
DoSuccessfulLogin(in_account_name, loginserver_account_id, "eqemu");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Client::ProcessHealthCheck(std::string username)
|
|
||||||
{
|
|
||||||
if (username == "healthcheckuser") {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Client::GetClientDescription()
|
|
||||||
{
|
{
|
||||||
in_addr in{};
|
in_addr in{};
|
||||||
in.s_addr = GetConnection()->GetRemoteIP();
|
in.s_addr = GetConnection()->GetRemoteIP();
|
||||||
|
|||||||
@ -8,204 +8,60 @@
|
|||||||
#include "../common/net/dns.h"
|
#include "../common/net/dns.h"
|
||||||
#include "../common/net/daybreak_connection.h"
|
#include "../common/net/daybreak_connection.h"
|
||||||
#include "login_types.h"
|
#include "login_types.h"
|
||||||
|
#include "../common/repositories/login_accounts_repository.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
/**
|
|
||||||
* Client class, controls a single client and it's connection to the login server
|
|
||||||
*/
|
|
||||||
class Client {
|
class Client {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor, sets our connection to c and version to v
|
|
||||||
*
|
|
||||||
* @param c
|
|
||||||
* @param v
|
|
||||||
*/
|
|
||||||
Client(std::shared_ptr<EQStreamInterface> c, LSClientVersion v);
|
Client(std::shared_ptr<EQStreamInterface> c, LSClientVersion v);
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor
|
|
||||||
*/
|
|
||||||
~Client() {}
|
~Client() {}
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes the client's connection and does various actions
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool Process();
|
bool Process();
|
||||||
|
void HandleSessionReady(const char *data, unsigned int size);
|
||||||
|
void HandleLogin(const char *data, unsigned int size);
|
||||||
|
|
||||||
/**
|
// Sends the expansion data packet
|
||||||
* Sends our reply to session ready packet
|
// Titanium uses the encrypted data block to contact the expansion (You own xxx:) and the max expansions (of yyy)
|
||||||
*
|
// Rof uses a separate data packet specifically for the expansion data
|
||||||
* @param data
|
// Live, as of July 2021 uses a similar but slightly different seperate data packet
|
||||||
* @param size
|
void SendExpansionPacketData(PlayerLoginReply &plrs);
|
||||||
*/
|
void SendPlayToWorld(const char *data);
|
||||||
void Handle_SessionReady(const char *data, unsigned int size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies login and send a reply
|
|
||||||
*
|
|
||||||
* @param data
|
|
||||||
* @param size
|
|
||||||
*/
|
|
||||||
void Handle_Login(const char *data, unsigned int size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends the expansion data packet
|
|
||||||
*
|
|
||||||
* Titanium uses the encrypted data block to contact the expansion (You own xxx:) and the max expansions (of yyy)
|
|
||||||
* Rof uses a seperate data packet specifically for the expansion data
|
|
||||||
* Live, as of July 2021 uses a similar but slightly different seperate data packet
|
|
||||||
*
|
|
||||||
* @param PlayerLoginReply_Struct
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void SendExpansionPacketData(PlayerLoginReply_Struct& plrs);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a packet to the requested server to see if the client is allowed or not
|
|
||||||
*
|
|
||||||
* @param data
|
|
||||||
*/
|
|
||||||
void Handle_Play(const char *data);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a server list packet to the client
|
|
||||||
*
|
|
||||||
* @param seq
|
|
||||||
*/
|
|
||||||
void SendServerListPacket(uint32 seq);
|
void SendServerListPacket(uint32 seq);
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends the input packet to the client and clears our play response states
|
|
||||||
*
|
|
||||||
* @param outapp
|
|
||||||
*/
|
|
||||||
void SendPlayResponse(EQApplicationPacket *outapp);
|
void SendPlayResponse(EQApplicationPacket *outapp);
|
||||||
|
void GenerateRandomLoginKey();
|
||||||
/**
|
|
||||||
* Generates a random login key for the client during login
|
|
||||||
*/
|
|
||||||
void GenerateKey();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the account id of this client
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
unsigned int GetAccountID() const { return m_account_id; }
|
unsigned int GetAccountID() const { return m_account_id; }
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the loginserver name of this client
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
std::string GetLoginServerName() const { return m_loginserver_name; }
|
std::string GetLoginServerName() const { return m_loginserver_name; }
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the account name of this client
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
std::string GetAccountName() const { return m_account_name; }
|
std::string GetAccountName() const { return m_account_name; }
|
||||||
|
std::string GetClientLoggingDescription();
|
||||||
/**
|
std::string GetLoginKey() const { return m_key; }
|
||||||
* Returns a description for the client for logging
|
unsigned int GetSelectedPlayServerID() const { return m_selected_play_server_id; }
|
||||||
* @return std::string
|
unsigned int GetCurrentPlaySequence() const { return m_play_sequence_id; }
|
||||||
*/
|
|
||||||
std::string GetClientDescription();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the key generated at login for this client
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
std::string GetKey() const { return m_key; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the server selected to be played on for this client
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
unsigned int GetPlayServerID() const { return m_play_server_id; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the play sequence state for this client
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
unsigned int GetPlaySequence() const { return m_play_sequence_id; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the client version
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
LSClientVersion GetClientVersion() const { return m_client_version; }
|
LSClientVersion GetClientVersion() const { return m_client_version; }
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the connection for this client
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
std::shared_ptr<EQStreamInterface> GetConnection() { return m_connection; }
|
std::shared_ptr<EQStreamInterface> GetConnection() { return m_connection; }
|
||||||
|
|
||||||
/**
|
void AttemptLoginAccountCreation(LoginAccountContext c);
|
||||||
* Attempts to create a login account
|
void SendFailedLogin();
|
||||||
*
|
bool VerifyAndUpdateLoginHash(LoginAccountContext c, const LoginAccountsRepository::LoginAccounts& a);
|
||||||
* @param user
|
void DoSuccessfulLogin(LoginAccountsRepository::LoginAccounts& a);
|
||||||
* @param pass
|
|
||||||
* @param loginserver
|
|
||||||
*/
|
|
||||||
void AttemptLoginAccountCreation(const std::string &user, const std::string &pass, const std::string &loginserver);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does a failed login
|
|
||||||
*/
|
|
||||||
void DoFailedLogin();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies a login hash, will also attempt to update a login hash if needed
|
|
||||||
*
|
|
||||||
* @param account_username
|
|
||||||
* @param source_loginserver
|
|
||||||
* @param account_password
|
|
||||||
* @param password_hash
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool VerifyLoginHash(
|
|
||||||
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);
|
|
||||||
void CreateLocalAccount(const std::string &username, const std::string &password);
|
|
||||||
void CreateEQEmuAccount(const std::string &in_account_name, const std::string &in_account_password, unsigned int loginserver_account_id);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EQ::Random m_random;
|
EQ::Random m_random;
|
||||||
std::shared_ptr<EQStreamInterface> m_connection;
|
std::shared_ptr<EQStreamInterface> m_connection;
|
||||||
LSClientVersion m_client_version;
|
LSClientVersion m_client_version;
|
||||||
LSClientStatus m_client_status;
|
LSClientStatus m_client_status;
|
||||||
|
std::string m_account_name;
|
||||||
std::string m_account_name;
|
unsigned int m_account_id;
|
||||||
unsigned int m_account_id;
|
std::string m_loginserver_name;
|
||||||
std::string m_loginserver_name;
|
unsigned int m_selected_play_server_id;
|
||||||
unsigned int m_play_server_id;
|
unsigned int m_play_sequence_id;
|
||||||
unsigned int m_play_sequence_id;
|
std::string m_key;
|
||||||
std::string m_key;
|
|
||||||
|
|
||||||
std::unique_ptr<EQ::Net::DaybreakConnectionManager> m_login_connection_manager;
|
std::unique_ptr<EQ::Net::DaybreakConnectionManager> m_login_connection_manager;
|
||||||
std::shared_ptr<EQ::Net::DaybreakConnection> m_login_connection;
|
std::shared_ptr<EQ::Net::DaybreakConnection> m_login_connection;
|
||||||
LoginBaseMessage_Struct m_llrs;
|
LoginBaseMessage m_login_base_message;
|
||||||
|
std::string m_stored_username;
|
||||||
std::string m_stored_user;
|
std::string m_stored_password;
|
||||||
std::string m_stored_pass;
|
static bool ProcessHealthCheck(std::string username) {
|
||||||
static bool ProcessHealthCheck(std::string username);
|
return username == "healthcheckuser";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -4,12 +4,12 @@
|
|||||||
extern LoginServer server;
|
extern LoginServer server;
|
||||||
extern bool run_server;
|
extern bool run_server;
|
||||||
|
|
||||||
#include "../common/eqemu_logsys.h"
|
|
||||||
#include "../common/misc.h"
|
#include "../common/misc.h"
|
||||||
#include "../common/path_manager.h"
|
#include "../common/path_manager.h"
|
||||||
#include "../common/file.h"
|
#include "../common/file.h"
|
||||||
|
|
||||||
void CheckTitaniumOpcodeFile(const std::string &path) {
|
void CheckTitaniumOpcodeFile(const std::string &path)
|
||||||
|
{
|
||||||
if (File::Exists(path)) {
|
if (File::Exists(path)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -32,7 +32,8 @@ void CheckTitaniumOpcodeFile(const std::string &path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckSoDOpcodeFile(const std::string& path) {
|
void CheckSoDOpcodeFile(const std::string &path)
|
||||||
|
{
|
||||||
if (File::Exists(path)) {
|
if (File::Exists(path)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -56,7 +57,8 @@ void CheckSoDOpcodeFile(const std::string& path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckLarionOpcodeFile(const std::string& path) {
|
void CheckLarionOpcodeFile(const std::string &path)
|
||||||
|
{
|
||||||
if (File::Exists(path)) {
|
if (File::Exists(path)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -87,8 +89,8 @@ ClientManager::ClientManager()
|
|||||||
|
|
||||||
EQStreamManagerInterfaceOptions titanium_opts(titanium_port, false, false);
|
EQStreamManagerInterfaceOptions titanium_opts(titanium_port, false, false);
|
||||||
|
|
||||||
titanium_stream = new EQ::Net::EQStreamManager(titanium_opts);
|
m_titanium_stream = new EQ::Net::EQStreamManager(titanium_opts);
|
||||||
titanium_ops = new RegularOpcodeManager;
|
m_titanium_ops = new RegularOpcodeManager;
|
||||||
|
|
||||||
std::string opcodes_path = fmt::format(
|
std::string opcodes_path = fmt::format(
|
||||||
"{}/{}",
|
"{}/{}",
|
||||||
@ -98,34 +100,34 @@ ClientManager::ClientManager()
|
|||||||
|
|
||||||
CheckTitaniumOpcodeFile(opcodes_path);
|
CheckTitaniumOpcodeFile(opcodes_path);
|
||||||
|
|
||||||
if (!titanium_ops->LoadOpcodes(opcodes_path.c_str())) {
|
if (!m_titanium_ops->LoadOpcodes(opcodes_path.c_str())) {
|
||||||
LogError(
|
LogError(
|
||||||
"ClientManager fatal error: couldn't load opcodes for Titanium file [{0}]",
|
"ClientManager fatal error: couldn't load opcodes for Titanium file [{}]",
|
||||||
server.config.GetVariableString("client_configuration", "titanium_opcodes", "login_opcodes.conf")
|
server.config.GetVariableString("client_configuration", "titanium_opcodes", "login_opcodes.conf")
|
||||||
);
|
);
|
||||||
|
|
||||||
run_server = false;
|
run_server = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
titanium_stream->OnNewConnection(
|
m_titanium_stream->OnNewConnection(
|
||||||
[this](std::shared_ptr<EQ::Net::EQStream> stream) {
|
[this](std::shared_ptr<EQ::Net::EQStream> stream) {
|
||||||
LogInfo(
|
LogInfo(
|
||||||
"New Titanium client connection from [{0}:{1}]",
|
"New Titanium client connection from [{}:{}]",
|
||||||
long2ip(stream->GetRemoteIP()),
|
long2ip(stream->GetRemoteIP()),
|
||||||
stream->GetRemotePort()
|
stream->GetRemotePort()
|
||||||
);
|
);
|
||||||
|
|
||||||
stream->SetOpcodeManager(&titanium_ops);
|
stream->SetOpcodeManager(&m_titanium_ops);
|
||||||
Client *c = new Client(stream, cv_titanium);
|
Client *c = new Client(stream, cv_titanium);
|
||||||
clients.push_back(c);
|
m_clients.push_back(c);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
int sod_port = server.config.GetVariableInt("client_configuration", "sod_port", 5999);
|
int sod_port = server.config.GetVariableInt("client_configuration", "sod_port", 5999);
|
||||||
|
|
||||||
EQStreamManagerInterfaceOptions sod_opts(sod_port, false, false);
|
EQStreamManagerInterfaceOptions sod_opts(sod_port, false, false);
|
||||||
sod_stream = new EQ::Net::EQStreamManager(sod_opts);
|
m_sod_stream = new EQ::Net::EQStreamManager(sod_opts);
|
||||||
sod_ops = new RegularOpcodeManager;
|
m_sod_ops = new RegularOpcodeManager;
|
||||||
|
|
||||||
opcodes_path = fmt::format(
|
opcodes_path = fmt::format(
|
||||||
"{}/{}",
|
"{}/{}",
|
||||||
@ -135,26 +137,26 @@ ClientManager::ClientManager()
|
|||||||
|
|
||||||
CheckSoDOpcodeFile(opcodes_path);
|
CheckSoDOpcodeFile(opcodes_path);
|
||||||
|
|
||||||
if (!sod_ops->LoadOpcodes(opcodes_path.c_str())) {
|
if (!m_sod_ops->LoadOpcodes(opcodes_path.c_str())) {
|
||||||
LogError(
|
LogError(
|
||||||
"ClientManager fatal error: couldn't load opcodes for SoD file {0}",
|
"ClientManager fatal error: couldn't load opcodes for SoD file {}",
|
||||||
server.config.GetVariableString("client_configuration", "sod_opcodes", "login_opcodes.conf").c_str()
|
server.config.GetVariableString("client_configuration", "sod_opcodes", "login_opcodes.conf").c_str()
|
||||||
);
|
);
|
||||||
|
|
||||||
run_server = false;
|
run_server = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
sod_stream->OnNewConnection(
|
m_sod_stream->OnNewConnection(
|
||||||
[this](std::shared_ptr<EQ::Net::EQStream> stream) {
|
[this](std::shared_ptr<EQ::Net::EQStream> stream) {
|
||||||
LogInfo(
|
LogInfo(
|
||||||
"New SoD+ client connection from [{0}:{1}]",
|
"New SoD+ client connection from [{}:{}]",
|
||||||
long2ip(stream->GetRemoteIP()),
|
long2ip(stream->GetRemoteIP()),
|
||||||
stream->GetRemotePort()
|
stream->GetRemotePort()
|
||||||
);
|
);
|
||||||
|
|
||||||
stream->SetOpcodeManager(&sod_ops);
|
stream->SetOpcodeManager(&m_sod_ops);
|
||||||
auto *c = new Client(stream, cv_sod);
|
auto *c = new Client(stream, cv_sod);
|
||||||
clients.push_back(c);
|
m_clients.push_back(c);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -162,8 +164,8 @@ ClientManager::ClientManager()
|
|||||||
|
|
||||||
EQStreamManagerInterfaceOptions larion_opts(larion_port, false, false);
|
EQStreamManagerInterfaceOptions larion_opts(larion_port, false, false);
|
||||||
|
|
||||||
larion_stream = new EQ::Net::EQStreamManager(larion_opts);
|
m_larion_stream = new EQ::Net::EQStreamManager(larion_opts);
|
||||||
larion_ops = new RegularOpcodeManager;
|
m_larion_ops = new RegularOpcodeManager;
|
||||||
|
|
||||||
opcodes_path = fmt::format(
|
opcodes_path = fmt::format(
|
||||||
"{}/{}",
|
"{}/{}",
|
||||||
@ -173,115 +175,98 @@ ClientManager::ClientManager()
|
|||||||
|
|
||||||
CheckLarionOpcodeFile(opcodes_path);
|
CheckLarionOpcodeFile(opcodes_path);
|
||||||
|
|
||||||
if (!larion_ops->LoadOpcodes(opcodes_path.c_str())) {
|
if (!m_larion_ops->LoadOpcodes(opcodes_path.c_str())) {
|
||||||
LogError(
|
LogError(
|
||||||
"ClientManager fatal error: couldn't load opcodes for Larion file [{0}]",
|
"ClientManager fatal error: couldn't load opcodes for Larion file [{}]",
|
||||||
server.config.GetVariableString("client_configuration", "larion_opcodes", "login_opcodes.conf")
|
server.config.GetVariableString("client_configuration", "larion_opcodes", "login_opcodes.conf")
|
||||||
);
|
);
|
||||||
|
|
||||||
run_server = false;
|
run_server = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
larion_stream->OnNewConnection(
|
m_larion_stream->OnNewConnection(
|
||||||
[this](std::shared_ptr<EQ::Net::EQStream> stream) {
|
[this](std::shared_ptr<EQ::Net::EQStream> stream) {
|
||||||
LogInfo(
|
LogInfo(
|
||||||
"New Larion client connection from [{0}:{1}]",
|
"New Larion client connection from [{}:{}]",
|
||||||
long2ip(stream->GetRemoteIP()),
|
long2ip(stream->GetRemoteIP()),
|
||||||
stream->GetRemotePort()
|
stream->GetRemotePort()
|
||||||
);
|
);
|
||||||
|
|
||||||
stream->SetOpcodeManager(&larion_ops);
|
stream->SetOpcodeManager(&m_larion_ops);
|
||||||
Client* c = new Client(stream, cv_larion);
|
Client *c = new Client(stream, cv_larion);
|
||||||
clients.push_back(c);
|
m_clients.push_back(c);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientManager::~ClientManager()
|
ClientManager::~ClientManager() {
|
||||||
{
|
delete m_titanium_stream;
|
||||||
if (titanium_stream) {
|
delete m_titanium_ops;
|
||||||
delete titanium_stream;
|
delete m_sod_stream;
|
||||||
}
|
delete m_sod_ops;
|
||||||
|
|
||||||
if (titanium_ops) {
|
|
||||||
delete titanium_ops;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sod_stream) {
|
|
||||||
delete sod_stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sod_ops) {
|
|
||||||
delete sod_ops;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientManager::Process()
|
void ClientManager::Process()
|
||||||
{
|
{
|
||||||
ProcessDisconnect();
|
ProcessDisconnect();
|
||||||
|
|
||||||
auto iter = clients.begin();
|
m_clients.erase(
|
||||||
while (iter != clients.end()) {
|
std::remove_if(
|
||||||
if ((*iter)->Process() == false) {
|
m_clients.begin(), m_clients.end(),
|
||||||
LogWarning("Client had a fatal error and had to be removed from the login");
|
[](Client *c) {
|
||||||
delete (*iter);
|
if (!c->Process()) {
|
||||||
iter = clients.erase(iter);
|
LogWarning("Client had a fatal error and had to be removed from the login");
|
||||||
}
|
delete c;
|
||||||
else {
|
return true;
|
||||||
++iter;
|
}
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
|
),
|
||||||
|
m_clients.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientManager::ProcessDisconnect()
|
void ClientManager::ProcessDisconnect()
|
||||||
{
|
{
|
||||||
auto iter = clients.begin();
|
m_clients.erase(
|
||||||
while (iter != clients.end()) {
|
std::remove_if(
|
||||||
std::shared_ptr<EQStreamInterface> c = (*iter)->GetConnection();
|
m_clients.begin(), m_clients.end(),
|
||||||
if (c->CheckState(CLOSED)) {
|
[](Client *c) {
|
||||||
LogInfo("Client disconnected from the server, removing client");
|
if (c->GetConnection()->CheckState(CLOSED)) {
|
||||||
delete (*iter);
|
LogInfo("Client disconnected from the server, removing client");
|
||||||
iter = clients.erase(iter);
|
delete c;
|
||||||
}
|
return true;
|
||||||
else {
|
}
|
||||||
++iter;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
),
|
||||||
|
m_clients.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param account_id
|
|
||||||
* @param loginserver
|
|
||||||
*/
|
|
||||||
void ClientManager::RemoveExistingClient(unsigned int account_id, const std::string &loginserver)
|
void ClientManager::RemoveExistingClient(unsigned int account_id, const std::string &loginserver)
|
||||||
{
|
{
|
||||||
auto iter = clients.begin();
|
m_clients.erase(
|
||||||
while (iter != clients.end()) {
|
std::remove_if(
|
||||||
if ((*iter)->GetAccountID() == account_id && (*iter)->GetLoginServerName().compare(loginserver) == 0) {
|
m_clients.begin(), m_clients.end(),
|
||||||
LogInfo("Client attempting to log in existing client already logged in, removing existing client");
|
[&](Client *c) {
|
||||||
delete (*iter);
|
if (c->GetAccountID() == account_id && c->GetLoginServerName() == loginserver) {
|
||||||
iter = clients.erase(iter);
|
LogInfo("Client attempting to log in existing client already logged in, removing existing client");
|
||||||
}
|
delete c;
|
||||||
else {
|
return true;
|
||||||
++iter;
|
}
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
|
),
|
||||||
|
m_clients.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param account_id
|
|
||||||
* @param loginserver
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Client *ClientManager::GetClient(unsigned int account_id, const std::string &loginserver)
|
Client *ClientManager::GetClient(unsigned int account_id, const std::string &loginserver)
|
||||||
{
|
{
|
||||||
auto iter = clients.begin();
|
auto iter = std::find_if(
|
||||||
while (iter != clients.end()) {
|
m_clients.begin(), m_clients.end(),
|
||||||
if ((*iter)->GetAccountID() == account_id && (*iter)->GetLoginServerName().compare(loginserver) == 0) {
|
[&](Client *c) {
|
||||||
return (*iter);
|
return c->GetAccountID() == account_id && c->GetLoginServerName() == loginserver;
|
||||||
}
|
}
|
||||||
++iter;
|
);
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
return (iter != m_clients.end()) ? *iter : nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,56 +7,23 @@
|
|||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
/**
|
|
||||||
* Client manager class, holds all the client objects and does basic processing.
|
|
||||||
*/
|
|
||||||
class ClientManager {
|
class ClientManager {
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
* Constructor: sets up the stream factories and opcode managers
|
|
||||||
*/
|
|
||||||
ClientManager();
|
ClientManager();
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor: shuts down the streams and opcode managers
|
|
||||||
*/
|
|
||||||
~ClientManager();
|
~ClientManager();
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes every client in the internal list, removes them if necessary.
|
|
||||||
*/
|
|
||||||
void Process();
|
void Process();
|
||||||
|
void RemoveExistingClient(unsigned int c, const std::string &loginserver);
|
||||||
/**
|
Client *GetClient(unsigned int c, const std::string &loginserver);
|
||||||
* Removes a client with a certain account id
|
|
||||||
*
|
|
||||||
* @param account_id
|
|
||||||
* @param loginserver
|
|
||||||
*/
|
|
||||||
void RemoveExistingClient(unsigned int account_id, const std::string &loginserver);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a client (if exists) by their account id
|
|
||||||
*
|
|
||||||
* @param account_id
|
|
||||||
* @param loginserver
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Client *GetClient(unsigned int account_id, const std::string &loginserver);
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes disconnected clients, removes them if necessary
|
|
||||||
*/
|
|
||||||
void ProcessDisconnect();
|
void ProcessDisconnect();
|
||||||
|
|
||||||
std::list<Client *> clients;
|
std::list<Client *> m_clients;
|
||||||
OpcodeManager *titanium_ops;
|
OpcodeManager *m_titanium_ops;
|
||||||
EQ::Net::EQStreamManager *titanium_stream;
|
EQ::Net::EQStreamManager *m_titanium_stream;
|
||||||
OpcodeManager *sod_ops;
|
OpcodeManager *m_sod_ops;
|
||||||
EQ::Net::EQStreamManager *sod_stream;
|
EQ::Net::EQStreamManager *m_sod_stream;
|
||||||
OpcodeManager *larion_ops;
|
OpcodeManager *m_larion_ops;
|
||||||
EQ::Net::EQStreamManager* larion_stream;
|
EQ::Net::EQStreamManager *m_larion_stream;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,680 +0,0 @@
|
|||||||
#include "../common/global_define.h"
|
|
||||||
|
|
||||||
#include "database.h"
|
|
||||||
#include "login_server.h"
|
|
||||||
#include "../common/eqemu_logsys.h"
|
|
||||||
#include "../common/strings.h"
|
|
||||||
#include "../common/util/uuid.h"
|
|
||||||
|
|
||||||
extern LoginServer server;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initial connect
|
|
||||||
*
|
|
||||||
* @param user
|
|
||||||
* @param pass
|
|
||||||
* @param host
|
|
||||||
* @param port
|
|
||||||
* @param name
|
|
||||||
*/
|
|
||||||
Database::Database(
|
|
||||||
std::string user,
|
|
||||||
std::string pass,
|
|
||||||
std::string host,
|
|
||||||
std::string port,
|
|
||||||
std::string name
|
|
||||||
)
|
|
||||||
{
|
|
||||||
uint32 errnum = 0;
|
|
||||||
char errbuf[MYSQL_ERRMSG_SIZE];
|
|
||||||
if (!Open(
|
|
||||||
host.c_str(),
|
|
||||||
user.c_str(),
|
|
||||||
pass.c_str(),
|
|
||||||
name.c_str(),
|
|
||||||
Strings::ToUnsignedInt(port),
|
|
||||||
&errnum,
|
|
||||||
errbuf
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
LogError("Failed to connect to database: Error: [{0}]", errbuf);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LogInfo("Using database [{0}] at [{1}:{2}]", name, host, port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deconstructor
|
|
||||||
*/
|
|
||||||
Database::~Database()
|
|
||||||
{
|
|
||||||
if (m_database) {
|
|
||||||
mysql_close(m_database);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param name
|
|
||||||
* @param loginserver
|
|
||||||
* @param password
|
|
||||||
* @param id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool Database::GetLoginDataFromAccountInfo(
|
|
||||||
const std::string &name,
|
|
||||||
const std::string &loginserver,
|
|
||||||
std::string &password,
|
|
||||||
unsigned int &id
|
|
||||||
)
|
|
||||||
{
|
|
||||||
auto query = fmt::format(
|
|
||||||
"SELECT id, account_password FROM login_accounts WHERE account_name = '{0}' AND source_loginserver = '{1}' LIMIT 1",
|
|
||||||
Strings::Escape(name),
|
|
||||||
Strings::Escape(loginserver)
|
|
||||||
);
|
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
|
||||||
|
|
||||||
if (results.RowCount() != 1) {
|
|
||||||
LogDebug(
|
|
||||||
"Could not find account for name [{0}] login [{1}]",
|
|
||||||
name,
|
|
||||||
loginserver
|
|
||||||
);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!results.Success()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto row = results.begin();
|
|
||||||
|
|
||||||
id = Strings::ToUnsignedInt(row[0]);
|
|
||||||
password = row[1];
|
|
||||||
|
|
||||||
LogDebug(
|
|
||||||
"Found account for name [{0}] login [{1}]",
|
|
||||||
name,
|
|
||||||
loginserver
|
|
||||||
);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param token
|
|
||||||
* @param ip
|
|
||||||
* @param db_account_id
|
|
||||||
* @param db_loginserver
|
|
||||||
* @param user
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool Database::GetLoginTokenDataFromToken(
|
|
||||||
const std::string &token,
|
|
||||||
const std::string &ip,
|
|
||||||
unsigned int &db_account_id,
|
|
||||||
std::string &db_loginserver,
|
|
||||||
std::string &user
|
|
||||||
)
|
|
||||||
{
|
|
||||||
auto query = fmt::format("SELECT login_server, username, account_id FROM login_tickets WHERE expires > NOW()"
|
|
||||||
" AND id='{0}' AND ip_address='{1}' LIMIT 1",
|
|
||||||
Strings::Escape(token),
|
|
||||||
Strings::Escape(ip));
|
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
|
||||||
if (results.RowCount() == 0 || !results.Success()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
|
||||||
db_loginserver = row[0];
|
|
||||||
user = row[1];
|
|
||||||
db_account_id = Strings::ToUnsignedInt(row[2]);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param loginserver
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
unsigned int Database::GetFreeID(const std::string &loginserver)
|
|
||||||
{
|
|
||||||
auto query = fmt::format(
|
|
||||||
"SELECT IFNULL(MAX(id), 0) + 1 FROM login_accounts WHERE source_loginserver = '{0}'",
|
|
||||||
Strings::Escape(loginserver)
|
|
||||||
);
|
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
|
||||||
if (!results.Success() || results.RowCount() != 1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto row = results.begin();
|
|
||||||
|
|
||||||
return Strings::ToUnsignedInt(row[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param name
|
|
||||||
* @param password
|
|
||||||
* @param loginserver
|
|
||||||
* @param id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool Database::CreateLoginData(
|
|
||||||
const std::string &name,
|
|
||||||
const std::string &password,
|
|
||||||
const std::string &loginserver,
|
|
||||||
unsigned int &id
|
|
||||||
)
|
|
||||||
{
|
|
||||||
uint32 free_id = GetFreeID(loginserver);
|
|
||||||
id = free_id;
|
|
||||||
|
|
||||||
return CreateLoginDataWithID(name, password, loginserver, free_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param name
|
|
||||||
* @param password
|
|
||||||
* @param loginserver
|
|
||||||
* @param email
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
uint32 Database::CreateLoginAccount(
|
|
||||||
const std::string &name,
|
|
||||||
const std::string &password,
|
|
||||||
const std::string &loginserver,
|
|
||||||
const std::string &email
|
|
||||||
)
|
|
||||||
{
|
|
||||||
uint32 free_id = GetFreeID(loginserver);
|
|
||||||
|
|
||||||
if (free_id <= 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto query = fmt::format(
|
|
||||||
"INSERT INTO login_accounts (id, source_loginserver, account_name, account_password, account_email, last_login_date, last_ip_address, created_at) "
|
|
||||||
"VALUES ({0}, '{1}', '{2}', '{3}', '{4}', NOW(), '127.0.0.1', NOW())",
|
|
||||||
free_id,
|
|
||||||
Strings::Escape(loginserver),
|
|
||||||
Strings::Escape(name),
|
|
||||||
Strings::Escape(password),
|
|
||||||
Strings::Escape(email)
|
|
||||||
);
|
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
|
||||||
|
|
||||||
return (results.Success() ? free_id : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param in_account_name
|
|
||||||
* @param in_account_password
|
|
||||||
* @param loginserver
|
|
||||||
* @param id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool Database::CreateLoginDataWithID(
|
|
||||||
const std::string &in_account_name,
|
|
||||||
const std::string &in_account_password,
|
|
||||||
const std::string &loginserver,
|
|
||||||
unsigned int id
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (id == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto query = fmt::format(
|
|
||||||
"INSERT INTO login_accounts (id, source_loginserver, account_name, account_password, account_email, last_login_date, last_ip_address, created_at) "
|
|
||||||
"VALUES ({0}, '{1}', '{2}', '{3}', 'local_creation', NOW(), '127.0.0.1', NOW())",
|
|
||||||
id,
|
|
||||||
Strings::Escape(loginserver),
|
|
||||||
Strings::Escape(in_account_name),
|
|
||||||
Strings::Escape(in_account_password)
|
|
||||||
);
|
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
|
||||||
|
|
||||||
return results.Success();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param name
|
|
||||||
* @param password
|
|
||||||
* @param loginserver
|
|
||||||
* @param id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool Database::DoesLoginServerAccountExist(
|
|
||||||
const std::string &name,
|
|
||||||
const std::string &password,
|
|
||||||
const std::string &loginserver,
|
|
||||||
unsigned int id
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (id == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto query = fmt::format(
|
|
||||||
"SELECT account_name FROM login_accounts WHERE account_name = '{0}' AND source_loginserver = '{1}'",
|
|
||||||
Strings::Escape(name),
|
|
||||||
Strings::Escape(loginserver)
|
|
||||||
);
|
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
|
||||||
if (!results.Success() || results.RowCount() != 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param name
|
|
||||||
* @param loginserver
|
|
||||||
* @param hash
|
|
||||||
*/
|
|
||||||
void Database::UpdateLoginserverAccountPasswordHash(
|
|
||||||
const std::string &name,
|
|
||||||
const std::string &loginserver,
|
|
||||||
const std::string &hash
|
|
||||||
)
|
|
||||||
{
|
|
||||||
LogDebug(
|
|
||||||
"name [{0}] loginserver [{1}] hash [{2}]",
|
|
||||||
name,
|
|
||||||
loginserver,
|
|
||||||
hash
|
|
||||||
);
|
|
||||||
|
|
||||||
auto query = fmt::format(
|
|
||||||
"UPDATE login_accounts SET account_password = '{0}' WHERE account_name = '{1}' AND source_loginserver = '{2}'",
|
|
||||||
hash,
|
|
||||||
Strings::Escape(name),
|
|
||||||
Strings::Escape(loginserver)
|
|
||||||
);
|
|
||||||
|
|
||||||
QueryDatabase(query);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param short_name
|
|
||||||
* @param long_name
|
|
||||||
* @param login_world_server_admin_id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Database::DbWorldRegistration Database::GetWorldRegistration(
|
|
||||||
const std::string &short_name,
|
|
||||||
const std::string &long_name,
|
|
||||||
uint32 login_world_server_admin_id
|
|
||||||
)
|
|
||||||
{
|
|
||||||
auto query = fmt::format(
|
|
||||||
"SELECT\n"
|
|
||||||
" WSR.id,\n"
|
|
||||||
" WSR.tag_description,\n"
|
|
||||||
" WSR.is_server_trusted,\n"
|
|
||||||
" SLT.id,\n"
|
|
||||||
" SLT.description,\n"
|
|
||||||
" ifnull(WSR.login_server_admin_id, 0) AS login_server_admin_id\n"
|
|
||||||
"FROM\n"
|
|
||||||
" login_world_servers AS WSR\n"
|
|
||||||
" JOIN login_server_list_types AS SLT ON WSR.login_server_list_type_id = SLT.id\n"
|
|
||||||
"WHERE\n"
|
|
||||||
" WSR.short_name = '{}' AND WSR.long_name = '{}' AND WSR.login_server_admin_id = {} LIMIT 1",
|
|
||||||
Strings::Escape(short_name),
|
|
||||||
Strings::Escape(long_name),
|
|
||||||
login_world_server_admin_id
|
|
||||||
);
|
|
||||||
|
|
||||||
Database::DbWorldRegistration r{};
|
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
|
||||||
if (!results.Success() || results.RowCount() != 1) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto row = results.begin();
|
|
||||||
|
|
||||||
r.loaded = true;
|
|
||||||
r.server_id = Strings::ToInt(row[0]);
|
|
||||||
r.server_description = row[1];
|
|
||||||
r.server_list_type = Strings::ToInt(row[3]);
|
|
||||||
r.is_server_trusted = Strings::ToInt(row[2]) > 0;
|
|
||||||
r.server_list_description = row[4];
|
|
||||||
r.server_admin_id = Strings::ToUnsignedInt(row[5]);
|
|
||||||
|
|
||||||
if (r.server_admin_id <= 0) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto world_registration_query = fmt::format(
|
|
||||||
"SELECT account_name, account_password FROM login_server_admins WHERE id = {0} LIMIT 1",
|
|
||||||
r.server_admin_id
|
|
||||||
);
|
|
||||||
|
|
||||||
auto world_registration_results = QueryDatabase(world_registration_query);
|
|
||||||
if (world_registration_results.Success() && world_registration_results.RowCount() == 1) {
|
|
||||||
auto world_registration_row = world_registration_results.begin();
|
|
||||||
r.server_admin_account_name = world_registration_row[0];
|
|
||||||
r.server_admin_account_password = world_registration_row[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param id
|
|
||||||
* @param ip_address
|
|
||||||
*/
|
|
||||||
void Database::UpdateLSAccountData(unsigned int id, std::string ip_address)
|
|
||||||
{
|
|
||||||
auto query = fmt::format(
|
|
||||||
"UPDATE login_accounts SET last_ip_address = '{0}', last_login_date = NOW() where id = {1}",
|
|
||||||
ip_address,
|
|
||||||
id
|
|
||||||
);
|
|
||||||
|
|
||||||
QueryDatabase(query);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param id
|
|
||||||
* @param name
|
|
||||||
* @param password
|
|
||||||
* @param email
|
|
||||||
*/
|
|
||||||
void Database::UpdateLSAccountInfo(
|
|
||||||
unsigned int id,
|
|
||||||
std::string name,
|
|
||||||
std::string password,
|
|
||||||
std::string email
|
|
||||||
)
|
|
||||||
{
|
|
||||||
auto query = fmt::format(
|
|
||||||
"REPLACE login_accounts SET id = {0}, account_name = '{1}', account_password = sha('{2}'), "
|
|
||||||
"account_email = '{3}', last_ip_address = '0.0.0.0', last_login_date = now()",
|
|
||||||
id,
|
|
||||||
Strings::Escape(name),
|
|
||||||
Strings::Escape(password),
|
|
||||||
Strings::Escape(email)
|
|
||||||
);
|
|
||||||
|
|
||||||
QueryDatabase(query);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param id
|
|
||||||
* @param long_name
|
|
||||||
* @param ip_address
|
|
||||||
*/
|
|
||||||
void Database::UpdateWorldRegistration(unsigned int id, std::string long_name, std::string ip_address)
|
|
||||||
{
|
|
||||||
auto query = fmt::format(
|
|
||||||
"UPDATE login_world_servers SET last_login_date = NOW(), last_ip_address = '{0}', long_name = '{1}' WHERE id = {2}",
|
|
||||||
ip_address,
|
|
||||||
Strings::Escape(long_name),
|
|
||||||
id
|
|
||||||
);
|
|
||||||
|
|
||||||
QueryDatabase(query);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param id
|
|
||||||
* @param admin_account_password_hash
|
|
||||||
*/
|
|
||||||
bool Database::UpdateLoginWorldAdminAccountPassword(
|
|
||||||
unsigned int id,
|
|
||||||
const std::string &admin_account_password_hash
|
|
||||||
)
|
|
||||||
{
|
|
||||||
auto results = QueryDatabase(
|
|
||||||
fmt::format(
|
|
||||||
"UPDATE login_server_admins SET account_password = '{}' WHERE id = {}",
|
|
||||||
Strings::Escape(admin_account_password_hash),
|
|
||||||
id
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return results.Success();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param admin_account_username
|
|
||||||
* @param admin_account_password_hash
|
|
||||||
*/
|
|
||||||
bool Database::UpdateLoginWorldAdminAccountPasswordByUsername(
|
|
||||||
const std::string &admin_account_username,
|
|
||||||
const std::string &admin_account_password_hash
|
|
||||||
)
|
|
||||||
{
|
|
||||||
auto results = QueryDatabase(
|
|
||||||
fmt::format(
|
|
||||||
"UPDATE login_server_admins SET account_password = '{}' WHERE account_name = '{}'",
|
|
||||||
Strings::Escape(admin_account_password_hash),
|
|
||||||
Strings::Escape(admin_account_username)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return results.Success();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param server_long_name
|
|
||||||
* @param server_short_name
|
|
||||||
* @param id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool Database::CreateWorldRegistration(
|
|
||||||
std::string server_long_name,
|
|
||||||
std::string server_short_name,
|
|
||||||
std::string server_remote_ip,
|
|
||||||
unsigned int &id,
|
|
||||||
unsigned int &server_admin_id
|
|
||||||
)
|
|
||||||
{
|
|
||||||
auto results = QueryDatabase("SELECT IFNULL(max(id), 0) + 1 FROM login_world_servers");
|
|
||||||
if (!results.Success() || results.RowCount() != 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto row = results.begin();
|
|
||||||
|
|
||||||
id = Strings::ToUnsignedInt(row[0]);
|
|
||||||
auto insert_query = fmt::format(
|
|
||||||
"INSERT INTO login_world_servers SET id = {0}, long_name = '{1}', short_name = '{2}', last_ip_address = '{3}', \n"
|
|
||||||
"login_server_list_type_id = 3, login_server_admin_id = {4}, is_server_trusted = 0, tag_description = ''",
|
|
||||||
id,
|
|
||||||
Strings::Escape(server_long_name),
|
|
||||||
Strings::Escape(server_short_name),
|
|
||||||
server_remote_ip,
|
|
||||||
server_admin_id
|
|
||||||
);
|
|
||||||
|
|
||||||
auto insert_results = QueryDatabase(insert_query);
|
|
||||||
if (!insert_results.Success()) {
|
|
||||||
LogError(
|
|
||||||
"Failed to register world server {0} - {1}",
|
|
||||||
server_long_name,
|
|
||||||
server_short_name
|
|
||||||
);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param long_name
|
|
||||||
* @param short_name
|
|
||||||
* @param id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
std::string Database::CreateLoginserverApiToken(
|
|
||||||
bool write_mode,
|
|
||||||
bool read_mode
|
|
||||||
)
|
|
||||||
{
|
|
||||||
std::string token = EQ::Util::UUID::Generate().ToString();
|
|
||||||
auto query = fmt::format(
|
|
||||||
"INSERT INTO login_api_tokens (token, can_write, can_read, created_at) VALUES ('{0}', {1}, {2}, NOW())",
|
|
||||||
token,
|
|
||||||
(write_mode ? "1" : "0"),
|
|
||||||
(read_mode ? "1" : "0")
|
|
||||||
);
|
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
|
||||||
if (!results.Success()) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param long_name
|
|
||||||
* @param short_name
|
|
||||||
* @param id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
MySQLRequestResult Database::GetLoginserverApiTokens()
|
|
||||||
{
|
|
||||||
return QueryDatabase("SELECT token, can_write, can_read FROM login_api_tokens");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param account_name
|
|
||||||
* @param account_password
|
|
||||||
* @param first_name
|
|
||||||
* @param last_name
|
|
||||||
* @param email
|
|
||||||
* @param ip_address
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
uint32 Database::CreateLoginserverWorldAdminAccount(
|
|
||||||
const std::string &account_name,
|
|
||||||
const std::string &account_password,
|
|
||||||
const std::string &first_name,
|
|
||||||
const std::string &last_name,
|
|
||||||
const std::string &email,
|
|
||||||
const std::string &ip_address
|
|
||||||
)
|
|
||||||
{
|
|
||||||
auto query = fmt::format(
|
|
||||||
"INSERT INTO login_server_admins (account_name, account_password, first_name, last_name, email, registration_date, "
|
|
||||||
"registration_ip_address) "
|
|
||||||
"VALUES ('{0}', '{1}', '{2}', '{3}', '{4}', NOW(), '{5}')",
|
|
||||||
Strings::Escape(account_name),
|
|
||||||
Strings::Escape(account_password),
|
|
||||||
Strings::Escape(first_name),
|
|
||||||
Strings::Escape(last_name),
|
|
||||||
Strings::Escape(email),
|
|
||||||
ip_address
|
|
||||||
);
|
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
|
||||||
|
|
||||||
return (results.Success() ? results.LastInsertedID() : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param account_name
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool Database::DoesLoginserverWorldAdminAccountExist(
|
|
||||||
const std::string &account_name
|
|
||||||
)
|
|
||||||
{
|
|
||||||
auto query = fmt::format(
|
|
||||||
"SELECT account_name FROM login_server_admins WHERE account_name = '{0}' LIMIT 1",
|
|
||||||
Strings::Escape(account_name)
|
|
||||||
);
|
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
|
||||||
|
|
||||||
return (results.RowCount() == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param account_name
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Database::DbLoginServerAdmin Database::GetLoginServerAdmin(const std::string &account_name)
|
|
||||||
{
|
|
||||||
auto query = fmt::format(
|
|
||||||
"SELECT id, account_name, account_password, first_name, last_name, email, registration_date, registration_ip_address"
|
|
||||||
" FROM login_server_admins WHERE account_name = '{0}' LIMIT 1",
|
|
||||||
Strings::Escape(account_name)
|
|
||||||
);
|
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
|
||||||
|
|
||||||
Database::DbLoginServerAdmin r{};
|
|
||||||
if (results.RowCount() == 1) {
|
|
||||||
auto row = results.begin();
|
|
||||||
r.loaded = true;
|
|
||||||
r.id = Strings::ToUnsignedInt(row[0]);
|
|
||||||
r.account_name = row[1];
|
|
||||||
r.account_password = row[2];
|
|
||||||
r.first_name = row[3];
|
|
||||||
r.last_name = row[4];
|
|
||||||
r.email = row[5];
|
|
||||||
r.registration_date = row[7];
|
|
||||||
r.registration_ip_address = row[8];
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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",
|
|
||||||
Strings::Escape(account_name),
|
|
||||||
Strings::Escape(source_loginserver)
|
|
||||||
);
|
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
|
||||||
|
|
||||||
Database::DbLoginServerAccount r{};
|
|
||||||
if (results.RowCount() == 1) {
|
|
||||||
auto row = results.begin();
|
|
||||||
r.loaded = true;
|
|
||||||
r.id = Strings::ToUnsignedInt(row[0]);
|
|
||||||
r.account_name = row[1];
|
|
||||||
r.account_password = row[2];
|
|
||||||
r.account_email = row[3];
|
|
||||||
r.source_loginserver = row[4];
|
|
||||||
r.last_ip_address = row[5];
|
|
||||||
r.last_login_date = row[6];
|
|
||||||
r.created_at = row[7];
|
|
||||||
r.updated_at = row[8];
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
@ -1,286 +0,0 @@
|
|||||||
#ifndef EQEMU_DATABASEMYSQL_H
|
|
||||||
#define EQEMU_DATABASEMYSQL_H
|
|
||||||
|
|
||||||
#include "../common/dbcore.h"
|
|
||||||
#include "../common/eqemu_logsys.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <mysql.h>
|
|
||||||
|
|
||||||
class Database : public DBcore {
|
|
||||||
public:
|
|
||||||
|
|
||||||
Database() { m_database = nullptr; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor, tries to set our database to connect to the supplied options.
|
|
||||||
*
|
|
||||||
* @param user
|
|
||||||
* @param pass
|
|
||||||
* @param host
|
|
||||||
* @param port
|
|
||||||
* @param name
|
|
||||||
*/
|
|
||||||
Database(std::string user, std::string pass, std::string host, std::string port, std::string name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor, frees our database if needed.
|
|
||||||
*/
|
|
||||||
~Database();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the login data (password hash and account id) from the account name provided needed for client login procedure.
|
|
||||||
* @param name
|
|
||||||
* @param loginserver
|
|
||||||
* @param password
|
|
||||||
* @param id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool GetLoginDataFromAccountInfo(
|
|
||||||
const std::string &name,
|
|
||||||
const std::string &loginserver,
|
|
||||||
std::string &password,
|
|
||||||
unsigned int &id
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param token
|
|
||||||
* @param ip
|
|
||||||
* @param db_account_id
|
|
||||||
* @param db_loginserver
|
|
||||||
* @param user
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool GetLoginTokenDataFromToken(
|
|
||||||
const std::string &token,
|
|
||||||
const std::string &ip,
|
|
||||||
unsigned int &db_account_id,
|
|
||||||
std::string &db_loginserver,
|
|
||||||
std::string &user
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param loginserver
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
unsigned int GetFreeID(const std::string &loginserver);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param name
|
|
||||||
* @param password
|
|
||||||
* @param loginserver
|
|
||||||
* @param id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool CreateLoginData(
|
|
||||||
const std::string &name,
|
|
||||||
const std::string &password,
|
|
||||||
const std::string &loginserver,
|
|
||||||
unsigned int &id
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param in_account_name
|
|
||||||
* @param in_account_password
|
|
||||||
* @param loginserver
|
|
||||||
* @param id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool CreateLoginDataWithID(
|
|
||||||
const std::string &in_account_name,
|
|
||||||
const std::string &in_account_password,
|
|
||||||
const std::string &loginserver,
|
|
||||||
unsigned int id
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param name
|
|
||||||
* @param loginserver
|
|
||||||
* @param hash
|
|
||||||
*/
|
|
||||||
void UpdateLoginserverAccountPasswordHash(
|
|
||||||
const std::string &name,
|
|
||||||
const std::string &loginserver,
|
|
||||||
const std::string &hash);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param name
|
|
||||||
* @param password
|
|
||||||
* @param loginserver
|
|
||||||
* @param id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool DoesLoginServerAccountExist(
|
|
||||||
const std::string &name,
|
|
||||||
const std::string &password,
|
|
||||||
const std::string &loginserver,
|
|
||||||
unsigned int id
|
|
||||||
);
|
|
||||||
|
|
||||||
struct DbWorldRegistration {
|
|
||||||
bool loaded = false;
|
|
||||||
int32 server_id = 0;
|
|
||||||
int8 server_list_type = 3;
|
|
||||||
bool is_server_trusted = false;
|
|
||||||
std::string server_description;
|
|
||||||
std::string server_list_description;
|
|
||||||
std::string server_admin_account_name;
|
|
||||||
std::string server_admin_account_password;
|
|
||||||
uint32 server_admin_id;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the world registration from the long and short names provided
|
|
||||||
* Needed for world login procedure
|
|
||||||
* Returns true if the record was found, false otherwise
|
|
||||||
*
|
|
||||||
* @param short_name
|
|
||||||
* @param long_name
|
|
||||||
* @param login_world_server_admin_id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
Database::DbWorldRegistration GetWorldRegistration(
|
|
||||||
const std::string &short_name,
|
|
||||||
const std::string &long_name,
|
|
||||||
uint32 login_world_server_admin_id
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param id
|
|
||||||
* @param ip_address
|
|
||||||
*/
|
|
||||||
void UpdateLSAccountData(unsigned int id, std::string ip_address);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param id
|
|
||||||
* @param name
|
|
||||||
* @param password
|
|
||||||
* @param email
|
|
||||||
*/
|
|
||||||
void UpdateLSAccountInfo(unsigned int id, std::string name, std::string password, std::string email);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param id
|
|
||||||
* @param long_name
|
|
||||||
* @param ip_address
|
|
||||||
*/
|
|
||||||
void UpdateWorldRegistration(unsigned int id, std::string long_name, std::string ip_address);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param server_long_name
|
|
||||||
* @param server_short_name
|
|
||||||
* @param id
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool CreateWorldRegistration(
|
|
||||||
std::string server_long_name,
|
|
||||||
std::string server_short_name,
|
|
||||||
std::string server_remote_ip,
|
|
||||||
unsigned int &id,
|
|
||||||
unsigned int &server_admin_id
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param write_mode
|
|
||||||
* @param read_mode
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
std::string CreateLoginserverApiToken(bool write_mode, bool read_mode);
|
|
||||||
MySQLRequestResult GetLoginserverApiTokens();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param account_name
|
|
||||||
* @param account_password
|
|
||||||
* @param first_name
|
|
||||||
* @param last_name
|
|
||||||
* @param email
|
|
||||||
* @param ip_address
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
uint32 CreateLoginserverWorldAdminAccount(
|
|
||||||
const std::string &account_name,
|
|
||||||
const std::string &account_password,
|
|
||||||
const std::string &first_name,
|
|
||||||
const std::string &last_name,
|
|
||||||
const std::string &email,
|
|
||||||
const std::string &ip_address
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param account_name
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool DoesLoginserverWorldAdminAccountExist(const std::string &account_name);
|
|
||||||
|
|
||||||
struct DbLoginServerAdmin {
|
|
||||||
bool loaded = false;
|
|
||||||
uint32 id;
|
|
||||||
std::string account_name;
|
|
||||||
std::string account_password;
|
|
||||||
std::string first_name;
|
|
||||||
std::string last_name;
|
|
||||||
std::string email;
|
|
||||||
std::string registration_date;
|
|
||||||
std::string registration_ip_address;
|
|
||||||
};
|
|
||||||
|
|
||||||
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 id
|
|
||||||
* @param admin_account_password_hash
|
|
||||||
*/
|
|
||||||
bool UpdateLoginWorldAdminAccountPassword(
|
|
||||||
unsigned int id,
|
|
||||||
const std::string& admin_account_password_hash
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param admin_account_username
|
|
||||||
* @param admin_account_password_hash
|
|
||||||
*/
|
|
||||||
bool UpdateLoginWorldAdminAccountPasswordByUsername(
|
|
||||||
const std::string &admin_account_username,
|
|
||||||
const std::string &admin_account_password_hash
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param name
|
|
||||||
* @param password
|
|
||||||
* @param loginserver
|
|
||||||
* @param email
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
uint32 CreateLoginAccount(
|
|
||||||
const std::string &name,
|
|
||||||
const std::string &password,
|
|
||||||
const std::string &loginserver = "local",
|
|
||||||
const std::string &email = "local_creation"
|
|
||||||
);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
MYSQL *m_database{};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@ -21,10 +21,6 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mode
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
std::string GetEncryptionByModeId(uint32 mode)
|
std::string GetEncryptionByModeId(uint32 mode)
|
||||||
{
|
{
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
@ -61,13 +57,6 @@ std::string GetEncryptionByModeId(uint32 mode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param buffer_in
|
|
||||||
* @param buffer_in_sz
|
|
||||||
* @param buffer_out
|
|
||||||
* @param enc
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
const char *eqcrypt_block(const char *buffer_in, size_t buffer_in_sz, char *buffer_out, bool enc)
|
const char *eqcrypt_block(const char *buffer_in, size_t buffer_in_sz, char *buffer_out, bool enc)
|
||||||
{
|
{
|
||||||
#ifdef EQEMU_USE_MBEDTLS
|
#ifdef EQEMU_USE_MBEDTLS
|
||||||
@ -113,7 +102,7 @@ const char *eqcrypt_block(const char *buffer_in, size_t buffer_in_sz, char *buff
|
|||||||
unsigned char iv[8];
|
unsigned char iv[8];
|
||||||
memset(&key, 0, MBEDTLS_DES_KEY_SIZE);
|
memset(&key, 0, MBEDTLS_DES_KEY_SIZE);
|
||||||
memset(&iv, 0, 8);
|
memset(&iv, 0, 8);
|
||||||
|
|
||||||
mbedtls_des_context context;
|
mbedtls_des_context context;
|
||||||
mbedtls_des_setkey_dec(&context, key);
|
mbedtls_des_setkey_dec(&context, key);
|
||||||
mbedtls_des_crypt_cbc(&context, MBEDTLS_DES_DECRYPT, buffer_in_sz, iv, (const unsigned char*)buffer_in, (unsigned char*)buffer_out);
|
mbedtls_des_crypt_cbc(&context, MBEDTLS_DES_DECRYPT, buffer_in_sz, iv, (const unsigned char*)buffer_in, (unsigned char*)buffer_out);
|
||||||
@ -123,23 +112,19 @@ const char *eqcrypt_block(const char *buffer_in, size_t buffer_in_sz, char *buff
|
|||||||
#ifdef EQEMU_USE_OPENSSL
|
#ifdef EQEMU_USE_OPENSSL
|
||||||
DES_key_schedule k;
|
DES_key_schedule k;
|
||||||
DES_cblock v;
|
DES_cblock v;
|
||||||
|
|
||||||
memset(&k, 0, sizeof(DES_key_schedule));
|
memset(&k, 0, sizeof(DES_key_schedule));
|
||||||
memset(&v, 0, sizeof(DES_cblock));
|
memset(&v, 0, sizeof(DES_cblock));
|
||||||
|
|
||||||
if (!enc && buffer_in_sz && buffer_in_sz % 8 != 0) {
|
if (!enc && buffer_in_sz && buffer_in_sz % 8 != 0) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
DES_ncbc_encrypt((const unsigned char*)buffer_in, (unsigned char*)buffer_out, (long)buffer_in_sz, &k, &v, enc);
|
DES_ncbc_encrypt((const unsigned char*)buffer_in, (unsigned char*)buffer_out, (long)buffer_in_sz, &k, &v, enc);
|
||||||
#endif
|
#endif
|
||||||
return buffer_out;
|
return buffer_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param msg
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
std::string eqcrypt_md5(const std::string &msg)
|
std::string eqcrypt_md5(const std::string &msg)
|
||||||
{
|
{
|
||||||
std::string ret;
|
std::string ret;
|
||||||
@ -174,10 +159,6 @@ std::string eqcrypt_md5(const std::string &msg)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param msg
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
std::string eqcrypt_sha1(const std::string &msg)
|
std::string eqcrypt_sha1(const std::string &msg)
|
||||||
{
|
{
|
||||||
std::string ret;
|
std::string ret;
|
||||||
@ -212,10 +193,6 @@ std::string eqcrypt_sha1(const std::string &msg)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param msg
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
std::string eqcrypt_sha512(const std::string &msg)
|
std::string eqcrypt_sha512(const std::string &msg)
|
||||||
{
|
{
|
||||||
std::string ret;
|
std::string ret;
|
||||||
@ -252,10 +229,6 @@ std::string eqcrypt_sha512(const std::string &msg)
|
|||||||
|
|
||||||
#ifdef ENABLE_SECURITY
|
#ifdef ENABLE_SECURITY
|
||||||
|
|
||||||
/**
|
|
||||||
* @param msg
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
std::string eqcrypt_argon2(const std::string &msg)
|
std::string eqcrypt_argon2(const std::string &msg)
|
||||||
{
|
{
|
||||||
char buffer[crypto_pwhash_STRBYTES] = {0};
|
char buffer[crypto_pwhash_STRBYTES] = {0};
|
||||||
@ -275,10 +248,6 @@ std::string eqcrypt_argon2(const std::string &msg)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param msg
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
std::string eqcrypt_scrypt(const std::string &msg)
|
std::string eqcrypt_scrypt(const std::string &msg)
|
||||||
{
|
{
|
||||||
char buffer[crypto_pwhash_scryptsalsa208sha256_STRBYTES] = {0};
|
char buffer[crypto_pwhash_scryptsalsa208sha256_STRBYTES] = {0};
|
||||||
@ -300,12 +269,6 @@ std::string eqcrypt_scrypt(const std::string &msg)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* @param username
|
|
||||||
* @param password
|
|
||||||
* @param mode
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
std::string eqcrypt_hash(const std::string &username, const std::string &password, int mode)
|
std::string eqcrypt_hash(const std::string &username, const std::string &password, int mode)
|
||||||
{
|
{
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
@ -346,13 +309,6 @@ std::string eqcrypt_hash(const std::string &username, const std::string &passwor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param username
|
|
||||||
* @param password
|
|
||||||
* @param pwhash
|
|
||||||
* @param mode
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool eqcrypt_verify_hash(const std::string &username, const std::string &password, const std::string &pwhash, int mode)
|
bool eqcrypt_verify_hash(const std::string &username, const std::string &password, const std::string &pwhash, int mode)
|
||||||
{
|
{
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
|
|||||||
@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "../common/types.h"
|
#include "../common/types.h"
|
||||||
|
#include "login_types.h"
|
||||||
|
#include "../common/eqemu_logsys.h"
|
||||||
|
#include "../common/strings.h"
|
||||||
|
|
||||||
enum EncryptionMode {
|
enum EncryptionMode {
|
||||||
EncryptionModeMD5 = 1,
|
EncryptionModeMD5 = 1,
|
||||||
@ -26,11 +29,34 @@ namespace CryptoHash {
|
|||||||
const int sha512_hash_length = 128;
|
const int sha512_hash_length = 128;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mode
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
std::string GetEncryptionByModeId(uint32 mode);
|
std::string GetEncryptionByModeId(uint32 mode);
|
||||||
const char *eqcrypt_block(const char *buffer_in, size_t buffer_in_sz, char *buffer_out, bool enc);
|
const char *eqcrypt_block(const char *buffer_in, size_t buffer_in_sz, char *buffer_out, bool enc);
|
||||||
std::string eqcrypt_hash(const std::string &username, const std::string &password, int mode);
|
std::string eqcrypt_hash(const std::string &username, const std::string &password, int mode);
|
||||||
bool eqcrypt_verify_hash(const std::string &username, const std::string &password, const std::string &pwhash, int mode);
|
bool eqcrypt_verify_hash(const std::string &username, const std::string &password, const std::string &pwhash, int mode);
|
||||||
|
|
||||||
|
struct EncryptionResult {
|
||||||
|
std::string password;
|
||||||
|
int mode = 0;
|
||||||
|
std::string mode_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
static EncryptionResult EncryptPasswordFromContext(LoginAccountContext c, int mode = EncryptionModeSCrypt)
|
||||||
|
{
|
||||||
|
if (mode == 0) {
|
||||||
|
LogError("Encryption mode not set!");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
EncryptionResult r;
|
||||||
|
r.password = eqcrypt_hash(
|
||||||
|
c.username,
|
||||||
|
c.password,
|
||||||
|
mode
|
||||||
|
);
|
||||||
|
r.mode = mode;
|
||||||
|
r.mode_name = GetEncryptionByModeId(r.mode);
|
||||||
|
|
||||||
|
LogInfo("Encrypted password for user [{}] using mode [{}] ({})", c.username, r.mode_name, r.mode);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|||||||
@ -3,29 +3,24 @@
|
|||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include "../common/json_config.h"
|
#include "../common/json_config.h"
|
||||||
#include "database.h"
|
|
||||||
#include "encryption.h"
|
#include "encryption.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "server_manager.h"
|
#include "world_server_manager.h"
|
||||||
#include "client_manager.h"
|
#include "client_manager.h"
|
||||||
#include "loginserver_webserver.h"
|
#include "loginserver_webserver.h"
|
||||||
|
|
||||||
/**
|
struct LoginServer {
|
||||||
* Login server struct, Contains every variable for the server that needs to exist outside the scope of main()
|
|
||||||
*/
|
|
||||||
struct LoginServer
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
LoginServer() : db(nullptr), server_manager(nullptr) {
|
LoginServer() : server_manager(nullptr)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EQ::JsonConfigFile config;
|
EQ::JsonConfigFile config;
|
||||||
Database *db;
|
|
||||||
LoginserverWebserver::TokenManager *token_manager{};
|
LoginserverWebserver::TokenManager *token_manager{};
|
||||||
Options options;
|
Options options;
|
||||||
ServerManager *server_manager;
|
WorldServerManager *server_manager;
|
||||||
ClientManager *client_manager{};
|
ClientManager *client_manager{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -4,30 +4,30 @@
|
|||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
|
|
||||||
// unencrypted base message header in all packets
|
// unencrypted base message header in all packets
|
||||||
struct LoginBaseMessage_Struct {
|
struct LoginBaseMessage {
|
||||||
int32_t sequence; // request type/login sequence (2: handshake, 3: login, 4: serverlist, ...)
|
int32_t sequence; // request type/login sequence (2: handshake, 3: login, 4: serverlist, ...)
|
||||||
bool compressed; // true: deflated
|
bool compressed; // true: deflated
|
||||||
int8_t encrypt_type; // 1: invert (unused) 2: des (2 for encrypted player logins and order expansions) (client uses what it sent, ignores in reply)
|
int8_t encrypt_type; // 1: invert (unused) 2: des (2 for encrypted player logins and order expansions) (client uses what it sent, ignores in reply)
|
||||||
int32_t unk3; // unused?
|
int32_t unk3; // unused?
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LoginBaseReplyMessage_Struct {
|
struct LoginBaseReplyMessage {
|
||||||
bool success; // 0: failure (shows error string) 1: success
|
bool success; // 0: failure (shows error string) 1: success
|
||||||
int32_t error_str_id; // last error eqlsstr id, default: 101 (no error)
|
int32_t error_str_id; // last error eqlsstr id, default: 101 (no error)
|
||||||
char str[1]; // variable length, unknown (may be unused, this struct is a common pattern elsewhere)
|
char str[1]; // variable length, unknown (may be unused, this struct is a common pattern elsewhere)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LoginHandShakeReply_Struct {
|
struct LoginHandShakeReply {
|
||||||
LoginBaseMessage_Struct base_header;
|
LoginBaseMessage base_header;
|
||||||
LoginBaseReplyMessage_Struct base_reply;
|
LoginBaseReplyMessage base_reply;
|
||||||
char unknown[1]; // variable length string
|
char unknown[1]; // variable length string
|
||||||
};
|
};
|
||||||
|
|
||||||
// variable length, can use directly if not serializing strings
|
// variable length, can use directly if not serializing strings
|
||||||
struct PlayerLoginReply_Struct {
|
struct PlayerLoginReply {
|
||||||
// base header excluded to make struct data easier to encrypt
|
// base header excluded to make struct data easier to encrypt
|
||||||
//LoginBaseMessage_Struct base_header;
|
//LoginBaseMessage base_header;
|
||||||
LoginBaseReplyMessage_Struct base_reply;
|
LoginBaseReplyMessage base_reply;
|
||||||
|
|
||||||
int8_t unk1; // (default: 0)
|
int8_t unk1; // (default: 0)
|
||||||
int8_t unk2; // (default: 0)
|
int8_t unk2; // (default: 0)
|
||||||
@ -47,7 +47,7 @@ struct PlayerLoginReply_Struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// variable length, for reference
|
// variable length, for reference
|
||||||
struct LoginClientServerData_Struct {
|
struct LoginClientServerData {
|
||||||
char ip[1];
|
char ip[1];
|
||||||
int32_t server_type; // legends, preferred, standard
|
int32_t server_type; // legends, preferred, standard
|
||||||
int32_t server_id;
|
int32_t server_id;
|
||||||
@ -59,24 +59,24 @@ struct LoginClientServerData_Struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// variable length, for reference
|
// variable length, for reference
|
||||||
struct ServerListReply_Struct {
|
struct ServerListReply {
|
||||||
LoginBaseMessage_Struct base_header;
|
LoginBaseMessage base_header;
|
||||||
LoginBaseReplyMessage_Struct base_reply;
|
LoginBaseReplyMessage base_reply;
|
||||||
|
|
||||||
int32_t server_count;
|
int32_t server_count;
|
||||||
LoginClientServerData_Struct servers[0];
|
LoginClientServerData servers[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PlayEverquestRequest_Struct {
|
struct PlayEverquestRequest {
|
||||||
LoginBaseMessage_Struct base_header;
|
LoginBaseMessage base_header;
|
||||||
uint32 server_number;
|
uint32 server_number;
|
||||||
};
|
};
|
||||||
|
|
||||||
// SCJoinServerReply
|
// SCJoinServerReply
|
||||||
struct PlayEverquestResponse_Struct {
|
struct PlayEverquestResponse {
|
||||||
LoginBaseMessage_Struct base_header;
|
LoginBaseMessage base_header;
|
||||||
LoginBaseReplyMessage_Struct base_reply;
|
LoginBaseReplyMessage base_reply;
|
||||||
uint32 server_number;
|
uint32 server_number;
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
@ -95,6 +95,34 @@ enum LSClientStatus {
|
|||||||
cs_logged_in
|
cs_logged_in
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LoginWorldContext {
|
||||||
|
std::string long_name;
|
||||||
|
std::string short_name;
|
||||||
|
std::string password;
|
||||||
|
std::string password_hash;
|
||||||
|
int64 admin_id = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LoginWorldAdminAccountContext {
|
||||||
|
int64 id;
|
||||||
|
std::string username;
|
||||||
|
std::string password;
|
||||||
|
std::string password_hash;
|
||||||
|
std::string email;
|
||||||
|
std::string first_name;
|
||||||
|
std::string last_name;
|
||||||
|
std::string ip_address;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LoginAccountContext {
|
||||||
|
std::string username;
|
||||||
|
std::string password;
|
||||||
|
std::string email;
|
||||||
|
std::string source_loginserver = "local";
|
||||||
|
uint32 login_account_id = 0;
|
||||||
|
bool password_is_encrypted = false;
|
||||||
|
};
|
||||||
|
|
||||||
namespace LS {
|
namespace LS {
|
||||||
namespace ServerStatusFlags {
|
namespace ServerStatusFlags {
|
||||||
enum eServerStatusFlags {
|
enum eServerStatusFlags {
|
||||||
@ -123,13 +151,13 @@ namespace LS {
|
|||||||
};
|
};
|
||||||
|
|
||||||
namespace ErrStr {
|
namespace ErrStr {
|
||||||
constexpr static int ERROR_NONE = 101; // No Error
|
constexpr static int ERROR_NONE = 101; // No Error
|
||||||
constexpr static int ERROR_UNKNOWN = 102; // Error - Unknown Error Occurred
|
constexpr static int ERROR_UNKNOWN = 102; // Error - Unknown Error Occurred
|
||||||
constexpr static int ERROR_ACTIVE_CHARACTER = 111; // Error 1018: You currently have an active character on that EverQuest Server, please allow a minute for synchronization and try again.
|
constexpr static int ERROR_ACTIVE_CHARACTER = 111; // Error 1018: You currently have an active character on that EverQuest Server, please allow a minute for synchronization and try again.
|
||||||
constexpr static int ERROR_SERVER_UNAVAILABLE = 326; // That server is currently unavailable. Please check the EverQuest webpage for current server status and try again later.
|
constexpr static int ERROR_SERVER_UNAVAILABLE = 326; // That server is currently unavailable. Please check the EverQuest webpage for current server status and try again later.
|
||||||
constexpr static int ERROR_ACCOUNT_SUSPENDED = 337; // This account is currently suspended. Please contact customer service for more information.
|
constexpr static int ERROR_ACCOUNT_SUSPENDED = 337; // This account is currently suspended. Please contact customer service for more information.
|
||||||
constexpr static int ERROR_ACCOUNT_BANNED = 338; // This account is currently banned. Please contact customer service for more information.
|
constexpr static int ERROR_ACCOUNT_BANNED = 338; // This account is currently banned. Please contact customer service for more information.
|
||||||
constexpr static int ERROR_WORLD_MAX_CAPACITY = 339; // The world server is currently at maximum capacity and not allowing further logins until the number of players online decreases. Please try again later.
|
constexpr static int ERROR_WORLD_MAX_CAPACITY = 339; // The world server is currently at maximum capacity and not allowing further logins until the number of players online decreases. Please try again later.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -33,10 +33,6 @@ CREATE TABLE `login_server_list_types` (
|
|||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||||
|
|
||||||
INSERT INTO `login_server_list_types` (`id`, `description`) VALUES ('1', 'Legends'),
|
|
||||||
('2', 'Preferred'),
|
|
||||||
('3', 'Standard');
|
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `login_world_servers`;
|
DROP TABLE IF EXISTS `login_world_servers`;
|
||||||
CREATE TABLE `login_world_servers` (
|
CREATE TABLE `login_world_servers` (
|
||||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
|||||||
@ -5,15 +5,11 @@
|
|||||||
#include "login_server.h"
|
#include "login_server.h"
|
||||||
#include "loginserver_webserver.h"
|
#include "loginserver_webserver.h"
|
||||||
#include "account_management.h"
|
#include "account_management.h"
|
||||||
|
#include "../common/repositories/login_api_tokens_repository.h"
|
||||||
|
|
||||||
extern LoginServer server;
|
extern LoginServer server;
|
||||||
|
|
||||||
namespace LoginserverCommandHandler {
|
namespace LoginserverCommandHandler {
|
||||||
|
|
||||||
/**
|
|
||||||
* @param argc
|
|
||||||
* @param argv
|
|
||||||
*/
|
|
||||||
void CommandHandler(int argc, char **argv)
|
void CommandHandler(int argc, char **argv)
|
||||||
{
|
{
|
||||||
if (argc == 1) { return; }
|
if (argc == 1) { return; }
|
||||||
@ -22,14 +18,7 @@ namespace LoginserverCommandHandler {
|
|||||||
cmd.parse(argc, argv, argh::parser::PREFER_PARAM_FOR_UNREG_OPTION);
|
cmd.parse(argc, argv, argh::parser::PREFER_PARAM_FOR_UNREG_OPTION);
|
||||||
EQEmuCommand::DisplayDebug(cmd);
|
EQEmuCommand::DisplayDebug(cmd);
|
||||||
|
|
||||||
/**
|
|
||||||
* Declare command mapping
|
|
||||||
*/
|
|
||||||
auto function_map = EQEmuCommand::function_map;
|
auto function_map = EQEmuCommand::function_map;
|
||||||
|
|
||||||
/**
|
|
||||||
* Register commands
|
|
||||||
*/
|
|
||||||
function_map["login-user:check-credentials"] = &LoginserverCommandHandler::CheckLoginserverUserCredentials;
|
function_map["login-user:check-credentials"] = &LoginserverCommandHandler::CheckLoginserverUserCredentials;
|
||||||
function_map["login-user:check-external-credentials"] = &LoginserverCommandHandler::CheckExternalLoginserverUserCredentials;
|
function_map["login-user:check-external-credentials"] = &LoginserverCommandHandler::CheckExternalLoginserverUserCredentials;
|
||||||
function_map["login-user:create"] = &LoginserverCommandHandler::CreateLocalLoginserverAccount;
|
function_map["login-user:create"] = &LoginserverCommandHandler::CreateLocalLoginserverAccount;
|
||||||
@ -43,12 +32,6 @@ namespace LoginserverCommandHandler {
|
|||||||
EQEmuCommand::HandleMenu(function_map, cmd, argc, argv);
|
EQEmuCommand::HandleMenu(function_map, cmd, argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param argc
|
|
||||||
* @param argv
|
|
||||||
* @param cmd
|
|
||||||
* @param description
|
|
||||||
*/
|
|
||||||
void CreateLoginserverApiToken(int argc, char **argv, argh::parser &cmd, std::string &description)
|
void CreateLoginserverApiToken(int argc, char **argv, argh::parser &cmd, std::string &description)
|
||||||
{
|
{
|
||||||
description = "Creates Loginserver API Token";
|
description = "Creates Loginserver API Token";
|
||||||
@ -69,22 +52,22 @@ namespace LoginserverCommandHandler {
|
|||||||
bool can_write = cmd[{"-w", "--write"}];
|
bool can_write = cmd[{"-w", "--write"}];
|
||||||
|
|
||||||
if (!can_read || !can_write) {
|
if (!can_read || !can_write) {
|
||||||
LogInfo("[{0}] --read or --write must be set or both!", __func__);
|
LogInfo("--read or --write must be set or both!");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string token = server.db->CreateLoginserverApiToken(can_write, can_read);
|
auto t = LoginApiTokensRepository::NewEntity();
|
||||||
if (!token.empty()) {
|
t.can_read = can_read;
|
||||||
LogInfo("[{0}] Created Loginserver API token [{1}]", __func__, token);
|
t.can_write = can_write;
|
||||||
|
t.token = EQ::Util::UUID::Generate().ToString();
|
||||||
|
t.created_at = std::time(nullptr);
|
||||||
|
|
||||||
|
auto created = LoginApiTokensRepository::InsertOne(database, t);
|
||||||
|
if (created.id) {
|
||||||
|
LogInfo("Created Loginserver API token [{}] [{}]", created.id, created.token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param argc
|
|
||||||
* @param argv
|
|
||||||
* @param cmd
|
|
||||||
* @param description
|
|
||||||
*/
|
|
||||||
void ListLoginserverApiTokens(int argc, char **argv, argh::parser &cmd, std::string &description)
|
void ListLoginserverApiTokens(int argc, char **argv, argh::parser &cmd, std::string &description)
|
||||||
{
|
{
|
||||||
description = "Lists Loginserver API Tokens";
|
description = "Lists Loginserver API Tokens";
|
||||||
@ -96,9 +79,10 @@ namespace LoginserverCommandHandler {
|
|||||||
server.token_manager = new LoginserverWebserver::TokenManager;
|
server.token_manager = new LoginserverWebserver::TokenManager;
|
||||||
server.token_manager->LoadApiTokens();
|
server.token_manager->LoadApiTokens();
|
||||||
|
|
||||||
for (auto &it : server.token_manager->loaded_api_tokens) {
|
for (auto &it: server.token_manager->loaded_api_tokens) {
|
||||||
LogInfo(
|
LogInfo(
|
||||||
"token [{0}] can_write [{1}] can_read [{2}]",
|
"token id [{}] [{}] can_write [{}] can_read [{}]",
|
||||||
|
it.second.id,
|
||||||
it.second.token,
|
it.second.token,
|
||||||
it.second.can_write,
|
it.second.can_write,
|
||||||
it.second.can_read
|
it.second.can_read
|
||||||
@ -106,12 +90,6 @@ namespace LoginserverCommandHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param argc
|
|
||||||
* @param argv
|
|
||||||
* @param cmd
|
|
||||||
* @param description
|
|
||||||
*/
|
|
||||||
void CreateLocalLoginserverAccount(int argc, char **argv, argh::parser &cmd, std::string &description)
|
void CreateLocalLoginserverAccount(int argc, char **argv, argh::parser &cmd, std::string &description)
|
||||||
{
|
{
|
||||||
description = "Creates Local Loginserver Account";
|
description = "Creates Local Loginserver Account";
|
||||||
@ -130,19 +108,14 @@ namespace LoginserverCommandHandler {
|
|||||||
|
|
||||||
EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv);
|
EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv);
|
||||||
|
|
||||||
AccountManagement::CreateLoginServerAccount(
|
LoginAccountContext c;
|
||||||
cmd(2).str(),
|
c.username = cmd(2).str();
|
||||||
cmd(3).str(),
|
c.password = cmd(3).str();
|
||||||
cmd("--email").str()
|
c.email = cmd("--email").str();
|
||||||
);
|
|
||||||
|
AccountManagement::CreateLoginServerAccount(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param argc
|
|
||||||
* @param argv
|
|
||||||
* @param cmd
|
|
||||||
* @param description
|
|
||||||
*/
|
|
||||||
void CreateLoginserverWorldAdminAccount(int argc, char **argv, argh::parser &cmd, std::string &description)
|
void CreateLoginserverWorldAdminAccount(int argc, char **argv, argh::parser &cmd, std::string &description)
|
||||||
{
|
{
|
||||||
description = "Creates Loginserver World Administrator Account";
|
description = "Creates Loginserver World Administrator Account";
|
||||||
@ -167,12 +140,6 @@ namespace LoginserverCommandHandler {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param argc
|
|
||||||
* @param argv
|
|
||||||
* @param cmd
|
|
||||||
* @param description
|
|
||||||
*/
|
|
||||||
void CheckLoginserverUserCredentials(int argc, char **argv, argh::parser &cmd, std::string &description)
|
void CheckLoginserverUserCredentials(int argc, char **argv, argh::parser &cmd, std::string &description)
|
||||||
{
|
{
|
||||||
description = "Check user login credentials";
|
description = "Check user login credentials";
|
||||||
@ -189,20 +156,15 @@ namespace LoginserverCommandHandler {
|
|||||||
|
|
||||||
EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv);
|
EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv);
|
||||||
|
|
||||||
auto res = AccountManagement::CheckLoginserverUserCredentials(
|
LoginAccountContext c;
|
||||||
cmd(2).str(),
|
c.username = cmd(2).str();
|
||||||
cmd(3).str()
|
c.password = cmd(3).str();
|
||||||
);
|
|
||||||
|
|
||||||
LogInfo("Credentials were {0}", res != 0 ? "accepted" : "not accepted");
|
auto res = AccountManagement::CheckLoginserverUserCredentials(c);
|
||||||
|
|
||||||
|
LogInfo("Credentials were {}", res != 0 ? "accepted" : "not accepted");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param argc
|
|
||||||
* @param argv
|
|
||||||
* @param cmd
|
|
||||||
* @param description
|
|
||||||
*/
|
|
||||||
void UpdateLoginserverUserCredentials(int argc, char **argv, argh::parser &cmd, std::string &description)
|
void UpdateLoginserverUserCredentials(int argc, char **argv, argh::parser &cmd, std::string &description)
|
||||||
{
|
{
|
||||||
description = "Change user login credentials";
|
description = "Change user login credentials";
|
||||||
@ -219,18 +181,12 @@ namespace LoginserverCommandHandler {
|
|||||||
|
|
||||||
EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv);
|
EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv);
|
||||||
|
|
||||||
AccountManagement::UpdateLoginserverUserCredentials(
|
LoginAccountContext c;
|
||||||
cmd(2).str(),
|
c.username = cmd(2).str();
|
||||||
cmd(3).str()
|
c.password = cmd(3).str();
|
||||||
);
|
AccountManagement::UpdateLoginserverUserCredentials(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param argc
|
|
||||||
* @param argv
|
|
||||||
* @param cmd
|
|
||||||
* @param description
|
|
||||||
*/
|
|
||||||
void CheckExternalLoginserverUserCredentials(int argc, char **argv, argh::parser &cmd, std::string &description)
|
void CheckExternalLoginserverUserCredentials(int argc, char **argv, argh::parser &cmd, std::string &description)
|
||||||
{
|
{
|
||||||
description = "Check user external login credentials";
|
description = "Check user external login credentials";
|
||||||
@ -247,20 +203,14 @@ namespace LoginserverCommandHandler {
|
|||||||
|
|
||||||
EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv);
|
EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv);
|
||||||
|
|
||||||
auto res = AccountManagement::CheckExternalLoginserverUserCredentials(
|
LoginAccountContext c;
|
||||||
cmd(2).str(),
|
c.username = cmd(2).str();
|
||||||
cmd(3).str()
|
c.password = cmd(3).str();
|
||||||
);
|
auto res = AccountManagement::CheckExternalLoginserverUserCredentials(c);
|
||||||
|
|
||||||
LogInfo("Credentials were {0}", res ? "accepted" : "not accepted");
|
LogInfo("Credentials were {}", res ? "accepted" : "not accepted");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param argc
|
|
||||||
* @param argv
|
|
||||||
* @param cmd
|
|
||||||
* @param description
|
|
||||||
*/
|
|
||||||
void UpdateLoginserverWorldAdminAccountPassword(int argc, char **argv, argh::parser &cmd, std::string &description)
|
void UpdateLoginserverWorldAdminAccountPassword(int argc, char **argv, argh::parser &cmd, std::string &description)
|
||||||
{
|
{
|
||||||
description = "Update world admin account password";
|
description = "Update world admin account password";
|
||||||
@ -277,18 +227,12 @@ namespace LoginserverCommandHandler {
|
|||||||
|
|
||||||
EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv);
|
EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv);
|
||||||
|
|
||||||
AccountManagement::UpdateLoginserverWorldAdminAccountPasswordByName(
|
LoginAccountContext c;
|
||||||
cmd(2).str(),
|
c.username = cmd(2).str();
|
||||||
cmd(3).str()
|
c.password = cmd(3).str();
|
||||||
);
|
AccountManagement::UpdateLoginserverWorldAdminAccountPasswordByName(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param argc
|
|
||||||
* @param argv
|
|
||||||
* @param cmd
|
|
||||||
* @param description
|
|
||||||
*/
|
|
||||||
void HealthCheckLogin(int argc, char **argv, argh::parser &cmd, std::string &description)
|
void HealthCheckLogin(int argc, char **argv, argh::parser &cmd, std::string &description)
|
||||||
{
|
{
|
||||||
description = "Checks login health using a test user";
|
description = "Checks login health using a test user";
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
#include "loginserver_webserver.h"
|
#include "loginserver_webserver.h"
|
||||||
#include "server_manager.h"
|
#include "world_server_manager.h"
|
||||||
#include "login_server.h"
|
#include "login_server.h"
|
||||||
#include "../common/json/json.h"
|
#include "../common/json/json.h"
|
||||||
#include "../common/strings.h"
|
#include "../common/strings.h"
|
||||||
#include "account_management.h"
|
#include "account_management.h"
|
||||||
|
#include "../common/repositories/login_api_tokens_repository.h"
|
||||||
|
|
||||||
extern LoginServer server;
|
extern LoginServer server;
|
||||||
|
|
||||||
@ -13,9 +14,6 @@ namespace LoginserverWebserver {
|
|||||||
constexpr static int HTTP_RESPONSE_BAD_REQUEST = 400;
|
constexpr static int HTTP_RESPONSE_BAD_REQUEST = 400;
|
||||||
constexpr static int HTTP_RESPONSE_UNAUTHORIZED = 401;
|
constexpr static int HTTP_RESPONSE_UNAUTHORIZED = 401;
|
||||||
|
|
||||||
/**
|
|
||||||
* @param api
|
|
||||||
*/
|
|
||||||
void RegisterRoutes(httplib::Server &api)
|
void RegisterRoutes(httplib::Server &api)
|
||||||
{
|
{
|
||||||
server.token_manager = new LoginserverWebserver::TokenManager;
|
server.token_manager = new LoginserverWebserver::TokenManager;
|
||||||
@ -27,21 +25,21 @@ namespace LoginserverWebserver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value response;
|
Json::Value response;
|
||||||
auto iter = server.server_manager->getWorldServers().begin();
|
auto iter = server.server_manager->GetWorldServers().begin();
|
||||||
while (iter != server.server_manager->getWorldServers().end()) {
|
for (const auto &s: server.server_manager->GetWorldServers()) {
|
||||||
Json::Value row;
|
Json::Value row;
|
||||||
row["server_long_name"] = (*iter)->GetServerLongName();
|
row["server_long_name"] = s->GetServerLongName();
|
||||||
row["server_short_name"] = (*iter)->GetServerShortName();
|
row["server_short_name"] = s->GetServerShortName();
|
||||||
row["server_list_type_id"] = (*iter)->GetServerListID();
|
row["server_list_type_id"] = s->GetServerListID();
|
||||||
row["server_status"] = (*iter)->GetStatus();
|
row["server_status"] = s->GetStatus();
|
||||||
row["zones_booted"] = (*iter)->GetZonesBooted();
|
row["zones_booted"] = s->GetZonesBooted();
|
||||||
row["local_ip"] = (*iter)->GetLocalIP();
|
row["local_ip"] = s->GetLocalIP();
|
||||||
row["remote_ip"] = (*iter)->GetRemoteIP();
|
row["remote_ip"] = s->GetRemoteIP();
|
||||||
row["players_online"] = (*iter)->GetPlayersOnline();
|
row["players_online"] = s->GetPlayersOnline();
|
||||||
row["world_id"] = (*iter)->GetServerId();
|
row["world_id"] = s->GetServerId();
|
||||||
|
|
||||||
response.append(row);
|
response.append(row);
|
||||||
++iter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LoginserverWebserver::SendResponse(response, res);
|
LoginserverWebserver::SendResponse(response, res);
|
||||||
@ -54,10 +52,10 @@ namespace LoginserverWebserver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value request_body = LoginserverWebserver::ParseRequestBody(request);
|
Json::Value req = LoginserverWebserver::ParseRequestBody(request);
|
||||||
std::string username = request_body.get("username", "").asString();
|
std::string username = req.get("username", "").asString();
|
||||||
std::string password = request_body.get("password", "").asString();
|
std::string password = req.get("password", "").asString();
|
||||||
std::string email = request_body.get("email", "").asString();
|
std::string email = req.get("email", "").asString();
|
||||||
|
|
||||||
Json::Value response;
|
Json::Value response;
|
||||||
if (username.empty() || password.empty()) {
|
if (username.empty() || password.empty()) {
|
||||||
@ -67,7 +65,12 @@ namespace LoginserverWebserver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 account_created_id = AccountManagement::CreateLoginServerAccount(username, password, email);
|
LoginAccountContext c;
|
||||||
|
c.username = username;
|
||||||
|
c.password = password;
|
||||||
|
c.email = email;
|
||||||
|
|
||||||
|
int32 account_created_id = AccountManagement::CreateLoginServerAccount(c);
|
||||||
if (account_created_id > 0) {
|
if (account_created_id > 0) {
|
||||||
response["message"] = "Account created successfully!";
|
response["message"] = "Account created successfully!";
|
||||||
response["data"]["account_id"] = account_created_id;
|
response["data"]["account_id"] = account_created_id;
|
||||||
@ -91,11 +94,11 @@ namespace LoginserverWebserver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value request_body = LoginserverWebserver::ParseRequestBody(request);
|
Json::Value req = LoginserverWebserver::ParseRequestBody(request);
|
||||||
std::string username = request_body.get("username", "").asString();
|
std::string username = req.get("username", "").asString();
|
||||||
std::string password = request_body.get("password", "").asString();
|
std::string password = req.get("password", "").asString();
|
||||||
std::string email = request_body.get("email", "").asString();
|
std::string email = req.get("email", "").asString();
|
||||||
uint32 login_account_id = request_body.get("login_account_id", "").asInt();
|
uint32 login_account_id = req.get("login_account_id", "").asInt();
|
||||||
|
|
||||||
Json::Value response;
|
Json::Value response;
|
||||||
if (username.empty() || password.empty()) {
|
if (username.empty() || password.empty()) {
|
||||||
@ -105,14 +108,14 @@ namespace LoginserverWebserver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string source_loginserver = "eqemu";
|
LoginAccountContext c;
|
||||||
int32 account_created_id = AccountManagement::CreateLoginServerAccount(
|
c.username = username;
|
||||||
username,
|
c.password = password;
|
||||||
password,
|
c.email = email;
|
||||||
email,
|
c.source_loginserver = "eqemu";
|
||||||
source_loginserver,
|
c.login_account_id = login_account_id;
|
||||||
login_account_id
|
|
||||||
);
|
int32 account_created_id = AccountManagement::CreateLoginServerAccount(c);
|
||||||
|
|
||||||
if (account_created_id > 0) {
|
if (account_created_id > 0) {
|
||||||
response["message"] = "Account created successfully!";
|
response["message"] = "Account created successfully!";
|
||||||
@ -137,9 +140,9 @@ namespace LoginserverWebserver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value request_body = LoginserverWebserver::ParseRequestBody(request);
|
Json::Value req = LoginserverWebserver::ParseRequestBody(request);
|
||||||
std::string username = request_body.get("username", "").asString();
|
std::string username = req.get("username", "").asString();
|
||||||
std::string password = request_body.get("password", "").asString();
|
std::string password = req.get("password", "").asString();
|
||||||
|
|
||||||
Json::Value response;
|
Json::Value response;
|
||||||
if (username.empty() || password.empty()) {
|
if (username.empty() || password.empty()) {
|
||||||
@ -149,11 +152,11 @@ namespace LoginserverWebserver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 login_account_id = AccountManagement::CheckLoginserverUserCredentials(
|
LoginAccountContext c;
|
||||||
username,
|
c.username = username;
|
||||||
password
|
c.password = password;
|
||||||
);
|
|
||||||
|
|
||||||
|
uint32 login_account_id = AccountManagement::CheckLoginserverUserCredentials(c);
|
||||||
if (login_account_id > 0) {
|
if (login_account_id > 0) {
|
||||||
response["message"] = "Credentials valid!";
|
response["message"] = "Credentials valid!";
|
||||||
response["data"]["account_id"] = login_account_id;
|
response["data"]["account_id"] = login_account_id;
|
||||||
@ -173,9 +176,9 @@ namespace LoginserverWebserver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value request_body = LoginserverWebserver::ParseRequestBody(request);
|
Json::Value req = LoginserverWebserver::ParseRequestBody(request);
|
||||||
std::string username = request_body.get("username", "").asString();
|
std::string username = req.get("username", "").asString();
|
||||||
std::string password = request_body.get("password", "").asString();
|
std::string password = req.get("password", "").asString();
|
||||||
|
|
||||||
Json::Value response;
|
Json::Value response;
|
||||||
if (username.empty() || password.empty()) {
|
if (username.empty() || password.empty()) {
|
||||||
@ -185,24 +188,20 @@ namespace LoginserverWebserver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Database::DbLoginServerAccount
|
LoginAccountContext c;
|
||||||
login_server_account = server.db->GetLoginServerAccountByAccountName(
|
c.username = username;
|
||||||
username
|
c.password = password;
|
||||||
);
|
|
||||||
|
|
||||||
if (!login_server_account.loaded) {
|
auto a = LoginAccountsRepository::GetAccountFromContext(database, c);
|
||||||
|
if (!a.id) {
|
||||||
res.status = HTTP_RESPONSE_BAD_REQUEST;
|
res.status = HTTP_RESPONSE_BAD_REQUEST;
|
||||||
response["error"] = "Failed to find associated loginserver account!";
|
response["error"] = "Failed to find associated loginserver account!";
|
||||||
LoginserverWebserver::SendResponse(response, res);
|
LoginserverWebserver::SendResponse(response, res);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool credentials_valid = AccountManagement::UpdateLoginserverUserCredentials(
|
bool success = AccountManagement::UpdateLoginserverUserCredentials(c);
|
||||||
username,
|
if (success) {
|
||||||
password
|
|
||||||
);
|
|
||||||
|
|
||||||
if (credentials_valid) {
|
|
||||||
response["message"] = "Loginserver account credentials updated!";
|
response["message"] = "Loginserver account credentials updated!";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -214,16 +213,15 @@ namespace LoginserverWebserver {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
api.Post(
|
api.Post(
|
||||||
"/v1/account/credentials/update/external", [](const httplib::Request &request, httplib::Response &res) {
|
"/v1/account/credentials/update/external", [](const httplib::Request &request, httplib::Response &res) {
|
||||||
if (!LoginserverWebserver::TokenManager::AuthCanWrite(request, res)) {
|
if (!LoginserverWebserver::TokenManager::AuthCanWrite(request, res)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value request_body = LoginserverWebserver::ParseRequestBody(request);
|
Json::Value req = LoginserverWebserver::ParseRequestBody(request);
|
||||||
std::string username = request_body.get("username", "").asString();
|
std::string username = req.get("username", "").asString();
|
||||||
std::string password = request_body.get("password", "").asString();
|
std::string password = req.get("password", "").asString();
|
||||||
|
|
||||||
Json::Value response;
|
Json::Value response;
|
||||||
if (username.empty() || password.empty()) {
|
if (username.empty() || password.empty()) {
|
||||||
@ -234,25 +232,20 @@ namespace LoginserverWebserver {
|
|||||||
|
|
||||||
std::string source_loginserver = "eqemu";
|
std::string source_loginserver = "eqemu";
|
||||||
|
|
||||||
Database::DbLoginServerAccount
|
LoginAccountContext c;
|
||||||
login_server_account = server.db->GetLoginServerAccountByAccountName(
|
c.username = username;
|
||||||
username,
|
c.password = password;
|
||||||
source_loginserver
|
c.source_loginserver = source_loginserver;
|
||||||
);
|
|
||||||
|
|
||||||
if (!login_server_account.loaded) {
|
auto a = LoginAccountsRepository::GetAccountFromContext(database, c);
|
||||||
|
if (!a.id) {
|
||||||
response["error"] = "Failed to find associated loginserver account!";
|
response["error"] = "Failed to find associated loginserver account!";
|
||||||
LoginserverWebserver::SendResponse(response, res);
|
LoginserverWebserver::SendResponse(response, res);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool credentials_valid = AccountManagement::UpdateLoginserverUserCredentials(
|
bool success = AccountManagement::UpdateLoginserverUserCredentials(c);
|
||||||
username,
|
if (success) {
|
||||||
password,
|
|
||||||
source_loginserver
|
|
||||||
);
|
|
||||||
|
|
||||||
if (credentials_valid) {
|
|
||||||
response["message"] = "Loginserver account credentials updated!";
|
response["message"] = "Loginserver account credentials updated!";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -269,9 +262,9 @@ namespace LoginserverWebserver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value request_body = LoginserverWebserver::ParseRequestBody(request);
|
Json::Value req = LoginserverWebserver::ParseRequestBody(request);
|
||||||
std::string username = request_body.get("username", "").asString();
|
std::string username = req.get("username", "").asString();
|
||||||
std::string password = request_body.get("password", "").asString();
|
std::string password = req.get("password", "").asString();
|
||||||
|
|
||||||
Json::Value response;
|
Json::Value response;
|
||||||
if (username.empty() || password.empty()) {
|
if (username.empty() || password.empty()) {
|
||||||
@ -280,10 +273,10 @@ namespace LoginserverWebserver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 account_id = AccountManagement::CheckExternalLoginserverUserCredentials(
|
LoginAccountContext c;
|
||||||
username,
|
c.username = username;
|
||||||
password
|
c.password = password;
|
||||||
);
|
uint32 account_id = AccountManagement::CheckExternalLoginserverUserCredentials(c);
|
||||||
|
|
||||||
if (account_id > 0) {
|
if (account_id > 0) {
|
||||||
response["message"] = "Credentials valid!";
|
response["message"] = "Credentials valid!";
|
||||||
@ -301,7 +294,7 @@ namespace LoginserverWebserver {
|
|||||||
api.Get(
|
api.Get(
|
||||||
"/probes/healthcheck", [](const httplib::Request &request, httplib::Response &res) {
|
"/probes/healthcheck", [](const httplib::Request &request, httplib::Response &res) {
|
||||||
Json::Value response;
|
Json::Value response;
|
||||||
uint32 login_response = AccountManagement::HealthCheckUserLogin();
|
uint32 login_response = AccountManagement::HealthCheckUserLogin();
|
||||||
|
|
||||||
response["status"] = login_response;
|
response["status"] = login_response;
|
||||||
if (login_response == 0) {
|
if (login_response == 0) {
|
||||||
@ -317,10 +310,6 @@ namespace LoginserverWebserver {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param payload
|
|
||||||
* @param res
|
|
||||||
*/
|
|
||||||
void SendResponse(const Json::Value &payload, httplib::Response &res)
|
void SendResponse(const Json::Value &payload, httplib::Response &res)
|
||||||
{
|
{
|
||||||
if (res.get_header_value("response_set") == "true") {
|
if (res.get_header_value("response_set") == "true") {
|
||||||
@ -342,10 +331,6 @@ namespace LoginserverWebserver {
|
|||||||
res.set_content(response_payload.str(), "application/json");
|
res.set_content(response_payload.str(), "application/json");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param payload
|
|
||||||
* @param res
|
|
||||||
*/
|
|
||||||
Json::Value ParseRequestBody(const httplib::Request &request)
|
Json::Value ParseRequestBody(const httplib::Request &request)
|
||||||
{
|
{
|
||||||
Json::Value request_body;
|
Json::Value request_body;
|
||||||
@ -364,13 +349,9 @@ namespace LoginserverWebserver {
|
|||||||
return request_body;
|
return request_body;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param request
|
|
||||||
* @param res
|
|
||||||
*/
|
|
||||||
bool LoginserverWebserver::TokenManager::AuthCanRead(const httplib::Request &request, httplib::Response &res)
|
bool LoginserverWebserver::TokenManager::AuthCanRead(const httplib::Request &request, httplib::Response &res)
|
||||||
{
|
{
|
||||||
LoginserverWebserver::TokenManager::token_data
|
LoginserverWebserver::TokenManager::Token
|
||||||
user_token = LoginserverWebserver::TokenManager::CheckApiAuthorizationHeaders(request);
|
user_token = LoginserverWebserver::TokenManager::CheckApiAuthorizationHeaders(request);
|
||||||
|
|
||||||
if (!user_token.can_read) {
|
if (!user_token.can_read) {
|
||||||
@ -384,7 +365,7 @@ namespace LoginserverWebserver {
|
|||||||
res.set_header("response_set", "true");
|
res.set_header("response_set", "true");
|
||||||
|
|
||||||
LogWarning(
|
LogWarning(
|
||||||
"AuthCanRead access failure remote_address [{0}] user_agent [{1}]",
|
"AuthCanRead access failure remote_address [{}] user_agent [{}]",
|
||||||
user_token.remote_address,
|
user_token.remote_address,
|
||||||
user_token.user_agent
|
user_token.user_agent
|
||||||
);
|
);
|
||||||
@ -395,13 +376,9 @@ namespace LoginserverWebserver {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param request
|
|
||||||
* @param res
|
|
||||||
*/
|
|
||||||
bool LoginserverWebserver::TokenManager::AuthCanWrite(const httplib::Request &request, httplib::Response &res)
|
bool LoginserverWebserver::TokenManager::AuthCanWrite(const httplib::Request &request, httplib::Response &res)
|
||||||
{
|
{
|
||||||
LoginserverWebserver::TokenManager::token_data
|
LoginserverWebserver::TokenManager::Token
|
||||||
user_token = LoginserverWebserver::TokenManager::CheckApiAuthorizationHeaders(request);
|
user_token = LoginserverWebserver::TokenManager::CheckApiAuthorizationHeaders(request);
|
||||||
|
|
||||||
if (!user_token.can_write) {
|
if (!user_token.can_write) {
|
||||||
@ -415,7 +392,7 @@ namespace LoginserverWebserver {
|
|||||||
res.set_header("response_set", "true");
|
res.set_header("response_set", "true");
|
||||||
|
|
||||||
LogWarning(
|
LogWarning(
|
||||||
"AuthCanWrite access failure remote_address [{0}] user_agent [{1}]",
|
"AuthCanWrite access failure remote_address [{}] user_agent [{}]",
|
||||||
user_token.remote_address,
|
user_token.remote_address,
|
||||||
user_token.user_agent
|
user_token.user_agent
|
||||||
);
|
);
|
||||||
@ -426,20 +403,16 @@ namespace LoginserverWebserver {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
LoginserverWebserver::TokenManager::Token
|
||||||
* @param request
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
LoginserverWebserver::TokenManager::token_data
|
|
||||||
LoginserverWebserver::TokenManager::CheckApiAuthorizationHeaders(
|
LoginserverWebserver::TokenManager::CheckApiAuthorizationHeaders(
|
||||||
const httplib::Request &request
|
const httplib::Request &request
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
std::string authorization_key;
|
std::string authorization_key;
|
||||||
|
|
||||||
LoginserverWebserver::TokenManager::token_data user_token{};
|
LoginserverWebserver::TokenManager::Token user_token{};
|
||||||
|
|
||||||
for (const auto &header : request.headers) {
|
for (const auto &header: request.headers) {
|
||||||
auto header_key = header.first;
|
auto header_key = header.first;
|
||||||
auto header_value = header.second;
|
auto header_value = header.second;
|
||||||
if (header_key == "Authorization") {
|
if (header_key == "Authorization") {
|
||||||
@ -460,7 +433,7 @@ namespace LoginserverWebserver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LogDebug(
|
LogDebug(
|
||||||
"Authentication Request | remote_address [{0}] user_agent [{1}] authorization_key [{2}] request_path [{3}]",
|
"Authentication Request | remote_address [{}] user_agent [{}] authorization_key [{}] request_path [{}]",
|
||||||
user_token.remote_address,
|
user_token.remote_address,
|
||||||
user_token.user_agent,
|
user_token.user_agent,
|
||||||
authorization_key,
|
authorization_key,
|
||||||
@ -470,43 +443,24 @@ namespace LoginserverWebserver {
|
|||||||
return user_token;
|
return user_token;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads API Tokens
|
|
||||||
*/
|
|
||||||
void TokenManager::LoadApiTokens()
|
void TokenManager::LoadApiTokens()
|
||||||
{
|
{
|
||||||
auto results = server.db->GetLoginserverApiTokens();
|
int token_count = 0;
|
||||||
int token_count = 0;
|
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
|
||||||
LoginserverWebserver::TokenManager::token_data token_data;
|
|
||||||
token_data.token = row[0];
|
|
||||||
token_data.can_write = Strings::ToInt(row[1]) > 0;
|
|
||||||
token_data.can_read = Strings::ToInt(row[2]) > 0;
|
|
||||||
|
|
||||||
LogDebug(
|
for (auto &t: LoginApiTokensRepository::GetWhere(database, "TRUE ORDER BY id ASC")) {
|
||||||
"Inserting api token to internal list [{0}] write {1} read {2}",
|
LoginserverWebserver::TokenManager::Token td;
|
||||||
token_data.token,
|
td.id = t.id;
|
||||||
token_data.can_read,
|
td.token = t.token;
|
||||||
token_data.can_write
|
td.can_write = t.can_write;
|
||||||
);
|
td.can_read = t.can_read;
|
||||||
|
|
||||||
server.token_manager->loaded_api_tokens.emplace(
|
|
||||||
std::make_pair(
|
|
||||||
token_data.token,
|
|
||||||
token_data
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
server.token_manager->loaded_api_tokens.emplace(std::make_pair(td.token, td));
|
||||||
token_count++;
|
token_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogInfo("Loaded [{}] API token(s)", token_count);
|
LogInfo("Loaded [{}] API token(s)", token_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param token
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool TokenManager::TokenExists(const std::string &token)
|
bool TokenManager::TokenExists(const std::string &token)
|
||||||
{
|
{
|
||||||
auto it = server.token_manager->loaded_api_tokens.find(token);
|
auto it = server.token_manager->loaded_api_tokens.find(token);
|
||||||
@ -514,11 +468,7 @@ namespace LoginserverWebserver {
|
|||||||
return !(it == server.token_manager->loaded_api_tokens.end());
|
return !(it == server.token_manager->loaded_api_tokens.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
LoginserverWebserver::TokenManager::Token TokenManager::GetToken(
|
||||||
* @param token
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
LoginserverWebserver::TokenManager::token_data TokenManager::GetToken(
|
|
||||||
const std::string &token
|
const std::string &token
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -12,7 +12,8 @@ namespace LoginserverWebserver {
|
|||||||
public:
|
public:
|
||||||
TokenManager() = default;
|
TokenManager() = default;
|
||||||
|
|
||||||
struct token_data {
|
struct Token {
|
||||||
|
int id;
|
||||||
std::string token;
|
std::string token;
|
||||||
bool can_read;
|
bool can_read;
|
||||||
bool can_write;
|
bool can_write;
|
||||||
@ -20,12 +21,12 @@ namespace LoginserverWebserver {
|
|||||||
std::string remote_address;
|
std::string remote_address;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<std::string, token_data> loaded_api_tokens{};
|
std::map<std::string, Token> loaded_api_tokens{};
|
||||||
|
|
||||||
void LoadApiTokens();
|
void LoadApiTokens();
|
||||||
static bool TokenExists(const std::string &token);
|
static bool TokenExists(const std::string &token);
|
||||||
token_data GetToken(const std::string &token);
|
Token GetToken(const std::string &token);
|
||||||
static token_data CheckApiAuthorizationHeaders(const httplib::Request &request);
|
static Token CheckApiAuthorizationHeaders(const httplib::Request &request);
|
||||||
static bool AuthCanRead(const httplib::Request &request, httplib::Response &res);
|
static bool AuthCanRead(const httplib::Request &request, httplib::Response &res);
|
||||||
static bool AuthCanWrite(const httplib::Request &request, httplib::Response &res);
|
static bool AuthCanWrite(const httplib::Request &request, httplib::Response &res);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -12,18 +12,23 @@
|
|||||||
#include "loginserver_command_handler.h"
|
#include "loginserver_command_handler.h"
|
||||||
#include "../common/strings.h"
|
#include "../common/strings.h"
|
||||||
#include "../common/path_manager.h"
|
#include "../common/path_manager.h"
|
||||||
|
#include "../common/database.h"
|
||||||
|
#include "../common/events/player_event_logs.h"
|
||||||
|
#include "../common/zone_store.h"
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
LoginServer server;
|
LoginServer server;
|
||||||
EQEmuLogSys LogSys;
|
EQEmuLogSys LogSys;
|
||||||
bool run_server = true;
|
bool run_server = true;
|
||||||
PathManager path;
|
PathManager path;
|
||||||
|
Database database;
|
||||||
|
PlayerEventLogs player_event_logs;
|
||||||
|
ZoneStore zone_store;
|
||||||
|
|
||||||
void ResolveAddresses();
|
|
||||||
void CatchSignal(int sig_num)
|
void CatchSignal(int sig_num)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -32,14 +37,16 @@ void LoadDatabaseConnection()
|
|||||||
{
|
{
|
||||||
LogInfo("MySQL Database Init");
|
LogInfo("MySQL Database Init");
|
||||||
|
|
||||||
server.db = new Database(
|
if (!database.Connect(
|
||||||
|
server.config.GetVariableString("database", "host", "localhost"),
|
||||||
server.config.GetVariableString("database", "user", "root"),
|
server.config.GetVariableString("database", "user", "root"),
|
||||||
server.config.GetVariableString("database", "password", ""),
|
server.config.GetVariableString("database", "password", ""),
|
||||||
server.config.GetVariableString("database", "host", "localhost"),
|
server.config.GetVariableString("database", "db", "peq"),
|
||||||
server.config.GetVariableString("database", "port", "3306"),
|
server.config.GetVariableInt("database", "port", 3306)
|
||||||
server.config.GetVariableString("database", "db", "peq")
|
)) {
|
||||||
);
|
LogError("Cannot continue without a database connection");
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadServerConfig()
|
void LoadServerConfig()
|
||||||
@ -49,9 +56,6 @@ void LoadServerConfig()
|
|||||||
);
|
);
|
||||||
LogInfo("Config System Init");
|
LogInfo("Config System Init");
|
||||||
|
|
||||||
/**
|
|
||||||
* Worldservers
|
|
||||||
*/
|
|
||||||
server.options.RejectDuplicateServers(
|
server.options.RejectDuplicateServers(
|
||||||
server.config.GetVariableBool(
|
server.config.GetVariableBool(
|
||||||
"worldservers",
|
"worldservers",
|
||||||
@ -82,41 +86,33 @@ void LoadServerConfig()
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
* Expansion Display Settings
|
|
||||||
*/
|
|
||||||
server.options.DisplayExpansions(
|
server.options.DisplayExpansions(
|
||||||
server.config.GetVariableBool(
|
server.config.GetVariableBool(
|
||||||
"client_configuration",
|
"client_configuration",
|
||||||
"display_expansions",
|
"display_expansions",
|
||||||
false
|
false
|
||||||
)); //disable by default
|
)
|
||||||
|
);
|
||||||
server.options.MaxExpansions(
|
server.options.MaxExpansions(
|
||||||
server.config.GetVariableInt(
|
server.config.GetVariableInt(
|
||||||
"client_configuration",
|
"client_configuration",
|
||||||
"max_expansions_mask",
|
"max_expansions_mask",
|
||||||
67108863
|
67108863
|
||||||
)); //enable display of all expansions
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Account
|
|
||||||
*/
|
|
||||||
server.options.AutoCreateAccounts(server.config.GetVariableBool("account", "auto_create_accounts", true));
|
|
||||||
server.options.AutoLinkAccounts(server.config.GetVariableBool("account", "auto_link_accounts", false));
|
|
||||||
|
|
||||||
#ifdef LSPX
|
|
||||||
server.options.EQEmuLoginServerAddress(
|
|
||||||
server.config.GetVariableString(
|
|
||||||
"general",
|
|
||||||
"eqemu_loginserver_address",
|
|
||||||
"login.eqemulator.net:5999"
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
server.options.AutoCreateAccounts(server.config.GetVariableBool("account", "auto_create_accounts", true));
|
||||||
* Default Loginserver Name (Don't change)
|
|
||||||
*/
|
if (std::getenv("LSPX")) {
|
||||||
|
server.options.EQEmuLoginServerAddress(
|
||||||
|
server.config.GetVariableString(
|
||||||
|
"general",
|
||||||
|
"eqemu_loginserver_address",
|
||||||
|
"login.eqemulator.net:5999"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
server.options.DefaultLoginServerName(
|
server.options.DefaultLoginServerName(
|
||||||
server.config.GetVariableString(
|
server.config.GetVariableString(
|
||||||
"general",
|
"general",
|
||||||
@ -125,10 +121,6 @@ void LoadServerConfig()
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
* Security
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef ENABLE_SECURITY
|
#ifdef ENABLE_SECURITY
|
||||||
server.options.EncryptionMode(server.config.GetVariableInt("security", "mode", 13));
|
server.options.EncryptionMode(server.config.GetVariableInt("security", "mode", 13));
|
||||||
#else
|
#else
|
||||||
@ -136,14 +128,6 @@ void LoadServerConfig()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
server.options.AllowTokenLogin(server.config.GetVariableBool("security", "allow_token_login", false));
|
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
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_web_server()
|
void start_web_server()
|
||||||
@ -151,7 +135,7 @@ void start_web_server()
|
|||||||
Sleep(1);
|
Sleep(1);
|
||||||
|
|
||||||
int web_api_port = server.config.GetVariableInt("web_api", "port", 6000);
|
int web_api_port = server.config.GetVariableInt("web_api", "port", 6000);
|
||||||
LogInfo("Webserver API now listening on port [{0}]", web_api_port);
|
LogInfo("Webserver API now listening on port [{}]", web_api_port);
|
||||||
|
|
||||||
httplib::Server api;
|
httplib::Server api;
|
||||||
|
|
||||||
@ -180,9 +164,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
path.LoadPaths();
|
path.LoadPaths();
|
||||||
|
|
||||||
/**
|
// command handler
|
||||||
* Command handler
|
|
||||||
*/
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
LogSys.SilenceConsoleLogging();
|
LogSys.SilenceConsoleLogging();
|
||||||
|
|
||||||
@ -197,43 +179,23 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
LoadServerConfig();
|
LoadServerConfig();
|
||||||
|
|
||||||
/**
|
|
||||||
* mysql connect
|
|
||||||
*/
|
|
||||||
LoadDatabaseConnection();
|
LoadDatabaseConnection();
|
||||||
|
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
LogSys.SetDatabase(server.db)
|
LogSys.SetDatabase(&database)
|
||||||
->SetLogPath("logs")
|
->SetLogPath("logs")
|
||||||
->LoadLogDatabaseSettings()
|
->LoadLogDatabaseSettings()
|
||||||
->StartFileLogs();
|
->StartFileLogs();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* make sure our database got created okay, otherwise cleanup and exit
|
|
||||||
*/
|
|
||||||
if (!server.db) {
|
|
||||||
LogError("Database Initialization Failure");
|
|
||||||
LogInfo("Log System Shutdown");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create server manager
|
|
||||||
*/
|
|
||||||
LogInfo("Server Manager Init");
|
LogInfo("Server Manager Init");
|
||||||
server.server_manager = new ServerManager();
|
server.server_manager = new WorldServerManager();
|
||||||
if (!server.server_manager) {
|
if (!server.server_manager) {
|
||||||
LogError("Server Manager Failed to Start");
|
LogError("Server Manager Failed to Start");
|
||||||
LogInfo("Database System Shutdown");
|
LogInfo("Database System Shutdown");
|
||||||
delete server.db;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* create client manager
|
|
||||||
*/
|
|
||||||
LogInfo("Client Manager Init");
|
LogInfo("Client Manager Init");
|
||||||
server.client_manager = new ClientManager();
|
server.client_manager = new ClientManager();
|
||||||
if (!server.client_manager) {
|
if (!server.client_manager) {
|
||||||
@ -242,7 +204,6 @@ int main(int argc, char **argv)
|
|||||||
delete server.server_manager;
|
delete server.server_manager;
|
||||||
|
|
||||||
LogInfo("Database System Shutdown");
|
LogInfo("Database System Shutdown");
|
||||||
delete server.db;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,37 +217,33 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
LogInfo("Server Started");
|
LogInfo("Server Started");
|
||||||
|
|
||||||
/**
|
|
||||||
* Web API
|
|
||||||
*/
|
|
||||||
bool web_api_enabled = server.config.GetVariableBool("web_api", "enabled", true);
|
bool web_api_enabled = server.config.GetVariableBool("web_api", "enabled", true);
|
||||||
if (web_api_enabled) {
|
if (web_api_enabled) {
|
||||||
std::thread web_api_thread(start_web_server);
|
std::thread web_api_thread(start_web_server);
|
||||||
web_api_thread.detach();
|
web_api_thread.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
LogInfo("[Config] [Account] CanAutoCreateAccounts [{0}]", server.options.CanAutoCreateAccounts());
|
LogInfo("[Config] [Account] CanAutoCreateAccounts [{}]", server.options.CanAutoCreateAccounts());
|
||||||
LogInfo("[Config] [ClientConfiguration] DisplayExpansions [{0}]", server.options.IsDisplayExpansions());
|
LogInfo("[Config] [ClientConfiguration] DisplayExpansions [{}]", server.options.IsDisplayExpansions());
|
||||||
LogInfo("[Config] [ClientConfiguration] MaxExpansions [{0}]", server.options.GetMaxExpansions());
|
LogInfo("[Config] [ClientConfiguration] MaxExpansions [{}]", server.options.GetMaxExpansions());
|
||||||
|
|
||||||
#ifdef LSPX
|
if (std::getenv("LSPX")) {
|
||||||
LogInfo("[Config] [Account] CanAutoLinkAccounts [{0}]", server.options.CanAutoLinkAccounts());
|
LogInfo("[Config] [Account] LSPX [on]");
|
||||||
#endif
|
}
|
||||||
LogInfo("[Config] [WorldServer] IsRejectingDuplicateServers [{0}]", server.options.IsRejectingDuplicateServers());
|
|
||||||
LogInfo("[Config] [WorldServer] IsUnregisteredAllowed [{0}]", server.options.IsUnregisteredAllowed());
|
LogInfo("[Config] [WorldServer] IsRejectingDuplicateServers [{}]", server.options.IsRejectingDuplicateServers());
|
||||||
LogInfo("[Config] [WorldServer] ShowPlayerCount [{0}]", server.options.IsShowPlayerCountEnabled());
|
LogInfo("[Config] [WorldServer] IsUnregisteredAllowed [{}]", server.options.IsUnregisteredAllowed());
|
||||||
|
LogInfo("[Config] [WorldServer] ShowPlayerCount [{}]", server.options.IsShowPlayerCountEnabled());
|
||||||
LogInfo(
|
LogInfo(
|
||||||
"[Config] [WorldServer] DevAndTestServersListBottom [{0}]",
|
"[Config] [WorldServer] DevAndTestServersListBottom [{}]",
|
||||||
server.options.IsWorldDevTestServersListBottom()
|
server.options.IsWorldDevTestServersListBottom()
|
||||||
);
|
);
|
||||||
LogInfo(
|
LogInfo(
|
||||||
"[Config] [WorldServer] SpecialCharactersStartListBottom [{0}]",
|
"[Config] [WorldServer] SpecialCharactersStartListBottom [{}]",
|
||||||
server.options.IsWorldSpecialCharacterStartListBottom()
|
server.options.IsWorldSpecialCharacterStartListBottom()
|
||||||
);
|
);
|
||||||
LogInfo("[Config] [Security] GetEncryptionMode [{0}]", server.options.GetEncryptionMode());
|
LogInfo("[Config] [Security] GetEncryptionMode [{}]", server.options.GetEncryptionMode());
|
||||||
LogInfo("[Config] [Security] IsTokenLoginAllowed [{0}]", server.options.IsTokenLoginAllowed());
|
LogInfo("[Config] [Security] IsTokenLoginAllowed [{}]", server.options.IsTokenLoginAllowed());
|
||||||
LogInfo("[Config] [Security] IsPasswordLoginAllowed [{0}]", server.options.IsPasswordLoginAllowed());
|
|
||||||
LogInfo("[Config] [Security] IsUpdatingInsecurePasswords [{0}]", server.options.IsUpdatingInsecurePasswords());
|
|
||||||
|
|
||||||
Timer keepalive(INTERSERVER_TIMER); // does auto-reconnect
|
Timer keepalive(INTERSERVER_TIMER); // does auto-reconnect
|
||||||
|
|
||||||
@ -295,7 +252,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
if (keepalive.Check()) {
|
if (keepalive.Check()) {
|
||||||
keepalive.Start();
|
keepalive.Start();
|
||||||
server.db->ping();
|
database.ping();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!run_server) {
|
if (!run_server) {
|
||||||
@ -319,8 +276,5 @@ int main(int argc, char **argv)
|
|||||||
LogInfo("Server Manager Shutdown");
|
LogInfo("Server Manager Shutdown");
|
||||||
delete server.server_manager;
|
delete server.server_manager;
|
||||||
|
|
||||||
LogInfo("Database System Shutdown");
|
|
||||||
delete server.db;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,124 +1,55 @@
|
|||||||
#ifndef EQEMU_OPTIONS_H
|
#ifndef EQEMU_OPTIONS_H
|
||||||
#define EQEMU_OPTIONS_H
|
#define EQEMU_OPTIONS_H
|
||||||
|
|
||||||
/**
|
|
||||||
* Collects options on one object, because having a bunch of global variables floating around is
|
|
||||||
* really ugly and just a little dangerous.
|
|
||||||
*/
|
|
||||||
class Options {
|
class Options {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor: Default options
|
|
||||||
*/
|
|
||||||
Options() :
|
Options() :
|
||||||
allow_unregistered(true),
|
m_allow_unregistered(true),
|
||||||
display_expansions(false),
|
m_display_expansions(false),
|
||||||
max_expansions_mask(0),
|
m_max_expansions_mask(0),
|
||||||
encryption_mode(5),
|
m_encryption_mode(14),
|
||||||
reject_duplicate_servers(false),
|
m_reject_duplicate_servers(false),
|
||||||
allow_password_login(true),
|
m_allow_token_login(false),
|
||||||
allow_token_login(false),
|
m_auto_create_accounts(false) {}
|
||||||
auto_create_accounts(false) {}
|
|
||||||
|
|
||||||
/**
|
inline void AllowUnregistered(bool b) { m_allow_unregistered = b; }
|
||||||
* Sets allow_unregistered.
|
inline void DisplayExpansions(bool b) { m_display_expansions = b; }
|
||||||
*/
|
inline void MaxExpansions(int i) { m_max_expansions_mask = i; }
|
||||||
inline void AllowUnregistered(bool b) { allow_unregistered = b; }
|
inline bool IsDisplayExpansions() const { return m_display_expansions; }
|
||||||
|
inline int GetMaxExpansions() const { return m_max_expansions_mask; }
|
||||||
/**
|
inline bool IsUnregisteredAllowed() const { return m_allow_unregistered; }
|
||||||
* Returns the value of expansion display settings.
|
inline void EncryptionMode(int m) { m_encryption_mode = m; }
|
||||||
*/
|
inline int GetEncryptionMode() const { return m_encryption_mode; }
|
||||||
inline void DisplayExpansions(bool b) { display_expansions = b; }
|
inline void RejectDuplicateServers(bool b) { m_reject_duplicate_servers = b; }
|
||||||
inline void MaxExpansions(int i) { max_expansions_mask = i; }
|
inline bool IsRejectingDuplicateServers() { return m_reject_duplicate_servers; }
|
||||||
inline bool IsDisplayExpansions() const { return display_expansions; }
|
inline void AllowTokenLogin(bool b) { m_allow_token_login = b; }
|
||||||
inline int GetMaxExpansions() const { return max_expansions_mask; }
|
inline bool IsTokenLoginAllowed() const { return m_allow_token_login; }
|
||||||
|
inline void AutoCreateAccounts(bool b) { m_auto_create_accounts = b; }
|
||||||
/**
|
inline bool CanAutoCreateAccounts() const { return m_auto_create_accounts; }
|
||||||
* Returns the value of allow_unregistered.
|
inline void EQEmuLoginServerAddress(const std::string &v) { m_eqemu_loginserver_address = v; }
|
||||||
*/
|
inline std::string GetEQEmuLoginServerAddress() const { return m_eqemu_loginserver_address; }
|
||||||
inline bool IsUnregisteredAllowed() const { return allow_unregistered; }
|
inline void DefaultLoginServerName(const std::string &v) { m_default_loginserver_name = v; }
|
||||||
|
inline std::string GetDefaultLoginServerName() const { return m_default_loginserver_name; }
|
||||||
/**
|
inline bool IsShowPlayerCountEnabled() const { return m_show_player_count; }
|
||||||
* Sets encryption_mode.
|
inline void SetShowPlayerCount(bool show_player_count) { show_player_count = show_player_count; }
|
||||||
*/
|
inline bool IsWorldDevTestServersListBottom() const { return m_world_dev_list_bottom; }
|
||||||
inline void EncryptionMode(int m) { encryption_mode = m; }
|
inline void SetWorldDevTestServersListBottom(bool list_bottom) { m_world_dev_list_bottom = list_bottom; }
|
||||||
|
inline bool IsWorldSpecialCharacterStartListBottom() const { return m_special_char_list_bottom; }
|
||||||
/**
|
inline void SetWorldSpecialCharacterStartListBottom(bool list_bottom) { m_special_char_list_bottom = list_bottom; }
|
||||||
* Returns the value of encryption_mode.
|
|
||||||
*/
|
|
||||||
inline int GetEncryptionMode() const { return encryption_mode; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether we are rejecting duplicate servers or not.
|
|
||||||
*/
|
|
||||||
inline void RejectDuplicateServers(bool b) { reject_duplicate_servers = b; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether we are rejecting duplicate servers or not.
|
|
||||||
*/
|
|
||||||
inline bool IsRejectingDuplicateServers() { return reject_duplicate_servers; }
|
|
||||||
|
|
||||||
inline void AllowTokenLogin(bool b) { allow_token_login = b; }
|
|
||||||
inline bool IsTokenLoginAllowed() const { return allow_token_login; }
|
|
||||||
|
|
||||||
inline void AllowPasswordLogin(bool b) { allow_password_login = b; }
|
|
||||||
inline bool IsPasswordLoginAllowed() const { return allow_password_login; }
|
|
||||||
|
|
||||||
inline void AutoCreateAccounts(bool b) { auto_create_accounts = b; }
|
|
||||||
inline bool CanAutoCreateAccounts() const { return auto_create_accounts; }
|
|
||||||
|
|
||||||
inline void AutoLinkAccounts(bool b) { auto_link_accounts = b; }
|
|
||||||
inline bool CanAutoLinkAccounts() const { return auto_link_accounts; }
|
|
||||||
|
|
||||||
inline void EQEmuLoginServerAddress(const std::string& v) { eqemu_loginserver_address = v; }
|
|
||||||
inline std::string GetEQEmuLoginServerAddress() const { return eqemu_loginserver_address; }
|
|
||||||
|
|
||||||
inline void DefaultLoginServerName(const 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; }
|
|
||||||
|
|
||||||
inline bool IsShowPlayerCountEnabled() const
|
|
||||||
{
|
|
||||||
return show_player_count;
|
|
||||||
}
|
|
||||||
inline void SetShowPlayerCount(bool show_player_count)
|
|
||||||
{
|
|
||||||
Options::show_player_count = show_player_count;
|
|
||||||
}
|
|
||||||
inline bool IsWorldDevTestServersListBottom() const { return world_dev_test_servers_list_bottom; }
|
|
||||||
inline void SetWorldDevTestServersListBottom(bool dev_test_servers_list_bottom)
|
|
||||||
{
|
|
||||||
Options::world_dev_test_servers_list_bottom = dev_test_servers_list_bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool IsWorldSpecialCharacterStartListBottom() const
|
|
||||||
{
|
|
||||||
return world_special_character_start_list_bottom;
|
|
||||||
}
|
|
||||||
inline void SetWorldSpecialCharacterStartListBottom(bool world_special_character_start_list_bottom)
|
|
||||||
{
|
|
||||||
Options::world_special_character_start_list_bottom = world_special_character_start_list_bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool allow_unregistered;
|
bool m_allow_unregistered;
|
||||||
bool display_expansions;
|
bool m_display_expansions;
|
||||||
bool reject_duplicate_servers;
|
bool m_reject_duplicate_servers;
|
||||||
bool world_dev_test_servers_list_bottom;
|
bool m_world_dev_list_bottom;
|
||||||
bool world_special_character_start_list_bottom;
|
bool m_special_char_list_bottom;
|
||||||
bool allow_token_login;
|
bool m_allow_token_login;
|
||||||
bool allow_password_login;
|
bool m_show_player_count;
|
||||||
bool show_player_count;
|
bool m_auto_create_accounts;
|
||||||
bool auto_create_accounts;
|
int m_encryption_mode;
|
||||||
bool auto_link_accounts;
|
int m_max_expansions_mask;
|
||||||
bool update_insecure_passwords;
|
std::string m_eqemu_loginserver_address;
|
||||||
int encryption_mode;
|
std::string m_default_loginserver_name;
|
||||||
int max_expansions_mask;
|
|
||||||
std::string eqemu_loginserver_address;
|
|
||||||
std::string default_loginserver_name;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,248 +0,0 @@
|
|||||||
#include "server_manager.h"
|
|
||||||
#include "login_server.h"
|
|
||||||
#include "login_types.h"
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "../common/eqemu_logsys.h"
|
|
||||||
#include "../common/ip_util.h"
|
|
||||||
|
|
||||||
extern LoginServer server;
|
|
||||||
extern bool run_server;
|
|
||||||
|
|
||||||
ServerManager::ServerManager()
|
|
||||||
{
|
|
||||||
int listen_port = server.config.GetVariableInt("general", "listen_port", 5998);
|
|
||||||
|
|
||||||
m_server_connection = std::make_unique<EQ::Net::ServertalkServer>();
|
|
||||||
EQ::Net::ServertalkServerOptions opts;
|
|
||||||
opts.port = listen_port;
|
|
||||||
opts.ipv6 = false;
|
|
||||||
m_server_connection->Listen(opts);
|
|
||||||
|
|
||||||
LogInfo("Loginserver now listening on port [{0}]", listen_port);
|
|
||||||
|
|
||||||
m_server_connection->OnConnectionIdentified(
|
|
||||||
"World", [this](std::shared_ptr<EQ::Net::ServertalkServerConnection> world_connection) {
|
|
||||||
LogInfo(
|
|
||||||
"New World Server connection from {0}:{1}",
|
|
||||||
world_connection->Handle()->RemoteIP(),
|
|
||||||
world_connection->Handle()->RemotePort()
|
|
||||||
);
|
|
||||||
|
|
||||||
auto iter = m_world_servers.begin();
|
|
||||||
while (iter != m_world_servers.end()) {
|
|
||||||
if ((*iter)->GetConnection()->Handle()->RemoteIP().compare(world_connection->Handle()->RemoteIP()) ==
|
|
||||||
0 &&
|
|
||||||
(*iter)->GetConnection()->Handle()->RemotePort() == world_connection->Handle()->RemotePort()) {
|
|
||||||
|
|
||||||
LogInfo(
|
|
||||||
"World server already existed for {0}:{1}, removing existing connection.",
|
|
||||||
world_connection->Handle()->RemoteIP(),
|
|
||||||
world_connection->Handle()->RemotePort()
|
|
||||||
);
|
|
||||||
|
|
||||||
m_world_servers.erase(iter);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_world_servers.push_back(std::make_unique<WorldServer>(world_connection));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
m_server_connection->OnConnectionRemoved(
|
|
||||||
"World", [this](std::shared_ptr<EQ::Net::ServertalkServerConnection> c) {
|
|
||||||
auto iter = m_world_servers.begin();
|
|
||||||
while (iter != m_world_servers.end()) {
|
|
||||||
if ((*iter)->GetConnection()->GetUUID() == c->GetUUID()) {
|
|
||||||
LogInfo(
|
|
||||||
"World server {0} has been disconnected, removing.",
|
|
||||||
(*iter)->GetServerLongName()
|
|
||||||
);
|
|
||||||
m_world_servers.erase(iter);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ServerManager::~ServerManager() = default;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param client
|
|
||||||
* @param sequence
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
std::unique_ptr<EQApplicationPacket> ServerManager::CreateServerListPacket(Client *client, uint32 sequence)
|
|
||||||
{
|
|
||||||
unsigned int server_count = 0;
|
|
||||||
in_addr in{};
|
|
||||||
in.s_addr = client->GetConnection()->GetRemoteIP();
|
|
||||||
std::string client_ip = inet_ntoa(in);
|
|
||||||
|
|
||||||
LogDebug("ServerManager::CreateServerListPacket via client address [{0}]", client_ip);
|
|
||||||
|
|
||||||
for (const auto& world_server : m_world_servers)
|
|
||||||
{
|
|
||||||
if (world_server->IsAuthorized()) {
|
|
||||||
++server_count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SerializeBuffer buf;
|
|
||||||
|
|
||||||
// LoginBaseMessage_Struct header
|
|
||||||
buf.WriteInt32(sequence);
|
|
||||||
buf.WriteInt8(0);
|
|
||||||
buf.WriteInt8(0);
|
|
||||||
buf.WriteInt32(0);
|
|
||||||
|
|
||||||
// LoginBaseReplyMessage_Struct
|
|
||||||
buf.WriteInt8(true); // success (no error)
|
|
||||||
buf.WriteInt32(0x65); // 101 "No Error" eqlsstr
|
|
||||||
buf.WriteString("");
|
|
||||||
|
|
||||||
// ServerListReply_Struct
|
|
||||||
buf.WriteInt32(server_count);
|
|
||||||
|
|
||||||
for (const auto& world_server : m_world_servers)
|
|
||||||
{
|
|
||||||
if (!world_server->IsAuthorized()) {
|
|
||||||
LogDebug(
|
|
||||||
"ServerManager::CreateServerListPacket | Server [{}] via IP [{}] is not authorized to be listed",
|
|
||||||
world_server->GetServerLongName(),
|
|
||||||
world_server->GetConnection()->Handle()->RemoteIP()
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool use_local_ip = false;
|
|
||||||
|
|
||||||
std::string world_ip = world_server->GetConnection()->Handle()->RemoteIP();
|
|
||||||
if (world_ip == client_ip || IpUtil::IsIpInPrivateRfc1918(client_ip)) {
|
|
||||||
use_local_ip = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
LogDebug(
|
|
||||||
"CreateServerListPacket | Building list entry | Client [{}] IP [{}] Server Long Name [{}] Server IP [{}] ({})",
|
|
||||||
client->GetAccountName(),
|
|
||||||
client_ip,
|
|
||||||
world_server->GetServerLongName(),
|
|
||||||
use_local_ip ? world_server->GetLocalIP() : world_server->GetRemoteIP(),
|
|
||||||
use_local_ip ? "Local" : "Remote"
|
|
||||||
);
|
|
||||||
|
|
||||||
world_server->SerializeForClientServerList(buf, use_local_ip, client->GetClientVersion());
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_unique<EQApplicationPacket>(OP_ServerListResponse, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param server_id
|
|
||||||
* @param client_account_id
|
|
||||||
* @param client_loginserver
|
|
||||||
*/
|
|
||||||
void ServerManager::SendUserToWorldRequest(
|
|
||||||
unsigned int server_id,
|
|
||||||
unsigned int client_account_id,
|
|
||||||
const std::string &client_loginserver
|
|
||||||
)
|
|
||||||
{
|
|
||||||
auto iter = m_world_servers.begin();
|
|
||||||
bool found = false;
|
|
||||||
while (iter != m_world_servers.end()) {
|
|
||||||
if ((*iter)->GetServerId() == server_id) {
|
|
||||||
EQ::Net::DynamicPacket outapp;
|
|
||||||
outapp.Resize(sizeof(UsertoWorldRequest_Struct));
|
|
||||||
|
|
||||||
auto *r = (UsertoWorldRequest_Struct *) outapp.Data();
|
|
||||||
r->worldid = server_id;
|
|
||||||
r->lsaccountid = client_account_id;
|
|
||||||
strncpy(r->login, &client_loginserver[0], 64);
|
|
||||||
(*iter)->GetConnection()->Send(ServerOP_UsertoWorldReq, outapp);
|
|
||||||
found = true;
|
|
||||||
|
|
||||||
LogNetcode(
|
|
||||||
"[UsertoWorldRequest] [Size: {}]\n{}",
|
|
||||||
outapp.Length(),
|
|
||||||
outapp.ToString()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
LogError("Client requested a user to world but supplied an invalid id of {0}", server_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param server_long_name
|
|
||||||
* @param server_short_name
|
|
||||||
* @param ignore
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool ServerManager::ServerExists(
|
|
||||||
std::string server_long_name,
|
|
||||||
std::string server_short_name,
|
|
||||||
WorldServer *ignore
|
|
||||||
)
|
|
||||||
{
|
|
||||||
auto iter = m_world_servers.begin();
|
|
||||||
while (iter != m_world_servers.end()) {
|
|
||||||
if ((*iter).get() == ignore) {
|
|
||||||
++iter;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((*iter)->GetServerLongName() == server_long_name && (*iter)->GetServerShortName() == server_short_name) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param server_long_name
|
|
||||||
* @param server_short_name
|
|
||||||
* @param ignore
|
|
||||||
*/
|
|
||||||
void ServerManager::DestroyServerByName(
|
|
||||||
std::string server_long_name,
|
|
||||||
std::string server_short_name,
|
|
||||||
WorldServer *ignore
|
|
||||||
)
|
|
||||||
{
|
|
||||||
auto iter = m_world_servers.begin();
|
|
||||||
while (iter != m_world_servers.end()) {
|
|
||||||
if ((*iter).get() == ignore) {
|
|
||||||
++iter;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((*iter)->GetServerLongName().compare(server_long_name) == 0 &&
|
|
||||||
(*iter)->GetServerShortName().compare(server_short_name) == 0) {
|
|
||||||
(*iter)->GetConnection()->Handle()->Disconnect();
|
|
||||||
iter = m_world_servers.erase(iter);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
const std::list<std::unique_ptr<WorldServer>> &ServerManager::getWorldServers() const
|
|
||||||
{
|
|
||||||
return m_world_servers;
|
|
||||||
}
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
#ifndef EQEMU_SERVERMANAGER_H
|
|
||||||
#define EQEMU_SERVERMANAGER_H
|
|
||||||
|
|
||||||
#include "../common/global_define.h"
|
|
||||||
#include "../common/servertalk.h"
|
|
||||||
#include "../common/packet_dump.h"
|
|
||||||
#include "../common/net/servertalk_server.h"
|
|
||||||
#include "world_server.h"
|
|
||||||
#include "client.h"
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Server manager class, deals with management of the world servers
|
|
||||||
*/
|
|
||||||
class ServerManager {
|
|
||||||
public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor, sets up the TCP server and starts listening
|
|
||||||
*/
|
|
||||||
ServerManager();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor, shuts down the TCP server.
|
|
||||||
*/
|
|
||||||
~ServerManager();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a request to world to see if the client is banned or suspended
|
|
||||||
*
|
|
||||||
* @param server_id
|
|
||||||
* @param client_account_id
|
|
||||||
* @param client_loginserver
|
|
||||||
*/
|
|
||||||
void SendUserToWorldRequest(
|
|
||||||
unsigned int server_id,
|
|
||||||
unsigned int client_account_id,
|
|
||||||
const std::string &client_loginserver
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a server list packet for the client
|
|
||||||
*
|
|
||||||
* @param client
|
|
||||||
* @param sequence
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
std::unique_ptr<EQApplicationPacket> CreateServerListPacket(Client *client, uint32 sequence);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks to see if there is a server exists with this name, ignoring option
|
|
||||||
*
|
|
||||||
* @param server_long_name
|
|
||||||
* @param server_short_name
|
|
||||||
* @param ignore
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool ServerExists(std::string server_long_name, std::string server_short_name, WorldServer *ignore = nullptr);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroys a server with this name, ignoring option
|
|
||||||
*
|
|
||||||
* @param server_long_name
|
|
||||||
* @param server_short_name
|
|
||||||
* @param ignore
|
|
||||||
*/
|
|
||||||
void DestroyServerByName(std::string server_long_name, std::string server_short_name, WorldServer *ignore = nullptr);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
const std::list<std::unique_ptr<WorldServer>> &getWorldServers() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<EQ::Net::ServertalkServer> m_server_connection;
|
|
||||||
std::list<std::unique_ptr<WorldServer>> m_world_servers;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -5,9 +5,10 @@
|
|||||||
#include "../common/net/servertalk_server_connection.h"
|
#include "../common/net/servertalk_server_connection.h"
|
||||||
#include "../common/servertalk.h"
|
#include "../common/servertalk.h"
|
||||||
#include "../common/packet_dump.h"
|
#include "../common/packet_dump.h"
|
||||||
#include "database.h"
|
|
||||||
#include "../common/event/timer.h"
|
#include "../common/event/timer.h"
|
||||||
#include "login_types.h"
|
#include "login_types.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "../common/repositories/login_server_admins_repository.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@ -17,25 +18,10 @@
|
|||||||
class WorldServer {
|
class WorldServer {
|
||||||
public:
|
public:
|
||||||
WorldServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> worldserver_connection);
|
WorldServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> worldserver_connection);
|
||||||
|
|
||||||
/**
|
|
||||||
* Destructor, frees our connection if it exists
|
|
||||||
*/
|
|
||||||
~WorldServer();
|
~WorldServer();
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets the basic stats of this server.
|
|
||||||
*/
|
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
/**
|
|
||||||
* Accesses connection, it is intentional that this is not const (trust me).
|
|
||||||
*/
|
|
||||||
std::shared_ptr<EQ::Net::ServertalkServerConnection> GetConnection() { return m_connection; }
|
std::shared_ptr<EQ::Net::ServertalkServerConnection> GetConnection() { return m_connection; }
|
||||||
|
|
||||||
/**
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
unsigned int GetServerId() const { return m_server_id; }
|
unsigned int GetServerId() const { return m_server_id; }
|
||||||
WorldServer *SetServerId(unsigned int id)
|
WorldServer *SetServerId(unsigned int id)
|
||||||
{
|
{
|
||||||
@ -43,25 +29,13 @@ public:
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
std::string GetServerLongName() const { return m_server_long_name; }
|
||||||
* @return
|
std::string GetServerShortName() const { return m_server_short_name; }
|
||||||
*/
|
bool IsAuthorizedToList() const { return m_is_server_authorized_to_list; }
|
||||||
std::string GetServerLongName() const { return m_long_name; }
|
|
||||||
std::string GetServerShortName() const { return m_short_name; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets whether the server is authorized to show up on the server list or not
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool IsAuthorized() const { return m_is_server_authorized; }
|
|
||||||
std::string GetLocalIP() const { return m_local_ip; }
|
std::string GetLocalIP() const { return m_local_ip; }
|
||||||
std::string GetRemoteIP() const { return m_remote_ip_address; }
|
std::string GetRemoteIP() const { return m_remote_ip_address; }
|
||||||
|
|
||||||
/**
|
// Gets what kind of server this server is (legends, preferred, normal)
|
||||||
* Gets what kind of server this server is (legends, preferred, normal)
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
unsigned int GetServerListID() const { return m_server_list_type_id; }
|
unsigned int GetServerListID() const { return m_server_list_type_id; }
|
||||||
WorldServer *SetServerListTypeId(unsigned int in_server_list_id);
|
WorldServer *SetServerListTypeId(unsigned int in_server_list_id);
|
||||||
|
|
||||||
@ -69,97 +43,18 @@ public:
|
|||||||
unsigned int GetZonesBooted() const { return m_zones_booted; }
|
unsigned int GetZonesBooted() const { return m_zones_booted; }
|
||||||
unsigned int GetPlayersOnline() const { return m_players_online; }
|
unsigned int GetPlayersOnline() const { return m_players_online; }
|
||||||
|
|
||||||
/**
|
void HandleNewWorldserver(LoginserverNewWorldRequest *req);
|
||||||
* Takes the info struct we received from world and processes it
|
void HandleWorldserverStatusUpdate(LoginserverWorldStatusUpdate *u);
|
||||||
*
|
bool HandleNewWorldserverValidation(LoginserverNewWorldRequest *r);
|
||||||
* @param new_world_server_info_packet
|
void SendClientAuthToWorld(Client *c);
|
||||||
*/
|
|
||||||
void Handle_NewLSInfo(ServerNewLSInfo_Struct *new_world_server_info_packet);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes the status struct we received from world and processes it
|
|
||||||
*
|
|
||||||
* @param server_login_status
|
|
||||||
*/
|
|
||||||
void Handle_LSStatus(ServerLSStatus_Struct *server_login_status);
|
|
||||||
|
|
||||||
bool HandleNewLoginserverInfoValidation(ServerNewLSInfo_Struct *new_world_server_info_packet);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Informs world that there is a client incoming with the following data.
|
|
||||||
*
|
|
||||||
* @param ip
|
|
||||||
* @param account
|
|
||||||
* @param key
|
|
||||||
* @param account_id
|
|
||||||
* @param loginserver_name
|
|
||||||
*/
|
|
||||||
void SendClientAuth(
|
|
||||||
std::string ip,
|
|
||||||
std::string account,
|
|
||||||
std::string key,
|
|
||||||
unsigned int account_id,
|
|
||||||
const std::string &loginserver_name
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param world_admin_id
|
|
||||||
* @param world_admin_username
|
|
||||||
* @param world_admin_password
|
|
||||||
* @param world_admin_password_hash
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
static bool ValidateWorldServerAdminLogin(
|
static bool ValidateWorldServerAdminLogin(
|
||||||
int world_admin_id,
|
LoginWorldAdminAccountContext &c,
|
||||||
const std::string &world_admin_username,
|
LoginServerAdminsRepository::LoginServerAdmins &admin
|
||||||
const std::string &world_admin_password,
|
|
||||||
const std::string &world_admin_password_hash
|
|
||||||
);
|
);
|
||||||
|
void SerializeForClientServerList(class SerializeBuffer &out, bool use_local_ip, LSClientVersion version) const;
|
||||||
WorldServer *SetZonesBooted(unsigned int in_zones_booted);
|
|
||||||
WorldServer *SetPlayersOnline(unsigned int in_players_online);
|
|
||||||
WorldServer *SetServerStatus(int in_server_status);
|
|
||||||
WorldServer *SetServerProcessType(unsigned int in_server_process_type);
|
|
||||||
WorldServer *SetLongName(const std::string &in_long_name);
|
|
||||||
WorldServer *SetShortName(const std::string &in_short_name);
|
|
||||||
WorldServer *SetAccountName(const std::string &in_account_name);
|
|
||||||
WorldServer *SetAccountPassword(const std::string &in_account_password);
|
|
||||||
WorldServer *SetRemoteIp(const std::string &in_remote_ip);
|
|
||||||
WorldServer *SetLocalIp(const std::string &in_local_ip);
|
|
||||||
WorldServer *SetProtocol(const std::string &in_protocol);
|
|
||||||
WorldServer *SetVersion(const std::string &in_version);
|
|
||||||
WorldServer *SetServerDescription(const std::string &in_server_description);
|
|
||||||
WorldServer *SetIsServerAuthorized(bool in_is_server_authorized);
|
|
||||||
WorldServer *SetIsServerLoggedIn(bool in_is_server_logged_in);
|
|
||||||
WorldServer *SetIsServerTrusted(bool in_is_server_trusted);
|
|
||||||
|
|
||||||
bool IsServerAuthorized() const;
|
|
||||||
bool IsServerLoggedIn() const;
|
|
||||||
bool IsServerTrusted() const;
|
|
||||||
const std::string &GetAccountName() const;
|
|
||||||
const std::string &GetAccountPassword() const;
|
|
||||||
const std::string &GetLocalIp() const;
|
|
||||||
const std::string &GetProtocol() const;
|
|
||||||
const std::string &GetRemoteIp() const;
|
|
||||||
const std::string &GetServerDescription() const;
|
|
||||||
const std::string &GetVersion() const;
|
|
||||||
int GetServerStatus() const;
|
|
||||||
unsigned int GetServerListTypeId() const;
|
|
||||||
unsigned int GetServerProcessType() const;
|
|
||||||
|
|
||||||
bool HandleNewLoginserverRegisteredOnly(Database::DbWorldRegistration &world_registration);
|
|
||||||
bool HandleNewLoginserverInfoUnregisteredAllowed(Database::DbWorldRegistration &world_registration);
|
|
||||||
|
|
||||||
void SerializeForClientServerList(class SerializeBuffer& out, bool use_local_ip, LSClientVersion version) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/**
|
|
||||||
* Packet processing functions
|
|
||||||
*
|
|
||||||
* @param opcode
|
|
||||||
* @param packet
|
|
||||||
*/
|
|
||||||
void ProcessNewLSInfo(uint16_t opcode, const EQ::Net::Packet &packet);
|
void ProcessNewLSInfo(uint16_t opcode, const EQ::Net::Packet &packet);
|
||||||
void ProcessLSStatus(uint16_t opcode, const EQ::Net::Packet &packet);
|
void ProcessLSStatus(uint16_t opcode, const EQ::Net::Packet &packet);
|
||||||
void ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Net::Packet &packet);
|
void ProcessUserToWorldResponseLegacy(uint16_t opcode, const EQ::Net::Packet &packet);
|
||||||
@ -175,15 +70,15 @@ private:
|
|||||||
unsigned int m_server_list_type_id;
|
unsigned int m_server_list_type_id;
|
||||||
unsigned int m_server_process_type;
|
unsigned int m_server_process_type;
|
||||||
std::string m_server_description;
|
std::string m_server_description;
|
||||||
std::string m_long_name;
|
std::string m_server_long_name;
|
||||||
std::string m_short_name;
|
std::string m_server_short_name;
|
||||||
std::string m_account_name;
|
std::string m_account_name;
|
||||||
std::string m_account_password;
|
std::string m_account_password;
|
||||||
std::string m_remote_ip_address;
|
std::string m_remote_ip_address;
|
||||||
std::string m_local_ip;
|
std::string m_local_ip;
|
||||||
std::string m_protocol;
|
std::string m_protocol;
|
||||||
std::string m_version;
|
std::string m_server_version;
|
||||||
bool m_is_server_authorized;
|
bool m_is_server_authorized_to_list;
|
||||||
bool m_is_server_logged_in;
|
bool m_is_server_logged_in;
|
||||||
bool m_is_server_trusted;
|
bool m_is_server_trusted;
|
||||||
|
|
||||||
|
|||||||
218
loginserver/world_server_manager.cpp
Normal file
218
loginserver/world_server_manager.cpp
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
#include "world_server_manager.h"
|
||||||
|
#include "login_server.h"
|
||||||
|
#include "login_types.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "../common/eqemu_logsys.h"
|
||||||
|
#include "../common/ip_util.h"
|
||||||
|
|
||||||
|
extern LoginServer server;
|
||||||
|
extern bool run_server;
|
||||||
|
|
||||||
|
WorldServerManager::WorldServerManager()
|
||||||
|
{
|
||||||
|
int listen_port = server.config.GetVariableInt("general", "listen_port", 5998);
|
||||||
|
|
||||||
|
m_server_connection = std::make_unique<EQ::Net::ServertalkServer>();
|
||||||
|
EQ::Net::ServertalkServerOptions opts;
|
||||||
|
opts.port = listen_port;
|
||||||
|
opts.ipv6 = false;
|
||||||
|
m_server_connection->Listen(opts);
|
||||||
|
|
||||||
|
LogInfo("Loginserver now listening on port [{}]", listen_port);
|
||||||
|
|
||||||
|
m_server_connection->OnConnectionIdentified(
|
||||||
|
"World", [this](std::shared_ptr<EQ::Net::ServertalkServerConnection> c) {
|
||||||
|
LogInfo(
|
||||||
|
"New World Server connection from remote_ip [{}] port [{}]",
|
||||||
|
c->Handle()->RemoteIP(),
|
||||||
|
c->Handle()->RemotePort()
|
||||||
|
);
|
||||||
|
|
||||||
|
auto iter = std::find_if(
|
||||||
|
m_world_servers.begin(), m_world_servers.end(),
|
||||||
|
[&](const std::unique_ptr<WorldServer> &s) {
|
||||||
|
return s->GetConnection()->Handle()->RemoteIP() == c->Handle()->RemoteIP() &&
|
||||||
|
s->GetConnection()->Handle()->RemotePort() == c->Handle()->RemotePort();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (iter != m_world_servers.end()) {
|
||||||
|
LogInfo(
|
||||||
|
"World server already existed for remote_ip [{}] port [{}] removing existing connection.",
|
||||||
|
c->Handle()->RemoteIP(),
|
||||||
|
c->Handle()->RemotePort()
|
||||||
|
);
|
||||||
|
|
||||||
|
m_world_servers.erase(iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_world_servers.push_back(std::make_unique<WorldServer>(c));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
m_server_connection->OnConnectionRemoved(
|
||||||
|
"World", [this](std::shared_ptr<EQ::Net::ServertalkServerConnection> c) {
|
||||||
|
auto iter = std::find_if(
|
||||||
|
m_world_servers.begin(), m_world_servers.end(),
|
||||||
|
[&](const std::unique_ptr<WorldServer> &server) {
|
||||||
|
return server->GetConnection()->GetUUID() == c->GetUUID();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (iter != m_world_servers.end()) {
|
||||||
|
LogInfo(
|
||||||
|
"World server ID [{}] long_name [{}] short_name [{}] has been disconnected, removing.",
|
||||||
|
(*iter)->GetServerId(),
|
||||||
|
(*iter)->GetServerLongName(),
|
||||||
|
(*iter)->GetServerShortName()
|
||||||
|
);
|
||||||
|
m_world_servers.erase(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldServerManager::~WorldServerManager() = default;
|
||||||
|
|
||||||
|
std::unique_ptr<EQApplicationPacket> WorldServerManager::CreateServerListPacket(Client *client, uint32 sequence)
|
||||||
|
{
|
||||||
|
unsigned int server_count = 0;
|
||||||
|
in_addr in{};
|
||||||
|
in.s_addr = client->GetConnection()->GetRemoteIP();
|
||||||
|
std::string client_ip = inet_ntoa(in);
|
||||||
|
|
||||||
|
LogDebug("ServerManager::CreateServerListPacket via client address [{}]", client_ip);
|
||||||
|
|
||||||
|
for (const auto &world_server: m_world_servers) {
|
||||||
|
if (world_server->IsAuthorizedToList()) {
|
||||||
|
++server_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializeBuffer buf;
|
||||||
|
|
||||||
|
// LoginBaseMessage_Struct header
|
||||||
|
buf.WriteInt32(sequence);
|
||||||
|
buf.WriteInt8(0);
|
||||||
|
buf.WriteInt8(0);
|
||||||
|
buf.WriteInt32(0);
|
||||||
|
|
||||||
|
// LoginBaseReplyMessage_Struct
|
||||||
|
buf.WriteInt8(true); // success (no error)
|
||||||
|
buf.WriteInt32(0x65); // 101 "No Error" eqlsstr
|
||||||
|
buf.WriteString("");
|
||||||
|
|
||||||
|
// ServerListReply_Struct
|
||||||
|
buf.WriteInt32(server_count);
|
||||||
|
|
||||||
|
for (const auto &s: m_world_servers) {
|
||||||
|
if (!s->IsAuthorizedToList()) {
|
||||||
|
LogDebug(
|
||||||
|
"ServerManager::CreateServerListPacket | Server [{}] via IP [{}] is not authorized to be listed",
|
||||||
|
s->GetServerLongName(),
|
||||||
|
s->GetConnection()->Handle()->RemoteIP()
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool use_local_ip = false;
|
||||||
|
|
||||||
|
std::string world_ip = s->GetConnection()->Handle()->RemoteIP();
|
||||||
|
if (world_ip == client_ip || IpUtil::IsIpInPrivateRfc1918(client_ip)) {
|
||||||
|
use_local_ip = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogDebug(
|
||||||
|
"CreateServerListPacket | Building list entry | Client [{}] IP [{}] Server Long Name [{}] Server IP [{}] ({})",
|
||||||
|
client->GetAccountName(),
|
||||||
|
client_ip,
|
||||||
|
s->GetServerLongName(),
|
||||||
|
use_local_ip ? s->GetLocalIP() : s->GetRemoteIP(),
|
||||||
|
use_local_ip ? "Local" : "Remote"
|
||||||
|
);
|
||||||
|
|
||||||
|
s->SerializeForClientServerList(buf, use_local_ip, client->GetClientVersion());
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::make_unique<EQApplicationPacket>(OP_ServerListResponse, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldServerManager::SendUserLoginToWorldRequest(
|
||||||
|
unsigned int server_id,
|
||||||
|
unsigned int client_account_id,
|
||||||
|
const std::string &client_loginserver
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto iter = std::find_if(
|
||||||
|
m_world_servers.begin(), m_world_servers.end(),
|
||||||
|
[&](const std::unique_ptr<WorldServer> &server) {
|
||||||
|
return server->GetServerId() == server_id;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (iter != m_world_servers.end()) {
|
||||||
|
EQ::Net::DynamicPacket outapp;
|
||||||
|
outapp.Resize(sizeof(UsertoWorldRequest_Struct));
|
||||||
|
|
||||||
|
auto *r = reinterpret_cast<UsertoWorldRequest_Struct *>(outapp.Data());
|
||||||
|
r->worldid = server_id;
|
||||||
|
r->lsaccountid = client_account_id;
|
||||||
|
strncpy(r->login, client_loginserver.c_str(), 64);
|
||||||
|
|
||||||
|
(*iter)->GetConnection()->Send(ServerOP_UsertoWorldReq, outapp);
|
||||||
|
|
||||||
|
LogNetcode("[UsertoWorldRequest] [Size: {}]\n{}", outapp.Length(), outapp.ToString());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LogError("Client requested a user to world but supplied an invalid id of {}", server_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WorldServerManager::DoesServerExist(
|
||||||
|
const std::string &server_long_name,
|
||||||
|
const std::string &server_short_name,
|
||||||
|
WorldServer *ignore
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return std::any_of(
|
||||||
|
m_world_servers.begin(), m_world_servers.end(), [&](const std::unique_ptr<WorldServer> &s) {
|
||||||
|
return s.get() != ignore &&
|
||||||
|
s->GetServerLongName() == server_long_name &&
|
||||||
|
s->GetServerShortName() == server_short_name;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldServerManager::DestroyServerByName(
|
||||||
|
std::string server_long_name,
|
||||||
|
std::string server_short_name,
|
||||||
|
WorldServer *ignore
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::erase_if(
|
||||||
|
m_world_servers, [&](const std::unique_ptr<WorldServer> &s) {
|
||||||
|
if (s.get() == ignore) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (s->GetServerLongName() == server_long_name &&
|
||||||
|
s->GetServerShortName() == server_short_name) {
|
||||||
|
s->GetConnection()->Handle()->Disconnect();
|
||||||
|
LogInfo(
|
||||||
|
"Removing world server ID [{}] long name [{}] short name [{}]",
|
||||||
|
s->GetServerId(),
|
||||||
|
server_long_name,
|
||||||
|
server_short_name
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::list<std::unique_ptr<WorldServer>> &WorldServerManager::GetWorldServers() const
|
||||||
|
{
|
||||||
|
return m_world_servers;
|
||||||
|
}
|
||||||
33
loginserver/world_server_manager.h
Normal file
33
loginserver/world_server_manager.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef EQEMU_SERVERMANAGER_H
|
||||||
|
#define EQEMU_SERVERMANAGER_H
|
||||||
|
|
||||||
|
#include "../common/global_define.h"
|
||||||
|
#include "../common/servertalk.h"
|
||||||
|
#include "../common/packet_dump.h"
|
||||||
|
#include "../common/net/servertalk_server.h"
|
||||||
|
#include "world_server.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
class WorldServerManager {
|
||||||
|
public:
|
||||||
|
WorldServerManager();
|
||||||
|
~WorldServerManager();
|
||||||
|
void SendUserLoginToWorldRequest(
|
||||||
|
unsigned int server_id,
|
||||||
|
unsigned int client_account_id,
|
||||||
|
const std::string &client_loginserver
|
||||||
|
);
|
||||||
|
std::unique_ptr<EQApplicationPacket> CreateServerListPacket(Client *client, uint32 sequence);
|
||||||
|
bool DoesServerExist(const std::string &s, const std::string &server_short_name, WorldServer *ignore = nullptr);
|
||||||
|
void DestroyServerByName(std::string s, std::string server_short_name, WorldServer *ignore = nullptr);
|
||||||
|
const std::list<std::unique_ptr<WorldServer>> &GetWorldServers() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<EQ::Net::ServertalkServer> m_server_connection;
|
||||||
|
std::list<std::unique_ptr<WorldServer>> m_world_servers;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@ -164,9 +164,9 @@ void ClientListEntry::LSUpdate(ZoneServer *iZS)
|
|||||||
if (WorldConfig::get()->UpdateStats) {
|
if (WorldConfig::get()->UpdateStats) {
|
||||||
auto pack = new ServerPacket;
|
auto pack = new ServerPacket;
|
||||||
pack->opcode = ServerOP_LSZoneInfo;
|
pack->opcode = ServerOP_LSZoneInfo;
|
||||||
pack->size = sizeof(ZoneInfo_Struct);
|
pack->size = sizeof(LoginserverZoneInfoUpdate);
|
||||||
pack->pBuffer = new uchar[pack->size];
|
pack->pBuffer = new uchar[pack->size];
|
||||||
ZoneInfo_Struct *zone = (ZoneInfo_Struct *) pack->pBuffer;
|
auto *zone = (LoginserverZoneInfoUpdate *) pack->pBuffer;
|
||||||
zone->count = iZS->NumPlayers();
|
zone->count = iZS->NumPlayers();
|
||||||
zone->zone = iZS->GetZoneID();
|
zone->zone = iZS->GetZoneID();
|
||||||
zone->zone_wid = iZS->GetID();
|
zone->zone_wid = iZS->GetID();
|
||||||
@ -174,6 +174,7 @@ void ClientListEntry::LSUpdate(ZoneServer *iZS)
|
|||||||
safe_delete(pack);
|
safe_delete(pack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientListEntry::LSZoneChange(ZoneToZone_Struct *ztz)
|
void ClientListEntry::LSZoneChange(ZoneToZone_Struct *ztz)
|
||||||
{
|
{
|
||||||
if (WorldConfig::get()->UpdateStats) {
|
if (WorldConfig::get()->UpdateStats) {
|
||||||
@ -181,7 +182,7 @@ void ClientListEntry::LSZoneChange(ZoneToZone_Struct *ztz)
|
|||||||
pack->opcode = ServerOP_LSPlayerZoneChange;
|
pack->opcode = ServerOP_LSPlayerZoneChange;
|
||||||
pack->size = sizeof(ServerLSPlayerZoneChange_Struct);
|
pack->size = sizeof(ServerLSPlayerZoneChange_Struct);
|
||||||
pack->pBuffer = new uchar[pack->size];
|
pack->pBuffer = new uchar[pack->size];
|
||||||
ServerLSPlayerZoneChange_Struct *zonechange = (ServerLSPlayerZoneChange_Struct *) pack->pBuffer;
|
auto *zonechange = (ServerLSPlayerZoneChange_Struct *) pack->pBuffer;
|
||||||
zonechange->lsaccount_id = LSID();
|
zonechange->lsaccount_id = LSID();
|
||||||
zonechange->from = ztz->current_zone_id;
|
zonechange->from = ztz->current_zone_id;
|
||||||
zonechange->to = ztz->requested_zone_id;
|
zonechange->to = ztz->requested_zone_id;
|
||||||
|
|||||||
@ -1,20 +1,3 @@
|
|||||||
/* EQEMu: Everquest Server Emulator
|
|
||||||
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; version 2 of the License.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
|
||||||
are required to give you total support for your newly bought product;
|
|
||||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
|
||||||
#include "../common/global_define.h"
|
#include "../common/global_define.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -37,7 +20,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include "cliententry.h"
|
#include "cliententry.h"
|
||||||
#include "world_config.h"
|
#include "world_config.h"
|
||||||
|
|
||||||
|
|
||||||
extern ZSList zoneserver_list;
|
extern ZSList zoneserver_list;
|
||||||
extern ClientList client_list;
|
extern ClientList client_list;
|
||||||
extern uint32 numzones;
|
extern uint32 numzones;
|
||||||
@ -609,11 +591,11 @@ void LoginServer::SendInfo()
|
|||||||
|
|
||||||
auto pack = new ServerPacket;
|
auto pack = new ServerPacket;
|
||||||
pack->opcode = ServerOP_NewLSInfo;
|
pack->opcode = ServerOP_NewLSInfo;
|
||||||
pack->size = sizeof(ServerNewLSInfo_Struct);
|
pack->size = sizeof(LoginserverNewWorldRequest);
|
||||||
pack->pBuffer = new uchar[pack->size];
|
pack->pBuffer = new uchar[pack->size];
|
||||||
memset(pack->pBuffer, 0, pack->size);
|
memset(pack->pBuffer, 0, pack->size);
|
||||||
|
|
||||||
auto *l = (ServerNewLSInfo_Struct *) pack->pBuffer;
|
auto *l = (LoginserverNewWorldRequest *) pack->pBuffer;
|
||||||
strcpy(l->protocol_version, EQEMU_PROTOCOL_VERSION);
|
strcpy(l->protocol_version, EQEMU_PROTOCOL_VERSION);
|
||||||
strcpy(l->server_version, LOGIN_VERSION);
|
strcpy(l->server_version, LOGIN_VERSION);
|
||||||
strcpy(l->server_long_name, Config->LongName.c_str());
|
strcpy(l->server_long_name, Config->LongName.c_str());
|
||||||
@ -657,10 +639,10 @@ void LoginServer::SendStatus()
|
|||||||
|
|
||||||
auto pack = new ServerPacket;
|
auto pack = new ServerPacket;
|
||||||
pack->opcode = ServerOP_LSStatus;
|
pack->opcode = ServerOP_LSStatus;
|
||||||
pack->size = sizeof(ServerLSStatus_Struct);
|
pack->size = sizeof(LoginserverWorldStatusUpdate);
|
||||||
pack->pBuffer = new uchar[pack->size];
|
pack->pBuffer = new uchar[pack->size];
|
||||||
memset(pack->pBuffer, 0, pack->size);
|
memset(pack->pBuffer, 0, pack->size);
|
||||||
auto loginserver_status = (ServerLSStatus_Struct *) pack->pBuffer;
|
auto loginserver_status = (LoginserverWorldStatusUpdate *) pack->pBuffer;
|
||||||
|
|
||||||
if (WorldConfig::get()->Locked) {
|
if (WorldConfig::get()->Locked) {
|
||||||
loginserver_status->status = -2;
|
loginserver_status->status = -2;
|
||||||
@ -678,9 +660,6 @@ void LoginServer::SendStatus()
|
|||||||
delete pack;
|
delete pack;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param pack
|
|
||||||
*/
|
|
||||||
void LoginServer::SendPacket(ServerPacket *pack)
|
void LoginServer::SendPacket(ServerPacket *pack)
|
||||||
{
|
{
|
||||||
if (m_legacy_client) {
|
if (m_legacy_client) {
|
||||||
@ -698,15 +677,15 @@ void LoginServer::SendAccountUpdate(ServerPacket *pack)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *ls_account_update = (ServerLSAccountUpdate_Struct *) pack->pBuffer;
|
auto *req = (LoginserverAccountUpdate *) pack->pBuffer;
|
||||||
if (CanUpdate()) {
|
if (CanUpdate()) {
|
||||||
LogInfo(
|
LogInfo(
|
||||||
"Sending ServerOP_LSAccountUpdate packet to loginserver: [{0}]:[{1}]",
|
"Sending ServerOP_LSAccountUpdate packet to loginserver: [{0}]:[{1}]",
|
||||||
m_loginserver_address,
|
m_loginserver_address,
|
||||||
m_loginserver_port
|
m_loginserver_port
|
||||||
);
|
);
|
||||||
strn0cpy(ls_account_update->worldaccount, m_login_account.c_str(), 30);
|
strn0cpy(req->world_account, m_login_account.c_str(), 30);
|
||||||
strn0cpy(ls_account_update->worldpassword, m_login_password.c_str(), 30);
|
strn0cpy(req->world_password, m_login_password.c_str(), 30);
|
||||||
SendPacket(pack);
|
SendPacket(pack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,14 +14,14 @@ void SetLoginserverInfo(Client *c, const Seperator *sep)
|
|||||||
const std::string& email = sep->arg[2];
|
const std::string& email = sep->arg[2];
|
||||||
const std::string& password = sep->arg[3];
|
const std::string& password = sep->arg[3];
|
||||||
|
|
||||||
auto pack = new ServerPacket(ServerOP_LSAccountUpdate, sizeof(ServerLSAccountUpdate_Struct));
|
auto pack = new ServerPacket(ServerOP_LSAccountUpdate, sizeof(LoginserverAccountUpdate));
|
||||||
|
|
||||||
auto s = (ServerLSAccountUpdate_Struct *) pack->pBuffer;
|
auto s = (LoginserverAccountUpdate *) pack->pBuffer;
|
||||||
|
|
||||||
s->useraccountid = c->LSAccountID();
|
s->user_account_id = c->LSAccountID();
|
||||||
strn0cpy(s->useraccount, c->AccountName(), 30);
|
strn0cpy(s->user_account_name, c->AccountName(), 30);
|
||||||
strn0cpy(s->user_email, email.c_str(), 100);
|
strn0cpy(s->user_email, email.c_str(), 100);
|
||||||
strn0cpy(s->userpassword, password.c_str(), 50);
|
strn0cpy(s->user_account_password, password.c_str(), 50);
|
||||||
|
|
||||||
worldserver.SendPacket(pack);
|
worldserver.SendPacket(pack);
|
||||||
safe_delete(pack);
|
safe_delete(pack);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user