From  fd92481223a0d213f1dc2f96745f495efcf33eca Mon Sep 17 00:00:00 2001
From: Ruediger Pluem <rpluem@apache.org>
Date: Fri, 31 Mar 2023 10:37:34 PM GMT+0800
Subject: [PATCH] mod_proxy:Check before forwarding that a nocanon path has not been
                           rewritten with spaces during processing

Conflict:NA
Reference:https://github.com/apache/httpd/commit/fd92481223a0d213f1dc2f96745f495efcf33eca

---
 modules/http2/mod_proxy_http2.c    | 31 +++++++++++++++++------------
 modules/proxy/mod_proxy_ajp.c      | 19 ++++++++++++------
 modules/proxy/mod_proxy_balancer.c | 19 ++++++++++++------
 modules/proxy/mod_proxy_fcgi.c     | 15 ++++++++++++--
 modules/proxy/mod_proxy_http.c     | 32 ++++++++++++++++++------------
 modules/proxy/mod_proxy_uwsgi.c    | 14 +++++++++++--
 modules/proxy/mod_proxy_wstunnel.c | 19 ++++++++++++------
 7 files changed, 101 insertions(+), 48 deletions(-)

diff --git a/modules/http2/mod_proxy_http2.c b/modules/http2/mod_proxy_http2.c
index 77e2641..957c7ba 100644
--- a/modules/http2/mod_proxy_http2.c
+++ b/modules/http2/mod_proxy_http2.c
@@ -164,26 +164,31 @@ static int proxy_http2_canon(request_rec *r, char *url)
 
             path = ap_proxy_canonenc_ex(r->pool, url, (int)strlen(url),
                                         enc_path, flags, r->proxyreq);
+            if (!path) {
+                return HTTP_BAD_REQUEST;
+            }
             search = r->args;
         }
-        if (search && *(ap_scan_vchar_obstext(search))) {
-            /*
-             * We have a raw control character or a ' ' in r->args.
-             * Correct encoding was missed.
-             */
-             ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10412)
-                           "To be forwarded query string contains control "
-                           "characters or spaces");
-             return HTTP_FORBIDDEN;
-        }
         break;
     case PROXYREQ_PROXY:
         path = url;
         break;
     }
-
-    if (path == NULL) {
-        return HTTP_BAD_REQUEST;
+    /*
+     * If we have a raw control character or a ' ' in nocanon path or
+     * r->args, correct encoding was missed.
+     */
+    if (path == url && *ap_scan_vchar_obstext(path)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10420)
+                      "To be forwarded path contains control "
+                      "characters or spaces");
+        return HTTP_FORBIDDEN;
+    }
+    if (search && *ap_scan_vchar_obstext(search)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10412)
+                      "To be forwarded query string contains control "
+                      "characters or spaces");
+        return HTTP_FORBIDDEN;
     }
 
     if (port != def_port) {
diff --git a/modules/proxy/mod_proxy_ajp.c b/modules/proxy/mod_proxy_ajp.c
index 747f928..4446c5e 100644
--- a/modules/proxy/mod_proxy_ajp.c
+++ b/modules/proxy/mod_proxy_ajp.c
@@ -75,20 +75,27 @@ static int proxy_ajp_canon(request_rec *r, char *url)
 
         path = ap_proxy_canonenc_ex(r->pool, url, strlen(url), enc_path, flags,
                                     r->proxyreq);
+        if (!path) {
+            return HTTP_BAD_REQUEST;
+        }
         search = r->args;
     }
+    /*
+     * If we have a raw control character or a ' ' in nocanon path or
+     * r->args, correct encoding was missed.
+     */
+    if (path == url && *ap_scan_vchar_obstext(path)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10418)
+                      "To be forwarded path contains control "
+                      "characters or spaces");
+        return HTTP_FORBIDDEN;
+    }
     if (search && *(ap_scan_vchar_obstext(search))) {
-        /*
-         * We have a raw control character or a ' ' in r->args.
-         * Correct encoding was missed.
-         */
          ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10406)
                        "To be forwarded query string contains control "
                        "characters or spaces");
          return HTTP_FORBIDDEN;
     }
-    if (path == NULL)
-        return HTTP_BAD_REQUEST;
 
     if (port != def_port)
          apr_snprintf(sport, sizeof(sport), ":%d", port);
diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c
index de31749..d175fcf 100644
--- a/modules/proxy/mod_proxy_balancer.c
+++ b/modules/proxy/mod_proxy_balancer.c
@@ -112,20 +112,27 @@ static int proxy_balancer_canon(request_rec *r, char *url)
 
         path = ap_proxy_canonenc_ex(r->pool, url, strlen(url), enc_path, flags,
                                     r->proxyreq);
+        if (!path) {
+            return HTTP_BAD_REQUEST;
+        }
         search = r->args;
     }
+    /*
+     * If we have a raw control character or a ' ' in nocanon path or
+     * r->args, correct encoding was missed.
+     */
+    if (path == url && *ap_scan_vchar_obstext(path)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10416)
+                      "To be forwarded path contains control "
+                      "characters or spaces");
+        return HTTP_FORBIDDEN;
+    }
     if (search && *(ap_scan_vchar_obstext(search))) {
-        /*
-         * We have a raw control character or a ' ' in r->args.
-         * Correct encoding was missed.
-         */
          ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10407)
                        "To be forwarded query string contains control "
                        "characters or spaces");
          return HTTP_FORBIDDEN;
     }
