From e916bba19006ef690d781e9ce06a657bd5059f94 Mon Sep 17 00:00:00 2001 From: NicknineTheEagle Date: Tue, 8 Jul 2025 19:39:14 +0300 Subject: [PATCH] Fixed old SteamGameServer interfaces --- dll/auth.cpp | 59 +++++++++++++++ dll/dll/auth.h | 2 + dll/steam_gameserver.cpp | 127 ++++++++++++++++++++------------ sdk/steam/isteamgameserver002.h | 16 ++++ 4 files changed, 157 insertions(+), 47 deletions(-) diff --git a/dll/auth.cpp b/dll/auth.cpp index b36d192d..9737950f 100644 --- a/dll/auth.cpp +++ b/dll/auth.cpp @@ -631,6 +631,35 @@ void Auth_Manager::launch_callback(CSteamID id, EAuthSessionResponse resp, doubl callbacks->addCBResult(data.k_iCallback, &data, sizeof(data), delay); } +void Auth_Manager::launch_callback_gs_steam2(CSteamID steam_id, uint32_t user_id, bool approved) +{ + if (approved) { + // Fire Steam2 callback. + GSClientSteam2Accept_t data2{}; + data2.m_UserID = user_id; + data2.m_SteamID = steam_id.ConvertToUint64(); + callbacks->addCBResult(data2.k_iCallback, &data2, sizeof(data2)); + + // Fire Steam3 callback. + GSClientApprove_t data3{}; + data3.m_SteamID = data3.m_OwnerSteamID = steam_id; + callbacks->addCBResult(data3.k_iCallback, &data3, sizeof(data3)); + } else { + // Fire Steam2 callback. This will kick the client so no need to send Steam3 callback. + GSClientSteam2Deny_t data2{}; + data2.m_UserID = user_id; + data2.m_eSteamError = k_EDenyNotLoggedOn; + callbacks->addCBResult(data2.k_iCallback, &data2, sizeof(data2)); + + /* + GSClientDeny_t data3{}; + data3.m_SteamID = steam_id; + data3.m_eDenyReason = k_EDenyNotLoggedOn; //TODO: other reasons? + callbacks->addCBResult(data3.k_iCallback, &data3, sizeof(data3)); + */ + } +} + void Auth_Manager::launch_callback_gs(CSteamID id, bool approved) { if (approved) { @@ -796,6 +825,36 @@ void Auth_Manager::cancelTicket(uint32 number) outbound.erase(ticket); } +bool Auth_Manager::SendSteam2UserConnect( uint32 unUserID, const void *pvRawKey, uint32 unKeyLen, uint32 unIPPublic, uint16 usPort, const void *pvCookie, uint32 cubCookie, CSteamID *pSteamIDUser ) +{ + // pvRawKey is Steam2 auth ticket, it comes from Steam.dll. + // pvCookie is Steam3 auth ticket, it comes from us. + // Steam3 ticket is technically optional but it should always be there if the client is using Goldberg + // so there's no real need to check Steam2 ticket. + if (cubCookie < STEAM_TICKET_MIN_SIZE) return false; + + Auth_Data data; + uint64 id; + memcpy(&id, (char *)pvCookie + STEAM_ID_OFFSET_TICKET, sizeof(id)); + uint32 number; + memcpy(&number, ((char *)pvCookie) + sizeof(uint64), sizeof(number)); + data.id = CSteamID(id); + data.number = number; + if (pSteamIDUser) *pSteamIDUser = data.id; + + for (auto & t : inbound) { + if (t.id == data.id) { + //Should this return false? + launch_callback_gs_steam2(id, unUserID, true); + return true; + } + } + + inbound.push_back(data); + launch_callback_gs_steam2(id, unUserID, true); + return true; +} + bool Auth_Manager::SendUserConnectAndAuthenticate( uint32 unIPClient, const void *pvAuthBlob, uint32 cubAuthBlobSize, CSteamID *pSteamIDUser ) { if (cubAuthBlobSize < STEAM_TICKET_MIN_SIZE) return false; diff --git a/dll/dll/auth.h b/dll/dll/auth.h index dfa2a236..79e80b6a 100644 --- a/dll/dll/auth.h +++ b/dll/dll/auth.h @@ -76,6 +76,7 @@ class Auth_Manager { std::vector outbound{}; void launch_callback(CSteamID id, EAuthSessionResponse resp, double delay=0); + void launch_callback_gs_steam2(CSteamID steam_id, uint32_t user_id, bool approved); void launch_callback_gs(CSteamID id, bool approved); static void ticket_callback(void *object, Common_Message *msg); @@ -94,6 +95,7 @@ public: uint32 countInboundAuth(); + bool SendSteam2UserConnect( uint32 unUserID, const void *pvRawKey, uint32 unKeyLen, uint32 unIPPublic, uint16 usPort, const void *pvCookie, uint32 cubCookie, CSteamID *pSteamIDUser ); bool SendUserConnectAndAuthenticate( uint32 unIPClient, const void *pvAuthBlob, uint32 cubAuthBlobSize, CSteamID *pSteamIDUser ); CSteamID fakeUser(); diff --git a/dll/steam_gameserver.cpp b/dll/steam_gameserver.cpp index acdbd28c..f3ae5b52 100644 --- a/dll/steam_gameserver.cpp +++ b/dll/steam_gameserver.cpp @@ -519,7 +519,7 @@ bool Steam_GameServer::BSetServerType( uint32 unServerFlags, uint32 unGameIP, ui } bool Steam_GameServer::BSetServerType( int32 nGameAppId, uint32 unServerFlags, uint32 unGameIP, uint16 unGamePort, - uint16 unSpectatorPort, uint16 usQueryPort, const char *pchGameDir, const char *pchVersion, bool bLANMode ) + uint16 unSpectatorPort, uint16 usQueryPort, const char *pchGameDir, const char *pchVersion, bool bLANMode ) { return BSetServerType(unServerFlags, unGameIP, unGamePort, unSpectatorPort, usQueryPort, pchGameDir, pchVersion, bLANMode); } @@ -887,48 +887,65 @@ void Steam_GameServer::RunCallbacks() void Steam_GameServer::GSSetSpawnCount( uint32 ucSpawn ) { PRINT_DEBUG_TODO(); - std::lock_guard lock(global_mutex); - - SetBotPlayerCount((int)ucSpawn); } bool Steam_GameServer::GSGetSteam2GetEncryptionKeyToSendToNewClient( void *pvEncryptionKey, uint32 *pcbEncryptionKey, uint32 cbMaxEncryptionKey ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); std::lock_guard lock(global_mutex); - - return false; + + if (cbMaxEncryptionKey < 160) + return false; + + // This key is used in Steam.dll to encrypt the auth ticket. None of Steam.dll emulators are known to use it + // so it doesn't really matter what we put in it. + memset(pvEncryptionKey, 0xab, 160); + *pcbEncryptionKey = 160; + return true; } -bool Steam_GameServer::GSSendSteam2UserConnect( uint32 unUserID, const void *pvRawKey, uint32 unKeyLen, uint32 unIPPublic, uint16 usPort, const void *pvCookie, uint32 cubCookie ) +bool Steam_GameServer::GSSendSteam2UserConnect( uint32 unUserID, const void *pvRawKey, uint32 unKeyLen, uint32 unIPPublic, uint16 usPort, const void *pvCookie, uint32 cubCookie ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); std::lock_guard lock(global_mutex); - - return SendUserConnectAndAuthenticate(unIPPublic, pvRawKey, unKeyLen, nullptr); + + CSteamID steam_id; + bool res = auth_manager->SendSteam2UserConnect(unUserID, pvRawKey, unKeyLen, unIPPublic, usPort, pvCookie, cubCookie, &steam_id); + + if (res) { + std::pair infos; + infos.first = steam_id; + infos.second.join_time = std::chrono::steady_clock::now(); + infos.second.score = 0; + infos.second.name = "unnamed"; + players.emplace_back(std::move(infos)); + } + + return res; } bool Steam_GameServer::GSSendSteam3UserConnect( CSteamID steamID, uint32 unIPPublic, const void *pvCookie, uint32 cubCookie ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); std::lock_guard lock(global_mutex); - - return SendUserConnectAndAuthenticate(unIPPublic, pvCookie, cubCookie, nullptr); + + CSteamID steam_id; + return SendUserConnectAndAuthenticate(unIPPublic, pvCookie, cubCookie, &steam_id); } bool Steam_GameServer::GSRemoveUserConnect( uint32 unUserID ) { PRINT_DEBUG_TODO(); std::lock_guard lock(global_mutex); - + return false; } bool Steam_GameServer::GSSendUserDisconnect( CSteamID steamID, uint32 unUserID ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); std::lock_guard lock(global_mutex); - + SendUserDisconnect(steamID); return true; } @@ -937,7 +954,7 @@ bool Steam_GameServer::GSSendUserStatusResponse( CSteamID steamID, int nSecondsC { PRINT_DEBUG_TODO(); std::lock_guard lock(global_mutex); - + return false; } @@ -945,48 +962,50 @@ bool Steam_GameServer::Obsolete_GSSetStatus( int32 nAppIdServed, uint32 unServer { PRINT_DEBUG_TODO(); std::lock_guard lock(global_mutex); - + return false; } bool Steam_GameServer::GSUpdateStatus( int cPlayers, int cPlayersMax, int cBotPlayers, const char *pchServerName, const char *pchMapName ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); std::lock_guard lock(global_mutex); - - return false; + + UpdateServerStatus(cPlayers, cPlayersMax, cBotPlayers, pchServerName, "", pchMapName); + return true; } bool Steam_GameServer::GSSetServerType( int32 nGameAppId, uint32 unServerFlags, uint32 unGameIP, uint32 unGamePort, const char *pchGameDir, const char *pchVersion ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); std::lock_guard lock(global_mutex); - - return BSetServerType(unServerFlags, unGameIP, unGamePort, 0, 0, pchGameDir, pchVersion, true); + + return BSetServerType(unServerFlags, unGameIP, unGamePort, 0, 0, pchGameDir, pchVersion, false); } bool Steam_GameServer::GSSetServerType2( int32 nGameAppId, uint32 unServerFlags, uint32 unGameIP, uint16 unGamePort, uint16 unSpectatorPort, uint16 usQueryPort, const char *pchGameDir, const char *pchVersion, bool bLANMode ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); std::lock_guard lock(global_mutex); - + SetSpectatorPort(unSpectatorPort); return BSetServerType(unServerFlags, unGameIP, unGamePort, unSpectatorPort, usQueryPort, pchGameDir, pchVersion, bLANMode); } bool Steam_GameServer::GSUpdateStatus2( int cPlayers, int cPlayersMax, int cBotPlayers, const char *pchServerName, const char *pSpectatorServerName, const char *pchMapName ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); std::lock_guard lock(global_mutex); - - return false; + + UpdateServerStatus(cPlayers, cPlayersMax, cBotPlayers, pchServerName, pSpectatorServerName, pchMapName); + return true; } bool Steam_GameServer::GSCreateUnauthenticatedUser( CSteamID *pSteamID ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); std::lock_guard lock(global_mutex); - + CSteamID steamId = CreateUnauthenticatedUserConnection(); if (pSteamID) *pSteamID = steamId; return true; @@ -994,23 +1013,23 @@ bool Steam_GameServer::GSCreateUnauthenticatedUser( CSteamID *pSteamID ) bool Steam_GameServer::GSSetUserData( CSteamID steamID, const char *pPlayerName, uint32 nFrags ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); std::lock_guard lock(global_mutex); - + return BUpdateUserData(steamID, pPlayerName, nFrags); } void Steam_GameServer::GSUpdateSpectatorPort( uint16 unSpectatorPort ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); std::lock_guard lock(global_mutex); - + UpdateSpectatorPort(unSpectatorPort); } void Steam_GameServer::GSSetGameType( const char *pchType ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); std::lock_guard lock(global_mutex); SetGameType(pchType); @@ -1018,34 +1037,48 @@ void Steam_GameServer::GSSetGameType( const char *pchType ) bool Steam_GameServer::GSSendUserConnect( uint32 unUserID, uint32 unIPPublic, uint16 usPort, const void *pvCookie, uint32 cubCookie ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); std::lock_guard lock(global_mutex); - - return SendUserConnectAndAuthenticate(unIPPublic, pvCookie, cubCookie, nullptr); + + // SteamGameServer003 still sends Steam2 callbacks, probably for backwards compatibility. + CSteamID steam_id; + bool res = auth_manager->SendSteam2UserConnect(unUserID, nullptr, 0, unIPPublic, usPort, pvCookie, cubCookie, &steam_id); + + if (res) { + std::pair infos; + infos.first = steam_id; + infos.second.join_time = std::chrono::steady_clock::now(); + infos.second.score = 0; + infos.second.name = "unnamed"; + players.emplace_back(std::move(infos)); + } + + return res; } bool Steam_GameServer::GSSetServerType( int32 nGameAppId, uint32 unServerFlags, uint32 unGameIP, uint16 unGamePort, uint16 unSpectatorPort, uint16 usQueryPort, const char *pchGameDir, const char *pchVersion, bool bLANMode ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); std::lock_guard lock(global_mutex); - + SetSpectatorPort(unSpectatorPort); return BSetServerType(unServerFlags, unGameIP, unGamePort, unSpectatorPort, usQueryPort, pchGameDir, pchVersion, bLANMode); } bool Steam_GameServer::GSUpdateStatus( int cPlayers, int cPlayersMax, int cBotPlayers, const char *pchServerName, const char *pSpectatorServerName, const char *pchMapName ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); std::lock_guard lock(global_mutex); - - return false; + + UpdateServerStatus(cPlayers, cPlayersMax, cBotPlayers, pchServerName, pSpectatorServerName, pchMapName); + return true; } bool Steam_GameServer::GSGetUserAchievementStatus( CSteamID steamID, const char *pchAchievementName ) { - PRINT_DEBUG_TODO(); + PRINT_DEBUG_ENTRY(); std::lock_guard lock(global_mutex); - + return BGetUserAchievementStatus(steamID, pchAchievementName); } // older sdk ----------------------------------------------- diff --git a/sdk/steam/isteamgameserver002.h b/sdk/steam/isteamgameserver002.h index a6989cf2..3c6c8faa 100644 --- a/sdk/steam/isteamgameserver002.h +++ b/sdk/steam/isteamgameserver002.h @@ -33,4 +33,20 @@ public: virtual void GSSetGameType( const char *pchType ) = 0; }; +// client has been denied to connect to this game server because of a Steam2 auth failure +struct GSClientSteam2Deny_t +{ + enum { k_iCallback = k_iSteamGameServerCallbacks + 4 }; + uint32 m_UserID; + uint32 m_eSteamError; +}; + +// client has been accepted by Steam2 to connect to this game server +struct GSClientSteam2Accept_t +{ + enum { k_iCallback = k_iSteamGameServerCallbacks + 5 }; + uint32 m_UserID; + uint64 m_SteamID; +}; + #endif // ISTEAMGAMESERVER002_H