From 9b7543a905c0638a5a995f77c2a73ace957a475f Mon Sep 17 00:00:00 2001 From: Thilo Schulz Date: Thu, 8 Oct 2009 20:03:25 +0000 Subject: [PATCH] Fix circumventing sv_maxping restriction, thanks to Amanieu for reporting. http://bugzilla.icculus.org/show_bug.cgi?id=3423 --- code/server/server.h | 1 + code/server/sv_client.c | 49 +++++++++++++++++++++++++++-------------- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/code/server/server.h b/code/server/server.h index eab244b3..bf85594e 100644 --- a/code/server/server.h +++ b/code/server/server.h @@ -208,6 +208,7 @@ typedef struct { int time; // time the last packet was sent to the autherize server int pingTime; // time the challenge response was sent to client int firstTime; // time the adr was first used, for authorize timeout checks + qboolean wasrefused; qboolean connected; } challenge_t; diff --git a/code/server/sv_client.c b/code/server/sv_client.c index 773c89e6..4387d24b 100644 --- a/code/server/sv_client.c +++ b/code/server/sv_client.c @@ -69,7 +69,7 @@ void SV_GetChallenge(netadr_t from) // see if we already have a challenge for this ip challenge = &svs.challenges[0]; for (i = 0 ; i < MAX_CHALLENGES ; i++, challenge++) { - if ( !challenge->connected && NET_CompareAdr( from, challenge->adr ) ) { + if (!challenge->connected && NET_CompareAdr( from, challenge->adr ) ) { break; } if ( challenge->time < oldestTime ) { @@ -82,7 +82,6 @@ void SV_GetChallenge(netadr_t from) { // this is the first time this client has asked for a challenge challenge = &svs.challenges[oldest]; - challenge->challenge = ( (rand() << 16) ^ rand() ) ^ svs.time; challenge->clientChallenge = 0; challenge->adr = from; challenge->firstTime = svs.time; @@ -90,6 +89,11 @@ void SV_GetChallenge(netadr_t from) challenge->connected = qfalse; } + // always generate a new challenge number, so the client cannot circumvent sv_maxping + challenge->challenge = ( (rand() << 16) ^ rand() ) ^ svs.time; + challenge->wasrefused = qfalse; + + #ifndef STANDALONE // Drop the authorize stuff if this client is coming in via v6 as the auth server does not support ipv6. // Drop also for addresses coming in on local LAN and for stand-alone games independent from id's assets. @@ -338,41 +342,54 @@ void SV_DirectConnect( netadr_t from ) { Info_SetValueForKey( userinfo, "ip", ip ); // see if the challenge is valid (LAN clients don't need to challenge) - if ( !NET_IsLocalAddress (from) ) { - int ping; + if (!NET_IsLocalAddress(from)) + { + int ping; + challenge_t *challengeptr; - for (i=0 ; iwasrefused) + { + // Return silently, so that error messages written by the server keep being displayed. return; } - ping = svs.time - svs.challenges[i].pingTime; - Com_Printf( "Client %i connecting with %i challenge ping\n", i, ping ); - svs.challenges[i].connected = qtrue; + ping = svs.time - challengeptr->pingTime; // never reject a LAN client based on ping if ( !Sys_IsLANAddress( from ) ) { if ( sv_minPing->value && ping < sv_minPing->value ) { - // don't let them keep trying until they get a big delay NET_OutOfBandPrint( NS_SERVER, from, "print\nServer is for high pings only\n" ); Com_DPrintf ("Client %i rejected on a too low ping\n", i); - // reset the address otherwise their ping will keep increasing - // with each connect message and they'd eventually be able to connect - svs.challenges[i].adr.port = 0; + challengeptr->wasrefused = qtrue; return; } if ( sv_maxPing->value && ping > sv_maxPing->value ) { NET_OutOfBandPrint( NS_SERVER, from, "print\nServer is for low pings only\n" ); Com_DPrintf ("Client %i rejected on a too high ping\n", i); + challengeptr->wasrefused = qtrue; return; } } + + Com_Printf("Client %i connecting with %i challenge ping\n", i, ping); + challengeptr->connected = qtrue; } newcl = &temp;