httpd: move proxy check before URL duplication and request type check
No binary (build failed)
—
(log yok)
| @@ -2190,6 +2190,9 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |
| CGI_INTERPRETER, | |
| } cgi_type = CGI_NONE; | |
| #endif | |
| + | #if ENABLE_FEATURE_HTTPD_PROXY |
| + | Htaccess_Proxy *proxy_entry; |
| + | #endif |
| #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | |
| smallint authorized = -1; | |
| #endif | |
| @@ -2231,13 +2234,57 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |
| if (!get_line()) /* EOF or error or empty line */ | |
| send_headers_and_exit(HTTP_BAD_REQUEST); | |
| - | /* Determine type of request (GET/POST/...) */ |
| + | /* Find URL */ |
| // rfc2616: method and URI is separated by exactly one space | |
| //urlp = strpbrk(iobuf, " \t"); - no, tab isn't allowed | |
| urlp = strchr(iobuf, ' '); | |
| if (urlp == NULL) | |
| send_headers_and_exit(HTTP_BAD_REQUEST); | |
| *urlp++ = '\0'; | |
| + | //urlp = skip_whitespace(urlp); - should not be necessary |
| + | if (urlp[0] != '/') |
| + | send_headers_and_exit(HTTP_BAD_REQUEST); |
| + | /* Find end of URL */ |
| + | HTTP_slash = strchr(urlp, ' '); |
| + | /* Is it " HTTP/"? */ |
| + | if (!HTTP_slash || strncmp(HTTP_slash + 1, HTTP_200, 5) != 0) |
| + | send_headers_and_exit(HTTP_BAD_REQUEST); |
| + | *HTTP_slash++ = '\0'; |
| + | |
| + | #if ENABLE_FEATURE_HTTPD_PROXY |
| + | proxy_entry = find_proxy_entry(urlp); |
| + | if (proxy_entry) { |
| + | int proxy_fd; |
| + | len_and_sockaddr *lsa; |
| + | |
| + | if (verbose > 1) |
| + | bb_error_msg("proxy:%s", urlp); |
| + | lsa = host2sockaddr(proxy_entry->host_port, 80); |
| + | if (!lsa) |
| + | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); |
| + | proxy_fd = socket(lsa->u.sa.sa_family, SOCK_STREAM, 0); |
| + | if (proxy_fd < 0) |
| + | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); |
| + | if (connect(proxy_fd, &lsa->u.sa, lsa->len) < 0) |
| + | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); |
| + | /* Disable peer header reading timeout */ |
| + | alarm(0); |
| + | /* Config directive was of the form: |
| + | * P:/url:[http://]hostname[:port]/new/path |
| + | * When /urlSFX is requested, reverse proxy it |
| + | * to http://hostname[:port]/new/pathSFX |
| + | */ |
| + | fdprintf(proxy_fd, "%s %s%s %s\r\n", |
| + | iobuf, /* "GET" / "POST" / etc */ |
| + | proxy_entry->url_to, /* "/new/path" */ |
| + | urlp + strlen(proxy_entry->url_from), /* "SFX" */ |
| + | HTTP_slash /* "HTTP/xyz" */ |
| + | ); |
| + | cgi_io_loop_and_exit(proxy_fd, proxy_fd, /*max POST length:*/ INT_MAX); |
| + | } |
| + | #endif |
| + | |
| + | /* Determine type of request (GET/POST/...) */ |
| #if ENABLE_FEATURE_HTTPD_CGI | |
| prequest = request_GET; | |
| if (strcasecmp(iobuf, prequest) == 0) | |
| @@ -2248,7 +2295,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |
| prequest = request_POST; | |
| if (strcasecmp(iobuf, prequest) == 0) | |
| goto found; | |
| - | /* For CGI, allow other requests too (DELETE, PUT, OPTIONS, etc) */ |
| + | /* For CGI, allow DELETE, PUT, OPTIONS, etc too */ |
| prequest = alloca(16); | |
| safe_strncpy((char*)prequest, iobuf, 16); | |
| found: | |
| @@ -2256,60 +2303,11 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |
| if (strcasecmp(iobuf, "GET") != 0) | |
| send_headers_and_exit(HTTP_NOT_IMPLEMENTED); | |
| #endif | |
| - | // rfc2616: method and URI is separated by exactly one space |
| - | //urlp = skip_whitespace(urlp); - should not be necessary |
| - | if (urlp[0] != '/') |
| - | send_headers_and_exit(HTTP_BAD_REQUEST); |
| - | |
| - | /* Find end of URL */ |
| - | HTTP_slash = strchr(urlp, ' '); |
| - | /* Is it " HTTP/"? */ |
| - | if (!HTTP_slash || strncmp(HTTP_slash + 1, HTTP_200, 5) != 0) |
| - | send_headers_and_exit(HTTP_BAD_REQUEST); |
| - | *HTTP_slash++ = '\0'; |
| - | |
| - | /* Copy URL from after "GET "/"POST " to stack-allocated char[] */ |
| + | /* Copy URL to stack-allocated char[] */ |
| urlcopy = alloca((HTTP_slash - urlp) + 2 + strlen(index_page)); | |
| - | /*if (urlcopy == NULL) |
| - | * send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);*/ |
| strcpy(urlcopy, urlp); | |
| /* NB: urlcopy ptr is never changed after this */ | |
| - | #if ENABLE_FEATURE_HTTPD_PROXY |
| - | { |
| - | int proxy_fd; |
| - | len_and_sockaddr *lsa; |
| - | Htaccess_Proxy *proxy_entry = find_proxy_entry(urlcopy); |
| - | |
| - | if (proxy_entry) { |
| - | if (verbose > 1) |
| - | bb_error_msg("proxy:%s", urlcopy); |
| - | lsa = host2sockaddr(proxy_entry->host_port, 80); |
| - | if (!lsa) |
| - | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); |
| - | proxy_fd = socket(lsa->u.sa.sa_family, SOCK_STREAM, 0); |
| - | if (proxy_fd < 0) |
| - | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); |
| - | if (connect(proxy_fd, &lsa->u.sa, lsa->len) < 0) |
| - | send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); |
| - | /* Disable peer header reading timeout */ |
| - | alarm(0); |
| - | /* Config directive was of the form: |
| - | * P:/url:[http://]hostname[:port]/new/path |
| - | * When /urlSFX is requested, reverse proxy it |
| - | * to http://hostname[:port]/new/pathSFX |
| - | */ |
| - | fdprintf(proxy_fd, "%s %s%s %s\r\n", |
| - | iobuf, /* "GET" / "POST" / etc */ |
| - | proxy_entry->url_to, /* "/new/path" */ |
| - | urlcopy + strlen(proxy_entry->url_from), /* "SFX" */ |
| - | HTTP_slash /* "HTTP/xyz" */ |
| - | ); |
| - | cgi_io_loop_and_exit(proxy_fd, proxy_fd, /*max POST length:*/ INT_MAX); |
| - | } |
| - | } |
| - | #endif |
| - | |
| /* Extract url args if present */ | |
| g_query = strchr(urlcopy, '?'); | |
| if (g_query) | |
| @@ -2571,9 +2569,8 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |
| send_headers_and_exit(HTTP_UNAUTHORIZED); | |
| #endif | |
| - | if (found_moved_temporarily) { |
| + | if (found_moved_temporarily) |
| send_headers_and_exit(HTTP_MOVED_TEMPORARILY); | |
| - | } |
| tptr = urlcopy + 1; /* skip first '/' */ | |
| @@ -2587,9 +2584,8 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |
| } | |
| #endif | |
| - | if (urlp[-1] == '/') { |
| + | if (urlp[-1] == '/') |
| strcpy(urlp, index_page); | |
| - | } |
| #if ENABLE_FEATURE_HTTPD_CGI | |
| if (prequest != request_GET && prequest != request_HEAD) { | |