feat(Core/Warden): Allow sending of custom lua payloads through Warden. (#14723)
This commit is contained in:
@@ -1297,6 +1297,11 @@ void WorldSession::InitWarden(SessionKey const& k, std::string const& os)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Warden* WorldSession::GetWarden()
|
||||||
|
{
|
||||||
|
return &(*_warden);
|
||||||
|
}
|
||||||
|
|
||||||
bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) const
|
bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) const
|
||||||
{
|
{
|
||||||
uint32 maxPacketCounterAllowed = GetMaxPacketCounterAllowed(p.GetOpcode());
|
uint32 maxPacketCounterAllowed = GetMaxPacketCounterAllowed(p.GetOpcode());
|
||||||
|
|||||||
@@ -374,6 +374,7 @@ public:
|
|||||||
uint32 GetTotalTime() const { return m_total_time; }
|
uint32 GetTotalTime() const { return m_total_time; }
|
||||||
|
|
||||||
void InitWarden(SessionKey const&, std::string const& os);
|
void InitWarden(SessionKey const&, std::string const& os);
|
||||||
|
Warden* GetWarden();
|
||||||
|
|
||||||
/// Session in auth.queue currently
|
/// Session in auth.queue currently
|
||||||
void SetInQueue(bool state) { m_inQueue = state; }
|
void SetInQueue(bool state) { m_inQueue = state; }
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
#include "WorldSession.h"
|
#include "WorldSession.h"
|
||||||
|
|
||||||
Warden::Warden() : _session(nullptr), _checkTimer(10000/*10 sec*/), _clientResponseTimer(0),
|
Warden::Warden() : _session(nullptr), _checkTimer(10000/*10 sec*/), _clientResponseTimer(0),
|
||||||
_dataSent(false), _module(nullptr), _initialized(false)
|
_dataSent(false), _module(nullptr), _initialized(false), _interrupted(false), _checkInProgress(false)
|
||||||
{
|
{
|
||||||
memset(_inputKey, 0, sizeof(_inputKey));
|
memset(_inputKey, 0, sizeof(_inputKey));
|
||||||
memset(_outputKey, 0, sizeof(_outputKey));
|
memset(_outputKey, 0, sizeof(_outputKey));
|
||||||
@@ -305,6 +305,11 @@ bool Warden::ProcessLuaCheckResponse(std::string const& msg)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WardenPayloadMgr* Warden::GetPayloadMgr()
|
||||||
|
{
|
||||||
|
return &_payloadMgr;
|
||||||
|
}
|
||||||
|
|
||||||
void WorldSession::HandleWardenDataOpcode(WorldPacket& recvData)
|
void WorldSession::HandleWardenDataOpcode(WorldPacket& recvData)
|
||||||
{
|
{
|
||||||
if (!_warden || recvData.empty())
|
if (!_warden || recvData.empty())
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "AuthDefines.h"
|
#include "AuthDefines.h"
|
||||||
#include "ByteBuffer.h"
|
#include "ByteBuffer.h"
|
||||||
#include "WardenCheckMgr.h"
|
#include "WardenCheckMgr.h"
|
||||||
|
#include "WardenPayloadMgr.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
enum WardenOpcodes
|
enum WardenOpcodes
|
||||||
@@ -113,6 +114,8 @@ public:
|
|||||||
virtual void InitializeModule() = 0;
|
virtual void InitializeModule() = 0;
|
||||||
virtual void RequestHash() = 0;
|
virtual void RequestHash() = 0;
|
||||||
virtual void HandleHashResult(ByteBuffer &buff) = 0;
|
virtual void HandleHashResult(ByteBuffer &buff) = 0;
|
||||||
|
virtual bool IsCheckInProgress() = 0;
|
||||||
|
virtual void ForceChecks() = 0;
|
||||||
virtual void RequestChecks() = 0;
|
virtual void RequestChecks() = 0;
|
||||||
virtual void HandleData(ByteBuffer &buff) = 0;
|
virtual void HandleData(ByteBuffer &buff) = 0;
|
||||||
bool ProcessLuaCheckResponse(std::string const& msg);
|
bool ProcessLuaCheckResponse(std::string const& msg);
|
||||||
@@ -129,8 +132,11 @@ public:
|
|||||||
// If no check is passed, the default action from config is executed
|
// If no check is passed, the default action from config is executed
|
||||||
void ApplyPenalty(uint16 checkId, std::string const& reason);
|
void ApplyPenalty(uint16 checkId, std::string const& reason);
|
||||||
|
|
||||||
|
WardenPayloadMgr* GetPayloadMgr();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WorldSession* _session;
|
WorldSession* _session;
|
||||||
|
WardenPayloadMgr _payloadMgr;
|
||||||
uint8 _inputKey[16];
|
uint8 _inputKey[16];
|
||||||
uint8 _outputKey[16];
|
uint8 _outputKey[16];
|
||||||
uint8 _seed[16];
|
uint8 _seed[16];
|
||||||
@@ -141,6 +147,9 @@ private:
|
|||||||
bool _dataSent;
|
bool _dataSent;
|
||||||
ClientWardenModule* _module;
|
ClientWardenModule* _module;
|
||||||
bool _initialized;
|
bool _initialized;
|
||||||
|
bool _interrupted;
|
||||||
|
bool _checkInProgress;
|
||||||
|
uint32 _interruptCounter = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,150 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 3 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "WardenPayloadMgr.h"
|
||||||
|
#include "StringFormat.h"
|
||||||
|
#include "Errors.h"
|
||||||
|
#include "Log.h"
|
||||||
|
|
||||||
|
WardenPayloadMgr::WardenPayloadMgr() { }
|
||||||
|
|
||||||
|
uint16 WardenPayloadMgr::GetFreePayloadId()
|
||||||
|
{
|
||||||
|
uint16 payloadId = WardenPayloadOffsetMin;
|
||||||
|
|
||||||
|
while (CachedChecks.find(payloadId) != CachedChecks.end())
|
||||||
|
{
|
||||||
|
payloadId++;
|
||||||
|
|
||||||
|
if (payloadId > WardenPayloadMgr::WardenPayloadOffsetMax)
|
||||||
|
{
|
||||||
|
LOG_ERROR("warden", "Max warden payload id of '{}' passed!", WardenPayloadMgr::WardenPayloadOffsetMax);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return payloadId;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 WardenPayloadMgr::RegisterPayload(const std::string& payload)
|
||||||
|
{
|
||||||
|
uint16 payloadId = GetFreePayloadId();
|
||||||
|
|
||||||
|
if (!payloadId || !RegisterPayload(payload, payloadId, false))
|
||||||
|
{
|
||||||
|
LOG_ERROR("warden", "Failed to register payload.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return payloadId;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WardenPayloadMgr::RegisterPayload(std::string const& payload, uint16 payloadId, bool replace)
|
||||||
|
{
|
||||||
|
//Payload id should be over or equal to the offset to prevent conflicts.
|
||||||
|
if (payloadId < WardenPayloadMgr::WardenPayloadOffsetMin)
|
||||||
|
{
|
||||||
|
LOG_ERROR("warden", "Tried to register payloadId lower than '{}'.", WardenPayloadMgr::WardenPayloadOffsetMin);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = CachedChecks.find(payloadId);
|
||||||
|
if (it != CachedChecks.end() && !replace)
|
||||||
|
{
|
||||||
|
LOG_ERROR("warden", "Payload Id '{}' already exists in CachedChecks.", payloadId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
WardenCheck wCheck;
|
||||||
|
wCheck.Type = WardenPayloadMgr::WardenPayloadCheckType;
|
||||||
|
wCheck.Str = payload;
|
||||||
|
wCheck.CheckId = payloadId;
|
||||||
|
|
||||||
|
std::string idStr = Acore::StringFormat("%04u", payloadId);
|
||||||
|
ASSERT(idStr.size() == 4);
|
||||||
|
std::copy(idStr.begin(), idStr.end(), wCheck.IdStr.begin());
|
||||||
|
|
||||||
|
if (replace)
|
||||||
|
{
|
||||||
|
CachedChecks.erase(payloadId);
|
||||||
|
}
|
||||||
|
|
||||||
|
CachedChecks.emplace(payloadId, wCheck);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WardenPayloadMgr::UnregisterPayload(uint16 payloadId)
|
||||||
|
{
|
||||||
|
return CachedChecks.erase(payloadId);
|
||||||
|
}
|
||||||
|
|
||||||
|
WardenCheck* WardenPayloadMgr::GetPayloadById(uint16 payloadId)
|
||||||
|
{
|
||||||
|
auto it = CachedChecks.find(payloadId);
|
||||||
|
|
||||||
|
if (it != CachedChecks.end())
|
||||||
|
{
|
||||||
|
return &it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WardenPayloadMgr::QueuePayload(uint16 payloadId, bool pushToFront)
|
||||||
|
{
|
||||||
|
auto it = CachedChecks.find(payloadId);
|
||||||
|
|
||||||
|
//Do not queue a payload if there is no payload matching the payloadId.
|
||||||
|
if (it == CachedChecks.end())
|
||||||
|
{
|
||||||
|
LOG_ERROR("warden", "Failed to queue payload id '{}' as it does not exist in CachedChecks.", payloadId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pushToFront)
|
||||||
|
{
|
||||||
|
QueuedPayloads.push_front(payloadId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QueuedPayloads.push_back(payloadId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WardenPayloadMgr::DequeuePayload(uint16 payloadId)
|
||||||
|
{
|
||||||
|
size_t const queueSize = QueuedPayloads.size();
|
||||||
|
QueuedPayloads.remove(payloadId);
|
||||||
|
|
||||||
|
return queueSize != QueuedPayloads.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WardenPayloadMgr::ClearQueuedPayloads()
|
||||||
|
{
|
||||||
|
QueuedPayloads.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 WardenPayloadMgr::GetPayloadCountInQueue()
|
||||||
|
{
|
||||||
|
return QueuedPayloads.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<uint16>* WardenPayloadMgr::GetPayloadsInQueue()
|
||||||
|
{
|
||||||
|
return &QueuedPayloads;
|
||||||
|
}
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 3 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _WARDEN_PAYLOAD_MGR_H
|
||||||
|
#define _WARDEN_PAYLOAD_MGR_H
|
||||||
|
|
||||||
|
#include "WardenCheckMgr.h"
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class WardenPayloadMgr
|
||||||
|
* @brief The WardenPayloadMgr is responsible for maintaining custom payloads used by modules.
|
||||||
|
* @details This allows users to send custom lua payloads up to a size of 512 bytes to the game client.
|
||||||
|
* Some of the things you can achieve with this is:
|
||||||
|
* - Interaction with the client interface (add custom frames)
|
||||||
|
* - Access to client CVars
|
||||||
|
* - Access to protected lua functions.
|
||||||
|
*
|
||||||
|
* Opening up many possiblilties for a patch-less custom server.
|
||||||
|
*/
|
||||||
|
class WardenPayloadMgr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WardenPayloadMgr();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Finds a free payload id in WardenPayloadMgr::CachedChecks.
|
||||||
|
* @return uint16 The free payload id. Returns 0 if there is no free id.
|
||||||
|
*/
|
||||||
|
uint16 GetFreePayloadId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register a payload into cache and returns its payload id.
|
||||||
|
* @param payload The payload to be stored in WardenPayloadMgr::CachedChecks.
|
||||||
|
* @return uint16 The payload id for use with WardenPayloadMgr::QueuePayload. Returns 0 if it failed to register.
|
||||||
|
* @note
|
||||||
|
* - Payloads are truncated to 512 bytes on the client, you may have to register your payloads in chunks if they are larger than this.
|
||||||
|
*/
|
||||||
|
uint16 RegisterPayload(const std::string& payload);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register a payload into cache with a custom id and returns the result.
|
||||||
|
* @param payload The payload to be stored in WardenPayloadMgr::CachedChecks.
|
||||||
|
* @param payloadId The payload id to be stored as the key in WardenPayloadMgr::CachedChecks.
|
||||||
|
* @param replace Whether the key should replace an existing entry value.
|
||||||
|
* @return bool The payload insertion result. If exists it will return false, otherwise true.
|
||||||
|
* @note
|
||||||
|
* - Payloads are truncated to 512 bytes on the client, you may have to register your payloads in chunks if they are larger than this.
|
||||||
|
* - It's a good idea to keep the value for payloadId between 9000-9999 for self defined payloads as they're the least likely occupied ids.
|
||||||
|
*/
|
||||||
|
bool RegisterPayload(std::string const& payload, uint16 payloadId, bool replace = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unregister a payload from cache and return if successful.
|
||||||
|
* @param payloadId The payload to removed from WardenPayloadMgr::CachedChecks.
|
||||||
|
* @return bool If the payloadId was present.
|
||||||
|
*/
|
||||||
|
bool UnregisterPayload(uint16 payloadId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get a payload by id from the WardenPayloadMgr::CachedChecks.
|
||||||
|
* @param payloadId The payload to fetched from WardenPayloadMgr::CachedChecks.
|
||||||
|
* @return WardenCheck* A pointer to the WardenCheck payload.
|
||||||
|
*/
|
||||||
|
WardenCheck* GetPayloadById(uint16 payloadId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Queue the payload into the normal warden checks.
|
||||||
|
* @param payloadId The payloadId to be queued.
|
||||||
|
* @param pushToFront If payload should be pushed to the front queue.
|
||||||
|
*/
|
||||||
|
void QueuePayload(uint16 payloadId, bool pushToFront = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Dequeue the payload from the WardenPayloadMgr::QueuedPayloads queue.
|
||||||
|
* @param payloadId The payloadId to be dequeued.
|
||||||
|
* @return bool If the payload was removed.
|
||||||
|
*/
|
||||||
|
bool DequeuePayload(uint16 payloadId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clear the payloads from the WardenPayloadMgr::QueuedPayloads queue.
|
||||||
|
*/
|
||||||
|
void ClearQueuedPayloads();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the amount of payloads waiting in WardenPayloadMgr::QueuedPayloads.
|
||||||
|
* @return The amount of payloads in queue.
|
||||||
|
*/
|
||||||
|
uint32 GetPayloadCountInQueue();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get payloads waiting in WardenPayloadMgr::QueuedPayloads.
|
||||||
|
* @return The payloads in queue.
|
||||||
|
*/
|
||||||
|
std::list<uint16>* GetPayloadsInQueue();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The minimum id available for custom payloads.
|
||||||
|
*/
|
||||||
|
static uint16 constexpr WardenPayloadOffsetMin = 5000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The maximum id available for custom payloads.
|
||||||
|
*/
|
||||||
|
static uint16 constexpr WardenPayloadOffsetMax = 9999;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The checktype used for warden payloads.
|
||||||
|
*/
|
||||||
|
static uint32 constexpr WardenPayloadCheckType = 139;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The list of currently queued payload ids to be sent through Warden.
|
||||||
|
*/
|
||||||
|
std::list<uint16> QueuedPayloads;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The cached payloads that are accessed by payload id.
|
||||||
|
*/
|
||||||
|
std::map<uint16, WardenCheck> CachedChecks;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _WARDEN_PAYLOAD_MGR_H
|
||||||
@@ -61,7 +61,18 @@ static uint16 GetCheckPacketSize(WardenCheck const* check)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 size = 1 + GetCheckPacketBaseSize(check->Type); // 1 byte check type
|
uint16 size = 1;
|
||||||
|
|
||||||
|
if (check->CheckId >= WardenPayloadMgr::WardenPayloadOffsetMin && check->Type == LUA_EVAL_CHECK)
|
||||||
|
{
|
||||||
|
// Custom payload has no prefix, midfix, postfix.
|
||||||
|
size = size + (4 + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size = size + GetCheckPacketBaseSize(check->Type); // 1 byte check type
|
||||||
|
}
|
||||||
|
|
||||||
if (!check->Str.empty())
|
if (!check->Str.empty())
|
||||||
{
|
{
|
||||||
size += (static_cast<uint16>(check->Str.length()) + 1); // 1 byte string length
|
size += (static_cast<uint16>(check->Str.length()) + 1); // 1 byte string length
|
||||||
@@ -239,10 +250,35 @@ void WardenWin::HandleHashResult(ByteBuffer& buff)
|
|||||||
_initialized = true;
|
_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the warden check state.
|
||||||
|
* @return The warden check state.
|
||||||
|
*/
|
||||||
|
bool WardenWin::IsCheckInProgress()
|
||||||
|
{
|
||||||
|
return _checkInProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Force call RequestChecks() so they are sent immediately, this interrupts warden and breaks result.
|
||||||
|
*/
|
||||||
|
void WardenWin::ForceChecks()
|
||||||
|
{
|
||||||
|
if (_dataSent)
|
||||||
|
{
|
||||||
|
_interrupted = true;
|
||||||
|
_interruptCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
RequestChecks();
|
||||||
|
}
|
||||||
|
|
||||||
void WardenWin::RequestChecks()
|
void WardenWin::RequestChecks()
|
||||||
{
|
{
|
||||||
LOG_DEBUG("warden", "Request data");
|
LOG_DEBUG("warden", "Request data");
|
||||||
|
|
||||||
|
_checkInProgress = true;
|
||||||
|
|
||||||
// If all checks were done, fill the todo list again
|
// If all checks were done, fill the todo list again
|
||||||
for (uint8 i = 0; i < MAX_WARDEN_CHECK_TYPES; ++i)
|
for (uint8 i = 0; i < MAX_WARDEN_CHECK_TYPES; ++i)
|
||||||
{
|
{
|
||||||
@@ -253,6 +289,30 @@ void WardenWin::RequestChecks()
|
|||||||
_serverTicks = GameTime::GetGameTimeMS().count();
|
_serverTicks = GameTime::GetGameTimeMS().count();
|
||||||
_CurrentChecks.clear();
|
_CurrentChecks.clear();
|
||||||
|
|
||||||
|
// Erase any nullptrs.
|
||||||
|
Acore::Containers::EraseIf(_PendingChecks,
|
||||||
|
[this](uint16 id)
|
||||||
|
{
|
||||||
|
WardenCheck const* check = sWardenCheckMgr->GetWardenDataById(id);
|
||||||
|
|
||||||
|
// Custom payload should be loaded in if equal to over offset.
|
||||||
|
if (!check && id >= WardenPayloadMgr::WardenPayloadOffsetMin)
|
||||||
|
{
|
||||||
|
if (_payloadMgr.CachedChecks.find(id) != _payloadMgr.CachedChecks.end())
|
||||||
|
{
|
||||||
|
check = &_payloadMgr.CachedChecks.at(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!check)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// No pending checks
|
// No pending checks
|
||||||
if (_PendingChecks.empty())
|
if (_PendingChecks.empty())
|
||||||
{
|
{
|
||||||
@@ -266,6 +326,19 @@ void WardenWin::RequestChecks()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load in any custom payloads if available.
|
||||||
|
if (checkType == WARDEN_CHECK_LUA_TYPE && !_payloadMgr.QueuedPayloads.empty())
|
||||||
|
{
|
||||||
|
uint16 payloadId = _payloadMgr.QueuedPayloads.front();
|
||||||
|
|
||||||
|
LOG_DEBUG("warden", "Adding custom warden payload '{}' to CurrentChecks.", payloadId);
|
||||||
|
|
||||||
|
_payloadMgr.QueuedPayloads.pop_front();
|
||||||
|
_CurrentChecks.push_front(payloadId);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Get check id from the end and remove it from todo
|
// Get check id from the end and remove it from todo
|
||||||
uint16 const id = _ChecksTodo[checkType].back();
|
uint16 const id = _ChecksTodo[checkType].back();
|
||||||
_ChecksTodo[checkType].pop_back();
|
_ChecksTodo[checkType].pop_back();
|
||||||
@@ -288,6 +361,13 @@ void WardenWin::RequestChecks()
|
|||||||
for (uint16 const checkId : _PendingChecks)
|
for (uint16 const checkId : _PendingChecks)
|
||||||
{
|
{
|
||||||
WardenCheck const* check = sWardenCheckMgr->GetWardenDataById(checkId);
|
WardenCheck const* check = sWardenCheckMgr->GetWardenDataById(checkId);
|
||||||
|
|
||||||
|
// Custom payload should be loaded in if equal to over offset.
|
||||||
|
if (!check && checkId >= WardenPayloadMgr::WardenPayloadOffsetMin)
|
||||||
|
{
|
||||||
|
check = &_payloadMgr.CachedChecks.at(checkId);
|
||||||
|
}
|
||||||
|
|
||||||
if (!hasLuaChecks && check->Type == LUA_EVAL_CHECK)
|
if (!hasLuaChecks && check->Type == LUA_EVAL_CHECK)
|
||||||
{
|
{
|
||||||
hasLuaChecks = true;
|
hasLuaChecks = true;
|
||||||
@@ -324,7 +404,21 @@ void WardenWin::RequestChecks()
|
|||||||
Acore::Containers::EraseIf(_CurrentChecks,
|
Acore::Containers::EraseIf(_CurrentChecks,
|
||||||
[this, &expectedSize](uint16 id)
|
[this, &expectedSize](uint16 id)
|
||||||
{
|
{
|
||||||
uint16 const thisSize = GetCheckPacketSize(sWardenCheckMgr->GetWardenDataById(id));
|
WardenCheck const* check = sWardenCheckMgr->GetWardenDataById(id);
|
||||||
|
|
||||||
|
// Custom payload should be loaded in if equal to over offset.
|
||||||
|
if (!check && id >= WardenPayloadMgr::WardenPayloadOffsetMin)
|
||||||
|
{
|
||||||
|
check = &_payloadMgr.CachedChecks.at(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove nullptr if it snuck in from earlier check.
|
||||||
|
if (!check)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 const thisSize = GetCheckPacketSize(check);
|
||||||
if ((expectedSize + thisSize) > 500) // warden packets are truncated to 512 bytes clientside
|
if ((expectedSize + thisSize) > 500) // warden packets are truncated to 512 bytes clientside
|
||||||
{
|
{
|
||||||
_PendingChecks.push_back(id);
|
_PendingChecks.push_back(id);
|
||||||
@@ -341,6 +435,18 @@ void WardenWin::RequestChecks()
|
|||||||
for (uint16 const checkId : _CurrentChecks)
|
for (uint16 const checkId : _CurrentChecks)
|
||||||
{
|
{
|
||||||
WardenCheck const* check = sWardenCheckMgr->GetWardenDataById(checkId);
|
WardenCheck const* check = sWardenCheckMgr->GetWardenDataById(checkId);
|
||||||
|
|
||||||
|
// Custom payloads do not have prefix, midfix, postfix.
|
||||||
|
if (!check && checkId >= WardenPayloadMgr::WardenPayloadOffsetMin)
|
||||||
|
{
|
||||||
|
check = &_payloadMgr.CachedChecks.at(checkId);
|
||||||
|
|
||||||
|
buff << uint8(check->Str.size());
|
||||||
|
buff.append(check->Str.data(), check->Str.size());
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
switch (check->Type)
|
switch (check->Type)
|
||||||
{
|
{
|
||||||
case LUA_EVAL_CHECK:
|
case LUA_EVAL_CHECK:
|
||||||
@@ -374,6 +480,13 @@ void WardenWin::RequestChecks()
|
|||||||
for (uint16 const checkId : _CurrentChecks)
|
for (uint16 const checkId : _CurrentChecks)
|
||||||
{
|
{
|
||||||
WardenCheck const* check = sWardenCheckMgr->GetWardenDataById(checkId);
|
WardenCheck const* check = sWardenCheckMgr->GetWardenDataById(checkId);
|
||||||
|
|
||||||
|
// Custom payload should be loaded in if equal to over offset.
|
||||||
|
if (!check && checkId >= WardenPayloadMgr::WardenPayloadOffsetMin)
|
||||||
|
{
|
||||||
|
check = &_payloadMgr.CachedChecks.at(checkId);
|
||||||
|
}
|
||||||
|
|
||||||
buff << uint8(check->Type ^ xorByte);
|
buff << uint8(check->Type ^ xorByte);
|
||||||
switch (check->Type)
|
switch (check->Type)
|
||||||
{
|
{
|
||||||
@@ -448,6 +561,8 @@ void WardenWin::RequestChecks()
|
|||||||
|
|
||||||
void WardenWin::HandleData(ByteBuffer& buff)
|
void WardenWin::HandleData(ByteBuffer& buff)
|
||||||
{
|
{
|
||||||
|
if (!_interrupted)
|
||||||
|
{
|
||||||
LOG_DEBUG("warden", "Handle data");
|
LOG_DEBUG("warden", "Handle data");
|
||||||
|
|
||||||
_dataSent = false;
|
_dataSent = false;
|
||||||
@@ -502,6 +617,13 @@ void WardenWin::HandleData(ByteBuffer& buff)
|
|||||||
for (uint16 const checkId : _CurrentChecks)
|
for (uint16 const checkId : _CurrentChecks)
|
||||||
{
|
{
|
||||||
WardenCheck const* rd = sWardenCheckMgr->GetWardenDataById(checkId);
|
WardenCheck const* rd = sWardenCheckMgr->GetWardenDataById(checkId);
|
||||||
|
|
||||||
|
// Custom payload should be loaded in if equal to over offset.
|
||||||
|
if (!rd && checkId >= WardenPayloadMgr::WardenPayloadOffsetMin)
|
||||||
|
{
|
||||||
|
rd = &_payloadMgr.CachedChecks.at(checkId);
|
||||||
|
}
|
||||||
|
|
||||||
uint8 const type = rd->Type;
|
uint8 const type = rd->Type;
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
@@ -537,17 +659,24 @@ void WardenWin::HandleData(ByteBuffer& buff)
|
|||||||
case DRIVER_CHECK:
|
case DRIVER_CHECK:
|
||||||
case MODULE_CHECK:
|
case MODULE_CHECK:
|
||||||
{
|
{
|
||||||
const uint8 byte = 0xE9;
|
uint8 const byte = 0xE9;
|
||||||
if (memcmp(buff.contents() + buff.rpos(), &byte, sizeof(uint8)) != 0)
|
if (memcmp(buff.contents() + buff.rpos(), &byte, sizeof(uint8)) != 0)
|
||||||
{
|
{
|
||||||
if (type == PAGE_CHECK_A || type == PAGE_CHECK_B)
|
if (type == PAGE_CHECK_A || type == PAGE_CHECK_B)
|
||||||
|
{
|
||||||
LOG_DEBUG("warden", "RESULT PAGE_CHECK fail, CheckId {} account Id {}", checkId, _session->GetAccountId());
|
LOG_DEBUG("warden", "RESULT PAGE_CHECK fail, CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||||
|
}
|
||||||
|
|
||||||
if (type == MODULE_CHECK)
|
if (type == MODULE_CHECK)
|
||||||
|
{
|
||||||
LOG_DEBUG("warden", "RESULT MODULE_CHECK fail, CheckId {} account Id {}", checkId, _session->GetAccountId());
|
LOG_DEBUG("warden", "RESULT MODULE_CHECK fail, CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||||
|
}
|
||||||
|
|
||||||
if (type == DRIVER_CHECK)
|
if (type == DRIVER_CHECK)
|
||||||
|
{
|
||||||
LOG_DEBUG("warden", "RESULT DRIVER_CHECK fail, CheckId {} account Id {}", checkId, _session->GetAccountId());
|
LOG_DEBUG("warden", "RESULT DRIVER_CHECK fail, CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||||
|
}
|
||||||
|
|
||||||
checkFailed = checkId;
|
checkFailed = checkId;
|
||||||
buff.rpos(buff.rpos() + 1);
|
buff.rpos(buff.rpos() + 1);
|
||||||
continue;
|
continue;
|
||||||
@@ -556,16 +685,23 @@ void WardenWin::HandleData(ByteBuffer& buff)
|
|||||||
buff.rpos(buff.rpos() + 1);
|
buff.rpos(buff.rpos() + 1);
|
||||||
|
|
||||||
if (type == PAGE_CHECK_A || type == PAGE_CHECK_B)
|
if (type == PAGE_CHECK_A || type == PAGE_CHECK_B)
|
||||||
|
{
|
||||||
LOG_DEBUG("warden", "RESULT PAGE_CHECK passed CheckId {} account Id {}", checkId, _session->GetAccountId());
|
LOG_DEBUG("warden", "RESULT PAGE_CHECK passed CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||||
|
}
|
||||||
else if (type == MODULE_CHECK)
|
else if (type == MODULE_CHECK)
|
||||||
|
{
|
||||||
LOG_DEBUG("warden", "RESULT MODULE_CHECK passed CheckId {} account Id {}", checkId, _session->GetAccountId());
|
LOG_DEBUG("warden", "RESULT MODULE_CHECK passed CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||||
|
}
|
||||||
else if (type == DRIVER_CHECK)
|
else if (type == DRIVER_CHECK)
|
||||||
|
{
|
||||||
LOG_DEBUG("warden", "RESULT DRIVER_CHECK passed CheckId {} account Id {}", checkId, _session->GetAccountId());
|
LOG_DEBUG("warden", "RESULT DRIVER_CHECK passed CheckId {} account Id {}", checkId, _session->GetAccountId());
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LUA_EVAL_CHECK:
|
case LUA_EVAL_CHECK:
|
||||||
{
|
{
|
||||||
uint8 const result = buff.read<uint8>();
|
uint8 const result = buff.read<uint8>();
|
||||||
|
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
{
|
{
|
||||||
buff.read_skip(buff.read<uint8>()); // discard attached string
|
buff.read_skip(buff.read<uint8>()); // discard attached string
|
||||||
@@ -606,8 +742,22 @@ void WardenWin::HandleData(ByteBuffer& buff)
|
|||||||
{
|
{
|
||||||
ApplyPenalty(checkFailed, "");
|
ApplyPenalty(checkFailed, "");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_DEBUG("warden", "Warden was interrupted by ForceChecks, ignoring results.");
|
||||||
|
|
||||||
|
_interruptCounter--;
|
||||||
|
|
||||||
|
if (_interruptCounter == 0)
|
||||||
|
{
|
||||||
|
_interrupted = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set hold off timer, minimum timer should at least be 1 second
|
// Set hold off timer, minimum timer should at least be 1 second
|
||||||
uint32 const holdOff = sWorld->getIntConfig(CONFIG_WARDEN_CLIENT_CHECK_HOLDOFF);
|
uint32 const holdOff = sWorld->getIntConfig(CONFIG_WARDEN_CLIENT_CHECK_HOLDOFF);
|
||||||
_checkTimer = (holdOff < 1 ? 1 : holdOff) * IN_MILLISECONDS;
|
_checkTimer = (holdOff < 1 ? 1 : holdOff) * IN_MILLISECONDS;
|
||||||
|
|
||||||
|
_checkInProgress = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,6 +81,8 @@ public:
|
|||||||
void RequestHash() override;
|
void RequestHash() override;
|
||||||
void HandleHashResult(ByteBuffer& buff) override;
|
void HandleHashResult(ByteBuffer& buff) override;
|
||||||
void RequestChecks() override;
|
void RequestChecks() override;
|
||||||
|
bool IsCheckInProgress() override;
|
||||||
|
void ForceChecks() override;
|
||||||
void HandleData(ByteBuffer& buff) override;
|
void HandleData(ByteBuffer& buff) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
Reference in New Issue
Block a user