httpd: fix decode of '/' when called via -d

This commit is contained in:
Denis Vlasenko 2006-11-29 15:58:50 +00:00
parent 2425bdce34
commit a35c9e91ba

View File

@ -671,44 +671,48 @@ static char *encodeString(const char *string)
* *
* $Parameters: * $Parameters:
* (char *) string . . . The first string to decode. * (char *) string . . . The first string to decode.
* (int) flag . . . 1 if need to decode '+' as ' ' for CGI * (int) option_d . . 1 if called for httpd -d
* *
* $Return: (char *) . . . . A pointer to the decoded string (same as input). * $Return: (char *) . . . . A pointer to the decoded string (same as input).
* *
* $Errors: None * $Errors: None
* *
****************************************************************************/ ****************************************************************************/
static char *decodeString(char *orig, int flag_plus_to_space) static char *decodeString(char *orig, int option_d)
{ {
/* note that decoded string is always shorter than original */ /* note that decoded string is always shorter than original */
char *string = orig; char *string = orig;
char *ptr = string; char *ptr = string;
char c;
while (*ptr) { while ((c = *ptr++) != '\0') {
if (*ptr == '+' && flag_plus_to_space) { unsigned value1, value2;
if (option_d && c == '+') {
*string++ = ' '; *string++ = ' ';
ptr++; continue;
} else if (*ptr != '%') { }
*string++ = *ptr++; if (c != '%') {
} else { *string++ = c;
unsigned int value1, value2; continue;
}
ptr++;
if (sscanf(ptr, "%1X", &value1) != 1 if (sscanf(ptr, "%1X", &value1) != 1
|| sscanf(ptr+1, "%1X", &value2) != 1 || sscanf(ptr+1, "%1X", &value2) != 1
) { ) {
if (!flag_plus_to_space) if (!option_d)
return NULL; return NULL;
*string++ = '%'; *string++ = '%';
} else { continue;
}
value1 = value1 * 16 + value2; value1 = value1 * 16 + value2;
if (value1 == '/' || value1 == 0) if (!option_d && (value1 == '/' || value1 == '\0')) {
return orig+1; /* caller takes it as indication of invalid
* (dangerous wrt exploits) chars */
return orig + 1;
}
*string++ = value1; *string++ = value1;
ptr += 2; ptr += 2;
} }
}
}
*string = '\0'; *string = '\0';
return orig; return orig;
} }
@ -1510,8 +1514,8 @@ static void handleIncoming(void)
test = decodeString(url, 0); test = decodeString(url, 0);
if (test == NULL) if (test == NULL)
goto BAD_REQUEST; goto BAD_REQUEST;
/* FIXME: bug? should be "url+1"? */ if (test == url+1) {
if (test == (buf+1)) { /* '/' or NUL is encoded */
sendHeaders(HTTP_NOT_FOUND); sendHeaders(HTTP_NOT_FOUND);
break; break;
} }
@ -1909,12 +1913,12 @@ int httpd_main(int argc, char *argv[])
char *e; char *e;
// FIXME: what the default group should be? // FIXME: what the default group should be?
ugid.gid = -1; ugid.gid = -1;
ugid.uid = strtoul(s_ugid, &e, 0); ugid.uid = bb_strtoul(s_ugid, &e, 0);
if (*e == ':') { if (*e == ':') {
e++; e++;
ugid.gid = strtoul(e, &e, 0); ugid.gid = bb_strtoul(e, NULL, 0);
} }
if (*e != '\0') { if (errno) {
/* not integer */ /* not integer */
if (!uidgid_get(&ugid, s_ugid)) if (!uidgid_get(&ugid, s_ugid))
bb_error_msg_and_die("unrecognized user[:group] " bb_error_msg_and_die("unrecognized user[:group] "
@ -1942,9 +1946,7 @@ int httpd_main(int argc, char *argv[])
#if ENABLE_FEATURE_HTTPD_CGI #if ENABLE_FEATURE_HTTPD_CGI
{ {
char *p = getenv("PATH"); char *p = getenv("PATH");
if (p) { p = xstrdup(p); /* if gets NULL, returns NULL */
p = xstrdup(p);
}
clearenv(); clearenv();
if (p) if (p)
setenv1("PATH", p); setenv1("PATH", p);