X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=fs.c;h=8bf3d1c56d905387eaebd12d69ef14752a90cde5;hb=a19dce25671ecfa28e4eb3861f8636750bf3ba68;hp=5a849e1466548dc2fbb9392390f6bb09b367f2b9;hpb=6d0fd928a5ea2089a7bc959d1e98e9383e3ee289;p=xonotic%2Fdarkplaces.git diff --git a/fs.c b/fs.c index 5a849e14..8bf3d1c5 100644 --- a/fs.c +++ b/fs.c @@ -1105,7 +1105,7 @@ void FS_Rescan_f (void) fs_modified = true; FS_AddGameHierarchy (fs_gamedirs[i]); // update the com_modname (used server info) - strlcpy (com_modname, com_argv[i], sizeof (com_modname)); + strlcpy (com_modname, fs_gamedirs[i], sizeof (com_modname)); } // set the default screenshot name to either the mod name or the @@ -1143,12 +1143,20 @@ FS_ChangeGameDir */ void Host_SaveConfig_f (void); void Host_LoadConfig_f (void); +int FS_CheckNastyPath (const char *path, qboolean isgamedir); qboolean FS_ChangeGameDir(const char *string) { // if already using the requested gamedir, do nothing if (fs_numgamedirs == 1 && !strcmp(fs_gamedirs[0], string)) return false; + // if string is nasty, reject it + if(FS_CheckNastyPath(string, true)) // overflowed or nasty? + { + Con_Printf("FS_ChangeGameDir(\"%s\"): nasty filename rejected\n", string); + return false; + } + // save the current config Host_SaveConfig_f(); @@ -1200,6 +1208,13 @@ void FS_GameDir_f (void) fs_numgamedirs = 0; for (i = 1;i < Cmd_Argc() && fs_numgamedirs < MAX_GAMEDIRS;i++) { + // if string is nasty, reject it + if(FS_CheckNastyPath(Cmd_Argv(i), true)) // overflowed or nasty? + { + Con_Printf("FS_GameDir_f(\"%s\"): nasty filename rejected\n", Cmd_Argv(i)); + continue; + } + strlcpy(fs_gamedirs[fs_numgamedirs], Cmd_Argv(i), sizeof(fs_gamedirs[fs_numgamedirs])); fs_numgamedirs++; } @@ -1419,7 +1434,7 @@ qfile_t *FS_OpenPackedFile (pack_t* pack, int pack_ind) if (lseek (pack->handle, pfile->offset, SEEK_SET) == -1) { Con_Printf ("FS_OpenPackedFile: can't lseek to %s in %s (offset: %d)\n", - pfile->name, pack->filename, pfile->offset); + pfile->name, pack->filename, (int) pfile->offset); return NULL; } @@ -1490,8 +1505,12 @@ Return true if the path should be rejected due to one of the following: or are just not a good idea for a mod to be using. ==================== */ -int FS_CheckNastyPath (const char *path) +int FS_CheckNastyPath (const char *path, qboolean isgamedir) { + // all: never allow an empty path, as for gamedir it would access the parent directory and a non-gamedir path it is just useless + if (!path[0]) + return 2; + // Windows: don't allow \ in filenames (windows-only), period. // (on Windows \ is a directory separator, but / is also supported) if (strstr(path, "\\")) @@ -1508,14 +1527,34 @@ int FS_CheckNastyPath (const char *path) if (strstr(path, "//")) return 1; // non-portable attempt to go to parent directory - // all: don't allow going to current directory (./) or parent directory (../ or /../) - if (strstr(path, "./")) + // all: don't allow going to parent directory (../ or /../) + if (strstr(path, "..")) return 2; // attempt to go outside the game directory // Windows and UNIXes: don't allow absolute paths if (path[0] == '/') return 2; // attempt to go outside the game directory + // all: don't allow . characters before the last slash (it should only be used in filenames, not path elements), this catches all imaginable cases of ./, ../, .../, etc + if (strchr(path, '.')) + { + if (isgamedir) + { + // gamedir is entirely path elements, so simply forbid . entirely + return 2; + } + if (strchr(path, '.') < strrchr(path, '/')) + return 2; // possible attempt to go outside the game directory + } + + // all: forbid trailing slash on gamedir + if (isgamedir && path[strlen(path)-1] == '/') + return 2; + + // all: forbid leading dot on any filename for any reason + if (strstr(path, "/.")) + return 2; // attempt to go outside the game directory + // after all these checks we're pretty sure it's a / separated filename // and won't do much if any harm return false; @@ -1651,7 +1690,7 @@ Open a file. The syntax is the same as fopen */ qfile_t* FS_Open (const char* filepath, const char* mode, qboolean quiet, qboolean nonblocking) { - if (FS_CheckNastyPath(filepath)) + if (FS_CheckNastyPath(filepath, false)) { Con_Printf("FS_Open(\"%s\", \"%s\", %s): nasty filename rejected\n", filepath, mode, quiet ? "true" : "false"); return NULL;