aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-06-13 09:55:13 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-06-13 09:55:13 +0000
commit25b463079d963ae4f482db7ced14d14c28b907b8 (patch)
tree80ff01df839338048b35d9abfd2a667fbe68a30a
parent0eb406caa85d6203b9d80da89e197f0b3e9fcc1d (diff)
downloadbusybox-w32-25b463079d963ae4f482db7ced14d14c28b907b8.tar.gz
busybox-w32-25b463079d963ae4f482db7ced14d14c28b907b8.tar.bz2
busybox-w32-25b463079d963ae4f482db7ced14d14c28b907b8.zip
httpd: fix bugs in authentication (by Peter Korsgaard <jacmet ATuclibc.org>)
we were accepting empty username; also we were always checking dummy user:passwd pair ":" if user gave us wrong one. function old new delta check_user_passwd 338 319 -19
-rw-r--r--networking/httpd.c98
1 files changed, 52 insertions, 46 deletions
diff --git a/networking/httpd.c b/networking/httpd.c
index e3c1a4e11..382893bfb 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -1664,70 +1664,76 @@ static int checkPermIP(void)
1664 * 1664 *
1665 * Returns 1 if user_and_passwd is OK. 1665 * Returns 1 if user_and_passwd is OK.
1666 */ 1666 */
1667static int check_user_passwd(const char *path, const char *request) 1667static int check_user_passwd(const char *path, const char *user_and_passwd)
1668{ 1668{
1669 Htaccess *cur; 1669 Htaccess *cur;
1670 const char *p;
1671 const char *p0;
1672
1673 const char *prev = NULL; 1670 const char *prev = NULL;
1674 1671
1675 /* This could stand some work */
1676 for (cur = g_auth; cur; cur = cur->next) { 1672 for (cur = g_auth; cur; cur = cur->next) {
1677 size_t l; 1673 const char *dir_prefix;
1674 size_t len;
1675
1676 dir_prefix = cur->before_colon;
1677
1678 /* WHY? */
1679 /* If already saw a match, don't accept other different matches */
1680 if (prev && strcmp(prev, dir_prefix) != 0)
1681 continue;
1678 1682
1679 p0 = cur->before_colon;
1680 if (prev != NULL && strcmp(prev, p0) != 0)
1681 continue; /* find next identical */
1682 p = cur->after_colon;
1683 if (DEBUG) 1683 if (DEBUG)
1684 fprintf(stderr, "checkPerm: '%s' ? '%s'\n", p0, request); 1684 fprintf(stderr, "checkPerm: '%s' ? '%s'\n", dir_prefix, user_and_passwd);
1685 1685
1686 l = strlen(p0); 1686 /* If it's not a prefix match, continue searching */
1687 if (strncmp(p0, path, l) == 0 1687 len = strlen(dir_prefix);
1688 && (l == 1 || path[l] == '/' || path[l] == '\0') 1688 if (len != 1 /* dir_prefix "/" matches all, don't need to check */
1689 && (strncmp(dir_prefix, path, len) != 0
1690 || (path[len] != '/' && path[len] != '\0'))
1689 ) { 1691 ) {
1690 char *u; 1692 continue;
1691 /* path match found. Check request */ 1693 }
1692 /* for check next /path:user:password */
1693 prev = p0;
1694 u = strchr(request, ':');
1695 if (u == NULL) {
1696 /* bad request, ':' required */
1697 break;
1698 }
1699 1694
1700 if (ENABLE_FEATURE_HTTPD_AUTH_MD5) { 1695 /* Path match found */
1701 char *pp; 1696 prev = dir_prefix;
1702 1697
1703 if (strncmp(p, request, u - request) != 0) { 1698 if (ENABLE_FEATURE_HTTPD_AUTH_MD5) {
1704 /* user doesn't match */ 1699 char *md5_passwd;
1705 continue; 1700
1706 } 1701 md5_passwd = strchr(cur->after_colon, ':');
1707 pp = strchr(p, ':'); 1702 if (md5_passwd && md5_passwd[1] == '$' && md5_passwd[2] == '1'
1708 if (pp && pp[1] == '$' && pp[2] == '1' 1703 && md5_passwd[3] == '$' && md5_passwd[4]
1709 && pp[3] == '$' && pp[4] 1704 ) {
1710 ) { 1705 char *encrypted;
1711 char *encrypted = pw_encrypt(u+1, ++pp, 1); 1706 int r, user_len_p1;
1712 int r = strcmp(encrypted, pp); 1707
1713 free(encrypted); 1708 md5_passwd++;
1714 if (r == 0) 1709 user_len_p1 = md5_passwd - cur->after_colon;
1715 goto set_remoteuser_var; /* Ok */ 1710 /* comparing "user:" */
1716 /* unauthorized */ 1711 if (strncmp(cur->after_colon, user_and_passwd, user_len_p1) != 0) {
1717 continue; 1712 continue;
1718 } 1713 }
1714
1715 encrypted = pw_encrypt(
1716 user_and_passwd + user_len_p1 /* cleartext pwd from user */,
1717 md5_passwd /*salt */, 1 /* cleanup */);
1718 r = strcmp(encrypted, md5_passwd);
1719 free(encrypted);
1720 if (r == 0)
1721 goto set_remoteuser_var; /* Ok */
1722 continue;
1719 } 1723 }
1724 }
1720 1725
1721 if (strcmp(p, request) == 0) { 1726 /* Comparing plaintext "user:pass" in one go */
1727 if (strcmp(cur->after_colon, user_and_passwd) == 0) {
1722 set_remoteuser_var: 1728 set_remoteuser_var:
1723 remoteuser = xstrndup(request, u - request); 1729 remoteuser = xstrndup(user_and_passwd,
1724 return 1; /* Ok */ 1730 strchrnul(user_and_passwd, ':') - user_and_passwd);
1725 } 1731 return 1; /* Ok */
1726 /* unauthorized */
1727 } 1732 }
1728 } /* for */ 1733 } /* for */
1729 1734
1730 return prev == NULL; 1735 /* 0(bad) if prev is set: matches were found but passwd was wrong */
1736 return (prev == NULL);
1731} 1737}
1732#endif /* FEATURE_HTTPD_BASIC_AUTH */ 1738#endif /* FEATURE_HTTPD_BASIC_AUTH */
1733 1739
@@ -2039,7 +2045,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
2039#if ENABLE_FEATURE_HTTPD_BASIC_AUTH 2045#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
2040 /* Case: no "Authorization:" was seen, but page does require passwd. 2046 /* Case: no "Authorization:" was seen, but page does require passwd.
2041 * Check that with dummy user:pass */ 2047 * Check that with dummy user:pass */
2042 if ((authorized <= 0) && check_user_passwd(urlcopy, ":") == 0) { 2048 if ((authorized < 0) && check_user_passwd(urlcopy, ":") == 0) {
2043 send_headers_and_exit(HTTP_UNAUTHORIZED); 2049 send_headers_and_exit(HTTP_UNAUTHORIZED);
2044 } 2050 }
2045#endif 2051#endif