diff options
-rw-r--r-- | networking/httpd.c | 225 |
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 "<Hello World>" | 33 | * bar=`httpd -e "<Hello World>"` # encode as "<Hello World>" |
@@ -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 | */ |
1690 | static int checkPerm(const char *path, const char *request) | 1667 | static 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 |