You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by rp...@apache.org on 2023/03/13 10:24:31 UTC

svn commit: r1908341 - in /httpd/httpd/trunk: changes-entries/ include/ modules/http2/ modules/proxy/

Author: rpluem
Date: Mon Mar 13 10:24:30 2023
New Revision: 1908341

URL: http://svn.apache.org/viewvc?rev=1908341&view=rev
Log:
Do not double encode encoded slashes

In case that AllowEncodedSlashes is set to NoDecode do not double encode
encoded slashes in the URL sent by the reverse proxy to the backend.

* include/ap_mmn.h: Document the addition of ap_proxy_canonenc_ex to the API.

* modules/proxy/mod_proxy.h: Declare ap_proxy_canonenc_ex and define flag
      values.

* modules/proxy/proxy_util.c: Implement ap_proxy_canonenc_ex by modifying
      ap_proxy_canonenc accordingly and reimplement ap_proxy_canonenc to
      use ap_proxy_canonenc_ex with the appropriate flag.

* modules/http2/mod_proxy_http2.c, modules/proxy/mod_proxy_*.c: Set the
      correct flag based on the AllowEncodedSlashes configuration and use
      ap_proxy_canonenc_ex instead of ap_proxy_canonenc.

Added:
    httpd/httpd/trunk/changes-entries/nodoubleencodeencodedslash.txt   (with props)
Modified:
    httpd/httpd/trunk/include/ap_mmn.h
    httpd/httpd/trunk/modules/http2/mod_proxy_http2.c
    httpd/httpd/trunk/modules/proxy/mod_proxy.h
    httpd/httpd/trunk/modules/proxy/mod_proxy_ajp.c
    httpd/httpd/trunk/modules/proxy/mod_proxy_balancer.c
    httpd/httpd/trunk/modules/proxy/mod_proxy_fcgi.c
    httpd/httpd/trunk/modules/proxy/mod_proxy_ftp.c
    httpd/httpd/trunk/modules/proxy/mod_proxy_http.c
    httpd/httpd/trunk/modules/proxy/mod_proxy_scgi.c
    httpd/httpd/trunk/modules/proxy/mod_proxy_uwsgi.c
    httpd/httpd/trunk/modules/proxy/mod_proxy_wstunnel.c
    httpd/httpd/trunk/modules/proxy/proxy_util.c

Added: httpd/httpd/trunk/changes-entries/nodoubleencodeencodedslash.txt
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/changes-entries/nodoubleencodeencodedslash.txt?rev=1908341&view=auto
==============================================================================
--- httpd/httpd/trunk/changes-entries/nodoubleencodeencodedslash.txt (added)
+++ httpd/httpd/trunk/changes-entries/nodoubleencodeencodedslash.txt Mon Mar 13 10:24:30 2023
@@ -0,0 +1,4 @@
+
+  *) mode_proxy: In case that AllowEncodedSlashes is set to NoDecode do not
+     double encode encoded slashes in the URL sent by the reverse proxy to the
+     backend. [Ruediger Pluem]

Propchange: httpd/httpd/trunk/changes-entries/nodoubleencodeencodedslash.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: httpd/httpd/trunk/include/ap_mmn.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_mmn.h?rev=1908341&r1=1908340&r2=1908341&view=diff
==============================================================================
--- httpd/httpd/trunk/include/ap_mmn.h (original)
+++ httpd/httpd/trunk/include/ap_mmn.h Mon Mar 13 10:24:30 2023
@@ -712,6 +712,7 @@
  * 20211221.7 (2.5.1-dev)  Add ap_h1_append_header()
  * 20211221.8 (2.5.1-dev)  Add ap_sb_get_child_thread()
  * 20211221.9 (2.5.1-dev)  Add additional hcmethod_t enums and PROXY_WORKER_IS_ERROR
+ * 20211221.10 (2.5.1-dev) Add ap_proxy_canonenc_ex
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */
@@ -719,7 +720,7 @@
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20211221
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 9             /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 10             /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a

