Skip to content

Commit cb4f7de

Browse files
committed
Server: Give certain access level for logged in users
1 parent 71fad70 commit cb4f7de

File tree

2 files changed

+192
-69
lines changed

2 files changed

+192
-69
lines changed

src/engine/server/server.cpp

Lines changed: 180 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -407,9 +407,19 @@ void CServer::AuthTick()
407407
nullptr);
408408

409409
{
410+
EAccessLevel AccessLevel{EAccessLevel::USER};
411+
for(const SAccountAccessInfo &AccessInfo : m_vAccountsAccessInfo)
412+
{
413+
if(AccessInfo.UserId == UserId)
414+
{
415+
AccessLevel = AccessInfo.AccessLevel;
416+
SetClientAccessLevel(ClientId, AccessInfo.AccessLevel, true);
417+
}
418+
}
419+
410420
char aBuf[256];
411-
str_format(aBuf, sizeof(aBuf), "ClientId=%d authed as %s (UserId %d)",
412-
ClientId, pUsername, UserId);
421+
str_format(aBuf, sizeof(aBuf), "ClientId=%d authed as %s (UserId %d, %s)",
422+
ClientId, pUsername, UserId, toString(AccessLevel));
413423
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "accounts", aBuf);
414424
}
415425
}
@@ -2056,7 +2066,6 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
20562066
return;
20572067
}
20582068

2059-
std::optional<int> LoggedInAuthLevel;
20602069
if(pName[0])
20612070
{
20622071
char aTrimmedName[MAX_NAME_LENGTH];
@@ -2086,79 +2095,20 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
20862095
return;
20872096
}
20882097

2098+
std::optional<EAccessLevel> LoggedInAccessLevel;
20892099
if(g_Config.m_SvRconPassword[0] && str_comp(pPw, g_Config.m_SvRconPassword) == 0)
20902100
{
2091-
LoggedInAuthLevel = AUTHED_ADMIN;
2101+
LoggedInAccessLevel = EAccessLevel::ADMIN;
20922102
}
20932103
else if(g_Config.m_SvRconModPassword[0] && str_comp(pPw, g_Config.m_SvRconModPassword) == 0)
20942104
{
2095-
LoggedInAuthLevel = AUTHED_MOD;
2105+
LoggedInAccessLevel = EAccessLevel::MOD;
20962106
}
20972107

2098-
if(LoggedInAuthLevel.has_value())
2108+
if(LoggedInAccessLevel.has_value())
20992109
{
2100-
if(m_aClients[ClientId].m_Authed != LoggedInAuthLevel.value())
2101-
{
2102-
if(!IsSixup(ClientId))
2103-
{
2104-
CMsgPacker Msgp(NETMSG_RCON_AUTH_STATUS, true);
2105-
Msgp.AddInt(1); // authed
2106-
Msgp.AddInt(1); // cmdlist
2107-
SendMsg(&Msgp, MSGFLAG_VITAL, ClientId);
2108-
}
2109-
else
2110-
{
2111-
CMsgPacker Msgp(protocol7::NETMSG_RCON_AUTH_ON, true, true);
2112-
SendMsg(&Msgp, MSGFLAG_VITAL, ClientId);
2113-
}
2114-
2115-
m_aClients[ClientId].m_Authed = LoggedInAuthLevel.value();
2116-
bool SendRconCmds = IsSixup(ClientId) ? true : (Unpacker.GetInt() > 0);
2117-
if(!Unpacker.Error() && SendRconCmds)
2118-
{
2119-
EAccessLevel ConsoleAccessLevel{};
2120-
switch(LoggedInAuthLevel.value())
2121-
{
2122-
case AUTHED_ADMIN:
2123-
ConsoleAccessLevel = EAccessLevel::ADMIN;
2124-
break;
2125-
case AUTHED_MOD:
2126-
ConsoleAccessLevel = EAccessLevel::MOD;
2127-
break;
2128-
default:
2129-
ConsoleAccessLevel = EAccessLevel::USER;
2130-
break;
2131-
}
2132-
2133-
m_aClients[ClientId].m_pRconCmdToSend = Console()->FirstCommandInfo(ConsoleAccessLevel, CFGFLAG_SERVER);
2134-
}
2135-
2136-
char aBuf[256];
2137-
switch(LoggedInAuthLevel.value())
2138-
{
2139-
case AUTHED_ADMIN:
2140-
{
2141-
SendRconLine(ClientId, "Admin authentication successful. Full remote console access granted.");
2142-
str_format(aBuf, sizeof(aBuf), "ClientId=%d authed (admin)", ClientId);
2143-
break;
2144-
}
2145-
case AUTHED_MOD:
2146-
{
2147-
SendRconLine(ClientId, "Moderator authentication successful. Limited remote console access granted.");
2148-
str_format(aBuf, sizeof(aBuf), "ClientId=%d authed (moderator)", ClientId);
2149-
break;
2150-
}
2151-
case AUTHED_HELPER:
2152-
{
2153-
SendRconLine(ClientId, "Helper authentication successful. Limited remote console access granted.");
2154-
str_format(aBuf, sizeof(aBuf), "ClientId=%d authed (helper)", ClientId);
2155-
break;
2156-
}
2157-
}
2158-
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
2159-
2160-
GameServer()->OnSetAuthed(ClientId, m_aClients[ClientId].m_Authed);
2161-
}
2110+
bool SendRconCmds = IsSixup(ClientId) ? true : (Unpacker.GetInt() > 0);
2111+
SetClientAccessLevel(ClientId, LoggedInAccessLevel.value(), !Unpacker.Error() && SendRconCmds);
21622112
}
21632113
else if(Config()->m_SvRconMaxTries)
21642114
{
@@ -3875,12 +3825,18 @@ void CServer::ConAccounts(IConsole::IResult *pResult)
38753825
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "accounts", " help");
38763826
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "accounts", " status");
38773827
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "accounts", " set_salt [string, at least 3 characters]");
3828+
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "accounts", " set_access_level [user_id number] [0: admin, 1: moderator]");
3829+
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "accounts", " reset_access_level [user_id number]");
3830+
};
3831+
auto InsufficientArguments = [this]() {
3832+
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "accounts", "Insufficient arguments.");
38783833
};
38793834

