Updated database check

When applied this commit updates the style of the database check, changes some logging statements, and makes developers able to skip the check.
This commit is contained in:
wincent 2021-12-16 23:11:51 +01:00
parent a5d527d0cf
commit 49aba62dbb

View File

@ -89,7 +89,7 @@ struct tempSessionInfo {
std::map<std::string, tempSessionInfo> m_PendingUsers; std::map<std::string, tempSessionInfo> m_PendingUsers;
int instanceID = 0; int instanceID = 0;
int g_CloneID = 0; int g_CloneID = 0;
std::string fdbChecksum = ""; std::string databaseChecksum = "";
int main(int argc, char** argv) { int main(int argc, char** argv) {
Diagnostics::SetProcessName("World"); Diagnostics::SetProcessName("World");
@ -239,28 +239,42 @@ int main(int argc, char** argv) {
// pre calculate the FDB checksum // pre calculate the FDB checksum
if (Game::config->GetValue("check_fdb") == "1") { if (Game::config->GetValue("check_fdb") == "1") {
std::ifstream fileStream; std::ifstream fileStream;
fileStream.open("res/CDServer.fdb", std::ios::binary | std::ios::in);
static const std::vector<std::string> alieses = {
"res/CDServers.fdb",
"res/cdserver.fdb",
"res/CDClient.fdb",
"res/cdclient.fdb",
};
for (const auto& file : alieses) {
fileStream.open(file);
if (fileStream.is_open()) {
break;
}
}
const int bufferSize = 1024; const int bufferSize = 1024;
MD5* md5 = new MD5(); MD5* md5 = new MD5();
std::vector<char> fileStreamBuffer = std::vector<char>(bufferSize, 0); char fileStreamBuffer[1024] = {};
while (!fileStream.eof()) { while (!fileStream.eof()) {
fileStreamBuffer.clear(); memset(fileStreamBuffer, 0, bufferSize);
fileStream.read(fileStreamBuffer.data(), bufferSize); fileStream.read(fileStreamBuffer, bufferSize);
md5->update(fileStreamBuffer.data(), fileStream.gcount()); md5->update(fileStreamBuffer, fileStream.gcount());
} }
fileStreamBuffer.clear(); fileStream.close();
const char* nullTerminateBuffer = "\0"; const char* nullTerminateBuffer = "\0";
md5->update(nullTerminateBuffer, 1); // null terminate the data md5->update(nullTerminateBuffer, 1); // null terminate the data
md5->finalize(); md5->finalize();
fdbChecksum = md5->hexdigest(); databaseChecksum = md5->hexdigest();
delete md5; delete md5;
Game::logger->Log("WorldServer", "FDB Checksum calculated as: %s\n", fdbChecksum.c_str()); Game::logger->Log("WorldServer", "FDB Checksum calculated as: %s\n", databaseChecksum.c_str());
} }
} }
@ -866,15 +880,18 @@ void HandlePacket(Packet* packet) {
case MSG_WORLD_CLIENT_VALIDATION: { case MSG_WORLD_CLIENT_VALIDATION: {
std::string username = PacketUtils::ReadString(0x08, packet, true); std::string username = PacketUtils::ReadString(0x08, packet, true);
std::string sessionKey = PacketUtils::ReadString(74, packet, true); std::string sessionKey = PacketUtils::ReadString(74, packet, true);
std::string theirFdbChecksum = PacketUtils::ReadString(packet->length - 33, packet, false); std::string clientDatabaseChecksum = PacketUtils::ReadString(packet->length - 33, packet, false);
theirFdbChecksum = theirFdbChecksum.substr(0, 32); // sometimes client puts a null terminator at the end of the checksum and sometimes doesn't; weird
if (Game::config->GetValue("check_fdb") == "1" && fdbChecksum != "") { // if fdbChecksum is empty, likely means we are a character server. // sometimes client puts a null terminator at the end of the checksum and sometimes doesn't, weird
clientDatabaseChecksum = clientDatabaseChecksum.substr(0, 32);
// If the check is turned on, validate the client's database checksum.
if (Game::config->GetValue("check_fdb") == "1" && !databaseChecksum.empty()) {
uint32_t gmLevel = 0; uint32_t gmLevel = 0;
sql::PreparedStatement* stmt = Database::CreatePreppedStmt("SELECT gm_level FROM accounts WHERE name=? LIMIT 1;"); auto* stmt = Database::CreatePreppedStmt("SELECT gm_level FROM accounts WHERE name=? LIMIT 1;");
stmt->setString(1, username.c_str()); stmt->setString(1, username.c_str());
sql::ResultSet* res = stmt->executeQuery(); auto* res = stmt->executeQuery();
while (res->next()) { while (res->next()) {
gmLevel = res->getInt(1); gmLevel = res->getInt(1);
} }
@ -882,13 +899,11 @@ void HandlePacket(Packet* packet) {
delete stmt; delete stmt;
delete res; delete res;
if (gmLevel != 9) { // Developers may skip this check
Game::logger->Log("WorldServer", "Got client checksum %s and we have server checksum %s. \n", theirFdbChecksum.c_str(), fdbChecksum.c_str()); if (gmLevel < 8 && clientDatabaseChecksum != databaseChecksum) {
if (theirFdbChecksum != fdbChecksum) { Game::logger->Log("WorldServer", "Client's database checksum does not match the server's, aborting connection.\n");
Game::logger->Log("WorldServer", "Client checksum does not match server checksum.\n"); Game::server->Disconnect(packet->systemAddress, SERVER_DISCON_KICK);
Game::server->Disconnect(packet->systemAddress, SERVER_DISCON_KICK); return;
return;
}
} }
} }