Modified: httpd/httpd/trunk/modules/http2/mod_proxy_http2.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/mod_proxy_http2.c?rev=1908341&r1=1908340&r2=1908341&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/mod_proxy_http2.c (original)
+++ httpd/httpd/trunk/modules/http2/mod_proxy_http2.c Mon Mar 13 10:24:30 2023
@@ -159,8 +159,11 @@ static int proxy_http2_canon(request_rec
             search = r->args;
         }
         else {
-            path = ap_proxy_canonenc(r->pool, url, (int)strlen(url),
-                                     enc_path, 0, r->proxyreq);
+            core_dir_config *d = ap_get_core_module_config(r->per_dir_config);
+            int flags = d->allow_encoded_slashes  && !d->decode_encoded_slashes ? PROXY_CANONENC_NOENCODEDSLASHENCODING : 0;
+
+            path = ap_proxy_canonenc_ex(r->pool, url, (int)strlen(url),
+                                        enc_path, flags, r->proxyreq);
             search = r->args;
         }
         if (search && *ap_scan_vchar_obstext(search)) {

Modified: httpd/httpd/trunk/modules/proxy/mod_proxy.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy.h?rev=1908341&r1=1908340&r2=1908341&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/proxy/mod_proxy.h (original)
+++ httpd/httpd/trunk/modules/proxy/mod_proxy.h Mon Mar 13 10:24:30 2023
@@ -76,6 +76,10 @@ enum enctype {
     enc_path, enc_search, enc_user, enc_fpath, enc_parm
 };
 
+/* Flags for ap_proxy_canonenc_ex */
+#define PROXY_CANONENC_FORCEDEC 0x01
+#define PROXY_CANONENC_NOENCODEDSLASHENCODING 0x02
+
 typedef enum {
     NONE, TCP, OPTIONS, HEAD, GET, CPING, PROVIDER, OPTIONS11, HEAD11, GET11, EOT
 } hcmethod_t;
@@ -693,6 +697,8 @@ PROXY_DECLARE(apr_status_t) ap_proxy_str
                                              apr_size_t dlen);
 PROXY_DECLARE(int) ap_proxy_hex2c(const char *x);
 PROXY_DECLARE(void) ap_proxy_c2hex(int ch, char *x);
+PROXY_DECLARE(char *)ap_proxy_canonenc_ex(apr_pool_t *p, const char *x, int len, enum enctype t,
+                                          int flags, int proxyreq);
 PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
                                        int forcedec, int proxyreq);
 PROXY_DECLARE(char *)ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,

Modified: httpd/httpd/trunk/modules/proxy/mod_proxy_ajp.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy_ajp.c?rev=1908341&r1=1908340&r2=1908341&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/proxy/mod_proxy_ajp.c (original)
+++ httpd/httpd/trunk/modules/proxy/mod_proxy_ajp.c Mon Mar 13 10:24:30 2023
@@ -70,8 +70,11 @@ static int proxy_ajp_canon(request_rec *
         search = r->args;
     }
     else {
-        path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
-                                 r->proxyreq);
+        core_dir_config *d = ap_get_core_module_config(r->per_dir_config);
+        int flags = d->allow_encoded_slashes  && !d->decode_encoded_slashes ? PROXY_CANONENC_NOENCODEDSLASHENCODING : 0;
+
+        path = ap_proxy_canonenc_ex(r->pool, url, strlen(url), enc_path, flags,
+                                    r->proxyreq);
         search = r->args;
     }
     if (search && *ap_scan_vchar_obstext(search)) {

Modified: httpd/httpd/trunk/modules/proxy/mod_proxy_balancer.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy_balancer.c?rev=1908341&r1=1908340&r2=1908341&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/proxy/mod_proxy_balancer.c (original)
+++ httpd/httpd/trunk/modules/proxy/mod_proxy_balancer.c Mon Mar 13 10:24:30 2023
@@ -107,8 +107,11 @@ static int proxy_balancer_canon(request_
         search = r->args;
     }
     else {
-        path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
-                                 r->proxyreq);
+        core_dir_config *d = ap_get_core_module_config(r->per_dir_config);
+        int flags = d->allow_encoded_slashes  && !d->decode_encoded_slashes ? PROXY_CANONENC_NOENCODEDSLASHENCODING : 0;
+
+        path = ap_proxy_canonenc_ex(r->pool, url, strlen(url), enc_path, flags,
+                                    r->proxyreq);
         search = r->args;
     }
     if (search && *ap_scan_vchar_obstext(search)) {

Modified: httpd/httpd/trunk/modules/proxy/mod_proxy_fcgi.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy_fcgi.c?rev=1908341&r1=1908340&r2=1908341&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/proxy/mod_proxy_fcgi.c (original)
+++ httpd/httpd/trunk/modules/proxy/mod_proxy_fcgi.c Mon Mar 13 10:24:30 2023
@@ -97,8 +97,11 @@ static int proxy_fcgi_canon(request_rec
         path = url;   /* this is the raw/encoded path */
     }
     else {
-        path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
-                             r->proxyreq);
+        core_dir_config *d = ap_get_core_module_config(r->per_dir_config);
+        int flags = d->allow_encoded_slashes  && !d->decode_encoded_slashes ? PROXY_CANONENC_NOENCODEDSLASHENCODING : 0;
+
+        path = ap_proxy_canonenc_ex(r->pool, url, strlen(url), enc_path, flags,
+                                    r->proxyreq);
     }
     if (path == NULL)
         return HTTP_BAD_REQUEST;

