Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client vs server build integrity check + server startup print neo_version info #496

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
2 changes: 2 additions & 0 deletions mp/src/game/server/gameinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ extern ConVar tf_mm_servermode;

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

extern IToolFrameworkServer *g_pToolFrameworkServer;
Expand Down Expand Up @@ -643,6 +644,7 @@ bool CServerGameDLL::DLLInit( CreateInterfaceFn appSystemFactory,
{
return false;
}
NeoVersionPrint();
#endif

// Yes, both the client and game .dlls will try to Connect, the soundemittersystem.dll will handle this gracefully
Expand Down
40 changes: 40 additions & 0 deletions mp/src/game/shared/neo/neo_gamerules.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "cbase.h"
#include "neo_gamerules.h"
#include "neo_version_info.h"
#include "in_buttons.h"
#include "ammodef.h"

Expand Down Expand Up @@ -36,6 +37,23 @@ ConVar neo_sv_player_restore("neo_sv_player_restore", "1", FCVAR_REPLICATED, "If
ConVar neo_name("neo_name", "", FCVAR_USERINFO | FCVAR_ARCHIVE, "The nickname to set instead of the steam profile name.");
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 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 );

BEGIN_NETWORK_TABLE_NOBASE( CNEORules, DT_NEORules )
Expand Down Expand Up @@ -1292,6 +1310,28 @@ void CNEORules::RestartGame()
#ifdef GAME_DLL
bool CNEORules::ClientConnected(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen)
{
if (neo_sv_build_integrity_check.GetBool())
{
const char *clientGitHash = engine->GetClientConVarValue(engine->IndexOfEdict(pEntity), "__neo_cl_git_hash");
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, cmpClientGitHash, MAX_GITHASH_SHOW, GIT_LONGHASH);
return false;
}
}
return BaseClass::ClientConnected(pEntity, pszName, pszAddress,
reject, maxrejectlen);
#if(0)
Expand Down
28 changes: 24 additions & 4 deletions mp/src/game/shared/neo/neo_version.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@
#include "convar.h"
#include "dbg.h"

namespace {
void neoVersionCallback()
void NeoVersionPrint()
{
#if defined(GAME_DLL)
static constexpr char HEADER[] = "neo_version (Server's build info):";
#else defined(CLIENT_DLL)
#elif defined(CLIENT_DLL)
static constexpr char HEADER[] = "neo_version (Client's build info):";
#endif
Msg("%s\n"
Expand All @@ -25,10 +24,31 @@ void neoVersionCallback()
COMPILER_ID, COMPILER_VERSION);
}

namespace {
#ifdef CLIENT_DLL
constexpr int NEO_VERSION_FLAGS = 0;
#else
constexpr int NEO_VERSION_FLAGS = FCVAR_HIDDEN;
#endif
ConCommand neo_version("neo_version", neoVersionCallback, "Print out client/server's build's information.", NEO_VERSION_FLAGS);
ConCommand neo_version("neo_version", NeoVersionPrint, "Print out client/server's build's information.", NEO_VERSION_FLAGS);

#ifdef CLIENT_DLL
ConVar __neo_cl_git_hash("__neo_cl_git_hash", GIT_LONGHASH,
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
7 changes: 7 additions & 0 deletions mp/src/game/shared/neo/neo_version.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once

void NeoVersionPrint();

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