diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2019-04-16 12:45:26 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2019-04-16 12:45:26 +0200 |
commit | c69f648457a552518f92c5a70689bd106f03ec13 (patch) | |
tree | 3ce1ee3bcfb0198fbd1bc442ea0c2b90656e37c9 | |
parent | cf695976c7cf169495e749c8a907e47c269e0068 (diff) | |
download | busybox-w32-c69f648457a552518f92c5a70689bd106f03ec13.tar.gz busybox-w32-c69f648457a552518f92c5a70689bd106f03ec13.tar.bz2 busybox-w32-c69f648457a552518f92c5a70689bd106f03ec13.zip |
httpd: do not decode URL and headers if proxying - send all verbatim
function old new delta
handle_incoming_and_exit 2566 2385 -181
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | networking/httpd.c | 114 |
1 files changed, 46 insertions, 68 deletions
diff --git a/networking/httpd.c b/networking/httpd.c index 8921c02a3..205c434bf 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -2085,12 +2085,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2085 | smallint authorized = -1; | 2085 | smallint authorized = -1; |
2086 | #endif | 2086 | #endif |
2087 | char http_major_version; | 2087 | char http_major_version; |
2088 | #if ENABLE_FEATURE_HTTPD_PROXY | 2088 | char *HTTP_slash; |
2089 | char http_minor_version; | ||
2090 | char *header_buf = header_buf; /* for gcc */ | ||
2091 | char *header_ptr = header_ptr; | ||
2092 | Htaccess_Proxy *proxy_entry; | ||
2093 | #endif | ||
2094 | 2089 | ||
2095 | /* Allocation of iobuf is postponed until now | 2090 | /* Allocation of iobuf is postponed until now |
2096 | * (IOW, server process doesn't need to waste 8k) */ | 2091 | * (IOW, server process doesn't need to waste 8k) */ |
@@ -2152,18 +2147,18 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2152 | send_headers_and_exit(HTTP_BAD_REQUEST); | 2147 | send_headers_and_exit(HTTP_BAD_REQUEST); |
2153 | 2148 | ||
2154 | /* Find end of URL and parse HTTP version, if any */ | 2149 | /* Find end of URL and parse HTTP version, if any */ |
2155 | http_major_version = '0'; | 2150 | //TODO: mayybe just reject all queries which have no " HTTP/xyz" suffix? |
2156 | IF_FEATURE_HTTPD_PROXY(http_minor_version = '0';) | 2151 | //Then 'http_major_version' can be deleted |
2157 | tptr = strchrnul(urlp, ' '); | 2152 | http_major_version = ('0' - 1); /* "less than 0th" version */ |
2153 | HTTP_slash = strchrnul(urlp, ' '); | ||
2158 | /* Is it " HTTP/"? */ | 2154 | /* Is it " HTTP/"? */ |
2159 | if (tptr[0] && strncmp(tptr + 1, HTTP_200, 5) == 0) { | 2155 | if (HTTP_slash[0] && strncmp(HTTP_slash + 1, HTTP_200, 5) == 0) { |
2160 | http_major_version = tptr[6]; | 2156 | http_major_version = HTTP_slash[6]; |
2161 | IF_FEATURE_HTTPD_PROXY(http_minor_version = tptr[8];) | 2157 | *HTTP_slash++ = '\0'; |
2162 | } | 2158 | } |
2163 | *tptr = '\0'; | ||
2164 | 2159 | ||
2165 | /* Copy URL from after "GET "/"POST " to stack-allocated char[] */ | 2160 | /* Copy URL from after "GET "/"POST " to stack-allocated char[] */ |
2166 | urlcopy = alloca((tptr - urlp) + 2 + strlen(index_page)); | 2161 | urlcopy = alloca((HTTP_slash - urlp) + 2 + strlen(index_page)); |
2167 | /*if (urlcopy == NULL) | 2162 | /*if (urlcopy == NULL) |
2168 | * send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);*/ | 2163 | * send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);*/ |
2169 | strcpy(urlcopy, urlp); | 2164 | strcpy(urlcopy, urlp); |
@@ -2178,23 +2173,45 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2178 | } | 2173 | } |
2179 | 2174 | ||
2180 | #if ENABLE_FEATURE_HTTPD_PROXY | 2175 | #if ENABLE_FEATURE_HTTPD_PROXY |
2181 | proxy_entry = find_proxy_entry(urlcopy); | ||
2182 | if (proxy_entry) | ||
2183 | header_buf = header_ptr = xmalloc(MAX_HTTP_HEADERS_SIZE + 2); | ||
2184 | //TODO: why we don't just start pumping data to proxy here, | ||
2185 | //without decoding URL, saving headers and such??? | ||
2186 | else | ||
2187 | #endif | ||
2188 | { | 2176 | { |
2189 | /* (If not proxying,) decode URL escape sequences */ | 2177 | int proxy_fd; |
2190 | tptr = percent_decode_in_place(urlcopy, /*strict:*/ 1); | 2178 | len_and_sockaddr *lsa; |
2191 | if (tptr == NULL) | 2179 | Htaccess_Proxy *proxy_entry = find_proxy_entry(urlcopy); |
2192 | send_headers_and_exit(HTTP_BAD_REQUEST); | 2180 | |
2193 | if (tptr == urlcopy + 1) { | 2181 | if (proxy_entry) { |
2194 | /* '/' or NUL is encoded */ | 2182 | lsa = host2sockaddr(proxy_entry->host_port, 80); |
2195 | send_headers_and_exit(HTTP_NOT_FOUND); | 2183 | if (!lsa) |
2184 | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); | ||
2185 | proxy_fd = socket(lsa->u.sa.sa_family, SOCK_STREAM, 0); | ||
2186 | if (proxy_fd < 0) | ||
2187 | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); | ||
2188 | if (connect(proxy_fd, &lsa->u.sa, lsa->len) < 0) | ||
2189 | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); | ||
2190 | /* Config directive was of the form: | ||
2191 | * P:/url:[http://]hostname[:port]/new/path | ||
2192 | * When /urlSFX is requested, reverse proxy it | ||
2193 | * to http://hostname[:port]/new/pathSFX | ||
2194 | */ | ||
2195 | fdprintf(proxy_fd, "%s %s%s%s%s %s\r\n", | ||
2196 | prequest, /* "GET" or "POST" */ | ||
2197 | proxy_entry->url_to, /* "/new/path" */ | ||
2198 | urlcopy + strlen(proxy_entry->url_from), /* "SFX" */ | ||
2199 | (g_query ? "?" : ""), /* "?" (maybe) */ | ||
2200 | (g_query ? g_query : ""), /* query string (maybe) */ | ||
2201 | HTTP_slash /* HTTP/xyz" or "" */ | ||
2202 | ); | ||
2203 | cgi_io_loop_and_exit(proxy_fd, proxy_fd, /*max POST length:*/ INT_MAX); | ||
2196 | } | 2204 | } |
2197 | //should path canonicalization also be conditional on not proxying? | 2205 | } |
2206 | #endif | ||
2207 | |||
2208 | /* Decode URL escape sequences */ | ||
2209 | tptr = percent_decode_in_place(urlcopy, /*strict:*/ 1); | ||
2210 | if (tptr == NULL) | ||
2211 | send_headers_and_exit(HTTP_BAD_REQUEST); | ||
2212 | if (tptr == urlcopy + 1) { | ||
2213 | /* '/' or NUL is encoded */ | ||
2214 | send_headers_and_exit(HTTP_NOT_FOUND); | ||
2198 | } | 2215 | } |
2199 | 2216 | ||
2200 | /* Canonicalize path */ | 2217 | /* Canonicalize path */ |
@@ -2321,16 +2338,6 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2321 | send_headers_and_exit(HTTP_ENTITY_TOO_LARGE); | 2338 | send_headers_and_exit(HTTP_ENTITY_TOO_LARGE); |
2322 | if (DEBUG) | 2339 | if (DEBUG) |
2323 | bb_error_msg("header: '%s'", iobuf); | 2340 | bb_error_msg("header: '%s'", iobuf); |
2324 | #if ENABLE_FEATURE_HTTPD_PROXY | ||
2325 | if (proxy_entry) { | ||
2326 | /* protected from overflow by header_len check above */ | ||
2327 | memcpy(header_ptr, iobuf, iobuf_len); | ||
2328 | header_ptr += iobuf_len; | ||
2329 | header_ptr[0] = '\r'; | ||
2330 | header_ptr[1] = '\n'; | ||
2331 | header_ptr += 2; | ||
2332 | } | ||
2333 | #endif | ||
2334 | 2341 | ||
2335 | #if ENABLE_FEATURE_HTTPD_CGI || ENABLE_FEATURE_HTTPD_PROXY | 2342 | #if ENABLE_FEATURE_HTTPD_CGI || ENABLE_FEATURE_HTTPD_PROXY |
2336 | /* Try and do our best to parse more lines */ | 2343 | /* Try and do our best to parse more lines */ |
@@ -2457,35 +2464,6 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2457 | send_headers_and_exit(HTTP_MOVED_TEMPORARILY); | 2464 | send_headers_and_exit(HTTP_MOVED_TEMPORARILY); |
2458 | } | 2465 | } |
2459 | 2466 | ||
2460 | #if ENABLE_FEATURE_HTTPD_PROXY | ||
2461 | if (proxy_entry) { | ||
2462 | int proxy_fd; | ||
2463 | len_and_sockaddr *lsa; | ||
2464 | |||
2465 | lsa = host2sockaddr(proxy_entry->host_port, 80); | ||
2466 | if (lsa == NULL) | ||
2467 | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); | ||
2468 | proxy_fd = socket(lsa->u.sa.sa_family, SOCK_STREAM, 0); | ||
2469 | if (proxy_fd < 0) | ||
2470 | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); | ||
2471 | if (connect(proxy_fd, &lsa->u.sa, lsa->len) < 0) | ||
2472 | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); | ||
2473 | fdprintf(proxy_fd, "%s %s%s%s%s HTTP/%c.%c\r\n", | ||
2474 | prequest, /* GET or POST */ | ||
2475 | proxy_entry->url_to, /* url part 1 */ | ||
2476 | urlcopy + strlen(proxy_entry->url_from), /* url part 2 */ | ||
2477 | (g_query ? "?" : ""), /* "?" (maybe) */ | ||
2478 | (g_query ? g_query : ""), /* query string (maybe) */ | ||
2479 | http_major_version, http_minor_version); | ||
2480 | header_ptr[0] = '\r'; | ||
2481 | header_ptr[1] = '\n'; | ||
2482 | header_ptr += 2; | ||
2483 | full_write(proxy_fd, header_buf, header_ptr - header_buf); | ||
2484 | free(header_buf); /* on the order of 8k, free it */ | ||
2485 | cgi_io_loop_and_exit(proxy_fd, proxy_fd, length); | ||
2486 | } | ||
2487 | #endif | ||
2488 | |||
2489 | tptr = urlcopy + 1; /* skip first '/' */ | 2467 | tptr = urlcopy + 1; /* skip first '/' */ |
2490 | 2468 | ||
2491 | #if ENABLE_FEATURE_HTTPD_CGI | 2469 | #if ENABLE_FEATURE_HTTPD_CGI |