diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-25 04:41:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-25 04:41:28 +0000 |
commit | 2eeb62e38ae17a3523ad3cd81c3de9f20f9e7742 (patch) | |
tree | fe91033d4712f6d836006b998525656b9dd193b8 /debian/patches/CVE-2021-33193.patch | |
parent | Merging upstream version 2.4.59. (diff) | |
download | apache2-2eeb62e38ae17a3523ad3cd81c3de9f20f9e7742.tar.xz apache2-2eeb62e38ae17a3523ad3cd81c3de9f20f9e7742.zip |
Adding debian version 2.4.59-1~deb10u1.debian/2.4.59-1_deb10u1debian
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'debian/patches/CVE-2021-33193.patch')
-rw-r--r-- | debian/patches/CVE-2021-33193.patch | 702 |
1 files changed, 0 insertions, 702 deletions
diff --git a/debian/patches/CVE-2021-33193.patch b/debian/patches/CVE-2021-33193.patch deleted file mode 100644 index d2737b8..0000000 --- a/debian/patches/CVE-2021-33193.patch +++ /dev/null @@ -1,702 +0,0 @@ -Description: Fix for CVE-2021-33193: mod_proxy HTTP/2 validation bypass - A crafted method sent through HTTP/2 will bypass validation and be forwarded by - mod_proxy, which can lead to request splitting or cache poisoning. -Origin: other, https://git.centos.org/rpms/httpd/blob/c496dea5e0b6e82a9f503e973fc5d5ea93a94180/f/SOURCES/httpd-2.4.37-CVE-2021-33193.patch -Forwarded: not-needed -Applied-Upstream: 2.4.49, https://github.com/apache/httpd/commit/ecebcc035ccd8d0e2984fe41420d9e944f456b3c -Last-Update: 2023-02-24 ---- -This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ ---- a/include/http_core.h -+++ b/include/http_core.h -@@ -741,6 +741,7 @@ - #define AP_HTTP_METHODS_REGISTERED 2 - char http_methods; - unsigned int merge_slashes; -+ unsigned int strict_host_check; - } core_server_config; - - /* for AddOutputFiltersByType in core.c */ -@@ -769,6 +770,11 @@ - typedef struct core_output_filter_ctx core_output_filter_ctx_t; - typedef struct core_filter_ctx core_ctx_t; - -+struct core_filter_ctx { -+ apr_bucket_brigade *b; -+ apr_bucket_brigade *tmpbb; -+}; -+ - typedef struct core_net_rec { - /** Connection to the client */ - apr_socket_t *client_socket; ---- a/include/http_protocol.h -+++ b/include/http_protocol.h -@@ -54,6 +54,13 @@ - */ - - /** -+ * Read an empty request and set reasonable defaults. -+ * @param c The current connection -+ * @return The new request_rec -+ */ -+AP_DECLARE(request_rec *) ap_create_request(conn_rec *c); -+ -+/** - * Read a request and fill in the fields. - * @param c The current connection - * @return The new request_rec -@@ -61,6 +68,20 @@ - request_rec *ap_read_request(conn_rec *c); - - /** -+ * Parse and validate the request line. -+ * @param r The current request -+ * @return 1 on success, 0 on failure -+ */ -+AP_DECLARE(int) ap_parse_request_line(request_rec *r); -+ -+/** -+ * Validate the request header and select vhost. -+ * @param r The current request -+ * @return 1 on success, 0 on failure -+ */ -+AP_DECLARE(int) ap_check_request_header(request_rec *r); -+ -+/** - * Read the mime-encoded headers. - * @param r The current request - */ ---- a/include/http_vhost.h -+++ b/include/http_vhost.h -@@ -100,6 +100,19 @@ - AP_DECLARE(void) ap_update_vhost_from_headers(request_rec *r); - - /** -+ * Updates r->server with the best name-based virtual host match, within -+ * the chain of matching virtual hosts selected by ap_update_vhost_given_ip. -+ * @param r The current request -+ * @param require_match 1 to return an HTTP error if the requested hostname is -+ * not explicitly matched to a VirtualHost. -+ * @return return HTTP_OK unless require_match was specified and the requested -+ * hostname did not match any ServerName, ServerAlias, or VirtualHost -+ * address-spec. -+ */ -+AP_DECLARE(int) ap_update_vhost_from_headers_ex(request_rec *r, int require_match); -+ -+ -+/** - * Match the host in the header with the hostname of the server for this - * request. - * @param r The current request ---- a/server/core.c -+++ b/server/core.c -@@ -494,6 +494,8 @@ - conf->protocols_honor_order = -1; - conf->merge_slashes = AP_CORE_CONFIG_UNSET; - -+ conf->strict_host_check= AP_CORE_CONFIG_UNSET; -+ - return (void *)conf; - } - -@@ -559,7 +561,13 @@ - base->protocols_honor_order : - virt->protocols_honor_order); - AP_CORE_MERGE_FLAG(merge_slashes, conf, base, virt); -- -+ -+ conf->strict_host_check = (virt->strict_host_check != AP_CORE_CONFIG_UNSET) -+ ? virt->strict_host_check -+ : base->strict_host_check; -+ -+ AP_CORE_MERGE_FLAG(strict_host_check, conf, base, virt); -+ - return conf; - } - -@@ -4518,7 +4526,10 @@ - AP_INIT_FLAG("QualifyRedirectURL", set_qualify_redirect_url, NULL, OR_FILEINFO, - "Controls whether HTTP authorization headers, normally hidden, will " - "be passed to scripts"), -- -+AP_INIT_FLAG("StrictHostCheck", set_core_server_flag, -+ (void *)APR_OFFSETOF(core_server_config, strict_host_check), -+ RSRC_CONF, -+ "Controls whether a hostname match is required"), - AP_INIT_TAKE1("ForceType", ap_set_string_slot_lower, - (void *)APR_OFFSETOF(core_dir_config, mime_type), OR_FILEINFO, - "a mime type that overrides other configured type"), -@@ -5492,4 +5503,3 @@ - core_cmds, /* command apr_table_t */ - register_hooks /* register hooks */ - }; -- ---- a/server/core_filters.c -+++ b/server/core_filters.c -@@ -84,11 +84,6 @@ - apr_size_t bytes_written; - }; - --struct core_filter_ctx { -- apr_bucket_brigade *b; -- apr_bucket_brigade *tmpbb; --}; -- - - apr_status_t ap_core_input_filter(ap_filter_t *f, apr_bucket_brigade *b, - ap_input_mode_t mode, apr_read_type_e block, ---- a/server/protocol.c -+++ b/server/protocol.c -@@ -611,8 +611,15 @@ - } - - r->args = r->parsed_uri.query; -- r->uri = r->parsed_uri.path ? r->parsed_uri.path -- : apr_pstrdup(r->pool, "/"); -+ if (r->parsed_uri.path) { -+ r->uri = r->parsed_uri.path; -+ } -+ else if (r->method_number == M_OPTIONS) { -+ r->uri = apr_pstrdup(r->pool, "*"); -+ } -+ else { -+ r->uri = apr_pstrdup(r->pool, "/"); -+ } - - #if defined(OS2) || defined(WIN32) - /* Handle path translations for OS/2 and plug security hole. -@@ -649,13 +656,6 @@ - - static int read_request_line(request_rec *r, apr_bucket_brigade *bb) - { -- enum { -- rrl_none, rrl_badmethod, rrl_badwhitespace, rrl_excesswhitespace, -- rrl_missinguri, rrl_baduri, rrl_badprotocol, rrl_trailingtext, -- rrl_badmethod09, rrl_reject09 -- } deferred_error = rrl_none; -- char *ll; -- char *uri; - apr_size_t len; - int num_blank_lines = DEFAULT_LIMIT_BLANK_LINES; - core_server_config *conf = ap_get_core_module_config(r->server->module_config); -@@ -720,6 +720,20 @@ - } - - r->request_time = apr_time_now(); -+ return 1; -+} -+ -+AP_DECLARE(int) ap_parse_request_line(request_rec *r) -+{ -+ core_server_config *conf = ap_get_core_module_config(r->server->module_config); -+ int strict = (conf->http_conformance != AP_HTTP_CONFORMANCE_UNSAFE); -+ enum { -+ rrl_none, rrl_badmethod, rrl_badwhitespace, rrl_excesswhitespace, -+ rrl_missinguri, rrl_baduri, rrl_badprotocol, rrl_trailingtext, -+ rrl_badmethod09, rrl_reject09 -+ } deferred_error = rrl_none; -+ apr_size_t len = 0; -+ char *uri, *ll; - - r->method = r->the_request; - -@@ -751,7 +765,6 @@ - if (deferred_error == rrl_none) - deferred_error = rrl_missinguri; - r->protocol = uri = ""; -- len = 0; - goto rrl_done; - } - else if (strict && ll[0] && apr_isspace(ll[1]) -@@ -782,7 +795,6 @@ - /* Verify URI terminated with a single SP, or mark as specific error */ - if (!ll) { - r->protocol = ""; -- len = 0; - goto rrl_done; - } - else if (strict && ll[0] && apr_isspace(ll[1]) -@@ -875,6 +887,14 @@ - r->header_only = 1; - - ap_parse_uri(r, uri); -+ if (r->status == HTTP_OK -+ && (r->parsed_uri.path != NULL) -+ && (r->parsed_uri.path[0] != '/') -+ && (r->method_number != M_OPTIONS -+ || strcmp(r->parsed_uri.path, "*") != 0)) { -+ /* Invalid request-target per RFC 7230 section 5.3 */ -+ r->status = HTTP_BAD_REQUEST; -+ } - - /* With the request understood, we can consider HTTP/0.9 specific errors */ - if (r->proto_num == HTTP_VERSION(0, 9) && deferred_error == rrl_none) { -@@ -982,6 +1002,79 @@ - return 0; - } - -+AP_DECLARE(int) ap_check_request_header(request_rec *r) -+{ -+ core_server_config *conf; -+ int strict_host_check; -+ const char *expect; -+ int access_status; -+ -+ conf = ap_get_core_module_config(r->server->module_config); -+ -+ /* update what we think the virtual host is based on the headers we've -+ * now read. may update status. -+ */ -+ strict_host_check = (conf->strict_host_check == AP_CORE_CONFIG_ON); -+ access_status = ap_update_vhost_from_headers_ex(r, strict_host_check); -+ if (strict_host_check && access_status != HTTP_OK) { -+ if (r->server == ap_server_conf) { -+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10156) -+ "Requested hostname '%s' did not match any ServerName/ServerAlias " -+ "in the global server configuration ", r->hostname); -+ } -+ else { -+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10157) -+ "Requested hostname '%s' did not match any ServerName/ServerAlias " -+ "in the matching virtual host (default vhost for " -+ "current connection is %s:%u)", -+ r->hostname, r->server->defn_name, r->server->defn_line_number); -+ } -+ r->status = access_status; -+ } -+ if (r->status != HTTP_OK) { -+ return 0; -+ } -+ -+ if ((!r->hostname && (r->proto_num >= HTTP_VERSION(1, 1))) -+ || ((r->proto_num == HTTP_VERSION(1, 1)) -+ && !apr_table_get(r->headers_in, "Host"))) { -+ /* -+ * Client sent us an HTTP/1.1 or later request without telling us the -+ * hostname, either with a full URL or a Host: header. We therefore -+ * need to (as per the 1.1 spec) send an error. As a special case, -+ * HTTP/1.1 mentions twice (S9, S14.23) that a request MUST contain -+ * a Host: header, and the server MUST respond with 400 if it doesn't. -+ */ -+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00569) -+ "client sent HTTP/1.1 request without hostname " -+ "(see RFC2616 section 14.23): %s", r->uri); -+ r->status = HTTP_BAD_REQUEST; -+ return 0; -+ } -+ -+ if (((expect = apr_table_get(r->headers_in, "Expect")) != NULL) -+ && (expect[0] != '\0')) { -+ /* -+ * The Expect header field was added to HTTP/1.1 after RFC 2068 -+ * as a means to signal when a 100 response is desired and, -+ * unfortunately, to signal a poor man's mandatory extension that -+ * the server must understand or return 417 Expectation Failed. -+ */ -+ if (ap_cstr_casecmp(expect, "100-continue") == 0) { -+ r->expecting_100 = 1; -+ } -+ else { -+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00570) -+ "client sent an unrecognized expectation value " -+ "of Expect: %s", expect); -+ r->status = HTTP_EXPECTATION_FAILED; -+ return 0; -+ } -+ } -+ -+ return 1; -+} -+ - static int table_do_fn_check_lengths(void *r_, const char *key, - const char *value) - { -@@ -1265,16 +1358,10 @@ - apr_brigade_destroy(tmp_bb); - } - --request_rec *ap_read_request(conn_rec *conn) -+AP_DECLARE(request_rec *) ap_create_request(conn_rec *conn) - { - request_rec *r; - apr_pool_t *p; -- const char *expect; -- int access_status; -- apr_bucket_brigade *tmp_bb; -- apr_socket_t *csd; -- apr_interval_time_t cur_timeout; -- - - apr_pool_create(&p, conn->pool); - apr_pool_tag(p, "request"); -@@ -1313,6 +1400,7 @@ - r->read_body = REQUEST_NO_BODY; - - r->status = HTTP_OK; /* Until further notice */ -+ r->header_only = 0; - r->the_request = NULL; - - /* Begin by presuming any module can make its own path_info assumptions, -@@ -1323,12 +1411,33 @@ - r->useragent_addr = conn->client_addr; - r->useragent_ip = conn->client_ip; - -+ return r; -+} -+ -+/* Apply the server's timeout/config to the connection/request. */ -+static void apply_server_config(request_rec *r) -+{ -+ apr_socket_t *csd; -+ -+ csd = ap_get_conn_socket(r->connection); -+ apr_socket_timeout_set(csd, r->server->timeout); -+ -+ r->per_dir_config = r->server->lookup_defaults; -+} -+ -+request_rec *ap_read_request(conn_rec *conn) -+{ -+ int access_status; -+ apr_bucket_brigade *tmp_bb; -+ -+ request_rec *r = ap_create_request(conn); - tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); - - ap_run_pre_read_request(r, conn); - - /* Get the request... */ -- if (!read_request_line(r, tmp_bb)) { -+ if (!read_request_line(r, tmp_bb) || !ap_parse_request_line(r)) { -+ apr_brigade_cleanup(tmp_bb); - switch (r->status) { - case HTTP_REQUEST_URI_TOO_LARGE: - case HTTP_BAD_REQUEST: -@@ -1344,49 +1453,38 @@ - "request failed: malformed request line"); - } - access_status = r->status; -- r->status = HTTP_OK; -- ap_die(access_status, r); -- ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r); -- ap_run_log_transaction(r); -- r = NULL; -- apr_brigade_destroy(tmp_bb); -- goto traceout; -+ goto die_unusable_input; -+ - case HTTP_REQUEST_TIME_OUT: -+ /* Just log, no further action on this connection. */ - ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, NULL); - if (!r->connection->keepalives) - ap_run_log_transaction(r); -- apr_brigade_destroy(tmp_bb); -- goto traceout; -- default: -- apr_brigade_destroy(tmp_bb); -- r = NULL; -- goto traceout; -+ break; - } -+ /* Not worth dying with. */ -+ conn->keepalive = AP_CONN_CLOSE; -+ apr_pool_destroy(r->pool); -+ goto ignore; - } -+ apr_brigade_cleanup(tmp_bb); - - /* We may have been in keep_alive_timeout mode, so toggle back - * to the normal timeout mode as we fetch the header lines, - * as necessary. - */ -- csd = ap_get_conn_socket(conn); -- apr_socket_timeout_get(csd, &cur_timeout); -- if (cur_timeout != conn->base_server->timeout) { -- apr_socket_timeout_set(csd, conn->base_server->timeout); -- cur_timeout = conn->base_server->timeout; -- } -+ apply_server_config(r); - - if (!r->assbackwards) { - const char *tenc; - - ap_get_mime_headers_core(r, tmp_bb); -+ apr_brigade_cleanup(tmp_bb); - if (r->status != HTTP_OK) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00567) - "request failed: error reading the headers"); -- ap_send_error_response(r, 0); -- ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r); -- ap_run_log_transaction(r); -- apr_brigade_destroy(tmp_bb); -- goto traceout; -+ access_status = r->status; -+ goto die_unusable_input; - } - - tenc = apr_table_get(r->headers_in, "Transfer-Encoding"); -@@ -1402,13 +1500,8 @@ - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02539) - "client sent unknown Transfer-Encoding " - "(%s): %s", tenc, r->uri); -- r->status = HTTP_BAD_REQUEST; -- conn->keepalive = AP_CONN_CLOSE; -- ap_send_error_response(r, 0); -- ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r); -- ap_run_log_transaction(r); -- apr_brigade_destroy(tmp_bb); -- goto traceout; -+ access_status = HTTP_BAD_REQUEST; -+ goto die_unusable_input; - } - - /* http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-23 -@@ -1421,88 +1514,81 @@ - } - } - -- apr_brigade_destroy(tmp_bb); -- -- /* update what we think the virtual host is based on the headers we've -- * now read. may update status. -- */ -- ap_update_vhost_from_headers(r); -- access_status = r->status; -- -- /* Toggle to the Host:-based vhost's timeout mode to fetch the -- * request body and send the response body, if needed. -- */ -- if (cur_timeout != r->server->timeout) { -- apr_socket_timeout_set(csd, r->server->timeout); -- cur_timeout = r->server->timeout; -- } -- -- /* we may have switched to another server */ -- r->per_dir_config = r->server->lookup_defaults; -- -- if ((!r->hostname && (r->proto_num >= HTTP_VERSION(1, 1))) -- || ((r->proto_num == HTTP_VERSION(1, 1)) -- && !apr_table_get(r->headers_in, "Host"))) { -- /* -- * Client sent us an HTTP/1.1 or later request without telling us the -- * hostname, either with a full URL or a Host: header. We therefore -- * need to (as per the 1.1 spec) send an error. As a special case, -- * HTTP/1.1 mentions twice (S9, S14.23) that a request MUST contain -- * a Host: header, and the server MUST respond with 400 if it doesn't. -- */ -- access_status = HTTP_BAD_REQUEST; -- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00569) -- "client sent HTTP/1.1 request without hostname " -- "(see RFC2616 section 14.23): %s", r->uri); -- } -- - /* - * Add the HTTP_IN filter here to ensure that ap_discard_request_body - * called by ap_die and by ap_send_error_response works correctly on - * status codes that do not cause the connection to be dropped and - * in situations where the connection should be kept alive. - */ -- - ap_add_input_filter_handle(ap_http_input_filter_handle, - NULL, r, r->connection); - -- if (access_status != HTTP_OK -- || (access_status = ap_post_read_request(r))) { -- ap_die(access_status, r); -- ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r); -- ap_run_log_transaction(r); -- r = NULL; -- goto traceout; -+ /* Validate Host/Expect headers and select vhost. */ -+ if (!ap_check_request_header(r)) { -+ /* we may have switched to another server still */ -+ apply_server_config(r); -+ access_status = r->status; -+ goto die_before_hooks; - } - -- if (((expect = apr_table_get(r->headers_in, "Expect")) != NULL) -- && (expect[0] != '\0')) { -- /* -- * The Expect header field was added to HTTP/1.1 after RFC 2068 -- * as a means to signal when a 100 response is desired and, -- * unfortunately, to signal a poor man's mandatory extension that -- * the server must understand or return 417 Expectation Failed. -- */ -- if (strcasecmp(expect, "100-continue") == 0) { -- r->expecting_100 = 1; -- } -- else { -- r->status = HTTP_EXPECTATION_FAILED; -- ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00570) -- "client sent an unrecognized expectation value of " -- "Expect: %s", expect); -- ap_send_error_response(r, 0); -- ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r); -- ap_run_log_transaction(r); -- goto traceout; -- } -+ /* we may have switched to another server */ -+ apply_server_config(r); -+ -+ if ((access_status = ap_run_post_read_request(r))) { -+ goto die; - } - -- AP_READ_REQUEST_SUCCESS((uintptr_t)r, (char *)r->method, (char *)r->uri, (char *)r->server->defn_name, r->status); -+ AP_READ_REQUEST_SUCCESS((uintptr_t)r, (char *)r->method, -+ (char *)r->uri, (char *)r->server->defn_name, -+ r->status); -+ - return r; -- traceout: -+ -+ /* Everything falls through on failure */ -+ -+die_unusable_input: -+ /* Input filters are in an undeterminate state, cleanup (including -+ * CORE_IN's socket) such that any further attempt to read is EOF. -+ */ -+ { -+ ap_filter_t *f = conn->input_filters; -+ while (f) { -+ if (f->frec == ap_core_input_filter_handle) { -+ core_net_rec *net = f->ctx; -+ apr_brigade_cleanup(net->in_ctx->b); -+ break; -+ } -+ ap_remove_input_filter(f); -+ f = f->next; -+ } -+ conn->input_filters = r->input_filters = f; -+ conn->keepalive = AP_CONN_CLOSE; -+ } -+ -+die_before_hooks: -+ /* First call to ap_die() (non recursive) */ -+ r->status = HTTP_OK; -+ -+die: -+ ap_die(access_status, r); -+ -+ /* ap_die() sent the response through the output filters, we must now -+ * end the request with an EOR bucket for stream/pipeline accounting. -+ */ -+ { -+ apr_bucket_brigade *eor_bb; -+ eor_bb = apr_brigade_create(conn->pool, conn->bucket_alloc); -+ APR_BRIGADE_INSERT_TAIL(eor_bb, -+ ap_bucket_eor_create(conn->bucket_alloc, r)); -+ ap_pass_brigade(conn->output_filters, eor_bb); -+ apr_brigade_cleanup(eor_bb); -+ } -+ -+ignore: -+ r = NULL; -+ - AP_READ_REQUEST_FAILURE((uintptr_t)r); -- return r; -+ return NULL; - } - - AP_DECLARE(int) ap_post_read_request(request_rec *r) ---- a/server/vhost.c -+++ b/server/vhost.c -@@ -34,6 +34,7 @@ - #include "http_vhost.h" - #include "http_protocol.h" - #include "http_core.h" -+#include "http_main.h" - - #if APR_HAVE_ARPA_INET_H - #include <arpa/inet.h> -@@ -973,7 +974,13 @@ - } - - --static void check_hostalias(request_rec *r) -+/* -+ * Updates r->server from ServerName/ServerAlias. Per the interaction -+ * of ip and name-based vhosts, it only looks in the best match from the -+ * connection-level ip-based matching. -+ * Returns HTTP_BAD_REQUEST if there was no match. -+ */ -+static int update_server_from_aliases(request_rec *r) - { - /* - * Even if the request has a Host: header containing a port we ignore -@@ -1050,11 +1057,18 @@ - goto found; - } - -- return; -+ if (!r->connection->vhost_lookup_data) { -+ if (matches_aliases(r->server, host)) { -+ s = r->server; -+ goto found; -+ } -+ } -+ return HTTP_BAD_REQUEST; - - found: - /* s is the first matching server, we're done */ - r->server = s; -+ return HTTP_OK; - } - - -@@ -1071,7 +1085,7 @@ - * This is in conjunction with the ServerPath code in http_core, so we - * get the right host attached to a non- Host-sending request. - * -- * See the comment in check_hostalias about how each vhost can be -+ * See the comment in update_server_from_aliases about how each vhost can be - * listed multiple times. - */ - -@@ -1135,10 +1149,16 @@ - - AP_DECLARE(void) ap_update_vhost_from_headers(request_rec *r) - { -+ ap_update_vhost_from_headers_ex(r, 0); -+} -+ -+AP_DECLARE(int) ap_update_vhost_from_headers_ex(request_rec *r, int require_match) -+{ - core_server_config *conf = ap_get_core_module_config(r->server->module_config); - const char *host_header = apr_table_get(r->headers_in, "Host"); - int is_v6literal = 0; - int have_hostname_from_url = 0; -+ int rc = HTTP_OK; - - if (r->hostname) { - /* -@@ -1151,8 +1171,8 @@ - else if (host_header != NULL) { - is_v6literal = fix_hostname(r, host_header, conf->http_conformance); - } -- if (r->status != HTTP_OK) -- return; -+ if (!require_match && r->status != HTTP_OK) -+ return HTTP_OK; - - if (conf->http_conformance != AP_HTTP_CONFORMANCE_UNSAFE) { - /* -@@ -1173,10 +1193,16 @@ - /* check if we tucked away a name_chain */ - if (r->connection->vhost_lookup_data) { - if (r->hostname) -- check_hostalias(r); -+ rc = update_server_from_aliases(r); - else - check_serverpath(r); - } -+ else if (require_match && r->hostname) { -+ /* check the base server config */ -+ rc = update_server_from_aliases(r); -+ } -+ -+ return rc; - } - - /** |