On Thursday 12 June 2008 21:43, Peter Korsgaard wrote:
> From: Peter Korsgaard <[EMAIL PROTECTED]>
>
> checkPerm only verified as many characters of the username as provided
> by the client, so E.G. an empty username would always match.
>
> Cleanup and save a few bytes while we are at it:
>
> function old new delta
> checkPerm 359 350 -9
> ------------------------------------------------------------------------------
> (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-9) Total: -9 bytes
>
> Based on (incorrect) patch by Lubos Stanek (lubek) sent to the openwrt list:
> http://thread.gmane.org/gmane.comp.embedded.openwrt.devel/1464
>
> Signed-off-by: Peter Korsgaard <[EMAIL PROTECTED]>
> ---
> networking/httpd.c | 28 +++++++++++++---------------
> 1 files changed, 13 insertions(+), 15 deletions(-)
>
> diff --git a/networking/httpd.c b/networking/httpd.c
> index 352a97d..db04cde 100644
> --- a/networking/httpd.c
> +++ b/networking/httpd.c
> @@ -1710,29 +1710,27 @@ static int checkPerm(const char *path, const char
> *request)
> if (strncmp(p0, path, l) == 0
> && (l == 1 || path[l] == '/' || path[l] == '\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;
> - }
I don't see what ensures ':' is always there.
The code we are called from is:
if (STRNCASECMP(iobuf, "Authorization:") == 0) {
/* We only allow Basic credentials.
* It shows up as "Authorization: Basic
<userid:password>" where
* the userid:password is base64 encoded.
*/
tptr = skip_whitespace(iobuf +
sizeof("Authorization:")-1);
if (STRNCASECMP(tptr, "Basic") != 0)
continue;
tptr += sizeof("Basic")-1;
/* decodeBase64() skips whitespace itself */
decodeBase64(tptr);
credentials = checkPerm(urlcopy, tptr); <=======
}
and here user can supply bad <userid:password> without ':'.
>
> if (ENABLE_FEATURE_HTTPD_AUTH_MD5) {
> char *pp;
>
> - if (strncmp(p, request, u - request) != 0) {
> - /* user doesn't match */
> - 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);
> + && pp[3] == '$' && pp[4]) {
> + char *encrypted;
> + int r, len;
> +
> + len = 1 + pp - p;
> + if (strncmp(p, request, len) != 0) {
> + /* user doesn't match */
> + continue;
> + }
> +
> + encrypted = pw_encrypt(request+len,
> p+len, 1);
> + r = strcmp(encrypted, p+len);
I spent some ten minutes understanding what is done here.
> free(encrypted);
> if (r == 0)
> goto set_remoteuser_var; /*
> Ok */
> @@ -1743,7 +1741,7 @@ static int checkPerm(const char *path, const char
> *request)
>
> if (strcmp(p, request) == 0) {
> set_remoteuser_var:
> - remoteuser = xstrndup(request, u - request);
> + remoteuser = xstrndup(request, strchr(request,
> ':') - request);
Here where request without ':' will bite us.
BTW: any idea why this routine locks on first found path?
This code part:
p0 = cur->before_colon;
if (prev != NULL && strcmp(prev, p0) != 0)
continue; /* find next identical */
Also: any idea what is going here in handle_incoming_and_exit()?
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
int credentials = -1; /* if not required this is Ok */
#endif
...
... (checks "Authorization: Basic <userid:password>" if present, sets
credentials to 0/1)
...
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH
if (credentials <= 0 && checkPerm(urlcopy, ":") == 0) {
send_headers_and_exit(HTTP_UNAUTHORIZED);
}
#endif
So, if there were no "Authorization: Basic", we still check empty
username/passwd.
ok. But the same will happen if "Authorization: Basic" was given with wrong
passwd!
Should it be "if (credentials < 0..."?
I applied your patch, and then did heavy editing on top -
variable names, comments, etc in config file parsing were atrocious.
Can you test current svn?
Thanks!
--
vda
_______________________________________________
busybox mailing list
[email protected]
http://busybox.net/cgi-bin/mailman/listinfo/busybox