X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fopenwrt.git;a=blobdiff_plain;f=package%2Fuhttpd%2Fsrc%2Fuhttpd.c;h=764ff7d5703b332ddfdbc4bd2e9f5eb63265dcc7;hp=da3779413ecd6f92ca8f768962cd3bed8f0eba8a;hb=48471980935097fbdc4e2f27b68636c55db48bd9;hpb=a0a640003469941c9067d8fab6e272a088aa45d8 diff --git a/package/uhttpd/src/uhttpd.c b/package/uhttpd/src/uhttpd.c index da3779413e..764ff7d570 100644 --- a/package/uhttpd/src/uhttpd.c +++ b/package/uhttpd/src/uhttpd.c @@ -47,7 +47,7 @@ static void uh_sigchld(int sig) while( waitpid(-1, NULL, WNOHANG) > 0 ) { } } -static void uh_config_parse(const char *path) +static void uh_config_parse(struct config *conf) { FILE *c; char line[512]; @@ -55,7 +55,10 @@ static void uh_config_parse(const char *path) char *pass = NULL; char *eol = NULL; - if( (c = fopen(path ? path : "/etc/httpd.conf", "r")) != NULL ) + const char *path = conf->file ? conf->file : "/etc/httpd.conf"; + + + if( (c = fopen(path, "r")) != NULL ) { memset(line, 0, sizeof(line)); @@ -71,12 +74,26 @@ static void uh_config_parse(const char *path) if( !uh_auth_add(line, user, pass) ) { fprintf(stderr, - "Can not manage more than %i basic auth realms, " - "will skip the rest\n", UH_LIMIT_AUTHREALMS + "Notice: No password set for user %s, ignoring " + "authentication on %s\n", user, line ); + } + } + else if( !strncmp(line, "I:", 2) ) + { + if( !(user = strchr(line, ':')) || (*user++ = 0) || + !(eol = strchr(user, '\n')) || (*eol++ = 0) ) + continue; - break; - } + conf->index_file = strdup(user); + } + else if( !strncmp(line, "E404:", 5) ) + { + if( !(user = strchr(line, ':')) || (*user++ = 0) || + !(eol = strchr(user, '\n')) || (*eol++ = 0) ) + continue; + + conf->error_handler = strdup(user); } } @@ -249,7 +266,8 @@ static struct http_request * uh_http_header_parse(struct client *cl, char *buffe } /* check version */ - if( strcmp(version, "HTTP/0.9") && strcmp(version, "HTTP/1.0") && strcmp(version, "HTTP/1.1") ) + if( (version == NULL) || (strcmp(version, "HTTP/0.9") && + strcmp(version, "HTTP/1.0") && strcmp(version, "HTTP/1.1")) ) { /* unsupported version */ uh_http_response(cl, 400, "Bad Request"); @@ -302,6 +320,7 @@ static struct http_request * uh_http_header_parse(struct client *cl, char *buffe } /* valid enough */ + req.redirect_status = 200; return &req; } @@ -416,8 +435,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 +448,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 +489,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 +499,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,8 +524,9 @@ 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, + "fSDRC:K:E:I:p:s:h:c:l:L:d:r:m:x:t:T:")) > 0 + ) { switch(opt) { /* [addr:]port */ @@ -546,6 +570,7 @@ int main (int argc, char **argv) &hints, (opt == 's'), &conf ); + memset(bind, 0, sizeof(bind)); break; #ifdef HAVE_TLS @@ -592,6 +617,42 @@ int main (int argc, char **argv) } break; + /* error handler */ + case 'E': + if( (strlen(optarg) == 0) || (optarg[0] != '/') ) + { + fprintf(stderr, "Error: Invalid error handler: %s\n", + optarg); + exit(1); + } + conf.error_handler = optarg; + break; + + /* index file */ + case 'I': + if( (strlen(optarg) == 0) || (optarg[0] == '/') ) + { + fprintf(stderr, "Error: Invalid index page: %s\n", + optarg); + exit(1); + } + conf.index_file = optarg; + break; + + /* don't follow symlinks */ + case 'S': + conf.no_symlinks = 1; + break; + + /* don't list directories */ + case 'D': + conf.no_dirlists = 1; + break; + + case 'R': + conf.rfc1918_filter = 1; + break; + #ifdef HAVE_CGI /* cgi prefix */ case 'x': @@ -618,6 +679,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 +729,11 @@ 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" + " -E string Use given virtual URL as 404 error handler\n" + " -I string Use given filename as index page for directories\n" + " -S Do not follow symbolic links outside of the docroot\n" + " -D Do not allow directory listings, send 403 instead\n" + " -R Enable RFC1918 filter\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 +744,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" @@ -710,7 +782,11 @@ int main (int argc, char **argv) conf.realm = "Protected Area"; /* config file */ - uh_config_parse(conf.file); + uh_config_parse(&conf); + + /* default network timeout */ + if( conf.network_timeout <= 0 ) + conf.network_timeout = 30; #if defined(HAVE_CGI) || defined(HAVE_LUA) /* default script timeout */ @@ -726,7 +802,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 +812,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 " @@ -862,6 +938,14 @@ int main (int argc, char **argv) /* parse message header */ if( (req = uh_http_header_recv(cl)) != NULL ) { + /* RFC1918 filtering required? */ + if( conf.rfc1918_filter && sa_rfc1918(&cl->peeraddr) && + !sa_rfc1918(&cl->servaddr) ) + { + uh_http_sendhf(cl, 403, "Forbidden", + "Rejected request from RFC1918 IP to public server address"); + } + else #ifdef HAVE_LUA /* Lua request? */ if( L && uh_path_match(conf.lua_prefix, req->url) ) @@ -892,16 +976,30 @@ int main (int argc, char **argv) /* 404 */ else { - uh_http_sendhf(cl, 404, "Not Found", - "No such file or directory"); - } - } + /* Try to invoke an error handler */ + pin = uh_path_lookup(cl, conf.error_handler); - /* 400 */ - else - { - uh_http_sendhf(cl, 400, "Bad Request", - "Malformed request received"); + if( pin && uh_auth_check(cl, req, pin) ) + { + req->redirect_status = 404; + +#ifdef HAVE_CGI + if( uh_path_match(conf.cgi_prefix, pin->name) ) + { + uh_cgi_request(cl, req, pin); + } + else +#endif + { + uh_file_request(cl, req, pin); + } + } + else + { + uh_http_sendhf(cl, 404, "Not Found", + "No such file or directory"); + } + } } #ifdef HAVE_TLS