summaryrefslogtreecommitdiffstats
path: root/debian/patches/CVE-2021-33193.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/CVE-2021-33193.patch')
-rw-r--r--debian/patches/CVE-2021-33193.patch702
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;
- }
-
- /**