diff options
| author | oy <Tom_Adams@web.de> | 2015-03-19 09:57:47 +0100 |
|---|---|---|
| committer | Learath <learath2@gmail.com> | 2018-08-20 15:27:59 +0300 |
| commit | 3f3abebebf20e8901376b929e2afcc6bdb404a3b (patch) | |
| tree | 6e8f5c8c46f73487d62fa3e12ff89e969d0ea8e8 | |
| parent | fc6d8b4d154049e6e3d6df9039669580f8ff747c (diff) | |
| download | zcatch-3f3abebebf20e8901376b929e2afcc6bdb404a3b.tar.gz zcatch-3f3abebebf20e8901376b929e2afcc6bdb404a3b.zip | |
force vital check on essential cl/srv messages and added additional sequence checking
| -rw-r--r-- | src/engine/client/client.cpp | 25 | ||||
| -rw-r--r-- | src/engine/server/server.cpp | 97 | ||||
| -rw-r--r-- | src/engine/shared/network.cpp | 2 | ||||
| -rw-r--r-- | src/engine/shared/network.h | 1 | ||||
| -rw-r--r-- | src/engine/shared/network_conn.cpp | 14 | ||||
| -rw-r--r-- | src/game/server/entities/character.cpp | 6 |
6 files changed, 81 insertions, 64 deletions
diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 30f92eb0..b58b1b5a 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -1027,7 +1027,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) if(Sys) { // system message - if(Msg == NETMSG_MAP_CHANGE) + if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_MAP_CHANGE) { const char *pMap = Unpacker.GetString(CUnpacker::SANITIZE_CC|CUnpacker::SKIP_START_WHITESPACES); int MapCrc = Unpacker.GetInt(); @@ -1090,7 +1090,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) } } } - else if(Msg == NETMSG_MAP_DATA) + else if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_MAP_DATA) { int Last = Unpacker.GetInt(); int MapCRC = Unpacker.GetInt(); @@ -1144,7 +1144,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) } } } - else if(Msg == NETMSG_CON_READY) + else if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_CON_READY) { GameClient()->OnConnected(); } @@ -1153,7 +1153,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) CMsgPacker Msg(NETMSG_PING_REPLY); SendMsgEx(&Msg, 0); } - else if(Msg == NETMSG_RCON_CMD_ADD) + else if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_CMD_ADD) { const char *pName = Unpacker.GetString(CUnpacker::SANITIZE_CC); const char *pHelp = Unpacker.GetString(CUnpacker::SANITIZE_CC); @@ -1161,13 +1161,13 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) if(Unpacker.Error() == 0) m_pConsole->RegisterTemp(pName, pParams, CFGFLAG_SERVER, pHelp); } - else if(Msg == NETMSG_RCON_CMD_REM) + else if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_CMD_REM) { const char *pName = Unpacker.GetString(CUnpacker::SANITIZE_CC); if(Unpacker.Error() == 0) m_pConsole->DeregisterTemp(pName); } - else if(Msg == NETMSG_RCON_AUTH_STATUS) + else if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_AUTH_STATUS) { int Result = Unpacker.GetInt(); if(Unpacker.Error() == 0) @@ -1179,7 +1179,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) if(Old != 0 && m_UseTempRconCommands == 0) m_pConsole->DeregisterTempAll(); } - else if(Msg == NETMSG_RCON_LINE) + else if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Msg == NETMSG_RCON_LINE) { const char *pLine = Unpacker.GetString(); if(Unpacker.Error() == 0) @@ -1401,11 +1401,14 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket) } else { - // game message - if(m_DemoRecorder.IsRecording()) - m_DemoRecorder.RecordMessage(pPacket->m_pData, pPacket->m_DataSize); + if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0) + { + // game message + if(m_DemoRecorder.IsRecording()) + m_DemoRecorder.RecordMessage(pPacket->m_pData, pPacket->m_DataSize); - GameClient()->OnMessage(Msg, &Unpacker); + GameClient()->OnMessage(Msg, &Unpacker); + } } } diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index f4adb967..6bcffae3 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -271,7 +271,7 @@ void CServerBan::ConBanExt(IConsole::IResult *pResult, void *pUser) const char *pStr = pResult->GetString(0); int Minutes = pResult->NumArguments()>1 ? clamp(pResult->GetInteger(1), 0, 44640) : defaultMinutes; const char *pReason = pResult->NumArguments()>2 ? pResult->GetString(2) : "No reason given"; - + // check if time was given or a reason instead const char *time; if(pResult->NumArguments() > 1) @@ -360,14 +360,14 @@ CServer::CServer() : m_DemoRecorder(&m_SnapshotDelta) m_RconClientID = IServer::RCON_CID_SERV; m_RconAuthLevel = AUTHED_SUBADMIN; - + // when starting there are no admins m_numLoggedInAdmins = 0; - + m_Votebans = NULL; m_InfoTexts = NULL; m_InfoTextInterval = -1; - + Init(); } @@ -380,7 +380,7 @@ CServer::~CServer() delete m_Votebans; m_Votebans = tmp; } - + // delte info texts while(m_InfoTexts != NULL) { @@ -834,10 +834,10 @@ int CServer::DelClientCallback(int ClientID, const char *pReason, void *pUser) pThis->m_aClients[ClientID].m_AuthTries = 0; pThis->m_aClients[ClientID].m_pRconCmdToSend = 0; pThis->m_aClients[ClientID].m_Snapshots.PurgeAll(); - + // could have been an admin pThis->UpdateLoggedInAdmins(); - + return 0; } @@ -931,7 +931,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) // system message if(Msg == NETMSG_INFO) { - if(m_aClients[ClientID].m_State == CClient::STATE_AUTH) + if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && m_aClients[ClientID].m_State == CClient::STATE_AUTH) { const char *pVersion = Unpacker.GetString(CUnpacker::SANITIZE_CC); if(str_comp(pVersion, GameServer()->NetVersion()) != 0) @@ -957,7 +957,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) } else if(Msg == NETMSG_REQUEST_MAP_DATA) { - if(m_aClients[ClientID].m_State < CClient::STATE_CONNECTING) + if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) == 0 || m_aClients[ClientID].m_State < CClient::STATE_CONNECTING) return; int Chunk = Unpacker.GetInt(); @@ -994,7 +994,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) } else if(Msg == NETMSG_READY) { - if(m_aClients[ClientID].m_State == CClient::STATE_CONNECTING) + if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && m_aClients[ClientID].m_State == CClient::STATE_CONNECTING) { char aAddrStr[NETADDR_MAXSTRSIZE]; net_addr_str(m_NetServer.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true); @@ -1009,7 +1009,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) } else if(Msg == NETMSG_ENTERGAME) { - if(m_aClients[ClientID].m_State == CClient::STATE_READY && GameServer()->IsClientReady(ClientID)) + if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && m_aClients[ClientID].m_State == CClient::STATE_READY && GameServer()->IsClientReady(ClientID)) { char aAddrStr[NETADDR_MAXSTRSIZE]; net_addr_str(m_NetServer.ClientAddr(ClientID), aAddrStr, sizeof(aAddrStr), true); @@ -1077,12 +1077,12 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) { const char *pCmd = Unpacker.GetString(); - if(Unpacker.Error() == 0 && m_aClients[ClientID].m_Authed) + if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Unpacker.Error() == 0 && m_aClients[ClientID].m_Authed) { - + // try to find first space const char *delimiter = strchr(pCmd, ' '); - + if(m_aClients[ClientID].m_Authed != AUTHED_SUBADMIN || ( m_aClients[ClientID].m_Authed == AUTHED_SUBADMIN @@ -1122,7 +1122,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) const char *pPw; Unpacker.GetString(); // login name, not used pPw = Unpacker.GetString(CUnpacker::SANITIZE_CC); - + // try matching username:password login const char *delimiter = strchr(pPw, ':'); std::string username, password; @@ -1133,8 +1133,8 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) username.assign(pPw, delimiter - pPw); password.assign(delimiter + 1); } - - if(Unpacker.Error() == 0) + + if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && Unpacker.Error() == 0) { if(g_Config.m_SvRconPassword[0] == 0 && g_Config.m_SvRconModPassword[0] == 0 && logins.empty()) { @@ -1146,7 +1146,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) Msg.AddInt(1); //authed Msg.AddInt(1); //cmdlist SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true); - + m_aClients[ClientID].m_Authed = AUTHED_ADMIN; int SendRconCmds = Unpacker.GetInt(); if(Unpacker.Error() == 0 && SendRconCmds) @@ -1182,12 +1182,12 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) Msg.AddInt(1); //authed Msg.AddInt(1); //cmdlist SendMsgEx(&Msg, MSGFLAG_VITAL, ClientID, true); - + m_aClients[ClientID].m_Authed = AUTHED_SUBADMIN; m_aClients[ClientID].m_SubAdminAuthName = loginit->first; m_aClients[ClientID].m_SubAdminAuthPass = loginit->second; m_aClients[ClientID].m_SubAdminCommandPassFails = 0; - + int SendRconCmds = Unpacker.GetInt(); if(Unpacker.Error() == 0 && SendRconCmds) m_aClients[ClientID].m_pRconCmdToSend = Console()->FirstCommandInfo(IConsole::ACCESS_LEVEL_SUBADMIN, CFGFLAG_SERVER); @@ -1247,7 +1247,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) else { // game message - if(m_aClients[ClientID].m_State >= CClient::STATE_READY) + if((pPacket->m_Flags&NET_CHUNKFLAG_VITAL) != 0 && m_aClients[ClientID].m_State >= CClient::STATE_READY) GameServer()->OnMessage(Msg, &Unpacker, ClientID); } } @@ -1738,10 +1738,10 @@ void CServer::ConVoteban(IConsole::IResult *pResult, void *pUser) void CServer::ConUnvoteban(IConsole::IResult *pResult, void *pUser) { CServer* pThis = static_cast<CServer *>(pUser); - + // index to unvoteban int index = pResult->GetInteger(0); - + CVoteban **v = &pThis->m_Votebans; for(int c = 0; *v != NULL; ++c) { @@ -1760,7 +1760,7 @@ void CServer::ConUnvoteban(IConsole::IResult *pResult, void *pUser) } v = &(*v)->m_Next; } - + // not found pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", "index was not found, please use 'votebans' to obtain an index"); } @@ -1788,7 +1788,7 @@ void CServer::ConVotebans(IConsole::IResult *pResult, void *pUser) char aAddrStr[NETADDR_MAXSTRSIZE]; int time; int count = 0; - + pThis->CleanVotebans(); CVoteban *v = pThis->m_Votebans; NETADDR addr; @@ -1802,7 +1802,7 @@ void CServer::ConVotebans(IConsole::IResult *pResult, void *pUser) pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf); v = v->m_Next; } - + str_format(aBuf, sizeof(aBuf), "%d votebanned ip(s)", count); pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf); } @@ -1813,12 +1813,12 @@ void CServer::ConAddLogin(IConsole::IResult *pResult, void *pUser) char aBuf[128]; std::string username(pResult->GetString(0)), password(pResult->GetString(1)); - + // insert if doesn't exist if(pThis->logins.find(username) == pThis->logins.end()) { pThis->logins[username] = password; - + str_format(aBuf, sizeof(aBuf), "Added login for '%s'.", username.c_str()); pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf); } @@ -1834,7 +1834,7 @@ void CServer::ConRemoveLogin(IConsole::IResult *pResult, void *pUser) char aBuf[128]; loginiterator loginit; std::string username(pResult->GetString(0)); - + // delete if exists if((loginit = pThis->logins.find(username)) != pThis->logins.end()) { @@ -1846,10 +1846,10 @@ void CServer::ConRemoveLogin(IConsole::IResult *pResult, void *pUser) pThis->rconLogClientOut(i, "You were logged out."); } } - + // finally delete pThis->logins.erase(loginit); - + str_format(aBuf, sizeof(aBuf), "Removed login '%s'.", username.c_str()); pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf); } @@ -1868,7 +1868,7 @@ void CServer::ConAddInfo(IConsole::IResult *pResult, void *pUser) pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", "Interval must be between 1 and 1440."); return; } - + // add info text CInfoText *t = new CInfoText; t->m_Interval = interval; @@ -1876,9 +1876,9 @@ void CServer::ConAddInfo(IConsole::IResult *pResult, void *pUser) // insert front t->m_Next = pThis->m_InfoTexts; pThis->m_InfoTexts = t; - + pThis->UpdateInfoTexts(); - + // message to console char aBuf[128]; str_format(aBuf, sizeof(aBuf), "Added the following info text: %s", t->m_Text.c_str()); @@ -1891,7 +1891,7 @@ void CServer::ConRemoveInfo(IConsole::IResult *pResult, void *pUser) int i = pResult->GetInteger(0); int count = 0; bool removed = false; - + CInfoText **t = &(pThis->m_InfoTexts); while(*t != NULL) { @@ -1906,9 +1906,9 @@ void CServer::ConRemoveInfo(IConsole::IResult *pResult, void *pUser) } t = &((*t)->m_Next); } - + pThis->UpdateInfoTexts(); - + if(removed) pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", "Info text removed"); else @@ -1920,7 +1920,7 @@ void CServer::ConListInfo(IConsole::IResult *pResult, void *pUser) CServer* pThis = static_cast<CServer *>(pUser); char aBuf[128]; int count = 0; - + CInfoText *t = pThis->m_InfoTexts; while(t != NULL) { @@ -1928,7 +1928,7 @@ void CServer::ConListInfo(IConsole::IResult *pResult, void *pUser) pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf); t = t->m_Next; } - + str_format(aBuf, sizeof(aBuf), "%d info text(s)", count); pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf); } @@ -1941,10 +1941,10 @@ void CServer::UpdateInfoTexts() m_InfoTextInterval = -1; // no interval return; } - + // need some random numbers later init_rand(); - + // update interval, set it to LCM(all text intervals) m_InfoTextInterval = 1; // lowest possible interval CInfoText *t = m_InfoTexts; @@ -1956,7 +1956,7 @@ void CServer::UpdateInfoTexts() t = t->m_Next; } m_InfoTextInterval *= TickSpeed() * 60; // min to ticks - + // count total number of messages per interval int numMsg = 0; t = m_InfoTexts; @@ -1965,7 +1965,7 @@ void CServer::UpdateInfoTexts() numMsg += m_InfoTextInterval / t->m_IntervalTicks; t = t->m_Next; } - + // interval between messages m_InfoTextMsgInterval = m_InfoTextInterval / numMsg; // additional pause to sync interval and msg interval @@ -1988,11 +1988,11 @@ std::string CServer::GetNextInfoText() selectedText = t; t = t->m_Next; } - + // return empty string if no text applies if(selectedText == NULL) return std::string(); - + // update tick and return string selectedText->m_NextTick += selectedText->m_IntervalTicks; return selectedText->m_Text; @@ -2204,15 +2204,15 @@ void CServer::RegisterCommands() Console()->Chain("sv_max_clients_per_ip", ConchainMaxclientsperipUpdate, this); Console()->Chain("mod_command", ConchainModCommandUpdate, this); Console()->Chain("console_output_level", ConchainConsoleOutputLevelUpdate, this); - + Console()->Register("voteban", "i?i", CFGFLAG_SERVER, ConVoteban, this, "Voteban a player by id"); Console()->Register("unvoteban", "i", CFGFLAG_SERVER, ConUnvoteban, this, "Remove voteban by index in list votebans"); Console()->Register("unvoteban_client", "i", CFGFLAG_SERVER, ConUnvotebanClient, this, "Remove voteban by player id"); Console()->Register("votebans", "", CFGFLAG_SERVER, ConVotebans, this, "Show all votebans"); - + Console()->Register("add_login", "ss", CFGFLAG_SERVER, ConAddLogin, this, "Add a subadmin login. The rcon password will be user:pass with no additional spaces.", IConsole::ACCESS_LEVEL_ADMIN); Console()->Register("remove_login", "s", CFGFLAG_SERVER, ConRemoveLogin, this, "Remove a subadmin login", IConsole::ACCESS_LEVEL_ADMIN); - + Console()->Register("add_info", "is", CFGFLAG_SERVER, ConAddInfo, this, "Add a info text that is printed in the chat repeatedly in the given interval of minutes."); Console()->Register("remove_info", "i", CFGFLAG_SERVER, ConRemoveInfo, this, "Remove a info text"); Console()->Register("list_info", "", CFGFLAG_SERVER, ConListInfo, this, "Show all info texts"); @@ -2343,4 +2343,3 @@ int main(int argc, const char **argv) // ignore_convention delete pConfig; return 0; } - diff --git a/src/engine/shared/network.cpp b/src/engine/shared/network.cpp index ada4b18a..13d62077 100644 --- a/src/engine/shared/network.cpp +++ b/src/engine/shared/network.cpp @@ -80,7 +80,7 @@ int CNetRecvUnpacker::FetchChunk(CNetChunk *pChunk) // fill in the info pChunk->m_ClientID = m_ClientID; pChunk->m_Address = m_Addr; - pChunk->m_Flags = 0; + pChunk->m_Flags = Header.m_Flags; pChunk->m_DataSize = Header.m_Size; pChunk->m_pData = pData; return 1; diff --git a/src/engine/shared/network.h b/src/engine/shared/network.h index 259d600f..cbc6e560 100644 --- a/src/engine/shared/network.h +++ b/src/engine/shared/network.h @@ -136,6 +136,7 @@ class CNetConnection private: unsigned short m_Sequence; unsigned short m_Ack; + unsigned short m_PeerAck; unsigned m_State; int m_Token; diff --git a/src/engine/shared/network_conn.cpp b/src/engine/shared/network_conn.cpp index cd2df048..7d76d585 100644 --- a/src/engine/shared/network_conn.cpp +++ b/src/engine/shared/network_conn.cpp @@ -13,6 +13,7 @@ void CNetConnection::Reset() { m_Sequence = 0; m_Ack = 0; + m_PeerAck = 0; m_RemoteClosed = 0; m_State = NET_CONNSTATE_OFFLINE; @@ -196,6 +197,19 @@ void CNetConnection::Disconnect(const char *pReason) int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr) { + // check if actual ack value is valid(own sequence..latest peer ack) + if(m_Sequence >= m_PeerAck) + { + if(pPacket->m_Ack < m_PeerAck || pPacket->m_Ack > m_Sequence) + return 0; + } + else + { + if(pPacket->m_Ack < m_PeerAck && pPacket->m_Ack > m_Sequence) + return 0; + } + m_PeerAck = pPacket->m_Ack; + int64 Now = time_get(); // check if resend is requested diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp index 30e32a92..cc51d856 100644 --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -440,7 +440,7 @@ void CCharacter::FireWeapon() for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++) Msg.AddInt(((int *)&p)[i]); - Server()->SendMsg(&Msg, 0, m_pPlayer->GetCID()); + Server()->SendMsg(&Msg, MSGFLAG_VITAL, m_pPlayer->GetCID()); GameServer()->CreateSound(m_Pos, SOUND_GUN_FIRE); } break; @@ -474,7 +474,7 @@ void CCharacter::FireWeapon() Msg.AddInt(((int *)&p)[i]); } - Server()->SendMsg(&Msg, 0,m_pPlayer->GetCID()); + Server()->SendMsg(&Msg, MSGFLAG_VITAL, m_pPlayer->GetCID()); GameServer()->CreateSound(m_Pos, SOUND_SHOTGUN_FIRE); } break; @@ -500,7 +500,7 @@ void CCharacter::FireWeapon() Msg.AddInt(1); for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++) Msg.AddInt(((int *)&p)[i]); - Server()->SendMsg(&Msg, 0, m_pPlayer->GetCID()); + Server()->SendMsg(&Msg, MSGFLAG_VITAL, m_pPlayer->GetCID()); GameServer()->CreateSound(m_Pos, SOUND_GRENADE_FIRE); } break; |