[git commit] httpd: move proxy check before URL duplication and request type check

Denys Vlasenko vda.linux at googlemail.com
Tue May 4 17:52:41 UTC 2021


commit: https://git.busybox.net/busybox/commit/?id=ff4d898fe6a0f082baff929087df7eb38d4e890c
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

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 at googlemail.com>
---
 networking/httpd.c | 108 ++++++++++++++++++++++++++---------------------------
 1 file 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)
 		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) {


More information about the busybox-cvs mailing list