[quake3-commits] r1566 - in trunk/code: qcommon server

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Mon Jun 1 01:28:48 EDT 2009


Author: thilo
Date: 2009-06-01 01:28:47 -0400 (Mon, 01 Jun 2009)
New Revision: 1566

Modified:
   trunk/code/qcommon/qcommon.h
   trunk/code/server/server.h
   trunk/code/server/sv_client.c
   trunk/code/server/sv_main.c
Log:
Make servers echo challenge codes from client getchallenge commands


Modified: trunk/code/qcommon/qcommon.h
===================================================================
--- trunk/code/qcommon/qcommon.h	2009-06-01 00:18:02 UTC (rev 1565)
+++ trunk/code/qcommon/qcommon.h	2009-06-01 05:28:47 UTC (rev 1566)
@@ -132,8 +132,8 @@
 #define	MAX_RELIABLE_COMMANDS	64			// max string commands buffered for restransmit
 
 typedef enum {
+	NA_BAD = 0,					// an address lookup failed
 	NA_BOT,
-	NA_BAD,					// an address lookup failed
 	NA_LOOPBACK,
 	NA_BROADCAST,
 	NA_IP,

Modified: trunk/code/server/server.h
===================================================================
--- trunk/code/server/server.h	2009-06-01 00:18:02 UTC (rev 1565)
+++ trunk/code/server/server.h	2009-06-01 05:28:47 UTC (rev 1566)
@@ -204,6 +204,7 @@
 typedef struct {
 	netadr_t	adr;
 	int			challenge;
+	int			clientChallenge;		// challenge number coming from the client
 	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
@@ -326,7 +327,7 @@
 //
 // sv_client.c
 //
-void SV_GetChallenge( netadr_t from );
+void SV_GetChallenge(netadr_t from);
 
 void SV_DirectConnect( netadr_t from );
 

Modified: trunk/code/server/sv_client.c
===================================================================
--- trunk/code/server/sv_client.c	2009-06-01 00:18:02 UTC (rev 1565)
+++ trunk/code/server/sv_client.c	2009-06-01 05:28:47 UTC (rev 1566)
@@ -41,12 +41,21 @@
 
 When an authorizeip is returned, a challenge response will be
 sent to that ip.
+
+ioquake3: we added a possibility for clients to add a challenge
+to their packets, to make it more difficult for malicious servers
+to hi-jack client connections.
+Also, the auth stuff is completely disabled for com_standalone games
+as well as IPv6 connections, since there is no way to use the
+v4-only auth server for these new types of connections.
 =================
 */
-void SV_GetChallenge( netadr_t from ) {
+void SV_GetChallenge(netadr_t from)
+{
 	int		i;
 	int		oldest;
 	int		oldestTime;
+	const char *clientChallenge = Cmd_Argv(1);
 	challenge_t	*challenge;
 
 	// ignore if we are in single player
@@ -69,62 +78,57 @@
 		}
 	}
 
-	if (i == MAX_CHALLENGES) {
+	if (i == MAX_CHALLENGES)
+	{
 		// 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;
 		challenge->time = svs.time;
 		challenge->connected = qfalse;
-		i = oldest;
 	}
 
-#ifdef STANDALONE
-	challenge->pingTime = svs.time;
-	NET_OutOfBandPrint( NS_SERVER, from, "challengeResponse %i", challenge->challenge );
-#else
-	// if they are on a lan address, send the challengeResponse immediately
-	if ( Sys_IsLANAddress( from ) ) {
-		challenge->pingTime = svs.time;
-		NET_OutOfBandPrint( NS_SERVER, from, "challengeResponse %i", challenge->challenge );
-		return;
-	}
-
+#ifndef STANDALONE
 	// Drop the authorize stuff if this client is coming in via v6 as the auth server does not support ipv6.
-	if(challenge->adr.type == NA_IP)
+	// Drop also for addresses coming in on local LAN and for stand-alone games independent from id's assets.
+	if(challenge->adr.type == NA_IP && !Cvar_VariableIntegerValue("com_standalone") && !Sys_IsLANAddress(from))
 	{
 		// look up the authorize server's IP
-		if ( !svs.authorizeAddress.ip[0] && svs.authorizeAddress.type != NA_BAD ) {
+		if (svs.authorizeAddress.type == NA_BAD)
+		{
 			Com_Printf( "Resolving %s\n", AUTHORIZE_SERVER_NAME );
-			if ( !NET_StringToAdr( AUTHORIZE_SERVER_NAME, &svs.authorizeAddress, NA_IP ) ) {
-				Com_Printf( "Couldn't resolve address\n" );
-				return;
+			
+			if (NET_StringToAdr(AUTHORIZE_SERVER_NAME, &svs.authorizeAddress, NA_IP))
+			{
+				svs.authorizeAddress.port = BigShort( PORT_AUTHORIZE );
+				Com_Printf( "%s resolved to %i.%i.%i.%i:%i\n", AUTHORIZE_SERVER_NAME,
+					svs.authorizeAddress.ip[0], svs.authorizeAddress.ip[1],
+					svs.authorizeAddress.ip[2], svs.authorizeAddress.ip[3],
+					BigShort( svs.authorizeAddress.port ) );
 			}
-			svs.authorizeAddress.port = BigShort( PORT_AUTHORIZE );
-			Com_Printf( "%s resolved to %i.%i.%i.%i:%i\n", AUTHORIZE_SERVER_NAME,
-				svs.authorizeAddress.ip[0], svs.authorizeAddress.ip[1],
-				svs.authorizeAddress.ip[2], svs.authorizeAddress.ip[3],
-				BigShort( svs.authorizeAddress.port ) );
 		}
 
+		// we couldn't contact the auth server, let them in.
+		if(svs.authorizeAddress.type == NA_BAD)
+			Com_Printf("Couldn't resolve auth server address\n");
+
 		// if they have been challenging for a long time and we
 		// haven't heard anything from the authorize server, go ahead and
 		// let them in, assuming the id server is down
-		if ( svs.time - challenge->firstTime > AUTHORIZE_TIMEOUT ) {
+		else if(svs.time - challenge->firstTime > AUTHORIZE_TIMEOUT)
 			Com_DPrintf( "authorize server timed out\n" );
-
-			challenge->pingTime = svs.time;
-			NET_OutOfBandPrint( NS_SERVER, challenge->adr, 
-				"challengeResponse %i", challenge->challenge );
-			return;
-		}
-
-		// otherwise send their ip to the authorize server
-		if ( svs.authorizeAddress.type != NA_BAD ) {
+		else
+		{
+			// otherwise send their ip to the authorize server
 			cvar_t	*fs;
 			char	game[1024];
 
+			// If the client provided us with a client challenge, store it...
+			if(*clientChallenge)
+				challenge->clientChallenge = atoi(clientChallenge);
+			
 			Com_DPrintf( "sending getIpAuthorize for %s\n", NET_AdrToString( from ));
 		
 			strcpy(game, BASEGAME);
@@ -132,22 +136,20 @@
 			if (fs && fs->string[0] != 0) {
 				strcpy(game, fs->string);
 			}
-		
+			
 			// the 0 is for backwards compatibility with obsolete sv_allowanonymous flags
 			// getIpAuthorize <challenge> <IP> <game> 0 <auth-flag>
 			NET_OutOfBandPrint( NS_SERVER, svs.authorizeAddress,
-				"getIpAuthorize %i %i.%i.%i.%i %s 0 %s",  svs.challenges[i].challenge,
+				"getIpAuthorize %i %i.%i.%i.%i %s 0 %s",  challenge->challenge,
 				from.ip[0], from.ip[1], from.ip[2], from.ip[3], game, sv_strictAuth->string );
+			
+			return;
 		}
 	}
-	else
-	{
-		challenge->pingTime = svs.time;
-		
-		NET_OutOfBandPrint( NS_SERVER, challenge->adr, 
-			"challengeResponse %i", challenge->challenge );
-	}
 #endif
+
+	challenge->pingTime = svs.time;
+	NET_OutOfBandPrint( NS_SERVER, challenge->adr, "challengeResponse %i %s", challenge->challenge, clientChallenge);
 }
 
 #ifndef STANDALONE
@@ -165,6 +167,7 @@
 	int		i;
 	char	*s;
 	char	*r;
+	challenge_t *challengeptr;
 
 	if ( !NET_CompareBaseAdr( from, svs.authorizeAddress ) ) {
 		Com_Printf( "SV_AuthorizeIpPacket: not from authorize server\n" );
@@ -182,44 +185,46 @@
 		Com_Printf( "SV_AuthorizeIpPacket: challenge not found\n" );
 		return;
 	}
+	
+	challengeptr = &svs.challenges[i];
 
 	// send a packet back to the original client
-	svs.challenges[i].pingTime = svs.time;
+	challengeptr->pingTime = svs.time;
 	s = Cmd_Argv( 2 );
 	r = Cmd_Argv( 3 );			// reason
 
 	if ( !Q_stricmp( s, "demo" ) ) {
 		// they are a demo client trying to connect to a real server
-		NET_OutOfBandPrint( NS_SERVER, svs.challenges[i].adr, "print\nServer is not a demo server\n" );
+		NET_OutOfBandPrint( NS_SERVER, challengeptr->adr, "print\nServer is not a demo server\n" );
 		// clear the challenge record so it won't timeout and let them through
-		Com_Memset( &svs.challenges[i], 0, sizeof( svs.challenges[i] ) );
+		Com_Memset( challengeptr, 0, sizeof( *challengeptr ) );
 		return;
 	}
 	if ( !Q_stricmp( s, "accept" ) ) {
-		NET_OutOfBandPrint( NS_SERVER, svs.challenges[i].adr, 
-			"challengeResponse %i", svs.challenges[i].challenge );
+		NET_OutOfBandPrint(NS_SERVER, challengeptr->adr,
+			"challengeResponse %d %d", challengeptr->challenge, challengeptr->clientChallenge);
 		return;
 	}
 	if ( !Q_stricmp( s, "unknown" ) ) {
 		if (!r) {
-			NET_OutOfBandPrint( NS_SERVER, svs.challenges[i].adr, "print\nAwaiting CD key authorization\n" );
+			NET_OutOfBandPrint( NS_SERVER, challengeptr->adr, "print\nAwaiting CD key authorization\n" );
 		} else {
-			NET_OutOfBandPrint( NS_SERVER, svs.challenges[i].adr, "print\n%s\n", r);
+			NET_OutOfBandPrint( NS_SERVER, challengeptr->adr, "print\n%s\n", r);
 		}
 		// clear the challenge record so it won't timeout and let them through
-		Com_Memset( &svs.challenges[i], 0, sizeof( svs.challenges[i] ) );
+		Com_Memset( challengeptr, 0, sizeof( *challengeptr ) );
 		return;
 	}
 
 	// authorization failed
 	if (!r) {
-		NET_OutOfBandPrint( NS_SERVER, svs.challenges[i].adr, "print\nSomeone is using this CD Key\n" );
+		NET_OutOfBandPrint( NS_SERVER, challengeptr->adr, "print\nSomeone is using this CD Key\n" );
 	} else {
-		NET_OutOfBandPrint( NS_SERVER, svs.challenges[i].adr, "print\n%s\n", r );
+		NET_OutOfBandPrint( NS_SERVER, challengeptr->adr, "print\n%s\n", r );
 	}
 
 	// clear the challenge record so it won't timeout and let them through
-	Com_Memset( &svs.challenges[i], 0, sizeof( svs.challenges[i] ) );
+	Com_Memset( challengeptr, 0, sizeof(*challengeptr) );
 }
 #endif
 
@@ -535,9 +540,11 @@
 		// see if we already have a challenge for this ip
 		challenge = &svs.challenges[0];
 
-		for (i = 0 ; i < MAX_CHALLENGES ; i++, challenge++) {
-			if ( NET_CompareAdr( drop->netchan.remoteAddress, challenge->adr ) ) {
-				challenge->connected = qfalse;
+		for (i = 0 ; i < MAX_CHALLENGES ; i++, challenge++)
+		{
+			if(NET_CompareAdr(drop->netchan.remoteAddress, challenge->adr))
+			{
+				Com_Memset(challenge, 0, sizeof(*challenge));
 				break;
 			}
 		}

Modified: trunk/code/server/sv_main.c
===================================================================
--- trunk/code/server/sv_main.c	2009-06-01 00:18:02 UTC (rev 1565)
+++ trunk/code/server/sv_main.c	2009-06-01 05:28:47 UTC (rev 1566)
@@ -548,7 +548,7 @@
   } else if (!Q_stricmp(c, "getinfo")) {
 		SVC_Info( from );
 	} else if (!Q_stricmp(c, "getchallenge")) {
-		SV_GetChallenge( from );
+		SV_GetChallenge(from);
 	} else if (!Q_stricmp(c, "connect")) {
 		SV_DirectConnect( from );
 #ifndef STANDALONE



More information about the quake3-commits mailing list