Skip to content

Commit 750d09a

Browse files
authored
Add element data client trust options. (#3839)
1 parent ad1da87 commit 750d09a

15 files changed

+96
-13
lines changed

Server/mods/deathmatch/local.conf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,12 @@
268268
Values: 0 - Off, 1 - Enabled. Default - 1 -->
269269
<resource_client_file_checks>1</resource_client_file_checks>
270270

271+
<!-- Enables extra protection for element data.
272+
When this option is enabled, the server ignores element data sync packets from the client,
273+
except for allowed keys.
274+
Values: 0 - Off, 1 - Enabled. Default - 0 -->
275+
<elementdata_whitelisted>0</elementdata_whitelisted>
276+
271277
<!-- Specifies the module(s) which are loaded with the server. To load several modules, add more <module>
272278
parameter(s). Optional parameter. -->
273279
<!-- <module src="sample_win32.dll"/> -->

Server/mods/deathmatch/logic/CCustomData.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ void CCustomData::Copy(CCustomData* pCustomData)
2121
}
2222
}
2323

24-
SCustomData* CCustomData::Get(const char* szName)
24+
SCustomData* CCustomData::Get(const char* szName) const
2525
{
2626
assert(szName);
2727

@@ -100,6 +100,7 @@ void CCustomData::Set(const char* szName, const CLuaArgument& Variable, ESyncTyp
100100
SCustomData newData;
101101
newData.Variable = Variable;
102102
newData.syncType = syncType;
103+
newData.clientChangesMode = eCustomDataClientTrust::UNSET;
103104
m_Data[szName] = newData;
104105
UpdateSynced(szName, Variable, syncType);
105106
}
@@ -120,6 +121,12 @@ bool CCustomData::Delete(const char* szName)
120121
return false;
121122
}
122123

124+
void CCustomData::SetClientChangesMode(const char* szName, eCustomDataClientTrust mode)
125+
{
126+
SCustomData& pData = m_Data[szName];
127+
pData.clientChangesMode = mode;
128+
}
129+
123130
CXMLNode* CCustomData::OutputToXML(CXMLNode* pNode)
124131
{
125132
std::map<std::string, SCustomData>::const_iterator iter = m_Data.begin();

Server/mods/deathmatch/logic/CCustomData.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,33 @@ enum class ESyncType
2525
SUBSCRIBE,
2626
};
2727

28+
enum class eCustomDataClientTrust : std::uint8_t
29+
{
30+
UNSET,
31+
ALLOW,
32+
DENY,
33+
};
34+
2835
struct SCustomData
2936
{
30-
CLuaArgument Variable;
31-
ESyncType syncType;
37+
CLuaArgument Variable;
38+
ESyncType syncType;
39+
eCustomDataClientTrust clientChangesMode;
3240
};
3341

3442
class CCustomData
3543
{
3644
public:
3745
void Copy(CCustomData* pCustomData);
3846

39-
SCustomData* Get(const char* szName);
47+
SCustomData* Get(const char* szName) const;
4048
SCustomData* GetSynced(const char* szName);
4149
void Set(const char* szName, const CLuaArgument& Variable, ESyncType syncType = ESyncType::BROADCAST);
4250

4351
bool Delete(const char* szName);
4452

53+
void SetClientChangesMode(const char* szName, eCustomDataClientTrust mode);
54+
4555
unsigned short CountOnlySynchronized();
4656

4757
CXMLNode* OutputToXML(CXMLNode* pNode);

Server/mods/deathmatch/logic/CElement.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ void CElement::ReadCustomData(CEvents* pEvents, CXMLNode& Node)
508508
}
509509
}
510510

