From b6dee3a3a8a6383ce66970e1b5ff6b1aaea517fd Mon Sep 17 00:00:00 2001 From: Peace-Maker Date: Thu, 3 Mar 2016 07:17:40 +0100 Subject: [PATCH] Add tv_force_steamauth convar Enable Steam authentication for SourceTV clients. Thanks to @GoD-Tony for his snippet! --- extension.cpp | 15 +++++++++++- extension.h | 8 ++++++- forwards.cpp | 49 +++++++++++++++++++++++++++++---------- forwards.h | 12 +++++++++- sourcetvmanager.games.txt | 12 ++++++++++ 5 files changed, 81 insertions(+), 15 deletions(-) diff --git a/extension.cpp b/extension.cpp index 90bdbfa..9a7dc4f 100644 --- a/extension.cpp +++ b/extension.cpp @@ -40,7 +40,8 @@ void *old_host_client = nullptr; bool g_HostClientOverridden = false; IGameEventManager2 *gameevents = nullptr; -CGlobalVars *gpGlobals; +CGlobalVars *gpGlobals = nullptr; +ICvar *icvar = nullptr; IBinTools *bintools = nullptr; ISDKTools *sdktools = nullptr; @@ -80,6 +81,8 @@ SMEXT_LINK(&g_STVManager); extern const sp_nativeinfo_t sourcetv_natives[]; +ConVar tv_force_steamauth("tv_force_steamauth", "1", FCVAR_NONE, "Validate SourceTV clients with Steam."); + bool SourceTVManager::SDK_OnLoad(char *error, size_t maxlength, bool late) { sharesys->AddDependency(myself, "bintools.ext", true, true); @@ -176,12 +179,22 @@ bool SourceTVManager::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxle { GET_V_IFACE_CURRENT(GetServerFactory, hltvdirector, IHLTVDirector, INTERFACEVERSION_HLTVDIRECTOR); GET_V_IFACE_CURRENT(GetEngineFactory, gameevents, IGameEventManager2, INTERFACEVERSION_GAMEEVENTSMANAGER2); + GET_V_IFACE_CURRENT(GetEngineFactory, icvar, ICvar, CVAR_INTERFACE_VERSION); gpGlobals = ismm->GetCGlobals(); + g_pCVar = icvar; + ConVar_Register(0, this); + return true; } +bool SourceTVManager::RegisterConCommandBase(ConCommandBase *pCommandBase) +{ + /* Always call META_REGCVAR instead of going through the engine. */ + return META_REGCVAR(pCommandBase); +} + void SourceTVManager::SDK_OnUnload() { #if SOURCE_ENGINE == SE_CSGO diff --git a/extension.h b/extension.h index 87db172..5b38903 100644 --- a/extension.h +++ b/extension.h @@ -52,11 +52,13 @@ class INetMessage; +extern ConVar tv_force_steamauth; + /** * @brief Sample implementation of the SDK Extension. * Note: Uncomment one of the pre-defined virtual functions in order to use it. */ -class SourceTVManager : public SDKExtension +class SourceTVManager : public SDKExtension, public IConCommandBaseAccessor { public: /** @@ -127,6 +129,9 @@ public: //virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength); #endif +public: // IConCommandBaseAccessor + bool RegisterConCommandBase(ConCommandBase *pCommandBase); + public: void SelectSourceTVServer(IHLTVServer *hltv); IDemoRecorder *GetDemoRecorderPtr(IHLTVServer *hltvserver); @@ -158,6 +163,7 @@ extern IGameConfig *g_pGameConf; extern IServer *iserver; extern CGlobalVars *gpGlobals; extern IGameEventManager2 *gameevents; +extern ICvar *icvar; extern IHLTVDirector *hltvdirector; extern IHLTVServer *hltvserver; diff --git a/forwards.cpp b/forwards.cpp index e6ce0e4..5571fd9 100644 --- a/forwards.cpp +++ b/forwards.cpp @@ -42,13 +42,15 @@ SH_DECL_HOOK0_void(IDemoRecorder, StopRecording, SH_NOATTRIB, 0) #endif #if SOURCE_ENGINE == SE_CSGO -SH_DECL_MANUALHOOK13(CHLTVServer_ConnectClient, 0, 0, 0, IClient *, netadr_s &, int, int, int, const char *, const char *, const char *, int, CUtlVector &, bool, CrossPlayPlatform_t, const unsigned char *, int); +SH_DECL_MANUALHOOK13(CHLTVServer_ConnectClient, 0, 0, 0, IClient *, const netadr_t &, int, int, int, const char *, const char *, const char *, int, CUtlVector &, bool, CrossPlayPlatform_t, const unsigned char *, int); SH_DECL_HOOK1_void(IClient, Disconnect, SH_NOATTRIB, 0, const char *); #else SH_DECL_MANUALHOOK9(CHLTVServer_ConnectClient, 0, 0, 0, IClient *, netadr_t &, int, int, int, int, const char *, const char *, const char *, int); SH_DECL_HOOK0_void_vafmt(IClient, Disconnect, SH_NOATTRIB, 0); #endif +SH_DECL_MANUALHOOK1(CHLTVServer_GetChallengeType, 0, 0, 0, int, const netadr_t &); + void CForwardManager::Init() { int offset = -1; @@ -61,6 +63,17 @@ void CForwardManager::Init() SH_MANUALHOOK_RECONFIGURE(CHLTVServer_ConnectClient, offset, 0, 0); m_bHasClientConnectOffset = true; } + + if (!g_pGameConf->GetOffset("CHLTVServer::GetChallengeType", &offset) || offset == -1) + { + smutils->LogError(myself, "Failed to get CHLTVServer::GetChallengeType offset."); + } + else + { + SH_MANUALHOOK_RECONFIGURE(CHLTVServer_GetChallengeType, offset, 0, 0); + m_bHasGetChallengeTypeOffset = true; + } + m_StartRecordingFwd = forwards->CreateForward("SourceTV_OnStartRecording", ET_Ignore, 2, NULL, Param_Cell, Param_String); m_StopRecordingFwd = forwards->CreateForward("SourceTV_OnStopRecording", ET_Ignore, 3, NULL, Param_Cell, Param_String, Param_Cell); m_SpectatorPreConnectFwd = forwards->CreateForward("SourceTV_OnSpectatorPreConnect", ET_LowEvent, 4, NULL, Param_String, Param_String, Param_String, Param_String); @@ -93,10 +106,11 @@ void CForwardManager::UnhookRecorder(IDemoRecorder *recorder) void CForwardManager::HookServer(IServer *server) { - if (!m_bHasClientConnectOffset) - return; - - SH_ADD_MANUALHOOK(CHLTVServer_ConnectClient, server, SH_MEMBER(this, &CForwardManager::OnSpectatorConnect), false); + if (m_bHasClientConnectOffset) + SH_ADD_MANUALHOOK(CHLTVServer_ConnectClient, server, SH_MEMBER(this, &CForwardManager::OnSpectatorConnect), false); + + if (m_bHasGetChallengeTypeOffset) + SH_ADD_MANUALHOOK(CHLTVServer_GetChallengeType, server, SH_MEMBER(this, &CForwardManager::OnGetChallengeType), false); // Hook all already connected clients as well for late loading for (int i = 0; i < server->GetClientCount(); i++) @@ -114,10 +128,11 @@ void CForwardManager::HookServer(IServer *server) void CForwardManager::UnhookServer(IServer *server) { - if (!m_bHasClientConnectOffset) - return; + if (m_bHasClientConnectOffset) + SH_REMOVE_MANUALHOOK(CHLTVServer_ConnectClient, server, SH_MEMBER(this, &CForwardManager::OnSpectatorConnect), false); - SH_REMOVE_MANUALHOOK(CHLTVServer_ConnectClient, server, SH_MEMBER(this, &CForwardManager::OnSpectatorConnect), false); + if (m_bHasGetChallengeTypeOffset) + SH_REMOVE_MANUALHOOK(CHLTVServer_GetChallengeType, server, SH_MEMBER(this, &CForwardManager::OnGetChallengeType), false); // Unhook all connected clients as well. for (int i = 0; i < server->GetClientCount(); i++) @@ -140,7 +155,7 @@ void CForwardManager::UnhookClient(IClient *client) #if SOURCE_ENGINE == SE_CSGO // CBaseServer::RejectConnection(ns_address const&, char const*, ...) -static void RejectConnection(IServer *server, netadr_t &address, char *pchReason) +static void RejectConnection(IServer *server, const netadr_t &address, const char *pchReason) { static ICallWrapper *pRejectConnection = nullptr; @@ -186,7 +201,7 @@ static void RejectConnection(IServer *server, netadr_t &address, char *pchReason vptr += sizeof(void *); *(char **)vptr = fmt; vptr += sizeof(char *); - *(char **)vptr = pchReason; + *(const char **)vptr = pchReason; pRejectConnection->Execute(vstk, NULL); } @@ -267,12 +282,12 @@ static void RejectConnection(IServer *server, netadr_t &address, int iClientChal char passwordBuffer[255]; #if SOURCE_ENGINE == SE_CSGO // CHLTVServer::ConnectClient(ns_address const&, int, int, int, char const*, char const*, char const*, int, CUtlVector *, CUtlMemory *, int>> &, bool, CrossPlayPlatform_t, unsigned char const*, int) -IClient *CForwardManager::OnSpectatorConnect(netadr_s & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector &pSplitPlayerConnectVector, bool bUnknown, CrossPlayPlatform_t platform, const unsigned char *pUnknown, int iUnknown) +IClient *CForwardManager::OnSpectatorConnect(const netadr_t & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector &pSplitPlayerConnectVector, bool bUnknown, CrossPlayPlatform_t platform, const unsigned char *pUnknown, int iUnknown) #else IClient *CForwardManager::OnSpectatorConnect(netadr_t & address, int nProtocol, int iChallenge, int iClientChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie) #endif { - if (!pCookie || cbCookie < sizeof(uint64)) + if (!pCookie || (size_t)cbCookie < sizeof(uint64)) RETURN_META_VALUE(MRES_IGNORED, nullptr); #if SOURCE_ENGINE == SE_CSGO @@ -332,6 +347,16 @@ IClient *CForwardManager::OnSpectatorConnect(netadr_t & address, int nProtocol, RETURN_META_VALUE(MRES_SUPERCEDE, client); } +// Force steam authentication +// Thanks GoD-Tony :) +int CForwardManager::OnGetChallengeType(const netadr_t &address) +{ + if (!tv_force_steamauth.GetBool()) + RETURN_META_VALUE(MRES_IGNORED, k_EAuthProtocolHashedCDKey); + + RETURN_META_VALUE(MRES_SUPERCEDE, k_EAuthProtocolSteam); +} + void CForwardManager::OnSpectatorDisconnect(const char *reason) { IClient *client = META_IFACEPTR(IClient); diff --git a/forwards.h b/forwards.h index 6eb51dc..3c3d516 100644 --- a/forwards.h +++ b/forwards.h @@ -49,6 +49,13 @@ typedef CNetMessagePB<16, CCLCMsg_SplitPlayerConnect, 0, true> NetMsg_SplitPlaye #endif +typedef enum EAuthProtocol +{ + k_EAuthProtocolWONCertificate = 1, + k_EAuthProtocolHashedCDKey = 2, + k_EAuthProtocolSteam = 3 +} EAuthProtocol; + class CGameInfo; class CForwardManager @@ -71,13 +78,15 @@ private: void OnStartRecording_Post(const char *filename, bool bContinuously); #if SOURCE_ENGINE == SE_CSGO void OnStopRecording_Post(CGameInfo const *info); - IClient *OnSpectatorConnect(netadr_s & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector &pSplitPlayerConnectVector, bool bUnknown, CrossPlayPlatform_t platform, const unsigned char *pUnknown, int iUnknown); + IClient *OnSpectatorConnect(const netadr_t & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector &pSplitPlayerConnectVector, bool bUnknown, CrossPlayPlatform_t platform, const unsigned char *pUnknown, int iUnknown); #else void OnStopRecording_Post(); IClient *OnSpectatorConnect(netadr_t &address, int nProtocol, int iChallenge, int iClientChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie); #endif void OnSpectatorDisconnect(const char *reason); + int OnGetChallengeType(const netadr_t &address); + private: IForward *m_StartRecordingFwd; IForward *m_StopRecordingFwd; @@ -87,6 +96,7 @@ private: IForward *m_SpectatorDisconnectedFwd; bool m_bHasClientConnectOffset = false; + bool m_bHasGetChallengeTypeOffset = false; }; extern CForwardManager g_pSTVForwards; diff --git a/sourcetvmanager.games.txt b/sourcetvmanager.games.txt index 9e58ae8..071f7e6 100644 --- a/sourcetvmanager.games.txt +++ b/sourcetvmanager.games.txt @@ -37,6 +37,12 @@ "linux" "53" } + "CHLTVServer::GetChallengeType" + { + "windows" "59" + "linux" "60" + } + "CHLTVServer::m_DemoRecorder" { "windows" "19600" @@ -129,6 +135,12 @@ "linux" "48" } + "CHLTVServer::GetChallengeType" + { + "windows" "54" + "linux" "55" + } + "CHLTVServer::m_DemoRecorder" { "windows" "19192"