r777 - in trunk/code: qcommon server

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Mon May 8 15:53:41 EDT 2006


Author: thilo
Date: 2006-05-08 15:53:41 -0400 (Mon, 08 May 2006)
New Revision: 777

Modified:
   trunk/code/qcommon/files.c
   trunk/code/server/sv_client.c
Log:
Fix bug that permits download of arbitrary files from a download enabled server by checking requested file name against the list of loaded pk3 files. See CVE-2006-2082


Modified: trunk/code/qcommon/files.c
===================================================================
--- trunk/code/qcommon/files.c	2006-05-07 10:48:13 UTC (rev 776)
+++ trunk/code/qcommon/files.c	2006-05-08 19:53:41 UTC (rev 777)
@@ -2556,16 +2556,9 @@
 */
 qboolean FS_idPak( char *pak, char *base ) {
 	int i;
-	char pakbuf[MAX_QPATH], *pakptr;
 
-	// Chop off filename extension if necessary.
-	Com_sprintf(pakbuf, sizeof(pakbuf), "%s", pak);
-	pakptr = Q_strrchr(pakbuf, '.');
-	if(pakptr)
-		*pakptr = '\0';
-
 	for (i = 0; i < NUM_ID_PAKS; i++) {
-		if ( !FS_FilenameCompare(pakbuf, va("%s/pak%d", base, i)) ) {
+		if ( !FS_FilenameCompare(pak, va("%s/pak%d", base, i)) ) {
 			break;
 		}
 	}

Modified: trunk/code/server/sv_client.c
===================================================================
--- trunk/code/server/sv_client.c	2006-05-07 10:48:13 UTC (rev 776)
+++ trunk/code/server/sv_client.c	2006-05-08 19:53:41 UTC (rev 777)
@@ -756,24 +756,60 @@
 	int curindex;
 	int rate;
 	int blockspersnap;
-	int idPack, missionPack;
+	int idPack, missionPack, unreferenced = 1;
 	char errorMessage[1024];
+	char pakbuf[MAX_QPATH], *pakptr;
+	int numRefPaks;
 
 	if (!*cl->downloadName)
 		return;	// Nothing being downloaded
 
 	if (!cl->download) {
-		// We open the file here
+ 		// Chop off filename extension.
+		Com_sprintf(pakbuf, sizeof(pakbuf), "%s", cl->downloadName);
+		pakptr = Q_strrchr(pakbuf, '.');
+		
+		if(pakptr)
+		{
+			*pakptr = '\0';
 
-		Com_Printf( "clientDownload: %d : begining \"%s\"\n", cl - svs.clients, cl->downloadName );
+			// Check for pk3 filename extension
+			if(!Q_stricmp(pakptr + 1, "pk3"))
+			{
+				const char *referencedPaks = FS_ReferencedPakNames();
 
-		missionPack = FS_idPak(cl->downloadName, "missionpack");
-		idPack = missionPack || FS_idPak(cl->downloadName, BASEGAME);
+				// Check whether the file appears in the list of referenced
+				// paks to prevent downloading of arbitrary files.
+				Cmd_TokenizeStringIgnoreQuotes(referencedPaks);
+				numRefPaks = Cmd_Argc();
 
-		if ( !sv_allowDownload->integer || idPack ||
+				for(curindex = 0; curindex < numRefPaks; curindex++)
+				{
+					if(!FS_FilenameCompare(Cmd_Argv(curindex), pakbuf))
+					{
+						unreferenced = 0;
+
+						// now that we know the file is referenced,
+						// check whether it's legal to download it.
+						missionPack = FS_idPak(pakbuf, "missionpack");
+						idPack = missionPack || FS_idPak(pakbuf, BASEGAME);
+
+						break;
+					}
+				}
+			}
+		}
+
+		// We open the file here
+		if ( !sv_allowDownload->integer || idPack || unreferenced ||
 			( cl->downloadSize = FS_SV_FOpenFileRead( cl->downloadName, &cl->download ) ) <= 0 ) {
 			// cannot auto-download file
-			if (idPack) {
+			if(unreferenced)
+			{
+				Com_Printf("clientDownload: %d : \"%s\" is not referenced and cannot be downloaded.\n", cl - svs.clients, cl->downloadName);
+				Com_sprintf(errorMessage, sizeof(errorMessage), "File \"%s\" is not referenced and cannot be downloaded.", cl->downloadName);
+			}
+			else if (idPack) {
 				Com_Printf("clientDownload: %d : \"%s\" cannot download id pk3 files\n", cl - svs.clients, cl->downloadName);
 				if (missionPack) {
 					Com_sprintf(errorMessage, sizeof(errorMessage), "Cannot autodownload Team Arena file \"%s\"\n"
@@ -809,6 +845,8 @@
 			return;
 		}
  
+		Com_Printf( "clientDownload: %d : beginning \"%s\"\n", cl - svs.clients, cl->downloadName );
+		
 		// Init
 		cl->downloadCurrentBlock = cl->downloadClientBlock = cl->downloadXmitBlock = 0;
 		cl->downloadCount = 0;




More information about the quake3-commits mailing list