aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networking/httpd.c225
1 files changed, 102 insertions, 123 deletions
diff --git a/networking/httpd.c b/networking/httpd.c
index 352a97d3c..e3c1a4e11 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -27,7 +27,7 @@
27 * Doc: 27 * Doc:
28 * "CGI Environment Variables": http://hoohoo.ncsa.uiuc.edu/cgi/env.html 28 * "CGI Environment Variables": http://hoohoo.ncsa.uiuc.edu/cgi/env.html
29 * 29 *
30 * The server can also be invoked as a url arg decoder and html text encoder 30 * The applet can also be invoked as a url arg decoder and html text encoder
31 * as follows: 31 * as follows:
32 * foo=`httpd -d $foo` # decode "Hello%20World" as "Hello World" 32 * foo=`httpd -d $foo` # decode "Hello%20World" as "Hello World"
33 * bar=`httpd -e "<Hello World>"` # encode as "&#60Hello&#32World&#62" 33 * bar=`httpd -e "<Hello World>"` # encode as "&#60Hello&#32World&#62"
@@ -55,19 +55,11 @@
55 * .au:audio/basic # additional mime type for audio.au files 55 * .au:audio/basic # additional mime type for audio.au files
56 * *.php:/path/php # running cgi.php scripts through an interpreter 56 * *.php:/path/php # running cgi.php scripts through an interpreter
57 * 57 *
58 * A/D may be as a/d or allow/deny - first char case insensitive 58 * A/D may be as a/d or allow/deny - only first char matters.
59 * Deny IP rules take precedence over allow rules. 59 * Deny/Allow IP logic:
60 * 60 * - Default is to allow all (Allow all (A:*) is a no-op).
61 *
62 * The Deny/Allow IP logic:
63 *
64 * - Default is to allow all. No addresses are denied unless
65 * denied with a D: rule.
66 * - Order of Deny/Allow rules is significant
67 * - Deny rules take precedence over allow rules. 61 * - Deny rules take precedence over allow rules.
68 * - If a deny all rule (D:*) is used it acts as a catch-all for unmatched 62 * - "Deny all" rule (D:*) is applied last.
69 * addresses.
70 * - Specification of Allow all (A:*) is a no-op
71 * 63 *
72 * Example: 64 * Example:
73 * 1. Allow only specified addresses 65 * 1. Allow only specified addresses
@@ -494,10 +486,10 @@ static void parse_conf(const char *path, int flag)
494 || ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR 486 || ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
495 Htaccess *cur; 487 Htaccess *cur;
496#endif 488#endif
497 const char *cf = configFile; 489 const char *filename = configFile;
498 char buf[160]; 490 char buf[160];
499 char *p0; 491 char *p, *p0;
500 char *c, *p; 492 char *after_colon;
501 Htaccess_IP *pip; 493 Htaccess_IP *pip;
502 494
503 /* discard old rules */ 495 /* discard old rules */
@@ -520,20 +512,20 @@ static void parse_conf(const char *path, int flag)
520 } 512 }
521#endif 513#endif
522 514
523 if (flag == SUBDIR_PARSE || cf == NULL) { 515 if (flag == SUBDIR_PARSE || filename == NULL) {
524 cf = alloca(strlen(path) + sizeof(httpd_conf) + 2); 516 filename = alloca(strlen(path) + sizeof(httpd_conf) + 2);
525 sprintf((char *)cf, "%s/%s", path, httpd_conf); 517 sprintf((char *)filename, "%s/%s", path, httpd_conf);
526 } 518 }
527 519
528 while ((f = fopen(cf, "r")) == NULL) { 520 while ((f = fopen(filename, "r")) == NULL) {
529 if (flag == SUBDIR_PARSE || flag == FIND_FROM_HTTPD_ROOT) { 521 if (flag == SUBDIR_PARSE || flag == FIND_FROM_HTTPD_ROOT) {
530 /* config file not found, no changes to config */ 522 /* config file not found, no changes to config */
531 return; 523 return;
532 } 524 }
533 if (configFile && flag == FIRST_PARSE) /* if -c option given */ 525 if (configFile && flag == FIRST_PARSE) /* if -c option given */
534 bb_simple_perror_msg_and_die(cf); 526 bb_simple_perror_msg_and_die(filename);
535 flag = FIND_FROM_HTTPD_ROOT; 527 flag = FIND_FROM_HTTPD_ROOT;
536 cf = httpd_conf; 528 filename = httpd_conf;
537 } 529 }
538 530
539#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 531#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
@@ -541,58 +533,53 @@ static void parse_conf(const char *path, int flag)
541#endif 533#endif
542 /* This could stand some work */ 534 /* This could stand some work */
543 while ((p0 = fgets(buf, sizeof(buf), f)) != NULL) { 535 while ((p0 = fgets(buf, sizeof(buf), f)) != NULL) {
544 c = NULL; 536 after_colon = NULL;
545 for (p = p0; *p0 != '\0' && *p0 != '#'; p0++) { 537 for (p = p0; *p0 != '\0' && *p0 != '#'; p0++) {
546 if (!isspace(*p0)) { 538 if (!isspace(*p0)) {
547 *p++ = *p0; 539 *p++ = *p0;
548 if (*p0 == ':' && c == NULL) 540 if (*p0 == ':' && after_colon == NULL)
549 c = p; 541 after_colon = p;
550 } 542 }
551 } 543 }
552 *p = '\0'; 544 *p = '\0';
553 545
554 /* test for empty or strange line */ 546 /* test for empty or strange line */
555 if (c == NULL || *c == '\0') 547 if (after_colon == NULL || *after_colon == '\0')
556 continue; 548 continue;
557 p0 = buf; 549 p0 = buf;
558 if (*p0 == 'd') 550 if (*p0 == 'd' || *p0 == 'a')
559 *p0 = 'D'; 551 *p0 -= 0x20; /* a/d -> A/D */
560 if (*c == '*') { 552 if (*after_colon == '*') {
561 if (*p0 == 'D') { 553 if (*p0 == 'D') {
562 /* memorize deny all */ 554 /* memorize "deny all" */
563 flg_deny_all = 1; 555 flg_deny_all = 1;
564 } 556 }
565 /* skip default other "word:*" config lines */ 557 /* skip assumed "A:*", it is a default anyway */
566 continue; 558 continue;
567 } 559 }
568 560
569 if (*p0 == 'a')
570 *p0 = 'A';
571 if (*p0 == 'A' || *p0 == 'D') { 561 if (*p0 == 'A' || *p0 == 'D') {
572 /* storing current config IP line */ 562 /* storing current config IP line */
573 pip = xzalloc(sizeof(Htaccess_IP)); 563 pip = xzalloc(sizeof(Htaccess_IP));
574 if (pip) { 564 if (scan_ip_mask(after_colon, &(pip->ip), &(pip->mask))) {
575 if (scan_ip_mask(c, &(pip->ip), &(pip->mask))) { 565 /* IP{/mask} syntax error detected, protect all */
576 /* syntax IP{/mask} error detected, protect all */ 566 *p0 = 'D';
577 *p0 = 'D'; 567 pip->mask = 0;
578 pip->mask = 0; 568 }
579 } 569 pip->allow_deny = *p0;
580 pip->allow_deny = *p0; 570 if (*p0 == 'D') {
581 if (*p0 == 'D') { 571 /* Deny:from_IP - prepend */
582 /* Deny:from_IP move top */ 572 pip->next = ip_a_d;
583 pip->next = ip_a_d; 573 ip_a_d = pip;
574 } else {
575 /* A:from_IP - append (thus D precedes A) */
576 Htaccess_IP *prev_IP = ip_a_d;
577 if (prev_IP == NULL) {
584 ip_a_d = pip; 578 ip_a_d = pip;
585 } else { 579 } else {
586 /* add to bottom A:form_IP config line */ 580 while (prev_IP->next)
587 Htaccess_IP *prev_IP = ip_a_d; 581 prev_IP = prev_IP->next;
588 582 prev_IP->next = pip;
589 if (prev_IP == NULL) {
590 ip_a_d = pip;
591 } else {
592 while (prev_IP->next)
593 prev_IP = prev_IP->next;
594 prev_IP->next = pip;
595 }
596 } 583 }
597 } 584 }
598 continue; 585 continue;
@@ -601,24 +588,18 @@ static void parse_conf(const char *path, int flag)
601#if ENABLE_FEATURE_HTTPD_ERROR_PAGES 588#if ENABLE_FEATURE_HTTPD_ERROR_PAGES
602 if (flag == FIRST_PARSE && *p0 == 'E') { 589 if (flag == FIRST_PARSE && *p0 == 'E') {
603 unsigned i; 590 unsigned i;
604 /* error status code */ 591 int status = atoi(++p0); /* error status code */
605 int status = atoi(++p0);
606 /* c already points at the character following ':' in parse loop */
607 /* c = strchr(p0, ':'); c++; */
608 if (status < HTTP_CONTINUE) { 592 if (status < HTTP_CONTINUE) {
609 bb_error_msg("config error '%s' in '%s'", buf, cf); 593 bb_error_msg("config error '%s' in '%s'", buf, filename);
610 continue; 594 continue;
611 } 595 }
612
613 /* then error page; find matching status */ 596 /* then error page; find matching status */
614 for (i = 0; i < ARRAY_SIZE(http_response_type); i++) { 597 for (i = 0; i < ARRAY_SIZE(http_response_type); i++) {
615 if (http_response_type[i] == status) { 598 if (http_response_type[i] == status) {
616 // We chdir to home_httpd, thus no need to 599 /* We chdir to home_httpd, thus no need to
617 // concat_path_file(home_httpd, c) 600 * concat_path_file(home_httpd, after_colon)
618 //if (c[0] == '/' || home_httpd[0] != '/') 601 * here */
619 http_error_page[i] = xstrdup(c); 602 http_error_page[i] = xstrdup(after_colon);
620 //else
621 // http_error_page[i] = concat_path_file(home_httpd, c);
622 break; 603 break;
623 } 604 }
624 } 605 }
@@ -632,22 +613,22 @@ static void parse_conf(const char *path, int flag)
632 char *url_from, *host_port, *url_to; 613 char *url_from, *host_port, *url_to;
633 Htaccess_Proxy *proxy_entry; 614 Htaccess_Proxy *proxy_entry;
634 615
635 url_from = c; 616 url_from = after_colon;
636 host_port = strchr(c, ':'); 617 host_port = strchr(after_colon, ':');
637 if (host_port == NULL) { 618 if (host_port == NULL) {
638 bb_error_msg("config error '%s' in '%s'", buf, cf); 619 bb_error_msg("config error '%s' in '%s'", buf, filename);
639 continue; 620 continue;
640 } 621 }
641 *host_port++ = '\0'; 622 *host_port++ = '\0';
642 if (strncmp(host_port, "http://", 7) == 0) 623 if (strncmp(host_port, "http://", 7) == 0)
643 host_port += 7; 624 host_port += 7;
644 if (*host_port == '\0') { 625 if (*host_port == '\0') {
645 bb_error_msg("config error '%s' in '%s'", buf, cf); 626 bb_error_msg("config error '%s' in '%s'", buf, filename);
646 continue; 627 continue;
647 } 628 }
648 url_to = strchr(host_port, '/'); 629 url_to = strchr(host_port, '/');
649 if (url_to == NULL) { 630 if (url_to == NULL) {
650 bb_error_msg("config error '%s' in '%s'", buf, cf); 631 bb_error_msg("config error '%s' in '%s'", buf, filename);
651 continue; 632 continue;
652 } 633 }
653 *url_to = '\0'; 634 *url_to = '\0';
@@ -665,45 +646,44 @@ static void parse_conf(const char *path, int flag)
665#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 646#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
666 if (*p0 == '/') { 647 if (*p0 == '/') {
667 /* make full path from httpd root / current_path / config_line_path */ 648 /* make full path from httpd root / current_path / config_line_path */
668 cf = (flag == SUBDIR_PARSE ? path : ""); 649 const char *tp = (flag == SUBDIR_PARSE ? path : "");
669 p0 = xmalloc(strlen(cf) + (c - buf) + 2 + strlen(c)); 650 p0 = xmalloc(strlen(tp) + (after_colon - buf) + 2 + strlen(after_colon));
670 c[-1] = '\0'; 651 after_colon[-1] = '\0';
671 sprintf(p0, "/%s%s", cf, buf); 652 sprintf(p0, "/%s%s", tp, buf);
672
673 /* another call bb_simplify_path */
674 cf = p = p0;
675 653
654 /* looks like bb_simplify_path... */
655 tp = p = p0;
676 do { 656 do {
677 if (*p == '/') { 657 if (*p == '/') {
678 if (*cf == '/') { /* skip duplicate (or initial) slash */ 658 if (*tp == '/') { /* skip duplicate (or initial) slash */
679 continue; 659 continue;
680 } 660 }
681 if (*cf == '.') { 661 if (*tp == '.') {
682 if (cf[1] == '/' || cf[1] == '\0') { /* remove extra '.' */ 662 if (tp[1] == '/' || tp[1] == '\0') { /* remove extra '.' */
683 continue; 663 continue;
684 } 664 }
685 if ((cf[1] == '.') && (cf[2] == '/' || cf[2] == '\0')) { 665 if ((tp[1] == '.') && (tp[2] == '/' || tp[2] == '\0')) {
686 ++cf; 666 ++tp;
687 if (p > p0) { 667 if (p > p0) {
688 while (*--p != '/') /* omit previous dir */; 668 while (*--p != '/') /* omit previous dir */
669 continue;
689 } 670 }
690 continue; 671 continue;
691 } 672 }
692 } 673 }
693 } 674 }
694 *++p = *cf; 675 *++p = *tp;
695 } while (*++cf); 676 } while (*++tp);
696 677
697 if ((p == p0) || (*p != '/')) { /* not a trailing slash */ 678 if ((p == p0) || (*p != '/')) { /* not a trailing slash */
698 ++p; /* so keep last character */ 679 ++p; /* so keep last character */
699 } 680 }
700 *p = ':'; 681 *p = ':';
701 strcpy(p + 1, c); 682 strcpy(p + 1, after_colon);
702 } 683 }
703#endif 684#endif
704
705 if (*p0 == 'I') { 685 if (*p0 == 'I') {
706 index_page = xstrdup(c); 686 index_page = xstrdup(after_colon);
707 continue; 687 continue;
708 } 688 }
709 689
@@ -712,38 +692,39 @@ static void parse_conf(const char *path, int flag)
712 || ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR 692 || ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
713 /* storing current config line */ 693 /* storing current config line */
714 cur = xzalloc(sizeof(Htaccess) + strlen(p0)); 694 cur = xzalloc(sizeof(Htaccess) + strlen(p0));
715 cf = strcpy(cur->before_colon, p0); 695 strcpy(cur->before_colon, p0);
716#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 696#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
717 if (*p0 == '/') 697 if (*p0 == '/') /* was malloced - see above */
718 free(p0); 698 free(p0);
719#endif 699#endif
720 c = strchr(cf, ':'); 700 cur->after_colon = strchr(cur->before_colon, ':');
721 *c++ = '\0'; 701 *cur->after_colon++ = '\0';
722 cur->after_colon = c;
723#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES 702#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_MIME_TYPES
724 if (*cf == '.') { 703 if (cur->before_colon[0] == '.') {
725 /* config .mime line move top for overwrite previous */ 704 /* .mime line: prepend to mime_a list */
726 cur->next = mime_a; 705 cur->next = mime_a;
727 mime_a = cur; 706 mime_a = cur;
728 continue; 707 continue;
729 } 708 }
730#endif 709#endif
731#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR 710#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
732 if (*cf == '*' && cf[1] == '.') { 711 if (cur->before_colon[0] == '*' && cur->before_colon[1] == '.') {
733 /* config script interpreter line move top for overwrite previous */ 712 /* script interpreter line: prepend to script_i list */
734 cur->next = script_i; 713 cur->next = script_i;
735 script_i = cur; 714 script_i = cur;
736 continue; 715 continue;
737 } 716 }
738#endif 717#endif
739#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 718#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
719//TODO: we do not test for leading "/"??
720//also, do we leak cur if BASIC_AUTH is off?
740 if (prev == NULL) { 721 if (prev == NULL) {
741 /* first line */ 722 /* first line */
742 g_auth = prev = cur; 723 g_auth = prev = cur;
743 } else { 724 } else {
744 /* sort path, if current length eq or bigger then move up */ 725 /* sort path, if current length eq or bigger then move up */
745 Htaccess *prev_hti = g_auth; 726 Htaccess *prev_hti = g_auth;
746 size_t l = strlen(cf); 727 size_t l = strlen(cur->before_colon);
747 Htaccess *hti; 728 Htaccess *hti;
748 729
749 for (hti = prev_hti; hti; hti = hti->next) { 730 for (hti = prev_hti; hti; hti = hti->next) {
@@ -1651,7 +1632,6 @@ static int checkPermIP(void)
1651{ 1632{
1652 Htaccess_IP *cur; 1633 Htaccess_IP *cur;
1653 1634
1654 /* This could stand some work */
1655 for (cur = ip_a_d; cur; cur = cur->next) { 1635 for (cur = ip_a_d; cur; cur = cur->next) {
1656#if DEBUG 1636#if DEBUG
1657 fprintf(stderr, 1637 fprintf(stderr,
@@ -1668,26 +1648,23 @@ static int checkPermIP(void)
1668 ); 1648 );
1669#endif 1649#endif
1670 if ((rmt_ip & cur->mask) == cur->ip) 1650 if ((rmt_ip & cur->mask) == cur->ip)
1671 return cur->allow_deny == 'A'; /* Allow/Deny */ 1651 return (cur->allow_deny == 'A'); /* A -> 1 */
1672 } 1652 }
1673 1653
1674 /* if unconfigured, return 1 - access from all */ 1654 return !flg_deny_all; /* depends on whether we saw "D:*" */
1675 return !flg_deny_all;
1676} 1655}
1677 1656
1678#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 1657#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
1679/* 1658/*
1680 * Check the permission file for access password protected. 1659 * Config file entries are of the form "/<path>:<user>:<passwd>".
1681 * 1660 * If config file has no prefix match for path, access is allowed.
1682 * If config file isn't present, everything is allowed.
1683 * Entries are of the form you can see example from header source
1684 * 1661 *
1685 * path The file path. 1662 * path The file path
1686 * request User information to validate. 1663 * user_and_passwd "user:passwd" to validate
1687 * 1664 *
1688 * Returns 1 if request is OK. 1665 * Returns 1 if user_and_passwd is OK.
1689 */ 1666 */
1690static int checkPerm(const char *path, const char *request) 1667static int check_user_passwd(const char *path, const char *request)
1691{ 1668{
1692 Htaccess *cur; 1669 Htaccess *cur;
1693 const char *p; 1670 const char *p;
@@ -1786,7 +1763,6 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
1786 char *urlcopy; 1763 char *urlcopy;
1787 char *urlp; 1764 char *urlp;
1788 char *tptr; 1765 char *tptr;
1789 int ip_allowed;
1790#if ENABLE_FEATURE_HTTPD_CGI 1766#if ENABLE_FEATURE_HTTPD_CGI
1791 static const char request_HEAD[] ALIGN1 = "HEAD"; 1767 static const char request_HEAD[] ALIGN1 = "HEAD";
1792 const char *prequest; 1768 const char *prequest;
@@ -1797,6 +1773,10 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
1797#define prequest request_GET 1773#define prequest request_GET
1798 unsigned long length = 0; 1774 unsigned long length = 0;
1799#endif 1775#endif
1776#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
1777 smallint authorized = -1;
1778#endif
1779 smallint ip_allowed;
1800 char http_major_version; 1780 char http_major_version;
1801#if ENABLE_FEATURE_HTTPD_PROXY 1781#if ENABLE_FEATURE_HTTPD_PROXY
1802 char http_minor_version; 1782 char http_minor_version;
@@ -1804,9 +1784,6 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
1804 char *header_ptr = header_ptr; 1784 char *header_ptr = header_ptr;
1805 Htaccess_Proxy *proxy_entry; 1785 Htaccess_Proxy *proxy_entry;
1806#endif 1786#endif
1807#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
1808 int credentials = -1; /* if not required this is Ok */
1809#endif
1810 1787
1811 /* Allocation of iobuf is postponed until now 1788 /* Allocation of iobuf is postponed until now
1812 * (IOW, server process doesn't need to waste 8k) */ 1789 * (IOW, server process doesn't need to waste 8k) */
@@ -1946,7 +1923,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
1946 /* have path1/path2 */ 1923 /* have path1/path2 */
1947 *tptr = '\0'; 1924 *tptr = '\0';
1948 if (is_directory(urlcopy + 1, 1, &sb)) { 1925 if (is_directory(urlcopy + 1, 1, &sb)) {
1949 /* may be having subdir config */ 1926 /* may have subdir config */
1950 parse_conf(urlcopy + 1, SUBDIR_PARSE); 1927 parse_conf(urlcopy + 1, SUBDIR_PARSE);
1951 ip_allowed = checkPermIP(); 1928 ip_allowed = checkPermIP();
1952 } 1929 }
@@ -2019,8 +1996,8 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2019#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 1996#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
2020 if (STRNCASECMP(iobuf, "Authorization:") == 0) { 1997 if (STRNCASECMP(iobuf, "Authorization:") == 0) {
2021 /* We only allow Basic credentials. 1998 /* We only allow Basic credentials.
2022 * It shows up as "Authorization: Basic <userid:password>" where 1999 * It shows up as "Authorization: Basic <user>:<passwd>" where
2023 * the userid:password is base64 encoded. 2000 * "<user>:<passwd>" is base64 encoded.
2024 */ 2001 */
2025 tptr = skip_whitespace(iobuf + sizeof("Authorization:")-1); 2002 tptr = skip_whitespace(iobuf + sizeof("Authorization:")-1);
2026 if (STRNCASECMP(tptr, "Basic") != 0) 2003 if (STRNCASECMP(tptr, "Basic") != 0)
@@ -2028,9 +2005,9 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2028 tptr += sizeof("Basic")-1; 2005 tptr += sizeof("Basic")-1;
2029 /* decodeBase64() skips whitespace itself */ 2006 /* decodeBase64() skips whitespace itself */
2030 decodeBase64(tptr); 2007 decodeBase64(tptr);
2031 credentials = checkPerm(urlcopy, tptr); 2008 authorized = check_user_passwd(urlcopy, tptr);
2032 } 2009 }
2033#endif /* FEATURE_HTTPD_BASIC_AUTH */ 2010#endif
2034#if ENABLE_FEATURE_HTTPD_RANGES 2011#if ENABLE_FEATURE_HTTPD_RANGES
2035 if (STRNCASECMP(iobuf, "Range:") == 0) { 2012 if (STRNCASECMP(iobuf, "Range:") == 0) {
2036 /* We know only bytes=NNN-[MMM] */ 2013 /* We know only bytes=NNN-[MMM] */
@@ -2054,13 +2031,15 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2054 /* We are done reading headers, disable peer timeout */ 2031 /* We are done reading headers, disable peer timeout */
2055 alarm(0); 2032 alarm(0);
2056 2033
2057 if (strcmp(bb_basename(urlcopy), httpd_conf) == 0 || ip_allowed == 0) { 2034 if (strcmp(bb_basename(urlcopy), httpd_conf) == 0 || !ip_allowed) {
2058 /* protect listing [/path]/httpd_conf or IP deny */ 2035 /* protect listing [/path]/httpd_conf or IP deny */
2059 send_headers_and_exit(HTTP_FORBIDDEN); 2036 send_headers_and_exit(HTTP_FORBIDDEN);
2060 } 2037 }
2061 2038
2062#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 2039#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
2063 if (credentials <= 0 && checkPerm(urlcopy, ":") == 0) { 2040 /* Case: no "Authorization:" was seen, but page does require passwd.
2041 * Check that with dummy user:pass */
2042 if ((authorized <= 0) && check_user_passwd(urlcopy, ":") == 0) {
2064 send_headers_and_exit(HTTP_UNAUTHORIZED); 2043 send_headers_and_exit(HTTP_UNAUTHORIZED);
2065 } 2044 }
2066#endif 2045#endif