Modified: httpd/httpd/trunk/modules/proxy/mod_proxy_ftp.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy_ftp.c?rev=1908341&r1=1908340&r2=1908341&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/proxy/mod_proxy_ftp.c (original)
+++ httpd/httpd/trunk/modules/proxy/mod_proxy_ftp.c Mon Mar 13 10:24:30 2023
@@ -289,6 +289,8 @@ static int proxy_ftp_canon(request_rec *
     apr_pool_t *p = r->pool;
     const char *err;
     apr_port_t port, def_port;
+    core_dir_config *d = ap_get_core_module_config(r->per_dir_config);
+    int flags = d->allow_encoded_slashes  && !d->decode_encoded_slashes ? PROXY_CANONENC_NOENCODEDSLASHENCODING : 0;
 
     /* */
     if (ap_cstr_casecmpn(url, "ftp:", 4) == 0) {
@@ -327,7 +329,8 @@ static int proxy_ftp_canon(request_rec *
     else
         parms = "";
 
-    path = ap_proxy_canonenc(p, url, strlen(url), enc_path, 0, r->proxyreq);
+    path = ap_proxy_canonenc_ex(p, url, strlen(url), enc_path, flags,
+                                r->proxyreq);
     if (path == NULL)
         return HTTP_BAD_REQUEST;
     if (!ftp_check_string(path))

Modified: httpd/httpd/trunk/modules/proxy/mod_proxy_http.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy_http.c?rev=1908341&r1=1908340&r2=1908341&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/proxy/mod_proxy_http.c (original)
+++ httpd/httpd/trunk/modules/proxy/mod_proxy_http.c Mon Mar 13 10:24:30 2023
@@ -123,8 +123,11 @@ static int proxy_http_canon(request_rec
             search = r->args;
         }
         else {
-            path = ap_proxy_canonenc(r->pool, url, strlen(url),
-                                     enc_path, 0, r->proxyreq);
+            core_dir_config *d = ap_get_core_module_config(r->per_dir_config);
+            int flags = d->allow_encoded_slashes  && !d->decode_encoded_slashes ? PROXY_CANONENC_NOENCODEDSLASHENCODING : 0;
+
+            path = ap_proxy_canonenc_ex(r->pool, url, strlen(url), enc_path,
+                                        flags, r->proxyreq);
             search = r->args;
         }
         if (search && *ap_scan_vchar_obstext(search)) {

Modified: httpd/httpd/trunk/modules/proxy/mod_proxy_scgi.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy_scgi.c?rev=1908341&r1=1908340&r2=1908341&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/proxy/mod_proxy_scgi.c (original)
+++ httpd/httpd/trunk/modules/proxy/mod_proxy_scgi.c Mon Mar 13 10:24:30 2023
@@ -179,6 +179,8 @@ static int scgi_canon(request_rec *r, ch
     char *host, sport[sizeof(":65535")];
     const char *err, *path;
     apr_port_t port, def_port;
+    core_dir_config *d = ap_get_core_module_config(r->per_dir_config);
+    int flags = d->allow_encoded_slashes  && !d->decode_encoded_slashes ? PROXY_CANONENC_NOENCODEDSLASHENCODING : 0;
 
     if (ap_cstr_casecmpn(url, SCHEME "://", sizeof(SCHEME) + 2)) {
         return DECLINED;
@@ -205,8 +207,8 @@ static int scgi_canon(request_rec *r, ch
         host = apr_pstrcat(r->pool, "[", host, "]", NULL);
     }
 
-    path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
-                             r->proxyreq);
+    path = ap_proxy_canonenc_ex(r->pool, url, strlen(url), enc_path, flags,
+                                r->proxyreq);
     if (!path) {
         return HTTP_BAD_REQUEST;
     }

Modified: httpd/httpd/trunk/modules/proxy/mod_proxy_uwsgi.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy_uwsgi.c?rev=1908341&r1=1908340&r2=1908341&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/proxy/mod_proxy_uwsgi.c (original)
+++ httpd/httpd/trunk/modules/proxy/mod_proxy_uwsgi.c Mon Mar 13 10:24:30 2023
@@ -89,8 +89,11 @@ static int uwsgi_canon(request_rec *r, c
         path = url;   /* this is the raw/encoded path */
     }
     else {
-        path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
-                                 r->proxyreq);
+        core_dir_config *d = ap_get_core_module_config(r->per_dir_config);
+        int flags = d->allow_encoded_slashes  && !d->decode_encoded_slashes ? PROXY_CANONENC_NOENCODEDSLASHENCODING : 0;
+
+        path = ap_proxy_canonenc_ex(r->pool, url, strlen(url), enc_path, flags,
+                                    r->proxyreq);
     }
     if (!path) {
         return HTTP_BAD_REQUEST;

Modified: httpd/httpd/trunk/modules/proxy/mod_proxy_wstunnel.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy_wstunnel.c?rev=1908341&r1=1908340&r2=1908341&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/proxy/mod_proxy_wstunnel.c (original)
+++ httpd/httpd/trunk/modules/proxy/mod_proxy_wstunnel.c Mon Mar 13 10:24:30 2023
@@ -200,8 +200,11 @@ static int proxy_wstunnel_canon(request_
         search = r->args;
     }
     else {
-        path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
-                                 r->proxyreq);
+        core_dir_config *d = ap_get_core_module_config(r->per_dir_config);
+        int flags = d->allow_encoded_slashes  && !d->decode_encoded_slashes ? PROXY_CANONENC_NOENCODEDSLASHENCODING : 0;
+
+        path = ap_proxy_canonenc_ex(r->pool, url, strlen(url), enc_path, flags,
+                                    r->proxyreq);
         search = r->args;
     }
     if (search && *ap_scan_vchar_obstext(search)) {

Modified: httpd/httpd/trunk/modules/proxy/proxy_util.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/proxy_util.c?rev=1908341&r1=1908340&r2=1908341&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/proxy/proxy_util.c (original)
+++ httpd/httpd/trunk/modules/proxy/proxy_util.c Mon Mar 13 10:24:30 2023
@@ -200,14 +200,16 @@ PROXY_DECLARE(void) ap_proxy_c2hex(int c
  * and encodes those which must be encoded, and does not touch
  * those which must not be touched.
  */
-PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len,
-                                       enum enctype t, int forcedec,
-                                       int proxyreq)
+PROXY_DECLARE(char *)ap_proxy_canonenc_ex(apr_pool_t *p, const char *x, int len,
+                                          enum enctype t, int flags,
+                                          int proxyreq)
 {
     int i, j, ch;
     char *y;
     char *allowed;  /* characters which should not be encoded */
     char *reserved; /* characters which much not be en/de-coded */
+    int forcedec = flags & PROXY_CANONENC_FORCEDEC;
+    int noencslashesenc = flags & PROXY_CANONENC_NOENCODEDSLASHENCODING;
 
 /*
  * N.B. in addition to :@&=, this allows ';' in an http path
@@ -256,7 +258,8 @@ PROXY_DECLARE(char *)ap_proxy_canonenc(a
  * decode it if not already done. do not decode reverse proxied URLs
  * unless specifically forced
  */
-        if ((forcedec || (proxyreq && proxyreq != PROXYREQ_REVERSE)) && ch == '%') {
+        if ((forcedec || noencslashesenc
+            ||(proxyreq && proxyreq != PROXYREQ_REVERSE)) && ch == '%') {
             if (!apr_isxdigit(x[i + 1]) || !apr_isxdigit(x[i + 2])) {
                 return NULL;
             }
@@ -267,7 +270,17 @@ PROXY_DECLARE(char *)ap_proxy_canonenc(a
                 y[j] = x[i];
                 continue;
             }
-            i += 2;
+            if (noencslashesenc && !forcedec && (proxyreq == PROXYREQ_REVERSE)) {
+                /*
+                 * In the reverse proxy case when we only want to keep encoded
+                 * slashes untouched revert back to '%' which will cause
+                 * '%' to be encoded in the following.
+                 */
+                ch = '%';
+            }
+            else {
+                i += 2;
+            }
         }
 /* recode it, if necessary */
         if (!apr_isalnum(ch) && !strchr(allowed, ch)) {
@@ -283,6 +296,22 @@ PROXY_DECLARE(char *)ap_proxy_canonenc(a
 }
 
 /*
+ * Convert a URL-encoded string to canonical form.
+ * It decodes characters which need not be encoded,
+ * and encodes those which must be encoded, and does not touch
+ * those which must not be touched.
+ */
+PROXY_DECLARE(char *)ap_proxy_canonenc(apr_pool_t *p, const char *x, int len,
+                                       enum enctype t, int forcedec,
+                                       int proxyreq)
+{
+    int flags;
+
+    flags = forcedec ? PROXY_CANONENC_FORCEDEC : 0;
+    return ap_proxy_canonenc_ex(p, x, len, t, flags, proxyreq);
+}
+
+/*
  * Parses network-location.
  *    urlp           on input the URL; on output the path, after the leading /
  *    user           NULL if no user/password permitted