summaryrefslogtreecommitdiff
path: root/src/qcommon
diff options
context:
space:
mode:
authorThilo Schulz <arny@ats.s.bawue.de>2011-07-12 11:59:48 +0000
committerTim Angus <tim@ngus.net>2013-01-10 22:16:30 +0000
commit3b328b36426e84975e85a572b82f17cd7caf3dc6 (patch)
treea2403aaa9324b934a89b706de3c770fdba298c29 /src/qcommon
parent733365194968c7a0f8e1df074a7d21435c519de9 (diff)
- Implement dual protocol support (#4962) - Fix several UDP spoofing security issues
Diffstat (limited to 'src/qcommon')
-rw-r--r--src/qcommon/net_chan.c27
-rw-r--r--src/qcommon/qcommon.h9
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