Skip to content

Commit

Permalink
Debug builds integrity check bypass
Browse files Browse the repository at this point in the history
* Debug builds will have their first byte final bit fliped to 1 to
  indicate it's a debug build
* This will indicate to the server that it's a debug build and if
  the server allows bypass, then it will
* Mask out final bit before comparison to allow debug build that
  matches hash without first byte final bit
  • Loading branch information
nullsystem committed Jul 7, 2024
1 parent e266b6d commit 44c04c4
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 4 deletions.
5 changes: 5 additions & 0 deletions mp/src/game/client/cdll_client_int.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ extern vgui::IInputInternal *g_InputInternal;
#endif

#ifdef NEO
#include "neo_version.h"
#include "neo_mount_original.h"
#endif

Expand Down Expand Up @@ -954,6 +955,10 @@ int CHLClient::Init( CreateInterfaceFn appSystemFactory, CreateInterfaceFn physi
InitFbx();
#endif

#if defined(NEO) && defined(DEBUG)
InitializeDbgNeoClGitHashEdit();
#endif

// it's ok if this is NULL. That just means the sourcevr.dll wasn't found
g_pSourceVR = (ISourceVirtualReality *)appSystemFactory(SOURCE_VIRTUAL_REALITY_INTERFACE_VERSION, NULL);

Expand Down
25 changes: 22 additions & 3 deletions mp/src/game/shared/neo/neo_gamerules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,20 @@ ConVar neo_name("neo_name", "", FCVAR_USERINFO | FCVAR_ARCHIVE, "The nickname to
ConVar cl_onlysteamnick("cl_onlysteamnick", "0", FCVAR_USERINFO | FCVAR_ARCHIVE, "Only show players Steam names, otherwise show player set names.", true, 0.0f, true, 1.0f);

#ifdef GAME_DLL
#ifdef DEBUG
// Debug build by default relax integrity check requirement among debug clients
static constexpr char INTEGRITY_CHECK_DBG[] = "1";
#else
static constexpr char INTEGRITY_CHECK_DBG[] = "0";
#endif
ConVar neo_sv_build_integrity_check("neo_sv_build_integrity_check", "1", FCVAR_GAMEDLL | FCVAR_REPLICATED,
"If enabled, the server checkes the build's Git hash between the client and"
"If enabled, the server checks the build's Git hash between the client and"
" the server. If it doesn't match, the server rejects and disconnects the client.",
true, 0.0f, true, 1.0f);
ConVar neo_sv_build_integrity_check_allow_debug("neo_sv_build_integrity_check_allow_debug", INTEGRITY_CHECK_DBG, FCVAR_GAMEDLL | FCVAR_REPLICATED,
"If enabled, when the server checks the client hashes, it'll also allow debug"
" builds which has a given special bit to bypass the check.",
true, 0.0f, true, 1.0f);
#endif

REGISTER_GAMERULES_CLASS( CNEORules );
Expand Down Expand Up @@ -1302,13 +1312,22 @@ bool CNEORules::ClientConnected(edict_t *pEntity, const char *pszName, const cha
if (neo_sv_build_integrity_check.GetBool())
{
const char *clientGitHash = engine->GetClientConVarValue(engine->IndexOfEdict(pEntity), "__neo_cl_git_hash");
if (V_strcmp(clientGitHash, GIT_LONGHASH))
const bool dbgBuildSkip = (neo_sv_build_integrity_check_allow_debug.GetBool()) ? (clientGitHash[0] & 0b1000'0000) : false;
if (dbgBuildSkip)
{
DevWarning("Client debug build integrity check bypass! Client: %s | Server: %s\n", clientGitHash, GIT_LONGHASH);
}
// NEO NOTE (nullsystem): Due to debug builds, if we're to match exactly, we'll have to mask out final bit first
char cmpClientGitHash[sizeof(GIT_LONGHASH) + 1];
V_strcpy_safe(cmpClientGitHash, clientGitHash);
cmpClientGitHash[0] &= 0b0111'1111;
if (!dbgBuildSkip && V_strcmp(cmpClientGitHash, GIT_LONGHASH))
{
// Truncate the git hash so it's short hash and doesn't make message too long
static constexpr int MAX_GITHASH_SHOW = 7;
V_snprintf(reject, maxrejectlen, "Build integrity failed! Client vs server mis-match: Check your neo_version. "
"Client: %.*s | Server: %.*s",
MAX_GITHASH_SHOW, clientGitHash, MAX_GITHASH_SHOW, GIT_LONGHASH);
MAX_GITHASH_SHOW, cmpClientGitHash, MAX_GITHASH_SHOW, GIT_LONGHASH);
return false;
}
}
Expand Down
17 changes: 16 additions & 1 deletion mp/src/game/shared/neo/neo_version.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,21 @@ ConCommand neo_version("neo_version", neoVersionPrint, "Print out client/server'

#ifdef CLIENT_DLL
ConVar __neo_cl_git_hash("__neo_cl_git_hash", GIT_LONGHASH,
FCVAR_USERINFO | FCVAR_HIDDEN | FCVAR_DONTRECORD | FCVAR_NOT_CONNECTED | FCVAR_PRINTABLEONLY);
FCVAR_USERINFO | FCVAR_HIDDEN | FCVAR_DONTRECORD | FCVAR_NOT_CONNECTED
#ifndef DEBUG
| FCVAR_PRINTABLEONLY
#endif
);
#endif
}

#if defined(CLIENT_DLL) && defined(DEBUG)
void InitializeDbgNeoClGitHashEdit()
{
static char static_dbgHash[sizeof(GIT_LONGHASH) + 1];
V_strcpy_safe(static_dbgHash, GIT_LONGHASH);
static_dbgHash[0] = static_dbgHash[0] | 0b1000'0000;
__neo_cl_git_hash.SetDefault(static_dbgHash);
__neo_cl_git_hash.Revert(); // It just sets to the default
}
#endif
4 changes: 4 additions & 0 deletions mp/src/game/shared/neo/neo_version.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#pragma once

void neoVersionPrint();

#if defined(CLIENT_DLL) && defined(DEBUG)
void InitializeDbgNeoClGitHashEdit();
#endif

0 comments on commit 44c04c4

Please sign in to comment.