511-
CLuaArgument* CElement::GetCustomData(const char* szName, bool bInheritData, ESyncType* pSyncType)
511+
CLuaArgument* CElement::GetCustomData(const char* szName, bool bInheritData, ESyncType* pSyncType, eCustomDataClientTrust* clientChangesMode)
512512
{
513513
assert(szName);
514514

@@ -518,13 +518,17 @@ CLuaArgument* CElement::GetCustomData(const char* szName, bool bInheritData, ESy
518518
{
519519
if (pSyncType)
520520
*pSyncType = pData->syncType;
521+
522+
if (clientChangesMode)
523+
*clientChangesMode = pData->clientChangesMode;
524+
521525
return &pData->Variable;
522526
}
523527

524528
// If none, try returning parent's custom data
525529
if (bInheritData && m_pParent)
526530
{
527-
return m_pParent->GetCustomData(szName, true, pSyncType);
531+
return m_pParent->GetCustomData(szName, true, pSyncType, clientChangesMode);
528532
}
529533

530534
// None available

Server/mods/deathmatch/logic/CElement.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ class CElement
136136

137137
void ReadCustomData(CEvents* pEvents, CXMLNode& Node);
138138
CCustomData& GetCustomDataManager() { return m_CustomData; }
139-
CLuaArgument* GetCustomData(const char* szName, bool bInheritData, ESyncType* pSyncType = NULL);
139+
CLuaArgument* GetCustomData(const char* szName, bool bInheritData, ESyncType* pSyncType = nullptr, eCustomDataClientTrust* clientChangesMode = nullptr);
140140
CLuaArguments* GetAllCustomData(CLuaArguments* table);
141141
bool GetCustomDataString(const char* szName, char* pOut, size_t sizeBuffer, bool bInheritData);
142142
bool GetCustomDataInt(const char* szName, int& iOut, bool bInheritData);

Server/mods/deathmatch/logic/CGame.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1607,6 +1607,7 @@ void CGame::AddBuiltInEvents()
16071607
m_Events.AddEvent("onPlayerTriggerEventThreshold", "", nullptr, false);
16081608
m_Events.AddEvent("onPlayerTeamChange", "oldTeam, newTeam", nullptr, false);
16091609
m_Events.AddEvent("onPlayerTriggerInvalidEvent", "eventName, isAdded, isRemote", nullptr, false);
1610+
m_Events.AddEvent("onPlayerChangesProtectedData", "element, key, value", nullptr, false);
16101611

16111612
// Ped events
16121613
m_Events.AddEvent("onPedVehicleEnter", "vehicle, seat, jacked", NULL, false);
@@ -2652,7 +2653,24 @@ void CGame::Packet_CustomData(CCustomDataPacket& Packet)
26522653
}
26532654

26542655
ESyncType lastSyncType = ESyncType::BROADCAST;
2655-
pElement->GetCustomData(szName, false, &lastSyncType);
2656+
eCustomDataClientTrust clientChangesMode{};
2657+
2658+
pElement->GetCustomData(szName, false, &lastSyncType, &clientChangesMode);
2659+
2660+
const bool changesAllowed = clientChangesMode == eCustomDataClientTrust::UNSET ? !m_pMainConfig->IsElementDataWhitelisted()
2661+
: clientChangesMode == eCustomDataClientTrust::ALLOW;
2662+
if (!changesAllowed)
2663+
{
2664+
CLogger::ErrorPrintf("Client trying to change protected element data %s (%s)", Packet.GetSourcePlayer()->GetNick(),
2665+
szName);
2666+
2667+
CLuaArguments arguments;
2668+
arguments.PushElement(pElement);
2669+
arguments.PushString(szName);
2670+
arguments.PushArgument(Value);
2671+
pSourcePlayer->CallEvent("onPlayerChangesProtectedData", arguments);
2672+
return;
2673+
}
26562674

26572675
if (lastSyncType != ESyncType::LOCAL)
26582676
{

Server/mods/deathmatch/logic/CMainConfig.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ CMainConfig::CMainConfig(CConsole* pConsole) : CXMLConfig(NULL)
7979
m_iBackupInterval = 3;
8080
m_iBackupAmount = 5;
8181
m_bSyncMapElementData = true;
82+
m_elementDataWhitelisted = false;
8283
}
8384

8485
bool CMainConfig::Load()
@@ -526,6 +527,8 @@ bool CMainConfig::Load()
526527
g_TickRateSettings.iLightSync = Clamp(200, g_TickRateSettings.iLightSync, 4000);
527528
}
528529

