Record rcon authentication stuff into teehistorian

This allows to check moderator actions after-the-fact.
This commit is contained in:
heinrich5991 2018-01-28 03:13:05 +01:00
parent f48a2a395b
commit 1c3dc8c316
8 changed files with 139 additions and 2 deletions

View file

@ -157,6 +157,7 @@ public:
};
virtual void SetRconCID(int ClientID) = 0;
virtual int GetAuthedState(int ClientID) = 0;
virtual const char *GetAuthName(int ClientID) = 0;
virtual void Kick(int ClientID, const char *pReason) = 0;
virtual void DemoRecorder_HandleAutoStart() = 0;

View file

@ -496,6 +496,16 @@ int CServer::GetAuthedState(int ClientID)
return m_aClients[ClientID].m_Authed;
}
const char *CServer::GetAuthName(int ClientID)
{
int Key = m_aClients[ClientID].m_AuthKey;
if(Key == -1)
{
return 0;
}
return m_AuthManager.KeyIdent(Key);
}
int CServer::GetClientInfo(int ClientID, CClientInfo *pInfo)
{
dbg_assert(ClientID >= 0 && ClientID < MAX_CLIENTS, "client_id is not valid");
@ -2588,6 +2598,8 @@ void CServer::LogoutClient(int ClientID, const char *pReason)
m_aClients[ClientID].m_Authed = AUTHED_NO;
m_aClients[ClientID].m_AuthKey = -1;
GameServer()->OnSetAuthed(ClientID, AUTHED_NO);
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
}

View file

@ -239,6 +239,7 @@ public:
void SetRconCID(int ClientID);
int GetAuthedState(int ClientID);
const char *GetAuthName(int ClientID);
void GetMapInfo(char *pMapName, int MapNameSize, int *pMapSize, int *pMapCrc);
int GetClientInfo(int ClientID, CClientInfo *pInfo);
void GetClientAddr(int ClientID, char *pAddrStr, int Size);

View file

@ -1 +1,4 @@
UUID(TEEHISTORIAN_TEST, "teehistorian-test@ddnet.tw")
UUID(TEEHISTORIAN_AUTH_INIT, "teehistorian-auth-init@ddnet.tw")
UUID(TEEHISTORIAN_AUTH_LOGIN, "teehistorian-auth-login@ddnet.tw")
UUID(TEEHISTORIAN_AUTH_LOGOUT, "teehistorian-auth-logout@ddnet.tw")

View file

@ -2599,6 +2599,15 @@ void CGameContext::OnInit(/*class IKernel *pKernel*/)
GameInfo.m_pMapName = aMapName;
m_TeeHistorian.Reset(&GameInfo, TeeHistorianWrite, this);
for(int i = 0; i < MAX_CLIENTS; i++)
{
int Level = Server()->GetAuthedState(i);
if(Level)
{
m_TeeHistorian.RecordAuthInitial(i, Level, Server()->GetAuthName(i));
}
}
}
if(g_Config.m_SvSoloServer)
@ -3084,6 +3093,17 @@ void CGameContext::OnSetAuthed(int ClientID, int Level)
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "CGameContext", "Aborted vote by admin login.");
}
}
if(m_TeeHistorianActive)
{
if(Level)
{
m_TeeHistorian.RecordAuthLogin(ClientID, Level, Server()->GetAuthName(ClientID));
}
else
{
m_TeeHistorian.RecordAuthLogout(ClientID);
}
}
}
void CGameContext::SendRecord(int ClientID)

View file

