Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Server/mods/deathmatch/local.conf
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,12 @@
Values: 0 - Off, 1 - Enabled. Default - 1 -->
<resource_client_file_checks>1</resource_client_file_checks>

<!-- Enables extra protection for element data.
When this option is enabled, the server ignores element data sync packets from the client,
except for allowed keys.
Values: 0 - Off, 1 - Enabled. Default - 0 -->
<elementdata_whitelisted>0</elementdata_whitelisted>

<!-- Specifies the module(s) which are loaded with the server. To load several modules, add more <module>
parameter(s). Optional parameter. -->
<!-- <module src="sample_win32.dll"/> -->
Expand Down
9 changes: 8 additions & 1 deletion Server/mods/deathmatch/logic/CCustomData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ void CCustomData::Copy(CCustomData* pCustomData)
}
}

SCustomData* CCustomData::Get(const char* szName)
SCustomData* CCustomData::Get(const char* szName) const
{
assert(szName);

Expand Down Expand Up @@ -100,6 +100,7 @@ void CCustomData::Set(const char* szName, const CLuaArgument& Variable, ESyncTyp
SCustomData newData;
newData.Variable = Variable;
newData.syncType = syncType;
newData.clientChangesMode = eCustomDataClientTrust::UNSET;
m_Data[szName] = newData;
UpdateSynced(szName, Variable, syncType);
}
Expand All @@ -120,6 +121,12 @@ bool CCustomData::Delete(const char* szName)
return false;
}

void CCustomData::SetClientChangesMode(const char* szName, eCustomDataClientTrust mode)
{
SCustomData& pData = m_Data[szName];
pData.clientChangesMode = mode;
}

CXMLNode* CCustomData::OutputToXML(CXMLNode* pNode)
{
std::map<std::string, SCustomData>::const_iterator iter = m_Data.begin();
Expand Down
16 changes: 13 additions & 3 deletions Server/mods/deathmatch/logic/CCustomData.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,33 @@ enum class ESyncType
SUBSCRIBE,
};

enum class eCustomDataClientTrust : std::uint8_t
{
UNSET,
ALLOW,
DENY,
};

struct SCustomData
{
CLuaArgument Variable;
ESyncType syncType;
CLuaArgument Variable;
ESyncType syncType;
eCustomDataClientTrust clientChangesMode;
};

class CCustomData
{
public:
void Copy(CCustomData* pCustomData);

SCustomData* Get(const char* szName);
SCustomData* Get(const char* szName) const;
SCustomData* GetSynced(const char* szName);
void Set(const char* szName, const CLuaArgument& Variable, ESyncType syncType = ESyncType::BROADCAST);

bool Delete(const char* szName);

void SetClientChangesMode(const char* szName, eCustomDataClientTrust mode);

unsigned short CountOnlySynchronized();

CXMLNode* OutputToXML(CXMLNode* pNode);
Expand Down
8 changes: 6 additions & 2 deletions Server/mods/deathmatch/logic/CElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ void CElement::ReadCustomData(CEvents* pEvents, CXMLNode& Node)
}
}

