From 0d5fef7f5c33fd4176b27c79d9cef7512801f471 Mon Sep 17 00:00:00 2001 From: Thilo Schulz Date: Wed, 27 Apr 2011 16:03:35 +0000 Subject: - Harden the client and server protocol against UDP spoofing attacks. This will defend ioquake3 against http://aluigi.altervista.org/papers/q3noclient.txt (#3041) - Retains full compatibility to the old but unsecure protocol between clients and servers - Harden the connection process against DoS attacks, possibly connected to UDP spoofing --- src/client/cl_main.c | 47 +++++++++++++++++++++++++---------------------- src/client/cl_net_chan.c | 6 ++---- 2 files changed, 27 insertions(+), 26 deletions(-) (limited to 'src/client') diff --git a/src/client/cl_main.c b/src/client/cl_main.c index 10bc313f..128db604 100644 --- a/src/client/cl_main.c +++ b/src/client/cl_main.c @@ -585,7 +585,6 @@ void CL_WriteDemoMessage ( msg_t *msg, int headerBytes ) { len = clc.serverMessageSequence; swlen = LittleLong( len ); FS_Write (&swlen, 4, clc.demofile); - // skip the packet sequencing information len = msg->cursize - headerBytes; swlen = LittleLong(len); @@ -717,7 +716,6 @@ void CL_Record_f( void ) { clc.spDemoRecording = qfalse; } - Q_strncpyz( clc.demoName, demoName, sizeof( clc.demoName ) ); // don't start saving messages until a non-delta compressed message is received @@ -941,14 +939,13 @@ void CL_ReadDemoMessage( void ) { CL_WalkDemoExt ==================== */ -static void CL_WalkDemoExt(char *arg, char *name, int *demofile) +static int CL_WalkDemoExt(char *arg, char *name, int *demofile) { int i = 0; *demofile = 0; - Com_sprintf (name, MAX_OSPATH, "demos/%s.%s%d", arg, DEMOEXT, PROTOCOL_VERSION); - - FS_FOpenFileRead( name, demofile, qtrue ); + Com_sprintf(name, MAX_OSPATH, "demos/%s.%s%d", arg, DEMOEXT, PROTOCOL_VERSION); + FS_FOpenFileRead(name, demofile, qtrue); if (*demofile) { @@ -960,17 +957,23 @@ static void CL_WalkDemoExt(char *arg, char *name, int *demofile) while(demo_protocols[i]) { + if(demo_protocols[i] == PROTOCOL_VERSION) + continue; + Com_sprintf (name, MAX_OSPATH, "demos/%s.%s%d", arg, DEMOEXT, demo_protocols[i]); FS_FOpenFileRead( name, demofile, qtrue ); if (*demofile) { Com_Printf("Demo file: %s\n", name); - break; + + return demo_protocols[i]; } else Com_Printf("Not found: %s\n", name); i++; } + + return -1; } /* @@ -1047,11 +1050,11 @@ void CL_PlayDemo_f( void ) { Q_strncpyz(retry, arg, len + 1); retry[len] = '\0'; - CL_WalkDemoExt(retry, name, &clc.demofile); + protocol = CL_WalkDemoExt(retry, name, &clc.demofile); } } else - CL_WalkDemoExt(arg, name, &clc.demofile); + protocol = CL_WalkDemoExt(arg, name, &clc.demofile); if (!clc.demofile) { Com_Error( ERR_DROP, "couldn't open %s", name); @@ -2603,6 +2606,7 @@ Responses to broadcasts, etc void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { char *s; char *c; + int challenge; MSG_BeginReadingOOB( msg ); MSG_ReadLong( msg ); // skip the -1 @@ -2624,15 +2628,17 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { return; } + c = Cmd_Argv(2); + if(*c) + challenge = atoi(c); + if(!NET_CompareAdr(from, clc.serverAddress)) { // This challenge response is not coming from the expected address. // Check whether we have a matching client challenge to prevent // connection hi-jacking. - - c = Cmd_Argv(2); - - if(!*c || atoi(c) != clc.challenge) + + if(!*c || challenge != clc.challenge) { Com_DPrintf("Challenge response received from unexpected source. Ignored.\n"); return; @@ -2666,7 +2672,10 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { Com_Printf( "connectResponse from wrong address. Ignored.\n" ); return; } - Netchan_Setup (NS_CLIENT, &clc.netchan, from, Cvar_VariableValue( "net_qport" ) ); + + Netchan_Setup(NS_CLIENT, &clc.netchan, from, Cvar_VariableValue("net_qport"), + clc.challenge); + cls.state = CA_CONNECTED; clc.lastPacketSentTime = -9999; // send first packet immediately return; @@ -2684,13 +2693,6 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { return; } - // a disconnect message from the server, which will happen if the server - // dropped the connection but it is still getting packets from us - if (!Q_stricmp(c, "disconnect")) { - CL_DisconnectPacket( from ); - return; - } - // echo request from server if ( !Q_stricmp(c, "echo") ) { NET_OutOfBandPrint( NS_CLIENT, from, "%s", Cmd_Argv(1) ); @@ -2704,7 +2706,7 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { } // echo request from server - if ( !Q_stricmp(c, "print") ) { + if(!Q_stricmp(c, "print")){ s = MSG_ReadString( msg ); Q_strncpyz( clc.serverMessage, s, sizeof( clc.serverMessage ) ); @@ -2719,6 +2721,7 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { // list of servers sent back by a master server (classic) if ( !Q_strncmp(c, "getserversResponse", 18) ) { CL_ServersResponsePacket( &from, msg, qfalse ); + return; } diff --git a/src/client/cl_net_chan.c b/src/client/cl_net_chan.c index 561f322a..fbfc4dc9 100644 --- a/src/client/cl_net_chan.c +++ b/src/client/cl_net_chan.c @@ -148,9 +148,6 @@ void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg ) { Netchan_Transmit( chan, msg->cursize, msg->data ); } -extern int oldsize; -int newsize = 0; - /* ================= CL_Netchan_Process @@ -162,7 +159,8 @@ qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ) { ret = Netchan_Process( chan, msg ); if (!ret) return qfalse; + CL_Netchan_Decode( msg ); - newsize += msg->cursize; + return qtrue; } -- cgit