@ -100,7 +100,8 @@ void CTeeHistorian::Reset(const CGameInfo *pGameInfo, WRITE_CALLBACK pfnWriteCal
m_Tick = 0;
m_LastWrittenTick = 0;
// `m_TickWritten` is initialized in `BeginTick`
// Tick 0 is implicit at the start, game starts as tick 1.
m_TickWritten = true;
m_MaxClientID = MAX_CLIENTS;
// `m_PrevMaxClientID` is initialized in `BeginTick`
for(int i = 0; i < MAX_CLIENTS; i++)
@ -515,6 +516,11 @@ void CTeeHistorian::RecordConsoleCommand(int ClientID, int FlagMask, const char
void CTeeHistorian::RecordTestExtra()
{
if(m_Debug)
{
dbg_msg("teehistorian", "test");
}
WriteExtra(UUID_TEEHISTORIAN_TEST, "", 0);
}
@ -531,6 +537,52 @@ void CTeeHistorian::EndTick()
m_State = STATE_BEFORE_TICK;
}
void CTeeHistorian::RecordAuthInitial(int ClientID, int Level, const char *pAuthName)
{
CPacker Buffer;
Buffer.Reset();
Buffer.AddInt(ClientID);
Buffer.AddInt(Level);
Buffer.AddString(pAuthName, 0);
if(m_Debug)
{
dbg_msg("teehistorian", "auth_init cid=%d level=%d auth_name=%s", ClientID, Level, pAuthName);
}
WriteExtra(UUID_TEEHISTORIAN_AUTH_INIT, Buffer.Data(), Buffer.Size());
}
void CTeeHistorian::RecordAuthLogin(int ClientID, int Level, const char *pAuthName)
{
CPacker Buffer;
Buffer.Reset();
Buffer.AddInt(ClientID);
Buffer.AddInt(Level);
Buffer.AddString(pAuthName, 0);
if(m_Debug)
{
dbg_msg("teehistorian", "auth_login cid=%d level=%d auth_name=%s", ClientID, Level, pAuthName);
}
WriteExtra(UUID_TEEHISTORIAN_AUTH_LOGIN, Buffer.Data(), Buffer.Size());
}
void CTeeHistorian::RecordAuthLogout(int ClientID)
{
CPacker Buffer;
Buffer.Reset();
Buffer.AddInt(ClientID);
if(m_Debug)
{
dbg_msg("teehistorian", "auth_logout cid=%d", ClientID);
}
WriteExtra(UUID_TEEHISTORIAN_AUTH_LOGOUT, Buffer.Data(), Buffer.Size());
}
void CTeeHistorian::Finish()
{
dbg_assert(m_State == STATE_START || m_State == STATE_INPUTS || m_State == STATE_BEFORE_ENDTICK || m_State == STATE_BEFORE_TICK, "invalid teehistorian state");

View file

@ -58,6 +58,10 @@ public:
void EndTick();
void RecordAuthInitial(int ClientID, int Level, const char *pAuthName);
void RecordAuthLogin(int ClientID, int Level, const char *pAuthName);
void RecordAuthLogout(int ClientID);
int m_Debug; // Possible values: 0, 1, 2.
private:

View file

@ -1,6 +1,7 @@
#include <gtest/gtest.h>
#include <base/detect.h>
#include <engine/server.h>
#include <engine/shared/config.h>
#include <game/gamecore.h>
#include <game/server/teehistorian.h>
@ -296,7 +297,7 @@ TEST_F(TeeHistorian, ExtraMessage)
{
const unsigned char EXPECTED[] = {
0x41, 0x00, // TICK_SKIP dt=0
// EX uuid=6bb8ba88-0f0b-382e-8dae-dbf4052b8b7d data=""
// EX uuid=6bb8ba88-0f0b-382e-8dae-dbf4052b8b7d data_len=0
0x4a,
0x6b, 0xb8, 0xba, 0x88, 0x0f, 0x0b, 0x38, 0x2e,
0x8d, 0xae, 0xdb, 0xf4, 0x05, 0x2b, 0x8b, 0x7d,
@ -307,3 +308,46 @@ TEST_F(TeeHistorian, ExtraMessage)
Finish();
Expect(EXPECTED, sizeof(EXPECTED));
}
TEST_F(TeeHistorian, Auth)
{
const unsigned char EXPECTED[] = {
// EX uuid=60daba5c-52c4-3aeb-b8ba-b2953fb55a17 data_len=16
0x4a,
0x60, 0xda, 0xba, 0x5c, 0x52, 0xc4, 0x3a, 0xeb,
0xb8, 0xba, 0xb2, 0x95, 0x3f, 0xb5, 0x5a, 0x17,
0x10,
// (AUTH_INIT) cid=0 level=3 auth_name="default_admin"
0x00, 0x03, 'd', 'e', 'f', 'a', 'u', 'l',
't', '_', 'a', 'd', 'm', 'i', 'n', 0x00,
// EX uuid=37ecd3b8-9218-3bb9-a71b-a935b86f6a81 data_len=9
0x4a,
0x37, 0xec, 0xd3, 0xb8, 0x92, 0x18, 0x3b, 0xb9,
0xa7, 0x1b, 0xa9, 0x35, 0xb8, 0x6f, 0x6a, 0x81,
0x09,
// (AUTH_LOGIN) cid=1 level=2 auth_name="foobar"
0x01, 0x02, 'f', 'o', 'o', 'b', 'a', 'r',
0x00,
// EX uuid=37ecd3b8-9218-3bb9-a71b-a935b86f6a81 data_len=7
0x4a,
0x37, 0xec, 0xd3, 0xb8, 0x92, 0x18, 0x3b, 0xb9,
0xa7, 0x1b, 0xa9, 0x35, 0xb8, 0x6f, 0x6a, 0x81,
0x07,
// (AUTH_LOGIN) cid=1 level=2 auth_name="foobar"
0x02, 0x01, 'h', 'e', 'l', 'p', 0x00,
// EX uuid=d4f5abe8-edd2-3fb9-abd8-1c8bb84f4a63 data_len=7
0x4a,
0xd4, 0xf5, 0xab, 0xe8, 0xed, 0xd2, 0x3f, 0xb9,
0xab, 0xd8, 0x1c, 0x8b, 0xb8, 0x4f, 0x4a, 0x63,
0x01,
// (AUTH_LOGOUT) cid=1
0x01,
0x40, // FINISH
};
m_TH.RecordAuthInitial(0, IServer::AUTHED_ADMIN, "default_admin");
m_TH.RecordAuthLogin(1, IServer::AUTHED_MOD, "foobar");
m_TH.RecordAuthLogin(2, IServer::AUTHED_HELPER, "help");
m_TH.RecordAuthLogout(1);
Finish();
Expect(EXPECTED, sizeof(EXPECTED));
}