summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuediger Pluem <rpluem@apache.org>2023-03-31 14:33:00 +0000
committerRuediger Pluem <rpluem@apache.org>2023-03-31 14:33:00 +0000
commit9b8cf1746bb004050b02a30bf0222479fbe405c2 (patch)
tree2e26c51335792dff81d5cb009de7f2c83d844928
parent386a268201e9424fb3e4be62fe5ff42b441a5760 (diff)
downloadhttpd-9b8cf1746bb004050b02a30bf0222479fbe405c2.tar.gz
Merge r1908341, r1908628, r1908629 from trunk:
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. * Whitespace fixes. No functional change. * Fix typo Reviewed by: rpluem, ylavic, covener Github: closes #351 git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1908864 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--CHANGES4
-rw-r--r--STATUS12
-rw-r--r--include/ap_mmn.h4
-rw-r--r--modules/http2/mod_proxy_http2.c7
-rw-r--r--modules/proxy/mod_proxy.h6
-rw-r--r--modules/proxy/mod_proxy_ajp.c7
-rw-r--r--modules/proxy/mod_proxy_balancer.c7
-rw-r--r--modules/proxy/mod_proxy_fcgi.c7
-rw-r--r--modules/proxy/mod_proxy_ftp.c5
-rw-r--r--modules/proxy/mod_proxy_http.c7
-rw-r--r--modules/proxy/mod_proxy_scgi.c6
-rw-r--r--modules/proxy/mod_proxy_uwsgi.c7
-rw-r--r--modules/proxy/mod_proxy_wstunnel.c7
-rw-r--r--modules/proxy/proxy_util.c39
14 files changed, 89 insertions, 36 deletions
diff --git a/CHANGES b/CHANGES
index a8ec904e1c..f4b84dcbdc 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,10 @@
-*- coding: utf-8 -*-
Changes with Apache 2.4.57
+ *) mod_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]
+
*) mod_http2: fixed a crash during connection termination. See PR 66539.
[Stefan Eissing]
diff --git a/STATUS b/STATUS
index b5a1ae12ef..13871e1a9c 100644
--- a/STATUS
+++ b/STATUS
@@ -151,18 +151,6 @@ RELEASE SHOWSTOPPERS:
PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
[ start all new proposals below, under PATCHES PROPOSED. ]
- *) mod_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.
- Trunk version of patch:
- https://svn.apache.org/r1908341
- https://svn.apache.org/r1908628
- https://svn.apache.org/r1908629
- Backport version for 2.4.x of patch:
- https://patch-diff.githubusercontent.com/raw/apache/httpd/pull/351.diff
- Can be applied via apply_backport_pr.sh 351
- +1: rpluem, ylavic, covener
-
*) mod_proxy: Check before forwarding that a nocanon path has not been
rewritten with spaces during processing.
trunk patch: https://svn.apache.org/r1908827
diff --git a/include/ap_mmn.h b/include/ap_mmn.h
index 402c23a3a8..ace7c43ed9 100644
--- a/include/ap_mmn.h
+++ b/include/ap_mmn.h
@@ -594,7 +594,7 @@
* 20120211.124 (2.4.51-dev) Add name_ex to struct proxy_worker_shared
* 20120211.125 (2.4.55-dev) Export mod_http2.h as public header
* 20120211.126 (2.4.55-dev) Add additional hcmethod_t enums and PROXY_WORKER_IS_ERROR
- *
+ * 20120211.127 (2.4.56-dev) Add ap_proxy_canonenc_ex
*/
#define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
@@ -602,7 +602,7 @@
#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20120211
#endif
-#define MODULE_MAGIC_NUMBER_MINOR 126 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 127 /* 0...n */
/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
diff --git a/modules/http2/mod_proxy_http2.c b/modules/http2/mod_proxy_http2.c
index f1c1bb92f4..8af0a34165 100644
--- a/modules/http2/mod_proxy_http2.c
+++ b/modules/http2/mod_proxy_http2.c
@@ -159,8 +159,11 @@ static int proxy_http2_canon(request_rec *r, char *url)
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)) {
diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h
index 5c08e99c9e..c51145e012 100644
--- a/modules/proxy/mod_proxy.h
+++ b/modules/proxy/mod_proxy.h
@@ -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;
@@ -676,6 +680,8 @@ PROXY_DECLARE(apr_status_t) ap_proxy_strncpy(char *dst, const char *src,
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,
diff --git a/modules/proxy/mod_proxy_ajp.c b/modules/proxy/mod_proxy_ajp.c
index a177b5f1f8..f5b25662e1 100644
--- a/modules/proxy/mod_proxy_ajp.c
+++ b/modules/proxy/mod_proxy_ajp.c
@@ -70,8 +70,11 @@ static int proxy_ajp_canon(request_rec *r, char *url)
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)) {
diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c
index 63c1d24c02..a3db6dcd9d 100644
--- a/modules/proxy/mod_proxy_balancer.c
+++ b/modules/proxy/mod_proxy_balancer.c
@@ -107,8 +107,11 @@ static int proxy_balancer_canon(request_rec *r, char *url)
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)) {
diff --git a/modules/proxy/mod_proxy_fcgi.c b/modules/proxy/mod_proxy_fcgi.c
index a89b9a9c7b..a422b4e20c 100644
--- a/modules/proxy/mod_proxy_fcgi.c
+++ b/modules/proxy/mod_proxy_fcgi.c
@@ -97,8 +97,11 @@ static int proxy_fcgi_canon(request_rec *r, char *url)
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;
diff --git a/modules/proxy/mod_proxy_ftp.c b/modules/proxy/mod_proxy_ftp.c
index 3237a2ba85..a3fb10a92c 100644
--- a/modules/proxy/mod_proxy_ftp.c
+++ b/modules/proxy/mod_proxy_ftp.c
@@ -289,6 +289,8 @@ static int proxy_ftp_canon(request_rec *r, char *url)
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 *r, char *url)
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))
diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c
index a4c0484004..657f098069 100644
--- a/modules/proxy/mod_proxy_http.c
+++ b/modules/proxy/mod_proxy_http.c
@@ -126,8 +126,11 @@ static int proxy_http_canon(request_rec *r, char *url)
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)) {
diff --git a/modules/proxy/mod_proxy_scgi.c b/modules/proxy/mod_proxy_scgi.c
index 493757d3c9..5444a5c427 100644
--- a/modules/proxy/mod_proxy_scgi.c
+++ b/modules/proxy/mod_proxy_scgi.c
@@ -179,6 +179,8 @@ static int scgi_canon(request_rec *r, char *url)
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, char *url)
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;
}
diff --git a/modules/proxy/mod_proxy_uwsgi.c b/modules/proxy/mod_proxy_uwsgi.c
index 9dc446d3eb..3bb1f62bea 100644
--- a/modules/proxy/mod_proxy_uwsgi.c
+++ b/modules/proxy/mod_proxy_uwsgi.c
@@ -89,8 +89,11 @@ static int uwsgi_canon(request_rec *r, char *url)
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;
diff --git a/modules/proxy/mod_proxy_wstunnel.c b/modules/proxy/mod_proxy_wstunnel.c
index 86c1b9ccae..012dd0a772 100644
--- a/modules/proxy/mod_proxy_wstunnel.c
+++ b/modules/proxy/mod_proxy_wstunnel.c
@@ -115,8 +115,11 @@ static int proxy_wstunnel_canon(request_rec *r, char *url)
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)) {
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
index 992dba8fae..caafde0b76 100644
--- a/modules/proxy/proxy_util.c
+++ b/modules/proxy/proxy_util.c
@@ -200,14 +200,16 @@ PROXY_DECLARE(void) ap_proxy_c2hex(int ch, char *x)
* 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(apr_pool_t *p, const char *x, int len,
* 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(apr_pool_t *p, const char *x, int len,
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(apr_pool_t *p, const char *x, int len,
}
/*
+ * 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