CLuaArgument* CElement::GetCustomData(const char* szName, bool bInheritData, ESyncType* pSyncType)
CLuaArgument* CElement::GetCustomData(const char* szName, bool bInheritData, ESyncType* pSyncType, eCustomDataClientTrust* clientChangesMode)
{
assert(szName);

Expand All @@ -518,13 +518,17 @@ CLuaArgument* CElement::GetCustomData(const char* szName, bool bInheritData, ESy
{
if (pSyncType)
*pSyncType = pData->syncType;

if (clientChangesMode)
*clientChangesMode = pData->clientChangesMode;

return &pData->Variable;
}

// If none, try returning parent's custom data
if (bInheritData && m_pParent)
{
return m_pParent->GetCustomData(szName, true, pSyncType);
return m_pParent->GetCustomData(szName, true, pSyncType, clientChangesMode);
}

// None available
Expand Down
2 changes: 1 addition & 1 deletion Server/mods/deathmatch/logic/CElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ class CElement

void ReadCustomData(CEvents* pEvents, CXMLNode& Node);
CCustomData& GetCustomDataManager() { return m_CustomData; }
CLuaArgument* GetCustomData(const char* szName, bool bInheritData, ESyncType* pSyncType = NULL);
CLuaArgument* GetCustomData(const char* szName, bool bInheritData, ESyncType* pSyncType = nullptr, eCustomDataClientTrust* clientChangesMode = nullptr);
CLuaArguments* GetAllCustomData(CLuaArguments* table);
bool GetCustomDataString(const char* szName, char* pOut, size_t sizeBuffer, bool bInheritData);
bool GetCustomDataInt(const char* szName, int& iOut, bool bInheritData);
Expand Down
20 changes: 19 additions & 1 deletion Server/mods/deathmatch/logic/CGame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1607,6 +1607,7 @@ void CGame::AddBuiltInEvents()
m_Events.AddEvent("onPlayerTriggerEventThreshold", "", nullptr, false);
m_Events.AddEvent("onPlayerTeamChange", "oldTeam, newTeam", nullptr, false);
m_Events.AddEvent("onPlayerTriggerInvalidEvent", "eventName, isAdded, isRemote", nullptr, false);
m_Events.AddEvent("onPlayerChangesProtectedData", "element, key, value", nullptr, false);

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

ESyncType lastSyncType = ESyncType::BROADCAST;
pElement->GetCustomData(szName, false, &lastSyncType);
eCustomDataClientTrust clientChangesMode{};

pElement->GetCustomData(szName, false, &lastSyncType, &clientChangesMode);

const bool changesAllowed = clientChangesMode == eCustomDataClientTrust::UNSET ? !m_pMainConfig->IsElementDataWhitelisted()
: clientChangesMode == eCustomDataClientTrust::ALLOW;
if (!changesAllowed)
{
CLogger::ErrorPrintf("Client trying to change protected element data %s (%s)", Packet.GetSourcePlayer()->GetNick(),
szName);

CLuaArguments arguments;
arguments.PushElement(pElement);
arguments.PushString(szName);
arguments.PushArgument(Value);
pSourcePlayer->CallEvent("onPlayerChangesProtectedData", arguments);
return;
}

if (lastSyncType != ESyncType::LOCAL)
{
Expand Down
3 changes: 3 additions & 0 deletions Server/mods/deathmatch/logic/CMainConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ CMainConfig::CMainConfig(CConsole* pConsole) : CXMLConfig(NULL)
m_iBackupInterval = 3;
m_iBackupAmount = 5;
m_bSyncMapElementData = true;
m_elementDataWhitelisted = false;
}

bool CMainConfig::Load()
Expand Down Expand Up @@ -526,6 +527,8 @@ bool CMainConfig::Load()
g_TickRateSettings.iLightSync = Clamp(200, g_TickRateSettings.iLightSync, 4000);
}

GetBoolean(m_pRootNode, "elementdata_whitelisted", m_elementDataWhitelisted);

ApplyNetOptions();

return true;
Expand Down
2 changes: 2 additions & 0 deletions Server/mods/deathmatch/logic/CMainConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ class CMainConfig : public CXMLConfig
const std::vector<SString>& GetOwnerEmailAddressList() const { return m_OwnerEmailAddressList; }
bool IsDatabaseCredentialsProtectionEnabled() const { return m_bDatabaseCredentialsProtectionEnabled != 0; }
bool IsFakeLagCommandEnabled() const { return m_bFakeLagCommandEnabled != 0; }
bool IsElementDataWhitelisted() const { return m_elementDataWhitelisted; }
bool IsCheckResourceClientFilesEnabled() const noexcept { return m_checkResourceClientFiles != 0; }

SString GetSetting(const SString& configSetting);
Expand Down Expand Up @@ -228,5 +229,6 @@ class CMainConfig : public CXMLConfig
int m_bFakeLagCommandEnabled;
int m_iPlayerTriggeredEventIntervalMs;
int m_iMaxPlayerTriggeredEventsPerInterval;
bool m_elementDataWhitelisted;
int m_checkResourceClientFiles;
};
11 changes: 8 additions & 3 deletions Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -954,14 +954,19 @@ bool CStaticFunctionDefinitions::SetElementID(CElement* pElement, const char* sz
return true;
}

