aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-08-17 19:19:42 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-08-17 19:19:42 +0000
commit91adf7d5877ecc7587556b993808b63f6f249080 (patch)
tree6b3cd51028fcefab504cd8502ffe0e9a03b4f665
parente45af73dc233d345a642386431703ad9a1597093 (diff)
downloadbusybox-w32-91adf7d5877ecc7587556b993808b63f6f249080.tar.gz
busybox-w32-91adf7d5877ecc7587556b993808b63f6f249080.tar.bz2
busybox-w32-91adf7d5877ecc7587556b993808b63f6f249080.zip
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
-rw-r--r--networking/httpd.c367
1 files changed, 181 insertions, 186 deletions
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)
1506 } 1506 }
1507 /* unauthorized */ 1507 /* unauthorized */
1508 } 1508 }
1509 } /* for */ 1509 } /* for */
1510 1510
1511 return prev == NULL; 1511 return prev == NULL;
1512} 1512}
@@ -1542,7 +1542,6 @@ static void handle_incoming_and_exit(void)
1542 char *content_type = 0; 1542 char *content_type = 0;
1543#endif 1543#endif
1544 struct sigaction sa; 1544 struct sigaction sa;
1545
1546#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 1545#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
1547 int credentials = -1; /* if not required this is Ok */ 1546 int credentials = -1; /* if not required this is Ok */
1548#endif 1547#endif
@@ -1552,229 +1551,226 @@ static void handle_incoming_and_exit(void)
1552 sa.sa_flags = 0; /* no SA_RESTART */ 1551 sa.sa_flags = 0; /* no SA_RESTART */
1553 sigaction(SIGALRM, &sa, NULL); 1552 sigaction(SIGALRM, &sa, NULL);
1554 1553
1555 /* It's not a real loop (it ends with while(0)). 1554 alarm(TIMEOUT);
1556 * Break from this "loop" jumps to exit(0) */ 1555 if (!get_line())
1557 do { 1556 _exit(0); /* EOF or error or empty line */
1558 alarm(TIMEOUT);
1559 if (!get_line())
1560 _exit(0); /* EOF or error or empty line */
1561 1557
1562 purl = strpbrk(iobuf, " \t"); 1558 purl = strpbrk(iobuf, " \t");
1563 if (purl == NULL) { 1559 if (purl == NULL) {
1564 send_headers_and_exit(HTTP_BAD_REQUEST); 1560 send_headers_and_exit(HTTP_BAD_REQUEST);
1565 } 1561 }
1566 *purl = '\0'; 1562 *purl = '\0';
1567#if ENABLE_FEATURE_HTTPD_CGI 1563#if ENABLE_FEATURE_HTTPD_CGI
1564 if (strcasecmp(iobuf, prequest) != 0) {
1565 prequest = "POST";
1568 if (strcasecmp(iobuf, prequest) != 0) { 1566 if (strcasecmp(iobuf, prequest) != 0) {
1569 prequest = "POST";
1570 if (strcasecmp(iobuf, prequest) != 0) {
1571 send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
1572 }
1573 }
1574#else
1575 if (strcasecmp(iobuf, request_GET) != 0) {
1576 send_headers_and_exit(HTTP_NOT_IMPLEMENTED); 1567 send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
1577 } 1568 }
1569 }
1570#else
1571 if (strcasecmp(iobuf, request_GET) != 0) {
1572 send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
1573 }
1578#endif 1574#endif
1579 *purl = ' '; 1575 *purl = ' ';
1580 count = sscanf(purl, " %[^ ] HTTP/%d.%*d", iobuf, &blank); 1576 count = sscanf(purl, " %[^ ] HTTP/%d.%*d", iobuf, &blank);
1581 1577
1582 if (count < 1 || iobuf[0] != '/') { 1578 if (count < 1 || iobuf[0] != '/') {
1583 /* Garbled request/URL */ 1579 /* Garbled request/URL */
1584 send_headers_and_exit(HTTP_BAD_REQUEST); 1580 send_headers_and_exit(HTTP_BAD_REQUEST);
1585 } 1581 }
1586 url = alloca(strlen(iobuf) + sizeof("/index.html")); 1582 url = alloca(strlen(iobuf) + sizeof("/index.html"));
1587 if (url == NULL) { 1583 if (url == NULL) {
1588 send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); 1584 send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);
1589 } 1585 }
1590 strcpy(url, iobuf); 1586 strcpy(url, iobuf);
1591 /* extract url args if present */ 1587 /* extract url args if present */
1592 test = strchr(url, '?'); 1588 test = strchr(url, '?');
1593 g_query = NULL; 1589 g_query = NULL;
1594 if (test) { 1590 if (test) {
1595 *test++ = '\0'; 1591 *test++ = '\0';
1596 g_query = test; 1592 g_query = test;
1597 } 1593 }
1598 1594
1599 test = decodeString(url, 0); 1595 test = decodeString(url, 0);
1600 if (test == NULL) 1596 if (test == NULL)
1601 send_headers_and_exit(HTTP_BAD_REQUEST); 1597 send_headers_and_exit(HTTP_BAD_REQUEST);
1602 if (test == url + 1) { 1598 if (test == url + 1) {
1603 /* '/' or NUL is encoded */ 1599 /* '/' or NUL is encoded */
1604 send_headers_and_exit(HTTP_NOT_FOUND); 1600 send_headers_and_exit(HTTP_NOT_FOUND);
1605 } 1601 }
1606 1602
1607 /* algorithm stolen from libbb bb_simplify_path(), 1603 /* algorithm stolen from libbb bb_simplify_path(),
1608 * but don't strdup and reducing trailing slash and protect out root */ 1604 * but don't strdup and reducing trailing slash and protect out root */
1609 purl = test = url; 1605 purl = test = url;
1610 do { 1606 do {
1611 if (*purl == '/') { 1607 if (*purl == '/') {
1612 /* skip duplicate (or initial) slash */ 1608 /* skip duplicate (or initial) slash */
1613 if (*test == '/') { 1609 if (*test == '/') {
1610 continue;
1611 }
1612 if (*test == '.') {
1613 /* skip extra '.' */
1614 if (test[1] == '/' || !test[1]) {
1614 continue; 1615 continue;
1615 } 1616 }
1616 if (*test == '.') { 1617 /* '..': be careful */
1617 /* skip extra '.' */ 1618 if (test[1] == '.' && (test[2] == '/' || !test[2])) {
1618 if (test[1] == '/' || !test[1]) { 1619 ++test;
1619 continue; 1620 if (purl == url) {
1620 } 1621 /* protect root */
1621 /* '..': be careful */ 1622 send_headers_and_exit(HTTP_BAD_REQUEST);
1622 if (test[1] == '.' && (test[2] == '/' || !test[2])) {
1623 ++test;
1624 if (purl == url) {
1625 /* protect root */
1626 send_headers_and_exit(HTTP_BAD_REQUEST);
1627 }
1628 while (*--purl != '/') /* omit previous dir */;
1629 continue;
1630 } 1623 }
1624 while (*--purl != '/') /* omit previous dir */;
1625 continue;
1631 } 1626 }
1632 } 1627 }
1633 *++purl = *test;
1634 } while (*++test);
1635 *++purl = '\0'; /* so keep last character */
1636 test = purl; /* end ptr */
1637
1638 /* If URL is directory, adding '/' */
1639 if (test[-1] != '/') {
1640 if (is_directory(url + 1, 1, &sb)) {
1641 found_moved_temporarily = url;
1642 }
1643 } 1628 }
1644 if (verbose > 1) 1629 *++purl = *test;
1645 bb_error_msg("url:%s", url); 1630 } while (*++test);
1646 1631 *++purl = '\0'; /* so keep last character */
1647 test = url; 1632 test = purl; /* end ptr */
1648 ip_allowed = checkPermIP(); 1633
1649 while (ip_allowed && (test = strchr(test + 1, '/')) != NULL) { 1634 /* If URL is directory, adding '/' */
1650 /* have path1/path2 */ 1635 if (test[-1] != '/') {
1651 *test = '\0'; 1636 if (is_directory(url + 1, 1, &sb)) {
1652 if (is_directory(url + 1, 1, &sb)) { 1637 found_moved_temporarily = url;
1653 /* may be having subdir config */ 1638 }
1654 parse_conf(url + 1, SUBDIR_PARSE); 1639 }
1655 ip_allowed = checkPermIP(); 1640
1656 } 1641 if (verbose > 1)
1657 *test = '/'; 1642 bb_error_msg("url:%s", url);
1643
1644 test = url;
1645 ip_allowed = checkPermIP();
1646 while (ip_allowed && (test = strchr(test + 1, '/')) != NULL) {
1647 /* have path1/path2 */
1648 *test = '\0';
1649 if (is_directory(url + 1, 1, &sb)) {
1650 /* may be having subdir config */
1651 parse_conf(url + 1, SUBDIR_PARSE);
1652 ip_allowed = checkPermIP();
1658 } 1653 }
1659 if (blank >= 0) { 1654 *test = '/';
1660 /* read until blank line for HTTP version specified, else parse immediate */ 1655 }
1661 while (1) { 1656 if (blank >= 0) {
1662 alarm(TIMEOUT); 1657 /* read until blank line for HTTP version specified, else parse immediate */
1663 if (!get_line()) 1658 while (1) {
1664 break; /* EOF or error or empty line */ 1659 alarm(TIMEOUT);
1665 1660 if (!get_line())
1666 if (DEBUG) 1661 break; /* EOF or error or empty line */
1667 bb_error_msg("header: '%s'", iobuf); 1662
1663 if (DEBUG)
1664 bb_error_msg("header: '%s'", iobuf);
1668#if ENABLE_FEATURE_HTTPD_CGI 1665#if ENABLE_FEATURE_HTTPD_CGI
1669 /* try and do our best to parse more lines */ 1666 /* try and do our best to parse more lines */
1670 if ((STRNCASECMP(iobuf, "Content-length:") == 0)) { 1667 if ((STRNCASECMP(iobuf, "Content-length:") == 0)) {
1671 /* extra read only for POST */ 1668 /* extra read only for POST */
1672 if (prequest != request_GET) { 1669 if (prequest != request_GET) {
1673 test = iobuf + sizeof("Content-length:") - 1; 1670 test = iobuf + sizeof("Content-length:") - 1;
1674 if (!test[0]) 1671 if (!test[0])
1675 _exit(0); 1672 _exit(0);
1676 errno = 0; 1673 errno = 0;
1677 /* not using strtoul: it ignores leading minus! */ 1674 /* not using strtoul: it ignores leading minus! */
1678 length = strtol(test, &test, 10); 1675 length = strtol(test, &test, 10);
1679 /* length is "ulong", but we need to pass it to int later */ 1676 /* length is "ulong", but we need to pass it to int later */
1680 /* so we check for negative or too large values in one go: */ 1677 /* so we check for negative or too large values in one go: */
1681 /* (long -> ulong conv caused negatives to be seen as > INT_MAX) */ 1678 /* (long -> ulong conv caused negatives to be seen as > INT_MAX) */
1682 if (test[0] || errno || length > INT_MAX) 1679 if (test[0] || errno || length > INT_MAX)
1683 _exit(0); 1680 _exit(0);
1684 }
1685 } else if (STRNCASECMP(iobuf, "Cookie:") == 0) {
1686 cookie = strdup(skip_whitespace(iobuf + sizeof("Cookie:")-1));
1687 } else if (STRNCASECMP(iobuf, "Content-Type:") == 0) {
1688 content_type = strdup(skip_whitespace(iobuf + sizeof("Content-Type:")-1));
1689 } else if (STRNCASECMP(iobuf, "Referer:") == 0) {
1690 referer = strdup(skip_whitespace(iobuf + sizeof("Referer:")-1));
1691 } else if (STRNCASECMP(iobuf, "User-Agent:") == 0) {
1692 user_agent = strdup(skip_whitespace(iobuf + sizeof("User-Agent:")-1));
1693 } 1681 }
1682 } else if (STRNCASECMP(iobuf, "Cookie:") == 0) {
1683 cookie = strdup(skip_whitespace(iobuf + sizeof("Cookie:")-1));
1684 } else if (STRNCASECMP(iobuf, "Content-Type:") == 0) {
1685 content_type = strdup(skip_whitespace(iobuf + sizeof("Content-Type:")-1));
1686 } else if (STRNCASECMP(iobuf, "Referer:") == 0) {
1687 referer = strdup(skip_whitespace(iobuf + sizeof("Referer:")-1));
1688 } else if (STRNCASECMP(iobuf, "User-Agent:") == 0) {
1689 user_agent = strdup(skip_whitespace(iobuf + sizeof("User-Agent:")-1));
1690 }
1694#endif 1691#endif
1695#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 1692#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
1696 if (STRNCASECMP(iobuf, "Authorization:") == 0) { 1693 if (STRNCASECMP(iobuf, "Authorization:") == 0) {
1697 /* We only allow Basic credentials. 1694 /* We only allow Basic credentials.
1698 * It shows up as "Authorization: Basic <userid:password>" where 1695 * It shows up as "Authorization: Basic <userid:password>" where
1699 * the userid:password is base64 encoded. 1696 * the userid:password is base64 encoded.
1700 */ 1697 */
1701 test = skip_whitespace(iobuf + sizeof("Authorization:")-1); 1698 test = skip_whitespace(iobuf + sizeof("Authorization:")-1);
1702 if (STRNCASECMP(test, "Basic") != 0) 1699 if (STRNCASECMP(test, "Basic") != 0)
1703 continue; 1700 continue;
1704 test += sizeof("Basic")-1; 1701 test += sizeof("Basic")-1;
1705 /* decodeBase64() skips whitespace itself */ 1702 /* decodeBase64() skips whitespace itself */
1706 decodeBase64(test); 1703 decodeBase64(test);
1707 credentials = checkPerm(url, test); 1704 credentials = checkPerm(url, test);
1708 } 1705 }
1709#endif /* FEATURE_HTTPD_BASIC_AUTH */ 1706#endif /* FEATURE_HTTPD_BASIC_AUTH */
1710 } /* while extra header reading */ 1707 } /* while extra header reading */
1711 } 1708 }
1712 alarm(0);
1713 1709
1714 if (strcmp(bb_basename(url), httpd_conf) == 0 || ip_allowed == 0) { 1710 alarm(0);
1715 /* protect listing [/path]/httpd_conf or IP deny */ 1711
1716 send_headers_and_exit(HTTP_FORBIDDEN); 1712 if (strcmp(bb_basename(url), httpd_conf) == 0 || ip_allowed == 0) {
1717 } 1713 /* protect listing [/path]/httpd_conf or IP deny */
1714 send_headers_and_exit(HTTP_FORBIDDEN);
1715 }
1718 1716
1719#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 1717#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
1720 if (credentials <= 0 && checkPerm(url, ":") == 0) { 1718 if (credentials <= 0 && checkPerm(url, ":") == 0) {
1721 send_headers_and_exit(HTTP_UNAUTHORIZED); 1719 send_headers_and_exit(HTTP_UNAUTHORIZED);
1722 } 1720 }
1723#endif 1721#endif
1724 1722
1725 if (found_moved_temporarily) { 1723 if (found_moved_temporarily) {
1726 send_headers_and_exit(HTTP_MOVED_TEMPORARILY); 1724 send_headers_and_exit(HTTP_MOVED_TEMPORARILY);
1727 } 1725 }
1728 1726
1729 test = url + 1; /* skip first '/' */ 1727 test = url + 1; /* skip first '/' */
1730 1728
1731#if ENABLE_FEATURE_HTTPD_CGI 1729#if ENABLE_FEATURE_HTTPD_CGI
1732 if (strncmp(test, "cgi-bin", 7) == 0) { 1730 if (strncmp(test, "cgi-bin", 7) == 0) {
1733 if (test[7] == '/' && test[8] == '\0') { 1731 if (test[7] == '/' && test[8] == '\0') {
1734 /* protect listing cgi-bin/ */ 1732 /* protect listing cgi-bin/ */
1735 send_headers_and_exit(HTTP_FORBIDDEN); 1733 send_headers_and_exit(HTTP_FORBIDDEN);
1736 }
1737 send_cgi_and_exit(url, prequest, length, cookie, content_type);
1738 } 1734 }
1735 send_cgi_and_exit(url, prequest, length, cookie, content_type);
1736 }
1739#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR 1737#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
1740 { 1738 {
1741 char *suffix = strrchr(test, '.'); 1739 char *suffix = strrchr(test, '.');
1742 if (suffix) { 1740 if (suffix) {
1743 Htaccess *cur; 1741 Htaccess *cur;
1744 for (cur = script_i; cur; cur = cur->next) { 1742 for (cur = script_i; cur; cur = cur->next) {
1745 if (strcmp(cur->before_colon + 1, suffix) == 0) { 1743 if (strcmp(cur->before_colon + 1, suffix) == 0) {
1746 send_cgi_and_exit(url, prequest, length, cookie, content_type); 1744 send_cgi_and_exit(url, prequest, length, cookie, content_type);
1747 }
1748 } 1745 }
1749 } 1746 }
1750 } 1747 }
1748 }
1751#endif 1749#endif
1752 if (prequest != request_GET) { 1750 if (prequest != request_GET) {
1753 send_headers_and_exit(HTTP_NOT_IMPLEMENTED); 1751 send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
1754 } 1752 }
1755#endif /* FEATURE_HTTPD_CGI */ 1753#endif /* FEATURE_HTTPD_CGI */
1756 if (purl[-1] == '/') 1754 if (purl[-1] == '/')
1757 strcpy(purl, "index.html"); 1755 strcpy(purl, "index.html");
1758 if (stat(test, &sb) == 0) { 1756 if (stat(test, &sb) == 0) {
1759 /* It's a dir URL and there is index.html */ 1757 /* It's a dir URL and there is index.html */
1760 ContentLength = sb.st_size; 1758 ContentLength = sb.st_size;
1761 last_mod = sb.st_mtime; 1759 last_mod = sb.st_mtime;
1762 } 1760 }
1763#if ENABLE_FEATURE_HTTPD_CGI 1761#if ENABLE_FEATURE_HTTPD_CGI
1764 else if (purl[-1] == '/') { 1762 else if (purl[-1] == '/') {
1765 /* It's a dir URL and there is no index.html 1763 /* It's a dir URL and there is no index.html
1766 * Try cgi-bin/index.cgi */ 1764 * Try cgi-bin/index.cgi */
1767 if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) { 1765 if (access("/cgi-bin/index.cgi"+1, X_OK) == 0) {
1768 purl[0] = '\0'; 1766 purl[0] = '\0';
1769 g_query = url; 1767 g_query = url;
1770 send_cgi_and_exit("/cgi-bin/index.cgi", prequest, length, cookie, content_type); 1768 send_cgi_and_exit("/cgi-bin/index.cgi", prequest, length, cookie, content_type);
1771 }
1772 } 1769 }
1770 }
1773#endif /* FEATURE_HTTPD_CGI */ 1771#endif /* FEATURE_HTTPD_CGI */
1774 send_file_and_exit(test);
1775 } while (0);
1776 1772
1777 _exit(0); 1773 send_file_and_exit(test);
1778 1774
1779#if 0 /* Is this needed? Why? */ 1775#if 0 /* Is this needed? Why? */
1780 if (DEBUG) 1776 if (DEBUG)
@@ -1817,7 +1813,6 @@ static void handle_incoming_and_exit(void)
1817static void mini_httpd(int server) ATTRIBUTE_NORETURN; 1813static void mini_httpd(int server) ATTRIBUTE_NORETURN;
1818static void mini_httpd(int server) 1814static void mini_httpd(int server)
1819{ 1815{
1820 /* copy the ports we are watching to the readfd set */
1821 while (1) { 1816 while (1) {
1822 int n; 1817 int n;
1823 len_and_sockaddr fromAddr; 1818 len_and_sockaddr fromAddr;