diff options
| -rw-r--r-- | package/uhttpd/Makefile | 2 | ||||
| -rw-r--r-- | package/uhttpd/files/uhttpd.config | 8 | ||||
| -rwxr-xr-x | package/uhttpd/files/uhttpd.init | 1 | ||||
| -rw-r--r-- | package/uhttpd/src/uhttpd-file.c | 20 | ||||
| -rw-r--r-- | package/uhttpd/src/uhttpd-mimetypes.h | 97 | ||||
| -rw-r--r-- | package/uhttpd/src/uhttpd-utils.c | 82 | ||||
| -rw-r--r-- | package/uhttpd/src/uhttpd.c | 54 | ||||
| -rw-r--r-- | package/uhttpd/src/uhttpd.h | 4 | 
8 files changed, 186 insertions, 82 deletions
diff --git a/package/uhttpd/Makefile b/package/uhttpd/Makefile index 6b4db3e15..0f267be2a 100644 --- a/package/uhttpd/Makefile +++ b/package/uhttpd/Makefile @@ -8,7 +8,7 @@  include $(TOPDIR)/rules.mk  PKG_NAME:=uhttpd -PKG_RELEASE:=7 +PKG_RELEASE:=8  PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) diff --git a/package/uhttpd/files/uhttpd.config b/package/uhttpd/files/uhttpd.config index 79b018cf8..acdd62ea4 100644 --- a/package/uhttpd/files/uhttpd.config +++ b/package/uhttpd/files/uhttpd.config @@ -29,10 +29,16 @@ config uhttpd main  	# CGI/Lua timeout, if the called script does not  	# write data within the given amount of seconds, -	# the server will temrinate the request with +	# the server will terminate the request with  	# 504 Gateway Timeout response.  	option script_timeout	60 +	# Network timeout, if the current connection is +	# blocked for the specified amount of seconds, +	# the server will terminate the associated +	# request process. +	option network_timeout	30 +  	# Basic auth realm, defaults to local hostname  #	option realm	OpenWrt diff --git a/package/uhttpd/files/uhttpd.init b/package/uhttpd/files/uhttpd.init index 4b747a0da..14f8fc4c4 100755 --- a/package/uhttpd/files/uhttpd.init +++ b/package/uhttpd/files/uhttpd.init @@ -58,6 +58,7 @@ start_instance()  	append_arg "$cfg" lua_prefix "-l"  	append_arg "$cfg" lua_handler "-L"  	append_arg "$cfg" script_timeout "-t" +	append_arg "$cfg" network_timeout "-T"  	config_get http "$cfg" listen_http  	for listen in $http; do diff --git a/package/uhttpd/src/uhttpd-file.c b/package/uhttpd/src/uhttpd-file.c index 2a06f8520..81f66a34b 100644 --- a/package/uhttpd/src/uhttpd-file.c +++ b/package/uhttpd/src/uhttpd-file.c @@ -29,23 +29,21 @@  static const char * uh_file_mime_lookup(const char *path)  {  	struct mimetype *m = &uh_mime_types[0]; -	char *p, *pd, *ps; +	char *e; -	ps = strrchr(path, '/'); -	pd = strrchr(path, '.'); - -	/* use either slash or dot as separator, whatever comes last */ -	p = (ps && pd && (ps > pd)) ? ps : pd; - -	if( (p != NULL) && (*(++p) != 0) ) +	while( m->extn )  	{ -		while( m->extn ) +		e = &path[strlen(path)-1]; + +		while( e >= path )  		{ -			if( ! strcasecmp(p, m->extn) ) +			if( (*e == '.') && !strcasecmp(&e[1], m->extn) )  				return m->mime; -			m++; +			e--;  		} + +		m++;  	}  	return "application/octet-stream"; diff --git a/package/uhttpd/src/uhttpd-mimetypes.h b/package/uhttpd/src/uhttpd-mimetypes.h index 1c93f3113..032d3d0c2 100644 --- a/package/uhttpd/src/uhttpd-mimetypes.h +++ b/package/uhttpd/src/uhttpd-mimetypes.h @@ -20,58 +20,61 @@  static struct mimetype uh_mime_types[] = { -	{ "txt",    "text/plain" }, -	{ "log",    "text/plain" }, -	{ "js",     "text/javascript" }, -	{ "css",    "text/css" }, -	{ "htm",    "text/html" }, -	{ "html",   "text/html" }, -	{ "diff",   "text/x-patch" }, -	{ "patch",  "text/x-patch" }, -	{ "c",      "text/x-csrc" }, -	{ "h",      "text/x-chdr" }, -	{ "o",      "text/x-object" }, -	{ "ko",     "text/x-object" }, +	{ "txt",     "text/plain" }, +	{ "log",     "text/plain" }, +	{ "js",      "text/javascript" }, +	{ "css",     "text/css" }, +	{ "htm",     "text/html" }, +	{ "html",    "text/html" }, +	{ "diff",    "text/x-patch" }, +	{ "patch",   "text/x-patch" }, +	{ "c",       "text/x-csrc" }, +	{ "h",       "text/x-chdr" }, +	{ "o",       "text/x-object" }, +	{ "ko",      "text/x-object" }, -	{ "bmp",    "image/bmp" }, -	{ "gif",    "image/gif" }, -	{ "png",    "image/png" }, -	{ "jpg",    "image/jpeg" }, -	{ "jpeg",   "image/jpeg" }, -	{ "svg",    "image/svg+xml" }, +	{ "bmp",     "image/bmp" }, +	{ "gif",     "image/gif" }, +	{ "png",     "image/png" }, +	{ "jpg",     "image/jpeg" }, +	{ "jpeg",    "image/jpeg" }, +	{ "svg",     "image/svg+xml" }, -	{ "zip",    "application/zip" }, -	{ "pdf",    "application/pdf" }, -	{ "xml",    "application/xml" }, -	{ "xsl",    "application/xml" }, -	{ "doc",    "application/msword" }, -	{ "ppt",    "application/vnd.ms-powerpoint" }, -	{ "xls",    "application/vnd.ms-excel" }, -	{ "odt",    "application/vnd.oasis.opendocument.text" }, -	{ "odp",    "application/vnd.oasis.opendocument.presentation" }, -	{ "pl",     "application/x-perl" }, -	{ "sh",     "application/x-shellscript" }, -	{ "php",    "application/x-php" }, -	{ "deb",    "application/x-deb" }, -	{ "iso",    "application/x-cd-image" }, -	{ "tgz",    "application/x-compressed-tar" }, -	{ "gz",     "application/x-gzip" }, -	{ "bz2",    "application/x-bzip" }, -	{ "tar",    "application/x-tar" }, -	{ "rar",    "application/x-rar-compressed" }, +	{ "zip",     "application/zip" }, +	{ "pdf",     "application/pdf" }, +	{ "xml",     "application/xml" }, +	{ "xsl",     "application/xml" }, +	{ "doc",     "application/msword" }, +	{ "ppt",     "application/vnd.ms-powerpoint" }, +	{ "xls",     "application/vnd.ms-excel" }, +	{ "odt",     "application/vnd.oasis.opendocument.text" }, +	{ "odp",     "application/vnd.oasis.opendocument.presentation" }, +	{ "pl",      "application/x-perl" }, +	{ "sh",      "application/x-shellscript" }, +	{ "php",     "application/x-php" }, +	{ "deb",     "application/x-deb" }, +	{ "iso",     "application/x-cd-image" }, +	{ "tar.gz",  "application/x-compressed-tar" }, +	{ "tgz",     "application/x-compressed-tar" }, +	{ "gz",      "application/x-gzip" }, +	{ "tar.bz2", "application/x-bzip-compressed-tar" }, +	{ "tbz",     "application/x-bzip-compressed-tar" }, +	{ "bz2",     "application/x-bzip" }, +	{ "tar",     "application/x-tar" }, +	{ "rar",     "application/x-rar-compressed" }, -	{ "mp3",    "audio/mpeg" }, -	{ "ogg",    "audio/x-vorbis+ogg" }, -	{ "wav",    "audio/x-wav" }, +	{ "mp3",     "audio/mpeg" }, +	{ "ogg",     "audio/x-vorbis+ogg" }, +	{ "wav",     "audio/x-wav" }, -	{ "mpg",    "video/mpeg" }, -	{ "mpeg",   "video/mpeg" }, -	{ "avi",    "video/x-msvideo" }, +	{ "mpg",     "video/mpeg" }, +	{ "mpeg",    "video/mpeg" }, +	{ "avi",     "video/x-msvideo" }, -	{ "README", "text/plain" }, -	{ "log",    "text/plain" }, -	{ "cfg",    "text/plain" }, -	{ "conf",   "text/plain" }, +	{ "README",  "text/plain" }, +	{ "log",     "text/plain" }, +	{ "cfg",     "text/plain" }, +	{ "conf",    "text/plain" },  	{ NULL, NULL }  }; diff --git a/package/uhttpd/src/uhttpd-utils.c b/package/uhttpd/src/uhttpd-utils.c index 55b2c410e..e65f2136d 100644 --- a/package/uhttpd/src/uhttpd-utils.c +++ b/package/uhttpd/src/uhttpd-utils.c @@ -116,8 +116,8 @@ int uh_tcp_send(struct client *cl, const char *buf, int len)  	FD_ZERO(&writer);  	FD_SET(cl->socket, &writer); -	timeout.tv_sec = 0; -	timeout.tv_usec = 500000; +	timeout.tv_sec = cl->server->conf->network_timeout; +	timeout.tv_usec = 0;  	if( select(cl->socket + 1, NULL, &writer, NULL, &timeout) > 0 )  	{ @@ -376,6 +376,78 @@ int uh_b64decode(char *buf, int blen, const unsigned char *src, int slen)  	return len;  } +static char * canonpath(const char *path, char *path_resolved) +{ +	char path_copy[PATH_MAX]; +	char *path_cpy = path_copy; +	char *path_res = path_resolved; + +	struct stat s; + + +	/* relative -> absolute */ +	if( *path != '/' ) +	{ +		getcwd(path_copy, PATH_MAX); +		strncat(path_copy, "/", PATH_MAX - strlen(path_copy)); +		strncat(path_copy, path, PATH_MAX - strlen(path_copy)); +	} +	else +	{ +		strncpy(path_copy, path, PATH_MAX); +	} + +	/* normalize */ +	while( (*path_cpy != '\0') && (path_cpy < (path_copy + PATH_MAX - 2)) ) +	{ +		if( *path_cpy == '/' ) +		{ +			/* skip repeating / */ +			if( path_cpy[1] == '/' ) +			{ +				path_cpy++; +				continue; +			} + +			/* /./ or /../ */ +			else if( path_cpy[1] == '.' ) +			{ +				/* skip /./ */ +				if( (path_cpy[2] == '/') || (path_cpy[2] == '\0') ) +				{ +					path_cpy += 2; +					continue; +				} + +				/* collapse /x/../ */ +				else if( path_cpy[2] == '.' ) +				{ +					while( (path_res > path_resolved) && (*--path_res != '/') ) +						; + +					path_cpy += 3; +					continue; +				} +			} +		} + +		*path_res++ = *path_cpy++; +	} + +	/* remove trailing slash if not root / */ +	if( (path_res > (path_resolved+1)) && (path_res[-1] == '/') ) +		path_res--; +	else if( path_res == path_resolved ) +		*path_res++ = '/'; + +	*path_res = '\0'; + +	/* test access */ +	if( !stat(path_resolved, &s) && (s.st_mode & S_IROTH) ) +		return path_resolved; + +	return NULL; +}  struct path_info * uh_path_lookup(struct client *cl, const char *url)  { @@ -387,6 +459,7 @@ struct path_info * uh_path_lookup(struct client *cl, const char *url)  	char *docroot = cl->server->conf->docroot;  	char *pathptr = NULL; +	int no_sym = cl->server->conf->no_symlinks;  	int i = 0;  	struct stat s; @@ -432,8 +505,9 @@ struct path_info * uh_path_lookup(struct client *cl, const char *url)  			memset(path_info, 0, sizeof(path_info));  			memcpy(path_info, buffer, min(i + 1, sizeof(path_info) - 1)); -			if( realpath(path_info, path_phys) ) -			{ +			if( no_sym ? realpath(path_info, path_phys) +			           : canonpath(path_info, path_phys) +			) {  				memset(path_info, 0, sizeof(path_info));  				memcpy(path_info, &buffer[i],  					min(strlen(buffer) - i, sizeof(path_info) - 1)); diff --git a/package/uhttpd/src/uhttpd.c b/package/uhttpd/src/uhttpd.c index da3779413..9de77c814 100644 --- a/package/uhttpd/src/uhttpd.c +++ b/package/uhttpd/src/uhttpd.c @@ -416,8 +416,11 @@ int main (int argc, char **argv)  	/* maximum file descriptor number */  	int new_fd, cur_fd, max_fd = 0; +#ifdef HAVE_TLS  	int tls = 0;  	int keys = 0; +#endif +  	int bound = 0;  	int nofork = 0; @@ -426,9 +429,10 @@ int main (int argc, char **argv)  	char bind[128];  	char *port = NULL; -	/* library handles */ -	void *tls_lib; -	void *lua_lib; +#if defined(HAVE_TLS) || defined(HAVE_LUA) +	/* library handle */ +	void *lib; +#endif  	/* clear the master and temp sets */  	FD_ZERO(&used_fds); @@ -466,7 +470,7 @@ int main (int argc, char **argv)  #ifdef HAVE_TLS  	/* load TLS plugin */ -	if( ! (tls_lib = dlopen("uhttpd_tls.so", RTLD_LAZY | RTLD_GLOBAL)) ) +	if( ! (lib = dlopen("uhttpd_tls.so", RTLD_LAZY | RTLD_GLOBAL)) )  	{  		fprintf(stderr,  			"Notice: Unable to load TLS plugin - disabling SSL support! " @@ -476,14 +480,14 @@ int main (int argc, char **argv)  	else  	{  		/* resolve functions */ -		if( !(conf.tls_init   = dlsym(tls_lib, "uh_tls_ctx_init"))      || -		    !(conf.tls_cert   = dlsym(tls_lib, "uh_tls_ctx_cert"))      || -		    !(conf.tls_key    = dlsym(tls_lib, "uh_tls_ctx_key"))       || -		    !(conf.tls_free   = dlsym(tls_lib, "uh_tls_ctx_free"))      || -			!(conf.tls_accept = dlsym(tls_lib, "uh_tls_client_accept")) || -			!(conf.tls_close  = dlsym(tls_lib, "uh_tls_client_close"))  || -			!(conf.tls_recv   = dlsym(tls_lib, "uh_tls_client_recv"))   || -			!(conf.tls_send   = dlsym(tls_lib, "uh_tls_client_send")) +		if( !(conf.tls_init   = dlsym(lib, "uh_tls_ctx_init"))      || +		    !(conf.tls_cert   = dlsym(lib, "uh_tls_ctx_cert"))      || +		    !(conf.tls_key    = dlsym(lib, "uh_tls_ctx_key"))       || +		    !(conf.tls_free   = dlsym(lib, "uh_tls_ctx_free"))      || +			!(conf.tls_accept = dlsym(lib, "uh_tls_client_accept")) || +			!(conf.tls_close  = dlsym(lib, "uh_tls_client_close"))  || +			!(conf.tls_recv   = dlsym(lib, "uh_tls_client_recv"))   || +			!(conf.tls_send   = dlsym(lib, "uh_tls_client_send"))  		) {  			fprintf(stderr,  				"Error: Failed to lookup required symbols " @@ -501,7 +505,7 @@ int main (int argc, char **argv)  	}  #endif -	while( (opt = getopt(argc, argv, "fC:K:p:s:h:c:l:L:d:r:m:x:t:")) > 0 ) +	while( (opt = getopt(argc, argv, "fSC:K:p:s:h:c:l:L:d:r:m:x:t:T:")) > 0 )  	{  		switch(opt)  		{ @@ -592,6 +596,11 @@ int main (int argc, char **argv)  				}  				break; +			/* don't follow symlinks */ +			case 'S': +				conf.no_symlinks = 1; +				break; +  #ifdef HAVE_CGI  			/* cgi prefix */  			case 'x': @@ -618,6 +627,11 @@ int main (int argc, char **argv)  				break;  #endif +			/* network timeout */ +			case 'T': +				conf.network_timeout = atoi(optarg); +				break; +  			/* no fork */  			case 'f':  				nofork = 1; @@ -663,6 +677,7 @@ int main (int argc, char **argv)  					"	-K file         ASN.1 server private key file\n"  #endif  					"	-h directory    Specify the document root, default is '.'\n" +					"	-S              Do not follow symbolic links outside of the docroot\n"  #ifdef HAVE_LUA  					"	-l string       URL prefix for Lua handler, default is '/lua'\n"  					"	-L file         Lua handler script, omit to disable Lua\n" @@ -673,6 +688,7 @@ int main (int argc, char **argv)  #if defined(HAVE_CGI) || defined(HAVE_LUA)  					"	-t seconds      CGI and Lua script timeout in seconds, default is 60\n"  #endif +					"	-T seconds      Network timeout in seconds, default is 30\n"  					"	-d string       URL decode given string\n"  					"	-r string       Specify basic auth realm\n"  					"	-m string       MD5 crypt given string\n" @@ -712,6 +728,10 @@ int main (int argc, char **argv)  	/* config file */  	uh_config_parse(conf.file); +	/* default network timeout */ +	if( conf.network_timeout <= 0 ) +		conf.network_timeout = 30; +  #if defined(HAVE_CGI) || defined(HAVE_LUA)  	/* default script timeout */  	if( conf.script_timeout <= 0 ) @@ -726,7 +746,7 @@ int main (int argc, char **argv)  #ifdef HAVE_LUA  	/* load Lua plugin */ -	if( ! (lua_lib = dlopen("uhttpd_lua.so", RTLD_LAZY | RTLD_GLOBAL)) ) +	if( ! (lib = dlopen("uhttpd_lua.so", RTLD_LAZY | RTLD_GLOBAL)) )  	{  		fprintf(stderr,  			"Notice: Unable to load Lua plugin - disabling Lua support! " @@ -736,9 +756,9 @@ int main (int argc, char **argv)  	else  	{  		/* resolve functions */ -		if( !(conf.lua_init    = dlsym(lua_lib, "uh_lua_init"))    || -		    !(conf.lua_close   = dlsym(lua_lib, "uh_lua_close"))   || -		    !(conf.lua_request = dlsym(lua_lib, "uh_lua_request")) +		if( !(conf.lua_init    = dlsym(lib, "uh_lua_init"))    || +		    !(conf.lua_close   = dlsym(lib, "uh_lua_close"))   || +		    !(conf.lua_request = dlsym(lib, "uh_lua_request"))  		) {  			fprintf(stderr,  				"Error: Failed to lookup required symbols " diff --git a/package/uhttpd/src/uhttpd.h b/package/uhttpd/src/uhttpd.h index 0e9f1ee88..32e397007 100644 --- a/package/uhttpd/src/uhttpd.h +++ b/package/uhttpd/src/uhttpd.h @@ -32,7 +32,7 @@  #include <linux/limits.h>  #include <netdb.h>  #include <ctype.h> - +#include <errno.h>  #include <dlfcn.h> @@ -64,6 +64,8 @@ struct config {  	char docroot[PATH_MAX];  	char *realm;  	char *file; +	int no_symlinks; +	int network_timeout;  #ifdef HAVE_CGI  	char *cgi_prefix;  #endif  | 
