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
This commit is contained in:
parent
e45af73dc2
commit
91adf7d587
@ -1506,7 +1506,7 @@ static int checkPerm(const char *path, const char *request)
|
|||||||
}
|
}
|
||||||
/* unauthorized */
|
/* unauthorized */
|
||||||
}
|
}
|
||||||
} /* for */
|
} /* for */
|
||||||
|
|
||||||
return prev == NULL;
|
return prev == NULL;
|
||||||
}
|
}
|
||||||
@ -1542,7 +1542,6 @@ static void handle_incoming_and_exit(void)
|
|||||||
char *content_type = 0;
|
char *content_type = 0;
|
||||||
#endif
|
#endif
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
|
|
||||||
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
|
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
|
||||||
int credentials = -1; /* if not required this is Ok */
|
int credentials = -1; /* if not required this is Ok */
|
||||||
#endif
|
#endif
|
||||||
@ -1552,229 +1551,226 @@ static void handle_incoming_and_exit(void)
|
|||||||
sa.sa_flags = 0; /* no SA_RESTART */
|
sa.sa_flags = 0; /* no SA_RESTART */
|
||||||
sigaction(SIGALRM, &sa, NULL);
|
sigaction(SIGALRM, &sa, NULL);
|
||||||
|
|
||||||
/* It's not a real loop (it ends with while(0)).
|
alarm(TIMEOUT);
|
||||||
* Break from this "loop" jumps to exit(0) */
|
if (!get_line())
|
||||||
do {
|
_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");
|
purl = strpbrk(iobuf, " \t");
|
||||||
if (purl == NULL) {
|
if (purl == NULL) {
|
||||||
send_headers_and_exit(HTTP_BAD_REQUEST);
|
send_headers_and_exit(HTTP_BAD_REQUEST);
|
||||||
}
|
}
|
||||||
*purl = '\0';
|
*purl = '\0';
|
||||||
#if ENABLE_FEATURE_HTTPD_CGI
|
#if ENABLE_FEATURE_HTTPD_CGI
|
||||||
|
if (strcasecmp(iobuf, prequest) != 0) {
|
||||||
|
prequest = "POST";
|
||||||
if (strcasecmp(iobuf, prequest) != 0) {
|
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);
|
send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (strcasecmp(iobuf, request_GET) != 0) {
|
||||||
|
send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
*purl = ' ';
|
*purl = ' ';
|
||||||
count = sscanf(purl, " %[^ ] HTTP/%d.%*d", iobuf, &blank);
|
count = sscanf(purl, " %[^ ] HTTP/%d.%*d", iobuf, &blank);
|
||||||
|
|
||||||
if (count < 1 || iobuf[0] != '/') {
|
if (count < 1 || iobuf[0] != '/') {
|
||||||
/* Garbled request/URL */
|
/* Garbled request/URL */
|
||||||
send_headers_and_exit(HTTP_BAD_REQUEST);
|
send_headers_and_exit(HTTP_BAD_REQUEST);
|
||||||
}
|
}
|
||||||
url = alloca(strlen(iobuf) + sizeof("/index.html"));
|
url = alloca(strlen(iobuf) + sizeof("/index.html"));
|
||||||
if (url == NULL) {
|
if (url == NULL) {
|
||||||
send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);
|
send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
strcpy(url, iobuf);
|
strcpy(url, iobuf);
|
||||||
/* extract url args if present */
|
/* extract url args if present */
|
||||||
test = strchr(url, '?');
|
test = strchr(url, '?');
|
||||||
g_query = NULL;
|
g_query = NULL;
|
||||||
if (test) {
|
if (test) {
|
||||||
*test++ = '\0';
|
*test++ = '\0';
|
||||||
g_query = test;
|
g_query = test;
|
||||||
}
|
}
|
||||||
|
|
||||||
test = decodeString(url, 0);
|
test = decodeString(url, 0);
|
||||||
if (test == NULL)
|
if (test == NULL)
|
||||||
send_headers_and_exit(HTTP_BAD_REQUEST);
|
send_headers_and_exit(HTTP_BAD_REQUEST);
|
||||||
if (test == url + 1) {
|
if (test == url + 1) {
|
||||||
/* '/' or NUL is encoded */
|
/* '/' or NUL is encoded */
|
||||||
send_headers_and_exit(HTTP_NOT_FOUND);
|
send_headers_and_exit(HTTP_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* algorithm stolen from libbb bb_simplify_path(),
|
/* algorithm stolen from libbb bb_simplify_path(),
|
||||||
* but don't strdup and reducing trailing slash and protect out root */
|
* but don't strdup and reducing trailing slash and protect out root */
|
||||||
purl = test = url;
|
purl = test = url;
|
||||||
do {
|
do {
|
||||||
if (*purl == '/') {
|
if (*purl == '/') {
|
||||||
/* skip duplicate (or initial) slash */
|
/* skip duplicate (or initial) slash */
|
||||||
if (*test == '/') {
|
if (*test == '/') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*test == '.') {
|
||||||
|
/* skip extra '.' */
|
||||||
|
if (test[1] == '/' || !test[1]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (*test == '.') {
|
/* '..': be careful */
|
||||||
/* skip extra '.' */
|
if (test[1] == '.' && (test[2] == '/' || !test[2])) {
|
||||||
if (test[1] == '/' || !test[1]) {
|
++test;
|
||||||
|
if (purl == url) {
|
||||||
|
/* protect root */
|
||||||
|
send_headers_and_exit(HTTP_BAD_REQUEST);
|
||||||
|
}
|
||||||
|
while (*--purl != '/') /* omit previous dir */;
|
||||||
continue;
|
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)
|
*++purl = *test;
|
||||||
bb_error_msg("url:%s", url);
|
} while (*++test);
|
||||||
|
*++purl = '\0'; /* so keep last character */
|
||||||
|
test = purl; /* end ptr */
|
||||||
|
|
||||||
test = url;
|
/* If URL is directory, adding '/' */
|
||||||
ip_allowed = checkPermIP();
|
if (test[-1] != '/') {
|
||||||
while (ip_allowed && (test = strchr(test + 1, '/')) != NULL) {
|
if (is_directory(url + 1, 1, &sb)) {
|
||||||
/* have path1/path2 */
|
found_moved_temporarily = url;
|
||||||
*test = '\0';
|
|
||||||
if (is_directory(url + 1, 1, &sb)) {
|
|
||||||
/* may be having subdir config */
|
|
||||||
parse_conf(url + 1, SUBDIR_PARSE);
|
|
||||||
ip_allowed = checkPermIP();
|
|
||||||
}
|
|
||||||
*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)
|
if (verbose > 1)
|
||||||
bb_error_msg("header: '%s'", iobuf);
|
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 = '/';
|
||||||
|
}
|
||||||
|
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
|
#if ENABLE_FEATURE_HTTPD_CGI
|
||||||
/* try and do our best to parse more lines */
|
/* try and do our best to parse more lines */
|
||||||
if ((STRNCASECMP(iobuf, "Content-length:") == 0)) {
|
if ((STRNCASECMP(iobuf, "Content-length:") == 0)) {
|
||||||
/* extra read only for POST */
|
/* extra read only for POST */
|
||||||
if (prequest != request_GET) {
|
if (prequest != request_GET) {
|
||||||
test = iobuf + sizeof("Content-length:") - 1;
|
test = iobuf + sizeof("Content-length:") - 1;
|
||||||
if (!test[0])
|
if (!test[0])
|
||||||
_exit(0);
|
_exit(0);
|
||||||
errno = 0;
|
errno = 0;
|
||||||
/* not using strtoul: it ignores leading minus! */
|
/* not using strtoul: it ignores leading minus! */
|
||||||
length = strtol(test, &test, 10);
|
length = strtol(test, &test, 10);
|
||||||
/* length is "ulong", but we need to pass it to int later */
|
/* length is "ulong", but we need to pass it to int later */
|
||||||
/* so we check for negative or too large values in one go: */
|
/* so we check for negative or too large values in one go: */
|
||||||
/* (long -> ulong conv caused negatives to be seen as > INT_MAX) */
|
/* (long -> ulong conv caused negatives to be seen as > INT_MAX) */
|
||||||
if (test[0] || errno || length > INT_MAX)
|
if (test[0] || errno || length > INT_MAX)
|
||||||
_exit(0);
|
_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));
|
|
||||||
}
|
}
|
||||||
|
} 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
|
#endif
|
||||||
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
|
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
|
||||||
if (STRNCASECMP(iobuf, "Authorization:") == 0) {
|
if (STRNCASECMP(iobuf, "Authorization:") == 0) {
|
||||||
/* We only allow Basic credentials.
|
/* We only allow Basic credentials.
|
||||||
* It shows up as "Authorization: Basic <userid:password>" where
|
* It shows up as "Authorization: Basic <userid:password>" where
|
||||||
* the userid:password is base64 encoded.
|
* the userid:password is base64 encoded.
|
||||||
*/
|
*/
|
||||||
test = skip_whitespace(iobuf + sizeof("Authorization:")-1);
|
test = skip_whitespace(iobuf + sizeof("Authorization:")-1);
|
||||||
if (STRNCASECMP(test, "Basic") != 0)
|
if (STRNCASECMP(test, "Basic") != 0)
|
||||||
continue;
|
continue;
|
||||||
test += sizeof("Basic")-1;
|
test += sizeof("Basic")-1;
|
||||||
/* decodeBase64() skips whitespace itself */
|
/* decodeBase64() skips whitespace itself */
|
||||||
decodeBase64(test);
|
decodeBase64(test);
|
||||||
credentials = checkPerm(url, test);
|
credentials = checkPerm(url, test);
|
||||||
}
|
}
|
||||||
#endif /* FEATURE_HTTPD_BASIC_AUTH */
|
#endif /* FEATURE_HTTPD_BASIC_AUTH */
|
||||||
} /* while extra header reading */
|
} /* while extra header reading */
|
||||||
}
|
}
|
||||||
alarm(0);
|
|
||||||
|
|
||||||
if (strcmp(bb_basename(url), httpd_conf) == 0 || ip_allowed == 0) {
|
alarm(0);
|
||||||
/* protect listing [/path]/httpd_conf or IP deny */
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (found_moved_temporarily) {
|
||||||
|
send_headers_and_exit(HTTP_MOVED_TEMPORARILY);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_headers_and_exit(HTTP_FORBIDDEN);
|
||||||
}
|
}
|
||||||
|
send_cgi_and_exit(url, prequest, length, cookie, content_type);
|
||||||
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
|
}
|
||||||
if (credentials <= 0 && checkPerm(url, ":") == 0) {
|
|
||||||
send_headers_and_exit(HTTP_UNAUTHORIZED);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (found_moved_temporarily) {
|
|
||||||
send_headers_and_exit(HTTP_MOVED_TEMPORARILY);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
|
#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
|
||||||
{
|
{
|
||||||
char *suffix = strrchr(test, '.');
|
char *suffix = strrchr(test, '.');
|
||||||
if (suffix) {
|
if (suffix) {
|
||||||
Htaccess *cur;
|
Htaccess *cur;
|
||||||
for (cur = script_i; cur; cur = cur->next) {
|
for (cur = script_i; cur; cur = cur->next) {
|
||||||
if (strcmp(cur->before_colon + 1, suffix) == 0) {
|
if (strcmp(cur->before_colon + 1, suffix) == 0) {
|
||||||
send_cgi_and_exit(url, prequest, length, cookie, content_type);
|
send_cgi_and_exit(url, prequest, length, cookie, content_type);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (prequest != request_GET) {
|
if (prequest != request_GET) {
|
||||||
send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
|
send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
|
||||||
}
|
}
|
||||||
#endif /* FEATURE_HTTPD_CGI */
|
#endif /* FEATURE_HTTPD_CGI */
|
||||||
if (purl[-1] == '/')
|
if (purl[-1] == '/')
|
||||||
strcpy(purl, "index.html");
|
strcpy(purl, "index.html");
|
||||||
if (stat(test, &sb) == 0) {
|
if (stat(test, &sb) == 0) {
|
||||||
/* It's a dir URL and there is index.html */
|
/* It's a dir URL and there is index.html */
|
||||||
ContentLength = sb.st_size;
|
ContentLength = sb.st_size;
|
||||||
last_mod = sb.st_mtime;
|
last_mod = sb.st_mtime;
|
||||||
}
|
}
|
||||||
#if ENABLE_FEATURE_HTTPD_CGI
|
#if ENABLE_FEATURE_HTTPD_CGI
|
||||||
else if (purl[-1] == '/') {
|
else if (purl[-1] == '/') {
|
||||||
/* It's a dir URL and there is no index.html
|
/* It's a dir URL and there is no index.html
|
||||||
* Try cgi-bin/index.cgi */
|
* Try cgi-bin/index.cgi */
|
||||||
if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) {
|
if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) {
|
||||||
purl[0] = '\0';
|
purl[0] = '\0';
|
||||||
g_query = url;
|
g_query = url;
|
||||||
send_cgi_and_exit("/cgi-bin/index.cgi", prequest, length, cookie, content_type);
|
send_cgi_and_exit("/cgi-bin/index.cgi", prequest, length, cookie, content_type);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif /* FEATURE_HTTPD_CGI */
|
#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 0 /* Is this needed? Why? */
|
||||||
if (DEBUG)
|
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) ATTRIBUTE_NORETURN;
|
||||||
static void mini_httpd(int server)
|
static void mini_httpd(int server)
|
||||||
{
|
{
|
||||||
/* copy the ports we are watching to the readfd set */
|
|
||||||
while (1) {
|
while (1) {
|
||||||
int n;
|
int n;
|
||||||
len_and_sockaddr fromAddr;
|
len_and_sockaddr fromAddr;
|
||||||
|
Loading…
Reference in New Issue
Block a user