mirror of https://github.com/hak5/openwrt.git
uhttpd: - make network timeout configurable, increase default to 30 seconds (#7067) - follow symlinks in docroot and add option to disable that - fix mimetype detection for files with combined extensions (.tar.gz, ...)
SVN-Revision: 20883lede-17.01
parent
a8e20318c5
commit
20ef055c2f
|
@ -8,7 +8,7 @@
|
||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=uhttpd
|
PKG_NAME:=uhttpd
|
||||||
PKG_RELEASE:=7
|
PKG_RELEASE:=8
|
||||||
|
|
||||||
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
|
||||||
|
|
||||||
|
|
|
@ -29,10 +29,16 @@ config uhttpd main
|
||||||
|
|
||||||
# CGI/Lua timeout, if the called script does not
|
# CGI/Lua timeout, if the called script does not
|
||||||
# write data within the given amount of seconds,
|
# 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.
|
# 504 Gateway Timeout response.
|
||||||
option script_timeout 60
|
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
|
# Basic auth realm, defaults to local hostname
|
||||||
# option realm OpenWrt
|
# option realm OpenWrt
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@ start_instance()
|
||||||
append_arg "$cfg" lua_prefix "-l"
|
append_arg "$cfg" lua_prefix "-l"
|
||||||
append_arg "$cfg" lua_handler "-L"
|
append_arg "$cfg" lua_handler "-L"
|
||||||
append_arg "$cfg" script_timeout "-t"
|
append_arg "$cfg" script_timeout "-t"
|
||||||
|
append_arg "$cfg" network_timeout "-T"
|
||||||
|
|
||||||
config_get http "$cfg" listen_http
|
config_get http "$cfg" listen_http
|
||||||
for listen in $http; do
|
for listen in $http; do
|
||||||
|
|
|
@ -29,23 +29,21 @@
|
||||||
static const char * uh_file_mime_lookup(const char *path)
|
static const char * uh_file_mime_lookup(const char *path)
|
||||||
{
|
{
|
||||||
struct mimetype *m = &uh_mime_types[0];
|
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 )
|
||||||
{
|
{
|
||||||
if( ! strcasecmp(p, m->extn) )
|
e = &path[strlen(path)-1];
|
||||||
|
|
||||||
|
while( e >= path )
|
||||||
|
{
|
||||||
|
if( (*e == '.') && !strcasecmp(&e[1], m->extn) )
|
||||||
return m->mime;
|
return m->mime;
|
||||||
|
|
||||||
m++;
|
e--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return "application/octet-stream";
|
return "application/octet-stream";
|
||||||
|
|
|
@ -54,8 +54,11 @@ static struct mimetype uh_mime_types[] = {
|
||||||
{ "php", "application/x-php" },
|
{ "php", "application/x-php" },
|
||||||
{ "deb", "application/x-deb" },
|
{ "deb", "application/x-deb" },
|
||||||
{ "iso", "application/x-cd-image" },
|
{ "iso", "application/x-cd-image" },
|
||||||
|
{ "tar.gz", "application/x-compressed-tar" },
|
||||||
{ "tgz", "application/x-compressed-tar" },
|
{ "tgz", "application/x-compressed-tar" },
|
||||||
{ "gz", "application/x-gzip" },
|
{ "gz", "application/x-gzip" },
|
||||||
|
{ "tar.bz2", "application/x-bzip-compressed-tar" },
|
||||||
|
{ "tbz", "application/x-bzip-compressed-tar" },
|
||||||
{ "bz2", "application/x-bzip" },
|
{ "bz2", "application/x-bzip" },
|
||||||
{ "tar", "application/x-tar" },
|
{ "tar", "application/x-tar" },
|
||||||
{ "rar", "application/x-rar-compressed" },
|
{ "rar", "application/x-rar-compressed" },
|
||||||
|
|
|
@ -116,8 +116,8 @@ int uh_tcp_send(struct client *cl, const char *buf, int len)
|
||||||
FD_ZERO(&writer);
|
FD_ZERO(&writer);
|
||||||
FD_SET(cl->socket, &writer);
|
FD_SET(cl->socket, &writer);
|
||||||
|
|
||||||
timeout.tv_sec = 0;
|
timeout.tv_sec = cl->server->conf->network_timeout;
|
||||||
timeout.tv_usec = 500000;
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
if( select(cl->socket + 1, NULL, &writer, NULL, &timeout) > 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;
|
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)
|
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 *docroot = cl->server->conf->docroot;
|
||||||
char *pathptr = NULL;
|
char *pathptr = NULL;
|
||||||
|
|
||||||
|
int no_sym = cl->server->conf->no_symlinks;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
struct stat s;
|
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));
|
memset(path_info, 0, sizeof(path_info));
|
||||||
memcpy(path_info, buffer, min(i + 1, sizeof(path_info) - 1));
|
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));
|
memset(path_info, 0, sizeof(path_info));
|
||||||
memcpy(path_info, &buffer[i],
|
memcpy(path_info, &buffer[i],
|
||||||
min(strlen(buffer) - i, sizeof(path_info) - 1));
|
min(strlen(buffer) - i, sizeof(path_info) - 1));
|
||||||
|
|
|
@ -416,8 +416,11 @@ int main (int argc, char **argv)
|
||||||
/* maximum file descriptor number */
|
/* maximum file descriptor number */
|
||||||
int new_fd, cur_fd, max_fd = 0;
|
int new_fd, cur_fd, max_fd = 0;
|
||||||
|
|
||||||
|
#ifdef HAVE_TLS
|
||||||
int tls = 0;
|
int tls = 0;
|
||||||
int keys = 0;
|
int keys = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
int bound = 0;
|
int bound = 0;
|
||||||
int nofork = 0;
|
int nofork = 0;
|
||||||
|
|
||||||
|
@ -426,9 +429,10 @@ int main (int argc, char **argv)
|
||||||
char bind[128];
|
char bind[128];
|
||||||
char *port = NULL;
|
char *port = NULL;
|
||||||
|
|
||||||
/* library handles */
|
#if defined(HAVE_TLS) || defined(HAVE_LUA)
|
||||||
void *tls_lib;
|
/* library handle */
|
||||||
void *lua_lib;
|
void *lib;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* clear the master and temp sets */
|
/* clear the master and temp sets */
|
||||||
FD_ZERO(&used_fds);
|
FD_ZERO(&used_fds);
|
||||||
|
@ -466,7 +470,7 @@ int main (int argc, char **argv)
|
||||||
|
|
||||||
#ifdef HAVE_TLS
|
#ifdef HAVE_TLS
|
||||||
/* load TLS plugin */
|
/* 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,
|
fprintf(stderr,
|
||||||
"Notice: Unable to load TLS plugin - disabling SSL support! "
|
"Notice: Unable to load TLS plugin - disabling SSL support! "
|
||||||
|
@ -476,14 +480,14 @@ int main (int argc, char **argv)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* resolve functions */
|
/* resolve functions */
|
||||||
if( !(conf.tls_init = dlsym(tls_lib, "uh_tls_ctx_init")) ||
|
if( !(conf.tls_init = dlsym(lib, "uh_tls_ctx_init")) ||
|
||||||
!(conf.tls_cert = dlsym(tls_lib, "uh_tls_ctx_cert")) ||
|
!(conf.tls_cert = dlsym(lib, "uh_tls_ctx_cert")) ||
|
||||||
!(conf.tls_key = dlsym(tls_lib, "uh_tls_ctx_key")) ||
|
!(conf.tls_key = dlsym(lib, "uh_tls_ctx_key")) ||
|
||||||
!(conf.tls_free = dlsym(tls_lib, "uh_tls_ctx_free")) ||
|
!(conf.tls_free = dlsym(lib, "uh_tls_ctx_free")) ||
|
||||||
!(conf.tls_accept = dlsym(tls_lib, "uh_tls_client_accept")) ||
|
!(conf.tls_accept = dlsym(lib, "uh_tls_client_accept")) ||
|
||||||
!(conf.tls_close = dlsym(tls_lib, "uh_tls_client_close")) ||
|
!(conf.tls_close = dlsym(lib, "uh_tls_client_close")) ||
|
||||||
!(conf.tls_recv = dlsym(tls_lib, "uh_tls_client_recv")) ||
|
!(conf.tls_recv = dlsym(lib, "uh_tls_client_recv")) ||
|
||||||
!(conf.tls_send = dlsym(tls_lib, "uh_tls_client_send"))
|
!(conf.tls_send = dlsym(lib, "uh_tls_client_send"))
|
||||||
) {
|
) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Error: Failed to lookup required symbols "
|
"Error: Failed to lookup required symbols "
|
||||||
|
@ -501,7 +505,7 @@ int main (int argc, char **argv)
|
||||||
}
|
}
|
||||||
#endif
|
#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)
|
switch(opt)
|
||||||
{
|
{
|
||||||
|
@ -592,6 +596,11 @@ int main (int argc, char **argv)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* don't follow symlinks */
|
||||||
|
case 'S':
|
||||||
|
conf.no_symlinks = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
#ifdef HAVE_CGI
|
#ifdef HAVE_CGI
|
||||||
/* cgi prefix */
|
/* cgi prefix */
|
||||||
case 'x':
|
case 'x':
|
||||||
|
@ -618,6 +627,11 @@ int main (int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* network timeout */
|
||||||
|
case 'T':
|
||||||
|
conf.network_timeout = atoi(optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
/* no fork */
|
/* no fork */
|
||||||
case 'f':
|
case 'f':
|
||||||
nofork = 1;
|
nofork = 1;
|
||||||
|
@ -663,6 +677,7 @@ int main (int argc, char **argv)
|
||||||
" -K file ASN.1 server private key file\n"
|
" -K file ASN.1 server private key file\n"
|
||||||
#endif
|
#endif
|
||||||
" -h directory Specify the document root, default is '.'\n"
|
" -h directory Specify the document root, default is '.'\n"
|
||||||
|
" -S Do not follow symbolic links outside of the docroot\n"
|
||||||
#ifdef HAVE_LUA
|
#ifdef HAVE_LUA
|
||||||
" -l string URL prefix for Lua handler, default is '/lua'\n"
|
" -l string URL prefix for Lua handler, default is '/lua'\n"
|
||||||
" -L file Lua handler script, omit to disable 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)
|
#if defined(HAVE_CGI) || defined(HAVE_LUA)
|
||||||
" -t seconds CGI and Lua script timeout in seconds, default is 60\n"
|
" -t seconds CGI and Lua script timeout in seconds, default is 60\n"
|
||||||
#endif
|
#endif
|
||||||
|
" -T seconds Network timeout in seconds, default is 30\n"
|
||||||
" -d string URL decode given string\n"
|
" -d string URL decode given string\n"
|
||||||
" -r string Specify basic auth realm\n"
|
" -r string Specify basic auth realm\n"
|
||||||
" -m string MD5 crypt given string\n"
|
" -m string MD5 crypt given string\n"
|
||||||
|
@ -712,6 +728,10 @@ int main (int argc, char **argv)
|
||||||
/* config file */
|
/* config file */
|
||||||
uh_config_parse(conf.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)
|
#if defined(HAVE_CGI) || defined(HAVE_LUA)
|
||||||
/* default script timeout */
|
/* default script timeout */
|
||||||
if( conf.script_timeout <= 0 )
|
if( conf.script_timeout <= 0 )
|
||||||
|
@ -726,7 +746,7 @@ int main (int argc, char **argv)
|
||||||
|
|
||||||
#ifdef HAVE_LUA
|
#ifdef HAVE_LUA
|
||||||
/* load Lua plugin */
|
/* 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,
|
fprintf(stderr,
|
||||||
"Notice: Unable to load Lua plugin - disabling Lua support! "
|
"Notice: Unable to load Lua plugin - disabling Lua support! "
|
||||||
|
@ -736,9 +756,9 @@ int main (int argc, char **argv)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* resolve functions */
|
/* resolve functions */
|
||||||
if( !(conf.lua_init = dlsym(lua_lib, "uh_lua_init")) ||
|
if( !(conf.lua_init = dlsym(lib, "uh_lua_init")) ||
|
||||||
!(conf.lua_close = dlsym(lua_lib, "uh_lua_close")) ||
|
!(conf.lua_close = dlsym(lib, "uh_lua_close")) ||
|
||||||
!(conf.lua_request = dlsym(lua_lib, "uh_lua_request"))
|
!(conf.lua_request = dlsym(lib, "uh_lua_request"))
|
||||||
) {
|
) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Error: Failed to lookup required symbols "
|
"Error: Failed to lookup required symbols "
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
#include <linux/limits.h>
|
#include <linux/limits.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,6 +64,8 @@ struct config {
|
||||||
char docroot[PATH_MAX];
|
char docroot[PATH_MAX];
|
||||||
char *realm;
|
char *realm;
|
||||||
char *file;
|
char *file;
|
||||||
|
int no_symlinks;
|
||||||
|
int network_timeout;
|
||||||
#ifdef HAVE_CGI
|
#ifdef HAVE_CGI
|
||||||
char *cgi_prefix;
|
char *cgi_prefix;
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue