diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-13 09:55:13 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-13 09:55:13 +0000 |
commit | 25b463079d963ae4f482db7ced14d14c28b907b8 (patch) | |
tree | 80ff01df839338048b35d9abfd2a667fbe68a30a | |
parent | 0eb406caa85d6203b9d80da89e197f0b3e9fcc1d (diff) | |
download | busybox-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.c | 98 |
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 | */ |
1667 | static int check_user_passwd(const char *path, const char *request) | 1667 | static 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 |