38803835
const char *pOptionStr = pResult->GetString(0);
38813836
if (!pOptionStr || !pOptionStr[0] || (str_comp(pOptionStr, "status") == 0))
38823837
{
38833838
PrintStatus();
3839+
PrintHelp();
38843840
}
38853841
else if(str_comp(pOptionStr, "help") == 0)
38863842
{
@@ -3902,6 +3858,92 @@ void CServer::ConAccounts(IConsole::IResult *pResult)
39023858
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "accounts", "Error: the salt should be at least 3 characters in length");
39033859
}
39043860
}
3861+
else
3862+
{
3863+
InsufficientArguments();
3864+
PrintHelp();
3865+
}
3866+
}
3867+
else if(str_comp(pOptionStr, "set_access_level") == 0)
3868+
{
3869+
if(pResult->NumArguments() > 2)
3870+
{
3871+
const int UserId = pResult->GetInteger(1);
3872+
const int RawLevel = pResult->GetInteger(2);
3873+
EAccessLevel AccessLevel = static_cast<EAccessLevel>(RawLevel);
3874+
if(RawLevel < 0 || RawLevel > 1)
3875+
{
3876+
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "accounts", "Error: the access level must be a positive number [0: admin, 1: moderator]");
3877+
}
3878+
else if(UserId <= 0)
3879+
{
3880+
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "accounts", "Error: the user id must be a positive number");
3881+
}
3882+
else
3883+
{
3884+
bool Set{};
3885+
for(SAccountAccessInfo &AccountAccessLevel : m_vAccountsAccessInfo)
3886+
{
3887+
if(AccountAccessLevel.UserId == UserId)
3888+
{
3889+
AccountAccessLevel.AccessLevel = AccessLevel;
3890+
Set = true;
3891+
}
3892+
}
3893+
3894+
if(!Set)
3895+
{
3896+
m_vAccountsAccessInfo.push_back({
3897+
.UserId = UserId,
3898+
.AccessLevel = AccessLevel,
3899+
});
3900+
}
3901+
3902+
char aBuf[128];
3903+
str_format(aBuf, sizeof(aBuf), "User %d access level is now set to %s", UserId, toString(AccessLevel));
3904+
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "accounts", aBuf);
3905+
}
3906+
}
3907+
else
3908+
{
3909+
InsufficientArguments();
3910+
PrintHelp();
3911+
}
3912+
}
3913+
else if(str_comp(pOptionStr, "reset_access_level") == 0)
3914+
{
3915+
if(pResult->NumArguments() > 1)
3916+
{
3917+
const int UserId = pResult->GetInteger(1);
3918+
if(UserId <= 0)
3919+
{
3920+
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "accounts", "Error: the user id must be a positive number");
3921+
}
3922+
else
3923+
{
3924+
auto InfoIt = std::find_if(std::begin(m_vAccountsAccessInfo), std::end(m_vAccountsAccessInfo), [UserId](const SAccountAccessInfo &Info) {
3925+
return Info.UserId == UserId;
3926+
});
3927+
if(InfoIt == m_vAccountsAccessInfo.end())
3928+
{
3929+
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "accounts", "The given user didn't have a custom access level");
3930+
}
3931+
else
3932+
{
3933+
EAccessLevel AccessLevel = InfoIt->AccessLevel;
3934+
m_vAccountsAccessInfo.erase(InfoIt);
3935+
3936+
char aBuf[128];
3937+
str_format(aBuf, sizeof(aBuf), "'%s' access revoked from user %d", toString(AccessLevel), UserId);
3938+
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "accounts", aBuf);
3939+
}
3940+
}
3941+
}
3942+
else
3943+
{
3944+
InsufficientArguments();
3945+
PrintHelp();
3946+
}
39053947
}
39063948
else
39073949
{
@@ -4160,7 +4202,7 @@ void CServer::RegisterCommands()
41604202
Console()->Register("logout", "", CFGFLAG_SERVER, ConLogout, this, "Logout of rcon");
41614203
Console()->Register("show_ips", "?i[show]", CFGFLAG_SERVER, ConShowIps, this, "Show IP addresses in rcon commands (1 = on, 0 = off)");
41624204

4163-
Console()->Register("accounts", "?s[command] ?s[arg1]", CFGFLAG_SERVER, ConAccounts, this, "Manage accounts");
4205+
Console()->Register("accounts", "?s[command] ?s[arg1] ?s[arg2]", CFGFLAG_SERVER, ConAccounts, this, "Manage accounts");
41644206

41654207
Console()->Register("record", "?s[file]", CFGFLAG_SERVER | CFGFLAG_STORE, ConRecord, this, "Record to a file");
41664208
Console()->Register("stoprecord", "", CFGFLAG_SERVER, ConStopRecord, this, "Stop recording");
@@ -6209,6 +6251,75 @@ void CServer::TakeUserName(int ClientId)
62096251
}
62106252
}
62116253

