TrinityCore
WardenCheckMgr.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "WardenCheckMgr.h"
19
20#include "Common.h"
21#include "DatabaseEnv.h"
22#include "Errors.h"
23#include "Log.h"
24#include "Warden.h"
25#include "World.h"
26
28{
29}
30
32{
33 uint32 oldMSTime = getMSTime();
34
35 // Check if Warden is enabled by config before loading anything
36 if (!sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED))
37 {
38 TC_LOG_INFO("warden", ">> Warden disabled, loading checks skipped.");
39 return;
40 }
41
42 QueryResult result = WorldDatabase.Query("SELECT MAX(id) FROM warden_checks");
43
44 if (!result)
45 {
46 TC_LOG_INFO("server.loading", ">> Loaded 0 Warden checks. DB table `warden_checks` is empty!");
47 return;
48 }
49
50 Field* fields = result->Fetch();
51
52 uint16 maxCheckId = fields[0].GetUInt16();
53
54 _checks.resize(maxCheckId+1);
55
56 // 0 1 2 3 4 5 6 7
57 result = WorldDatabase.Query("SELECT id, type, data, result, address, length, str, comment FROM warden_checks ORDER BY id ASC");
58
59 uint32 count = 0;
60 do
61 {
62 fields = result->Fetch();
63
64 uint16 const id = fields[0].GetUInt16();
65 WardenCheckType const type = static_cast<WardenCheckType>(fields[1].GetUInt8());
66 WardenCheckCategory const category = GetWardenCheckCategory(type);
67
68 if (category == NUM_CHECK_CATEGORIES)
69 {
70 TC_LOG_ERROR("sql.sql", "Warden check with id {} lists check type {} in `warden_checks`, which is not supported. Skipped.", id, type);
71 continue;
72 }
73
74 if ((type == LUA_EVAL_CHECK) && (id > 9999))
75 {
76 TC_LOG_ERROR("sql.sql", "Warden Lua check with id {} found in `warden_checks`. Lua checks may have four-digit IDs at most. Skipped.", id);
77 continue;
78 }
79
80 WardenCheck& wardenCheck = _checks[id];
81 wardenCheck.CheckId = id;
82 wardenCheck.Type = type;
83
84 if (type == PAGE_CHECK_A || type == PAGE_CHECK_B || type == DRIVER_CHECK)
85 wardenCheck.Data = fields[2].GetBinary();
86
87 if (type == MPQ_CHECK || type == MEM_CHECK)
88 _checkResults.emplace(id, fields[3].GetBinary());
89
90 if (type == MEM_CHECK || type == PAGE_CHECK_A || type == PAGE_CHECK_B || type == PROC_CHECK)
91 wardenCheck.Address = fields[4].GetUInt32();
92
93 if (type == PAGE_CHECK_A || type == PAGE_CHECK_B || type == PROC_CHECK)
94 wardenCheck.Length = fields[5].GetUInt8();
95
96 // PROC_CHECK support missing
97 if (type == MEM_CHECK || type == MPQ_CHECK || type == LUA_EVAL_CHECK || type == DRIVER_CHECK || type == MODULE_CHECK)
98 wardenCheck.Str = fields[6].GetString();
99
100 wardenCheck.Comment = fields[7].GetString();
101 if (wardenCheck.Comment.empty())
102 wardenCheck.Comment = "Undocumented Check";
103
104 if (type == LUA_EVAL_CHECK)
105 {
106 if (wardenCheck.Str.size() > WARDEN_MAX_LUA_CHECK_LENGTH)
107 {
108 TC_LOG_ERROR("sql.sql", "Found over-long Lua check for Warden check with id {} in `warden_checks`. Max length is {}. Skipped.", id, WARDEN_MAX_LUA_CHECK_LENGTH);
109 continue;
110 }
111
112 std::string str = Trinity::StringFormat("{:04}", id);
113 ASSERT(str.size() == 4);
114 std::copy(str.begin(), str.end(), wardenCheck.IdStr.begin());
115 }
116
117 // initialize action with default action from config, this may be overridden later
118 wardenCheck.Action = WardenActions(sWorld->getIntConfig(CONFIG_WARDEN_CLIENT_FAIL_ACTION));
119
120 _pools[category].push_back(id);
121 ++count;
122 }
123 while (result->NextRow());
124
125 TC_LOG_INFO("server.loading", ">> Loaded {} warden checks in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
126}
127
129{
130 uint32 oldMSTime = getMSTime();
131
132 // Check if Warden is enabled by config before loading anything
133 if (!sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED))
134 {
135 TC_LOG_INFO("warden", ">> Warden disabled, loading check overrides skipped.");
136 return;
137 }
138
139 // 0 1
140 QueryResult result = CharacterDatabase.Query("SELECT wardenId, action FROM warden_action");
141
142 if (!result)
143 {
144 TC_LOG_INFO("server.loading", ">> Loaded 0 Warden action overrides. DB table `warden_action` is empty!");
145 return;
146 }
147
148 uint32 count = 0;
149
150 do
151 {
152 Field* fields = result->Fetch();
153
154 uint16 checkId = fields[0].GetUInt16();
155 uint8 action = fields[1].GetUInt8();
156
157 // Check if action value is in range (0-2, see WardenActions enum)
158 if (action > WARDEN_ACTION_BAN)
159 TC_LOG_ERROR("warden", "Warden check override action out of range (ID: {}, action: {})", checkId, action);
160 // Check if check actually exists before accessing the _checks vector
161 else if (checkId >= _checks.size())
162 TC_LOG_ERROR("warden", "Warden check action override for non-existing check (ID: {}, action: {}), skipped", checkId, action);
163 else
164 {
165 _checks[checkId].Action = WardenActions(action);
166 ++count;
167 }
168 }
169 while (result->NextRow());
170
171 TC_LOG_INFO("server.loading", ">> Loaded {} warden action overrides in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
172}
173
175{
177 return &instance;
178}
179
181{
182 ASSERT(Id < _checks.size(), "Requested Warden data for invalid check ID %u", uint32(Id));
183 return _checks[Id];
184}
185
187{
188 auto it = _checkResults.find(Id);
189 ASSERT(it != _checkResults.end(), "Requested Warden result for invalid check ID %u", uint32(Id));
190 return it->second;
191}
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
Definition: DatabaseEnv.cpp:20
uint8_t uint8
Definition: Define.h:144
uint16_t uint16
Definition: Define.h:143
uint32_t uint32
Definition: Define.h:142
#define ASSERT
Definition: Errors.h:68
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
#define TC_LOG_INFO(filterType__,...)
Definition: Log.h:159
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition: Timer.h:57
uint32 getMSTime()
Definition: Timer.h:33
constexpr uint8 WARDEN_MAX_LUA_CHECK_LENGTH
std::vector< uint8 > WardenCheckResult
constexpr WardenCheckCategory GetWardenCheckCategory(WardenCheckType type)
WardenCheckCategory
@ NUM_CHECK_CATEGORIES
WardenCheckType
@ PROC_CHECK
@ DRIVER_CHECK
@ PAGE_CHECK_A
@ PAGE_CHECK_B
@ LUA_EVAL_CHECK
@ MPQ_CHECK
@ MEM_CHECK
@ MODULE_CHECK
WardenActions
@ WARDEN_ACTION_BAN
Class used to access individual fields of database query result.
Definition: Field.h:90
uint8 GetUInt8() const
Definition: Field.cpp:30
std::string GetString() const
Definition: Field.cpp:118
std::vector< uint8 > GetBinary() const
Definition: Field.cpp:142
uint16 GetUInt16() const
Definition: Field.cpp:46
uint32 GetUInt32() const
Definition: Field.cpp:62
void LoadWardenOverrides()
std::vector< WardenCheck > _checks
WardenCheckResult const & GetCheckResult(uint16 Id) const
std::unordered_map< uint16, WardenCheckResult > _checkResults
std::array< std::vector< uint16 >, NUM_CHECK_CATEGORIES > _pools
static WardenCheckMgr * instance()
WardenCheck const & GetCheckData(uint16 Id) const
#define sWorld
Definition: World.h:931
@ CONFIG_WARDEN_CLIENT_FAIL_ACTION
Definition: World.h:386
@ CONFIG_WARDEN_ENABLED
Definition: World.h:167
std::string StringFormat(FormatString< Args... > fmt, Args &&... args)
Default TC string format function.
Definition: StringFormat.h:38
std::array< char, 4 > IdStr
std::vector< uint8 > Data
std::string Str
WardenActions Action
std::string Comment
WardenCheckType Type