From 1ebb4f89a649484b6307e633ae98db82de84d0d8 Mon Sep 17 00:00:00 2001 From: heinrich5991 Date: Mon, 24 Jul 2017 21:43:55 +0200 Subject: [PATCH] Reopen: Add a flag for rcon login via username (#800) This uses an extended protocol message to signal that rcon authentication might require a username, allowing the client to enable the username prompt. Add a forgotten logout on key update --- src/engine/client.h | 1 + src/engine/client/client.cpp | 5 +++++ src/engine/server/authmanager.cpp | 6 ++++++ src/engine/server/authmanager.h | 1 + src/engine/server/server.cpp | 24 ++++++++++++++++++++++++ src/engine/server/server.h | 1 + src/engine/shared/protocol_ex_msgs.h | 2 ++ src/game/client/components/console.cpp | 23 +++++++++++------------ src/game/client/components/console.h | 2 ++ src/game/client/gameclient.cpp | 5 +++++ src/game/client/gameclient.h | 1 + 11 files changed, 59 insertions(+), 12 deletions(-) diff --git a/src/engine/client.h b/src/engine/client.h index 271510f38..04c33e87e 100644 --- a/src/engine/client.h +++ b/src/engine/client.h @@ -204,6 +204,7 @@ protected: public: virtual void OnConsoleInit() = 0; + virtual void OnRconType(bool UsernameReq) = 0; virtual void OnRconLine(const char *pLine) = 0; virtual void OnInit() = 0; virtual void OnNewSnapshot() = 0; diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 8c0e2108a..5baeab32d 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -1978,6 +1978,11 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) } } } + else if(Msg == NETMSG_RCONTYPE) + { + bool UsernameReq = Unpacker.GetInt() & 1; + GameClient()->OnRconType(UsernameReq); + } } else { diff --git a/src/engine/server/authmanager.cpp b/src/engine/server/authmanager.cpp index 8e4f7358e..a65263f2c 100644 --- a/src/engine/server/authmanager.cpp +++ b/src/engine/server/authmanager.cpp @@ -182,3 +182,9 @@ bool CAuthManager::IsGenerated() { return m_Generated; } + +int CAuthManager::NumNonDefaultKeys() +{ + int DefaultCount = (m_aDefault[0] >= 0) + (m_aDefault[1] >= 0) + (m_aDefault[2] >= 0); + return m_aKeys.size() - DefaultCount; +} diff --git a/src/engine/server/authmanager.h b/src/engine/server/authmanager.h index 7cae19b29..1267917b7 100644 --- a/src/engine/server/authmanager.h +++ b/src/engine/server/authmanager.h @@ -46,6 +46,7 @@ public: void ListKeys(FListCallback pfnListCallbac, void *pUser); void AddDefaultKey(int Level, const char *pPw); bool IsGenerated(); + int NumNonDefaultKeys(); }; #endif //ENGINE_SERVER_AUTH_MANAGER_H diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index 2f9a2cbe4..ddd86fbad 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -864,6 +864,13 @@ int CServer::DelClientCallback(int ClientID, const char *pReason, void *pUser) return 0; } +void CServer::SendRconType(int ClientID, bool UsernameReq) +{ + CMsgPacker Msg(NETMSG_RCONTYPE); + Msg.AddInt(UsernameReq); + SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true); +} + void CServer::SendMap(int ClientID) { CMsgPacker Msg(NETMSG_MAP_CHANGE); @@ -1052,6 +1059,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) } m_aClients[ClientID].m_State = CClient::STATE_CONNECTING; + SendRconType(ClientID, m_AuthManager.NumNonDefaultKeys() > 0); SendMap(ClientID); } } @@ -2094,10 +2102,15 @@ void CServer::ConAuthAdd(IConsole::IResult *pResult, void *pUser) return; } + bool NeedUpdate = !pManager->NumNonDefaultKeys(); if(pManager->AddKey(pIdent, pPw, Level) < 0) pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "auth", "ident already exists"); else + { + if(NeedUpdate) + pThis->SendRconType(-1, true); pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "auth", "key added"); + } } void CServer::ConAuthAddHashed(IConsole::IResult *pResult, void *pUser) @@ -2131,10 +2144,16 @@ void CServer::ConAuthAddHashed(IConsole::IResult *pResult, void *pUser) return; } + bool NeedUpdate = !pManager->NumNonDefaultKeys(); + if(pManager->AddKeyHash(pIdent, aHash, aSalt, Level) < 0) pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "auth", "ident already exists"); else + { + if(NeedUpdate) + pThis->SendRconType(-1, true); pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "auth", "key added"); + } } void CServer::ConAuthUpdate(IConsole::IResult *pResult, void *pUser) @@ -2161,6 +2180,7 @@ void CServer::ConAuthUpdate(IConsole::IResult *pResult, void *pUser) } pManager->UpdateKey(KeySlot, pPw, Level); + pThis->LogoutKey(KeySlot, "key update"); pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "auth", "key updated"); } @@ -2224,6 +2244,10 @@ void CServer::ConAuthRemove(IConsole::IResult *pResult, void *pUser) } pThis->AuthRemoveKey(KeySlot); + + if(!pManager->NumNonDefaultKeys()) + pThis->SendRconType(-1, false); + pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "auth", "key removed, all users logged out"); } diff --git a/src/engine/server/server.h b/src/engine/server/server.h index aa572ec7c..9ab477dca 100644 --- a/src/engine/server/server.h +++ b/src/engine/server/server.h @@ -252,6 +252,7 @@ public: static int ClientRejoinCallback(int ClientID, void *pUser); + void SendRconType(int ClientID, bool UsernameReq); void SendMap(int ClientID); void SendMapData(int ClientID, int Chunk); void SendConnectionReady(int ClientID); diff --git a/src/engine/shared/protocol_ex_msgs.h b/src/engine/shared/protocol_ex_msgs.h index 1d98014ce..eb660da61 100644 --- a/src/engine/shared/protocol_ex_msgs.h +++ b/src/engine/shared/protocol_ex_msgs.h @@ -20,3 +20,5 @@ UUID(NETMSG_WHATIS, "what-is@ddnet.tw") UUID(NETMSG_ITIS, "it-is@ddnet.tw") UUID(NETMSG_IDONTKNOW, "i-dont-know@ddnet.tw") + +UUID(NETMSG_RCONTYPE, "rcon-type@ddnet.tw") diff --git a/src/game/client/components/console.cpp b/src/game/client/components/console.cpp index 6aa6ad1d4..07c76e2c3 100644 --- a/src/game/client/components/console.cpp +++ b/src/game/client/components/console.cpp @@ -51,6 +51,7 @@ CGameConsole::CInstance::CInstance(int Type) m_aUser[0] = '\0'; m_UserGot = false; + m_UsernameReq = false; m_IsCommand = false; } @@ -82,10 +83,7 @@ void CGameConsole::CInstance::ExecuteLine(const char *pLine) m_pGameConsole->Client()->Rcon(pLine); else { - CServerInfo pServerInfo; - m_pGameConsole->Client()->GetServerInfo(&pServerInfo); - - if(!m_UserGot && IsDDNet(&pServerInfo)) + if(!m_UserGot && m_UsernameReq) { m_UserGot = true; str_copy(m_aUser, pLine, sizeof m_aUser); @@ -149,9 +147,7 @@ void CGameConsole::CInstance::OnInput(IInput::CEvent Event) { if(Event.m_Key == KEY_RETURN || Event.m_Key == KEY_KP_ENTER) { - CServerInfo pServerInfo; - m_pGameConsole->Client()->GetServerInfo(&pServerInfo); - if(m_Input.GetString()[0] || (IsDDNet(&pServerInfo) && !m_pGameConsole->Client()->RconAuthed() && !m_UserGot)) + if(m_Input.GetString()[0] || (m_UsernameReq && !m_pGameConsole->Client()->RconAuthed() && !m_UserGot)) { if(m_Type == CONSOLETYPE_LOCAL || m_pGameConsole->Client()->RconAuthed()) { @@ -488,9 +484,6 @@ void CGameConsole::OnRender() Info.m_pCurrentCmd = pConsole->m_aCompletionBuffer; TextRender()->SetCursor(&Info.m_Cursor, x+Info.m_Offset, y+RowHeight+2.0f, FontSize, TEXTFLAG_RENDER); - CServerInfo pServerInfo; - Client()->GetServerInfo(&pServerInfo); - // render prompt CTextCursor Cursor; TextRender()->SetCursor(&Cursor, x, y, FontSize, TEXTFLAG_RENDER); @@ -503,7 +496,7 @@ void CGameConsole::OnRender() pPrompt = "rcon> "; else { - if(IsDDNet(&pServerInfo)) + if(pConsole->m_UsernameReq) { if(!pConsole->m_UserGot) pPrompt = "Enter Username> "; @@ -537,7 +530,7 @@ void CGameConsole::OnRender() //hide rcon password char aInputString[512]; str_copy(aInputString, pConsole->m_Input.GetString(Editing), sizeof(aInputString)); - if(m_ConsoleType == CONSOLETYPE_REMOTE && Client()->State() == IClient::STATE_ONLINE && !Client()->RconAuthed() && (pConsole->m_UserGot || !IsDDNet(&pServerInfo))) + if(m_ConsoleType == CONSOLETYPE_REMOTE && Client()->State() == IClient::STATE_ONLINE && !Client()->RconAuthed() && (pConsole->m_UserGot || !pConsole->m_UsernameReq)) { for(int i = 0; i < pConsole->m_Input.GetLength(Editing); ++i) aInputString[i] = '*'; @@ -788,6 +781,11 @@ void CGameConsole::ConchainConsoleOutputLevelUpdate(IConsole::IResult *pResult, } } +void CGameConsole::RequireUsername(bool UsernameReq) +{ + m_RemoteConsole.m_UsernameReq = UsernameReq; +} + void CGameConsole::PrintLine(int Type, const char *pLine) { if(Type == CONSOLETYPE_LOCAL) @@ -823,5 +821,6 @@ void CGameConsole::OnStateChange(int NewState, int OldState) { m_RemoteConsole.m_UserGot = false; m_RemoteConsole.m_Input.Clear(); + m_RemoteConsole.m_UsernameReq = false; } } diff --git a/src/game/client/components/console.h b/src/game/client/components/console.h index 88e7a7ef4..ecdb71fc3 100644 --- a/src/game/client/components/console.h +++ b/src/game/client/components/console.h @@ -45,6 +45,7 @@ class CGameConsole : public CComponent char m_aUser[32]; bool m_UserGot; + bool m_UsernameReq; bool m_IsCommand; char m_aCommandName[IConsole::TEMPCMD_NAME_LENGTH]; @@ -103,6 +104,7 @@ public: CGameConsole(); void PrintLine(int Type, const char *pLine); + void RequireUsername(bool UsernameReq); virtual void OnStateChange(int NewState, int OldState); virtual void OnConsoleInit(); diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 1797348ef..5cb4968cd 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -884,6 +884,11 @@ void CGameClient::OnFlagGrab(int TeamID) m_aStats[m_Snap.m_pGameDataObj->m_FlagCarrierBlue].m_FlagGrabs++; } +void CGameClient::OnRconType(bool UsernameReq) +{ + m_pGameConsole->RequireUsername(UsernameReq); +} + void CGameClient::OnRconLine(const char *pLine) { m_pGameConsole->PrintLine(CGameConsole::CONSOLETYPE_REMOTE, pLine); diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index cecff7e7c..cc4deb85e 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -311,6 +311,7 @@ public: virtual int OnSnapInput(int *pData, bool Dummy, bool Force); virtual void OnShutdown(); virtual void OnEnterGame(); + virtual void OnRconType(bool UsernameReq); virtual void OnRconLine(const char *pLine); virtual void OnGameOver(); virtual void OnStartGame();