Skip to content

Commit

Permalink
Merge pull request #486 from alliedmodders/csgo-safety
Browse files Browse the repository at this point in the history
Add initial version of safety checks for CS:GO to attempt to avoid user GSLT bans.
  • Loading branch information
psychonic committed Mar 2, 2016
2 parents 7bd1ed2 + b65de29 commit 19bcc84
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 0 deletions.
13 changes: 13 additions & 0 deletions configs/core.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -132,5 +132,18 @@
* passed. You can disable this feature by setting the value to "0".
*/
"SlowScriptTimeout" "8"

/**
* Per "http://blog.counter-strike.net/index.php/server_guidelines/", certain plugin
* functionality will trigger all of the game server owner's Game Server Login Tokens
* (GSLTs) to get banned when executed on a Counter-Strike: Global Offensive game server.
*
* Enabling this option will block plugins from using functionality that is known to cause this.
* This option only has any effect on CS:GO. Note that this does NOT guarantee that you cannot
* receive a ban.
*
* Disable this option at your own risk.
*/
"FollowCSGOServerGuidelines" "yes"
}

51 changes: 51 additions & 0 deletions core/HalfLife2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,57 @@ void CHalfLife2::OnSourceModAllInitialized_Post()
{
InitLogicalEntData();
InitCommandLine();
#if SOURCE_ENGINE == SE_CSGO
m_CSGOBadList.init();
m_CSGOBadList.add("m_iItemDefinitionIndex");
m_CSGOBadList.add("m_iEntityLevel");
m_CSGOBadList.add("m_iItemIDHigh");
m_CSGOBadList.add("m_iItemIDLow");
m_CSGOBadList.add("m_iAccountID");
m_CSGOBadList.add("m_iEntityQuality");
m_CSGOBadList.add("m_bInitialized");
m_CSGOBadList.add("m_szCustomName");
m_CSGOBadList.add("m_iAttributeDefinitionIndex");
m_CSGOBadList.add("m_iRawValue32");
m_CSGOBadList.add("m_iRawInitialValue32");
m_CSGOBadList.add("m_nRefundableCurrency");
m_CSGOBadList.add("m_bSetBonus");
m_CSGOBadList.add("m_OriginalOwnerXuidLow");
m_CSGOBadList.add("m_OriginalOwnerXuidHigh");
m_CSGOBadList.add("m_nFallbackPaintKit");
m_CSGOBadList.add("m_nFallbackSeed");
m_CSGOBadList.add("m_flFallbackWear");
m_CSGOBadList.add("m_nFallbackStatTrak");
m_CSGOBadList.add("m_iCompetitiveRanking");
m_CSGOBadList.add("m_nActiveCoinRank");
m_CSGOBadList.add("m_nMusicID");
#endif
}

ConfigResult CHalfLife2::OnSourceModConfigChanged(const char *key, const char *value,
ConfigSource source, char *error, size_t maxlength)
{
if (strcasecmp(key, "FollowCSGOServerGuidelines") == 0)
{
#if SOURCE_ENGINE == SE_CSGO
if (strcasecmp(value, "no") == 0)
{
m_bFollowCSGOServerGuidelines = false;
return ConfigResult_Accept;
}
else if (strcasecmp(value, "yes") == 0)
{
m_bFollowCSGOServerGuidelines = true;
return ConfigResult_Accept;
}

return ConfigResult_Reject;
#else
return ConfigResult_Accept;
#endif
}

return ConfigResult_Ignore;
}

void CHalfLife2::InitLogicalEntData()
Expand Down
13 changes: 13 additions & 0 deletions core/HalfLife2.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <sh_string.h>
#include <sh_tinyhash.h>
#include <am-utility.h>
#include <am-hashset.h>
#include <am-hashmap.h>
#include <sm_stringhashmap.h>
#include <sm_namehashset.h>
Expand Down Expand Up @@ -152,6 +153,8 @@ class CHalfLife2 :
void OnSourceModAllInitialized();
void OnSourceModAllInitialized_Post();
/*void OnSourceModAllShutdown();*/
ConfigResult OnSourceModConfigChanged(const char *key, const char *value,
ConfigSource source, char *error, size_t maxlength) override;
public: //IGameHelpers
SendProp *FindInSendTable(const char *classname, const char *offset);
bool FindSendPropInfo(const char *classname, const char *offset, sm_sendprop_info_t *info);
Expand Down Expand Up @@ -220,6 +223,16 @@ class CHalfLife2 :
CStack<CachedCommandInfo> m_CommandStack;
Queue<DelayedKickInfo> m_DelayedKicks;
void *m_pGetCommandLine;
#if SOURCE_ENGINE == SE_CSGO
public:
bool CanSetCSGOEntProp(const char *pszPropName)
{
return !m_bFollowCSGOServerGuidelines || !m_CSGOBadList.has(pszPropName);
}
private:
ke::HashSet<ke::AString, detail::StringHashMapPolicy> m_CSGOBadList;
bool m_bFollowCSGOServerGuidelines = true;
#endif
};

