Skip to content

Commit

Permalink
Revert "Move player auth to CServer::ConnectClient (#548)" (#610)
Browse files Browse the repository at this point in the history
This reverts commit 17217a3 (PR #548) which introduced a regression allowing auth to progress further than intended.

(cherry picked from commit a27c702)
  • Loading branch information
GeckoEidechse committed Dec 1, 2023
1 parent 67b005e commit 9c35f10
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 56 deletions.
89 changes: 35 additions & 54 deletions NorthstarDLL/server/auth/serverauthentication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ 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);
Expand Down Expand Up @@ -104,7 +101,7 @@ bool ServerAuthenticationManager::IsDuplicateAccount(R2::CBaseClient* pPlayer, c
return false;
}

bool ServerAuthenticationManager::CheckAuthentication(R2::CBaseClient* pPlayer, uint64_t iUid, const char* pAuthToken)
bool ServerAuthenticationManager::CheckAuthentication(R2::CBaseClient* pPlayer, uint64_t iUid, char* pAuthToken)
{
std::string sUid = std::to_string(iUid);

Expand All @@ -129,7 +126,7 @@ bool ServerAuthenticationManager::CheckAuthentication(R2::CBaseClient* pPlayer,
return false;
}

void ServerAuthenticationManager::AuthenticatePlayer(R2::CBaseClient* pPlayer, uint64_t iUid, const char* pAuthToken)
void ServerAuthenticationManager::AuthenticatePlayer(R2::CBaseClient* pPlayer, uint64_t iUid, char* pAuthToken)
{
// for bot players, generate a new uid
if (pPlayer->m_bFakePlayer)
Expand Down Expand Up @@ -205,9 +202,14 @@ 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
char* pNextPlayerToken;
uint64_t iNextPlayerUid;

// clang-format off
AUTOHOOK(CBaseServer__ConnectClient, engine.dll + 0x114430,
R2::CBaseClient*,, (
void*,, (
void* self,
void* addr,
void* a3,
Expand All @@ -227,71 +229,51 @@ R2::CBaseClient*,, (
uint32_t a17))
// clang-format on
{
// 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;
// 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;

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 (!client->m_bFakePlayer)
if (!bFakePlayer)
{
if (!g_pServerAuthentication->VerifyPlayerName(authToken, playerName, pVerifiedName))
if (!g_pServerAuthentication->VerifyPlayerName(pNextPlayerToken, pName, pVerifiedName))
pAuthenticationFailure = "Invalid Name.";
else if (!g_pBanSystem->IsUIDAllowed(uid))
else if (!g_pBanSystem->IsUIDAllowed(iNextPlayerUid))
pAuthenticationFailure = "Banned From server.";
else if (!g_pServerAuthentication->CheckAuthentication(client, uid, authToken))
else if (!g_pServerAuthentication->CheckAuthentication(self, iNextPlayerUid, pNextPlayerToken))
pAuthenticationFailure = "Authentication Failed.";
}
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;
}
else // need to copy name for bots still
strncpy_s(pVerifiedName, pName, 63);

if (pAuthenticationFailure)
{
spdlog::info("{}'s (uid {}) connection was rejected: \"{}\"", playerName, uid, pAuthenticationFailure);
spdlog::info("{}'s (uid {}) connection was rejected: \"{}\"", pName, iNextPlayerUid, pAuthenticationFailure);

CBaseServer__PushDisconnectReason(self, (int32_t)((uintptr_t)self + 0xc), addr, pAuthenticationFailure);
return nullptr;
strncpy_s(pDisconnectReason, 256, pAuthenticationFailure, 255);
return false;
}

// 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 if not counted 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
if (!CBaseClient__Connect(self, pName, pNetChannel, bFakePlayer, a5, pDisconnectReason, a7))
// try to actually connect the player
if (!CBaseClient__Connect(self, pVerifiedName, pNetChannel, bFakePlayer, a5, pDisconnectReason, a7))
return false;

g_pServerAuthentication->AuthenticatePlayer(self, 0, "0");
// we already know this player's authentication data is legit, actually write it to them now
g_pServerAuthentication->AuthenticatePlayer(self, iNextPlayerUid, pNextPlayerToken);

g_pServerAuthentication->AddPlayer(self, "0");
g_pServerAuthentication->AddPlayer(self, pNextPlayerToken);
g_pServerLimits->AddPlayer(self);

return true;
Expand Down Expand Up @@ -387,7 +369,6 @@ ON_DLL_LOAD_RELIESON("engine.dll", ServerAuthentication, (ConCommand, ConVar), (
module.Offset(0x101012).Patch("E9 90 00");

CBaseServer__RejectConnection = module.Offset(0x1182E0).RCast<CBaseServer__RejectConnectionType>();
CBaseServer__PushDisconnectReason = module.Offset(0x1155D0).RCast<CBaseServer__PushDisconnectReasonType>();

if (Tier0::CommandLine()->CheckParm("-allowdupeaccounts"))
{
Expand Down
4 changes: 2 additions & 2 deletions NorthstarDLL/server/auth/serverauthentication.h
Original file line number Diff line number Diff line change
Expand Up @@ -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, const char* pAuthToken);
bool CheckAuthentication(R2::CBaseClient* pPlayer, uint64_t iUid, char* pAuthToken);

void AuthenticatePlayer(R2::CBaseClient* pPlayer, uint64_t iUid, const char* pAuthToken);
void AuthenticatePlayer(R2::CBaseClient* pPlayer, uint64_t iUid, char* pAuthToken);
bool RemovePlayerAuthData(R2::CBaseClient* pPlayer);
void WritePersistentData(R2::CBaseClient* pPlayer);
};
Expand Down

0 comments on commit 9c35f10

Please sign in to comment.