-    if (path == NULL)
-        return HTTP_BAD_REQUEST;
 
     r->filename = apr_pstrcat(r->pool, "proxy:" BALANCER_PREFIX, host,
             "/", path, (search) ? "?" : "", (search) ? search : "", NULL);
diff --git a/modules/proxy/mod_proxy_fcgi.c b/modules/proxy/mod_proxy_fcgi.c
index a422b4e..831bd15 100644
--- a/modules/proxy/mod_proxy_fcgi.c
+++ b/modules/proxy/mod_proxy_fcgi.c
@@ -102,9 +102,20 @@ static int proxy_fcgi_canon(request_rec *r, char *url)
 
         path = ap_proxy_canonenc_ex(r->pool, url, strlen(url), enc_path, flags,
                                     r->proxyreq);
+        if (!path) {
+            return HTTP_BAD_REQUEST;
+        }
+    }
+    /*
+     * If we have a raw control character or a ' ' in nocanon path,
+     * correct encoding was missed.
+     */
+    if (path == url && *ap_scan_vchar_obstext(path)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10414)
+                      "To be forwarded path contains control "
+                      "characters or spaces");
+        return HTTP_FORBIDDEN;
     }
-    if (path == NULL)
-        return HTTP_BAD_REQUEST;
 
     r->filename = apr_pstrcat(r->pool, "proxy:fcgi://", host, sport, "/",
                               path, NULL);
diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c
index fca8d5d..40f0787 100644
--- a/modules/proxy/mod_proxy_http.c
+++ b/modules/proxy/mod_proxy_http.c
@@ -131,26 +131,32 @@ static int proxy_http_canon(request_rec *r, char *url)
 
             path = ap_proxy_canonenc_ex(r->pool, url, strlen(url), enc_path,
                                         flags, r->proxyreq);
+            if (!path) {
+                return HTTP_BAD_REQUEST;
+            }
             search = r->args;
         }
-        if (search && *(ap_scan_vchar_obstext(search))) {
-            /*
-             * We have a raw control character or a ' ' in r->args.
-             * Correct encoding was missed.
-             */
-             ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10408)
-                           "To be forwarded query string contains control "
-                           "characters or spaces");
-             return HTTP_FORBIDDEN;
-        }
         break;
     case PROXYREQ_PROXY:
         path = url;
         break;
     }
-
-    if (path == NULL)
-        return HTTP_BAD_REQUEST;
+    /*
+     * If we have a raw control character or a ' ' in nocanon path or
+     * r->args, correct encoding was missed.
+     */
+    if (path == url && *ap_scan_vchar_obstext(path)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10415)
+                      "To be forwarded path contains control "
+                      "characters or spaces");
+        return HTTP_FORBIDDEN;
+    }
+    if (search && *ap_scan_vchar_obstext(search)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10408)
+                      "To be forwarded query string contains control "
+                      "characters or spaces");
+        return HTTP_FORBIDDEN;
+    }
 
     if (port != def_port)
         apr_snprintf(sport, sizeof(sport), ":%d", port);
diff --git a/modules/proxy/mod_proxy_uwsgi.c b/modules/proxy/mod_proxy_uwsgi.c
index 771fcea..f0cbb5d 100644
--- a/modules/proxy/mod_proxy_uwsgi.c
+++ b/modules/proxy/mod_proxy_uwsgi.c
@@ -94,9 +94,19 @@ static int uwsgi_canon(request_rec *r, char *url)
 
         path = ap_proxy_canonenc_ex(r->pool, url, strlen(url), enc_path, flags,
                                     r->proxyreq);
+        if (!path) {
+            return HTTP_BAD_REQUEST;
+        }
     }
-    if (!path) {
-        return HTTP_BAD_REQUEST;
+    /*
+     * If we have a raw control character or a ' ' in nocanon path,
+     * correct encoding was missed.
+     */
+    if (path == url && *ap_scan_vchar_obstext(path)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10417)
+                      "To be forwarded path contains control "
+                      "characters or spaces");
+        return HTTP_FORBIDDEN;
     }
 
     r->filename =
diff --git a/modules/proxy/mod_proxy_wstunnel.c b/modules/proxy/mod_proxy_wstunnel.c
index a44bb44..227dba4 100644
--- a/modules/proxy/mod_proxy_wstunnel.c
+++ b/modules/proxy/mod_proxy_wstunnel.c
@@ -120,20 +120,27 @@ static int proxy_wstunnel_canon(request_rec *r, char *url)
 
         path = ap_proxy_canonenc_ex(r->pool, url, strlen(url), enc_path, flags,
                                     r->proxyreq);
+        if (!path) {
+            return HTTP_BAD_REQUEST;
+        }
         search = r->args;
     }
+    /*
+     * If we have a raw control character or a ' ' in nocanon path or
+     * r->args, correct encoding was missed.
+     */
+    if (path == url && *ap_scan_vchar_obstext(path)) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10419)
+                      "To be forwarded path contains control "
+                      "characters or spaces");
+        return HTTP_FORBIDDEN;
+    }
     if (search && *(ap_scan_vchar_obstext(search))) {
-        /*
-         * We have a raw control character or a ' ' in r->args.
-         * Correct encoding was missed.
-         */
          ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10409)
                        "To be forwarded query string contains control "
                        "characters or spaces");
          return HTTP_FORBIDDEN;
     }
-    if (path == NULL)
-        return HTTP_BAD_REQUEST;
 
     if (port != def_port)
         apr_snprintf(sport, sizeof(sport), ":%d", port);
-- 
2.27.0

