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:
Denis Vlasenko 2007-08-17 19:19:42 +00:00
parent e45af73dc2
commit 91adf7d587

View File

@ -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;