httpd: fix /../ sanitization (had one extra semicolon). rewrote it

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2011-12-16 01:37:02 +01:00
parent cda6ea905d
commit b05cd6b7a7

View File

@ -2012,30 +2012,36 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
/* Algorithm stolen from libbb bb_simplify_path(), /* Algorithm stolen from libbb bb_simplify_path(),
* but don't strdup, retain trailing slash, protect root */ * but don't strdup, retain trailing slash, protect root */
urlp = tptr = urlcopy; urlp = tptr = urlcopy;
do { for (;;) {
if (*urlp == '/') { if (*urlp == '/') {
/* skip duplicate (or initial) slash */ /* skip duplicate (or initial) slash */
if (*tptr == '/') { if (*tptr == '/') {
continue; goto next_char;
} }
if (*tptr == '.') { if (*tptr == '.') {
/* skip extra "/./" */ if (tptr[1] == '.' && (tptr[2] == '/' || tptr[2] == '\0')) {
if (tptr[1] == '/' || !tptr[1]) { /* "..": be careful */
continue; /* protect root */
} if (urlp == urlcopy)
/* "..": be careful */
if (tptr[1] == '.' && (tptr[2] == '/' || !tptr[2])) {
++tptr;
if (urlp == urlcopy) /* protect root */
send_headers_and_exit(HTTP_BAD_REQUEST); send_headers_and_exit(HTTP_BAD_REQUEST);
while (*--urlp != '/') /* omit previous dir */; /* omit previous dir */
while (*--urlp != '/')
continue; continue;
/* skip to "./" or ".<NUL>" */
tptr++;
}
if (tptr[1] == '/' || tptr[1] == '\0') {
/* skip extra "/./" */
goto next_char;
} }
} }
} }
*++urlp = *tptr; *++urlp = *tptr;
} while (*++tptr); if (*urlp == '\0')
*++urlp = '\0'; /* terminate after last character */ break;
next_char:
tptr++;
}
/* If URL is a directory, add '/' */ /* If URL is a directory, add '/' */
if (urlp[-1] != '/') { if (urlp[-1] != '/') {