diff options
author | Thilo Schulz <arny@ats.s.bawue.de> | 2011-07-12 11:59:48 +0000 |
---|---|---|
committer | Tim Angus <tim@ngus.net> | 2013-01-10 22:16:30 +0000 |
commit | 3b328b36426e84975e85a572b82f17cd7caf3dc6 (patch) | |
tree | a2403aaa9324b934a89b706de3c770fdba298c29 /src/qcommon | |
parent | 733365194968c7a0f8e1df074a7d21435c519de9 (diff) |
- Implement dual protocol support (#4962) - Fix several UDP spoofing security issues
Diffstat (limited to 'src/qcommon')
-rw-r--r-- | src/qcommon/net_chan.c | 27 | ||||
-rw-r--r-- | src/qcommon/qcommon.h | 9 |
2 files changed, 27 insertions, 9 deletions
diff --git a/src/qcommon/net_chan.c b/src/qcommon/net_chan.c index 4aacfa7e..d9c6760b 100644 --- a/src/qcommon/net_chan.c +++ b/src/qcommon/net_chan.c @@ -84,7 +84,8 @@ Netchan_Setup called to open a channel to a remote system ============== */ -void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport ) { +void Netchan_Setup(netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, int challenge) +{ Com_Memset (chan, 0, sizeof(*chan)); chan->sock = sock; @@ -92,6 +93,7 @@ void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport ) { chan->qport = qport; chan->incomingSequence = 0; chan->outgoingSequence = 1; + chan->challenge = challenge; } // TTimo: unused, commenting out to make gcc happy @@ -191,17 +193,21 @@ void Netchan_TransmitNextFragment( netchan_t *chan ) { msg_t send; byte send_buf[MAX_PACKETLEN]; int fragmentLength; + int outgoingSequence; // write the packet header MSG_InitOOB (&send, send_buf, sizeof(send_buf)); // <-- only do the oob here - MSG_WriteLong( &send, chan->outgoingSequence | FRAGMENT_BIT ); + outgoingSequence = chan->outgoingSequence | FRAGMENT_BIT; + MSG_WriteLong(&send, outgoingSequence); // send the qport if we are a client if ( chan->sock == NS_CLIENT ) { MSG_WriteShort( &send, qport->integer ); } + MSG_WriteLong(&send, NETCHAN_GENCHECKSUM(chan->challenge, chan->outgoingSequence)); + // copy the reliable message to the packet first fragmentLength = FRAGMENT_SIZE; if ( chan->unsentFragmentStart + fragmentLength > chan->unsentLength ) { @@ -269,12 +275,14 @@ void Netchan_Transmit( netchan_t *chan, int length, const byte *data ) { MSG_InitOOB (&send, send_buf, sizeof(send_buf)); MSG_WriteLong( &send, chan->outgoingSequence ); - chan->outgoingSequence++; // send the qport if we are a client - if ( chan->sock == NS_CLIENT ) { - MSG_WriteShort( &send, qport->integer ); - } + if(chan->sock == NS_CLIENT) + MSG_WriteShort(&send, qport->integer); + + MSG_WriteLong(&send, NETCHAN_GENCHECKSUM(chan->challenge, chan->outgoingSequence)); + + chan->outgoingSequence++; MSG_WriteData( &send, data, length ); @@ -306,6 +314,7 @@ qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) { int sequence; int qport; int fragmentStart, fragmentLength; + int checksum; qboolean fragmented; // XOR unscramble all data in the packet after the header @@ -328,6 +337,12 @@ qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) { qport = MSG_ReadShort( msg ); } + checksum = MSG_ReadLong(msg); + + // UDP spoofing protection + if(NETCHAN_GENCHECKSUM(chan->challenge, sequence) != checksum) + return qfalse; + // read the fragment information if ( fragmented ) { fragmentStart = MSG_ReadShort( msg ); diff --git a/src/qcommon/qcommon.h b/src/qcommon/qcommon.h index 165dccae..28834168 100644 --- a/src/qcommon/qcommon.h +++ b/src/qcommon/qcommon.h @@ -193,7 +193,8 @@ void NET_Sleep(int msec); #define MAX_DOWNLOAD_WINDOW 48 // ACK window of 48 download chunks. Cannot set this higher, or clients // will overflow the reliable commands buffer #define MAX_DOWNLOAD_BLKSIZE 1024 // 896 byte block chunks - + +#define NETCHAN_GENCHECKSUM(challenge, sequence) ((challenge) ^ ((sequence) * (challenge))) /* Netchan handles packet fragmentation and out of order / duplicate suppression @@ -222,10 +223,12 @@ typedef struct { int unsentFragmentStart; int unsentLength; byte unsentBuffer[MAX_MSGLEN]; + + int challenge; } netchan_t; void Netchan_Init( int qport ); -void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport ); +void Netchan_Setup(netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, int challenge); void Netchan_Transmit( netchan_t *chan, int length, const byte *data ); void Netchan_TransmitNextFragment( netchan_t *chan ); @@ -241,7 +244,7 @@ PROTOCOL ============================================================== */ -#define PROTOCOL_VERSION 70 +#define PROTOCOL_VERSION 71 // maintain a list of compatible protocols for demo playing // NOTE: that stuff only works with two digits protocols |