From a356fdbfb93c59a4e359f0a81b38aef31ddd856e Mon Sep 17 00:00:00 2001
From: Eric covener <covener@apache.org>
Date: Mon, 20 Mar 2023 05:29:03 AM GMT+0800
Subject: [PATCH] mod_proxy: Fix double encoding of the uri-path of the request forwarded 
                            to the origin server, when using mapping=encoded|servlet

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

---
 modules/http2/mod_proxy_http2.c    | 20 ++++++++++----------
 modules/proxy/mod_proxy.c          | 17 +++++++++++------
 modules/proxy/mod_proxy_ajp.c      | 20 ++++++++++----------
 modules/proxy/mod_proxy_balancer.c | 20 ++++++++++----------
 modules/proxy/mod_proxy_fcgi.c     |  5 +++--
 modules/proxy/mod_proxy_http.c     | 20 ++++++++++----------
 modules/proxy/mod_proxy_uwsgi.c    | 10 ++++++++--
 modules/proxy/mod_proxy_wstunnel.c | 20 ++++++++++----------
 8 files changed, 72 insertions(+), 60 deletions(-)

diff --git a/modules/http2/mod_proxy_http2.c b/modules/http2/mod_proxy_http2.c
index 753f7f4..9b741e1 100644
--- a/modules/http2/mod_proxy_http2.c
+++ b/modules/http2/mod_proxy_http2.c
@@ -162,16 +162,16 @@ static int proxy_http2_canon(request_rec *r, char *url)
             path = ap_proxy_canonenc(r->pool, url, (int)strlen(url),
                                      enc_path, 0, r->proxyreq);
             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;
-            }
+        }
+        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:
diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
index f8a4db6..6717782 100644
--- a/modules/proxy/mod_proxy.c
+++ b/modules/proxy/mod_proxy.c
@@ -960,6 +960,8 @@ PROXY_DECLARE(int) ap_proxy_trans_match(request_rec *r, struct proxy_alias *ent,
     }
 
     if (found) {
+        unsigned int encoded = ent->flags & PROXYPASS_MAP_ENCODED;
+
         /* A proxy module is assigned this URL, check whether it's interested
          * in the request itself (e.g. proxy_wstunnel cares about Upgrade
          * requests only, and could hand over to proxy_http otherwise).
@@ -979,6 +981,9 @@ PROXY_DECLARE(int) ap_proxy_trans_match(request_rec *r, struct proxy_alias *ent,
         if (ent->flags & PROXYPASS_NOQUERY) {
             apr_table_setn(r->notes, "proxy-noquery", "1");
         }
+        if (encoded) {
+            apr_table_setn(r->notes, "proxy-noencode", "1");
+        }
 
         if (servlet_uri) {
             ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(10248)
@@ -992,13 +997,13 @@ PROXY_DECLARE(int) ap_proxy_trans_match(request_rec *r, struct proxy_alias *ent,
              */
             AP_DEBUG_ASSERT(strlen(r->uri) >= strlen(servlet_uri));
             strcpy(r->uri, servlet_uri);
-            return DONE;
         }
-
-        ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(03464)
-                      "URI path '%s' matches proxy handler '%s'", r->uri,
-                      found);
-        return OK;
+        else {
+            ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(03464)
+                          "URI path '%s' matches proxy handler '%s'", r->uri,
+                          found);
+        }
+        return (encoded) ? DONE : OK;
     }
 
     return HTTP_CONTINUE;
diff --git a/modules/proxy/mod_proxy_ajp.c b/modules/proxy/mod_proxy_ajp.c
index ba41fbd..731e4ed 100644
--- a/modules/proxy/mod_proxy_ajp.c
+++ b/modules/proxy/mod_proxy_ajp.c
@@ -73,16 +73,16 @@ static int proxy_ajp_canon(request_rec *r, char *url)
         path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
                                  r->proxyreq);
         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(10406)
-                           "To be forwarded query string 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;
diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c
index c8bba0f..719a99e 100644
--- a/modules/proxy/mod_proxy_balancer.c
+++ b/modules/proxy/mod_proxy_balancer.c
@@ -110,16 +110,16 @@ static int proxy_balancer_canon(request_rec *r, char *url)
         path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
                                  r->proxyreq);
         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(10407)
-                           "To be forwarded query string 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;
diff --git a/modules/proxy/mod_proxy_fcgi.c b/modules/proxy/mod_proxy_fcgi.c
index 3382b9b..a89b9a9 100644
--- a/modules/proxy/mod_proxy_fcgi.c
+++ b/modules/proxy/mod_proxy_fcgi.c
@@ -92,8 +92,9 @@ static int proxy_fcgi_canon(request_rec *r, char *url)
         host = apr_pstrcat(r->pool, "[", host, "]", NULL);
     }
 
-    if (apr_table_get(r->notes, "proxy-nocanon")) {
-        path = url;   /* this is the raw path */
+    if (apr_table_get(r->notes, "proxy-nocanon")
+        || apr_table_get(r->notes, "proxy-noencode")) {
+        path = url;   /* this is the raw/encoded path */
     }
     else {
         path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c
index 09269b2..4d0f8de 100644
--- a/modules/proxy/mod_proxy_http.c
+++ b/modules/proxy/mod_proxy_http.c
@@ -129,16 +129,16 @@ static int proxy_http_canon(request_rec *r, char *url)
             path = ap_proxy_canonenc(r->pool, url, strlen(url),
                                      enc_path, 0, r->proxyreq);
             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;
-            }
+        }
+        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:
diff --git a/modules/proxy/mod_proxy_uwsgi.c b/modules/proxy/mod_proxy_uwsgi.c
index cc21e38..71c6ebb 100644
--- a/modules/proxy/mod_proxy_uwsgi.c
+++ b/modules/proxy/mod_proxy_uwsgi.c
@@ -84,8 +84,14 @@ static int uwsgi_canon(request_rec *r, char *url)
         host = apr_pstrcat(r->pool, "[", host, "]", NULL);
     }
 
-    path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
-                             r->proxyreq);
+    if (apr_table_get(r->notes, "proxy-nocanon")
+        || apr_table_get(r->notes, "proxy-noencode")) {
+        path = url;   /* this is the raw/encoded path */
+    }
+    else {
+        path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
+                                 r->proxyreq);
+    }
     if (!path) {
         return HTTP_BAD_REQUEST;
     }
diff --git a/modules/proxy/mod_proxy_wstunnel.c b/modules/proxy/mod_proxy_wstunnel.c
index e2fcba2..3f8de25 100644
--- a/modules/proxy/mod_proxy_wstunnel.c
+++ b/modules/proxy/mod_proxy_wstunnel.c
@@ -118,16 +118,16 @@ static int proxy_wstunnel_canon(request_rec *r, char *url)
         path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
                                  r->proxyreq);
         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(10409)
-                          "To be forwarded query string 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;
-- 
2.27.0

