X-Git-Url: https://git.rohieb.name/openwrt.git/blobdiff_plain/56d71638dbf48b8e4885e1e5ed5d0f1859674541..53e5fdd4e4c2cf8b53702e559797185f2d009187:/package/uhttpd/src/uhttpd-utils.c?ds=sidebyside diff --git a/package/uhttpd/src/uhttpd-utils.c b/package/uhttpd/src/uhttpd-utils.c index c1e08b069..60badf26d 100644 --- a/package/uhttpd/src/uhttpd-utils.c +++ b/package/uhttpd/src/uhttpd-utils.c @@ -88,6 +88,25 @@ char *strfind(char *haystack, int hslen, const char *needle, int ndlen) return NULL; } +/* interruptable select() */ +int select_intr(int n, fd_set *r, fd_set *w, fd_set *e, struct timeval *t) +{ + int rv; + sigset_t ssn, sso; + + /* unblock SIGCHLD */ + sigemptyset(&ssn); + sigaddset(&ssn, SIGCHLD); + sigprocmask(SIG_UNBLOCK, &ssn, &sso); + + rv = select(n, r, w, e, t); + + /* restore signal mask */ + sigprocmask(SIG_SETMASK, &sso, NULL); + + return rv; +} + int uh_tcp_send(struct client *cl, const char *buf, int len) { @@ -97,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 ) { @@ -357,6 +376,79 @@ 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] == '.') && + ((path_cpy[3] == '/') || (path_cpy[3] == '\0')) + ) { + 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) { @@ -368,9 +460,13 @@ 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; + /* back out early if url is undefined */ + if ( url == NULL ) + return NULL; memset(path_phys, 0, sizeof(path_phys)); memset(path_info, 0, sizeof(path_info)); @@ -413,8 +509,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)); @@ -456,18 +553,31 @@ struct path_info * uh_path_lookup(struct client *cl, const char *url) memcpy(buffer, path_phys, sizeof(buffer)); pathptr = &buffer[strlen(buffer)]; - for( i = 0; i < array_size(uh_index_files); i++ ) + if( cl->server->conf->index_file ) { - strncat(buffer, uh_index_files[i], sizeof(buffer)); + strncat(buffer, cl->server->conf->index_file, sizeof(buffer)); if( !stat(buffer, &s) && (s.st_mode & S_IFREG) ) { memcpy(path_phys, buffer, sizeof(path_phys)); memcpy(&p.stat, &s, sizeof(p.stat)); - break; } + } + else + { + for( i = 0; i < array_size(uh_index_files); i++ ) + { + strncat(buffer, uh_index_files[i], sizeof(buffer)); - *pathptr = 0; + if( !stat(buffer, &s) && (s.st_mode & S_IFREG) ) + { + memcpy(path_phys, buffer, sizeof(path_phys)); + memcpy(&p.stat, &s, sizeof(p.stat)); + break; + } + + *pathptr = 0; + } } p.root = docroot; @@ -528,10 +638,14 @@ struct auth_realm * uh_auth_add(char *path, char *user, char *pass) min(strlen(pass), sizeof(new->pass) - 1)); } - uh_realm_count++; + if( new->pass[0] ) + { + uh_realm_count++; + return new; + } } - return new; + return NULL; } int uh_auth_check(