/* ================== SV_BeginDownload_f ================== */ void SV_BeginDownload_f(void){ char *name; extern cvar_t *allow_download; extern cvar_t *allow_download_players; extern cvar_t *allow_download_models; extern cvar_t *allow_download_sounds; extern cvar_t *allow_download_maps; extern int file_from_pak; // ZOID did file come from pak? int offset = 0; name = Cmd_Argv(1); if(Cmd_Argc() > 2) offset = atoi(Cmd_Argv(2)); // downloaded offset // hacked by zoid to allow more conrol over download // first off, no .. or global allow check if(strstr(name, "..") || strstr(name, "\\/") || !allow_download->value // leading dot is no good || *name == '.' // leading slash bad as well, must be in subdir || *name == '/' // next up, skin check ||(strncmp(name, "players/", 6) == 0 && !allow_download_players->value) // now models ||(strncmp(name, "models/", 6) == 0 && !allow_download_models->value) // now sounds ||(strncmp(name, "sound/", 6) == 0 && !allow_download_sounds->value) // now maps(note special case for maps, must not be in pak) ||(strncmp(name, "maps/", 6) == 0 && !allow_download_maps->value) // MUST be in a subdirectory || !strstr(name, "/")){ // don't allow anything with .. path MSG_WriteByte(&sv_client->netchan.message, svc_download); MSG_WriteShort(&sv_client->netchan.message, -1); MSG_WriteByte(&sv_client->netchan.message, 0); return; } if(sv_client->download) FS_FreeFile(sv_client->download); sv_client->downloadsize = FS_LoadFile(name, (void **)(char *)&sv_client->download); sv_client->downloadcount = offset; if(offset > sv_client->downloadsize) sv_client->downloadcount = sv_client->downloadsize; if(!sv_client->download // special check for maps, if it came from a pak file, don't allow // download ZOID ||(strncmp(name, "maps/", 5) == 0 && file_from_pak)){ Com_DPrintf("Couldn't download %s to %s\n", name, sv_client->name); if(sv_client->download){ FS_FreeFile(sv_client->download); sv_client->download = NULL; } MSG_WriteByte(&sv_client->netchan.message, svc_download); MSG_WriteShort(&sv_client->netchan.message, -1); MSG_WriteByte(&sv_client->netchan.message, 0); return; } SV_NextDownload_f(); Com_DPrintf("Downloading %s to %s\n", name, sv_client->name); }
void SV_BeginDownload_f(void) { char *name; extern cvar_t *allow_download; extern cvar_t *allow_download_players; extern cvar_t *allow_download_models; extern cvar_t *allow_download_sounds; extern cvar_t *allow_download_maps; extern int file_from_pak; int offset = 0; name = Cmd_Argv(1); if (Cmd_Argc() > 2) { offset = (int)strtol(Cmd_Argv(2), (char **)NULL, 10); /* downloaded offset */ } /* hacked by zoid to allow more conrol over download first off, no .. or global allow check */ if (strstr(name, "..") || strstr(name, "\\") || !allow_download->value /* leading dot is no good */ || (*name == '.') /* leading slash bad as well, must be in subdir */ || (*name == '/') /* next up, skin check */ || ((strncmp(name, "players/", 6) == 0) && !allow_download_players->value) /* now models */ || ((strncmp(name, "models/", 6) == 0) && !allow_download_models->value) /* now sounds */ || ((strncmp(name, "sound/", 6) == 0) && !allow_download_sounds->value) /* now maps (note special case for maps, must not be in pak) */ || ((strncmp(name, "maps/", 6) == 0) && !allow_download_maps->value) /* MUST be in a subdirectory */ || !strstr(name, "/")) { MSG_WriteByte(&sv_client->netchan.message, svc_download); MSG_WriteShort(&sv_client->netchan.message, -1); MSG_WriteByte(&sv_client->netchan.message, 0); return; } if (sv_client->download) { FS_FreeFile(sv_client->download); } sv_client->downloadsize = FS_LoadFile(name, (void **)&sv_client->download); sv_client->downloadcount = offset; if (offset > sv_client->downloadsize) { sv_client->downloadcount = sv_client->downloadsize; } if (!sv_client->download || ((strncmp(name, "maps/", 5) == 0) && file_from_pak)) { Com_DPrintf("Couldn't download %s to %s\n", name, sv_client->name); if (sv_client->download) { FS_FreeFile(sv_client->download); sv_client->download = NULL; } MSG_WriteByte(&sv_client->netchan.message, svc_download); MSG_WriteShort(&sv_client->netchan.message, -1); MSG_WriteByte(&sv_client->netchan.message, 0); return; } SV_NextDownload_f(); Com_DPrintf("Downloading %s to %s\n", name, sv_client->name); }
/* ================== SV_BeginDownload_f ================== */ static void SV_BeginDownload_f(void) { char name[MAX_OSPATH], *p; q_strlcpy (name, Cmd_Argv(1), sizeof(name)); // hacked by zoid to allow more conrol over download // first off, no .. or global allow check if (strstr (name, "..") || !allow_download.integer // leading dot is no good || *name == '.' // leading slash bad as well, must be in subdir || *name == '/' // next up, skin check || (strncmp(name, "skins/", 6) == 0 && !allow_download_skins.integer) // now models || (strncmp(name, "models/", 6) == 0 && !allow_download_models.integer) // now sounds || (strncmp(name, "sound/", 6) == 0 && !allow_download_sounds.integer) // now maps (note special case for maps, must not be in pak) || (strncmp(name, "maps/", 6) == 0 && !allow_download_maps.integer) // MUST be in a subdirectory || !strstr (name, "/") ) { // don't allow anything with .. path MSG_WriteByte (&host_client->netchan.message, svc_download); MSG_WriteShort (&host_client->netchan.message, -1); MSG_WriteByte (&host_client->netchan.message, 0); return; } if (host_client->download) { fclose (host_client->download); host_client->download = NULL; } // lowercase the name (needed for case sensitive file systems) for (p = name; *p; p++) *p = (char)tolower(*p); host_client->downloadsize = FS_OpenFile (name, &host_client->download, false); host_client->downloadcount = 0; if (!host_client->download // special check for maps, if it came from a pak file, // don't allow download ZOID || (strncmp(name, "maps/", 5) == 0 && file_from_pak)) { if (host_client->download) { fclose(host_client->download); host_client->download = NULL; } Sys_Printf ("Couldn't download %s to %s\n", name, host_client->name); MSG_WriteByte (&host_client->netchan.message, svc_download); MSG_WriteShort (&host_client->netchan.message, -1); MSG_WriteByte (&host_client->netchan.message, 0); return; } SV_NextDownload_f (); Sys_Printf ("Downloading %s to %s\n", name, host_client->name); }
/* ================== SV_BeginDownload_f ================== */ void SV_BeginDownload_f(void) { char *name, *p; size_t length; qboolean valid; // extern int file_from_pak; // ZOID did file come from pak? int offset = 0; name = Cmd_Argv(1); if (Cmd_Argc() > 2) offset = atoi(Cmd_Argv(2)); // downloaded offset // r1ch fix: name is always filtered for security reasons StripHighBits (name, 1); // hacked by zoid to allow more conrol over download // first off, no .. or global allow check // r1ch fix: for some ./ references in maps, eg ./textures/map/file length = strlen(name); p = name; while ((p = strstr (p, "./"))) { memmove (p, p+2, length - (p - name) - 1); length -= 2; } // r1ch fix: block the really nasty ones - \server.cfg will download from mod root on win32, .. is obvious if (name[0] == '\\' || strstr (name, "..")) { Com_Printf ("Refusing illegal download path %s to %s\n", name, sv_client->name); MSG_WriteByte (&sv_client->netchan.message, svc_download); MSG_WriteShort (&sv_client->netchan.message, -1); MSG_WriteByte (&sv_client->netchan.message, 0); Com_Printf ("Client %s[%s] tried to download illegal path: %s\n", sv_client->name, NET_AdrToString (sv_client->netchan.remote_address), name); SV_DropClient (sv_client); return; } else if (offset < 0) // r1ch fix: negative offset will crash on read { Com_Printf ("Refusing illegal download offset %d to %s\n", offset, sv_client->name); MSG_WriteByte (&sv_client->netchan.message, svc_download); MSG_WriteShort (&sv_client->netchan.message, -1); MSG_WriteByte (&sv_client->netchan.message, 0); Com_Printf ("Client %s[%s] supplied illegal download offset for %s: %d\n", sv_client->name, NET_AdrToString (sv_client->netchan.remote_address), name, offset); SV_DropClient (sv_client); return; } else if ( !length || name[0] == 0 // empty name, maybe as result of ./ normalize || !IsValidChar(name[0]) // r1ch: \ is bad in general, client won't even write properly if we do sent it || strchr (name, '\\') // MUST be in a subdirectory, unless a pk3 || (!strstr (name, "/") && strcmp(name+strlen(name)-4, ".pk3")) // r1ch: another bug, maps/. will fopen(".") -> crash || !IsValidChar(name[length-1]) ) /* if (strstr (name, "..") || !allow_download->value // leading dot is no good || *name == '.' // leading slash bad as well, must be in subdir || *name == '/' // next up, skin check || (strncmp(name, "players/", 8) == 0 && !allow_download_players->value) // now models || (strncmp(name, "models/", 7) == 0 && !allow_download_models->value) // now sounds || (strncmp(name, "sound/", 6) == 0 && !allow_download_sounds->value) // now maps (note special case for maps, must not be in pak) || (strncmp(name, "maps/", 5) == 0 && !allow_download_maps->value) // MUST be in a subdirectory, unless a pk3 || (!strstr (name, "/") && strcmp(name+strlen(name)-4, ".pk3")) ) */ { // don't allow anything with .. path MSG_WriteByte (&sv_client->netchan.message, svc_download); MSG_WriteShort (&sv_client->netchan.message, -1); MSG_WriteByte (&sv_client->netchan.message, 0); return; } valid = true; if ( !allow_download->value || (strncmp(name, "players/", 8) == 0 && !allow_download_players->value) || (strncmp(name, "models/", 7) == 0 && !allow_download_models->value) || (strncmp(name, "sound/", 6) == 0 && !allow_download_sounds->value) || (strncmp(name, "maps/", 5) == 0 && !allow_download_maps->value) || (strncmp(name, "pics/", 5) == 0 && !allow_download_pics->value) || ( ((strncmp(name, "env/", 4) == 0 || strncmp(name, "textures/", 9) == 0)) && !allow_download_textures->value ) ) valid = false; if (!valid) { MSG_WriteByte (&sv_client->netchan.message, svc_download); MSG_WriteShort (&sv_client->netchan.message, -1); MSG_WriteByte (&sv_client->netchan.message, 0); return; } if (sv_client->download) FS_FreeFile (sv_client->download); sv_client->downloadsize = FS_LoadFile (name, (void **)&sv_client->download); sv_client->downloadcount = offset; if (offset > sv_client->downloadsize) sv_client->downloadcount = sv_client->downloadsize; // ZOID- special check for maps, if it came from a pak file, don't allow download if (!sv_client->download || (strncmp(name, "maps/", 5) == 0 && file_from_pak)) { Com_DPrintf ("Couldn't download %s to %s\n", name, sv_client->name); if (sv_client->download) { FS_FreeFile (sv_client->download); sv_client->download = NULL; } MSG_WriteByte (&sv_client->netchan.message, svc_download); MSG_WriteShort (&sv_client->netchan.message, -1); MSG_WriteByte (&sv_client->netchan.message, 0); return; } SV_NextDownload_f (); Com_DPrintf ("Downloading %s to %s\n", name, sv_client->name); }
void SV_BeginDownload_f(void) { char *name; extern cvar_t allow_download; extern cvar_t allow_download_skins; extern cvar_t allow_download_models; extern cvar_t allow_download_sounds; extern cvar_t allow_download_maps; extern int file_from_pak; // ZOID did file come from pak? name = Cmd_Argv(1); // hacked by zoid to allow more conrol over download // first off, no .. or global allow check if (strstr (name, "..") || !allow_download.value // leading dot is no good || *name == '.' // leading slash bad as well, must be in subdir || *name == '/' // next up, skin check || (strncmp(name, "skins/", 6) == 0 && !allow_download_skins.value) // now models || (strncmp(name, "progs/", 6) == 0 && !allow_download_models.value) // now sounds || (strncmp(name, "sound/", 6) == 0 && !allow_download_sounds.value) // now maps (note special case for maps, must not be in pak) || (strncmp(name, "maps/", 6) == 0 && !allow_download_maps.value) // MUST be in a subdirectory || !strstr (name, "/") ) { // don't allow anything with .. path ClientReliableWrite_Begin (host_client, svc_download, 4); ClientReliableWrite_Short (host_client, -1); ClientReliableWrite_Byte (host_client, 0); return; } if (host_client->download) { fclose (host_client->download); host_client->download = NULL; } // lowercase name (needed for casesen file systems) { char *p; for (p = name; *p; p++) *p = (char)tolower(*p); } host_client->downloadsize = COM_FOpenFile (name, &host_client->download); host_client->downloadcount = 0; if (!host_client->download // special check for maps, if it came from a pak file, don't allow // download ZOID || (strncmp(name, "maps/", 5) == 0 && file_from_pak)) { if (host_client->download) { fclose(host_client->download); host_client->download = NULL; } Sys_Printf ("Couldn't download %s to %s\n", name, host_client->name); ClientReliableWrite_Begin (host_client, svc_download, 4); ClientReliableWrite_Short (host_client, -1); ClientReliableWrite_Byte (host_client, 0); return; } SV_NextDownload_f (); Sys_Printf ("Downloading %s to %s\n", name, host_client->name); }