6254+
int toAuthed(EAccessLevel AccessLevel)
6255+
{
6256+
switch(AccessLevel)
6257+
{
6258+
case EAccessLevel::ADMIN:
6259+
return AUTHED_ADMIN;
6260+
case EAccessLevel::MOD:
6261+
return AUTHED_MOD;
6262+
case EAccessLevel::HELPER:
6263+
return AUTHED_HELPER;
6264+
case EAccessLevel::USER:
6265+
break;
6266+
}
6267+
6268+
return AUTHED_NO;
6269+
}
6270+
6271+
void CServer::SetClientAccessLevel(int ClientId, EAccessLevel AccessLevel, bool SendRconCmds)
6272+
{
6273+
int Authed = toAuthed(AccessLevel);
6274+
if(m_aClients[ClientId].m_Authed == Authed)
6275+
return;
6276+
6277+
if(AccessLevel > EAccessLevel::MOD)
6278+
{
6279+
return;
6280+
}
6281+
6282+
if(!IsSixup(ClientId))
6283+
{
6284+
CMsgPacker Msgp(NETMSG_RCON_AUTH_STATUS, true);
6285+
Msgp.AddInt(1); // authed
6286+
Msgp.AddInt(1); // cmdlist
6287+
SendMsg(&Msgp, MSGFLAG_VITAL, ClientId);
6288+
}
6289+
else
6290+
{
6291+
CMsgPacker Msgp(protocol7::NETMSG_RCON_AUTH_ON, true, true);
6292+
SendMsg(&Msgp, MSGFLAG_VITAL, ClientId);
6293+
}
6294+
6295+
m_aClients[ClientId].m_Authed = Authed;
6296+
if(SendRconCmds)
6297+
{
6298+
m_aClients[ClientId].m_pRconCmdToSend = Console()->FirstCommandInfo(AccessLevel, CFGFLAG_SERVER);
6299+
}
6300+
6301+
char aBuf[256];
6302+
switch(AccessLevel)
6303+
{
6304+
case EAccessLevel::ADMIN:
6305+
SendRconLine(ClientId, "Admin authentication successful. Full remote console access granted.");
6306+
break;
6307+
case EAccessLevel::MOD:
6308+
SendRconLine(ClientId, "Moderator authentication successful. Limited remote console access granted.");
6309+
break;
6310+
case EAccessLevel::HELPER:
6311+
SendRconLine(ClientId, "Helper authentication successful. Limited remote console access granted.");
6312+
break;
6313+
case EAccessLevel::USER:
6314+
break;
6315+
}
6316+
6317+
str_format(aBuf, sizeof(aBuf), "ClientId=%d authed (%s)", ClientId, toString(AccessLevel));
6318+
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
6319+
6320+
GameServer()->OnSetAuthed(ClientId, m_aClients[ClientId].m_Authed);
6321+
}
6322+
62126323
void CServer::SetErrorShutdown(const char *pReason)
62136324
{
62146325
str_copy(m_aErrorShutdownReason, pReason);

src/engine/server/server.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636

3737
class CLogMessage;
3838

39+
enum class EAccessLevel;
40+
3941
class CSnapIdPool
4042
{
4143
enum
@@ -546,6 +548,8 @@ class CServer : public IServer
546548
std::optional<int> GetClientIdByUserId(int UserId) const;
547549
void TakeUserName(int ClientId);
548550

551+
void SetClientAccessLevel(int ClientId, EAccessLevel AccessLevel, bool SendRconCmds);
552+
549553
public:
550554
class CGameServerCmd
551555
{
@@ -565,6 +569,14 @@ class CServer : public IServer
565569
CClientAccountRequests m_AccountsRequests[MAX_CLIENTS];
566570
char m_aServerSalt[ServerSaltMaxLength]{};
567571

572+
struct SAccountAccessInfo
573+
{
574+
int UserId{};
575+
EAccessLevel AccessLevel{};
576+
};
577+
578+
std::vector<SAccountAccessInfo> m_vAccountsAccessInfo;
579+
568580
#ifdef CONF_SQL
569581
public:
570582
array<CGameServerCmd*> m_lGameServerCmds;

0 commit comments

Comments
 (0)