[Feature] Client Checksum Verification (Resubmit old 1678) (#1922)

* [Feature] Client Checksum Verification (Resubmit old 1678)

* Updated db version

* Add new updatechecksum to CmakeLists.txt

* Removed magic number and used constant

* Fix new command to have access to worldserver

* spacing, more venbose desc and remove unneeded check

* Cleanup, refactoring

Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
Paul Coene
2022-03-06 21:26:29 -05:00
committed by GitHub
parent eca2ed0321
commit 2a5ddde78a
23 changed files with 356 additions and 33 deletions
+13 -1
View File
@@ -997,6 +997,18 @@ bool Database::SetVariable(const std::string varname, const std::string &varvalu
return true;
}
void Database::SetAccountCRCField(uint32 account_id, std::string field_name, uint64 checksum)
{
QueryDatabase(
fmt::format(
"UPDATE `account` SET `{}` = '{}' WHERE `id` = {}",
field_name,
checksum,
account_id
)
);
}
// Get zone starting points from DB
bool Database::GetSafePoints(const char* zone_short_name, uint32 instance_version, float* safe_x, float* safe_y, float* safe_z, float* safe_heading, int16* min_status, uint8* min_level, char *flag_needed) {
@@ -2285,7 +2297,7 @@ void Database::SetIPExemption(std::string account_ip, int exemption_amount) {
auto row = results.begin();
exemption_id = atoi(row[0]);
}
query = fmt::format(
"INSERT INTO `ip_exemptions` (`exemption_ip`, `exemption_amount`) VALUES ('{}', {})",
account_ip,
+2
View File
@@ -190,6 +190,8 @@ public:
int16 CheckStatus(uint32 account_id);
void SetAccountCRCField(uint32 account_id, std::string field_name, uint64 checksum);
uint32 CheckLogin(const char* name, const char* password, const char *loginserver, int16* oStatus = 0);
uint32 CreateAccount(const char* name, const char* password, int16 status, const char* loginserver, uint32 lsaccount_id);
uint32 GetAccountIDFromLSID(const std::string& in_loginserver_id, uint32 in_loginserver_account_id, char* in_account_name = 0, int16* in_status = 0);
+1
View File
@@ -558,6 +558,7 @@ N(OP_WhoAllRequest),
N(OP_WhoAllResponse),
N(OP_World_Client_CRC1),
N(OP_World_Client_CRC2),
N(OP_World_Client_CRC3),
N(OP_WorldClientReady),
N(OP_WorldComplete),
N(OP_WorldLogout),
+5
View File
@@ -5582,6 +5582,11 @@ struct SayLinkBodyFrame_Struct {
/*056*/
};
struct Checksum_Struct {
uint64 checksum;
uint8 data[2048];
};
struct UpdateMovementEntry {
/* 00 */ float Y;
/* 04 */ float X;
+19 -17
View File
@@ -116,22 +116,24 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults()
/**
* Set Defaults
*/
log_settings[Logs::WorldServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::ZoneServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::QSServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::UCSServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::MySQLError].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Loginserver].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::HeadlessClient].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::NPCScaling].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::HotReload].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::HotReload].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Loot].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::Scheduler].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Cheat].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::HTTP].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::HTTP].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::WorldServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::ZoneServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::QSServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::UCSServer].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Crash].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::MySQLError].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Loginserver].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::HeadlessClient].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::NPCScaling].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::HotReload].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::HotReload].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Loot].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::Scheduler].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::Cheat].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::HTTP].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::HTTP].log_to_gmsay = static_cast<uint8>(Logs::General);
log_settings[Logs::ChecksumVerification].log_to_console = static_cast<uint8>(Logs::General);
log_settings[Logs::ChecksumVerification].log_to_gmsay = static_cast<uint8>(Logs::General);
/**
* RFC 5424
@@ -241,7 +243,7 @@ void EQEmuLogSys::ProcessGMSay(
*/
if (EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformZone ||
EQEmuLogSys::log_platform == EQEmuExePlatform::ExePlatformWorld
) {
) {
on_log_gmsay_hook(log_category, message);
}
}
+2
View File
@@ -127,6 +127,7 @@ namespace Logs {
DiaWind,
HTTP,
Saylink,
ChecksumVerification,
MaxCategoryID /* Don't Remove this */
};
@@ -212,6 +213,7 @@ namespace Logs {
"DialogueWindow",
"HTTP",
"Saylink",
"ChecksumVerification",
};
}
+22
View File
@@ -696,6 +696,16 @@
OutF(LogSys, Logs::Detail, Logs::Saylink, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogChecksumVerification(message, ...) do {\
if (LogSys.log_settings[Logs::ChecksumVerification].is_category_enabled == 1)\
OutF(LogSys, Logs::General, Logs::ChecksumVerification, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define LogChecksumVerificationDetail(message, ...) do {\
if (LogSys.log_settings[Logs::ChecksumVerification].is_category_enabled == 1)\
OutF(LogSys, Logs::Detail, Logs::ChecksumVerification, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
} while (0)
#define Log(debug_level, log_category, message, ...) do {\
if (LogSys.log_settings[log_category].is_category_enabled == 1)\
LogSys.Out(debug_level, log_category, __FILE__, __func__, __LINE__, message, ##__VA_ARGS__);\
@@ -1092,6 +1102,18 @@
#define LogHTTPDetail(message, ...) do {\
} while (0)
#define LogSaylink(message, ...) do {\
} while (0)
#define LogSaylinkDetail(message, ...) do {\
} while (0)
#define LogChecksumVerification(message, ...) do {\
} while (0)
#define LogChecksumVerificationDetail(message, ...) do {\
} while (0)
#define Log(debug_level, log_category, message, ...) do {\
} while (0)
+5
View File
@@ -5218,6 +5218,11 @@ struct SayLinkBodyFrame_Struct {
/*056*/
};
struct Checksum_Struct {
uint64_t checksum;
uint8_t data[2048];
};
}; /*structs*/
}; /*RoF2*/
@@ -14,6 +14,7 @@
#include "../../database.h"
#include "../../string_util.h"
#include <ctime>
class BaseAccountRepository {
public:
@@ -32,11 +33,14 @@ public:
std::string minilogin_ip;
int hideme;
int rulesflag;
std::string suspendeduntil;
time_t suspendeduntil;
int time_creation;
int expansion;
std::string ban_reason;
std::string suspend_reason;
std::string crc_eqgame;
std::string crc_skillcaps;
std::string crc_basedata;
};
static std::string PrimaryKey()
@@ -66,6 +70,37 @@ public:
"expansion",
"ban_reason",
"suspend_reason",
"crc_eqgame",
"crc_skillcaps",
"crc_basedata",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"id",
"name",
"charname",
"sharedplat",
"password",
"status",
"ls_id",
"lsaccount_id",
"gmspeed",
"revoked",
"karma",
"minilogin_ip",
"hideme",
"rulesflag",
"UNIX_TIMESTAMP(suspendeduntil)",
"time_creation",
"expansion",
"ban_reason",
"suspend_reason",
"crc_eqgame",
"crc_skillcaps",
"crc_basedata",
};
}
@@ -74,6 +109,11 @@ public:
return std::string(implode(", ", Columns()));
}
static std::string SelectColumnsRaw()
{
return std::string(implode(", ", SelectColumns()));
}
static std::string TableName()
{
return std::string("account");
@@ -83,7 +123,7 @@ public:
{
return fmt::format(
"SELECT {} FROM {}",
ColumnsRaw(),
SelectColumnsRaw(),
TableName()
);
}
@@ -115,11 +155,14 @@ public:
entry.minilogin_ip = "";
entry.hideme = 0;
entry.rulesflag = 0;
entry.suspendeduntil = "0000-00-00 00:00:00";
entry.suspendeduntil = 0;
entry.time_creation = 0;
entry.expansion = 0;
entry.ban_reason = "";
entry.suspend_reason = "";
entry.crc_eqgame = "";
entry.crc_skillcaps = "";
entry.crc_basedata = "";
return entry;
}
@@ -169,11 +212,14 @@ public:
entry.minilogin_ip = row[11] ? row[11] : "";
entry.hideme = atoi(row[12]);
entry.rulesflag = atoi(row[13]);
entry.suspendeduntil = row[14] ? row[14] : "";
entry.suspendeduntil = strtoll(row[14] ? row[14] : "-1", nullptr, 10);
entry.time_creation = atoi(row[15]);
entry.expansion = atoi(row[16]);
entry.ban_reason = row[17] ? row[17] : "";
entry.suspend_reason = row[18] ? row[18] : "";
entry.crc_eqgame = row[19] ? row[19] : "";
entry.crc_skillcaps = row[20] ? row[20] : "";
entry.crc_basedata = row[21] ? row[21] : "";
return entry;
}
@@ -220,11 +266,14 @@ public:
update_values.push_back(columns[11] + " = '" + EscapeString(account_entry.minilogin_ip) + "'");
update_values.push_back(columns[12] + " = " + std::to_string(account_entry.hideme));
update_values.push_back(columns[13] + " = " + std::to_string(account_entry.rulesflag));
update_values.push_back(columns[14] + " = '" + EscapeString(account_entry.suspendeduntil) + "'");
update_values.push_back(columns[14] + " = FROM_UNIXTIME(" + (account_entry.suspendeduntil > 0 ? std::to_string(account_entry.suspendeduntil) : "null") + ")");
update_values.push_back(columns[15] + " = " + std::to_string(account_entry.time_creation));
update_values.push_back(columns[16] + " = " + std::to_string(account_entry.expansion));
update_values.push_back(columns[17] + " = '" + EscapeString(account_entry.ban_reason) + "'");
update_values.push_back(columns[18] + " = '" + EscapeString(account_entry.suspend_reason) + "'");
update_values.push_back(columns[19] + " = '" + EscapeString(account_entry.crc_eqgame) + "'");
update_values.push_back(columns[20] + " = '" + EscapeString(account_entry.crc_skillcaps) + "'");
update_values.push_back(columns[21] + " = '" + EscapeString(account_entry.crc_basedata) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -260,11 +309,14 @@ public:
insert_values.push_back("'" + EscapeString(account_entry.minilogin_ip) + "'");
insert_values.push_back(std::to_string(account_entry.hideme));
insert_values.push_back(std::to_string(account_entry.rulesflag));
insert_values.push_back("'" + EscapeString(account_entry.suspendeduntil) + "'");
insert_values.push_back("FROM_UNIXTIME(" + (account_entry.suspendeduntil > 0 ? std::to_string(account_entry.suspendeduntil) : "null") + ")");
insert_values.push_back(std::to_string(account_entry.time_creation));
insert_values.push_back(std::to_string(account_entry.expansion));
insert_values.push_back("'" + EscapeString(account_entry.ban_reason) + "'");
insert_values.push_back("'" + EscapeString(account_entry.suspend_reason) + "'");
insert_values.push_back("'" + EscapeString(account_entry.crc_eqgame) + "'");
insert_values.push_back("'" + EscapeString(account_entry.crc_skillcaps) + "'");
insert_values.push_back("'" + EscapeString(account_entry.crc_basedata) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -308,11 +360,14 @@ public:
insert_values.push_back("'" + EscapeString(account_entry.minilogin_ip) + "'");
insert_values.push_back(std::to_string(account_entry.hideme));
insert_values.push_back(std::to_string(account_entry.rulesflag));
insert_values.push_back("'" + EscapeString(account_entry.suspendeduntil) + "'");
insert_values.push_back("FROM_UNIXTIME(" + (account_entry.suspendeduntil > 0 ? std::to_string(account_entry.suspendeduntil) : "null") + ")");
insert_values.push_back(std::to_string(account_entry.time_creation));
insert_values.push_back(std::to_string(account_entry.expansion));
insert_values.push_back("'" + EscapeString(account_entry.ban_reason) + "'");
insert_values.push_back("'" + EscapeString(account_entry.suspend_reason) + "'");
insert_values.push_back("'" + EscapeString(account_entry.crc_eqgame) + "'");
insert_values.push_back("'" + EscapeString(account_entry.crc_skillcaps) + "'");
insert_values.push_back("'" + EscapeString(account_entry.crc_basedata) + "'");
insert_chunks.push_back("(" + implode(",", insert_values) + ")");
}
@@ -360,11 +415,14 @@ public:
entry.minilogin_ip = row[11] ? row[11] : "";
entry.hideme = atoi(row[12]);
entry.rulesflag = atoi(row[13]);
entry.suspendeduntil = row[14] ? row[14] : "";
entry.suspendeduntil = strtoll(row[14] ? row[14] : "-1", nullptr, 10);
entry.time_creation = atoi(row[15]);
entry.expansion = atoi(row[16]);
entry.ban_reason = row[17] ? row[17] : "";
entry.suspend_reason = row[18] ? row[18] : "";
entry.crc_eqgame = row[19] ? row[19] : "";
entry.crc_skillcaps = row[20] ? row[20] : "";
entry.crc_basedata = row[21] ? row[21] : "";
all_entries.push_back(entry);
}
@@ -403,11 +461,14 @@ public:
entry.minilogin_ip = row[11] ? row[11] : "";
entry.hideme = atoi(row[12]);
entry.rulesflag = atoi(row[13]);
entry.suspendeduntil = row[14] ? row[14] : "";
entry.suspendeduntil = strtoll(row[14] ? row[14] : "-1", nullptr, 10);
entry.time_creation = atoi(row[15]);
entry.expansion = atoi(row[16]);
entry.ban_reason = row[17] ? row[17] : "";
entry.suspend_reason = row[18] ? row[18] : "";
entry.crc_eqgame = row[19] ? row[19] : "";
entry.crc_skillcaps = row[20] ? row[20] : "";
entry.crc_basedata = row[21] ? row[21] : "";
all_entries.push_back(entry);
}
+2
View File
@@ -242,6 +242,7 @@ RULE_INT(GM, MinStatusToSummonItem, 250, "Minimum required status to summon item
RULE_INT(GM, MinStatusToZoneAnywhere, 250, "Minimum required status to zone anywhere")
RULE_INT(GM, MinStatusToLevelTarget, 100, "Minimum required status to set the level of a player")
RULE_INT(GM, MinStatusToBypassLockedServer, 100, "Players >= this status can log in to the server even when it is locked")
RULE_INT(GM, MinStatusToBypassCheckSumVerification, 100, "Players >= this status can bypass the eqgame.exe and spells_us.txt checksum verification")
RULE_CATEGORY_END()
RULE_CATEGORY(World)
@@ -275,6 +276,7 @@ RULE_INT (World, TellQueueSize, 20, "Maximum tell queue size")
RULE_BOOL(World, StartZoneSameAsBindOnCreation, true, "Should the start zone always be the same location as your bind?")
RULE_BOOL(World, EnforceCharacterLimitAtLogin, false, "Enforce the limit for characters that are online at login")
RULE_BOOL(World, EnableDevTools, true, "Enable or Disable the Developer Tools globally (Most of the time you want this enabled)")
RULE_BOOL(World, EnableChecksumVerification, false, "Enable or Disable the Checksum Verification for eqgame.exe and spells_us.txt")
RULE_CATEGORY_END()
RULE_CATEGORY(Zone)
+1
View File
@@ -227,6 +227,7 @@
#define ServerOP_HotReloadQuests 0x4011
#define ServerOP_UpdateSchedulerEvents 0x4012
#define ServerOP_ReloadContentFlags 0x4013
#define ServerOP_ReloadVariablesWorld 0x4014
#define ServerOP_CZDialogueWindow 0x4500
#define ServerOP_CZLDoNUpdate 0x4501
+1 -1
View File
@@ -34,7 +34,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9175
#define CURRENT_BINARY_DATABASE_VERSION 9176
#ifdef BOTS
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9028