From 0e865c0618d92358fce94530ec1271a0d36cc3e2 Mon Sep 17 00:00:00 2001 From: Asher Baker Date: Thu, 7 Mar 2013 00:58:17 +0000 Subject: [PATCH] Allow access to unvalidated authstrings (bug 5587, r=psychonic). --- core/PlayerManager.cpp | 56 +++++++++++++++++++------------- core/PlayerManager.h | 11 +++---- core/smn_player.cpp | 12 +++++-- plugins/adminmenu/dynamicmenu.sp | 4 +-- plugins/basebans/ban.sp | 3 +- plugins/basevotes/voteban.sp | 1 - plugins/include/clients.inc | 5 ++- public/IPlayerHelpers.h | 5 +-- 8 files changed, 59 insertions(+), 38 deletions(-) diff --git a/core/PlayerManager.cpp b/core/PlayerManager.cpp index 33992fbc..afa488bb 100644 --- a/core/PlayerManager.cpp +++ b/core/PlayerManager.cpp @@ -116,7 +116,7 @@ PlayerManager::PlayerManager() m_SourceTVUserId = -1; m_ReplayUserId = -1; - m_bUseSteamAdminAuth = true; // use steam auth by default + m_bAuthstringValidation = true; // use steam auth by default m_UserIdLookUp = new int[USHRT_MAX+1]; memset(m_UserIdLookUp, 0, sizeof(int) * (USHRT_MAX+1)); @@ -234,9 +234,9 @@ ConfigResult PlayerManager::OnSourceModConfigChanged(const char *key, } else if (strcmp( key, "SteamAuthstringValidation" ) == 0) { if (strcasecmp(value, "yes") == 0) { - m_bUseSteamAdminAuth = true; + m_bAuthstringValidation = true; } else if ( strcasecmp(value, "no") == 0) { - m_bUseSteamAdminAuth = false; + m_bAuthstringValidation = false; } else { UTIL_Format(error, maxlength, "Invalid value: must be \"yes\" or \"no\""); return ConfigResult_Reject; @@ -367,23 +367,18 @@ void PlayerManager::RunAuthChecks() { pPlayer = &m_Players[m_AuthQueue[i]]; authstr = engine->GetPlayerNetworkIDString(pPlayer->m_pEdict); + pPlayer->SetAuthString(authstr); -#if SOURCE_ENGINE >= SE_ORANGEBOX - // we can only easily check if the client is fully authed if we're on a recent engine - if (m_bUseSteamAdminAuth && !g_HL2.IsLANServer()) + if (!pPlayer->IsAuthStringValidated()) { - if (!pPlayer->IsAuthedBySteam()) - { - continue; // we're using steam auth, and steam doesn't know about this player yet so we can't do anything about them for now - } + continue; // we're using steam auth, and steam doesn't know about this player yet so we can't do anything about them for now } -#endif if (authstr && authstr[0] != '\0' && (strcmp(authstr, "STEAM_ID_PENDING") != 0)) { /* Set authorization */ - pPlayer->Authorize(authstr); + pPlayer->Authorize(); /* Mark as removed from queue */ unsigned int client = m_AuthQueue[i]; @@ -558,7 +553,8 @@ void PlayerManager::OnClientPutInServer(edict_t *pEntity, const char *playername /* Run manual connection routines */ char error[255]; const char *authid = engine->GetPlayerNetworkIDString(pEntity); - pPlayer->Authorize(authid); + pPlayer->SetAuthString(authid); + pPlayer->Authorize(); pPlayer->m_bFakeClient = true; /* @@ -1272,11 +1268,12 @@ void PlayerManager::ProcessCommandTarget(cmd_target_info_t *info) { continue; } - if (!pTarget->IsConnected() || !pTarget->IsAuthorized()) + if (!pTarget->IsConnected()) { continue; } - if (strcmp(pTarget->GetAuthString(), new_pattern) == 0) + const char *authstr = pTarget->GetAuthString(false); // We want to make it easy for people to be kicked/banned, so don't require validation for command targets. + if (authstr && strcmp(authstr, new_pattern) == 0) { if ((info->reason = FilterCommandTarget(pAdmin, pTarget, info->flags)) == COMMAND_TARGET_VALID) @@ -1634,17 +1631,22 @@ void CPlayer::Connect() } } -void CPlayer::Authorize(const char *steamid) +void CPlayer::SetAuthString(const char *steamid) { if (m_IsAuthorized) { return; } - m_IsAuthorized = true; m_AuthID.assign(steamid); } +// Ensure a valid AuthString is set before calling. +void CPlayer::Authorize() +{ + m_IsAuthorized = true; +} + void CPlayer::Disconnect() { DumpAdmin(false); @@ -1685,8 +1687,13 @@ const char *CPlayer::GetIPAddress() return m_Ip.c_str(); } -const char *CPlayer::GetAuthString() +const char *CPlayer::GetAuthString(bool validated) { + if (validated && !IsAuthStringValidated()) + { + return NULL; + } + return m_AuthID.c_str(); } @@ -1715,12 +1722,17 @@ bool CPlayer::IsAuthorized() return m_IsAuthorized; } +bool CPlayer::IsAuthStringValidated() +{ #if SOURCE_ENGINE >= SE_ORANGEBOX -bool CPlayer::IsAuthedBySteam() -{ - return engine->IsClientFullyAuthenticated( m_pEdict ); + if (g_Players.m_bAuthstringValidation && !g_HL2.IsLANServer()) + { + return engine->IsClientFullyAuthenticated(m_pEdict); + } +#endif + + return true; } -#endif IPlayerInfo *CPlayer::GetPlayerInfo() { diff --git a/core/PlayerManager.h b/core/PlayerManager.h index 8b2c6669..f5f83362 100644 --- a/core/PlayerManager.h +++ b/core/PlayerManager.h @@ -69,15 +69,12 @@ public: public: const char *GetName(); const char *GetIPAddress(); - const char *GetAuthString(); + const char *GetAuthString(bool validated = true); edict_t *GetEdict(); bool IsInGame(); bool WasCountedAsInGame(); bool IsConnected(); bool IsAuthorized(); -#if SOURCE_ENGINE >= SE_ORANGEBOX - bool IsAuthedBySteam(); -#endif bool IsFakeClient(); bool IsSourceTV() const; bool IsReplay() const; @@ -102,9 +99,11 @@ private: void Disconnect(); void SetName(const char *name); void DumpAdmin(bool deleting); - void Authorize(const char *auth); + void SetAuthString(const char *auth); + void Authorize(); void Authorize_Post(); void DoPostConnectAuthorization(); + bool IsAuthStringValidated(); private: bool m_IsConnected; bool m_IsInGame; @@ -220,7 +219,7 @@ private: unsigned int *m_AuthQueue; String m_PassInfoVar; bool m_QueryLang; - bool m_bUseSteamAdminAuth; // are we validating admins with steam before authorizing? + bool m_bAuthstringValidation; // are we validating admins with steam before authorizing? bool m_bIsListenServer; int m_ListenClient; bool m_bIsSourceTVActive; diff --git a/core/smn_player.cpp b/core/smn_player.cpp index dc304011..257dee7e 100644 --- a/core/smn_player.cpp +++ b/core/smn_player.cpp @@ -156,12 +156,20 @@ static cell_t sm_GetClientAuthStr(IPluginContext *pCtx, const cell_t *params) return pCtx->ThrowNativeError("Client %d is not connected", index); } - if (!pPlayer->IsAuthorized()) + bool validate = true; + if (params[0] > 3) + { + validate = !!params[4]; + } + + const char *authstr = pPlayer->GetAuthString(validate); + + if (!authstr || authstr[0] == '\0') { return 0; } - pCtx->StringToLocal(params[2], static_cast(params[3]), pPlayer->GetAuthString()); + pCtx->StringToLocal(params[2], static_cast(params[3]), authstr); return 1; } diff --git a/plugins/adminmenu/dynamicmenu.sp b/plugins/adminmenu/dynamicmenu.sp index 5ac57402..4deba54a 100644 --- a/plugins/adminmenu/dynamicmenu.sp +++ b/plugins/adminmenu/dynamicmenu.sp @@ -534,8 +534,8 @@ public ParamCheck(client) } case SteamId: { - GetClientAuthString(i, infoBuffer, sizeof(infoBuffer)); - AddMenuItem(itemMenu, infoBuffer, nameBuffer); + if (GetClientAuthString(i, infoBuffer, sizeof(infoBuffer))) + AddMenuItem(itemMenu, infoBuffer, nameBuffer); } case IpAddress: { diff --git a/plugins/basebans/ban.sp b/plugins/basebans/ban.sp index 6624e4ac..cf0566fa 100644 --- a/plugins/basebans/ban.sp +++ b/plugins/basebans/ban.sp @@ -49,8 +49,7 @@ PrepareBan(client, target, time, const String:reason[]) return; } - decl String:authid[64], String:name[32]; - GetClientAuthString(target, authid, sizeof(authid)); + new String:name[32]; GetClientName(target, name, sizeof(name)); if (!time) diff --git a/plugins/basevotes/voteban.sp b/plugins/basevotes/voteban.sp index 80c28a18..73acd0d8 100644 --- a/plugins/basevotes/voteban.sp +++ b/plugins/basevotes/voteban.sp @@ -37,7 +37,6 @@ DisplayVoteBanMenu(client, target) g_voteClient[VOTE_USERID] = GetClientUserId(target); GetClientName(target, g_voteInfo[VOTE_NAME], sizeof(g_voteInfo[])); - GetClientAuthString(target, g_voteInfo[VOTE_AUTHID], sizeof(g_voteInfo[])); GetClientIP(target, g_voteInfo[VOTE_IP], sizeof(g_voteInfo[])); LogAction(client, target, "\"%L\" initiated a ban vote against \"%L\"", client, target); diff --git a/plugins/include/clients.inc b/plugins/include/clients.inc index d4e34eb4..02ad529f 100644 --- a/plugins/include/clients.inc +++ b/plugins/include/clients.inc @@ -261,10 +261,13 @@ native bool:GetClientIP(client, String:ip[], maxlen, bool:remport=true); * @param client Player index. * @param auth Buffer to store the client's auth string. * @param maxlen Maximum length of string buffer (includes NULL terminator). + * @param validate Check backend validation status. + * DO NOT PASS FALSE UNLESS YOU UNDERSTAND THE CONSEQUENCES, + * You WILL KNOW if you need to use this, MOST WILL NOT. * @return True on success, false otherwise. * @error If the client is not connected or the index is invalid. */ -native bool:GetClientAuthString(client, String:auth[], maxlen); +native bool:GetClientAuthString(client, String:auth[], maxlen, bool:validate=true); /** * Retrieves a client's user id, which is an index incremented for every client diff --git a/public/IPlayerHelpers.h b/public/IPlayerHelpers.h index 7c9055f1..deaa6299 100644 --- a/public/IPlayerHelpers.h +++ b/public/IPlayerHelpers.h @@ -41,7 +41,7 @@ #include #define SMINTERFACE_PLAYERMANAGER_NAME "IPlayerManager" -#define SMINTERFACE_PLAYERMANAGER_VERSION 15 +#define SMINTERFACE_PLAYERMANAGER_VERSION 16 struct edict_t; class IPlayerInfo; @@ -76,10 +76,11 @@ namespace SourceMod /** * @brief Returns the player's authentication string. * + * @param validated Check backend validation status. * @return String containing the player's auth string. * May be NULL if unavailable. */ - virtual const char *GetAuthString() =0; + virtual const char *GetAuthString(bool validated = true) =0; /** * @brief Returns the player's edict_t structure.