From 5e166cb9cebfa51e5ac451fdbfb1efda52ed9542 Mon Sep 17 00:00:00 2001 From: Spoike Date: Sun, 25 May 2008 22:02:52 +0000 Subject: [PATCH] Made the (currently disabled) http download code more secure. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2975 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- fteqtv/control.c | 3 ++- fteqtv/httpsv.c | 51 ++++++++++++++++++++++++++++++++++++++++++------ fteqtv/qtv.h | 3 +++ 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/fteqtv/control.c b/fteqtv/control.c index ca09a5b93..80d49856d 100644 --- a/fteqtv/control.c +++ b/fteqtv/control.c @@ -503,7 +503,8 @@ int main(int argc, char **argv) strcpy(cluster->hostname, DEFAULT_HOSTNAME); cluster->buildnumber = build_number(); cluster->maxproxies = -1; - + + strcpy(cluster->downloaddir, "id1/"); strcpy(cluster->demodir, "qw/demos/"); Sys_Printf(cluster, "QTV Build %i.\n", cluster->buildnumber); diff --git a/fteqtv/httpsv.c b/fteqtv/httpsv.c index 781aadc83..e19b4d7cc 100644 --- a/fteqtv/httpsv.c +++ b/fteqtv/httpsv.c @@ -562,8 +562,10 @@ static void HTTPSV_GenerateDemoListing(cluster_t *cluster, oproxy_t *dest) static void HTTPSV_GenerateDownload(cluster_t *cluster, oproxy_t *dest, char *filename) { #ifdef ALLOWDOWNLOADS - char fname[256]; - char *s; + char fname[256]; + char link[512]; + char *s, *suppliedname; + int len; if (cluster->allowdownloads) #endif @@ -575,8 +577,8 @@ static void HTTPSV_GenerateDownload(cluster_t *cluster, oproxy_t *dest, char *fi HTTPSV_SendHTMLFooter(cluster, dest); return; } -#ifdef ALLOWDOWNLOADS - s = fname; +#ifdef ALLOWDOWNLOADS + suppliedname = s = fname + strlcpy(fname, cluster->downloaddir, sizeof(fname)); while (*filename > ' ') { if (s > fname + sizeof(fname)-4) //4 cos I'm too lazy to work out what the actual number should be @@ -611,7 +613,38 @@ static void HTTPSV_GenerateDownload(cluster_t *cluster, oproxy_t *dest, char *fi else *s++ = *filename++; } - *s = 0; + *s = 0; + + if (*suppliedname == '\\' || *suppliedname == '/' || strstr(suppliedname, "..") || suppliedname[1] == ':') + { + HTTPSV_SendHTTPHeader(cluster, dest, "403", "text/html", true); + HTTPSV_SendHTMLHeader(cluster, dest, "Permission denied"); + HTMLPRINT("

403: Forbidden

"); + + HTMLPRINT("

"); + HTMLprintf(link, sizeof(link), "The filename '%s' names an absolute path.", suppliedname); + Net_ProxySend(cluster, dest, link, strlen(link)); + HTMLPRINT("

"); + return; + } + len = strlen(fname); + if (len > 4) + { + if (!stricmp(link+len-4, ".pak")) + { + HTTPSV_SendHTTPHeader(cluster, dest, "403", "text/html", true); + HTTPSV_SendHTMLHeader(cluster, dest, "Permission denied"); + HTMLPRINT("

403: Forbidden

"); + + HTMLPRINT("

"); + HTMLprintf(link, sizeof(link), "Pak files may not be downloaded.", suppliedname); + Net_ProxySend(cluster, dest, link, strlen(link)); + HTMLPRINT("

"); + return; + } + } + + dest->srcfile = fopen(fname, "rb"); if (dest->srcfile) @@ -622,7 +655,13 @@ static void HTTPSV_GenerateDownload(cluster_t *cluster, oproxy_t *dest, char *fi { HTTPSV_SendHTTPHeader(cluster, dest, "404", "text/html", true); HTTPSV_SendHTMLHeader(cluster, dest, "File not found"); - HTMLPRINT("

404: File not found

"); + HTMLPRINT("

404: File not found

"); + + HTMLPRINT("

"); + HTMLprintf(link, sizeof(link), "The file '%s' could not be found on this server", fname); + Net_ProxySend(cluster, dest, link, strlen(link)); + HTMLPRINT("

"); + HTTPSV_SendHTMLFooter(cluster, dest); } #endif diff --git a/fteqtv/qtv.h b/fteqtv/qtv.h index f4388a87a..7a510155e 100644 --- a/fteqtv/qtv.h +++ b/fteqtv/qtv.h @@ -629,6 +629,7 @@ struct cluster_s { char hostname[256]; char master[MAX_QPATH]; char demodir[MAX_QPATH]; + char downloaddir[MAX_QPATH]; //must be slash terminated, or empty. qboolean chokeonnotupdated; qboolean lateforward; qboolean notalking; @@ -636,6 +637,8 @@ struct cluster_s { qboolean allownqclients; //nq clients require no challenge qboolean nouserconnects; //prohibit users from connecting to new streams. + qboolean allowdownloads; + int maxviewers; int buildnumber;