diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 2fc0c27eb..4eed7f3d8 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -1366,6 +1366,34 @@ static inline int MsgFromSixup(int Msg, bool System) return Msg; } +bool CServer::CheckReservedSlotAuth(int ClientID, const char *pPassword) +{ + char aBuf[256]; + + if(Config()->m_SvReservedSlotsPass[0] && !str_comp(Config()->m_SvReservedSlotsPass, pPassword)) + { + str_format(aBuf, sizeof(aBuf), "cid=%d joining reserved slot with reserved pass", ClientID); + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); + return true; + } + + // "^#(.*?)#(.*)$" + if(Config()->m_SvReservedSlotsAuthLevel != 4 && pPassword[0] == '#') + { + char aName[sizeof(Config()->m_Password)]; + const char *pPass = str_next_token(pPassword + 1, "#", aName, sizeof(aName)); + int Slot = m_AuthManager.FindKey(aName); + if(pPass && m_AuthManager.CheckKey(Slot, pPass + 1) && m_AuthManager.KeyLevel(Slot) >= Config()->m_SvReservedSlotsAuthLevel) + { + str_format(aBuf, sizeof(aBuf), "cid=%d joining reserved slot with key=%s", ClientID, m_AuthManager.KeyIdent(Slot)); + Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf); + return true; + } + } + + return false; +} + void CServer::ProcessClientPacket(CNetChunk *pPacket) { int ClientID = pPacket->m_ClientID; @@ -1466,30 +1494,12 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) } // reserved slot - if(ClientID >= Config()->m_SvMaxClients - Config()->m_SvReservedSlots) + if(ClientID >= Config()->m_SvMaxClients - Config()->m_SvReservedSlots && !CheckReservedSlotAuth(ClientID, pPassword)) { - if(Config()->m_SvReservedSlotsPass[0] && !str_comp(Config()->m_SvReservedSlotsPass, pPassword)) - { - goto join; - } - - // "^#(.*?)#(.*)$" - if(pPassword[0] == '#') - { - char aName[sizeof(Config()->m_Password)]; - const char *pPass = str_next_token(pPassword + 1, "#", aName, sizeof(aName)); - int Slot = m_AuthManager.FindKey(aName); - if(pPass && m_AuthManager.CheckKey(Slot, pPass + 1)) - { - goto join; - } - } - m_NetServer.Drop(ClientID, "This server is full"); return; } - join: m_aClients[ClientID].m_State = CClient::STATE_CONNECTING; SendRconType(ClientID, m_AuthManager.NumNonDefaultKeys() > 0); SendCapabilities(ClientID); diff --git a/src/engine/server/server.h b/src/engine/server/server.h index 13e8c3e9a..2f8d6cffd 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -339,6 +339,7 @@ public: void SendRconCmdRem(const IConsole::CCommandInfo *pCommandInfo, int ClientID); void UpdateClientRconCommands(); + bool CheckReservedSlotAuth(int ClientID, const char *pPassword); void ProcessClientPacket(CNetChunk *pPacket); class CCache diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h index bd794f9c8..b82945d32 100644 --- a/src/engine/shared/config_variables.h +++ b/src/engine/shared/config_variables.h @@ -207,6 +207,7 @@ MACRO_CONFIG_INT(HttpAllowInsecure, http_allow_insecure, 0, 0, 1, CFGFLAG_CLIENT MACRO_CONFIG_STR(SvWelcome, sv_welcome, 64, "", CFGFLAG_SERVER, "Message that will be displayed to players who join the server") MACRO_CONFIG_INT(SvReservedSlots, sv_reserved_slots, 0, 0, MAX_CLIENTS, CFGFLAG_SERVER, "The number of slots that are reserved for special players") MACRO_CONFIG_STR(SvReservedSlotsPass, sv_reserved_slots_pass, 32, "", CFGFLAG_SERVER | CFGFLAG_NONTEEHISTORIC, "The password that is required to use a reserved slot") +MACRO_CONFIG_INT(SvReservedSlotsAuthLevel, sv_reserved_slots_auth_level, 1, 1, 4, CFGFLAG_SERVER, "Minimum rcon auth level needed to use a reserved slot. 4 = rcon auth disabled") MACRO_CONFIG_INT(SvHit, sv_hit, 1, 0, 1, CFGFLAG_SERVER | CFGFLAG_GAME, "Whether players can hammer/grenade/laser each other or not") MACRO_CONFIG_INT(SvEndlessDrag, sv_endless_drag, 0, 0, 1, CFGFLAG_SERVER | CFGFLAG_GAME, "Turns endless hooking on/off") MACRO_CONFIG_INT(SvTestingCommands, sv_test_cmds, 0, 0, 1, CFGFLAG_SERVER, "Turns testing commands aka cheats on/off (setting only works in initial config)")