bool CStaticFunctionDefinitions::SetElementData(CElement* pElement, const char* szName, const CLuaArgument& Variable, ESyncType syncType)
bool CStaticFunctionDefinitions::SetElementData(CElement* pElement, const char* szName, const CLuaArgument& Variable, ESyncType syncType,
std::optional<eCustomDataClientTrust> clientTrust)
{
assert(pElement);
assert(szName);
assert(strlen(szName) <= MAX_CUSTOMDATA_NAME_LENGTH);

ESyncType lastSyncType = ESyncType::BROADCAST;
CLuaArgument* pCurrentVariable = pElement->GetCustomData(szName, false, &lastSyncType);
ESyncType lastSyncType = ESyncType::BROADCAST;
eCustomDataClientTrust lastClientTrust{};
CLuaArgument* pCurrentVariable = pElement->GetCustomData(szName, false, &lastSyncType, &lastClientTrust);

if (clientTrust.has_value() && lastClientTrust != clientTrust.value())
pElement->GetCustomDataManager().SetClientChangesMode(szName, clientTrust.value());

if (!pCurrentVariable || *pCurrentVariable != Variable || lastSyncType != syncType)
{
Expand Down
3 changes: 2 additions & 1 deletion Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ class CStaticFunctionDefinitions
// Element set funcs
static bool ClearElementVisibleTo(CElement* pElement);
static bool SetElementID(CElement* pElement, const char* szID);
static bool SetElementData(CElement* pElement, const char* szName, const CLuaArgument& Variable, ESyncType syncType);
static bool SetElementData(CElement* pElement, const char* szName, const CLuaArgument& Variable, ESyncType syncType,
std::optional<eCustomDataClientTrust> clientTrust);
static bool RemoveElementData(CElement* pElement, const char* szName);
static bool AddElementDataSubscriber(CElement* pElement, const char* szName, CPlayer* pPlayer);
static bool RemoveElementDataSubscriber(CElement* pElement, const char* szName, CPlayer* pPlayer);
Expand Down
6 changes: 6 additions & 0 deletions Server/mods/deathmatch/logic/lua/CLuaFunctionParseHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,12 @@ ADD_ENUM(ESyncType::LOCAL, "local")
ADD_ENUM(ESyncType::SUBSCRIBE, "subscribe")
IMPLEMENT_ENUM_CLASS_END("sync-mode")

IMPLEMENT_ENUM_CLASS_BEGIN(eCustomDataClientTrust)
ADD_ENUM(eCustomDataClientTrust::UNSET, "default")
ADD_ENUM(eCustomDataClientTrust::ALLOW, "allow")
ADD_ENUM(eCustomDataClientTrust::DENY, "deny")
IMPLEMENT_ENUM_CLASS_END("client-trust-mode")

//
// CResource from userdata
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ DECLARE_ENUM(CAccessControlListRight::ERightType);
DECLARE_ENUM(CElement::EElementType);
DECLARE_ENUM(CAccountPassword::EAccountPasswordType);
DECLARE_ENUM_CLASS(ESyncType);
DECLARE_ENUM_CLASS(eCustomDataClientTrust)

enum eHudComponent
{
Expand Down
10 changes: 9 additions & 1 deletion Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1538,6 +1538,7 @@ int CLuaElementDefs::setElementData(lua_State* luaVM)
SString strKey;
CLuaArgument value;
ESyncType syncType = ESyncType::BROADCAST;
std::optional<eCustomDataClientTrust> clientTrust{};

CScriptArgReader argStream(luaVM);
argStream.ReadUserData(pElement);
Expand All @@ -1554,6 +1555,13 @@ int CLuaElementDefs::setElementData(lua_State* luaVM)
else
argStream.ReadEnumString(syncType, ESyncType::BROADCAST);

if (!argStream.NextIsNone())
{
eCustomDataClientTrust trustReaded;
argStream.ReadEnumString(trustReaded);
clientTrust = trustReaded;
}

if (!argStream.HasErrors())
{
LogWarningIfPlayerHasNotJoinedYet(luaVM, pElement);
Expand All @@ -1566,7 +1574,7 @@ int CLuaElementDefs::setElementData(lua_State* luaVM)
strKey = strKey.Left(MAX_CUSTOMDATA_NAME_LENGTH);
}

if (CStaticFunctionDefinitions::SetElementData(pElement, strKey, value, syncType))
if (CStaticFunctionDefinitions::SetElementData(pElement, strKey, value, syncType, clientTrust))
{
lua_pushboolean(luaVM, true);
return 1;
Expand Down
6 changes: 6 additions & 0 deletions Server/mods/deathmatch/mtaserver.conf
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,12 @@
Values: 0 - Off, 1 - Enabled. Default - 1 -->
<database_credentials_protection>1</database_credentials_protection>

<!-- Enables extra protection for element data.
When this option is enabled, the server ignores element data sync packets from the client,
except for allowed keys.
Values: 0 - Off, 1 - Enabled. Default - 0 -->
<elementdata_whitelisted>0</elementdata_whitelisted>

<!-- These parameters specify the maximum amount of events that can be triggered by the client (via triggerServerEvent) within the given interval.
Note: The interval is given in milliseconds
Interval range: 50 to 5000. Default: 1000
Expand Down
6 changes: 6 additions & 0 deletions Server/mods/deathmatch/mtaserver.conf.template
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,12 @@
Values: 0 - Off, 1 - Enabled. Default - 1 -->
<database_credentials_protection>1</database_credentials_protection>

<!-- Enables extra protection for element data.
When this option is enabled, the server ignores element data sync packets from the client,
except for allowed keys.
Values: 0 - Off, 1 - Enabled. Default - 0 -->
<elementdata_whitelisted>0</elementdata_whitelisted>

<!-- These parameters specify the maximum amount of events that can be triggered by the client (via triggerServerEvent) within the given interval.
Note: The interval is given in milliseconds
Interval range: 50 to 5000. Default: 1000
Expand Down
Loading