From 6b095e39dab3552b582511af7a70fe337269d536 Mon Sep 17 00:00:00 2001 From: Foereaper Date: Sun, 12 Apr 2015 00:09:12 +0200 Subject: [PATCH] [Warden] General update Added Warden log file Added very basic Mac support Added separate config options for Win and OSX Warden scans --- src/game/Server/WorldSession.cpp | 9 ++-- src/game/Server/WorldSocket.cpp | 2 +- src/game/Warden/Warden.cpp | 18 ++++---- src/game/Warden/WardenCheckMgr.cpp | 20 ++++----- src/game/Warden/WardenMac.cpp | 47 +++++++++++-------- src/game/Warden/WardenWin.cpp | 72 +++++++++++++++--------------- src/game/WorldHandlers/World.cpp | 3 +- src/game/WorldHandlers/World.h | 3 +- src/mangosd/mangosd.conf.dist.in | 21 +++++++-- src/shared/Log/Log.cpp | 66 ++++++++++++++++++++++++++- src/shared/Log/Log.h | 18 ++++++++ src/shared/SystemConfig.h.in | 2 +- 12 files changed, 193 insertions(+), 88 deletions(-) diff --git a/src/game/Server/WorldSession.cpp b/src/game/Server/WorldSession.cpp index 16f4e683..322231dc 100644 --- a/src/game/Server/WorldSession.cpp +++ b/src/game/Server/WorldSession.cpp @@ -825,15 +825,14 @@ void WorldSession::SendPlaySpellVisual(ObjectGuid guid, uint32 spellArtKit) void WorldSession::InitWarden(BigNumber* k, std::string const& os) { - if (os == "Win") + if (os == "Win" && sWorld.getConfig(CONFIG_BOOL_WARDEN_WIN_ENABLED)) { _warden = new WardenWin(); _warden->Init(this, k); } - else if (os == "OSX") + else if (os == "OSX" && sWorld.getConfig(CONFIG_BOOL_WARDEN_OSX_ENABLED)) { - // Disabled as it is causing the client to crash - // _warden = new WardenMac(); - // _warden->Init(this, k); + _warden = new WardenMac(); + _warden->Init(this, k); } } \ No newline at end of file diff --git a/src/game/Server/WorldSocket.cpp b/src/game/Server/WorldSocket.cpp index 6f56d4e8..e6d5c4cf 100644 --- a/src/game/Server/WorldSocket.cpp +++ b/src/game/Server/WorldSocket.cpp @@ -659,7 +659,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket) BigNumber v, s, g, N, K; std::string os; WorldPacket packet, SendAddonPacked; - bool wardenActive = sWorld.getConfig(CONFIG_BOOL_WARDEN_ENABLED); + bool wardenActive = (sWorld.getConfig(CONFIG_BOOL_WARDEN_WIN_ENABLED) || sWorld.getConfig(CONFIG_BOOL_WARDEN_OSX_ENABLED)); // Read the content of the packet recvPacket >> BuiltNumberClient; diff --git a/src/game/Warden/Warden.cpp b/src/game/Warden/Warden.cpp index 7b97d134..0c6b8c20 100644 --- a/src/game/Warden/Warden.cpp +++ b/src/game/Warden/Warden.cpp @@ -53,7 +53,7 @@ Warden::~Warden() void Warden::SendModuleToClient() { - sLog.outError("[Warden]: Send module to client"); + sLog.outWarden("Send module to client"); // Create packet structure WardenModuleTransfer packet; @@ -79,7 +79,7 @@ void Warden::SendModuleToClient() void Warden::RequestModule() { - sLog.outError("[Warden]: Request module"); + sLog.outWarden("Request module"); // Create packet structure WardenModuleUse request; @@ -114,7 +114,7 @@ void Warden::Update() // Kick player if client response delays more than set in config if (_clientResponseTimer > maxClientResponseDelay * IN_MILLISECONDS) { - sLog.outError("[Warden]: %s (latency: %u, IP: %s) exceeded Warden module response delay for more than %s - disconnecting client", + sLog.outWarden("%s (latency: %u, IP: %s) exceeded Warden module response delay for more than %s - disconnecting client", _session->GetPlayerName(), _session->GetLatency(), _session->GetRemoteAddress().c_str(), secsToTimeString(maxClientResponseDelay, true).c_str()); _session->KickPlayer(); } @@ -150,12 +150,12 @@ bool Warden::IsValidCheckSum(uint32 checksum, const uint8* data, const uint16 le if (checksum != newChecksum) { - sLog.outError("[Warden]: CHECKSUM IS NOT VALID"); + sLog.outWarden("CHECKSUM IS NOT VALID"); return false; } else { - sLog.outError("[Warden]: CHECKSUM IS VALID"); + sLog.outWarden("CHECKSUM IS VALID"); return true; } } @@ -233,7 +233,7 @@ void WorldSession::HandleWardenDataOpcode(WorldPacket& recvData) _warden->DecryptData(const_cast(recvData.contents()), recvData.size()); uint8 opcode; recvData >> opcode; - sLog.outError("[Warden]: Got packet, opcode %02X, size %u", opcode, uint32(recvData.size())); + sLog.outWarden("Got packet, opcode %02X, size %u", opcode, uint32(recvData.size())); recvData.hexlike(); switch (opcode) @@ -248,17 +248,17 @@ void WorldSession::HandleWardenDataOpcode(WorldPacket& recvData) _warden->HandleData(recvData); break; case WARDEN_CMSG_MEM_CHECKS_RESULT: - sLog.outError("[Warden]: NYI WARDEN_CMSG_MEM_CHECKS_RESULT received!"); + sLog.outWarden("NYI WARDEN_CMSG_MEM_CHECKS_RESULT received!"); break; case WARDEN_CMSG_HASH_RESULT: _warden->HandleHashResult(recvData); _warden->InitializeModule(); break; case WARDEN_CMSG_MODULE_FAILED: - sLog.outError("[Warden]: NYI WARDEN_CMSG_MODULE_FAILED received!"); + sLog.outWarden("NYI WARDEN_CMSG_MODULE_FAILED received!"); break; default: - sLog.outError("[Warden]: Got unknown warden opcode %02X of size %u.", opcode, uint32(recvData.size() - 1)); + sLog.outWarden("Got unknown warden opcode %02X of size %u.", opcode, uint32(recvData.size() - 1)); break; } } diff --git a/src/game/Warden/WardenCheckMgr.cpp b/src/game/Warden/WardenCheckMgr.cpp index 2ed379d5..4c976c41 100644 --- a/src/game/Warden/WardenCheckMgr.cpp +++ b/src/game/Warden/WardenCheckMgr.cpp @@ -46,9 +46,9 @@ WardenCheckMgr::~WardenCheckMgr() void WardenCheckMgr::LoadWardenChecks() { // Check if Warden is enabled by config before loading anything - if (!sWorld.getConfig(CONFIG_BOOL_WARDEN_ENABLED)) + if (!sWorld.getConfig(CONFIG_BOOL_WARDEN_WIN_ENABLED) && !sWorld.getConfig(CONFIG_BOOL_WARDEN_OSX_ENABLED)) { - sLog.outError("[Warden]: >> Warden disabled, loading checks skipped."); + sLog.outWarden(">> Warden disabled, loading checks skipped."); return; } @@ -56,7 +56,7 @@ void WardenCheckMgr::LoadWardenChecks() if (!result) { - sLog.outError("[Warden]: >> Loaded 0 Warden checks. DB table `warden_checks` is empty!"); + sLog.outWarden(">> Loaded 0 Warden checks. DB table `warden_checks` is empty!"); return; } @@ -154,15 +154,15 @@ void WardenCheckMgr::LoadWardenChecks() ++count; } while (result->NextRow()); - sLog.outError("[Warden]: >> Loaded %u warden checks.", count); + sLog.outWarden(">> Loaded %u warden checks.", count); } void WardenCheckMgr::LoadWardenOverrides() { // Check if Warden is enabled by config before loading anything - if (!sWorld.getConfig(CONFIG_BOOL_WARDEN_ENABLED)) + if (!sWorld.getConfig(CONFIG_BOOL_WARDEN_WIN_ENABLED) && !sWorld.getConfig(CONFIG_BOOL_WARDEN_OSX_ENABLED)) { - sLog.outError("[Warden]: >> Warden disabled, loading check overrides skipped."); + sLog.outWarden(">> Warden disabled, loading check overrides skipped."); return; } @@ -171,7 +171,7 @@ void WardenCheckMgr::LoadWardenOverrides() if (!result) { - sLog.outError("[Warden]: >> Loaded 0 Warden action overrides. DB table `warden_action` is empty!"); + sLog.outWarden(">> Loaded 0 Warden action overrides. DB table `warden_action` is empty!"); return; } @@ -188,10 +188,10 @@ void WardenCheckMgr::LoadWardenOverrides() // Check if action value is in range (0-2, see WardenActions enum) if (action > WARDEN_ACTION_BAN) - sLog.outError("[Warden]: Warden check override action out of range (ID: %u, action: %u)", checkId, action); + sLog.outWarden("Warden check override action out of range (ID: %u, action: %u)", checkId, action); // Check if check actually exists before accessing the CheckStore vector else if (checkId > CheckStore.size()) - sLog.outError("[Warden]: Warden check action override for non-existing check (ID: %u, action: %u), skipped", checkId, action); + sLog.outWarden("Warden check action override for non-existing check (ID: %u, action: %u), skipped", checkId, action); else { CheckStore[checkId]->Action = WardenActions(action); @@ -200,7 +200,7 @@ void WardenCheckMgr::LoadWardenOverrides() } while (result->NextRow()); - sLog.outError("[Warden]: >> Loaded %u warden action overrides.", count); + sLog.outWarden(">> Loaded %u warden action overrides.", count); } WardenCheck* WardenCheckMgr::GetWardenDataById(uint16 Id) diff --git a/src/game/Warden/WardenMac.cpp b/src/game/Warden/WardenMac.cpp index 569c51fa..10505eb6 100644 --- a/src/game/Warden/WardenMac.cpp +++ b/src/game/Warden/WardenMac.cpp @@ -61,16 +61,16 @@ void WardenMac::Init(WorldSession* pClient, BigNumber* K) _inputCrypto.Init(_inputKey); _outputCrypto.Init(_outputKey); - sLog.outError("[Warden]: Server side warden for client %u initializing...", pClient->GetAccountId()); - sLog.outError("[Warden]: C->S Key: %s", ByteArrayToHexStr(_inputKey, 16).c_str()); - sLog.outError("[Warden]: S->C Key: %s", ByteArrayToHexStr(_outputKey, 16).c_str()); - sLog.outError("[Warden]: Seed: %s", ByteArrayToHexStr(_seed, 16).c_str()); - sLog.outError("[Warden]: Loading Module..."); + sLog.outWarden("Server side warden for client %u initializing...", pClient->GetAccountId()); + sLog.outWarden("C->S Key: %s", ByteArrayToHexStr(_inputKey, 16).c_str()); + sLog.outWarden("S->C Key: %s", ByteArrayToHexStr(_outputKey, 16).c_str()); + sLog.outWarden(" Seed: %s", ByteArrayToHexStr(_seed, 16).c_str()); + sLog.outWarden("Loading Module..."); _module = GetModuleForClient(); - sLog.outError("[Warden]: Module Key: %s", ByteArrayToHexStr(_module->Key, 16).c_str()); - sLog.outError("[Warden]: Module ID: %s", ByteArrayToHexStr(_module->Id, 16).c_str()); + sLog.outWarden("Module Key: %s", ByteArrayToHexStr(_module->Key, 16).c_str()); + sLog.outWarden("Module ID: %s", ByteArrayToHexStr(_module->Id, 16).c_str()); RequestModule(); } @@ -97,12 +97,12 @@ ClientWardenModule* WardenMac::GetModuleForClient() void WardenMac::InitializeModule() { - sLog.outError("[Warden]: Initialize module"); + sLog.outWarden("Initialize module"); } void WardenMac::RequestHash() { - sLog.outError("[Warden]: Request hash"); + sLog.outWarden("Request hash"); // Create packet structure WardenHashRequest Request; @@ -170,11 +170,13 @@ void WardenMac::HandleHashResult(ByteBuffer &buff) // Verify key if (memcmp(buff.contents() + 1, sha1.GetDigest(), 20) != 0) { - sLog.outError("[Warden]: %s failed hash reply. Action: %s", _session->GetPlayerName(), Penalty().c_str()); + sLog.outWarden("%s failed hash reply. Action: %s", _session->GetPlayerName(), Penalty().c_str()); + if (sWorld.getConfig(CONFIG_INT32_WARDEN_CLIENT_FAIL_ACTION) != 0) + _session->KickPlayer(); return; } - sLog.outError("[Warden]: Request hash reply: succeed"); + sLog.outWarden("Request hash reply: succeed"); // client 7F96EEFDA5B63D20A4DF8E00CBF48304 //const uint8 client_key[16] = { 0x7F, 0x96, 0xEE, 0xFD, 0xA5, 0xB6, 0x3D, 0x20, 0xA4, 0xDF, 0x8E, 0x00, 0xCB, 0xF4, 0x83, 0x04 }; @@ -196,7 +198,7 @@ void WardenMac::HandleHashResult(ByteBuffer &buff) void WardenMac::RequestData() { - sLog.outError("[Warden]: Request data"); + sLog.outWarden("Request data"); ByteBuffer buff; buff << uint8(WARDEN_SMSG_CHEAT_CHECKS_REQUEST); @@ -220,7 +222,7 @@ void WardenMac::RequestData() void WardenMac::HandleData(ByteBuffer &buff) { - sLog.outError("[Warden]: Handle data"); + sLog.outWarden("Handle data"); _dataSent = false; _clientResponseTimer = 0; @@ -238,7 +240,7 @@ void WardenMac::HandleData(ByteBuffer &buff) // return; //} - //bool found = false; + bool found = false; std::string str = "Test string!"; @@ -253,8 +255,8 @@ void WardenMac::HandleData(ByteBuffer &buff) if (memcmp(sha1Hash, sha1.GetDigest(), 20) != 0) { - sLog.outError("[Warden]: Handle data failed: SHA1 hash is wrong!"); - //found = true; + sLog.outWarden("Handle data failed: SHA1 hash is wrong!"); + found = true; } MD5_CTX ctx; @@ -268,9 +270,16 @@ void WardenMac::HandleData(ByteBuffer &buff) if (memcmp(ourMD5Hash, theirsMD5Hash, 16) != 0) { - sLog.outError("[Warden]: Handle data failed: MD5 hash is wrong!"); - //found = true; + sLog.outWarden("Handle data failed: MD5 hash is wrong!"); + found = true; } - _session->KickPlayer(); + if (found && sWorld.getConfig(CONFIG_INT32_WARDEN_CLIENT_FAIL_ACTION) != 0) + _session->KickPlayer(); + else + sLog.outWarden("SHA1 and MD5 hash verified. Handle data passed."); + + // Set hold off timer, minimum timer should at least be 1 second + uint32 holdOff = sWorld.getConfig(CONFIG_INT32_WARDEN_CLIENT_CHECK_HOLDOFF); + _checkTimer = (holdOff < 1 ? 1 : holdOff) * IN_MILLISECONDS; } diff --git a/src/game/Warden/WardenWin.cpp b/src/game/Warden/WardenWin.cpp index 4831f1ac..ce4fd0f8 100644 --- a/src/game/Warden/WardenWin.cpp +++ b/src/game/Warden/WardenWin.cpp @@ -56,16 +56,16 @@ void WardenWin::Init(WorldSession* session, BigNumber* k) _inputCrypto.Init(_inputKey); _outputCrypto.Init(_outputKey); - sLog.outError("[Warden]: Server side warden for client %u initializing...", session->GetAccountId()); - sLog.outError("[Warden]: C->S Key: %s", ByteArrayToHexStr(_inputKey, 16).c_str()); - sLog.outError("[Warden]: S->C Key: %s", ByteArrayToHexStr(_outputKey, 16).c_str()); - sLog.outError("[Warden]: Seed: %s", ByteArrayToHexStr(_seed, 16).c_str()); - sLog.outError("[Warden]: Loading Module..."); + sLog.outWarden("Server side warden for client %u initializing...", session->GetAccountId()); + sLog.outWarden("C->S Key: %s", ByteArrayToHexStr(_inputKey, 16).c_str()); + sLog.outWarden("S->C Key: %s", ByteArrayToHexStr(_outputKey, 16).c_str()); + sLog.outWarden(" Seed: %s", ByteArrayToHexStr(_seed, 16).c_str()); + sLog.outWarden("Loading Module..."); _module = GetModuleForClient(); - sLog.outError("[Warden]: Module Key: %s", ByteArrayToHexStr(_module->Key, 16).c_str()); - sLog.outError("[Warden]: Module ID: %s", ByteArrayToHexStr(_module->Id, 16).c_str()); + sLog.outWarden("Module Key: %s", ByteArrayToHexStr(_module->Key, 16).c_str()); + sLog.outWarden("Module ID: %s", ByteArrayToHexStr(_module->Id, 16).c_str()); RequestModule(); } @@ -92,7 +92,7 @@ ClientWardenModule* WardenWin::GetModuleForClient() void WardenWin::InitializeModule() { - sLog.outError("[Warden]: Initialize module"); + sLog.outWarden("Initialize module"); // Create packet structure WardenInitModuleRequest Request; @@ -136,7 +136,7 @@ void WardenWin::InitializeModule() void WardenWin::RequestHash() { - sLog.outError("[Warden]: Request hash"); + sLog.outWarden("Request hash"); // Create packet structure WardenHashRequest Request; @@ -158,11 +158,11 @@ void WardenWin::HandleHashResult(ByteBuffer &buff) // Verify key if (memcmp(buff.contents() + 1, Module.ClientKeySeedHash, sizeof(Module.ClientKeySeedHash)) != 0) { - sLog.outError("[Warden]: %s failed hash reply. Action: %s", _session->GetPlayerName(), Penalty().c_str()); + sLog.outWarden("%s failed hash reply. Action: %s", _session->GetPlayerName(), Penalty().c_str()); return; } - sLog.outError("[Warden]: Request hash reply: succeed"); + sLog.outWarden("Request hash reply: succeed"); // Change keys here memcpy(_inputKey, Module.ClientKeySeed, 16); @@ -178,7 +178,7 @@ void WardenWin::HandleHashResult(ByteBuffer &buff) void WardenWin::RequestData() { - sLog.outError("[Warden]: Request data"); + sLog.outWarden("Request data"); // If all checks were done, fill the todo list again if (_memChecksTodo.empty()) @@ -325,12 +325,12 @@ void WardenWin::RequestData() for (std::list::iterator itr = _currentChecks.begin(); itr != _currentChecks.end(); ++itr) stream << *itr << " "; - sLog.outError("[Warden]: %s", stream.str().c_str()); + sLog.outWarden("%s", stream.str().c_str()); } void WardenWin::HandleData(ByteBuffer &buff) { - sLog.outError("[Warden]: Handle data"); + sLog.outWarden("Handle data"); _dataSent = false; _clientResponseTimer = 0; @@ -343,7 +343,7 @@ void WardenWin::HandleData(ByteBuffer &buff) if (!IsValidCheckSum(Checksum, buff.contents() + buff.rpos(), Length)) { buff.rpos(buff.wpos()); - sLog.outError("[Warden]: %s failed checksum. Action: %s", _session->GetPlayerName(), Penalty().c_str()); + sLog.outWarden("%s failed checksum. Action: %s", _session->GetPlayerName(), Penalty().c_str()); return; } @@ -354,7 +354,7 @@ void WardenWin::HandleData(ByteBuffer &buff) /// @todo test it. if (result == 0x00) { - sLog.outError("[Warden]: %s failed timing check. Action: %s", _session->GetPlayerName(), Penalty().c_str()); + sLog.outWarden("%s failed timing check. Action: %s", _session->GetPlayerName(), Penalty().c_str()); return; } @@ -364,10 +364,10 @@ void WardenWin::HandleData(ByteBuffer &buff) uint32 ticksNow = WorldTimer::getMSTime(); uint32 ourTicks = newClientTicks + (ticksNow - _serverTicks); - sLog.outError("[Warden]: ServerTicks %u", ticksNow); // Now - sLog.outError("[Warden]: RequestTicks %u", _serverTicks); // At request - sLog.outError("[Warden]: Ticks %u", newClientTicks); // At response - sLog.outError("[Warden]: Ticks diff %u", ourTicks - newClientTicks); + sLog.outWarden("ServerTicks %u", ticksNow); // Now + sLog.outWarden("RequestTicks %u", _serverTicks); // At request + sLog.outWarden("Ticks %u", newClientTicks); // At response + sLog.outWarden("Ticks diff %u", ourTicks - newClientTicks); } WardenCheckResult* rs; @@ -392,20 +392,20 @@ void WardenWin::HandleData(ByteBuffer &buff) if (Mem_Result != 0) { - sLog.outError("[Warden]: RESULT MEM_CHECK not 0x00, CheckId %u account Id %u", *itr, _session->GetAccountId()); + sLog.outWarden("RESULT MEM_CHECK not 0x00, CheckId %u account Id %u", *itr, _session->GetAccountId()); checkFailed = *itr; continue; } if (memcmp(buff.contents() + buff.rpos(), rs->Result.AsByteArray(0, false), rd->Length) != 0) { - sLog.outError("[Warden]: RESULT MEM_CHECK fail CheckId %u account Id %u", *itr, _session->GetAccountId()); + sLog.outWarden("RESULT MEM_CHECK fail CheckId %u account Id %u", *itr, _session->GetAccountId()); checkFailed = *itr; buff.rpos(buff.rpos() + rd->Length); continue; } buff.rpos(buff.rpos() + rd->Length); - sLog.outError("[Warden]: RESULT MEM_CHECK passed CheckId %u account Id %u", *itr, _session->GetAccountId()); + sLog.outWarden("RESULT MEM_CHECK passed CheckId %u account Id %u", *itr, _session->GetAccountId()); break; } case PAGE_CHECK_A: @@ -417,11 +417,11 @@ void WardenWin::HandleData(ByteBuffer &buff) if (memcmp(buff.contents() + buff.rpos(), &byte, sizeof(uint8)) != 0) { if (type == PAGE_CHECK_A || type == PAGE_CHECK_B) - sLog.outError("[Warden]: RESULT PAGE_CHECK fail, CheckId %u account Id %u", *itr, _session->GetAccountId()); + sLog.outWarden("RESULT PAGE_CHECK fail, CheckId %u account Id %u", *itr, _session->GetAccountId()); if (type == MODULE_CHECK) - sLog.outError("[Warden]: RESULT MODULE_CHECK fail, CheckId %u account Id %u", *itr, _session->GetAccountId()); + sLog.outWarden("RESULT MODULE_CHECK fail, CheckId %u account Id %u", *itr, _session->GetAccountId()); if (type == DRIVER_CHECK) - sLog.outError("[Warden]: RESULT DRIVER_CHECK fail, CheckId %u account Id %u", *itr, _session->GetAccountId()); + sLog.outWarden("RESULT DRIVER_CHECK fail, CheckId %u account Id %u", *itr, _session->GetAccountId()); checkFailed = *itr; buff.rpos(buff.rpos() + 1); continue; @@ -429,11 +429,11 @@ void WardenWin::HandleData(ByteBuffer &buff) buff.rpos(buff.rpos() + 1); if (type == PAGE_CHECK_A || type == PAGE_CHECK_B) - sLog.outError("[Warden]: RESULT PAGE_CHECK passed CheckId %u account Id %u", *itr, _session->GetAccountId()); + sLog.outWarden("RESULT PAGE_CHECK passed CheckId %u account Id %u", *itr, _session->GetAccountId()); else if (type == MODULE_CHECK) - sLog.outError("[Warden]: RESULT MODULE_CHECK passed CheckId %u account Id %u", *itr, _session->GetAccountId()); + sLog.outWarden("RESULT MODULE_CHECK passed CheckId %u account Id %u", *itr, _session->GetAccountId()); else if (type == DRIVER_CHECK) - sLog.outError("[Warden]: RESULT DRIVER_CHECK passed CheckId %u account Id %u", *itr, _session->GetAccountId()); + sLog.outWarden("RESULT DRIVER_CHECK passed CheckId %u account Id %u", *itr, _session->GetAccountId()); break; } case LUA_STR_CHECK: @@ -443,7 +443,7 @@ void WardenWin::HandleData(ByteBuffer &buff) if (Lua_Result != 0) { - sLog.outError("[Warden]: RESULT LUA_STR_CHECK fail, CheckId %u account Id %u", *itr, _session->GetAccountId()); + sLog.outWarden("RESULT LUA_STR_CHECK fail, CheckId %u account Id %u", *itr, _session->GetAccountId()); checkFailed = *itr; continue; } @@ -456,11 +456,11 @@ void WardenWin::HandleData(ByteBuffer &buff) char *str = new char[luaStrLen + 1]; memcpy(str, buff.contents() + buff.rpos(), luaStrLen); str[luaStrLen] = '\0'; // null terminator - sLog.outError("[Warden]: Lua string: %s", str); + sLog.outWarden("Lua string: %s", str); delete[] str; } buff.rpos(buff.rpos() + luaStrLen); // Skip string - sLog.outError("[Warden]: RESULT LUA_STR_CHECK passed, CheckId %u account Id %u", *itr, _session->GetAccountId()); + sLog.outWarden("RESULT LUA_STR_CHECK passed, CheckId %u account Id %u", *itr, _session->GetAccountId()); break; } case MPQ_CHECK: @@ -470,21 +470,21 @@ void WardenWin::HandleData(ByteBuffer &buff) if (Mpq_Result != 0) { - sLog.outError("[Warden]: RESULT MPQ_CHECK not 0x00 account id %u", _session->GetAccountId()); + sLog.outWarden("RESULT MPQ_CHECK not 0x00 account id %u", _session->GetAccountId()); checkFailed = *itr; continue; } if (memcmp(buff.contents() + buff.rpos(), rs->Result.AsByteArray(0, false), 20) != 0) // SHA1 { - sLog.outError("[Warden]: RESULT MPQ_CHECK fail, CheckId %u account Id %u", *itr, _session->GetAccountId()); + sLog.outWarden("RESULT MPQ_CHECK fail, CheckId %u account Id %u", *itr, _session->GetAccountId()); checkFailed = *itr; buff.rpos(buff.rpos() + 20); // 20 bytes SHA1 continue; } buff.rpos(buff.rpos() + 20); // 20 bytes SHA1 - sLog.outError("[Warden]: RESULT MPQ_CHECK passed, CheckId %u account Id %u", *itr, _session->GetAccountId()); + sLog.outWarden("RESULT MPQ_CHECK passed, CheckId %u account Id %u", *itr, _session->GetAccountId()); break; } default: // Should never happen @@ -495,7 +495,7 @@ void WardenWin::HandleData(ByteBuffer &buff) if (checkFailed > 0) { WardenCheck* check = sWardenCheckMgr->GetWardenDataById(checkFailed); - sLog.outError("[Warden]: %s failed Warden check %u. Action: %s", _session->GetPlayerName(), checkFailed, Penalty(check).c_str()); + sLog.outWarden("%s failed Warden check %u. Action: %s", _session->GetPlayerName(), checkFailed, Penalty(check).c_str()); } // Set hold off timer, minimum timer should at least be 1 second diff --git a/src/game/WorldHandlers/World.cpp b/src/game/WorldHandlers/World.cpp index ee04748c..792d8467 100644 --- a/src/game/WorldHandlers/World.cpp +++ b/src/game/WorldHandlers/World.cpp @@ -734,7 +734,8 @@ void World::LoadConfigSettings(bool reload) // WARDEN - setConfig(CONFIG_BOOL_WARDEN_ENABLED, "Warden.Enabled", false); + setConfig(CONFIG_BOOL_WARDEN_WIN_ENABLED, "Warden.WinEnabled", true); + setConfig(CONFIG_BOOL_WARDEN_OSX_ENABLED, "Warden.OSXEnabled", false); setConfig(CONFIG_INT32_WARDEN_NUM_MEM_CHECKS, "Warden.NumMemChecks", 3); setConfig(CONFIG_INT32_WARDEN_NUM_OTHER_CHECKS, "Warden.NumOtherChecks", 7); setConfig(CONFIG_INT32_WARDEN_CLIENT_BAN_DURATION, "Warden.BanDuration", 86400); diff --git a/src/game/WorldHandlers/World.h b/src/game/WorldHandlers/World.h index 1bba6bba..01681964 100644 --- a/src/game/WorldHandlers/World.h +++ b/src/game/WorldHandlers/World.h @@ -357,7 +357,8 @@ enum eConfigBoolValues CONFIG_BOOL_PLAYERBOT_COLLECT_OBJECTS, CONFIG_BOOL_PLAYERBOT_SELL_TRASH, #endif - CONFIG_BOOL_WARDEN_ENABLED, + CONFIG_BOOL_WARDEN_WIN_ENABLED, + CONFIG_BOOL_WARDEN_OSX_ENABLED, CONFIG_BOOL_VALUE_COUNT }; diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index e2b7aff1..b68fa1a1 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -3,7 +3,7 @@ ################################################################################ [MangosdConf] -ConfVersion=2015040901 +ConfVersion=2015041201 ################################################################################ # CONNECTIONS AND DIRECTORIES @@ -372,6 +372,11 @@ CleanCharacterDB = 1 # Default: "Ra.log" # "" - Empty name for disable # +# WardenLogFile +# Log file for warden-related output +# Default: "" - no log file created +# "warden.log" - recommended name to create a log file +# # LogColors # Color for messages (format "normal_color details_color debug_color error_color") # Colors: 0 - BLACK, 1 - RED, 2 - GREEN, 3 - BROWN, 4 - BLUE, 5 - MAGENTA, 6 - CYAN, 7 - GREY, @@ -417,6 +422,8 @@ GmLogFile = "world-gamemaster.log" GmLogTimestamp = 0 GmLogPerAccount = 0 RaLogFile = "world-remote-access.log" +WardenLogFile = "warden.log" +WardenLogTimestamp = 0 LogColors = "13 7 11 9" SD2ErrorLogFile = "scriptdev2-errors.log" @@ -1621,11 +1628,16 @@ CharDelete.KeepDays = 30 ################################################################################################### # WARDEN SETTINGS # -# Warden.Enabled -# Description: Enable Warden anticheat system. +# Warden.WinEnabled +# Description: Enables Warden checks for Windows clients. # Default: 1 - (Enabled) # 0 - (Disabled) # +# Warden.OSXEnabled +# Description: Enables Warden checks for OSX clients. +# Default: 0 - (Disabled) +# 1 - (Enabled) +# # Warden.NumMemChecks # Description: Number of Warden memory checks that are sent to the client each cycle. # Default: 3 - (Enabled) @@ -1664,7 +1676,8 @@ CharDelete.KeepDays = 30 # ################################################################################################### -Warden.Enabled = 1 +Warden.WinEnabled = 1 +Warden.OSXEnabled = 0 Warden.NumMemChecks = 3 Warden.NumOtherChecks = 7 Warden.ClientResponseDelay = 600 diff --git a/src/shared/Log/Log.cpp b/src/shared/Log/Log.cpp index 3fd711aa..466da04d 100644 --- a/src/shared/Log/Log.cpp +++ b/src/shared/Log/Log.cpp @@ -76,7 +76,7 @@ Log::Log() : #ifdef ENABLE_ELUNA elunaErrLogfile(NULL), #endif /* ENABLE_ELUNA */ - eventAiErLogfile(NULL), scriptErrLogFile(NULL), worldLogfile(NULL), m_colored(false), + eventAiErLogfile(NULL), scriptErrLogFile(NULL), worldLogfile(NULL), wardenLogfile(NULL), m_colored(false), m_includeTime(false), m_gmlog_per_account(false), m_scriptLibName(NULL) { Initialize(); @@ -279,6 +279,7 @@ void Log::Initialize() eventAiErLogfile = openLogFile("EventAIErrorLogFile", NULL, "a"); raLogfile = openLogFile("RaLogFile", NULL, "a"); worldLogfile = openLogFile("WorldLogFile", "WorldLogTimestamp", "a"); + wardenLogfile = openLogFile("WardenLogFile", "WardenLogTimestamp", "a"); // Main log file settings m_includeTime = sConfig.GetBoolDefault("LogTime", false); @@ -869,6 +870,69 @@ void Log::outCommand(uint32 account, const char* str, ...) fflush(stdout); } +void Log::outWarden() +{ + if (m_includeTime) + { + outTime(); + } + printf("\n"); + if (wardenLogfile) + { + outTimestamp(wardenLogfile); + fprintf(wardenLogfile, "\n"); + fflush(wardenLogfile); + } + + fflush(stdout); +} + +void Log::outWarden(const char* str, ...) +{ + if (!str) + { + return; + } + + if (m_colored) + { + SetColor(true, m_colors[LogNormal]); + } + + if (m_includeTime) + { + outTime(); + } + + va_list ap; + + va_start(ap, str); + vutf8printf(stdout, str, &ap); + va_end(ap); + + if (m_colored) + { + ResetColor(true); + } + + printf("\n"); + + if (wardenLogfile) + { + outTimestamp(wardenLogfile); + fprintf(wardenLogfile, "[Warden]: "); + + va_start(ap, str); + vfprintf(wardenLogfile, str, ap); + fprintf(wardenLogfile, "\n"); + va_end(ap); + + fflush(wardenLogfile); + } + + fflush(stdout); +} + void Log::outChar(const char* str, ...) { if (!str) diff --git a/src/shared/Log/Log.h b/src/shared/Log/Log.h index a265f0d8..0633da52 100644 --- a/src/shared/Log/Log.h +++ b/src/shared/Log/Log.h @@ -166,6 +166,12 @@ class Log : public MaNGOS::Singleton