From 8aaf37f956a2dc48592c366a0ad668af0cdf75cb Mon Sep 17 00:00:00 2001 From: cat_or_not <41955154+catornot@users.noreply.github.com> Date: Sun, 10 Sep 2023 13:22:43 -0400 Subject: [PATCH 1/7] fix tokens for bots --- .../server/auth/serverauthentication.cpp | 18 +++++++++++++----- .../server/auth/serverauthentication.h | 4 ++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/NorthstarDLL/server/auth/serverauthentication.cpp b/NorthstarDLL/server/auth/serverauthentication.cpp index d5653dccf..e98ffe942 100644 --- a/NorthstarDLL/server/auth/serverauthentication.cpp +++ b/NorthstarDLL/server/auth/serverauthentication.cpp @@ -101,7 +101,7 @@ bool ServerAuthenticationManager::IsDuplicateAccount(R2::CBaseClient* pPlayer, c return false; } -bool ServerAuthenticationManager::CheckAuthentication(R2::CBaseClient* pPlayer, uint64_t iUid, char* pAuthToken) +bool ServerAuthenticationManager::CheckAuthentication(R2::CBaseClient* pPlayer, uint64_t iUid, const char* pAuthToken) { std::string sUid = std::to_string(iUid); @@ -126,7 +126,7 @@ bool ServerAuthenticationManager::CheckAuthentication(R2::CBaseClient* pPlayer, return false; } -void ServerAuthenticationManager::AuthenticatePlayer(R2::CBaseClient* pPlayer, uint64_t iUid, char* pAuthToken) +void ServerAuthenticationManager::AuthenticatePlayer(R2::CBaseClient* pPlayer, uint64_t iUid, const char* pAuthToken) { // for bot players, generate a new uid if (pPlayer->m_bFakePlayer) @@ -204,8 +204,8 @@ void ServerAuthenticationManager::WritePersistentData(R2::CBaseClient* pPlayer) // store these in vars so we can use them in CBaseClient::Connect // this is fine because ptrs won't decay by the time we use this, just don't use it outside of calls from cbaseclient::connectclient -char* pNextPlayerToken; -uint64_t iNextPlayerUid; +const char* pNextPlayerToken = "0"; +uint64_t iNextPlayerUid = 0; // clang-format off AUTOHOOK(CBaseServer__ConnectClient, engine.dll + 0x114430, @@ -255,9 +255,17 @@ bool,, (R2::CBaseClient* self, char* pName, void* pNetChannel, char bFakePlayer, else if (!g_pServerAuthentication->CheckAuthentication(self, iNextPlayerUid, pNextPlayerToken)) pAuthenticationFailure = "Authentication Failed."; } - else // need to copy name for bots still + else + { + // need to copy name for bots still strncpy_s(pVerifiedName, pName, 63); + // insert zeroed token since bots steal tokens from previously connected players + // pNextPlayerToken is also uninit if a bot spawns before a player connects + pNextPlayerToken = "0000000000000"; + iNextPlayerUid = 0; + } + if (pAuthenticationFailure) { spdlog::info("{}'s (uid {}) connection was rejected: \"{}\"", pName, iNextPlayerUid, pAuthenticationFailure); diff --git a/NorthstarDLL/server/auth/serverauthentication.h b/NorthstarDLL/server/auth/serverauthentication.h index dd0e13af7..34680bd6c 100644 --- a/NorthstarDLL/server/auth/serverauthentication.h +++ b/NorthstarDLL/server/auth/serverauthentication.h @@ -48,9 +48,9 @@ class ServerAuthenticationManager bool VerifyPlayerName(const char* pAuthToken, const char* pName, char pOutVerifiedName[64]); bool IsDuplicateAccount(R2::CBaseClient* pPlayer, const char* pUid); - bool CheckAuthentication(R2::CBaseClient* pPlayer, uint64_t iUid, char* pAuthToken); + bool CheckAuthentication(R2::CBaseClient* pPlayer, uint64_t iUid, const char* pAuthToken); - void AuthenticatePlayer(R2::CBaseClient* pPlayer, uint64_t iUid, char* pAuthToken); + void AuthenticatePlayer(R2::CBaseClient* pPlayer, uint64_t iUid, const char* pAuthToken); bool RemovePlayerAuthData(R2::CBaseClient* pPlayer); void WritePersistentData(R2::CBaseClient* pPlayer); }; From 29f1b084062f85b665b82ff2662799747cbc27e0 Mon Sep 17 00:00:00 2001 From: cat_or_not <41955154+catornot@users.noreply.github.com> Date: Sun, 10 Sep 2023 13:39:50 -0400 Subject: [PATCH 2/7] fmt --- NorthstarDLL/server/auth/serverauthentication.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NorthstarDLL/server/auth/serverauthentication.cpp b/NorthstarDLL/server/auth/serverauthentication.cpp index e98ffe942..92e085e5a 100644 --- a/NorthstarDLL/server/auth/serverauthentication.cpp +++ b/NorthstarDLL/server/auth/serverauthentication.cpp @@ -262,9 +262,9 @@ bool,, (R2::CBaseClient* self, char* pName, void* pNetChannel, char bFakePlayer, // insert zeroed token since bots steal tokens from previously connected players // pNextPlayerToken is also uninit if a bot spawns before a player connects - pNextPlayerToken = "0000000000000"; + pNextPlayerToken = "000000000000"; iNextPlayerUid = 0; - } + } if (pAuthenticationFailure) { From 37d74d489049f76c549bed65bde0736b3f62d5b4 Mon Sep 17 00:00:00 2001 From: cat_or_not <41955154+catornot@users.noreply.github.com> Date: Mon, 11 Sep 2023 19:14:19 -0400 Subject: [PATCH 3/7] remove check --- NorthstarDLL/server/auth/serverauthentication.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/NorthstarDLL/server/auth/serverauthentication.cpp b/NorthstarDLL/server/auth/serverauthentication.cpp index 92e085e5a..3db6261f4 100644 --- a/NorthstarDLL/server/auth/serverauthentication.cpp +++ b/NorthstarDLL/server/auth/serverauthentication.cpp @@ -255,17 +255,9 @@ bool,, (R2::CBaseClient* self, char* pName, void* pNetChannel, char bFakePlayer, else if (!g_pServerAuthentication->CheckAuthentication(self, iNextPlayerUid, pNextPlayerToken)) pAuthenticationFailure = "Authentication Failed."; } - else - { - // need to copy name for bots still + else // need to copy name for bots still strncpy_s(pVerifiedName, pName, 63); - // insert zeroed token since bots steal tokens from previously connected players - // pNextPlayerToken is also uninit if a bot spawns before a player connects - pNextPlayerToken = "000000000000"; - iNextPlayerUid = 0; - } - if (pAuthenticationFailure) { spdlog::info("{}'s (uid {}) connection was rejected: \"{}\"", pName, iNextPlayerUid, pAuthenticationFailure); From 826c84fbd22eef79264fb47786cbe7b3c7187ed2 Mon Sep 17 00:00:00 2001 From: cat_or_not <41955154+catornot@users.noreply.github.com> Date: Wed, 13 Sep 2023 21:13:04 -0400 Subject: [PATCH 4/7] move player auth to CServer::ConnectClient --- .../server/auth/serverauthentication.cpp | 90 ++++++++++++------- 1 file changed, 58 insertions(+), 32 deletions(-) diff --git a/NorthstarDLL/server/auth/serverauthentication.cpp b/NorthstarDLL/server/auth/serverauthentication.cpp index 3db6261f4..bd6184ad8 100644 --- a/NorthstarDLL/server/auth/serverauthentication.cpp +++ b/NorthstarDLL/server/auth/serverauthentication.cpp @@ -25,6 +25,9 @@ AUTOHOOK_INIT() ServerAuthenticationManager* g_pServerAuthentication; CBaseServer__RejectConnectionType CBaseServer__RejectConnection; +typedef void (*CBaseServer__PushDisconnectReasonType)(void*, int32_t, void*, const char*); +CBaseServer__PushDisconnectReasonType CBaseServer__PushDisconnectReason; + void ServerAuthenticationManager::AddRemotePlayer(std::string token, uint64_t uid, std::string username, std::string pdata) { std::string uidS = std::to_string(uid); @@ -202,14 +205,9 @@ void ServerAuthenticationManager::WritePersistentData(R2::CBaseClient* pPlayer) // auth hooks -// store these in vars so we can use them in CBaseClient::Connect -// this is fine because ptrs won't decay by the time we use this, just don't use it outside of calls from cbaseclient::connectclient -const char* pNextPlayerToken = "0"; -uint64_t iNextPlayerUid = 0; - // clang-format off AUTOHOOK(CBaseServer__ConnectClient, engine.dll + 0x114430, -void*,, ( +R2::CBaseClient*,, ( void* self, void* addr, void* a3, @@ -229,51 +227,78 @@ void*,, ( uint32_t a17)) // clang-format on { - // auth tokens are sent with serverfilter, can't be accessed from player struct to my knowledge, so have to do this here - pNextPlayerToken = serverFilter; - iNextPlayerUid = uid; + // try to connect the client to get a client object + R2::CBaseClient* client = + CBaseServer__ConnectClient(self, addr, a3, a4, a5, a6, a7, playerName, serverFilter, a10, a11, a12, a13, a14, uid, a16, a17); + if (!client) + return nullptr; - return CBaseServer__ConnectClient(self, addr, a3, a4, a5, a6, a7, playerName, serverFilter, a10, a11, a12, a13, a14, uid, a16, a17); -} - -ConVar* Cvar_ns_allowuserclantags; - -// clang-format off -AUTOHOOK(CBaseClient__Connect, engine.dll + 0x101740, -bool,, (R2::CBaseClient* self, char* pName, void* pNetChannel, char bFakePlayer, void* a5, char pDisconnectReason[256], void* a7)) -// clang-format on -{ const char* pAuthenticationFailure = nullptr; char pVerifiedName[64]; + const char* authToken = serverFilter; - if (!bFakePlayer) + if (!client->m_bFakePlayer) { - if (!g_pServerAuthentication->VerifyPlayerName(pNextPlayerToken, pName, pVerifiedName)) + if (!g_pServerAuthentication->VerifyPlayerName(authToken, playerName, pVerifiedName)) pAuthenticationFailure = "Invalid Name."; - else if (!g_pBanSystem->IsUIDAllowed(iNextPlayerUid)) + else if (!g_pBanSystem->IsUIDAllowed(uid)) pAuthenticationFailure = "Banned From server."; - else if (!g_pServerAuthentication->CheckAuthentication(self, iNextPlayerUid, pNextPlayerToken)) + else if (!g_pServerAuthentication->CheckAuthentication(client, uid, authToken)) pAuthenticationFailure = "Authentication Failed."; } - else // need to copy name for bots still - strncpy_s(pVerifiedName, pName, 63); + else + { + spdlog::error("A bot called CBaseServer__ConnectClient, should be impossible!"); + + CBaseServer__PushDisconnectReason(self, (int32_t)((uintptr_t)self + 0xc), addr, "A bot was init in CServer__ConnectClient"); + return nullptr; + + // this should never happen but just in case + // need to copy name for bots still + // strncpy_s(pVerifiedName, playerName, 63); + // default stuff for bots + // authToken = "00000000000000"; + // uid = 0; + } if (pAuthenticationFailure) { - spdlog::info("{}'s (uid {}) connection was rejected: \"{}\"", pName, iNextPlayerUid, pAuthenticationFailure); + spdlog::info("{}'s (uid {}) connection was rejected: \"{}\"", playerName, uid, pAuthenticationFailure); - strncpy_s(pDisconnectReason, 256, pAuthenticationFailure, 255); - return false; + CBaseServer__PushDisconnectReason(self, (int32_t)((uintptr_t)self + 0xc), addr, pAuthenticationFailure); + return nullptr; } - // try to actually connect the player - if (!CBaseClient__Connect(self, pVerifiedName, pNetChannel, bFakePlayer, a5, pDisconnectReason, a7)) + // write name into the client + strncpy_s(pVerifiedName, client->m_Name, 63); + + // we already know this player's authentication data is legit, actually write it to them now + g_pServerAuthentication->AuthenticatePlayer(client, uid, authToken); + + g_pServerAuthentication->AddPlayer(client, authToken); + g_pServerLimits->AddPlayer(client); +} + +ConVar* Cvar_ns_allowuserclantags; + +// clang-format off +AUTOHOOK(CBaseClient__Connect, engine.dll + 0x101740, +bool,, (R2::CBaseClient* self, char* pName, void* pNetChannel, char bFakePlayer, void* a5, char pDisconnectReason[256], void* a7)) +// clang-format on +{ + // only remains to count bots in player count, since bots take player slots and it will give a false player count on the server browser. + + if (!bFakePlayer) + return CBaseClient__Connect(self, pName, pNetChannel, bFakePlayer, a5, pDisconnectReason, a7); + + // try to actually connect the bot + else if (!CBaseClient__Connect(self, pName, pNetChannel, bFakePlayer, a5, pDisconnectReason, a7)) return false; // we already know this player's authentication data is legit, actually write it to them now - g_pServerAuthentication->AuthenticatePlayer(self, iNextPlayerUid, pNextPlayerToken); + g_pServerAuthentication->AuthenticatePlayer(self, 0, "0"); - g_pServerAuthentication->AddPlayer(self, pNextPlayerToken); + g_pServerAuthentication->AddPlayer(self, "0"); g_pServerLimits->AddPlayer(self); return true; @@ -369,6 +394,7 @@ ON_DLL_LOAD_RELIESON("engine.dll", ServerAuthentication, (ConCommand, ConVar), ( module.Offset(0x101012).Patch("E9 90 00"); CBaseServer__RejectConnection = module.Offset(0x1182E0).RCast(); + CBaseServer__PushDisconnectReason = module.Offset(0x1155D0).RCast(); if (Tier0::CommandLine()->CheckParm("-allowdupeaccounts")) { From 96a7cbc78a9719f4068322ef191ab4c7459eeecd Mon Sep 17 00:00:00 2001 From: cat_or_not <41955154+catornot@users.noreply.github.com> Date: Wed, 13 Sep 2023 21:17:36 -0400 Subject: [PATCH 5/7] remove commented out code --- NorthstarDLL/server/auth/serverauthentication.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/NorthstarDLL/server/auth/serverauthentication.cpp b/NorthstarDLL/server/auth/serverauthentication.cpp index bd6184ad8..bfad13d45 100644 --- a/NorthstarDLL/server/auth/serverauthentication.cpp +++ b/NorthstarDLL/server/auth/serverauthentication.cpp @@ -252,13 +252,6 @@ R2::CBaseClient*,, ( CBaseServer__PushDisconnectReason(self, (int32_t)((uintptr_t)self + 0xc), addr, "A bot was init in CServer__ConnectClient"); return nullptr; - - // this should never happen but just in case - // need to copy name for bots still - // strncpy_s(pVerifiedName, playerName, 63); - // default stuff for bots - // authToken = "00000000000000"; - // uid = 0; } if (pAuthenticationFailure) @@ -286,7 +279,7 @@ AUTOHOOK(CBaseClient__Connect, engine.dll + 0x101740, bool,, (R2::CBaseClient* self, char* pName, void* pNetChannel, char bFakePlayer, void* a5, char pDisconnectReason[256], void* a7)) // clang-format on { - // only remains to count bots in player count, since bots take player slots and it will give a false player count on the server browser. + // only remains to count bots in player count, since bots take player slots and it will give if not counted a false player count on the server browser. if (!bFakePlayer) return CBaseClient__Connect(self, pName, pNetChannel, bFakePlayer, a5, pDisconnectReason, a7); From eff51971261b813856d19458aea986cf980b3913 Mon Sep 17 00:00:00 2001 From: cat_or_not <41955154+catornot@users.noreply.github.com> Date: Wed, 13 Sep 2023 21:44:47 -0400 Subject: [PATCH 6/7] fmt --- NorthstarDLL/server/auth/serverauthentication.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/NorthstarDLL/server/auth/serverauthentication.cpp b/NorthstarDLL/server/auth/serverauthentication.cpp index bfad13d45..afe449ca9 100644 --- a/NorthstarDLL/server/auth/serverauthentication.cpp +++ b/NorthstarDLL/server/auth/serverauthentication.cpp @@ -279,7 +279,8 @@ AUTOHOOK(CBaseClient__Connect, engine.dll + 0x101740, bool,, (R2::CBaseClient* self, char* pName, void* pNetChannel, char bFakePlayer, void* a5, char pDisconnectReason[256], void* a7)) // clang-format on { - // only remains to count bots in player count, since bots take player slots and it will give if not counted a false player count on the server browser. + // only remains to count bots in player count, + // since bots take player slots and it will give if not counted a false player count on the server browser. if (!bFakePlayer) return CBaseClient__Connect(self, pName, pNetChannel, bFakePlayer, a5, pDisconnectReason, a7); From 02673aad28979880366024ed3d91ec0cc91c902a Mon Sep 17 00:00:00 2001 From: cat_or_not <41955154+catornot@users.noreply.github.com> Date: Sat, 21 Oct 2023 21:55:20 -0400 Subject: [PATCH 7/7] improve control flow and remove a useless comment --- NorthstarDLL/server/auth/serverauthentication.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/NorthstarDLL/server/auth/serverauthentication.cpp b/NorthstarDLL/server/auth/serverauthentication.cpp index afe449ca9..14e166bdd 100644 --- a/NorthstarDLL/server/auth/serverauthentication.cpp +++ b/NorthstarDLL/server/auth/serverauthentication.cpp @@ -286,10 +286,9 @@ bool,, (R2::CBaseClient* self, char* pName, void* pNetChannel, char bFakePlayer, return CBaseClient__Connect(self, pName, pNetChannel, bFakePlayer, a5, pDisconnectReason, a7); // try to actually connect the bot - else if (!CBaseClient__Connect(self, pName, pNetChannel, bFakePlayer, a5, pDisconnectReason, a7)) + if (!CBaseClient__Connect(self, pName, pNetChannel, bFakePlayer, a5, pDisconnectReason, a7)) return false; - // we already know this player's authentication data is legit, actually write it to them now g_pServerAuthentication->AuthenticatePlayer(self, 0, "0"); g_pServerAuthentication->AddPlayer(self, "0");