From 14c07462120e0b1e30329c8a043f5a02f3ca7031 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Wed, 10 Apr 2024 15:15:27 +0200 Subject: [PATCH] Engine: move rcon_password entirely to server The client doesn't need this convar, client only needs cl_rcon_address. --- r5dev/common/callback.cpp | 7 +--- r5dev/engine/client/cl_rcon.cpp | 13 ++------ r5dev/engine/server/sv_rcon.cpp | 51 +++++++++++++++++++++++++---- r5dev/engine/server/sv_rcon.h | 2 ++ r5dev/engine/shared/base_rcon.cpp | 4 +-- r5dev/engine/shared/shared_rcon.cpp | 50 ++++++++-------------------- r5dev/engine/shared/shared_rcon.h | 4 ++- 7 files changed, 68 insertions(+), 63 deletions(-) diff --git a/r5dev/common/callback.cpp b/r5dev/common/callback.cpp index e47ddbe0..e932710c 100644 --- a/r5dev/common/callback.cpp +++ b/r5dev/common/callback.cpp @@ -245,12 +245,7 @@ void NET_UseSocketsForLoopbackChanged_f(IConVar* pConVar, const char* pOldString #ifndef CLIENT_DLL // Reboot the RCON server to switch address type. - if (RCONServer()->IsInitialized()) - { - Msg(eDLL_T::SERVER, "Rebooting RCON server...\n"); - RCONServer()->Shutdown(); - RCONServer()->Init(rcon_password.GetString(), RCONServer()->GetKey()); - } + RCONServer()->Reboot(); #endif // !CLIENT_DLL } } diff --git a/r5dev/engine/client/cl_rcon.cpp b/r5dev/engine/client/cl_rcon.cpp index 9daf067b..213a7d0a 100644 --- a/r5dev/engine/client/cl_rcon.cpp +++ b/r5dev/engine/client/cl_rcon.cpp @@ -330,17 +330,10 @@ static void RCON_CmdQuery_f(const CCommand& args) { bSuccess = RCONClient()->Serialize(vecMsg, args.Arg(2), "", netcon::request_e::SERVERDATA_REQUEST_AUTH); } - else // Auth with RCON server using rcon_password ConVar value. + else // Need at least 3 arguments for a password in PASS command (rcon PASS ) { - const char* storedPassword = rcon_password.GetString(); - - if (!strlen(storedPassword)) - { - Warning(eDLL_T::CLIENT, "Failed to issue command to RCON server: %s\n", "no password given"); - return; - } - - bSuccess = RCONClient()->Serialize(vecMsg, storedPassword, "", netcon::request_e::SERVERDATA_REQUEST_AUTH); + Warning(eDLL_T::CLIENT, "Failed to issue command to RCON server: %s\n", "no password given"); + return; } if (bSuccess) diff --git a/r5dev/engine/server/sv_rcon.cpp b/r5dev/engine/server/sv_rcon.cpp index 0fc7b21a..ae71061e 100644 --- a/r5dev/engine/server/sv_rcon.cpp +++ b/r5dev/engine/server/sv_rcon.cpp @@ -10,14 +10,13 @@ #include "tier2/socketcreator.h" #include "engine/cmd.h" #include "engine/net.h" +#include "engine/shared/shared_rcon.h" #include "engine/server/sv_rcon.h" #include "protoc/netcon.pb.h" #include "common/igameserverdata.h" #include "mbedtls/include/mbedtls/sha512.h" -#include -#include -#include -#include +#include "mbedtls/aes.h" +#include "mbedtls/ctr_drbg.h" //----------------------------------------------------------------------------- // Purpose: constants @@ -30,9 +29,11 @@ static const char s_BannedMessage[] = "Go away.\n"; //----------------------------------------------------------------------------- // Purpose: console variables //----------------------------------------------------------------------------- +static void RCON_PasswordChanged_f(IConVar* pConVar, const char* pOldString); static void RCON_WhiteListAddresChanged_f(IConVar* pConVar, const char* pOldString); static void RCON_ConnectionCountChanged_f(IConVar* pConVar, const char* pOldString); +static ConVar sv_rcon_password("sv_rcon_password", "", FCVAR_RELEASE, "Remote server access password (rcon server is disabled if empty)", &RCON_PasswordChanged_f); static ConVar sv_rcon_sendlogs("sv_rcon_sendlogs", "0", FCVAR_RELEASE, "Network console logs to connected and authenticated sockets"); //static ConVar sv_rcon_banpenalty("sv_rcon_banpenalty" , "10", FCVAR_RELEASE, "Number of minutes to ban users who fail rcon authentication"); @@ -41,7 +42,7 @@ static ConVar sv_rcon_maxignores("sv_rcon_maxignores", "15", FCVAR_RELEASE, "Max static ConVar sv_rcon_maxsockets("sv_rcon_maxsockets", "32", FCVAR_RELEASE, "Max number of accepted sockets before the server starts closing redundant sockets", true, 1.f, true, MAX_PLAYERS); static ConVar sv_rcon_maxconnections("sv_rcon_maxconnections", "1", FCVAR_RELEASE, "Max number of authenticated connections before the server closes the listen socket", true, 1.f, true, MAX_PLAYERS, &RCON_ConnectionCountChanged_f); -static ConVar sv_rcon_maxframesize("sv_rcon_maxframesize", "1024", FCVAR_RELEASE, "Max number of bytes allowed in a command frame from a non-authenticated netconsole", true, 0.f, false, 0.f); +static ConVar sv_rcon_maxframesize("sv_rcon_maxframesize", "1024", FCVAR_RELEASE, "Max number of bytes allowed in a message frame from a non-authenticated netconsole", true, 0.f, false, 0.f); static ConVar sv_rcon_whitelist_address("sv_rcon_whitelist_address", "", FCVAR_RELEASE, "This address is not considered a 'redundant' socket and will never be banned for failed authentication attempts", &RCON_WhiteListAddresChanged_f, "Format: '::ffff:127.0.0.1'"); //----------------------------------------------------------------------------- @@ -123,6 +124,19 @@ void CRConServer::Shutdown(void) Msg(eDLL_T::SERVER, "Remote server access deinitialized ('%i' accepted sockets closed)\n", nConnCount); } +//----------------------------------------------------------------------------- +// Purpose: reboots the RCON server if initialized +//----------------------------------------------------------------------------- +void CRConServer::Reboot(void) +{ + if (RCONServer()->IsInitialized()) + { + Msg(eDLL_T::SERVER, "Rebooting RCON server...\n"); + RCONServer()->Shutdown(); + RCONServer()->Init(sv_rcon_password.GetString(), RCONServer()->GetKey()); + } +} + //----------------------------------------------------------------------------- // Purpose: run tasks for the RCON server //----------------------------------------------------------------------------- @@ -569,7 +583,7 @@ bool CRConServer::CheckForBan(CConnectedNetConsoleData& data) const char* pszWhiteListAddress = sv_rcon_whitelist_address.GetString(); if (!pszWhiteListAddress[0]) { - Warning(eDLL_T::SERVER, "Banned list overflowed; please use a whitelist address. RCON shutting down...\n"); + Warning(eDLL_T::SERVER, "Banned list overflowed, please use a whitelist address; remote server access shutting down...\n"); Shutdown(); return true; @@ -580,7 +594,7 @@ bool CRConServer::CheckForBan(CConnectedNetConsoleData& data) { if (rcon_debug.GetBool()) { - Msg(eDLL_T::SERVER, "Banned list is full; dropping '%s'\n", szNetAdr); + Msg(eDLL_T::SERVER, "Banned list is full, dropping '%s'\n", szNetAdr); } return true; @@ -704,6 +718,29 @@ int CRConServer::GetAuthenticatedCount(void) const return m_nAuthConnections; } +//----------------------------------------------------------------------------- +// Purpose: change RCON password on server and drop all connections +//----------------------------------------------------------------------------- +static void RCON_PasswordChanged_f(IConVar* pConVar, const char* pOldString) +{ + if (ConVar* pConVarRef = g_pCVar->FindVar(pConVar->GetName())) + { + const char* pNewString = pConVarRef->GetString(); + + if (strcmp(pOldString, pNewString) == NULL) + return; // Same password. + + if (RCONServer()->IsInitialized()) + { + RCONServer()->SetPassword(pNewString); + } + else // Initialize first + { + RCON_InitServerAndTrySyncKeys(pNewString); + } + } +} + //----------------------------------------------------------------------------- // Purpose: change whitelist address on RCON server //----------------------------------------------------------------------------- diff --git a/r5dev/engine/server/sv_rcon.h b/r5dev/engine/server/sv_rcon.h index 71770910..821c7589 100644 --- a/r5dev/engine/server/sv_rcon.h +++ b/r5dev/engine/server/sv_rcon.h @@ -17,6 +17,8 @@ public: void Init(const char* pPassword, const char* pNetKey = nullptr); void Shutdown(void); + void Reboot(void); + bool SetPassword(const char* pszPassword); bool SetWhiteListAddress(const char* pszAddress); diff --git a/r5dev/engine/shared/base_rcon.cpp b/r5dev/engine/shared/base_rcon.cpp index bf24f5fb..2b677e79 100644 --- a/r5dev/engine/shared/base_rcon.cpp +++ b/r5dev/engine/shared/base_rcon.cpp @@ -94,9 +94,9 @@ void CNetConBase::SetKey(const char* pBase64NetKey, const bool bUseDefaultOnFail Error(eDLL_T::ENGINE, NO_ERROR, "RCON Key: encode error (%d)\n", encodeRet); useDefaultKey = true; } - else if (numBytesEncoded != sizeof(m_NetKey)) + else if (numBytesEncoded != AES_128_B64_ENCODED_SIZE) { - Error(eDLL_T::ENGINE, NO_ERROR, "RCON Key: write error (%zu != %zu)\n", numBytesEncoded, sizeof(m_NetKey)); + Error(eDLL_T::ENGINE, NO_ERROR, "RCON Key: write error (%zu != %zu)\n", numBytesEncoded, AES_128_B64_ENCODED_SIZE); failure = true; } else diff --git a/r5dev/engine/shared/shared_rcon.cpp b/r5dev/engine/shared/shared_rcon.cpp index bda8b88c..ec20405c 100644 --- a/r5dev/engine/shared/shared_rcon.cpp +++ b/r5dev/engine/shared/shared_rcon.cpp @@ -325,7 +325,6 @@ void RCON_PasswordChanged_f(IConVar* pConVar, const char* pOldString); ConVar rcon_debug("rcon_debug", "0", FCVAR_RELEASE, "Show rcon debug information ( !slower! )"); ConVar rcon_encryptframes("rcon_encryptframes", "1", FCVAR_RELEASE, "Whether to encrypt RCON messages"); ConVar rcon_key("rcon_key", "", FCVAR_SERVER_CANNOT_QUERY | FCVAR_DONTRECORD | FCVAR_RELEASE, "Base64 remote server access encryption key (random if empty or invalid)", &RCON_KeyChanged_f); -ConVar rcon_password("rcon_password", "", FCVAR_SERVER_CANNOT_QUERY | FCVAR_DONTRECORD | FCVAR_RELEASE, "Remote server access password (rcon server is disabled if empty)", &RCON_PasswordChanged_f); //----------------------------------------------------------------------------- // Purpose: change RCON key on server and client @@ -364,45 +363,22 @@ void RCON_KeyChanged_f(IConVar* pConVar, const char* pOldString) } } -//----------------------------------------------------------------------------- -// Purpose: change RCON password on server and drop all connections -//----------------------------------------------------------------------------- -void RCON_PasswordChanged_f(IConVar* pConVar, const char* pOldString) -{ - if (ConVar* pConVarRef = g_pCVar->FindVar(pConVar->GetName())) - { - const char* pNewString = pConVarRef->GetString(); - - if (strcmp(pOldString, pNewString) == NULL) - return; // Same password. - #ifndef CLIENT_DLL - if (RCONServer()->IsInitialized()) - { - RCONServer()->SetPassword(pNewString); - } - else // Initialize first -#endif // !CLIENT_DLL - { -#if !defined(DEDICATED) && !defined(CLIENT_DLL) - RCONServer()->Init(pNewString, rcon_key.GetString()); - - if (RCONServer()->IsInitialized()) - { - // Sync server & client keys - RCONClient()->SetKey(RCONServer()->GetKey()); - } -#else -#ifdef DEDICATED - RCONServer()->Init(pNewString, rcon_key.GetString()); -#endif // DEDICATED -#ifdef CLIENT_DLL - RCONClient()->Init(rcon_key.GetString()); -#endif // CLIENT_DLL -#endif // !DEDICATED && !CLIENT_DLL - } +void RCON_InitServerAndTrySyncKeys(const char* pPassword) +{ +#ifndef DEDICATED + RCONServer()->Init(pPassword, rcon_key.GetString()); + + if (RCONServer()->IsInitialized()) + { + // Sync server & client keys + RCONClient()->SetKey(RCONServer()->GetKey()); } +#else + RCONServer()->Init(pPassword, rcon_key.GetString()); +#endif // !DEDICATED } +#endif // !CLIENT_DLL #ifndef DEDICATED void RCON_InitClientAndTrySyncKeys() diff --git a/r5dev/engine/shared/shared_rcon.h b/r5dev/engine/shared/shared_rcon.h index c8eb8852..b2ed8fcc 100644 --- a/r5dev/engine/shared/shared_rcon.h +++ b/r5dev/engine/shared/shared_rcon.h @@ -7,8 +7,10 @@ extern ConVar rcon_debug; extern ConVar rcon_encryptframes; extern ConVar rcon_key; -extern ConVar rcon_password; +#ifndef CLIENT_DLL +extern void RCON_InitServerAndTrySyncKeys(const char* pPassword); +#endif // !CLIENT_DLL #ifndef DEDICATED extern void RCON_InitClientAndTrySyncKeys(); #endif // !DEDICATED