mirror of
https://github.com/topjohnwu/ndk-busybox.git
synced 2024-12-14 15:28:38 +00:00
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
This commit is contained in:
parent
0eb406caa8
commit
25b463079d
@ -1664,70 +1664,76 @@ static int checkPermIP(void)
|
|||||||
*
|
*
|
||||||
* Returns 1 if user_and_passwd is OK.
|
* Returns 1 if user_and_passwd is OK.
|
||||||
*/
|
*/
|
||||||
static int check_user_passwd(const char *path, const char *request)
|
static int check_user_passwd(const char *path, const char *user_and_passwd)
|
||||||
{
|
{
|
||||||
Htaccess *cur;
|
Htaccess *cur;
|
||||||
const char *p;
|
|
||||||
const char *p0;
|
|
||||||
|
|
||||||
const char *prev = NULL;
|
const char *prev = NULL;
|
||||||
|
|
||||||
/* This could stand some work */
|
|
||||||
for (cur = g_auth; cur; cur = cur->next) {
|
for (cur = g_auth; cur; cur = cur->next) {
|
||||||
size_t l;
|
const char *dir_prefix;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
dir_prefix = cur->before_colon;
|
||||||
|
|
||||||
|
/* WHY? */
|
||||||
|
/* If already saw a match, don't accept other different matches */
|
||||||
|
if (prev && strcmp(prev, dir_prefix) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
p0 = cur->before_colon;
|
|
||||||
if (prev != NULL && strcmp(prev, p0) != 0)
|
|
||||||
continue; /* find next identical */
|
|
||||||
p = cur->after_colon;
|
|
||||||
if (DEBUG)
|
if (DEBUG)
|
||||||
fprintf(stderr, "checkPerm: '%s' ? '%s'\n", p0, request);
|
fprintf(stderr, "checkPerm: '%s' ? '%s'\n", dir_prefix, user_and_passwd);
|
||||||
|
|
||||||
l = strlen(p0);
|
/* If it's not a prefix match, continue searching */
|
||||||
if (strncmp(p0, path, l) == 0
|
len = strlen(dir_prefix);
|
||||||
&& (l == 1 || path[l] == '/' || path[l] == '\0')
|
if (len != 1 /* dir_prefix "/" matches all, don't need to check */
|
||||||
|
&& (strncmp(dir_prefix, path, len) != 0
|
||||||
|
|| (path[len] != '/' && path[len] != '\0'))
|
||||||
) {
|
) {
|
||||||
char *u;
|
continue;
|
||||||
/* path match found. Check request */
|
}
|
||||||
/* for check next /path:user:password */
|
|
||||||
prev = p0;
|
|
||||||
u = strchr(request, ':');
|
|
||||||
if (u == NULL) {
|
|
||||||
/* bad request, ':' required */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ENABLE_FEATURE_HTTPD_AUTH_MD5) {
|
/* Path match found */
|
||||||
char *pp;
|
prev = dir_prefix;
|
||||||
|
|
||||||
if (strncmp(p, request, u - request) != 0) {
|
if (ENABLE_FEATURE_HTTPD_AUTH_MD5) {
|
||||||
/* user doesn't match */
|
char *md5_passwd;
|
||||||
|
|
||||||
|
md5_passwd = strchr(cur->after_colon, ':');
|
||||||
|
if (md5_passwd && md5_passwd[1] == '$' && md5_passwd[2] == '1'
|
||||||
|
&& md5_passwd[3] == '$' && md5_passwd[4]
|
||||||
|
) {
|
||||||
|
char *encrypted;
|
||||||
|
int r, user_len_p1;
|
||||||
|
|
||||||
|
md5_passwd++;
|
||||||
|
user_len_p1 = md5_passwd - cur->after_colon;
|
||||||
|
/* comparing "user:" */
|
||||||
|
if (strncmp(cur->after_colon, user_and_passwd, user_len_p1) != 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
pp = strchr(p, ':');
|
|
||||||
if (pp && pp[1] == '$' && pp[2] == '1'
|
|
||||||
&& pp[3] == '$' && pp[4]
|
|
||||||
) {
|
|
||||||
char *encrypted = pw_encrypt(u+1, ++pp, 1);
|
|
||||||
int r = strcmp(encrypted, pp);
|
|
||||||
free(encrypted);
|
|
||||||
if (r == 0)
|
|
||||||
goto set_remoteuser_var; /* Ok */
|
|
||||||
/* unauthorized */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(p, request) == 0) {
|
encrypted = pw_encrypt(
|
||||||
|
user_and_passwd + user_len_p1 /* cleartext pwd from user */,
|
||||||
|
md5_passwd /*salt */, 1 /* cleanup */);
|
||||||
|
r = strcmp(encrypted, md5_passwd);
|
||||||
|
free(encrypted);
|
||||||
|
if (r == 0)
|
||||||
|
goto set_remoteuser_var; /* Ok */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Comparing plaintext "user:pass" in one go */
|
||||||
|
if (strcmp(cur->after_colon, user_and_passwd) == 0) {
|
||||||
set_remoteuser_var:
|
set_remoteuser_var:
|
||||||
remoteuser = xstrndup(request, u - request);
|
remoteuser = xstrndup(user_and_passwd,
|
||||||
return 1; /* Ok */
|
strchrnul(user_and_passwd, ':') - user_and_passwd);
|
||||||
}
|
return 1; /* Ok */
|
||||||
/* unauthorized */
|
|
||||||
}
|
}
|
||||||
} /* for */
|
} /* for */
|
||||||
|
|
||||||
return prev == NULL;
|
/* 0(bad) if prev is set: matches were found but passwd was wrong */
|
||||||
|
return (prev == NULL);
|
||||||
}
|
}
|
||||||
#endif /* FEATURE_HTTPD_BASIC_AUTH */
|
#endif /* FEATURE_HTTPD_BASIC_AUTH */
|
||||||
|
|
||||||
@ -2039,7 +2045,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
|
|||||||
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
|
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
|
||||||
/* Case: no "Authorization:" was seen, but page does require passwd.
|
/* Case: no "Authorization:" was seen, but page does require passwd.
|
||||||
* Check that with dummy user:pass */
|
* Check that with dummy user:pass */
|
||||||
if ((authorized <= 0) && check_user_passwd(urlcopy, ":") == 0) {
|
if ((authorized < 0) && check_user_passwd(urlcopy, ":") == 0) {
|
||||||
send_headers_and_exit(HTTP_UNAUTHORIZED);
|
send_headers_and_exit(HTTP_UNAUTHORIZED);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user