Merge pull request #7580 from Robyt3/Message-Unpack-Check

Add missing unpacker error checks for server and client packets
This commit is contained in:
heinrich5991 2023-12-05 19:01:33 +00:00 committed by GitHub
commit 801274ac63
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 228 additions and 184 deletions

View file

@ -1329,7 +1329,6 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
SHA256_DIGEST *pMapSha256 = (SHA256_DIGEST *)Unpacker.GetRaw(sizeof(*pMapSha256));
int MapCrc = Unpacker.GetInt();
int MapSize = Unpacker.GetInt();
if(Unpacker.Error())
{
return;
@ -1356,7 +1355,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
}
int Version = Unpacker.GetInt();
int Flags = Unpacker.GetInt();
if(Version <= 0)
if(Unpacker.Error() || Version <= 0)
{
return;
}
@ -1377,85 +1376,82 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
const char *pMap = Unpacker.GetString(CUnpacker::SANITIZE_CC | CUnpacker::SKIP_START_WHITESPACES);
int MapCrc = Unpacker.GetInt();
int MapSize = Unpacker.GetInt();
const char *pError = 0;
if(Unpacker.Error())
if(Unpacker.Error() || MapSize < 0)
{
return;
if(m_DummyConnected)
DummyDisconnect(0);
}
for(int i = 0; pMap[i]; i++) // protect the player from nasty map names
{
if(pMap[i] == '/' || pMap[i] == '\\')
pError = "strange character in map name";
{
return;
}
}
if(MapSize < 0)
pError = "invalid map size";
if(m_DummyConnected)
{
DummyDisconnect(0);
}
if(pError)
DisconnectWithReason(pError);
SHA256_DIGEST *pMapSha256 = nullptr;
const char *pMapUrl = nullptr;
if(MapDetailsWerePresent && str_comp(m_aMapDetailsName, pMap) == 0 && m_MapDetailsCrc == MapCrc)
{
pMapSha256 = &m_MapDetailsSha256;
pMapUrl = m_aMapDetailsUrl[0] ? m_aMapDetailsUrl : nullptr;
}
if(LoadMapSearch(pMap, pMapSha256, MapCrc) != nullptr)
{
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "loading done");
SetLoadingStateDetail(IClient::LOADING_STATE_DETAIL_SENDING_READY);
SendReady(CONN_MAIN);
}
else
{
SHA256_DIGEST *pMapSha256 = 0;
const char *pMapUrl = nullptr;
if(MapDetailsWerePresent && str_comp(m_aMapDetailsName, pMap) == 0 && m_MapDetailsCrc == MapCrc)
if(m_MapdownloadFileTemp)
{
pMapSha256 = &m_MapDetailsSha256;
pMapUrl = m_aMapDetailsUrl[0] ? m_aMapDetailsUrl : nullptr;
io_close(m_MapdownloadFileTemp);
Storage()->RemoveFile(m_aMapdownloadFilenameTemp, IStorage::TYPE_SAVE);
}
pError = LoadMapSearch(pMap, pMapSha256, MapCrc);
if(!pError)
// start map download
FormatMapDownloadFilename(pMap, pMapSha256, MapCrc, false, m_aMapdownloadFilename, sizeof(m_aMapdownloadFilename));
FormatMapDownloadFilename(pMap, pMapSha256, MapCrc, true, m_aMapdownloadFilenameTemp, sizeof(m_aMapdownloadFilenameTemp));
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "starting to download map to '%s'", m_aMapdownloadFilenameTemp);
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", aBuf);
m_MapdownloadChunk = 0;
str_copy(m_aMapdownloadName, pMap);
m_MapdownloadSha256Present = (bool)pMapSha256;
m_MapdownloadSha256 = pMapSha256 ? *pMapSha256 : SHA256_ZEROED;
m_MapdownloadCrc = MapCrc;
m_MapdownloadTotalsize = MapSize;
m_MapdownloadAmount = 0;
ResetMapDownload();
if(pMapSha256)
{
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "loading done");
SetLoadingStateDetail(IClient::LOADING_STATE_DETAIL_SENDING_READY);
SendReady(CONN_MAIN);
char aUrl[256];
char aEscaped[256];
EscapeUrl(aEscaped, sizeof(aEscaped), m_aMapdownloadFilename + 15); // cut off downloadedmaps/
bool UseConfigUrl = str_comp(g_Config.m_ClMapDownloadUrl, "https://maps.ddnet.org") != 0 || m_aMapDownloadUrl[0] == '\0';
str_format(aUrl, sizeof(aUrl), "%s/%s", UseConfigUrl ? g_Config.m_ClMapDownloadUrl : m_aMapDownloadUrl, aEscaped);
m_pMapdownloadTask = HttpGetFile(pMapUrl ? pMapUrl : aUrl, Storage(), m_aMapdownloadFilenameTemp, IStorage::TYPE_SAVE);
m_pMapdownloadTask->Timeout(CTimeout{g_Config.m_ClMapDownloadConnectTimeoutMs, 0, g_Config.m_ClMapDownloadLowSpeedLimit, g_Config.m_ClMapDownloadLowSpeedTime});
m_pMapdownloadTask->MaxResponseSize(1024 * 1024 * 1024); // 1 GiB
m_pMapdownloadTask->ExpectSha256(*pMapSha256);
Engine()->AddJob(m_pMapdownloadTask);
}
else
{
if(m_MapdownloadFileTemp)
{
io_close(m_MapdownloadFileTemp);
Storage()->RemoveFile(m_aMapdownloadFilenameTemp, IStorage::TYPE_SAVE);
}
// start map download
FormatMapDownloadFilename(pMap, pMapSha256, MapCrc, false, m_aMapdownloadFilename, sizeof(m_aMapdownloadFilename));
FormatMapDownloadFilename(pMap, pMapSha256, MapCrc, true, m_aMapdownloadFilenameTemp, sizeof(m_aMapdownloadFilenameTemp));
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "starting to download map to '%s'", m_aMapdownloadFilenameTemp);
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", aBuf);
m_MapdownloadChunk = 0;
str_copy(m_aMapdownloadName, pMap);
m_MapdownloadSha256Present = (bool)pMapSha256;
m_MapdownloadSha256 = pMapSha256 ? *pMapSha256 : SHA256_ZEROED;
m_MapdownloadCrc = MapCrc;
m_MapdownloadTotalsize = MapSize;
m_MapdownloadAmount = 0;
ResetMapDownload();
if(pMapSha256)
{
char aUrl[256];
char aEscaped[256];
EscapeUrl(aEscaped, sizeof(aEscaped), m_aMapdownloadFilename + 15); // cut off downloadedmaps/
bool UseConfigUrl = str_comp(g_Config.m_ClMapDownloadUrl, "https://maps.ddnet.org") != 0 || m_aMapDownloadUrl[0] == '\0';
str_format(aUrl, sizeof(aUrl), "%s/%s", UseConfigUrl ? g_Config.m_ClMapDownloadUrl : m_aMapDownloadUrl, aEscaped);
m_pMapdownloadTask = HttpGetFile(pMapUrl ? pMapUrl : aUrl, Storage(), m_aMapdownloadFilenameTemp, IStorage::TYPE_SAVE);
m_pMapdownloadTask->Timeout(CTimeout{g_Config.m_ClMapDownloadConnectTimeoutMs, 0, g_Config.m_ClMapDownloadLowSpeedLimit, g_Config.m_ClMapDownloadLowSpeedTime});
m_pMapdownloadTask->MaxResponseSize(1024 * 1024 * 1024); // 1 GiB
m_pMapdownloadTask->ExpectSha256(*pMapSha256);
Engine()->AddJob(m_pMapdownloadTask);
}
else
SendMapRequest();
SendMapRequest();
}
}
}
@ -1466,10 +1462,10 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
int Chunk = Unpacker.GetInt();
int Size = Unpacker.GetInt();
const unsigned char *pData = Unpacker.GetRaw(Size);
// check for errors
if(Unpacker.Error() || Size <= 0 || MapCRC != m_MapdownloadCrc || Chunk != m_MapdownloadChunk || !m_MapdownloadFileTemp)
{
return;
}
io_write(m_MapdownloadFileTemp, pData, Size);
@ -1566,6 +1562,10 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
else if(Msg == NETMSG_REDIRECT)
{
int RedirectPort = Unpacker.GetInt();
if(Unpacker.Error())
{
return;
}
char aAddr[128];
char aIP[64];
NETADDR ServerAddr = ServerAddress();
@ -1578,35 +1578,47 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
const char *pName = Unpacker.GetString(CUnpacker::SANITIZE_CC);
const char *pHelp = Unpacker.GetString(CUnpacker::SANITIZE_CC);
const char *pParams = Unpacker.GetString(CUnpacker::SANITIZE_CC);
if(Unpacker.Error() == 0)
if(!Unpacker.Error())
{
m_pConsole->RegisterTemp(pName, pParams, CFGFLAG_SERVER, pHelp);
}
}
else if(Conn == CONN_MAIN && (pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_CMD_REM)
{
const char *pName = Unpacker.GetString(CUnpacker::SANITIZE_CC);
if(Unpacker.Error() == 0)
if(!Unpacker.Error())
{
m_pConsole->DeregisterTemp(pName);
}
}
else if((pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_AUTH_STATUS)
{
int ResultInt = Unpacker.GetInt();
if(Unpacker.Error() == 0)
if(!Unpacker.Error())
{
m_aRconAuthed[Conn] = ResultInt;
}
if(Conn == CONN_MAIN)
{
int Old = m_UseTempRconCommands;
m_UseTempRconCommands = Unpacker.GetInt();
if(Unpacker.Error() != 0)
if(Unpacker.Error())
{
m_UseTempRconCommands = 0;
}
if(Old != 0 && m_UseTempRconCommands == 0)
{
m_pConsole->DeregisterTempAll();
}
}
}
else if(!Dummy && (pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_LINE)
{
const char *pLine = Unpacker.GetString();
if(Unpacker.Error() == 0)
if(!Unpacker.Error())
{
GameClient()->OnRconLine(pLine);
}
}
else if(Conn == CONN_MAIN && Msg == NETMSG_PING_REPLY)
{
@ -1618,6 +1630,11 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
{
int InputPredTick = Unpacker.GetInt();
int TimeLeft = Unpacker.GetInt();
if(Unpacker.Error())
{
return;
}
int64_t Now = time_get();
// adjust our prediction time
@ -1637,16 +1654,20 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
}
else if(Msg == NETMSG_SNAP || Msg == NETMSG_SNAPSINGLE || Msg == NETMSG_SNAPEMPTY)
{
int GameTick = Unpacker.GetInt();
int DeltaTick = GameTick - Unpacker.GetInt();
// only allow packets from the server we actually want
if(net_addr_comp(&pPacket->m_Address, &ServerAddress()))
{
return;
}
// we are not allowed to process snapshot yet
if(State() < IClient::STATE_LOADING)
{
return;
}
int GameTick = Unpacker.GetInt();
int DeltaTick = GameTick - Unpacker.GetInt();
int NumParts = 1;
int Part = 0;
@ -1665,9 +1686,10 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
}
const char *pData = (const char *)Unpacker.GetRaw(PartSize);
if(Unpacker.Error() || NumParts < 1 || NumParts > CSnapshot::MAX_PARTS || Part < 0 || Part >= NumParts || PartSize < 0 || PartSize > MAX_SNAPSHOT_PACKSIZE)
{
return;
}
// Check m_aAckGameTick to see if we already got a snapshot for that tick
if(GameTick >= m_aCurrentRecvTick[Conn] && GameTick > m_aAckGameTick[Conn])
@ -1917,23 +1939,23 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
else if(Conn == CONN_MAIN && Msg == NETMSG_RCONTYPE)
{
bool UsernameReq = Unpacker.GetInt() & 1;
GameClient()->OnRconType(UsernameReq);
if(!Unpacker.Error())
{
GameClient()->OnRconType(UsernameReq);
}
}
}
else
else if((pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0)
{
if((pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0)
// game message
if(!Dummy)
{
// game message
if(!Dummy)
{
for(auto &DemoRecorder : m_aDemoRecorder)
if(DemoRecorder.IsRecording())
DemoRecorder.RecordMessage(pPacket->m_pData, pPacket->m_DataSize);
}
GameClient()->OnMessage(Msg, &Unpacker, Conn, Dummy);
for(auto &DemoRecorder : m_aDemoRecorder)
if(DemoRecorder.IsRecording())
DemoRecorder.RecordMessage(pPacket->m_pData, pPacket->m_DataSize);
}
GameClient()->OnMessage(Msg, &Unpacker, Conn, Dummy);
}
}

View file

@ -1540,7 +1540,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
CUuid *pConnectionID = (CUuid *)Unpacker.GetRaw(sizeof(*pConnectionID));
int DDNetVersion = Unpacker.GetInt();
const char *pDDNetVersionStr = Unpacker.GetString(CUnpacker::SANITIZE_CC);
if(Unpacker.Error() || !str_utf8_check(pDDNetVersionStr) || DDNetVersion < 0)
if(Unpacker.Error() || DDNetVersion < 0)
{
return;
}
@ -1557,7 +1557,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
if((pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && (m_aClients[ClientID].m_State == CClient::STATE_PREAUTH || m_aClients[ClientID].m_State == CClient::STATE_AUTH))
{
const char *pVersion = Unpacker.GetString(CUnpacker::SANITIZE_CC);
if(!str_utf8_check(pVersion))
if(Unpacker.Error())
{
return;
}
@ -1571,7 +1571,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
}
const char *pPassword = Unpacker.GetString(CUnpacker::SANITIZE_CC);
if(!str_utf8_check(pPassword))
if(Unpacker.Error())
{
return;
}
@ -1610,6 +1610,10 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
}
int Chunk = Unpacker.GetInt();
if(Unpacker.Error())
{
return;
}
if(Chunk != m_aClients[ClientID].m_NextMapChunk || !Config()->m_SvFastDownload)
{
SendMapData(ClientID, Chunk);
@ -1675,14 +1679,15 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
}
else if(Msg == NETMSG_INPUT)
{
m_aClients[ClientID].m_LastAckedSnapshot = Unpacker.GetInt();
const int LastAckedSnapshot = Unpacker.GetInt();
int IntendedTick = Unpacker.GetInt();
int Size = Unpacker.GetInt();
// check for errors
if(Unpacker.Error() || Size / 4 > MAX_INPUT_SIZE || IntendedTick < MIN_TICK || IntendedTick >= MAX_TICK)
{
return;
}
m_aClients[ClientID].m_LastAckedSnapshot = LastAckedSnapshot;
if(m_aClients[ClientID].m_LastAckedSnapshot > 0)
m_aClients[ClientID].m_SnapRate = CClient::SNAPRATE_FULL;
@ -1712,7 +1717,13 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
pInput->m_GameTick = IntendedTick;
for(int i = 0; i < Size / 4; i++)
{
pInput->m_aData[i] = Unpacker.GetInt();
}
if(Unpacker.Error())
{
return;
}
GameServer()->OnClientPrepareInput(ClientID, pInput->m_aData);
mem_copy(m_aClients[ClientID].m_LatestInput.m_aData, pInput->m_aData, MAX_INPUT_SIZE * sizeof(int));
@ -1727,11 +1738,11 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
else if(Msg == NETMSG_RCON_CMD)
{
const char *pCmd = Unpacker.GetString();
if(!str_utf8_check(pCmd))
if(Unpacker.Error())
{
return;
}
if(Unpacker.Error() == 0 && !str_comp(pCmd, "crashmeplx"))
if(!str_comp(pCmd, "crashmeplx"))
{
int Version = m_aClients[ClientID].m_DDNetVersion;
if(GameServer()->PlayerExists(ClientID) && Version < VERSION_DDNET_OLD)
@ -1739,7 +1750,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
m_aClients[ClientID].m_DDNetVersion = VERSION_DDNET_OLD;
}
}
else if((pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && Unpacker.Error() == 0 && m_aClients[ClientID].m_Authed)
else if((pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && m_aClients[ClientID].m_Authed)
{
if(GameServer()->PlayerExists(ClientID))
{
@ -1762,108 +1773,113 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
}
else if(Msg == NETMSG_RCON_AUTH)
{
if((pPacket->m_Flags & NET_CHUNKFLAG_VITAL) == 0)
{
return;
}
const char *pName = "";
if(!IsSixup(ClientID))
{
pName = Unpacker.GetString(CUnpacker::SANITIZE_CC); // login name, now used
}
const char *pPw = Unpacker.GetString(CUnpacker::SANITIZE_CC);
if(!str_utf8_check(pPw) || !str_utf8_check(pName))
if(Unpacker.Error())
{
return;
}
if((pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && Unpacker.Error() == 0)
int AuthLevel = -1;
int KeySlot = -1;
if(!pName[0])
{
int AuthLevel = -1;
int KeySlot = -1;
if(m_AuthManager.CheckKey((KeySlot = m_AuthManager.DefaultKey(AUTHED_ADMIN)), pPw))
AuthLevel = AUTHED_ADMIN;
else if(m_AuthManager.CheckKey((KeySlot = m_AuthManager.DefaultKey(AUTHED_MOD)), pPw))
AuthLevel = AUTHED_MOD;
else if(m_AuthManager.CheckKey((KeySlot = m_AuthManager.DefaultKey(AUTHED_HELPER)), pPw))
AuthLevel = AUTHED_HELPER;
}
else
{
KeySlot = m_AuthManager.FindKey(pName);
if(m_AuthManager.CheckKey(KeySlot, pPw))
AuthLevel = m_AuthManager.KeyLevel(KeySlot);
}
if(!pName[0])
if(AuthLevel != -1)
{
if(m_aClients[ClientID].m_Authed != AuthLevel)
{
if(m_AuthManager.CheckKey((KeySlot = m_AuthManager.DefaultKey(AUTHED_ADMIN)), pPw))
AuthLevel = AUTHED_ADMIN;
else if(m_AuthManager.CheckKey((KeySlot = m_AuthManager.DefaultKey(AUTHED_MOD)), pPw))
AuthLevel = AUTHED_MOD;
else if(m_AuthManager.CheckKey((KeySlot = m_AuthManager.DefaultKey(AUTHED_HELPER)), pPw))
AuthLevel = AUTHED_HELPER;
}
else
{
KeySlot = m_AuthManager.FindKey(pName);
if(m_AuthManager.CheckKey(KeySlot, pPw))
AuthLevel = m_AuthManager.KeyLevel(KeySlot);
}
if(AuthLevel != -1)
{
if(m_aClients[ClientID].m_Authed != AuthLevel)
if(!IsSixup(ClientID))
{
if(!IsSixup(ClientID))
{
CMsgPacker Msgp(NETMSG_RCON_AUTH_STATUS, true);
Msgp.AddInt(1); //authed
Msgp.AddInt(1); //cmdlist
SendMsg(&Msgp, MSGFLAG_VITAL, ClientID);
}
else
{
CMsgPacker Msgp(protocol7::NETMSG_RCON_AUTH_ON, true, true);
SendMsg(&Msgp, MSGFLAG_VITAL, ClientID);
}
m_aClients[ClientID].m_Authed = AuthLevel; // Keeping m_Authed around is unwise...
m_aClients[ClientID].m_AuthKey = KeySlot;
int SendRconCmds = IsSixup(ClientID) ? true : Unpacker.GetInt();
if(Unpacker.Error() == 0 && SendRconCmds)
// AUTHED_ADMIN - AuthLevel gets the proper IConsole::ACCESS_LEVEL_<x>
m_aClients[ClientID].m_pRconCmdToSend = Console()->FirstCommandInfo(AUTHED_ADMIN - AuthLevel, CFGFLAG_SERVER);
char aBuf[256];
const char *pIdent = m_AuthManager.KeyIdent(KeySlot);
switch(AuthLevel)
{
case AUTHED_ADMIN:
{
SendRconLine(ClientID, "Admin authentication successful. Full remote console access granted.");
str_format(aBuf, sizeof(aBuf), "ClientID=%d authed with key=%s (admin)", ClientID, pIdent);
break;
}
case AUTHED_MOD:
{
SendRconLine(ClientID, "Moderator authentication successful. Limited remote console access granted.");
str_format(aBuf, sizeof(aBuf), "ClientID=%d authed with key=%s (moderator)", ClientID, pIdent);
break;
}
case AUTHED_HELPER:
{
SendRconLine(ClientID, "Helper authentication successful. Limited remote console access granted.");
str_format(aBuf, sizeof(aBuf), "ClientID=%d authed with key=%s (helper)", ClientID, pIdent);
break;
}
}
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
// DDRace
GameServer()->OnSetAuthed(ClientID, AuthLevel);
CMsgPacker Msgp(NETMSG_RCON_AUTH_STATUS, true);
Msgp.AddInt(1); //authed
Msgp.AddInt(1); //cmdlist
SendMsg(&Msgp, MSGFLAG_VITAL, ClientID);
}
}
else if(Config()->m_SvRconMaxTries)
{
m_aClients[ClientID].m_AuthTries++;
char aBuf[128];
str_format(aBuf, sizeof(aBuf), "Wrong password %d/%d.", m_aClients[ClientID].m_AuthTries, Config()->m_SvRconMaxTries);
SendRconLine(ClientID, aBuf);
if(m_aClients[ClientID].m_AuthTries >= Config()->m_SvRconMaxTries)
else
{
if(!Config()->m_SvRconBantime)
m_NetServer.Drop(ClientID, "Too many remote console authentication tries");
else
m_ServerBan.BanAddr(m_NetServer.ClientAddr(ClientID), Config()->m_SvRconBantime * 60, "Too many remote console authentication tries");
CMsgPacker Msgp(protocol7::NETMSG_RCON_AUTH_ON, true, true);
SendMsg(&Msgp, MSGFLAG_VITAL, ClientID);
}
m_aClients[ClientID].m_Authed = AuthLevel; // Keeping m_Authed around is unwise...
m_aClients[ClientID].m_AuthKey = KeySlot;
int SendRconCmds = IsSixup(ClientID) ? true : Unpacker.GetInt();
if(!Unpacker.Error() && SendRconCmds)
{
// AUTHED_ADMIN - AuthLevel gets the proper IConsole::ACCESS_LEVEL_<x>
m_aClients[ClientID].m_pRconCmdToSend = Console()->FirstCommandInfo(AUTHED_ADMIN - AuthLevel, CFGFLAG_SERVER);
}
char aBuf[256];
const char *pIdent = m_AuthManager.KeyIdent(KeySlot);
switch(AuthLevel)
{
case AUTHED_ADMIN:
{
SendRconLine(ClientID, "Admin authentication successful. Full remote console access granted.");
str_format(aBuf, sizeof(aBuf), "ClientID=%d authed with key=%s (admin)", ClientID, pIdent);
break;
}
case AUTHED_MOD:
{
SendRconLine(ClientID, "Moderator authentication successful. Limited remote console access granted.");
str_format(aBuf, sizeof(aBuf), "ClientID=%d authed with key=%s (moderator)", ClientID, pIdent);
break;
}
case AUTHED_HELPER:
{
SendRconLine(ClientID, "Helper authentication successful. Limited remote console access granted.");
str_format(aBuf, sizeof(aBuf), "ClientID=%d authed with key=%s (helper)", ClientID, pIdent);
break;
}
}
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
// DDRace
GameServer()->OnSetAuthed(ClientID, AuthLevel);
}
else
}
else if(Config()->m_SvRconMaxTries)
{
m_aClients[ClientID].m_AuthTries++;
char aBuf[128];
str_format(aBuf, sizeof(aBuf), "Wrong password %d/%d.", m_aClients[ClientID].m_AuthTries, Config()->m_SvRconMaxTries);
SendRconLine(ClientID, aBuf);
if(m_aClients[ClientID].m_AuthTries >= Config()->m_SvRconMaxTries)
{
SendRconLine(ClientID, "Wrong password.");
if(!Config()->m_SvRconBantime)
m_NetServer.Drop(ClientID, "Too many remote console authentication tries");
else
m_ServerBan.BanAddr(m_NetServer.ClientAddr(ClientID), Config()->m_SvRconBantime * 60, "Too many remote console authentication tries");
}
}
else
{
SendRconLine(ClientID, "Wrong password.");
}
}
else if(Msg == NETMSG_PING)
{
@ -1896,11 +1912,10 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
}
}
}
else
else if((pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && m_aClients[ClientID].m_State >= CClient::STATE_READY)
{
// game message
if((pPacket->m_Flags & NET_CHUNKFLAG_VITAL) != 0 && m_aClients[ClientID].m_State >= CClient::STATE_READY)
GameServer()->OnMessage(Msg, &Unpacker, ClientID);
GameServer()->OnMessage(Msg, &Unpacker, ClientID);
}
}
@ -2491,13 +2506,14 @@ void CServer::PumpNetwork(bool PacketWaiting)
Unpacker.Reset((unsigned char *)Packet.m_pData + sizeof(SERVERBROWSE_GETINFO), Packet.m_DataSize - sizeof(SERVERBROWSE_GETINFO));
int SrvBrwsToken = Unpacker.GetInt();
if(Unpacker.Error())
{
continue;
}
CPacker Packer;
CNetChunk Response;
GetServerInfoSixup(&Packer, SrvBrwsToken, RateLimitServerInfoConnless());
CNetChunk Response;
Response.m_ClientID = -1;
Response.m_Address = Packet.m_Address;
Response.m_Flags = NETSENDFLAG_CONNLESS;

View file

@ -172,6 +172,12 @@ const char *CUnpacker::GetString(int SanitizeType)
}
m_pCurrent++;
if(!str_utf8_check(pPtr))
{
m_Error = true;
return "";
}
// sanitize all strings
if(SanitizeType & SANITIZE)
str_sanitize(pPtr);