Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Step:15
apache2
apache2-CVE-2021-44224-1.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File apache2-CVE-2021-44224-1.patch of Package apache2
Index: httpd-2.4.33/modules/proxy/mod_proxy.c =================================================================== --- httpd-2.4.33.orig/modules/proxy/mod_proxy.c 2022-01-05 09:04:47.845745324 +0100 +++ httpd-2.4.33/modules/proxy/mod_proxy.c 2022-01-05 09:42:10.490493313 +0100 @@ -1724,7 +1724,8 @@ static const char * const apr_array_header_t *arr; const apr_table_entry_t *elts; int i; - int use_regex = is_regex; + unsigned int worker_type = (is_regex) ? AP_PROXY_WORKER_IS_MATCH + : AP_PROXY_WORKER_IS_PREFIX; unsigned int flags = 0; const char *err; @@ -1740,7 +1741,7 @@ static const char * if (is_regex) { return "ProxyPassMatch invalid syntax ('~' usage)."; } - use_regex = 1; + worker_type = AP_PROXY_WORKER_IS_MATCH; continue; } f = word; @@ -1791,7 +1792,7 @@ static const char * dconf->alias_set = 1; new = dconf->alias; if (apr_fnmatch_test(f)) { - use_regex = 1; + worker_type = AP_PROXY_WORKER_IS_MATCH; } } /* if per server, add to the alias array */ @@ -1802,7 +1803,7 @@ static const char * new->fake = apr_pstrdup(cmd->pool, f); new->real = apr_pstrdup(cmd->pool, ap_proxy_de_socketfy(cmd->pool, r)); new->flags = flags; - if (use_regex) { + if (worker_type & AP_PROXY_WORKER_IS_MATCH) { new->regex = ap_pregcomp(cmd->pool, f, AP_REG_EXTENDED); if (new->regex == NULL) return "Regular expression could not be compiled."; @@ -1826,7 +1827,7 @@ static const char * * cannot be parsed anyway with apr_uri_parse later on in * ap_proxy_define_balancer / ap_proxy_update_balancer */ - if (use_regex) { + if (worker_type & AP_PROXY_WORKER_IS_MATCH) { fake_copy = NULL; } else { @@ -1849,10 +1850,13 @@ static const char * new->balancer = balancer; } else { - proxy_worker *worker = ap_proxy_get_worker(cmd->temp_pool, NULL, conf, ap_proxy_de_socketfy(cmd->pool, r)); int reuse = 0; + proxy_worker *worker = ap_proxy_get_worker_ex(cmd->temp_pool, NULL, + conf, new->real, + worker_type); if (!worker) { - const char *err = ap_proxy_define_worker(cmd->pool, &worker, NULL, conf, r, 0); + const char *err = ap_proxy_define_worker_ex(cmd->pool, &worker, NULL, + conf, r, worker_type); if (err) return apr_pstrcat(cmd->temp_pool, "ProxyPass ", err, NULL); @@ -2329,7 +2333,8 @@ static const char *add_member(cmd_parms } /* Try to find existing worker */ - worker = ap_proxy_get_worker(cmd->temp_pool, balancer, conf, ap_proxy_de_socketfy(cmd->temp_pool, name)); + worker = ap_proxy_get_worker(cmd->temp_pool, balancer, conf, + ap_proxy_de_socketfy(cmd->temp_pool, name)); if (!worker) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, APLOGNO(01147) "Defining worker '%s' for balancer '%s'", @@ -2378,6 +2383,7 @@ static const char * char *word, *val; proxy_balancer *balancer = NULL; proxy_worker *worker = NULL; + unsigned int worker_type = 0; int in_proxy_section = 0; /* XXX: Should this be NOT_IN_DIRECTORY|NOT_IN_FILES? */ const char *err = ap_check_cmd_context(cmd, NOT_IN_HTACCESS); @@ -2394,6 +2400,13 @@ static const char * name = ap_getword_conf(cmd->temp_pool, &pargs); if ((word = ap_strchr(name, '>'))) *word = '\0'; + if (strncasecmp(cmd->directive->parent->directive + 6, + "Match", 5) == 0) { + worker_type = AP_PROXY_WORKER_IS_MATCH; + } + else { + worker_type = AP_PROXY_WORKER_IS_PREFIX; + } in_proxy_section = 1; } else { @@ -2418,11 +2431,13 @@ static const char * } } else { - worker = ap_proxy_get_worker(cmd->temp_pool, NULL, conf, ap_proxy_de_socketfy(cmd->temp_pool, name)); + worker = ap_proxy_get_worker_ex(cmd->temp_pool, NULL, conf, + ap_proxy_de_socketfy(cmd->temp_pool, name), + worker_type); if (!worker) { if (in_proxy_section) { - err = ap_proxy_define_worker(cmd->pool, &worker, NULL, - conf, name, 0); + err = ap_proxy_define_worker_ex(cmd->pool, &worker, NULL, + conf, name, worker_type); if (err) return apr_pstrcat(cmd->temp_pool, "ProxySet ", err, NULL); @@ -2477,6 +2492,7 @@ static const char *proxysection(cmd_parm proxy_balancer *balancer = NULL; proxy_worker *worker = NULL; + unsigned int worker_type = AP_PROXY_WORKER_IS_PREFIX; const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_CONTEXT); proxy_server_conf *sconf = (proxy_server_conf *) ap_get_module_config(cmd->server->module_config, &proxy_module); @@ -2514,6 +2530,8 @@ static const char *proxysection(cmd_parm if (!r) { return "Regex could not be compiled"; } + + worker_type = AP_PROXY_WORKER_IS_MATCH; } /* initialize our config and fetch it */ @@ -2560,11 +2578,12 @@ static const char *proxysection(cmd_parm } } else { - worker = ap_proxy_get_worker(cmd->temp_pool, NULL, sconf, - ap_proxy_de_socketfy(cmd->temp_pool, (char*)conf->p)); + worker = ap_proxy_get_worker_ex(cmd->temp_pool, NULL, sconf, + ap_proxy_de_socketfy(cmd->temp_pool, conf->p), + worker_type); if (!worker) { - err = ap_proxy_define_worker(cmd->pool, &worker, NULL, - sconf, conf->p, 0); + err = ap_proxy_define_worker_ex(cmd->pool, &worker, NULL, sconf, + conf->p, worker_type); if (err) return apr_pstrcat(cmd->temp_pool, thiscmd->name, " ", err, NULL); Index: httpd-2.4.33/modules/proxy/mod_proxy.h =================================================================== --- httpd-2.4.33.orig/modules/proxy/mod_proxy.h 2022-01-05 09:04:47.745744754 +0100 +++ httpd-2.4.33/modules/proxy/mod_proxy.h 2022-01-05 09:04:47.873745482 +0100 @@ -703,8 +703,29 @@ typedef __declspec(dllimport) const char PROXY_DECLARE(char *) ap_proxy_worker_name(apr_pool_t *p, proxy_worker *worker); +/* Bitmask for ap_proxy_{define,get}_worker_ex(). */ +#define AP_PROXY_WORKER_IS_PREFIX (1u << 0) +#define AP_PROXY_WORKER_IS_MATCH (1u << 1) +#define AP_PROXY_WORKER_IS_MALLOCED (1u << 2) + +/** + * Get the worker from proxy configuration, looking for either PREFIXED or + * MATCHED or both types of workers according to given mask + * @param p memory pool used for finding worker + * @param balancer the balancer that the worker belongs to + * @param conf current proxy server configuration + * @param url url to find the worker from + * @param mask bitmask of AP_PROXY_WORKER_IS_* + * @return proxy_worker or NULL if not found + */ +PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker_ex(apr_pool_t *p, + proxy_balancer *balancer, + proxy_server_conf *conf, + const char *url, + unsigned int mask); + /** - * Get the worker from proxy configuration + * Get the worker from proxy configuration, both types * @param p memory pool used for finding worker * @param balancer the balancer that the worker belongs to * @param conf current proxy server configuration @@ -715,7 +736,26 @@ PROXY_DECLARE(proxy_worker *) ap_proxy_g proxy_balancer *balancer, proxy_server_conf *conf, const char *url); + /** + * Define and Allocate space for the worker to proxy configuration, of either + * PREFIXED or MATCHED type according to given mask + * @param p memory pool to allocate worker from + * @param worker the new worker + * @param balancer the balancer that the worker belongs to + * @param conf current proxy server configuration + * @param url url containing worker name + * @param mask bitmask of AP_PROXY_WORKER_IS_* + * @return error message or NULL if successful (*worker is new worker) + */ +PROXY_DECLARE(char *) ap_proxy_define_worker_ex(apr_pool_t *p, + proxy_worker **worker, + proxy_balancer *balancer, + proxy_server_conf *conf, + const char *url, + unsigned int mask); + + /** * Define and Allocate space for the worker to proxy configuration * @param p memory pool to allocate worker from * @param worker the new worker @@ -724,6 +764,7 @@ PROXY_DECLARE(proxy_worker *) ap_proxy_g * @param url url containing worker name * @param do_malloc true if shared struct should be malloced * @return error message or NULL if successful (*worker is new worker) + * @deprecated Replaced by ap_proxy_define_worker_ex() */ PROXY_DECLARE(char *) ap_proxy_define_worker(apr_pool_t *p, proxy_worker **worker, Index: httpd-2.4.33/modules/proxy/proxy_util.c =================================================================== --- httpd-2.4.33.orig/modules/proxy/proxy_util.c 2022-01-05 09:04:47.845745324 +0100 +++ httpd-2.4.33/modules/proxy/proxy_util.c 2022-01-05 10:26:11.597464406 +0100 @@ -19,6 +19,7 @@ #include "ap_mpm.h" #include "scoreboard.h" #include "apr_version.h" +#include "apr_strings.h" #include "apr_hash.h" #include "proxy_util.h" #include "ajp.h" @@ -1503,10 +1504,11 @@ PROXY_DECLARE(char *) ap_proxy_worker_na return apr_pstrcat(p, "unix:", worker->s->uds_path, "|", worker->s->name, NULL); } -PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p, - proxy_balancer *balancer, - proxy_server_conf *conf, - const char *url) +PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker_ex(apr_pool_t *p, + proxy_balancer *balancer, + proxy_server_conf *conf, + const char *url, + unsigned int mask) { proxy_worker *worker; proxy_worker *max_worker = NULL; @@ -1532,6 +1534,11 @@ PROXY_DECLARE(proxy_worker *) ap_proxy_g url_length = strlen(url); url_copy = apr_pstrmemdup(p, url, url_length); + /* Default to lookup for both _PREFIX and _MATCH workers */ + if (!(mask & (AP_PROXY_WORKER_IS_PREFIX | AP_PROXY_WORKER_IS_MATCH))) { + mask |= AP_PROXY_WORKER_IS_PREFIX | AP_PROXY_WORKER_IS_MATCH; + } + /* * We need to find the start of the path and * therefore we know the length of the scheme://hostname/ @@ -1565,7 +1572,7 @@ PROXY_DECLARE(proxy_worker *) ap_proxy_g if ( ((worker_name_length = strlen(worker->s->name)) <= url_length) && (worker_name_length >= min_match) && (worker_name_length > max_match) - && (strncmp(url_copy, worker->s->name, worker_name_length) == 0) ) { + && ((mask & AP_PROXY_WORKER_IS_PREFIX) && strncmp(url_copy, worker->s->name, worker_name_length) == 0) ) { max_worker = worker; max_match = worker_name_length; } @@ -1577,7 +1584,7 @@ PROXY_DECLARE(proxy_worker *) ap_proxy_g if ( ((worker_name_length = strlen(worker->s->name)) <= url_length) && (worker_name_length >= min_match) && (worker_name_length > max_match) - && (strncmp(url_copy, worker->s->name, worker_name_length) == 0) ) { + && ((mask & AP_PROXY_WORKER_IS_PREFIX) && strncmp(url_copy, worker->s->name, worker_name_length) == 0) ) { max_worker = worker; max_match = worker_name_length; } @@ -1587,6 +1594,14 @@ PROXY_DECLARE(proxy_worker *) ap_proxy_g return max_worker; } +PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p, + proxy_balancer *balancer, + proxy_server_conf *conf, + const char *url) +{ + return ap_proxy_get_worker_ex(p, balancer, conf, url, 0); +} + /* * To create a worker from scratch first we define the * specifics of the worker; this is all local data. @@ -1594,46 +1609,86 @@ PROXY_DECLARE(proxy_worker *) ap_proxy_g * shared. This allows for dynamic addition during * config and runtime. */ -PROXY_DECLARE(char *) ap_proxy_define_worker(apr_pool_t *p, +PROXY_DECLARE(char *) ap_proxy_define_worker_ex(apr_pool_t *p, proxy_worker **worker, proxy_balancer *balancer, proxy_server_conf *conf, const char *url, - int do_malloc) + unsigned int mask) { - int rv; - apr_uri_t uri, urisock; + apr_status_t rv; proxy_worker_shared *wshared; - char *ptr, *sockpath = NULL; + const char *ptr = NULL, *sockpath = NULL, *pdollars = NULL; + apr_port_t port_of_scheme; + apr_uri_t uri; /* * Look to see if we are using UDS: * require format: unix:/path/foo/bar.sock|http://ignored/path2/ * This results in talking http to the socket at /path/foo/bar.sock */ - ptr = ap_strchr((char *)url, '|'); - if (ptr) { - *ptr = '\0'; - rv = apr_uri_parse(p, url, &urisock); - if (rv == APR_SUCCESS && !strcasecmp(urisock.scheme, "unix")) { - sockpath = ap_runtime_dir_relative(p, urisock.path);; - url = ptr+1; /* so we get the scheme for the uds */ + if (!ap_cstr_casecmpn(url, "unix:", 5) + && (ptr = ap_strchr_c(url + 5, '|'))) { + rv = apr_uri_parse(p, apr_pstrmemdup(p, url, ptr - url), &uri); + if (rv == APR_SUCCESS) { + sockpath = ap_runtime_dir_relative(p, uri.path);; + ptr++; /* so we get the scheme for the uds */ } else { - *ptr = '|'; + ptr = url; } } - rv = apr_uri_parse(p, url, &uri); + else { + ptr = url; + } + if (mask & AP_PROXY_WORKER_IS_MATCH) { + /* apr_uri_parse() will accept the '$' sign anywhere in the URL but + * in the :port part, and we don't want scheme://host:port$1$2/path + * to fail (e.g. "ProxyPassMatch ^/(a|b)(/.*)? http://host:port$2"). + * So we trim all the $n from the :port and prepend them in uri.path + * afterward for apr_uri_unparse() to restore the original URL below. + */ +#define IS_REF(x) (x[0] == '$' && apr_isdigit(x[1])) + const char *pos = ap_strstr_c(ptr, "://"); + if (pos) { + pos += 3; + while (*pos && *pos != ':' && *pos != '/') { + pos++; + } + if (*pos == ':') { + pos++; + while (*pos && !IS_REF(pos) && *pos != '/') { + pos++; + } + if (IS_REF(pos)) { + struct iovec vec[2]; + const char *path = pos + 2; + while (*path && *path != '/') { + path++; + } + pdollars = apr_pstrmemdup(p, pos, path - pos); + vec[0].iov_base = (void *)ptr; + vec[0].iov_len = pos - ptr; + vec[1].iov_base = (void *)path; + vec[1].iov_len = strlen(path); + ptr = apr_pstrcatv(p, vec, 2, NULL); + } + } + } +#undef IS_REF + } + /* Normalize the url (worker name) */ + rv = apr_uri_parse(p, ptr, &uri); if (rv != APR_SUCCESS) { return apr_pstrcat(p, "Unable to parse URL: ", url, NULL); } if (!uri.scheme) { return apr_pstrcat(p, "URL must be absolute!: ", url, NULL); } - /* allow for unix:/path|http: */ if (!uri.hostname) { if (sockpath) { + /* allow for unix:/path|http: */ uri.hostname = "localhost"; } else { @@ -1644,6 +1699,16 @@ PROXY_DECLARE(char *) ap_proxy_define_wo ap_str_tolower(uri.hostname); } ap_str_tolower(uri.scheme); + port_of_scheme = ap_proxy_port_of_scheme(uri.scheme); + if (uri.port && uri.port == port_of_scheme) { + uri.port = 0; + } + if (pdollars) { + /* Restore/prepend pdollars into the path. */ + uri.path = apr_pstrcat(p, pdollars, uri.path, NULL); + } + ptr = apr_uri_unparse(p, &uri, APR_URI_UNP_REVEALPASSWORD); + /* * Workers can be associated w/ balancers or on their * own; ie: the generic reverse-proxy or a worker @@ -1667,23 +1732,17 @@ PROXY_DECLARE(char *) ap_proxy_define_wo /* we need to allocate space here */ *worker = apr_palloc(p, sizeof(proxy_worker)); } - memset(*worker, 0, sizeof(proxy_worker)); + /* right here we just want to tuck away the worker info. * if called during config, we don't have shm setup yet, * so just note the info for later. */ - if (do_malloc) + if (mask & AP_PROXY_WORKER_IS_MALLOCED) wshared = ap_malloc(sizeof(proxy_worker_shared)); /* will be freed ap_proxy_share_worker */ else wshared = apr_palloc(p, sizeof(proxy_worker_shared)); - memset(wshared, 0, sizeof(proxy_worker_shared)); - wshared->port = (uri.port ? uri.port : ap_proxy_port_of_scheme(uri.scheme)); - if (uri.port && uri.port == ap_proxy_port_of_scheme(uri.scheme)) { - uri.port = 0; - } - ptr = apr_uri_unparse(p, &uri, APR_URI_UNP_REVEALPASSWORD); if (PROXY_STRNCPY(wshared->name, ptr) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02808) "Alert! worker name (%s) too long; truncated to: %s", ptr, wshared->name); @@ -1700,6 +1759,7 @@ PROXY_DECLARE(char *) ap_proxy_define_wo "worker hostname (%s) too long; truncated for legacy modules that do not use " "proxy_worker_shared->hostname_ex: %s", uri.hostname, wshared->hostname); } + wshared->port = (uri.port) ? uri.port : port_of_scheme; wshared->flush_packets = flush_off; wshared->flush_wait = PROXY_FLUSH_WAIT; wshared->is_address_reusable = 1; @@ -1710,7 +1770,7 @@ PROXY_DECLARE(char *) ap_proxy_define_wo wshared->smax = -1; wshared->hash.def = ap_proxy_hashfunc(wshared->name, PROXY_HASHFUNC_DEFAULT); wshared->hash.fnv = ap_proxy_hashfunc(wshared->name, PROXY_HASHFUNC_FNV); - wshared->was_malloced = (do_malloc != 0); + wshared->was_malloced = (mask & AP_PROXY_WORKER_IS_MALLOCED) != 0; if (sockpath) { if (PROXY_STRNCPY(wshared->uds_path, sockpath) != APR_SUCCESS) { return apr_psprintf(p, "worker uds path (%s) too long", sockpath); @@ -1730,9 +1790,37 @@ PROXY_DECLARE(char *) ap_proxy_define_wo (*worker)->balancer = balancer; (*worker)->s = wshared; + if (mask & AP_PROXY_WORKER_IS_MATCH) { + if (ap_strchr_c((*worker)->s->name, '$')) { + /* Before AP_PROXY_WORKER_IS_MATCH (< 2.4.47), a regex worker + * with dollar substitution was never matched against the actual + * URL thus the request fell through the generic worker. To avoid + * dns and connection reuse compat issues, let's disable connection + * reuse by default, it can still be overwritten by an explicit + * enablereuse=on. + */ + (*worker)->s->disablereuse = 1; + } + } + + return NULL; } +PROXY_DECLARE(char *) ap_proxy_define_worker(apr_pool_t *p, + proxy_worker **worker, + proxy_balancer *balancer, + proxy_server_conf *conf, + const char *url, + int do_malloc) +{ + return ap_proxy_define_worker_ex(p, worker, balancer, conf, url, + AP_PROXY_WORKER_IS_PREFIX | + (do_malloc ? AP_PROXY_WORKER_IS_MALLOCED + : 0)); +} + + /* * Create an already defined worker and free up memory */
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor