Skip to content

Commit 7877018

Browse files
BoondorlRicardoLuis0
authored andcommitted
Added CRC to packets
Verify that data is correctly ordered and reject packets that aren't. Also generates a random game id to ensure packets are coming from legitimate clients.
1 parent 9e2b1f9 commit 7877018

File tree

3 files changed

+67
-32
lines changed

3 files changed

+67
-32
lines changed

src/common/engine/i_net.cpp

+66-27
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
#include "c_cvars.h"
7979
#include "version.h"
8080
#include "i_net.h"
81+
#include "m_random.h"
8182

8283
/* [Petteri] Get more portable: */
8384
#ifndef __WIN32__
@@ -162,13 +163,14 @@ int consoleplayer = 0;
162163
int Net_Arbitrator = 0;
163164
FClientStack NetworkClients = {};
164165

165-
uint32_t GameID = DEFAULT_GAME_ID;
166+
uint64_t GameID = 0u;
166167
uint8_t TicDup = 1u;
167168
int MaxClients = 1;
168169
int RemoteClient = -1;
169170
size_t NetBufferLength = 0u;
170171
uint8_t NetBuffer[MAX_MSGLEN] = {};
171172

173+
static FRandom GameIDGen = {};
172174
static u_short GamePort = (IPPORT_USERRESERVED + 29);
173175
static SOCKET MySocket = INVALID_SOCKET;
174176
static FConnection Connected[MAXPLAYERS] = {};
@@ -483,22 +485,34 @@ static void SendPacket(const sockaddr_in& to)
483485

484486
assert(!(NetBuffer[0] & NCMD_COMPRESSED));
485487

486-
uLong size = MaxTransmitSize - 1u;
487-
int res = -1;
488+
uint8_t* dataStart = &TransmitBuffer[4];
489+
uLong size = MaxTransmitSize - 5u;
488490
if (NetBufferLength >= MinCompressionSize)
489491
{
490-
TransmitBuffer[0] = NetBuffer[0] | NCMD_COMPRESSED;
492+
*dataStart = NetBuffer[0] | NCMD_COMPRESSED;
493+
const int res = compress2(dataStart + 1, &size, NetBuffer + 1, NetBufferLength - 1u, 9);
494+
if (res != Z_OK)
495+
I_Error("Net compression failed (zlib error %d)", res);
491496

492-
res = compress2(TransmitBuffer + 1, &size, NetBuffer + 1, uint32_t(NetBufferLength - 1u), 9);
493497
++size;
494498
}
495-
496-
if (res == Z_OK && size < static_cast<uLong>(NetBufferLength))
497-
res = sendto(MySocket, (const char*)TransmitBuffer, (int)size, 0, (const sockaddr*)&to, sizeof(to));
498-
else if (NetBufferLength > MaxTransmitSize)
499-
I_Error("Net compression failed (zlib error %d)", res);
500499
else
501-
res = sendto(MySocket, (const char*)NetBuffer, (int)NetBufferLength, 0, (const sockaddr*)&to, sizeof(to));
500+
{
501+
memcpy(dataStart, NetBuffer, NetBufferLength);
502+
size = NetBufferLength;
503+
}
504+
505+
if (size + 4 > MaxTransmitSize)
506+
I_Error("Failed to compress data down to acceptable transmission size");
507+
508+
// If a connection packet, don't check the game id since they might not have it yet.
509+
const uint32_t crc = (NetBuffer[0] & NCMD_SETUP) ? CalcCRC32(dataStart, size) : AddCRC32(CalcCRC32(dataStart, size), (uint8_t*)&GameID, sizeof(GameID));
510+
TransmitBuffer[0] = crc >> 24;
511+
TransmitBuffer[1] = crc >> 16;
512+
TransmitBuffer[2] = crc >> 8;
513+
TransmitBuffer[3] = crc;
514+
515+
sendto(MySocket, (const char*)TransmitBuffer, size + 4, 0, (const sockaddr*)&to, sizeof(to));
502516
}
503517

504518
static void GetPacket(sockaddr_in* const from = nullptr)
@@ -544,7 +558,8 @@ static void GetPacket(sockaddr_in* const from = nullptr)
544558
}
545559
else if (msgSize > 0)
546560
{
547-
if (client == -1 && !(TransmitBuffer[0] & NCMD_SETUP))
561+
const uint8_t* dataStart = &TransmitBuffer[4];
562+
if (client == -1 && !(*dataStart & NCMD_SETUP))
548563
{
549564
msgSize = 0;
550565
}
@@ -558,26 +573,38 @@ static void GetPacket(sockaddr_in* const from = nullptr)
558573
}
559574
else
560575
{
561-
NetBuffer[0] = (TransmitBuffer[0] & ~NCMD_COMPRESSED);
562-
if (TransmitBuffer[0] & NCMD_COMPRESSED)
576+
const uint32_t check = (*dataStart & NCMD_SETUP) ? CalcCRC32(dataStart, msgSize - 4) : AddCRC32(CalcCRC32(dataStart, msgSize - 4), (uint8_t*)GameID, sizeof(GameID));
577+
const uint32_t crc = (TransmitBuffer[0] << 24) | (TransmitBuffer[1] << 16) | (TransmitBuffer[2] << 8) | TransmitBuffer[3];
578+
if (check != crc)
579+
{
580+
DPrintf(DMSG_NOTIFY, "Checksum on packet failed: expected %u, got %u", check, crc);
581+
client = -1;
582+
msgSize = 0;
583+
}
584+
else
563585
{
564-
uLongf size = MAX_MSGLEN - 1;
565-
int err = uncompress(NetBuffer + 1, &size, TransmitBuffer + 1, msgSize - 1);
566-
if (err != Z_OK)
586+
NetBuffer[0] = (*dataStart & ~NCMD_COMPRESSED);
587+
if (*dataStart & NCMD_COMPRESSED)
567588
{
568-
Printf("Net decompression failed (zlib error %s)\n", M_ZLibError(err).GetChars());
569-
client = -1;
570-
msgSize = 0;
589+
uLongf size = MAX_MSGLEN - 1;
590+
int err = uncompress(NetBuffer + 1, &size, dataStart + 1, msgSize - 5);
591+
if (err != Z_OK)
592+
{
593+
Printf("Net decompression failed (zlib error %s)\n", M_ZLibError(err).GetChars());
594+
client = -1;
595+
msgSize = 0;
596+
}
597+
else
598+
{
599+
msgSize = size + 1;
600+
}
571601
}
572602
else
573603
{
574-
msgSize = size + 1;
604+
msgSize -= 4;
605+
memcpy(NetBuffer + 1, dataStart + 1, msgSize - 1);
575606
}
576607
}
577-
else
578-
{
579-
memcpy(NetBuffer + 1, TransmitBuffer + 1, msgSize - 1);
580-
}
581608
}
582609
}
583610
else
@@ -847,7 +874,15 @@ static bool Host_CheckForConnections(void* connected)
847874
{
848875
NetBuffer[1] = PRE_GAME_INFO;
849876
NetBuffer[2] = TicDup;
850-
NetBufferLength = 3u;
877+
NetBuffer[3] = GameID >> 56;
878+
NetBuffer[4] = GameID >> 48;
879+
NetBuffer[5] = GameID >> 40;
880+
NetBuffer[6] = GameID >> 32;
881+
NetBuffer[7] = GameID >> 24;
882+
NetBuffer[8] = GameID >> 16;
883+
NetBuffer[9] = GameID >> 8;
884+
NetBuffer[10] = GameID;
885+
NetBufferLength = 11u;
851886

852887
uint8_t* stream = &NetBuffer[NetBufferLength];
853888
NetBufferLength += Net_SetGameInfo(stream);
@@ -931,6 +966,7 @@ static bool HostGame(int arg, bool forcedNetMode)
931966
if (MaxClients > MAXPLAYERS)
932967
I_FatalError("Cannot host a game with %u players. The limit is currently %u", MaxClients, MAXPLAYERS);
933968

969+
GameID = GameIDGen.GenRand64();
934970
NetworkClients += 0;
935971
Connected[consoleplayer].Status = CSTAT_READY;
936972
Net_SetupUserInfo();
@@ -1092,7 +1128,9 @@ static bool Guest_ContactHost(void* unused)
10921128
if (!Connected[consoleplayer].bHasGameInfo)
10931129
{
10941130
TicDup = clamp<int>(NetBuffer[2], 1, MAXTICDUP);
1095-
uint8_t* stream = &NetBuffer[3];
1131+
GameID = ((uint64_t)NetBuffer[3] << 56) | ((uint64_t)NetBuffer[4] << 48) | ((uint64_t)NetBuffer[5] << 40) | ((uint64_t)NetBuffer[6] << 32)
1132+
| ((uint64_t)NetBuffer[7] << 24) | ((uint64_t)NetBuffer[8] << 16) | ((uint64_t)NetBuffer[9] << 8) | (uint64_t)NetBuffer[10];
1133+
uint8_t* stream = &NetBuffer[11];
10961134
Net_ReadGameInfo(stream);
10971135
Connected[consoleplayer].bHasGameInfo = true;
10981136
}
@@ -1255,6 +1293,7 @@ bool I_InitNetwork()
12551293
else
12561294
{
12571295
// single player game
1296+
GameID = GameIDGen.GenRand64();
12581297
TicDup = 1;
12591298
NetworkClients += 0;
12601299
Connected[0].Status = CSTAT_READY;

src/common/engine/i_net.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ inline constexpr size_t MAXPLAYERS = 64u;
88

99
enum ENetConstants
1010
{
11-
DEFAULT_GAME_ID = 0x12345678,
1211
BACKUPTICS = 35 * 5, // Remember up to 5 seconds of data.
1312
MAXTICDUP = 3,
1413
MAXSENDTICS = 35 * 1, // Only send up to 1 second of data at a time.
@@ -67,7 +66,7 @@ extern size_t NetBufferLength;
6766
extern uint8_t TicDup;
6867
extern int RemoteClient;
6968
extern int MaxClients;
70-
extern uint32_t GameID;
69+
extern uint64_t GameID;
7170

7271
bool I_InitNetwork();
7372
void I_ClearClient(size_t client);

src/d_net.cpp

-3
Original file line numberDiff line numberDiff line change
@@ -1695,9 +1695,6 @@ bool D_CheckNetGame()
16951695
if (!I_InitNetwork())
16961696
return false;
16971697

1698-
if (GameID != DEFAULT_GAME_ID)
1699-
I_FatalError("Invalid id set for network buffer");
1700-
17011698
if (Args->CheckParm("-extratic"))
17021699
net_extratic = true;
17031700

0 commit comments

Comments
 (0)