530+
GetBoolean(m_pRootNode, "elementdata_whitelisted", m_elementDataWhitelisted);
531+
529532
ApplyNetOptions();
530533

531534
return true;

Server/mods/deathmatch/logic/CMainConfig.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ class CMainConfig : public CXMLConfig
126126
const std::vector<SString>& GetOwnerEmailAddressList() const { return m_OwnerEmailAddressList; }
127127
bool IsDatabaseCredentialsProtectionEnabled() const { return m_bDatabaseCredentialsProtectionEnabled != 0; }
128128
bool IsFakeLagCommandEnabled() const { return m_bFakeLagCommandEnabled != 0; }
129+
bool IsElementDataWhitelisted() const { return m_elementDataWhitelisted; }
129130
bool IsCheckResourceClientFilesEnabled() const noexcept { return m_checkResourceClientFiles != 0; }
130131

131132
SString GetSetting(const SString& configSetting);
@@ -228,5 +229,6 @@ class CMainConfig : public CXMLConfig
228229
int m_bFakeLagCommandEnabled;
229230
int m_iPlayerTriggeredEventIntervalMs;
230231
int m_iMaxPlayerTriggeredEventsPerInterval;
232+
bool m_elementDataWhitelisted;
231233
int m_checkResourceClientFiles;
232234
};

Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -954,14 +954,19 @@ bool CStaticFunctionDefinitions::SetElementID(CElement* pElement, const char* sz
954954
return true;
955955
}
956956

957-
bool CStaticFunctionDefinitions::SetElementData(CElement* pElement, const char* szName, const CLuaArgument& Variable, ESyncType syncType)
957+
bool CStaticFunctionDefinitions::SetElementData(CElement* pElement, const char* szName, const CLuaArgument& Variable, ESyncType syncType,
958+
std::optional<eCustomDataClientTrust> clientTrust)
958959
{
959960
assert(pElement);
960961
assert(szName);
961962
assert(strlen(szName) <= MAX_CUSTOMDATA_NAME_LENGTH);
962963

963-
ESyncType lastSyncType = ESyncType::BROADCAST;
964-
CLuaArgument* pCurrentVariable = pElement->GetCustomData(szName, false, &lastSyncType);
964+
ESyncType lastSyncType = ESyncType::BROADCAST;
965+
eCustomDataClientTrust lastClientTrust{};
966+
CLuaArgument* pCurrentVariable = pElement->GetCustomData(szName, false, &lastSyncType, &lastClientTrust);
967+
968+
if (clientTrust.has_value() && lastClientTrust != clientTrust.value())
969+
pElement->GetCustomDataManager().SetClientChangesMode(szName, clientTrust.value());
965970

966971
if (!pCurrentVariable || *pCurrentVariable != Variable || lastSyncType != syncType)
967972
{

Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ class CStaticFunctionDefinitions
8383
// Element set funcs
8484
static bool ClearElementVisibleTo(CElement* pElement);
8585
static bool SetElementID(CElement* pElement, const char* szID);
86-
static bool SetElementData(CElement* pElement, const char* szName, const CLuaArgument& Variable, ESyncType syncType);
86+
static bool SetElementData(CElement* pElement, const char* szName, const CLuaArgument& Variable, ESyncType syncType,
87+
std::optional<eCustomDataClientTrust> clientTrust);
8788
static bool RemoveElementData(CElement* pElement, const char* szName);
8889
static bool AddElementDataSubscriber(CElement* pElement, const char* szName, CPlayer* pPlayer);
8990
static bool RemoveElementDataSubscriber(CElement* pElement, const char* szName, CPlayer* pPlayer);

0 commit comments

Comments
 (0)