summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko2019-04-16 10:00:06 +0200
committerDenys Vlasenko2019-04-16 10:07:33 +0200
commitbae8f7eaf2997938615ed4282d6d93d3aa1f3fc1 (patch)
tree034d95d6c9a6a2c9dc6978774322aea0572d6a33
parent02d650e15919e48fe031308c77c041159c0e3631 (diff)
downloadbusybox-bae8f7eaf2997938615ed4282d6d93d3aa1f3fc1.zip
busybox-bae8f7eaf2997938615ed4282d6d93d3aa1f3fc1.tar.gz
httpd: do not percent-decode URI if proxying
The proxying is documented as follows: P:/url:[http://]hostname[:port]/new/path Howeverm urlcopy is not a true copy anymore when it is fdprint'ed to proxy_fd, this is because percent_decode_in_place() is called after the copy is created. This breaks reverse proxying all URIs containing percent encoded spaces, e.g. - because a decoded URI will be printed out to proxy_fd instead of the original. The fix keeps the logic in place to canonicalize the uri first, before reverse proxying (one could argue that the uri should be proxied completely unaltered, except for the prefix rewrite). function old new delta handle_incoming_and_exit 2752 2792 +40 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/httpd.c32
1 files changed, 22 insertions, 10 deletions
diff --git a/networking/httpd.c b/networking/httpd.c
index c486197..bc0e386 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -1817,7 +1817,7 @@ static NOINLINE void send_file_and_exit(const char *url, int what)
log_and_exit();
}
-static void send_HTTP_FORBIDDEN_and_exit_if_denied_ip(void)
+static void if_ip_denied_send_HTTP_FORBIDDEN_and_exit(void)
{
Htaccess_IP *cur;
@@ -2195,6 +2195,24 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
send_headers_and_exit(HTTP_NOT_FOUND);
}
+#if ENABLE_FEATURE_HTTPD_PROXY
+ proxy_entry = find_proxy_entry(urlcopy);
+ if (proxy_entry)
+ header_buf = header_ptr = xmalloc(IOBUF_SIZE);
+ else
+#endif
+ {
+ /* (If not proxying,) decode URL escape sequences */
+ tptr = percent_decode_in_place(urlcopy, /*strict:*/ 1);
+ if (tptr == NULL)
+ send_headers_and_exit(HTTP_BAD_REQUEST);
+ if (tptr == urlcopy + 1) {
+ /* '/' or NUL is encoded */
+ send_headers_and_exit(HTTP_NOT_FOUND);
+ }
+//should path canonicalization also be conditional on not proxying?
+ }
+
/* Canonicalize path */
/* Algorithm stolen from libbb bb_simplify_path(),
* but don't strdup, retain trailing slash, protect root */
@@ -2224,7 +2242,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
}
}
*++urlp = *tptr;
- if (*urlp == '\0')
+ if (*tptr == '\0')
break;
next_char:
tptr++;
@@ -2242,24 +2260,18 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
bb_error_msg("url:%s", urlcopy);
tptr = urlcopy;
- send_HTTP_FORBIDDEN_and_exit_if_denied_ip();
+ if_ip_denied_send_HTTP_FORBIDDEN_and_exit();
while ((tptr = strchr(tptr + 1, '/')) != NULL) {
/* have path1/path2 */
*tptr = '\0';
if (is_directory(urlcopy + 1, /*followlinks:*/ 1)) {
/* may have subdir config */
parse_conf(urlcopy + 1, SUBDIR_PARSE);
- send_HTTP_FORBIDDEN_and_exit_if_denied_ip();
+ if_ip_denied_send_HTTP_FORBIDDEN_and_exit();
}
*tptr = '/';
}
-#if ENABLE_FEATURE_HTTPD_PROXY
- proxy_entry = find_proxy_entry(urlcopy);
- if (proxy_entry)
- header_buf = header_ptr = xmalloc(IOBUF_SIZE);
-#endif
-
if (http_major_version >= '0') {
/* Request was with "... HTTP/nXXX", and n >= 0 */