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.
|
||||
*/
|
||||
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;
|
||||
const char *p;
|
||||
const char *p0;
|
||||
|
||||
const char *prev = NULL;
|
||||
|
||||
/* This could stand some work */
|
||||
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)
|
||||
fprintf(stderr, "checkPerm: '%s' ? '%s'\n", p0, request);
|
||||
fprintf(stderr, "checkPerm: '%s' ? '%s'\n", dir_prefix, user_and_passwd);
|
||||
|
||||
l = strlen(p0);
|
||||
if (strncmp(p0, path, l) == 0
|
||||
&& (l == 1 || path[l] == '/' || path[l] == '\0')
|
||||
/* If it's not a prefix match, continue searching */
|
||||
len = strlen(dir_prefix);
|
||||
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;
|
||||
/* path match found. Check request */
|
||||
/* for check next /path:user:password */
|
||||
prev = p0;
|
||||
u = strchr(request, ':');
|
||||
if (u == NULL) {
|
||||
/* bad request, ':' required */
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ENABLE_FEATURE_HTTPD_AUTH_MD5) {
|
||||
char *pp;
|
||||
/* Path match found */
|
||||
prev = dir_prefix;
|
||||
|
||||
if (strncmp(p, request, u - request) != 0) {
|
||||
/* user doesn't match */
|
||||
if (ENABLE_FEATURE_HTTPD_AUTH_MD5) {
|
||||
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;
|
||||
}
|
||||
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:
|
||||
remoteuser = xstrndup(request, u - request);
|
||||
return 1; /* Ok */
|
||||
}
|
||||
/* unauthorized */
|
||||
remoteuser = xstrndup(user_and_passwd,
|
||||
strchrnul(user_and_passwd, ':') - user_and_passwd);
|
||||
return 1; /* Ok */
|
||||
}
|
||||
} /* 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 */
|
||||
|
||||
@ -2039,7 +2045,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
|
||||
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
|
||||
/* Case: no "Authorization:" was seen, but page does require passwd.
|
||||
* 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);
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user