From 5b4c64005f1fcf787f0d4b037879c15fa4099f2f Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Wed, 14 Oct 2020 01:19:41 +0200 Subject: [PATCH 1/2] Disallow player name changes when the player is muted --- src/game/server/gamecontext.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 8f55c0953..0801cf23a 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -2176,16 +2176,23 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) Server()->SetClientName(ClientID, pMsg->m_pName); if(str_comp(aOldName, Server()->ClientName(ClientID)) != 0) { - char aChatText[256]; - str_format(aChatText, sizeof(aChatText), "'%s' changed name to '%s'", aOldName, Server()->ClientName(ClientID)); - SendChat(-1, CGameContext::CHAT_ALL, aChatText); + if(ProcessSpamProtection(ClientID)) + { + Server()->SetClientName(ClientID, aOldName); + } + else + { + char aChatText[256]; + str_format(aChatText, sizeof(aChatText), "'%s' changed name to '%s'", aOldName, Server()->ClientName(ClientID)); + SendChat(-1, CGameContext::CHAT_ALL, aChatText); - // reload scores - Score()->PlayerData(ClientID)->Reset(); - m_apPlayers[ClientID]->m_Score = -9999; - Score()->LoadPlayerData(ClientID); + // reload scores + Score()->PlayerData(ClientID)->Reset(); + m_apPlayers[ClientID]->m_Score = -9999; + Score()->LoadPlayerData(ClientID); - SixupNeedsUpdate = true; + SixupNeedsUpdate = true; + } } if(str_comp(Server()->ClientClan(ClientID), pMsg->m_pClan)) From 246d2ac3d66dc416ff5dff7f81740f83de64089a Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Wed, 14 Oct 2020 16:42:35 +0200 Subject: [PATCH 2/2] Allow IServer users to check when client's names change Use that available interface to process name change spam protection more cleanly. --- src/engine/server.h | 1 + src/engine/server/server.cpp | 100 ++++++++++++++++++-------------- src/engine/server/server.h | 4 +- src/game/server/gamecontext.cpp | 28 ++++----- 4 files changed, 72 insertions(+), 61 deletions(-) diff --git a/src/engine/server.h b/src/engine/server.h index 010e3edf0..54c63da66 100644 --- a/src/engine/server.h +++ b/src/engine/server.h @@ -190,6 +190,7 @@ public: virtual void GetMapInfo(char *pMapName, int MapNameSize, int *pMapSize, SHA256_DIGEST *pSha256, int *pMapCrc) = 0; + virtual bool WouldClientNameChange(int ClientID, const char *pNameRequest) = 0; virtual void SetClientName(int ClientID, char const *pName) = 0; virtual void SetClientClan(int ClientID, char const *pClan) = 0; virtual void SetClientCountry(int ClientID, int Country) = 0; diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 216264f43..fc835d0e4 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -329,82 +329,96 @@ CServer::CServer() : Init(); } -int CServer::TrySetClientName(int ClientID, const char *pName) +bool CServer::IsClientNameAvailable(int ClientID, const char *pNameRequest) { - char aTrimmedName[64]; - - // trim the name - str_copy(aTrimmedName, str_utf8_skip_whitespaces(pName), sizeof(aTrimmedName)); - str_utf8_trim_right(aTrimmedName); - // check for empty names - if(!aTrimmedName[0]) - return -1; + if(!pNameRequest[0]) + return false; // check for names starting with /, as they can be abused to make people // write chat commands - if(aTrimmedName[0] == '/') - return -1; + if(pNameRequest[0] == '/') + return false; // make sure that two clients don't have the same name for(int i = 0; i < MAX_CLIENTS; i++) { if(i != ClientID && m_aClients[i].m_State >= CClient::STATE_READY) { - if(str_utf8_comp_confusable(aTrimmedName, m_aClients[i].m_aName) == 0) - return -1; + if(str_utf8_comp_confusable(pNameRequest, m_aClients[i].m_aName) == 0) + return false; } } - char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "'%s' -> '%s'", pName, aTrimmedName); - Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf); - pName = aTrimmedName; - - // set the client name - str_copy(m_aClients[ClientID].m_aName, pName, MAX_NAME_LENGTH); - return 0; + return true; } -void CServer::SetClientName(int ClientID, const char *pName) +bool CServer::SetClientNameImpl(int ClientID, const char *pNameRequest, bool Set) { - if(ClientID < 0 || ClientID >= MAX_CLIENTS || m_aClients[ClientID].m_State < CClient::STATE_READY) - return; + dbg_assert(0 <= ClientID && ClientID < MAX_CLIENTS, "invalid client id"); + if(m_aClients[ClientID].m_State < CClient::STATE_READY) + return false; - if(!pName) - return; - - CNameBan *pBanned = IsNameBanned(pName, m_aNameBans.base_ptr(), m_aNameBans.size()); - if(pBanned) + if(Set) { - if(m_aClients[ClientID].m_State == CClient::STATE_READY) + CNameBan *pBanned = IsNameBanned(pNameRequest, m_aNameBans.base_ptr(), m_aNameBans.size()); + if(pBanned) { - char aBuf[256]; - if(pBanned->m_aReason[0]) + if(m_aClients[ClientID].m_State == CClient::STATE_READY) { - str_format(aBuf, sizeof(aBuf), "Kicked (your name is banned: %s)", pBanned->m_aReason); + char aBuf[256]; + if(pBanned->m_aReason[0]) + { + str_format(aBuf, sizeof(aBuf), "Kicked (your name is banned: %s)", pBanned->m_aReason); + } + else + { + str_copy(aBuf, "Kicked (your name is banned)", sizeof(aBuf)); + } + Kick(ClientID, aBuf); } - else - { - str_copy(aBuf, "Kicked (your name is banned)", sizeof(aBuf)); - } - Kick(ClientID, aBuf); + return true; } - return; } + // trim the name + char aTrimmedName[MAX_NAME_LENGTH]; + str_copy(aTrimmedName, str_utf8_skip_whitespaces(pNameRequest), sizeof(aTrimmedName)); + str_utf8_trim_right(aTrimmedName); + char aNameTry[MAX_NAME_LENGTH]; - str_copy(aNameTry, pName, sizeof(aNameTry)); - if(TrySetClientName(ClientID, aNameTry)) + str_copy(aNameTry, aTrimmedName, sizeof(aNameTry)); + + if(!IsClientNameAvailable(ClientID, aNameTry)) { // auto rename for(int i = 1;; i++) { - str_format(aNameTry, sizeof(aNameTry), "(%d)%s", i, pName); - if(TrySetClientName(ClientID, aNameTry) == 0) + str_format(aNameTry, sizeof(aNameTry), "(%d)%s", i, aTrimmedName); + if(IsClientNameAvailable(ClientID, aNameTry)) break; } } + + bool Changed = str_comp(m_aClients[ClientID].m_aName, aNameTry) != 0; + + if(Set) + { + // set the client name + str_copy(m_aClients[ClientID].m_aName, aNameTry, MAX_NAME_LENGTH); + } + + return Changed; +} + +bool CServer::WouldClientNameChange(int ClientID, const char *pNameRequest) +{ + return SetClientNameImpl(ClientID, pNameRequest, false); +} + +void CServer::SetClientName(int ClientID, const char *pName) +{ + SetClientNameImpl(ClientID, pName, true); } void CServer::SetClientClan(int ClientID, const char *pClan) diff --git a/src/engine/server/server.h b/src/engine/server/server.h index 8cc7236f0..56913e109 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -258,8 +258,10 @@ public: CServer(); - int TrySetClientName(int ClientID, const char *pName); + bool IsClientNameAvailable(int ClientID, const char *pNameRequest); + bool SetClientNameImpl(int ClientID, const char *pNameRequest, bool Set); + virtual bool WouldClientNameChange(int ClientID, const char *pNameRequest); virtual void SetClientName(int ClientID, const char *pName); virtual void SetClientClan(int ClientID, char const *pClan); virtual void SetClientCountry(int ClientID, int Country); diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 0801cf23a..542265af7 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -2173,26 +2173,20 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID) // set infos char aOldName[MAX_NAME_LENGTH]; str_copy(aOldName, Server()->ClientName(ClientID), sizeof(aOldName)); - Server()->SetClientName(ClientID, pMsg->m_pName); - if(str_comp(aOldName, Server()->ClientName(ClientID)) != 0) + if(Server()->WouldClientNameChange(ClientID, pMsg->m_pName) && !ProcessSpamProtection(ClientID)) { - if(ProcessSpamProtection(ClientID)) - { - Server()->SetClientName(ClientID, aOldName); - } - else - { - char aChatText[256]; - str_format(aChatText, sizeof(aChatText), "'%s' changed name to '%s'", aOldName, Server()->ClientName(ClientID)); - SendChat(-1, CGameContext::CHAT_ALL, aChatText); + Server()->SetClientName(ClientID, pMsg->m_pName); - // reload scores - Score()->PlayerData(ClientID)->Reset(); - m_apPlayers[ClientID]->m_Score = -9999; - Score()->LoadPlayerData(ClientID); + char aChatText[256]; + str_format(aChatText, sizeof(aChatText), "'%s' changed name to '%s'", aOldName, Server()->ClientName(ClientID)); + SendChat(-1, CGameContext::CHAT_ALL, aChatText); - SixupNeedsUpdate = true; - } + // reload scores + Score()->PlayerData(ClientID)->Reset(); + m_apPlayers[ClientID]->m_Score = -9999; + Score()->LoadPlayerData(ClientID); + + SixupNeedsUpdate = true; } if(str_comp(Server()->ClientClan(ClientID), pMsg->m_pClan))