From 8c89b72fbc8b31c0794562683df69ea72c3cadc2 Mon Sep 17 00:00:00 2001 From: Nicholas Hastings Date: Tue, 2 Sep 2014 14:40:39 -0700 Subject: [PATCH] Expose explicit client auth string formats --- core/PlayerManager.cpp | 38 +++++--- core/PlayerManager.h | 6 +- core/logic/smn_players.cpp | 117 ++++++++++++++++++++++-- gamedata/core.games/engine.bgt.txt | 5 + gamedata/core.games/engine.css.txt | 5 + gamedata/core.games/engine.darkm.txt | 5 + gamedata/core.games/engine.ep1.txt | 5 + gamedata/core.games/engine.ep2.txt | 8 ++ gamedata/core.games/engine.ep2valve.txt | 5 + gamedata/core.games/engine.eye.txt | 5 + gamedata/core.games/engine.sdk2013.txt | 8 ++ plugins/include/clients.inc | 16 +++- public/IPlayerHelpers.h | 11 ++- 13 files changed, 210 insertions(+), 24 deletions(-) diff --git a/core/PlayerManager.cpp b/core/PlayerManager.cpp index 587db7e5..4bdecd8a 100644 --- a/core/PlayerManager.cpp +++ b/core/PlayerManager.cpp @@ -1914,7 +1914,7 @@ CPlayer::CPlayer() m_bIsSourceTV = false; m_bIsReplay = false; m_Serial.value = -1; - m_SteamAccountID = 0; + m_SteamID = k_steamIDNil; #if SOURCE_ENGINE == SE_CSGO m_LanguageCookie = InvalidQueryCvarCookie; #endif @@ -1997,7 +1997,7 @@ void CPlayer::Disconnect() m_bIsSourceTV = false; m_bIsReplay = false; m_Serial.value = -1; - m_SteamAccountID = 0; + m_SteamID = k_steamIDNil; #if SOURCE_ENGINE == SE_CSGO m_LanguageCookie = InvalidQueryCvarCookie; #endif @@ -2033,16 +2033,17 @@ const char *CPlayer::GetAuthString(bool validated) return m_AuthID.c_str(); } -unsigned int CPlayer::GetSteamAccountID(bool validated) +const CSteamID &CPlayer::GetSteamID(bool validated) { if (IsFakeClient() || (validated && !IsAuthStringValidated())) { - return 0; + static const CSteamID invalidId = k_steamIDNil; + return invalidId; } - if (m_SteamAccountID != 0) + if (m_SteamID.IsValid()) { - return m_SteamAccountID; + return m_SteamID; } #if SOURCE_ENGINE < SE_ORANGEBOX @@ -2050,22 +2051,35 @@ unsigned int CPlayer::GetSteamAccountID(bool validated) /* STEAM_0:1:123123 | STEAM_ID_LAN | STEAM_ID_PENDING */ if (pAuth && (strlen(pAuth) > 10) && pAuth[8] != '_') { - m_SteamAccountID = (atoi(&pAuth[8]) | (atoi(&pAuth[10]) << 1)); + m_SteamID = CSteamID(atoi(&pAuth[8]) | (atoi(&pAuth[10]) << 1), + k_unSteamUserDesktopInstance, k_EUniversePublic, k_EAccountTypeIndividual); } #else - unsigned long long *steamId; + const CSteamID *steamId; #if SOURCE_ENGINE == SE_DOTA - steamId = (unsigned long long *)engine->GetClientSteamID(m_iIndex); + steamId = engine->GetClientSteamID(m_iIndex); #else - steamId = (unsigned long long *)engine->GetClientSteamID(m_pEdict); + steamId = engine->GetClientSteamID(m_pEdict); #endif if (steamId) { - m_SteamAccountID = (*steamId & 0xFFFFFFFF); + m_SteamID = (*steamId); } #endif - return m_SteamAccountID; + return m_SteamID; +} + +unsigned int CPlayer::GetSteamAccountID(bool validated) +{ + if (!IsFakeClient() && (!validated || IsAuthStringValidated())) + { + const CSteamID &id = GetSteamID(); + if (id.IsValid()) + return id.GetAccountID(); + } + + return 0; } edict_t *CPlayer::GetEdict() diff --git a/core/PlayerManager.h b/core/PlayerManager.h index 9bb58f0b..ad98090c 100644 --- a/core/PlayerManager.h +++ b/core/PlayerManager.h @@ -43,6 +43,8 @@ #include #include "ConVarManager.h" +#include + using namespace SourceHook; #define PLAYER_LIFE_UNKNOWN 0 @@ -71,6 +73,8 @@ public: const char *GetIPAddress(); const char *GetAuthString(bool validated = true); unsigned int GetSteamAccountID(bool validated = true); + const CSteamID &GetSteamID(bool validated = true); + uint64_t GetSteamID64(bool validated = true) { return GetSteamID(validated).ConvertToUint64(); } edict_t *GetEdict(); bool IsInGame(); bool WasCountedAsInGame(); @@ -130,7 +134,7 @@ private: bool m_bIsSourceTV; bool m_bIsReplay; serial_t m_Serial; - unsigned int m_SteamAccountID; + CSteamID m_SteamID; #if SOURCE_ENGINE == SE_CSGO QueryCvarCookie_t m_LanguageCookie; #endif diff --git a/core/logic/smn_players.cpp b/core/logic/smn_players.cpp index 47288f0a..7b27c0a1 100644 --- a/core/logic/smn_players.cpp +++ b/core/logic/smn_players.cpp @@ -37,12 +37,21 @@ #include #include #include +#include "GameConfigs.h" #include "CellArray.h" #include "AutoHandleRooter.h" using namespace SourceHook; using namespace SourceMod; +#ifndef PRIu64 +#ifdef _WIN32 +#define PRIu64 "I64u" +#else +#define PRIu64 "llu" +#endif +#endif + static const int kActivityNone = 0; static const int kActivityNonAdmins = 1; // Show admin activity to non-admins anonymously. static const int kActivityNonAdminsNames = 2; // If 1 is specified, admin names will be shown. @@ -322,6 +331,15 @@ static cell_t sm_GetClientIP(IPluginContext *pCtx, const cell_t *params) return 1; } +// Must match clients.inc +enum class AuthStringType +{ + Engine, + Steam2, + Steam3, + SteamID64, +}; + static cell_t sm_GetClientAuthStr(IPluginContext *pCtx, const cell_t *params) { int index = params[1]; @@ -337,19 +355,100 @@ static cell_t sm_GetClientAuthStr(IPluginContext *pCtx, const cell_t *params) } bool validate = true; - if (params[0] > 3) + if (params[0] >= 4) { validate = !!params[4]; - } - - const char *authstr = pPlayer->GetAuthString(validate); - - if (!authstr || authstr[0] == '\0') - { - return 0; } + + AuthStringType authType = AuthStringType::Engine; + if (params[0] >= 5) + { + authType = (AuthStringType)params[5]; + } - pCtx->StringToLocal(params[2], static_cast(params[3]), authstr); + switch (authType) + { + case AuthStringType::Engine: + { + const char *authstr = pPlayer->GetAuthString(validate); + if (!authstr || authstr[0] == '\0') + { + return 0; + } + + pCtx->StringToLocal(params[2], static_cast(params[3]), authstr); + } + break; + case AuthStringType::Steam2: + case AuthStringType::Steam3: + { + if (pPlayer->IsFakeClient()) + { + pCtx->StringToLocal(params[2], static_cast(params[3]), "BOT"); + return 1; + } + + uint64_t steamId = pPlayer->GetSteamID64(validate); + if (steamId == 0) + { + if (gamehelpers->IsLANServer()) + { + pCtx->StringToLocal(params[2], static_cast(params[3]), "STEAM_ID_LAN"); + } + else + { + pCtx->StringToLocal(params[2], static_cast(params[3]), "STEAM_ID_PENDING"); + } + + return 1; + } + + char szAuth[64]; + unsigned int universe = steamId >> 56; + unsigned int accountId = steamId & 0xFFFFFFFF; + unsigned int instance = (steamId >> 32) & 0x000FFFFF; + if (authType == AuthStringType::Steam2) + { + if (atoi(g_pGameConf->GetKeyValue("UseInvalidUniverseInSteam2IDs")) == 1) + { + universe = 0; + } + + snprintf(szAuth, sizeof(szAuth), "STEAM_%u:%u:%u", universe, accountId % 2, accountId >> 1); + } + else if (instance != 1) + { + snprintf(szAuth, sizeof(szAuth), "[U:%u:%u:%u]", universe, accountId, instance); + } + else + { + snprintf(szAuth, sizeof(szAuth), "[U:%u:%u]", universe, accountId); + } + + pCtx->StringToLocal(params[2], static_cast(params[3]), szAuth); + } + break; + + case AuthStringType::SteamID64: + { + if (pPlayer->IsFakeClient() || gamehelpers->IsLANServer()) + { + return 0; + } + + uint64_t steamId = pPlayer->GetSteamID64(validate); + if (steamId == 0) + { + return 0; + } + + char szAuth[64]; + snprintf(szAuth, sizeof(szAuth), "%" PRIu64, steamId); + + pCtx->StringToLocal(params[2], static_cast(params[3]), szAuth); + } + break; + } return 1; } diff --git a/gamedata/core.games/engine.bgt.txt b/gamedata/core.games/engine.bgt.txt index 674993e8..c4502dbb 100644 --- a/gamedata/core.games/engine.bgt.txt +++ b/gamedata/core.games/engine.bgt.txt @@ -36,5 +36,10 @@ "windows" "\xE8\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\xB9\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x6A" } } + + "Keys" + { + "UseInvalidUniverseInSteam2IDs" "1" + } } } diff --git a/gamedata/core.games/engine.css.txt b/gamedata/core.games/engine.css.txt index cf08b2b0..2ec1cc75 100644 --- a/gamedata/core.games/engine.css.txt +++ b/gamedata/core.games/engine.css.txt @@ -53,5 +53,10 @@ "mac" "@gEntList" } } + + "Keys" + { + "UseInvalidUniverseInSteam2IDs" "1" + } } } diff --git a/gamedata/core.games/engine.darkm.txt b/gamedata/core.games/engine.darkm.txt index d84d54b3..f458d257 100644 --- a/gamedata/core.games/engine.darkm.txt +++ b/gamedata/core.games/engine.darkm.txt @@ -42,5 +42,10 @@ "windows" "\xE8\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\xB9\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\xE8" } } + + "Keys" + { + "UseInvalidUniverseInSteam2IDs" "1" + } } } diff --git a/gamedata/core.games/engine.ep1.txt b/gamedata/core.games/engine.ep1.txt index de669556..932f92ca 100644 --- a/gamedata/core.games/engine.ep1.txt +++ b/gamedata/core.games/engine.ep1.txt @@ -106,6 +106,11 @@ "windows" "\x56\x8B\x74\x24\x08\x57\x56\x8B\xF9\xE8\x2A\x2A\x2A\x2A\x84\xC0\x0F\x85\xC4\x00\x00\x00\x56\x8D" } } + + "Keys" + { + "UseInvalidUniverseInSteam2IDs" "1" + } } } diff --git a/gamedata/core.games/engine.ep2.txt b/gamedata/core.games/engine.ep2.txt index ba0a3460..d1a4f5bd 100644 --- a/gamedata/core.games/engine.ep2.txt +++ b/gamedata/core.games/engine.ep2.txt @@ -58,4 +58,12 @@ } } } + + "#default" + { + "Keys" + { + "UseInvalidUniverseInSteam2IDs" "1" + } + } } diff --git a/gamedata/core.games/engine.ep2valve.txt b/gamedata/core.games/engine.ep2valve.txt index 55eef306..0dc63e82 100644 --- a/gamedata/core.games/engine.ep2valve.txt +++ b/gamedata/core.games/engine.ep2valve.txt @@ -52,5 +52,10 @@ "mac" "@gEntList" } } + + "Keys" + { + "UseInvalidUniverseInSteam2IDs" "1" + } } } diff --git a/gamedata/core.games/engine.eye.txt b/gamedata/core.games/engine.eye.txt index f99e691d..045f65aa 100644 --- a/gamedata/core.games/engine.eye.txt +++ b/gamedata/core.games/engine.eye.txt @@ -41,5 +41,10 @@ "windows" "\xE8\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\xB9\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\xE8" } } + + "Keys" + { + "UseInvalidUniverseInSteam2IDs" "1" + } } } diff --git a/gamedata/core.games/engine.sdk2013.txt b/gamedata/core.games/engine.sdk2013.txt index 498fb367..4912944c 100644 --- a/gamedata/core.games/engine.sdk2013.txt +++ b/gamedata/core.games/engine.sdk2013.txt @@ -95,4 +95,12 @@ } } } + + "#default" + { + "Keys" + { + "UseInvalidUniverseInSteam2IDs" "1" + } + } } diff --git a/plugins/include/clients.inc b/plugins/include/clients.inc index 174ca0ad..913d26a3 100644 --- a/plugins/include/clients.inc +++ b/plugins/include/clients.inc @@ -45,6 +45,19 @@ enum NetFlow NetFlow_Both, /**< Both values added together */ }; +/** + * Auth string types. + */ +enum AuthStringType +{ + AuthString_Engine, /**< The game-specific auth string as returned from the engine */ + + // The following are only available on games that support Steam authentication. + AuthString_Steam2, /**< Steam2 rendered format, ex "STEAM_1:1:4153990" */ + AuthString_Steam3, /**< Steam3 rendered format, ex "[U:1:8307981]" */ + AuthString_SteamID64, /**< A SteamID64 (uint64) as a String, ex "76561197968573709" */ +}; + /** * MAXPLAYERS is not the same as MaxClients. * MAXPLAYERS is a hardcoded value as an upper limit. MaxClients changes based on the server. @@ -264,10 +277,11 @@ native bool:GetClientIP(client, String:ip[], maxlen, bool:remport=true); * @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. + * @param authType Auth string type and format to use. * @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, bool:validate=true); +native bool:GetClientAuthString(client, String:auth[], maxlen, bool:validate=true, AuthStringType:authType=AuthString_Engine); /** * Returns the client's Steam account ID. diff --git a/public/IPlayerHelpers.h b/public/IPlayerHelpers.h index 8b1d9cd2..72e007e4 100644 --- a/public/IPlayerHelpers.h +++ b/public/IPlayerHelpers.h @@ -41,7 +41,7 @@ #include #define SMINTERFACE_PLAYERMANAGER_NAME "IPlayerManager" -#define SMINTERFACE_PLAYERMANAGER_VERSION 20 +#define SMINTERFACE_PLAYERMANAGER_VERSION 21 struct edict_t; class IPlayerInfo; @@ -267,6 +267,15 @@ namespace SourceMod * @brief Removes admin access from the client. */ virtual void ClearAdmin() =0; + + /** + * @brief Returns the client's Steam ID as a uint64. + * + * @param validated Check backend validation status. + * + * @return Steam ID or 0 if not available. + */ + virtual uint64_t GetSteamID64(bool validated = true) =0; }; /**