mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-02-08 17:22:18 +00:00
Disallow adding files with absolute path or traversing upward
(Except as part of srb2home, srb2path or addons_folder -- this lets addons menu work, primarily.) - disallowed when using addfile or addfolder - security check for xcmd receive
This commit is contained in:
parent
373af01092
commit
b1a86b0b34
3 changed files with 94 additions and 22 deletions
71
src/d_main.c
71
src/d_main.c
|
@ -1689,3 +1689,74 @@ const char *D_Home(void)
|
||||||
if (usehome) return userhome;
|
if (usehome) return userhome;
|
||||||
else return NULL;
|
else return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boolean check_top_dir(const char **path, const char *top)
|
||||||
|
{
|
||||||
|
// empty string does NOT match
|
||||||
|
if (!strcmp(top, ""))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!startswith(*path, top))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*path += strlen(top);
|
||||||
|
|
||||||
|
// if it doesn't already end with a path separator,
|
||||||
|
// check if a separator follows
|
||||||
|
if (!endswith(top, PATHSEP))
|
||||||
|
{
|
||||||
|
if (startswith(*path, PATHSEP))
|
||||||
|
*path += strlen(PATHSEP);
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmp_strlen_desc(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
return ((int)strlen(*(const char*const*)b) - (int)strlen(*(const char*const*)a));
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean D_IsPathAllowed(const char *path)
|
||||||
|
{
|
||||||
|
const char *paths[] = {
|
||||||
|
srb2home,
|
||||||
|
srb2path,
|
||||||
|
cv_addons_folder.string
|
||||||
|
};
|
||||||
|
|
||||||
|
const size_t n_paths = sizeof paths / sizeof *paths;
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
// Sort folder paths by longest to shortest so
|
||||||
|
// overlapping paths work. E.g.:
|
||||||
|
// Path 1: /home/james/.srb2/addons
|
||||||
|
// Path 2: /home/james/.srb2
|
||||||
|
qsort(paths, n_paths, sizeof *paths, cmp_strlen_desc);
|
||||||
|
|
||||||
|
// These paths are allowed to be absolute
|
||||||
|
// path is offset so ".." can be checked only in the
|
||||||
|
// rest of the path
|
||||||
|
for (i = 0; i < n_paths; ++i)
|
||||||
|
{
|
||||||
|
if (check_top_dir(&path, paths[i]))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only if none of the presets matched
|
||||||
|
if (i == n_paths)
|
||||||
|
{
|
||||||
|
// Cannot be an absolute path
|
||||||
|
if (M_IsPathAbsolute(path))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cannot traverse upwards
|
||||||
|
if (strstr(path, ".."))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -44,6 +44,8 @@ void D_ProcessEvents(void);
|
||||||
|
|
||||||
const char *D_Home(void);
|
const char *D_Home(void);
|
||||||
|
|
||||||
|
boolean D_IsPathAllowed(const char *path);
|
||||||
|
|
||||||
//
|
//
|
||||||
// BASE LEVEL
|
// BASE LEVEL
|
||||||
//
|
//
|
||||||
|
|
|
@ -7860,8 +7860,10 @@ static lumpinfo_t* FindFolder(const char *folName, UINT16 *start, UINT16 *end, l
|
||||||
// Add a wadfile to the active wad files,
|
// Add a wadfile to the active wad files,
|
||||||
// replace sounds, musics, patches, textures, sprites and maps
|
// replace sounds, musics, patches, textures, sprites and maps
|
||||||
//
|
//
|
||||||
static boolean P_LoadAddon(UINT16 wadnum, UINT16 numlumps)
|
static boolean P_LoadAddon(UINT16 numlumps)
|
||||||
{
|
{
|
||||||
|
const UINT16 wadnum = (UINT16)(numwadfiles-1);
|
||||||
|
|
||||||
size_t i, j, sreplaces = 0, mreplaces = 0, digmreplaces = 0;
|
size_t i, j, sreplaces = 0, mreplaces = 0, digmreplaces = 0;
|
||||||
char *name;
|
char *name;
|
||||||
lumpinfo_t *lumpinfo;
|
lumpinfo_t *lumpinfo;
|
||||||
|
@ -7883,6 +7885,12 @@ static boolean P_LoadAddon(UINT16 wadnum, UINT16 numlumps)
|
||||||
// UINT16 flaPos, flaNum = 0;
|
// UINT16 flaPos, flaNum = 0;
|
||||||
// UINT16 mapPos, mapNum = 0;
|
// UINT16 mapPos, mapNum = 0;
|
||||||
|
|
||||||
|
if (numlumps == INT16_MAX)
|
||||||
|
{
|
||||||
|
refreshdirmenu |= REFRESHDIR_NOTLOADED;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
switch(wadfiles[wadnum]->type)
|
switch(wadfiles[wadnum]->type)
|
||||||
{
|
{
|
||||||
case RET_PK3:
|
case RET_PK3:
|
||||||
|
@ -8051,34 +8059,25 @@ static boolean P_LoadAddon(UINT16 wadnum, UINT16 numlumps)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean P_AddWadFile(const char *wadfilename)
|
static boolean P_CheckAddonPath(const char *path)
|
||||||
{
|
{
|
||||||
UINT16 numlumps, wadnum;
|
if (!D_IsPathAllowed(path))
|
||||||
|
|
||||||
// Init file.
|
|
||||||
if ((numlumps = W_InitFile(wadfilename, false, false)) == INT16_MAX)
|
|
||||||
{
|
{
|
||||||
refreshdirmenu |= REFRESHDIR_NOTLOADED;
|
CONS_Alert(CONS_WARNING, "%s: tried to add file, location is not allowed\n", path);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
wadnum = (UINT16)(numwadfiles-1);
|
|
||||||
|
|
||||||
return P_LoadAddon(wadnum, numlumps);
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean P_AddWadFile(const char *wadfilename)
|
||||||
|
{
|
||||||
|
return P_CheckAddonPath(wadfilename) &&
|
||||||
|
P_LoadAddon(W_InitFile(wadfilename, false, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean P_AddFolder(const char *folderpath)
|
boolean P_AddFolder(const char *folderpath)
|
||||||
{
|
{
|
||||||
UINT16 numlumps, wadnum;
|
return P_CheckAddonPath(folderpath) &&
|
||||||
|
P_LoadAddon(W_InitFolder(folderpath, false, false));
|
||||||
// Init file.
|
|
||||||
if ((numlumps = W_InitFolder(folderpath, false, false)) == INT16_MAX)
|
|
||||||
{
|
|
||||||
refreshdirmenu |= REFRESHDIR_NOTLOADED;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
wadnum = (UINT16)(numwadfiles-1);
|
|
||||||
|
|
||||||
return P_LoadAddon(wadnum, numlumps);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue