summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYann Ylavic <ylavic@apache.org>2024-08-01 13:35:26 +0200
committerYann Ylavic <ylavic@apache.org>2024-08-01 13:35:26 +0200
commit2f1f9c5df027e86bf4c3dbdb96c9e52748421c20 (patch)
treee186b3c9ffbb791eb7091d003f03f5b8d5a276fc
parentFollow-up to r1919587: CMake: Fix type in variable name (MODULES_SYNMBOLS -> ... (diff)
downloadapache2-2f1f9c5df027e86bf4c3dbdb96c9e52748421c20.tar.xz
apache2-2f1f9c5df027e86bf4c3dbdb96c9e52748421c20.zip
mod_proxy: Fix selection of ProxyPassMatch workers with host/port substitution. PR 69233.
With "ProxyPassMatch ^/([^/]+)/(.*)$ https://$1/$2", ap_proxy_get_worker_ex() should not consider the length of scheme://host part of the given URL because of the globbing match on the host part. Fix it by setting worker->s>is_host_matchable when creating a worker with host substitution and avoiding the min_match check in worker_matches() in this case. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1919617 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--changes-entries/bz69233.txt2
-rw-r--r--include/ap_mmn.h3
-rw-r--r--modules/proxy/mod_proxy.h1
-rw-r--r--modules/proxy/proxy_util.c30
4 files changed, 22 insertions, 14 deletions
diff --git a/changes-entries/bz69233.txt b/changes-entries/bz69233.txt
new file mode 100644
index 0000000000..9e1e43bfd0
--- /dev/null
+++ b/changes-entries/bz69233.txt
@@ -0,0 +1,2 @@
+ *) mod_proxy: Fix selection of ProxyPassMatch workers with substitution
+ in the host name or port. PR 69233. [Yann Ylavic] \ No newline at end of file
diff --git a/include/ap_mmn.h b/include/ap_mmn.h
index ad4b77bd33..c9ae4c157c 100644
--- a/include/ap_mmn.h
+++ b/include/ap_mmn.h
@@ -731,6 +731,7 @@
* and AP_REQUEST_TRUSTED_CT BNOTE.
* 20211221.24 (2.5.1-dev) Add ap_proxy_fixup_uds_filename()
* 20211221.25 (2.5.1-dev) AP_SLASHES and AP_IS_SLASH
+ * 20211221.26 (2.5.1-dev) Add is_host_matchable to proxy_worker_shared
*/
#define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */
@@ -738,7 +739,7 @@
#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20211221
#endif
-#define MODULE_MAGIC_NUMBER_MINOR 25 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 26 /* 0...n */
/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h
index cf6d5057df..6594159e98 100644
--- a/modules/proxy/mod_proxy.h
+++ b/modules/proxy/mod_proxy.h
@@ -492,6 +492,7 @@ typedef struct {
unsigned int disablereuse_set:1;
unsigned int was_malloced:1;
unsigned int is_name_matchable:1;
+ unsigned int is_host_matchable:1;
unsigned int response_field_size_set:1;
unsigned int address_ttl_set:1;
apr_int32_t address_ttl; /* backend address' TTL (seconds) */
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
index 558af5cfab..1a11498f5d 100644
--- a/modules/proxy/proxy_util.c
+++ b/modules/proxy/proxy_util.c
@@ -1832,23 +1832,26 @@ static int ap_proxy_strcmp_ematch(const char *str, const char *expected)
return 0;
}
-static APR_INLINE
-int worker_matches(proxy_worker *worker,
- const char *url, apr_size_t url_len,
- apr_size_t min_match, apr_size_t *max_match,
- unsigned int mask)
+static int worker_matches(proxy_worker *worker,
+ const char *url, apr_size_t url_len,
+ apr_size_t min_match, apr_size_t *max_match,
+ unsigned int mask)
{
apr_size_t name_len = strlen(worker->s->name);
- int name_match = worker->s->is_name_matchable;
if (name_len <= url_len
- && name_len >= min_match
&& name_len > *max_match
- && ((name_match
- && (mask & AP_PROXY_WORKER_IS_MATCH)
- && !ap_proxy_strcmp_ematch(url, worker->s->name))
- || (!name_match
- && (mask & AP_PROXY_WORKER_IS_PREFIX)
- && !strncmp(url, worker->s->name, name_len)))) {
+ /* min_match is the length of the scheme://host part only of url,
+ * so it's used as a fast path to avoid the match when url is too
+ * small, but it's irrelevant when the worker host contains globs
+ * (i.e. ->is_host_matchable).
+ */
+ && (worker->s->is_name_matchable
+ ? ((mask & AP_PROXY_WORKER_IS_MATCH)
+ && (worker->s->is_host_matchable || name_len >= min_match)
+ && !ap_proxy_strcmp_ematch(url, worker->s->name))
+ : ((mask & AP_PROXY_WORKER_IS_PREFIX)
+ && (name_len >= min_match)
+ && !strncmp(url, worker->s->name, name_len)))) {
*max_match = name_len;
return 1;
}
@@ -2139,6 +2142,7 @@ PROXY_DECLARE(char *) ap_proxy_define_worker_ex(apr_pool_t *p,
wshared->was_malloced = (mask & AP_PROXY_WORKER_IS_MALLOCED) != 0;
if (mask & AP_PROXY_WORKER_IS_MATCH) {
wshared->is_name_matchable = 1;
+ wshared->is_host_matchable = (address_not_reusable != 0);
/* Before AP_PROXY_WORKER_IS_MATCH (< 2.4.47), a regex worker with
* dollar substitution was never matched against any actual URL, thus