extern CHalfLife2 g_HL2;
Expand Down
22 changes: 22 additions & 0 deletions core/smn_entities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,15 @@ enum PropFieldType
PropField_String_T, /**< Valid for Data fields. Read only! */
};

inline bool CanSetPropName(const char *pszPropName)
{
#if SOURCE_ENGINE == SE_CSGO
return g_HL2.CanSetCSGOEntProp(pszPropName);
#else
return true;
#endif
}

inline edict_t *BaseEntityToEdict(CBaseEntity *pEntity)
{
IServerUnknown *pUnk = (IServerUnknown *)pEntity;
Expand Down Expand Up @@ -1351,6 +1360,10 @@ static cell_t SetEntProp(IPluginContext *pContext, const cell_t *params)
case Prop_Send:
{
FIND_PROP_SEND(DPT_Int, "integer");
if (!CanSetPropName(prop))
{
return pContext->ThrowNativeError("Cannot set %s with \"FollowCSGOServerGuidelines\" option enabled.", prop);
}

// This isn't in CS:S yet, but will be, doesn't hurt to add now, and will save us a build later
#if SOURCE_ENGINE == SE_CSS || SOURCE_ENGINE == SE_HL2DM || SOURCE_ENGINE == SE_DODS \
Expand Down Expand Up @@ -1503,6 +1516,10 @@ static cell_t SetEntPropFloat(IPluginContext *pContext, const cell_t *params)
case Prop_Send:
{
FIND_PROP_SEND(DPT_Float, "float");
if (!CanSetPropName(prop))
{
return pContext->ThrowNativeError("Cannot set %s with \"FollowCSGOServerGuidelines\" option enabled.", prop);
}
break;
}
default:
Expand Down Expand Up @@ -2088,6 +2105,11 @@ static cell_t SetEntPropString(IPluginContext *pContext, const cell_t *params)
}
}

if (!CanSetPropName(prop))
{
return pContext->ThrowNativeError("Cannot set %s with \"FollowCSGOServerGuidelines\" option enabled.", prop);
}

if (bIsStringIndex)
{
offset += (element * (td->fieldSizeInBytes / td->fieldSize));
Expand Down
9 changes: 9 additions & 0 deletions extensions/sdktools/extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,15 @@ bool SDKTools::SDK_OnLoad(char *error, size_t maxlength, bool late)

InitSDKToolsAPI();

#if SOURCE_ENGINE == SE_CSGO
m_bFollowCSGOServerGuidelines = true;
const char *pszValue = g_pSM->GetCoreConfigValue("FollowCSGOServerGuidelines");
if (pszValue && strcasecmp(pszValue, "no") == 0)
{
m_bFollowCSGOServerGuidelines = false;
}
#endif

return true;
}

Expand Down
2 changes: 2 additions & 0 deletions extensions/sdktools/extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,10 @@ class SDKTools :
void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax);
public:
bool HasAnyLevelInited() { return m_bAnyLevelInited; }
bool ShouldFollowCSGOServerGuidelines() const { return m_bFollowCSGOServerGuidelines; }

private:
bool m_bFollowCSGOServerGuidelines = false;
bool m_bAnyLevelInited = false;
};

Expand Down
14 changes: 14 additions & 0 deletions extensions/sdktools/vnatives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,20 @@ static cell_t RemovePlayerItem(IPluginContext *pContext, const cell_t *params)
class CEconItemView;
static cell_t GiveNamedItem(IPluginContext *pContext, const cell_t *params)
{
if (g_SdkTools.ShouldFollowCSGOServerGuidelines())
{
char *pWeaponName;
pContext->LocalToString(params[2], &pWeaponName);

// Don't allow knives other than weapon_knife, weapon_knifegg, and wewapon_knife_t.
// Others follow pattern weapon_knife_*
size_t len = strlen(pWeaponName);
if (len >= 14 && strnicmp(pWeaponName, "weapon_knife_", 13) == 0 && !(pWeaponName[13] == 't' && pWeaponName[14] == '\0'))
{
return pContext->ThrowNativeError("Blocked giving of %s due to core.cfg option FollowCSGOServerGuidelines", pWeaponName);
}
}

static ValveCall *pCall = NULL;
if (!pCall)
{
Expand Down

0 comments on commit 19bcc84

Please sign in to comment.