From 0aab8e0bd6493812fbed3cf7eb22793cec97b565 Mon Sep 17 00:00:00 2001 From: jenz Date: Fri, 5 Jun 2026 23:54:25 +0100 Subject: [PATCH] adding support for switching steamID for the nosteam webclients --- connect2.games.txt | 6 +++ extension/extension.cpp | 115 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 112 insertions(+), 9 deletions(-) diff --git a/connect2.games.txt b/connect2.games.txt index 10e0e98..b6e56c2 100644 --- a/connect2.games.txt +++ b/connect2.games.txt @@ -74,6 +74,12 @@ "library" "engine" "linux" "@_ZN13CSteam3Server28OnValidateAuthTicketResponseEP28ValidateAuthTicketResponse_t" } + + "CBaseClient__SetSteamID" + { + "library" "engine" + "linux" "@_ZN11CBaseClient10SetSteamIDERK8CSteamID" + } } } } diff --git a/extension/extension.cpp b/extension/extension.cpp index dbd645e..cb490ee 100644 --- a/extension/extension.cpp +++ b/extension/extension.cpp @@ -37,6 +37,7 @@ ConVar g_SvNoSteam("sv_nosteam", "0", FCVAR_NOTIFY, "Disable steam validation an ConVar g_SvForceSteam("sv_forcesteam", "0", FCVAR_NOTIFY, "Force steam authentication."); ConVar g_SvGameDesc("sv_gamedesc_override", "default", FCVAR_NOTIFY, "Overwrite the default game description. Set to 'default' to keep default description."); ConVar g_SvMapName("sv_mapname_override", "default", FCVAR_NOTIFY, "Overwrite the map name. Set to 'default' to keep default name."); +ConVar g_SvSetSteamIDIPS("sv_set_steam_id_ips", "default", FCVAR_NOTIFY, "IP's allowed for webclient nosteamers"); IGameConfig *g_pGameConf = NULL; @@ -150,6 +151,7 @@ public: CDetour* detourCBaseServer__ConnectClient = nullptr; CDetour *g_Detour_CSteam3Server__OnValidateAuthTicketResponse = NULL; +CDetour *g_Detour_CBaseClient__SetSteamID = NULL; bool g_bSuppressBeginAuthSession = false; @@ -227,6 +229,7 @@ public: bool SteamLegal; bool SteamAuthFailed; bool ManualRetry; + bool Webclient; void *pvTicket; int cbTicket; @@ -250,6 +253,7 @@ public: this->SteamLegal = false; this->SteamAuthFailed = false; this->ManualRetry = false; + this->Webclient = false; // Calculate and store the ticket pointer this->pvTicket = (void *)((intptr_t)this->pCookie + sizeof(uint64)); @@ -258,6 +262,61 @@ public: }; StringHashMap g_ConnectClientStorage; + +//ai generated function +uint64 GenerateSteamIDFromName(const char *pchName) +{ + uint64 hash = 14695981039346656037ULL; + for (const char *p = pchName; *p; p++) + { + hash ^= (uint64)(unsigned char)*p; + hash *= 1099511628211ULL; + } + + uint32 W = hash & 1; + // Range within existing Steam accounts: 1 to 700,000,000 + uint32 Z = 1 + (uint32)((hash >> 1) % 699999999); + + uint64 steamID64 = 0x0110000100000000ULL | ((uint64)Z << 1) | W; + return steamID64; +} + +DETOUR_DECL_MEMBER1(CBaseClient__SetSteamID, void, const CSteamID &, steamID) +{ + char aSteamID[32]; + V_strncpy(aSteamID, steamID.Render(), 32); + ConnectClientStorage storage; + if (g_ConnectClientStorage.retrieve(aSteamID, &storage)) + { + if (storage.SteamAuthFailed) + { + char IpsAllowed[255]; + V_strncpy(IpsAllowed, g_SvSetSteamIDIPS.GetString(), 255); + + char ipString[30]; + V_snprintf(ipString, sizeof(ipString), "%u.%u.%u.%u", storage.address.ip[0], storage.address.ip[1], storage.address.ip[2], storage.address.ip[3]); + + //smutils->LogMessage(myself, "inside SetSteamID steamAuthFailed. IpsAllowed: %s. ipString: %s", IpsAllowed, ipString); + //connects from the IP's designated for the webclients. + if (strcmp(IpsAllowed, ipString) == 0) + { + uint64 steamID64 = GenerateSteamIDFromName(storage.pchName); + CSteamID newSteamID = CSteamID(steamID64); + //smutils->LogMessage(myself, "Generated SteamID64: %llu for name: %s", steamID64, storage.pchName); + //smutils->LogMessage(myself, "SteamID render: %s", newSteamID.Render()); + + storage.ullSteamID = steamID64; + storage.Webclient = true; + + g_ConnectClientStorage.replace(aSteamID, storage); + DETOUR_MEMBER_CALL(CBaseClient__SetSteamID)(newSteamID); + return; + } + } + } + DETOUR_MEMBER_CALL(CBaseClient__SetSteamID)(steamID); +} + DETOUR_DECL_MEMBER1(CSteam3Server__OnValidateAuthTicketResponse, int, ValidateAuthTicketResponse_t *, pResponse) { char aSteamID[32]; @@ -580,17 +639,41 @@ DETOUR_DECL_MEMBER9(CBaseServer__ConnectClient, IClient*, netadr_t&, address, in //auto client = DETOUR_MEMBER_MCALL_ORIGINAL(CBaseServer__ConnectClient, this)(address, nProtocol, iChallenge, iClientChallenge, nAuthProtocol, pchName, pchPassword, pCookie, cbCookie); g_bSuppressBeginAuthSession = false; g_pSM->LogMessage(myself, "finished DETOUR_MEMBER_CALL. %s", aSteamID); - Storage.pClient = client; - g_ConnectClientStorage.replace(aSteamID, Storage); - if (client && SteamAuthFailed) + //doing another retrieve in case of SetSteamID for webclient. + ConnectClientStorage storage_setSteamID; + g_ConnectClientStorage.retrieve(aSteamID, &storage_setSteamID); + if (storage_setSteamID.Webclient) { - ValidateAuthTicketResponse_t Response; - Response.m_SteamID = g_lastClientSteamID; - Response.m_eAuthSessionResponse = k_EAuthSessionResponseAuthTicketInvalid; //nosteamer monkeys - Response.m_OwnerSteamID = Response.m_SteamID; - g_pSM->LogMessage(myself, "about to do OnValidateAuthTicketResponse. %s", aSteamID); - DETOUR_MEMBER_MCALL_CALLBACK(CSteam3Server__OnValidateAuthTicketResponse, g_pSteam3Server)(&Response); + CSteamID newSteamID = CSteamID(storage_setSteamID.ullSteamID); + storage_setSteamID.pClient = client; + g_ConnectClientStorage.replace(newSteamID.Render(), storage_setSteamID); + g_ConnectClientStorage.remove(aSteamID); + + if (client && SteamAuthFailed) + { + ValidateAuthTicketResponse_t Response; + Response.m_SteamID = newSteamID; + Response.m_eAuthSessionResponse = k_EAuthSessionResponseAuthTicketInvalid; //nosteamer monkeys + Response.m_OwnerSteamID = Response.m_SteamID; + g_pSM->LogMessage(myself, "about to do OnValidateAuthTicketResponse webclient. %s", newSteamID.Render()); + DETOUR_MEMBER_MCALL_CALLBACK(CSteam3Server__OnValidateAuthTicketResponse, g_pSteam3Server)(&Response); + } + } + else + { + Storage.pClient = client; + g_ConnectClientStorage.replace(aSteamID, Storage); + + if (client && SteamAuthFailed) + { + ValidateAuthTicketResponse_t Response; + Response.m_SteamID = g_lastClientSteamID; + Response.m_eAuthSessionResponse = k_EAuthSessionResponseAuthTicketInvalid; //nosteamer monkeys + Response.m_OwnerSteamID = Response.m_SteamID; + g_pSM->LogMessage(myself, "about to do OnValidateAuthTicketResponse. %s", aSteamID); + DETOUR_MEMBER_MCALL_CALLBACK(CSteam3Server__OnValidateAuthTicketResponse, g_pSteam3Server)(&Response); + } } g_pSM->LogMessage(myself, "MEMBER 9 end. %s", aSteamID); return client; @@ -699,6 +782,14 @@ bool Connect::SDK_OnLoad(char *error, size_t maxlen, bool late) } g_Detour_CSteam3Server__OnValidateAuthTicketResponse->EnableDetour(); + g_Detour_CBaseClient__SetSteamID = DETOUR_CREATE_MEMBER(CBaseClient__SetSteamID, "CBaseClient__SetSteamID"); + if(!g_Detour_CBaseClient__SetSteamID) + { + snprintf(error, maxlen, "Failed to detour CBaseClient__SetSteamID.\n"); + return false; + } + g_Detour_CBaseClient__SetSteamID->EnableDetour(); + g_pConnectForward = g_pForwards->CreateForward("OnClientPreConnectEx", ET_LowEvent, 5, NULL, Param_String, Param_String, Param_String, Param_String, Param_String); return true; @@ -733,6 +824,12 @@ bool Connect::SDK_OnMetamodUnload(char *error, size_t maxlen) delete g_Detour_CSteam3Server__OnValidateAuthTicketResponse; } + if (g_Detour_CBaseClient__SetSteamID) + { + g_Detour_CBaseClient__SetSteamID->DisableDetour(); + delete g_Detour_CBaseClient__SetSteamID; + } + return true; }