From: Denis Vlasenko Date: Fri, 17 Aug 2007 19:19:42 +0000 (-0000) Subject: httpd shrink and logging update, part 4 of 7 X-Git-Tag: 1_7_0~32 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=91adf7d5877ecc7587556b993808b63f6f249080;p=oweals%2Fbusybox.git httpd shrink and logging update, part 4 of 7 text data bss dec hex filename 9836 0 0 9836 266c busybox.t1/networking/httpd.o.orig 9724 0 0 9724 25fc busybox.t2/networking/httpd.o 9657 0 0 9657 25b9 busybox.t3/networking/httpd.o 9342 0 0 9342 247e busybox.t4/networking/httpd.o 9342 0 0 9342 247e busybox.t5/networking/httpd.o 9262 0 0 9262 242e busybox.t6/networking/httpd.o 9283 0 0 9283 2443 busybox.t7/networking/httpd.o 9334 0 0 9334 2476 busybox.t8/networking/httpd.o --- diff --git a/networking/httpd.c b/networking/httpd.c index 35aa492d0..69d994a47 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -1506,7 +1506,7 @@ static int checkPerm(const char *path, const char *request) } /* unauthorized */ } - } /* for */ + } /* for */ return prev == NULL; } @@ -1542,7 +1542,6 @@ static void handle_incoming_and_exit(void) char *content_type = 0; #endif struct sigaction sa; - #if ENABLE_FEATURE_HTTPD_BASIC_AUTH int credentials = -1; /* if not required this is Ok */ #endif @@ -1552,229 +1551,226 @@ static void handle_incoming_and_exit(void) sa.sa_flags = 0; /* no SA_RESTART */ sigaction(SIGALRM, &sa, NULL); - /* It's not a real loop (it ends with while(0)). - * Break from this "loop" jumps to exit(0) */ - do { - alarm(TIMEOUT); - if (!get_line()) - _exit(0); /* EOF or error or empty line */ + alarm(TIMEOUT); + if (!get_line()) + _exit(0); /* EOF or error or empty line */ - purl = strpbrk(iobuf, " \t"); - if (purl == NULL) { - send_headers_and_exit(HTTP_BAD_REQUEST); - } - *purl = '\0'; + purl = strpbrk(iobuf, " \t"); + if (purl == NULL) { + send_headers_and_exit(HTTP_BAD_REQUEST); + } + *purl = '\0'; #if ENABLE_FEATURE_HTTPD_CGI + if (strcasecmp(iobuf, prequest) != 0) { + prequest = "POST"; if (strcasecmp(iobuf, prequest) != 0) { - prequest = "POST"; - if (strcasecmp(iobuf, prequest) != 0) { - send_headers_and_exit(HTTP_NOT_IMPLEMENTED); - } - } -#else - if (strcasecmp(iobuf, request_GET) != 0) { send_headers_and_exit(HTTP_NOT_IMPLEMENTED); } + } +#else + if (strcasecmp(iobuf, request_GET) != 0) { + send_headers_and_exit(HTTP_NOT_IMPLEMENTED); + } #endif - *purl = ' '; - count = sscanf(purl, " %[^ ] HTTP/%d.%*d", iobuf, &blank); + *purl = ' '; + count = sscanf(purl, " %[^ ] HTTP/%d.%*d", iobuf, &blank); - if (count < 1 || iobuf[0] != '/') { - /* Garbled request/URL */ - send_headers_and_exit(HTTP_BAD_REQUEST); - } - url = alloca(strlen(iobuf) + sizeof("/index.html")); - if (url == NULL) { - send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); - } - strcpy(url, iobuf); - /* extract url args if present */ - test = strchr(url, '?'); - g_query = NULL; - if (test) { - *test++ = '\0'; - g_query = test; - } + if (count < 1 || iobuf[0] != '/') { + /* Garbled request/URL */ + send_headers_and_exit(HTTP_BAD_REQUEST); + } + url = alloca(strlen(iobuf) + sizeof("/index.html")); + if (url == NULL) { + send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); + } + strcpy(url, iobuf); + /* extract url args if present */ + test = strchr(url, '?'); + g_query = NULL; + if (test) { + *test++ = '\0'; + g_query = test; + } - test = decodeString(url, 0); - if (test == NULL) - send_headers_and_exit(HTTP_BAD_REQUEST); - if (test == url + 1) { - /* '/' or NUL is encoded */ - send_headers_and_exit(HTTP_NOT_FOUND); - } + test = decodeString(url, 0); + if (test == NULL) + send_headers_and_exit(HTTP_BAD_REQUEST); + if (test == url + 1) { + /* '/' or NUL is encoded */ + send_headers_and_exit(HTTP_NOT_FOUND); + } - /* algorithm stolen from libbb bb_simplify_path(), - * but don't strdup and reducing trailing slash and protect out root */ - purl = test = url; - do { - if (*purl == '/') { - /* skip duplicate (or initial) slash */ - if (*test == '/') { + /* algorithm stolen from libbb bb_simplify_path(), + * but don't strdup and reducing trailing slash and protect out root */ + purl = test = url; + do { + if (*purl == '/') { + /* skip duplicate (or initial) slash */ + if (*test == '/') { + continue; + } + if (*test == '.') { + /* skip extra '.' */ + if (test[1] == '/' || !test[1]) { continue; } - if (*test == '.') { - /* skip extra '.' */ - if (test[1] == '/' || !test[1]) { - continue; - } - /* '..': be careful */ - if (test[1] == '.' && (test[2] == '/' || !test[2])) { - ++test; - if (purl == url) { - /* protect root */ - send_headers_and_exit(HTTP_BAD_REQUEST); - } - while (*--purl != '/') /* omit previous dir */; - continue; + /* '..': be careful */ + if (test[1] == '.' && (test[2] == '/' || !test[2])) { + ++test; + if (purl == url) { + /* protect root */ + send_headers_and_exit(HTTP_BAD_REQUEST); } + while (*--purl != '/') /* omit previous dir */; + continue; } } - *++purl = *test; - } while (*++test); - *++purl = '\0'; /* so keep last character */ - test = purl; /* end ptr */ - - /* If URL is directory, adding '/' */ - if (test[-1] != '/') { - if (is_directory(url + 1, 1, &sb)) { - found_moved_temporarily = url; - } } - if (verbose > 1) - bb_error_msg("url:%s", url); - - test = url; - ip_allowed = checkPermIP(); - while (ip_allowed && (test = strchr(test + 1, '/')) != NULL) { - /* have path1/path2 */ - *test = '\0'; - if (is_directory(url + 1, 1, &sb)) { - /* may be having subdir config */ - parse_conf(url + 1, SUBDIR_PARSE); - ip_allowed = checkPermIP(); - } - *test = '/'; + *++purl = *test; + } while (*++test); + *++purl = '\0'; /* so keep last character */ + test = purl; /* end ptr */ + + /* If URL is directory, adding '/' */ + if (test[-1] != '/') { + if (is_directory(url + 1, 1, &sb)) { + found_moved_temporarily = url; + } + } + + if (verbose > 1) + bb_error_msg("url:%s", url); + + test = url; + ip_allowed = checkPermIP(); + while (ip_allowed && (test = strchr(test + 1, '/')) != NULL) { + /* have path1/path2 */ + *test = '\0'; + if (is_directory(url + 1, 1, &sb)) { + /* may be having subdir config */ + parse_conf(url + 1, SUBDIR_PARSE); + ip_allowed = checkPermIP(); } - if (blank >= 0) { - /* read until blank line for HTTP version specified, else parse immediate */ - while (1) { - alarm(TIMEOUT); - if (!get_line()) - break; /* EOF or error or empty line */ - - if (DEBUG) - bb_error_msg("header: '%s'", iobuf); + *test = '/'; + } + if (blank >= 0) { + /* read until blank line for HTTP version specified, else parse immediate */ + while (1) { + alarm(TIMEOUT); + if (!get_line()) + break; /* EOF or error or empty line */ + + if (DEBUG) + bb_error_msg("header: '%s'", iobuf); #if ENABLE_FEATURE_HTTPD_CGI - /* try and do our best to parse more lines */ - if ((STRNCASECMP(iobuf, "Content-length:") == 0)) { - /* extra read only for POST */ - if (prequest != request_GET) { - test = iobuf + sizeof("Content-length:") - 1; - if (!test[0]) - _exit(0); - errno = 0; - /* not using strtoul: it ignores leading minus! */ - length = strtol(test, &test, 10); - /* length is "ulong", but we need to pass it to int later */ - /* so we check for negative or too large values in one go: */ - /* (long -> ulong conv caused negatives to be seen as > INT_MAX) */ - if (test[0] || errno || length > INT_MAX) - _exit(0); - } - } else if (STRNCASECMP(iobuf, "Cookie:") == 0) { - cookie = strdup(skip_whitespace(iobuf + sizeof("Cookie:")-1)); - } else if (STRNCASECMP(iobuf, "Content-Type:") == 0) { - content_type = strdup(skip_whitespace(iobuf + sizeof("Content-Type:")-1)); - } else if (STRNCASECMP(iobuf, "Referer:") == 0) { - referer = strdup(skip_whitespace(iobuf + sizeof("Referer:")-1)); - } else if (STRNCASECMP(iobuf, "User-Agent:") == 0) { - user_agent = strdup(skip_whitespace(iobuf + sizeof("User-Agent:")-1)); + /* try and do our best to parse more lines */ + if ((STRNCASECMP(iobuf, "Content-length:") == 0)) { + /* extra read only for POST */ + if (prequest != request_GET) { + test = iobuf + sizeof("Content-length:") - 1; + if (!test[0]) + _exit(0); + errno = 0; + /* not using strtoul: it ignores leading minus! */ + length = strtol(test, &test, 10); + /* length is "ulong", but we need to pass it to int later */ + /* so we check for negative or too large values in one go: */ + /* (long -> ulong conv caused negatives to be seen as > INT_MAX) */ + if (test[0] || errno || length > INT_MAX) + _exit(0); } + } else if (STRNCASECMP(iobuf, "Cookie:") == 0) { + cookie = strdup(skip_whitespace(iobuf + sizeof("Cookie:")-1)); + } else if (STRNCASECMP(iobuf, "Content-Type:") == 0) { + content_type = strdup(skip_whitespace(iobuf + sizeof("Content-Type:")-1)); + } else if (STRNCASECMP(iobuf, "Referer:") == 0) { + referer = strdup(skip_whitespace(iobuf + sizeof("Referer:")-1)); + } else if (STRNCASECMP(iobuf, "User-Agent:") == 0) { + user_agent = strdup(skip_whitespace(iobuf + sizeof("User-Agent:")-1)); + } #endif #if ENABLE_FEATURE_HTTPD_BASIC_AUTH - if (STRNCASECMP(iobuf, "Authorization:") == 0) { - /* We only allow Basic credentials. - * It shows up as "Authorization: Basic " where - * the userid:password is base64 encoded. - */ - test = skip_whitespace(iobuf + sizeof("Authorization:")-1); - if (STRNCASECMP(test, "Basic") != 0) - continue; - test += sizeof("Basic")-1; - /* decodeBase64() skips whitespace itself */ - decodeBase64(test); - credentials = checkPerm(url, test); - } + if (STRNCASECMP(iobuf, "Authorization:") == 0) { + /* We only allow Basic credentials. + * It shows up as "Authorization: Basic " where + * the userid:password is base64 encoded. + */ + test = skip_whitespace(iobuf + sizeof("Authorization:")-1); + if (STRNCASECMP(test, "Basic") != 0) + continue; + test += sizeof("Basic")-1; + /* decodeBase64() skips whitespace itself */ + decodeBase64(test); + credentials = checkPerm(url, test); + } #endif /* FEATURE_HTTPD_BASIC_AUTH */ - } /* while extra header reading */ - } - alarm(0); + } /* while extra header reading */ + } - if (strcmp(bb_basename(url), httpd_conf) == 0 || ip_allowed == 0) { - /* protect listing [/path]/httpd_conf or IP deny */ - send_headers_and_exit(HTTP_FORBIDDEN); - } + alarm(0); + + if (strcmp(bb_basename(url), httpd_conf) == 0 || ip_allowed == 0) { + /* protect listing [/path]/httpd_conf or IP deny */ + send_headers_and_exit(HTTP_FORBIDDEN); + } #if ENABLE_FEATURE_HTTPD_BASIC_AUTH - if (credentials <= 0 && checkPerm(url, ":") == 0) { - send_headers_and_exit(HTTP_UNAUTHORIZED); - } + if (credentials <= 0 && checkPerm(url, ":") == 0) { + send_headers_and_exit(HTTP_UNAUTHORIZED); + } #endif - if (found_moved_temporarily) { - send_headers_and_exit(HTTP_MOVED_TEMPORARILY); - } + if (found_moved_temporarily) { + send_headers_and_exit(HTTP_MOVED_TEMPORARILY); + } - test = url + 1; /* skip first '/' */ + test = url + 1; /* skip first '/' */ #if ENABLE_FEATURE_HTTPD_CGI - if (strncmp(test, "cgi-bin", 7) == 0) { - if (test[7] == '/' && test[8] == '\0') { - /* protect listing cgi-bin/ */ - send_headers_and_exit(HTTP_FORBIDDEN); - } - send_cgi_and_exit(url, prequest, length, cookie, content_type); + if (strncmp(test, "cgi-bin", 7) == 0) { + if (test[7] == '/' && test[8] == '\0') { + /* protect listing cgi-bin/ */ + send_headers_and_exit(HTTP_FORBIDDEN); } + send_cgi_and_exit(url, prequest, length, cookie, content_type); + } #if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR - { - char *suffix = strrchr(test, '.'); - if (suffix) { - Htaccess *cur; - for (cur = script_i; cur; cur = cur->next) { - if (strcmp(cur->before_colon + 1, suffix) == 0) { - send_cgi_and_exit(url, prequest, length, cookie, content_type); - } + { + char *suffix = strrchr(test, '.'); + if (suffix) { + Htaccess *cur; + for (cur = script_i; cur; cur = cur->next) { + if (strcmp(cur->before_colon + 1, suffix) == 0) { + send_cgi_and_exit(url, prequest, length, cookie, content_type); } } } + } #endif - if (prequest != request_GET) { - send_headers_and_exit(HTTP_NOT_IMPLEMENTED); - } + if (prequest != request_GET) { + send_headers_and_exit(HTTP_NOT_IMPLEMENTED); + } #endif /* FEATURE_HTTPD_CGI */ - if (purl[-1] == '/') - strcpy(purl, "index.html"); - if (stat(test, &sb) == 0) { - /* It's a dir URL and there is index.html */ - ContentLength = sb.st_size; - last_mod = sb.st_mtime; - } + if (purl[-1] == '/') + strcpy(purl, "index.html"); + if (stat(test, &sb) == 0) { + /* It's a dir URL and there is index.html */ + ContentLength = sb.st_size; + last_mod = sb.st_mtime; + } #if ENABLE_FEATURE_HTTPD_CGI - else if (purl[-1] == '/') { - /* It's a dir URL and there is no index.html - * Try cgi-bin/index.cgi */ - if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) { - purl[0] = '\0'; - g_query = url; - send_cgi_and_exit("/cgi-bin/index.cgi", prequest, length, cookie, content_type); - } + else if (purl[-1] == '/') { + /* It's a dir URL and there is no index.html + * Try cgi-bin/index.cgi */ + if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) { + purl[0] = '\0'; + g_query = url; + send_cgi_and_exit("/cgi-bin/index.cgi", prequest, length, cookie, content_type); } + } #endif /* FEATURE_HTTPD_CGI */ - send_file_and_exit(test); - } while (0); - _exit(0); + send_file_and_exit(test); #if 0 /* Is this needed? Why? */ if (DEBUG) @@ -1817,7 +1813,6 @@ static void handle_incoming_and_exit(void) static void mini_httpd(int server) ATTRIBUTE_NORETURN; static void mini_httpd(int server) { - /* copy the ports we are watching to the readfd set */ while (1) { int n; len_and_sockaddr fromAddr;