diff --git a/changes-entries/bz69233.txt b/changes-entries/bz69233.txt new file mode 100644 index 00000000000..9e1e43bfd08 --- /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 2e63617271e..c124eb5370e 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -607,6 +607,7 @@ * and CONN_STATE_PROCESSING * 20120211.136 (2.4.63-dev) Add wait_io field to struct process_score * 20120211.137 (2.4.63-dev) Add AP_MPMQ_CAN_WAITIO + * 20120211.138 (2.4.63-dev) Add is_host_matchable to proxy_worker_shared */ #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */ @@ -614,7 +615,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20120211 #endif -#define MODULE_MAGIC_NUMBER_MINOR 137 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 138 /* 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 cd388898c14..329d10fdaa9 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -493,6 +493,7 @@ typedef struct { unsigned int address_ttl_set:1; apr_int32_t address_ttl; /* backend address' TTL (seconds) */ apr_uint32_t address_expiry; /* backend address' next expiry time */ + unsigned int is_host_matchable:1; } proxy_worker_shared; #define ALIGNED_PROXY_WORKER_SHARED_SIZE (APR_ALIGN_DEFAULT(sizeof(proxy_worker_shared))) diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index 005346acfa9..993533be6be 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -1826,23 +1826,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_ex); - 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_ex)) - || (!name_match - && (mask & AP_PROXY_WORKER_IS_PREFIX) - && !strncmp(url, worker->s->name_ex, 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_ex)) + : ((mask & AP_PROXY_WORKER_IS_PREFIX) + && (name_len >= min_match) + && !strncmp(url, worker->s->name_ex, name_len)))) { *max_match = name_len; return 1; } @@ -2132,6 +2135,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