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>
This commit is contained in:
Denys Vlasenko 2021-05-04 19:51:39 +02:00
parent 36e932abdf
commit ff4d898fe6

View File

@ -2190,6 +2190,9 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
CGI_INTERPRETER, CGI_INTERPRETER,
} cgi_type = CGI_NONE; } cgi_type = CGI_NONE;
#endif #endif
#if ENABLE_FEATURE_HTTPD_PROXY
Htaccess_Proxy *proxy_entry;
#endif
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH #if ENABLE_FEATURE_HTTPD_BASIC_AUTH
smallint authorized = -1; smallint authorized = -1;
#endif #endif
@ -2231,36 +2234,16 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
if (!get_line()) /* EOF or error or empty line */ if (!get_line()) /* EOF or error or empty line */
send_headers_and_exit(HTTP_BAD_REQUEST); 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 // rfc2616: method and URI is separated by exactly one space
//urlp = strpbrk(iobuf, " \t"); - no, tab isn't allowed //urlp = strpbrk(iobuf, " \t"); - no, tab isn't allowed
urlp = strchr(iobuf, ' '); urlp = strchr(iobuf, ' ');
if (urlp == NULL) if (urlp == NULL)
send_headers_and_exit(HTTP_BAD_REQUEST); send_headers_and_exit(HTTP_BAD_REQUEST);
*urlp++ = '\0'; *urlp++ = '\0';
#if ENABLE_FEATURE_HTTPD_CGI
prequest = request_GET;
if (strcasecmp(iobuf, prequest) == 0)
goto found;
prequest = request_HEAD;
if (strcasecmp(iobuf, prequest) == 0)
goto found;
prequest = request_POST;
if (strcasecmp(iobuf, prequest) == 0)
goto found;
/* For CGI, allow other requests too (DELETE, PUT, OPTIONS, etc) */
prequest = alloca(16);
safe_strncpy((char*)prequest, iobuf, 16);
found:
#else
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 //urlp = skip_whitespace(urlp); - should not be necessary
if (urlp[0] != '/') if (urlp[0] != '/')
send_headers_and_exit(HTTP_BAD_REQUEST); send_headers_and_exit(HTTP_BAD_REQUEST);
/* Find end of URL */ /* Find end of URL */
HTTP_slash = strchr(urlp, ' '); HTTP_slash = strchr(urlp, ' ');
/* Is it " HTTP/"? */ /* Is it " HTTP/"? */
@ -2268,22 +2251,14 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
send_headers_and_exit(HTTP_BAD_REQUEST); send_headers_and_exit(HTTP_BAD_REQUEST);
*HTTP_slash++ = '\0'; *HTTP_slash++ = '\0';
/* Copy URL from after "GET "/"POST " 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 #if ENABLE_FEATURE_HTTPD_PROXY
{ proxy_entry = find_proxy_entry(urlp);
if (proxy_entry) {
int proxy_fd; int proxy_fd;
len_and_sockaddr *lsa; len_and_sockaddr *lsa;
Htaccess_Proxy *proxy_entry = find_proxy_entry(urlcopy);
if (proxy_entry) {
if (verbose > 1) if (verbose > 1)
bb_error_msg("proxy:%s", urlcopy); bb_error_msg("proxy:%s", urlp);
lsa = host2sockaddr(proxy_entry->host_port, 80); lsa = host2sockaddr(proxy_entry->host_port, 80);
if (!lsa) if (!lsa)
send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR); send_headers_and_exit(HTTP_INTERNAL_SERVER_ERROR);
@ -2302,14 +2277,37 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
fdprintf(proxy_fd, "%s %s%s %s\r\n", fdprintf(proxy_fd, "%s %s%s %s\r\n",
iobuf, /* "GET" / "POST" / etc */ iobuf, /* "GET" / "POST" / etc */
proxy_entry->url_to, /* "/new/path" */ proxy_entry->url_to, /* "/new/path" */
urlcopy + strlen(proxy_entry->url_from), /* "SFX" */ urlp + strlen(proxy_entry->url_from), /* "SFX" */
HTTP_slash /* "HTTP/xyz" */ HTTP_slash /* "HTTP/xyz" */
); );
cgi_io_loop_and_exit(proxy_fd, proxy_fd, /*max POST length:*/ INT_MAX); cgi_io_loop_and_exit(proxy_fd, proxy_fd, /*max POST length:*/ INT_MAX);
} }
}
#endif #endif
/* Determine type of request (GET/POST/...) */
#if ENABLE_FEATURE_HTTPD_CGI
prequest = request_GET;
if (strcasecmp(iobuf, prequest) == 0)
goto found;
prequest = request_HEAD;
if (strcasecmp(iobuf, prequest) == 0)
goto found;
prequest = request_POST;
if (strcasecmp(iobuf, prequest) == 0)
goto found;
/* For CGI, allow DELETE, PUT, OPTIONS, etc too */
prequest = alloca(16);
safe_strncpy((char*)prequest, iobuf, 16);
found:
#else
if (strcasecmp(iobuf, "GET") != 0)
send_headers_and_exit(HTTP_NOT_IMPLEMENTED);
#endif
/* Copy URL to stack-allocated char[] */
urlcopy = alloca((HTTP_slash - urlp) + 2 + strlen(index_page));
strcpy(urlcopy, urlp);
/* NB: urlcopy ptr is never changed after this */
/* Extract url args if present */ /* Extract url args if present */
g_query = strchr(urlcopy, '?'); g_query = strchr(urlcopy, '?');
if (g_query) if (g_query)
@ -2571,9 +2569,8 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
send_headers_and_exit(HTTP_UNAUTHORIZED); send_headers_and_exit(HTTP_UNAUTHORIZED);
#endif #endif
if (found_moved_temporarily) { if (found_moved_temporarily)
send_headers_and_exit(HTTP_MOVED_TEMPORARILY); send_headers_and_exit(HTTP_MOVED_TEMPORARILY);
}
tptr = urlcopy + 1; /* skip first '/' */ tptr = urlcopy + 1; /* skip first '/' */
@ -2587,9 +2584,8 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr)
} }
#endif #endif
if (urlp[-1] == '/') { if (urlp[-1] == '/')
strcpy(urlp, index_page); strcpy(urlp, index_page);
}
#if ENABLE_FEATURE_HTTPD_CGI #if ENABLE_FEATURE_HTTPD_CGI
if (prequest != request_GET && prequest != request_HEAD) { if (prequest != request_GET && prequest != request_HEAD) {