r811 - in trunk: . code/client code/qcommon

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Mon Jul 3 17:37:51 EDT 2006


Author: thilo
Date: 2006-07-03 17:37:50 -0400 (Mon, 03 Jul 2006)
New Revision: 811

Modified:
   trunk/README
   trunk/code/client/cl_parse.c
   trunk/code/qcommon/cvar.c
   trunk/code/qcommon/files.c
   trunk/code/qcommon/q_shared.h
   trunk/code/qcommon/qcommon.h
Log:
- Fix arbitrary cvar overwrite flaw: http://aluigi.altervista.org/adv.htm
- Add myself to maintainer list :)


Modified: trunk/README
===================================================================
--- trunk/README	2006-06-17 21:01:57 UTC (rev 810)
+++ trunk/README	2006-07-03 21:37:50 UTC (rev 811)
@@ -244,6 +244,7 @@
   Aaron Gyes <floam at sh dot nu>
   Ludwig Nussel <ludwig.nussel at suse.de>
   Ryan C. Gordon <icculus at icculus.org>
+  Thilo Schulz <arny at ats.s.bawue.de>
   Tim Angus <tim at ngus.net>
   Zachary J. Slater <zakk at timedoctor.org>
 

Modified: trunk/code/client/cl_parse.c
===================================================================
--- trunk/code/client/cl_parse.c	2006-06-17 21:01:57 UTC (rev 810)
+++ trunk/code/client/cl_parse.c	2006-07-03 21:37:50 UTC (rev 811)
@@ -368,16 +368,35 @@
 	// scan through all the variables in the systeminfo and locally set cvars to match
 	s = systemInfo;
 	while ( s ) {
+		int cvar_flags;
+		
 		Info_NextPair( &s, key, value );
 		if ( !key[0] ) {
 			break;
 		}
+		
 		// ehw!
-		if ( !Q_stricmp( key, "fs_game" ) ) {
+		if (!Q_stricmp(key, "fs_game"))
+		{
+			if(FS_CheckDirTraversal(value))
+			{
+				Com_Printf("WARNING: Server sent invalid fs_game value %s\n", value);
+				continue;
+			}
+				
 			gameSet = qtrue;
 		}
 
-		Cvar_Set( key, value );
+		if((cvar_flags = Cvar_Flags(key)) == CVAR_NONEXISTENT)
+			Cvar_Get(key, value, CVAR_SERVER_CREATED | CVAR_ROM);
+		else
+		{
+			// If this cvar may not be modified by a server discard the value.
+			if(!(cvar_flags & (CVAR_SYSTEMINFO | CVAR_SERVER_CREATED)))
+				continue;
+
+			Cvar_Set(key, value);
+		}
 	}
 	// if game folder should not be set and it is set at the client side
 	if ( !gameSet && *Cvar_VariableString("fs_game") ) {

Modified: trunk/code/qcommon/cvar.c
===================================================================
--- trunk/code/qcommon/cvar.c	2006-06-17 21:01:57 UTC (rev 810)
+++ trunk/code/qcommon/cvar.c	2006-07-03 21:37:50 UTC (rev 811)
@@ -161,6 +161,20 @@
 	}
 }
 
+/*
+============
+Cvar_Flags
+============
+*/
+int Cvar_Flags(const char *var_name)
+{
+	cvar_t *var;
+	
+	if(! (var = Cvar_FindVar(var_name)) )
+		return CVAR_NONEXISTENT;
+	else
+		return var->flags;
+}
 
 /*
 ============

Modified: trunk/code/qcommon/files.c
===================================================================
--- trunk/code/qcommon/files.c	2006-06-17 21:01:57 UTC (rev 810)
+++ trunk/code/qcommon/files.c	2006-07-03 21:37:50 UTC (rev 811)
@@ -2570,6 +2570,23 @@
 
 /*
 ================
+FS_idPak
+
+Check whether the string contains stuff like "../" to prevent directory traversal bugs
+and return qtrue if it does.
+================
+*/
+
+qboolean FS_CheckDirTraversal(const char *checkdir)
+{
+	if(strstr(checkdir, "../") || strstr(checkdir, "..\\"))
+		return qtrue;
+	
+	return qfalse;
+}
+
+/*
+================
 FS_ComparePaks
 
 ----------------
@@ -2617,7 +2634,7 @@
 		}
 
 		// Make sure the server cannot make us write to non-quake3 directories.
-		if(strstr(fs_serverReferencedPakNames[i], "../") || strstr(fs_serverReferencedPakNames[i], "..\\"))
+		if(FS_CheckDirTraversal(fs_serverReferencedPakNames[i]))
                 {
 			Com_Printf("WARNING: Invalid download name %s\n", fs_serverReferencedPakNames[i]);
                         continue;

Modified: trunk/code/qcommon/q_shared.h
===================================================================
--- trunk/code/qcommon/q_shared.h	2006-06-17 21:01:57 UTC (rev 810)
+++ trunk/code/qcommon/q_shared.h	2006-07-03 21:37:50 UTC (rev 811)
@@ -756,6 +756,9 @@
 #define CVAR_CHEAT			512	// can not be changed if cheats are disabled
 #define CVAR_NORESTART		1024	// do not clear when a cvar_restart is issued
 
+#define CVAR_SERVER_CREATED	2048	// cvar was created by a server the client connected to.
+#define CVAR_NONEXISTENT	0xFFFFFFFF	// Cvar doesn't exist.
+
 // nothing outside the Cvar_*() functions should modify these fields!
 typedef struct cvar_s {
 	char		*name;

Modified: trunk/code/qcommon/qcommon.h
===================================================================
--- trunk/code/qcommon/qcommon.h	2006-06-17 21:01:57 UTC (rev 810)
+++ trunk/code/qcommon/qcommon.h	2006-07-03 21:37:50 UTC (rev 811)
@@ -480,6 +480,9 @@
 void	Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize );
 // returns an empty string if not defined
 
+int	Cvar_Flags(const char *var_name);
+// returns CVAR_NONEXISTENT if cvar doesn't exist or the flags of that particular CVAR.
+
 void	Cvar_CommandCompletion( void(*callback)(const char *s) );
 // callback with each valid string
 
@@ -648,6 +651,7 @@
 // separated checksums will be checked for files, with the
 // sole exception of .cfg files.
 
+qboolean FS_CheckDirTraversal(const char *checkdir);
 qboolean FS_idPak( char *pak, char *base );
 qboolean FS_ComparePaks( char *neededpaks, int len, qboolean dlstring );
 




More information about the quake3-commits mailing list