Fix circumventing sv_maxping restriction, thanks to Amanieu for reporting. http://bugzilla.icculus.org/show_bug.cgi?id=3423

This commit is contained in:
Thilo Schulz 2009-10-08 20:03:25 +00:00
parent 40c773d80e
commit 9b7543a905
2 changed files with 34 additions and 16 deletions

View file

@ -208,6 +208,7 @@ typedef struct {
int time; // time the last packet was sent to the autherize server int time; // time the last packet was sent to the autherize server
int pingTime; // time the challenge response was sent to client int pingTime; // time the challenge response was sent to client
int firstTime; // time the adr was first used, for authorize timeout checks int firstTime; // time the adr was first used, for authorize timeout checks
qboolean wasrefused;
qboolean connected; qboolean connected;
} challenge_t; } challenge_t;

View file

@ -69,7 +69,7 @@ void SV_GetChallenge(netadr_t from)
// see if we already have a challenge for this ip // see if we already have a challenge for this ip
challenge = &svs.challenges[0]; challenge = &svs.challenges[0];
for (i = 0 ; i < MAX_CHALLENGES ; i++, challenge++) { 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; break;
} }
if ( challenge->time < oldestTime ) { 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 // this is the first time this client has asked for a challenge
challenge = &svs.challenges[oldest]; challenge = &svs.challenges[oldest];
challenge->challenge = ( (rand() << 16) ^ rand() ) ^ svs.time;
challenge->clientChallenge = 0; challenge->clientChallenge = 0;
challenge->adr = from; challenge->adr = from;
challenge->firstTime = svs.time; challenge->firstTime = svs.time;
@ -90,6 +89,11 @@ void SV_GetChallenge(netadr_t from)
challenge->connected = qfalse; 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 #ifndef STANDALONE
// Drop the authorize stuff if this client is coming in via v6 as the auth server does not support ipv6. // 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. // 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 ); Info_SetValueForKey( userinfo, "ip", ip );
// see if the challenge is valid (LAN clients don't need to challenge) // see if the challenge is valid (LAN clients don't need to challenge)
if ( !NET_IsLocalAddress (from) ) { if (!NET_IsLocalAddress(from))
{
int ping; int ping;
challenge_t *challengeptr;
for (i=0 ; i<MAX_CHALLENGES ; i++) { for (i=0; i<MAX_CHALLENGES; i++)
if (NET_CompareAdr(from, svs.challenges[i].adr)) { {
if ( challenge == svs.challenges[i].challenge ) if (NET_CompareAdr(from, svs.challenges[i].adr))
{
if(challenge == svs.challenges[i].challenge)
break; break;
} }
} }
if (i == MAX_CHALLENGES) {
NET_OutOfBandPrint( NS_SERVER, from, "print\nNo or bad challenge for address.\n" ); if (i == MAX_CHALLENGES)
{
NET_OutOfBandPrint( NS_SERVER, from, "print\nNo or bad challenge for your address.\n" );
return; return;
} }
ping = svs.time - svs.challenges[i].pingTime; challengeptr = &svs.challenges[i];
Com_Printf( "Client %i connecting with %i challenge ping\n", i, ping );
svs.challenges[i].connected = qtrue; if(challengeptr->wasrefused)
{
// Return silently, so that error messages written by the server keep being displayed.
return;
}
ping = svs.time - challengeptr->pingTime;
// never reject a LAN client based on ping // never reject a LAN client based on ping
if ( !Sys_IsLANAddress( from ) ) { if ( !Sys_IsLANAddress( from ) ) {
if ( sv_minPing->value && ping < sv_minPing->value ) { 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" ); 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); Com_DPrintf ("Client %i rejected on a too low ping\n", i);
// reset the address otherwise their ping will keep increasing challengeptr->wasrefused = qtrue;
// with each connect message and they'd eventually be able to connect
svs.challenges[i].adr.port = 0;
return; return;
} }
if ( sv_maxPing->value && ping > sv_maxPing->value ) { if ( sv_maxPing->value && ping > sv_maxPing->value ) {
NET_OutOfBandPrint( NS_SERVER, from, "print\nServer is for low pings only\n" ); 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); Com_DPrintf ("Client %i rejected on a too high ping\n", i);
challengeptr->wasrefused = qtrue;
return; return;
} }
} }
Com_Printf("Client %i connecting with %i challenge ping\n", i, ping);
challengeptr->connected = qtrue;
} }
newcl = &temp; newcl = &temp;