diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2021-05-04 19:51:39 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-05-04 19:52:41 +0200 |
| commit | ff4d898fe6a0f082baff929087df7eb38d4e890c (patch) | |
| tree | 760ced4e69b3a63dda413c7a66dbc6f0789213d9 | |
| parent | 36e932abdfd79f55fdded4142d10319ba843839e (diff) | |
| download | busybox-w32-ff4d898fe6a0f082baff929087df7eb38d4e890c.tar.gz busybox-w32-ff4d898fe6a0f082baff929087df7eb38d4e890c.tar.bz2 busybox-w32-ff4d898fe6a0f082baff929087df7eb38d4e890c.zip | |
httpd: move proxy check before URL duplication and request type check
This makes proxy work for any type of requests.
function old new delta
handle_incoming_and_exit 2240 2172 -68
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
| -rw-r--r-- | networking/httpd.c | 108 |
1 files changed, 52 insertions, 56 deletions
diff --git a/networking/httpd.c b/networking/httpd.c index 09e19dc29..951213ec5 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
| @@ -2190,6 +2190,9 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
| 2190 | CGI_INTERPRETER, | 2190 | CGI_INTERPRETER, |
| 2191 | } cgi_type = CGI_NONE; | 2191 | } cgi_type = CGI_NONE; |
| 2192 | #endif | 2192 | #endif |
| 2193 | #if ENABLE_FEATURE_HTTPD_PROXY | ||
| 2194 | Htaccess_Proxy *proxy_entry; | ||
| 2195 | #endif | ||
| 2193 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 2196 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
| 2194 | smallint authorized = -1; | 2197 | smallint authorized = -1; |
| 2195 | #endif | 2198 | #endif |
| @@ -2231,13 +2234,57 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
| 2231 | if (!get_line()) /* EOF or error or empty line */ | 2234 | if (!get_line()) /* EOF or error or empty line */ |
| 2232 | send_headers_and_exit(HTTP_BAD_REQUEST); | 2235 | send_headers_and_exit(HTTP_BAD_REQUEST); |
| 2233 | 2236 | ||
| 2234 | /* Determine type of request (GET/POST/...) */ | 2237 | /* Find URL */ |
| 2235 | // rfc2616: method and URI is separated by exactly one space | 2238 | // rfc2616: method and URI is separated by exactly one space |
| 2236 | //urlp = strpbrk(iobuf, " \t"); - no, tab isn't allowed | 2239 | //urlp = strpbrk(iobuf, " \t"); - no, tab isn't allowed |
| 2237 | urlp = strchr(iobuf, ' '); | 2240 | urlp = strchr(iobuf, ' '); |
| 2238 | if (urlp == NULL) | 2241 | if (urlp == NULL) |
| 2239 | send_headers_and_exit(HTTP_BAD_REQUEST); | 2242 | send_headers_and_exit(HTTP_BAD_REQUEST); |
| 2240 | *urlp++ = '\0'; | 2243 | *urlp++ = '\0'; |
| 2244 | //urlp = skip_whitespace(urlp); - should not be necessary | ||
| 2245 | if (urlp[0] != '/') | ||
| 2246 | send_headers_and_exit(HTTP_BAD_REQUEST); | ||
| 2247 | /* Find end of URL */ | ||
| 2248 | HTTP_slash = strchr(urlp, ' '); | ||
| 2249 | /* Is it " HTTP/"? */ | ||
| 2250 | if (!HTTP_slash || strncmp(HTTP_slash + 1, HTTP_200, 5) != 0) | ||
| 2251 | send_headers_and_exit(HTTP_BAD_REQUEST); | ||
| 2252 | *HTTP_slash++ = '\0'; | ||
| 2253 | |||
| 2254 | #if ENABLE_FEATURE_HTTPD_PROXY | ||
| 2255 | proxy_entry = find_proxy_entry(urlp); | ||
| 2256 | if (proxy_entry) { | ||
| 2257 | int proxy_fd; | ||
| 2258 | len_and_sockaddr *lsa; | ||
| 2259 | |||
| 2260 | if (verbose > 1) | ||
| 2261 | bb_error_msg("proxy:%s", urlp); | ||
| 2262 | lsa = host2sockaddr(proxy_entry->host_port, 80); | ||
| 2263 | if (!lsa) | ||
| 2264 | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); | ||
| 2265 | proxy_fd = socket(lsa->u.sa.sa_family, SOCK_STREAM, 0); | ||
| 2266 | if (proxy_fd < 0) | ||
| 2267 | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); | ||
| 2268 | if (connect(proxy_fd, &lsa->u.sa, lsa->len) < 0) | ||
| 2269 | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); | ||
| 2270 | /* Disable peer header reading timeout */ | ||
| 2271 | alarm(0); | ||
| 2272 | /* Config directive was of the form: | ||
| 2273 | * P:/url:[http://]hostname[:port]/new/path | ||
| 2274 | * When /urlSFX is requested, reverse proxy it | ||
| 2275 | * to http://hostname[:port]/new/pathSFX | ||
| 2276 | */ | ||
| 2277 | fdprintf(proxy_fd, "%s %s%s %s\r\n", | ||
| 2278 | iobuf, /* "GET" / "POST" / etc */ | ||
| 2279 | proxy_entry->url_to, /* "/new/path" */ | ||
| 2280 | urlp + strlen(proxy_entry->url_from), /* "SFX" */ | ||
| 2281 | HTTP_slash /* "HTTP/xyz" */ | ||
| 2282 | ); | ||
| 2283 | cgi_io_loop_and_exit(proxy_fd, proxy_fd, /*max POST length:*/ INT_MAX); | ||
| 2284 | } | ||
| 2285 | #endif | ||
| 2286 | |||
| 2287 | /* Determine type of request (GET/POST/...) */ | ||
| 2241 | #if ENABLE_FEATURE_HTTPD_CGI | 2288 | #if ENABLE_FEATURE_HTTPD_CGI |
| 2242 | prequest = request_GET; | 2289 | prequest = request_GET; |
| 2243 | if (strcasecmp(iobuf, prequest) == 0) | 2290 | if (strcasecmp(iobuf, prequest) == 0) |
| @@ -2248,7 +2295,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
| 2248 | prequest = request_POST; | 2295 | prequest = request_POST; |
| 2249 | if (strcasecmp(iobuf, prequest) == 0) | 2296 | if (strcasecmp(iobuf, prequest) == 0) |
| 2250 | goto found; | 2297 | goto found; |
| 2251 | /* For CGI, allow other requests too (DELETE, PUT, OPTIONS, etc) */ | 2298 | /* For CGI, allow DELETE, PUT, OPTIONS, etc too */ |
| 2252 | prequest = alloca(16); | 2299 | prequest = alloca(16); |
| 2253 | safe_strncpy((char*)prequest, iobuf, 16); | 2300 | safe_strncpy((char*)prequest, iobuf, 16); |
| 2254 | found: | 2301 | found: |
| @@ -2256,60 +2303,11 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
| 2256 | if (strcasecmp(iobuf, "GET") != 0) | 2303 | if (strcasecmp(iobuf, "GET") != 0) |
| 2257 | send_headers_and_exit(HTTP_NOT_IMPLEMENTED); | 2304 | send_headers_and_exit(HTTP_NOT_IMPLEMENTED); |
| 2258 | #endif | 2305 | #endif |
| 2259 | // rfc2616: method and URI is separated by exactly one space | 2306 | /* Copy URL to stack-allocated char[] */ |
| 2260 | //urlp = skip_whitespace(urlp); - should not be necessary | ||
| 2261 | if (urlp[0] != '/') | ||
| 2262 | send_headers_and_exit(HTTP_BAD_REQUEST); | ||
| 2263 | |||
| 2264 | /* Find end of URL */ | ||
| 2265 | HTTP_slash = strchr(urlp, ' '); | ||
| 2266 | /* Is it " HTTP/"? */ | ||
| 2267 | if (!HTTP_slash || strncmp(HTTP_slash + 1, HTTP_200, 5) != 0) | ||
| 2268 | send_headers_and_exit(HTTP_BAD_REQUEST); | ||
| 2269 | *HTTP_slash++ = '\0'; | ||
| 2270 | |||
| 2271 | /* Copy URL from after "GET "/"POST " to stack-allocated char[] */ | ||
| 2272 | urlcopy = alloca((HTTP_slash - urlp) + 2 + strlen(index_page)); | 2307 | urlcopy = alloca((HTTP_slash - urlp) + 2 + strlen(index_page)); |
| 2273 | /*if (urlcopy == NULL) | ||
| 2274 | * send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);*/ | ||
| 2275 | strcpy(urlcopy, urlp); | 2308 | strcpy(urlcopy, urlp); |
| 2276 | /* NB: urlcopy ptr is never changed after this */ | 2309 | /* NB: urlcopy ptr is never changed after this */ |
| 2277 | 2310 | ||
| 2278 | #if ENABLE_FEATURE_HTTPD_PROXY | ||
| 2279 | { | ||
| 2280 | int proxy_fd; | ||
| 2281 | len_and_sockaddr *lsa; | ||
| 2282 | Htaccess_Proxy *proxy_entry = find_proxy_entry(urlcopy); | ||
| 2283 | |||
| 2284 | if (proxy_entry) { | ||
| 2285 | if (verbose > 1) | ||
| 2286 | bb_error_msg("proxy:%s", urlcopy); | ||
| 2287 | lsa = host2sockaddr(proxy_entry->host_port, 80); | ||
| 2288 | if (!lsa) | ||
| 2289 | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); | ||
| 2290 | proxy_fd = socket(lsa->u.sa.sa_family, SOCK_STREAM, 0); | ||
| 2291 | if (proxy_fd < 0) | ||
| 2292 | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); | ||
| 2293 | if (connect(proxy_fd, &lsa->u.sa, lsa->len) < 0) | ||
| 2294 | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); | ||
| 2295 | /* Disable peer header reading timeout */ | ||
| 2296 | alarm(0); | ||
| 2297 | /* Config directive was of the form: | ||
| 2298 | * P:/url:[http://]hostname[:port]/new/path | ||
| 2299 | * When /urlSFX is requested, reverse proxy it | ||
| 2300 | * to http://hostname[:port]/new/pathSFX | ||
| 2301 | */ | ||
| 2302 | fdprintf(proxy_fd, "%s %s%s %s\r\n", | ||
| 2303 | iobuf, /* "GET" / "POST" / etc */ | ||
| 2304 | proxy_entry->url_to, /* "/new/path" */ | ||
| 2305 | urlcopy + strlen(proxy_entry->url_from), /* "SFX" */ | ||
| 2306 | HTTP_slash /* "HTTP/xyz" */ | ||
| 2307 | ); | ||
| 2308 | cgi_io_loop_and_exit(proxy_fd, proxy_fd, /*max POST length:*/ INT_MAX); | ||
| 2309 | } | ||
| 2310 | } | ||
| 2311 | #endif | ||
| 2312 | |||
| 2313 | /* Extract url args if present */ | 2311 | /* Extract url args if present */ |
| 2314 | g_query = strchr(urlcopy, '?'); | 2312 | g_query = strchr(urlcopy, '?'); |
| 2315 | if (g_query) | 2313 | if (g_query) |
| @@ -2571,9 +2569,8 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
| 2571 | send_headers_and_exit(HTTP_UNAUTHORIZED); | 2569 | send_headers_and_exit(HTTP_UNAUTHORIZED); |
| 2572 | #endif | 2570 | #endif |
| 2573 | 2571 | ||
| 2574 | if (found_moved_temporarily) { | 2572 | if (found_moved_temporarily) |
| 2575 | send_headers_and_exit(HTTP_MOVED_TEMPORARILY); | 2573 | send_headers_and_exit(HTTP_MOVED_TEMPORARILY); |
| 2576 | } | ||
| 2577 | 2574 | ||
| 2578 | tptr = urlcopy + 1; /* skip first '/' */ | 2575 | tptr = urlcopy + 1; /* skip first '/' */ |
| 2579 | 2576 | ||
| @@ -2587,9 +2584,8 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
| 2587 | } | 2584 | } |
| 2588 | #endif | 2585 | #endif |
| 2589 | 2586 | ||
| 2590 | if (urlp[-1] == '/') { | 2587 | if (urlp[-1] == '/') |
| 2591 | strcpy(urlp, index_page); | 2588 | strcpy(urlp, index_page); |
| 2592 | } | ||
| 2593 | 2589 | ||
| 2594 | #if ENABLE_FEATURE_HTTPD_CGI | 2590 | #if ENABLE_FEATURE_HTTPD_CGI |
| 2595 | if (prequest != request_GET && prequest != request_HEAD) { | 2591 | if (prequest != request_GET && prequest != request_HEAD) { |
