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) { |