Package: release.debian.org Severity: normal User: release.debian....@packages.debian.org Usertags: unblock
Please unblock package apache2, it fixes various security issues (no other changes). Debdiff is attached unblock apache2/2.4.38-3
diff -Nru apache2-2.4.38/debian/changelog apache2-2.4.38/debian/changelog --- apache2-2.4.38/debian/changelog 2019-01-31 21:54:05.000000000 +0100 +++ apache2-2.4.38/debian/changelog 2019-04-07 20:15:40.000000000 +0200 @@ -1,3 +1,40 @@ +apache2 (2.4.38-3) unstable; urgency=high + + [ Marc Deslauriers ] + * SECURITY UPDATE: read-after-free on a string compare in mod_http2 + - debian/patches/CVE-2019-0196.patch: disentangelment of stream and + request method in modules/http2/h2_request.c. + - CVE-2019-0196 + * SECURITY UPDATE: privilege escalation from modules' scripts + - debian/patches/CVE-2019-0211.patch: bind the bucket number of each + child to its slot number in include/scoreboard.h, + server/mpm/event/event.c, server/mpm/prefork/prefork.c, + server/mpm/worker/worker.c. + - CVE-2019-0211 + * SECURITY UPDATE: mod_ssl access control bypass + - debian/patches/CVE-2019-0215.patch: restore SSL verify state after + PHA failure in TLSv1.3 in modules/ssl/ssl_engine_kernel.c. + - CVE-2019-0215 + * SECURITY UPDATE: mod_auth_digest access control bypass + - debian/patches/CVE-2019-0217.patch: fix a race condition in + modules/aaa/mod_auth_digest.c. + - CVE-2019-0217 + * SECURITY UPDATE: URL normalization inconsistincy + - debian/patches/CVE-2019-0220-1.patch: merge consecutive slashes in + the path in include/http_core.h, include/httpd.h, server/core.c, + server/request.c, server/util.c. + - debian/patches/CVE-2019-0220-2.patch: fix r->parsed_uri.path safety + in server/request.c, server/util.c. + - debian/patches/CVE-2019-0220-3.patch: maintainer mode fix in + server/util.c. + - CVE-2019-0220 + + [ Stefan Fritsch ] + * Pull security fixes from 2.4.39 via Ubuntu + * CVE-2019-0197: mod_http2: Fix possible crash on late upgrade + + -- Stefan Fritsch <s...@debian.org> Sun, 07 Apr 2019 20:15:40 +0200 + apache2 (2.4.38-2) unstable; urgency=medium * Disable "reset" test in allowmethods.t (Closes: #921024) diff -Nru apache2-2.4.38/debian/patches/CVE-2019-0196.patch apache2-2.4.38/debian/patches/CVE-2019-0196.patch --- apache2-2.4.38/debian/patches/CVE-2019-0196.patch 1970-01-01 01:00:00.000000000 +0100 +++ apache2-2.4.38/debian/patches/CVE-2019-0196.patch 2019-04-07 19:37:55.000000000 +0200 @@ -0,0 +1,27 @@ +From 8de3c6f2a0df79d1476c89ec480a96f9282cea28 Mon Sep 17 00:00:00 2001 +From: Stefan Eissing <ic...@apache.org> +Date: Tue, 5 Feb 2019 11:52:28 +0000 +Subject: [PATCH] Merge of r1852986 from trunk: + +mod_http2: disentangelment of stream and request method. + + + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1852989 13f79535-47bb-0310-9956-ffa450edef68 +--- + modules/http2/h2_request.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/modules/http2/h2_request.c b/modules/http2/h2_request.c +index 8899c4feb75..5ee88e9679f 100644 +--- a/modules/http2/h2_request.c ++++ b/modules/http2/h2_request.c +@@ -266,7 +266,7 @@ request_rec *h2_request_create_rec(const h2_request *req, conn_rec *c) + + /* Time to populate r with the data we have. */ + r->request_time = req->request_time; +- r->method = req->method; ++ r->method = apr_pstrdup(r->pool, req->method); + /* Provide quick information about the request method as soon as known */ + r->method_number = ap_method_number_of(r->method); + if (r->method_number == M_GET && r->method[0] == 'H') { diff -Nru apache2-2.4.38/debian/patches/CVE-2019-0197.patch apache2-2.4.38/debian/patches/CVE-2019-0197.patch --- apache2-2.4.38/debian/patches/CVE-2019-0197.patch 1970-01-01 01:00:00.000000000 +0100 +++ apache2-2.4.38/debian/patches/CVE-2019-0197.patch 2019-04-07 19:49:17.000000000 +0200 @@ -0,0 +1,93 @@ +# https://svn.apache.org/r1855406 +--- apache2.orig/modules/http2/h2_conn.c ++++ apache2/modules/http2/h2_conn.c +@@ -305,6 +305,10 @@ conn_rec *h2_slave_create(conn_rec *mast + c->notes = apr_table_make(pool, 5); + c->input_filters = NULL; + c->output_filters = NULL; ++ c->keepalives = 0; ++#if AP_MODULE_MAGIC_AT_LEAST(20180903, 1) ++ c->filter_conn_ctx = NULL; ++#endif + c->bucket_alloc = apr_bucket_alloc_create(pool); + c->data_in_input_filters = 0; + c->data_in_output_filters = 0; +@@ -332,16 +336,15 @@ conn_rec *h2_slave_create(conn_rec *mast + ap_set_module_config(c->conn_config, mpm, cfg); + } + +- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, +- "h2_stream(%ld-%d): created slave", master->id, slave_id); ++ ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c, ++ "h2_slave(%s): created", c->log_id); + return c; + } + + void h2_slave_destroy(conn_rec *slave) + { +- ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, slave, +- "h2_stream(%s): destroy slave", +- apr_table_get(slave->notes, H2_TASK_ID_NOTE)); ++ ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, slave, ++ "h2_slave(%s): destroy", slave->log_id); + slave->sbh = NULL; + apr_pool_destroy(slave->pool); + } +@@ -365,6 +368,7 @@ apr_status_t h2_slave_run_pre_connection + slave->keepalive = AP_CONN_CLOSE; + return ap_run_pre_connection(slave, csd); + } ++ ap_assert(slave->output_filters); + return APR_SUCCESS; + } + +--- apache2.orig/modules/http2/h2_mplx.c ++++ apache2/modules/http2/h2_mplx.c +@@ -327,7 +327,8 @@ static int stream_destroy_iter(void *ctx + && !task->rst_error); + } + +- if (reuse_slave && slave->keepalive == AP_CONN_KEEPALIVE) { ++ task->c = NULL; ++ if (reuse_slave) { + h2_beam_log(task->output.beam, m->c, APLOG_DEBUG, + APLOGNO(03385) "h2_task_destroy, reuse slave"); + h2_task_destroy(task); +@@ -437,6 +438,8 @@ void h2_mplx_release_and_join(h2_mplx *m + apr_status_t status; + int i, wait_secs = 60; + ++ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c, ++ "h2_mplx(%ld): start release", m->id); + /* How to shut down a h2 connection: + * 0. abort and tell the workers that no more tasks will come from us */ + m->aborted = 1; +@@ -977,6 +980,9 @@ static apr_status_t unschedule_slow_task + */ + n = (m->tasks_active - m->limit_active - (int)h2_ihash_count(m->sredo)); + while (n > 0 && (stream = get_latest_repeatable_unsubmitted_stream(m))) { ++ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, m->c, ++ "h2_mplx(%s): unschedule, resetting task for redo later", ++ stream->task->id); + h2_task_rst(stream->task, H2_ERR_CANCEL); + h2_ihash_add(m->sredo, stream); + --n; +--- apache2.orig/modules/http2/h2_task.c ++++ apache2/modules/http2/h2_task.c +@@ -504,7 +504,7 @@ static int h2_task_pre_conn(conn_rec* c, + (void)arg; + if (h2_ctx_is_task(ctx)) { + ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, +- "h2_h2, pre_connection, found stream task"); ++ "h2_slave(%s), pre_connection, adding filters", c->log_id); + ap_add_input_filter("H2_SLAVE_IN", NULL, NULL, c); + ap_add_output_filter("H2_PARSE_H1", NULL, NULL, c); + ap_add_output_filter("H2_SLAVE_OUT", NULL, NULL, c); +@@ -545,7 +545,6 @@ h2_task *h2_task_create(conn_rec *slave, + void h2_task_destroy(h2_task *task) + { + if (task->output.beam) { +- h2_beam_log(task->output.beam, task->c, APLOG_TRACE2, "task_destroy"); + h2_beam_destroy(task->output.beam); + task->output.beam = NULL; + } diff -Nru apache2-2.4.38/debian/patches/CVE-2019-0211.patch apache2-2.4.38/debian/patches/CVE-2019-0211.patch --- apache2-2.4.38/debian/patches/CVE-2019-0211.patch 1970-01-01 01:00:00.000000000 +0100 +++ apache2-2.4.38/debian/patches/CVE-2019-0211.patch 2019-04-07 19:37:55.000000000 +0200 @@ -0,0 +1,249 @@ +From df7edb5ddae609ea1fd4285f7439f0d590d97b37 Mon Sep 17 00:00:00 2001 +From: Yann Ylavic <yla...@apache.org> +Date: Wed, 13 Mar 2019 08:59:54 +0000 +Subject: [PATCH] Merge r1855306 from trunk: + +MPMs unix: bind the bucket number of each child to its slot number + +We need not remember each child's bucket number in SHM for restarts, for the +lifetime of the httpd main process the bucket number can be bound to the slot +number such that: bucket = slot % num_buckets. + +This both simplifies the logic and helps children maintenance per bucket in +threaded MPMs, where previously perform_idle_server_maintenance() could create +or kill children processes for the buckets it was not in charge of. + +Submitted by: ylavic +Reviewed by: ylavic, rpluem, jorton + + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1855378 13f79535-47bb-0310-9956-ffa450edef68 +--- + CHANGES | 3 +++ + include/scoreboard.h | 4 +++- + server/mpm/event/event.c | 13 ++++++++----- + server/mpm/prefork/prefork.c | 19 +++++++------------ + server/mpm/worker/worker.c | 10 ++++++---- + 5 files changed, 27 insertions(+), 22 deletions(-) + +#diff --git a/CHANGES b/CHANGES +#index e79251389d5..6b560802119 100644 +#--- a/CHANGES +#+++ b/CHANGES +#@@ -1,6 +1,9 @@ +# -*- coding: utf-8 -*- +# Changes with Apache 2.4.39 +# +#+ *) MPMs unix: bind the bucket number of each child to its slot number, for a +#+ more efficient per bucket maintenance. [Yann Ylavic] +#+ +# *) mod_auth_digest: Fix a race condition. Authentication with valid +# credentials could be refused in case of concurrent accesses from +# different users. PR 63124. [Simon Kappel <simon.kappel axis.com>] +diff --git a/include/scoreboard.h b/include/scoreboard.h +index 9376da246b0..92d198d6de1 100644 +--- a/include/scoreboard.h ++++ b/include/scoreboard.h +@@ -148,7 +148,9 @@ struct process_score { + apr_uint32_t lingering_close; /* async connections in lingering close */ + apr_uint32_t keep_alive; /* async connections in keep alive */ + apr_uint32_t suspended; /* connections suspended by some module */ +- int bucket; /* Listener bucket used by this child */ ++ int bucket; /* Listener bucket used by this child; this field is DEPRECATED ++ * and no longer updated by the MPMs (i.e. always zero). ++ */ + }; + + /* Scoreboard is now in 'local' memory, since it isn't updated once created, +diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c +index 4cfb09c5b28..5e5af339adc 100644 +--- a/server/mpm/event/event.c ++++ b/server/mpm/event/event.c +@@ -2696,7 +2696,6 @@ static int make_child(server_rec * s, int slot, int bucket) + + ap_scoreboard_image->parent[slot].quiescing = 0; + ap_scoreboard_image->parent[slot].not_accepting = 0; +- ap_scoreboard_image->parent[slot].bucket = bucket; + event_note_child_started(slot, pid); + active_daemons++; + retained->total_daemons++; +@@ -2735,6 +2734,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets) + * that threads_per_child is always > 0 */ + int status = SERVER_DEAD; + int child_threads_active = 0; ++ int bucket = i % num_buckets; + + if (i >= retained->max_daemons_limit && + free_length == retained->idle_spawn_rate[child_bucket]) { +@@ -2758,7 +2758,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets) + */ + if (status <= SERVER_READY && !ps->quiescing && !ps->not_accepting + && ps->generation == retained->mpm->my_generation +- && ps->bucket == child_bucket) ++ && bucket == child_bucket) + { + ++idle_thread_count; + } +@@ -2769,7 +2769,9 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets) + last_non_dead = i; + } + active_thread_count += child_threads_active; +- if (!ps->pid && free_length < retained->idle_spawn_rate[child_bucket]) ++ if (!ps->pid ++ && bucket == child_bucket ++ && free_length < retained->idle_spawn_rate[child_bucket]) + free_slots[free_length++] = i; + else if (child_threads_active == threads_per_child) + had_healthy_child = 1; +@@ -2962,13 +2964,14 @@ static void server_main_loop(int remaining_children_to_start, int num_buckets) + retained->total_daemons--; + if (processed_status == APEXIT_CHILDSICK) { + /* resource shortage, minimize the fork rate */ +- retained->idle_spawn_rate[ps->bucket] = 1; ++ retained->idle_spawn_rate[child_slot % num_buckets] = 1; + } + else if (remaining_children_to_start) { + /* we're still doing a 1-for-1 replacement of dead + * children with new children + */ +- make_child(ap_server_conf, child_slot, ps->bucket); ++ make_child(ap_server_conf, child_slot, ++ child_slot % num_buckets); + --remaining_children_to_start; + } + } +diff --git a/server/mpm/prefork/prefork.c b/server/mpm/prefork/prefork.c +index 8efda72ee18..7c006257301 100644 +--- a/server/mpm/prefork/prefork.c ++++ b/server/mpm/prefork/prefork.c +@@ -637,8 +637,9 @@ static void child_main(int child_num_arg, int child_bucket) + } + + +-static int make_child(server_rec *s, int slot, int bucket) ++static int make_child(server_rec *s, int slot) + { ++ int bucket = slot % retained->mpm->num_buckets; + int pid; + + if (slot + 1 > retained->max_daemons_limit) { +@@ -716,7 +717,6 @@ static int make_child(server_rec *s, int slot, int bucket) + child_main(slot, bucket); + } + +- ap_scoreboard_image->parent[slot].bucket = bucket; + prefork_note_child_started(slot, pid); + + return 0; +@@ -732,7 +732,7 @@ static void startup_children(int number_to_start) + if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) { + continue; + } +- if (make_child(ap_server_conf, i, i % retained->mpm->num_buckets) < 0) { ++ if (make_child(ap_server_conf, i) < 0) { + break; + } + --number_to_start; +@@ -741,8 +741,6 @@ static void startup_children(int number_to_start) + + static void perform_idle_server_maintenance(apr_pool_t *p) + { +- static int bucket_make_child_record = -1; +- static int bucket_kill_child_record = -1; + int i; + int idle_count; + worker_score *ws; +@@ -789,6 +787,7 @@ static void perform_idle_server_maintenance(apr_pool_t *p) + } + retained->max_daemons_limit = last_non_dead + 1; + if (idle_count > ap_daemons_max_free) { ++ static int bucket_kill_child_record = -1; + /* kill off one child... we use the pod because that'll cause it to + * shut down gracefully, in case it happened to pick up a request + * while we were counting +@@ -819,10 +818,7 @@ static void perform_idle_server_maintenance(apr_pool_t *p) + idle_count, total_non_dead); + } + for (i = 0; i < free_length; ++i) { +- bucket_make_child_record++; +- bucket_make_child_record %= retained->mpm->num_buckets; +- make_child(ap_server_conf, free_slots[i], +- bucket_make_child_record); ++ make_child(ap_server_conf, free_slots[i]); + } + /* the next time around we want to spawn twice as many if this + * wasn't good enough, but not if we've just done a graceful +@@ -867,7 +863,7 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) + + if (one_process) { + AP_MONCONTROL(1); +- make_child(ap_server_conf, 0, 0); ++ make_child(ap_server_conf, 0); + /* NOTREACHED */ + ap_assert(0); + return !OK; +@@ -976,8 +972,7 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s) + /* we're still doing a 1-for-1 replacement of dead + * children with new children + */ +- make_child(ap_server_conf, child_slot, +- ap_get_scoreboard_process(child_slot)->bucket); ++ make_child(ap_server_conf, child_slot); + --remaining_children_to_start; + } + #if APR_HAS_OTHER_CHILD +diff --git a/server/mpm/worker/worker.c b/server/mpm/worker/worker.c +index 8012fe29d8d..a92794245c5 100644 +--- a/server/mpm/worker/worker.c ++++ b/server/mpm/worker/worker.c +@@ -1339,7 +1339,6 @@ static int make_child(server_rec *s, int slot, int bucket) + worker_note_child_lost_slot(slot, pid); + } + ap_scoreboard_image->parent[slot].quiescing = 0; +- ap_scoreboard_image->parent[slot].bucket = bucket; + worker_note_child_started(slot, pid); + return 0; + } +@@ -1388,6 +1387,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets) + int any_dead_threads = 0; + int all_dead_threads = 1; + int child_threads_active = 0; ++ int bucket = i % num_buckets; + + if (i >= retained->max_daemons_limit && + totally_free_length == retained->idle_spawn_rate[child_bucket]) { +@@ -1420,7 +1420,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets) + if (status <= SERVER_READY && + !ps->quiescing && + ps->generation == retained->mpm->my_generation && +- ps->bucket == child_bucket) { ++ bucket == child_bucket) { + ++idle_thread_count; + } + if (status >= SERVER_READY && status < SERVER_GRACEFUL) { +@@ -1430,6 +1430,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets) + } + active_thread_count += child_threads_active; + if (any_dead_threads ++ && bucket == child_bucket + && totally_free_length < retained->idle_spawn_rate[child_bucket] + && free_length < MAX_SPAWN_RATE / num_buckets + && (!ps->pid /* no process in the slot */ +@@ -1615,14 +1616,15 @@ static void server_main_loop(int remaining_children_to_start, int num_buckets) + ps->quiescing = 0; + if (processed_status == APEXIT_CHILDSICK) { + /* resource shortage, minimize the fork rate */ +- retained->idle_spawn_rate[ps->bucket] = 1; ++ retained->idle_spawn_rate[child_slot % num_buckets] = 1; + } + else if (remaining_children_to_start + && child_slot < ap_daemons_limit) { + /* we're still doing a 1-for-1 replacement of dead + * children with new children + */ +- make_child(ap_server_conf, child_slot, ps->bucket); ++ make_child(ap_server_conf, child_slot, ++ child_slot % num_buckets); + --remaining_children_to_start; + } + } diff -Nru apache2-2.4.38/debian/patches/CVE-2019-0215.patch apache2-2.4.38/debian/patches/CVE-2019-0215.patch --- apache2-2.4.38/debian/patches/CVE-2019-0215.patch 1970-01-01 01:00:00.000000000 +0100 +++ apache2-2.4.38/debian/patches/CVE-2019-0215.patch 2019-04-07 19:37:55.000000000 +0200 @@ -0,0 +1,52 @@ +From 84edf5f49db23ced03259812bbf9426685f7d82a Mon Sep 17 00:00:00 2001 +From: Joe Orton <jor...@apache.org> +Date: Wed, 20 Mar 2019 15:45:16 +0000 +Subject: [PATCH] Merge r1855849 from trunk: + +* modules/ssl/ssl_engine_kernel.c (ssl_hook_Access_modern): Correctly + restore SSL verify state after PHA failure in TLSv1.3. + +Submitted by: Michael Kaufmann <mail michael-kaufmann.ch> +Reviewed by: jorton, covener, jim + + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1855917 13f79535-47bb-0310-9956-ffa450edef68 +--- + CHANGES | 3 +++ + modules/ssl/ssl_engine_kernel.c | 2 ++ + 2 files changed, 5 insertions(+) + +#diff --git a/CHANGES b/CHANGES +#index 6b03eadfa07..6f20d688ece 100644 +#--- a/CHANGES +#+++ b/CHANGES +#@@ -1,6 +1,9 @@ +# -*- coding: utf-8 -*- +# Changes with Apache 2.4.39 +# +#+ *) mod_ssl: Correctly restore SSL verify state after TLSv1.3 PHA failure. +#+ [Michael Kaufmann <mail michael-kaufmann.ch>] +#+ +# *) mod_log_config: Support %{c}h for conn-hostname, %h for useragent_host +# PR 55348 +# +Index: apache2-2.4.38/modules/ssl/ssl_engine_kernel.c +=================================================================== +--- apache2-2.4.38.orig/modules/ssl/ssl_engine_kernel.c 2019-04-03 14:31:14.279214679 -0400 ++++ apache2-2.4.38/modules/ssl/ssl_engine_kernel.c 2019-04-03 14:31:14.279214679 -0400 +@@ -1154,6 +1154,7 @@ static int ssl_hook_Access_modern(reques + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, r->server); + apr_table_setn(r->notes, "error-notes", + "Reason: Cannot perform Post-Handshake Authentication.<br />"); ++ SSL_set_verify(ssl, vmode_inplace, NULL); + return HTTP_FORBIDDEN; + } + +@@ -1175,6 +1176,7 @@ static int ssl_hook_Access_modern(reques + * Finally check for acceptable renegotiation results + */ + if (OK != (rc = ssl_check_post_client_verify(r, sc, dc, sslconn, ssl))) { ++ SSL_set_verify(ssl, vmode_inplace, NULL); + return rc; + } + } diff -Nru apache2-2.4.38/debian/patches/CVE-2019-0217.patch apache2-2.4.38/debian/patches/CVE-2019-0217.patch --- apache2-2.4.38/debian/patches/CVE-2019-0217.patch 1970-01-01 01:00:00.000000000 +0100 +++ apache2-2.4.38/debian/patches/CVE-2019-0217.patch 2019-04-07 19:37:55.000000000 +0200 @@ -0,0 +1,147 @@ +From 44b3ddc560c490c60600998fa2bf59b142d08e05 Mon Sep 17 00:00:00 2001 +From: Joe Orton <jor...@apache.org> +Date: Tue, 12 Mar 2019 09:24:26 +0000 +Subject: [PATCH] Merge r1853190 from trunk: + +Fix a race condition. Authentication with valid credentials could be +refused in case of concurrent accesses from different users. + +PR: 63124 +Submitted by: Simon Kappel <simon.kappel axis.com> +Reviewed by: jailletc36, icing, jorton + + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1855298 13f79535-47bb-0310-9956-ffa450edef68 +--- + CHANGES | 4 ++++ + modules/aaa/mod_auth_digest.c | 26 ++++++++++++-------------- + 2 files changed, 16 insertions(+), 14 deletions(-) + +#diff --git a/CHANGES b/CHANGES +#index 08fc740db30..e79251389d5 100644 +#--- a/CHANGES +#+++ b/CHANGES +#@@ -1,6 +1,10 @@ +# -*- coding: utf-8 -*- +# Changes with Apache 2.4.39 +# +#+ *) mod_auth_digest: Fix a race condition. Authentication with valid +#+ credentials could be refused in case of concurrent accesses from +#+ different users. PR 63124. [Simon Kappel <simon.kappel axis.com>] +#+ +# *) mod_proxy_wstunnel: Fix websocket proxy over UDS. +# PR 62932 <pavel dcmsys.com> +# +diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c +index a67f06986f2..b76094114dd 100644 +--- a/modules/aaa/mod_auth_digest.c ++++ b/modules/aaa/mod_auth_digest.c +@@ -92,7 +92,6 @@ typedef struct digest_config_struct { + int check_nc; + const char *algorithm; + char *uri_list; +- const char *ha1; + } digest_config_rec; + + +@@ -153,6 +152,7 @@ typedef struct digest_header_struct { + apr_time_t nonce_time; + enum hdr_sts auth_hdr_sts; + int needed_auth; ++ const char *ha1; + client_entry *client; + } digest_header_rec; + +@@ -1304,7 +1304,7 @@ static int hook_note_digest_auth_failure(request_rec *r, const char *auth_type) + */ + + static authn_status get_hash(request_rec *r, const char *user, +- digest_config_rec *conf) ++ digest_config_rec *conf, const char **rethash) + { + authn_status auth_result; + char *password; +@@ -1356,7 +1356,7 @@ static authn_status get_hash(request_rec *r, const char *user, + } while (current_provider); + + if (auth_result == AUTH_USER_FOUND) { +- conf->ha1 = password; ++ *rethash = password; + } + + return auth_result; +@@ -1483,25 +1483,24 @@ static int check_nonce(request_rec *r, digest_header_rec *resp, + + /* RFC-2069 */ + static const char *old_digest(const request_rec *r, +- const digest_header_rec *resp, const char *ha1) ++ const digest_header_rec *resp) + { + const char *ha2; + + ha2 = ap_md5(r->pool, (unsigned char *)apr_pstrcat(r->pool, resp->method, ":", + resp->uri, NULL)); + return ap_md5(r->pool, +- (unsigned char *)apr_pstrcat(r->pool, ha1, ":", resp->nonce, +- ":", ha2, NULL)); ++ (unsigned char *)apr_pstrcat(r->pool, resp->ha1, ":", ++ resp->nonce, ":", ha2, NULL)); + } + + /* RFC-2617 */ + static const char *new_digest(const request_rec *r, +- digest_header_rec *resp, +- const digest_config_rec *conf) ++ digest_header_rec *resp) + { + const char *ha1, *ha2, *a2; + +- ha1 = conf->ha1; ++ ha1 = resp->ha1; + + a2 = apr_pstrcat(r->pool, resp->method, ":", resp->uri, NULL); + ha2 = ap_md5(r->pool, (const unsigned char *)a2); +@@ -1514,7 +1513,6 @@ static const char *new_digest(const request_rec *r, + NULL)); + } + +- + static void copy_uri_components(apr_uri_t *dst, + apr_uri_t *src, request_rec *r) { + if (src->scheme && src->scheme[0] != '\0') { +@@ -1759,7 +1757,7 @@ static int authenticate_digest_user(request_rec *r) + return HTTP_UNAUTHORIZED; + } + +- return_code = get_hash(r, r->user, conf); ++ return_code = get_hash(r, r->user, conf, &resp->ha1); + + if (return_code == AUTH_USER_NOT_FOUND) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01790) +@@ -1789,7 +1787,7 @@ static int authenticate_digest_user(request_rec *r) + + if (resp->message_qop == NULL) { + /* old (rfc-2069) style digest */ +- if (strcmp(resp->digest, old_digest(r, resp, conf->ha1))) { ++ if (strcmp(resp->digest, old_digest(r, resp))) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01792) + "user %s: password mismatch: %s", r->user, + r->uri); +@@ -1819,7 +1817,7 @@ static int authenticate_digest_user(request_rec *r) + return HTTP_UNAUTHORIZED; + } + +- exp_digest = new_digest(r, resp, conf); ++ exp_digest = new_digest(r, resp); + if (!exp_digest) { + /* we failed to allocate a client struct */ + return HTTP_INTERNAL_SERVER_ERROR; +@@ -1903,7 +1901,7 @@ static int add_auth_info(request_rec *r) + + /* calculate rspauth attribute + */ +- ha1 = conf->ha1; ++ ha1 = resp->ha1; + + a2 = apr_pstrcat(r->pool, ":", resp->uri, NULL); + ha2 = ap_md5(r->pool, (const unsigned char *)a2); diff -Nru apache2-2.4.38/debian/patches/CVE-2019-0220-1.patch apache2-2.4.38/debian/patches/CVE-2019-0220-1.patch --- apache2-2.4.38/debian/patches/CVE-2019-0220-1.patch 1970-01-01 01:00:00.000000000 +0100 +++ apache2-2.4.38/debian/patches/CVE-2019-0220-1.patch 2019-04-07 19:37:55.000000000 +0200 @@ -0,0 +1,278 @@ +From 9bc1917a27a2323e535aadb081e38172ae0e3fc2 Mon Sep 17 00:00:00 2001 +From: Stefan Eissing <ic...@apache.org> +Date: Mon, 18 Mar 2019 08:49:59 +0000 +Subject: [PATCH] Merge of r1855705 from trunk: + +core: merge consecutive slashes in the path + + + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1855737 13f79535-47bb-0310-9956-ffa450edef68 +--- + CHANGES | 4 ++++ + docs/manual/mod/core.xml | 26 ++++++++++++++++++++++++++ + include/ap_mmn.h | 4 +++- + include/http_core.h | 2 +- + include/httpd.h | 14 ++++++++++++-- + server/core.c | 13 +++++++++++++ + server/request.c | 25 +++++++++---------------- + server/util.c | 10 +++++++--- + 8 files changed, 75 insertions(+), 23 deletions(-) + +#diff --git a/CHANGES b/CHANGES +#index e3e8a98db24..9dd7045c232 100644 +#--- a/CHANGES +#+++ b/CHANGES +#@@ -1,6 +1,10 @@ +# -*- coding: utf-8 -*- +# Changes with Apache 2.4.39 +# +#+ *) core: new configuration option 'MergeSlashes on|off' that controls handling of +#+ multiple, consecutive slash ('/') characters in the path component of the request URL. +#+ [Eric Covener] +#+ +# *) mod_http2: when SSL renegotiation is inhibited and a 403 ErrorDocument is +# in play, the proper HTTP/2 stream reset did not trigger with H2_ERR_HTTP_1_1_REQUIRED. +# Fixed. [Michael Kaufmann] +#diff --git a/docs/manual/mod/core.xml b/docs/manual/mod/core.xml +#index fc664116727..460b4367621 100644 +#--- a/docs/manual/mod/core.xml +#+++ b/docs/manual/mod/core.xml +#@@ -5138,4 +5138,30 @@ recognized methods to modules.</p> +# <seealso><directive module="mod_allowmethods">AllowMethods</directive></seealso> +# </directivesynopsis> +# +#+<directivesynopsis> +#+<name>MergeSlashes</name> +#+<description>Controls whether the server merges consecutive slashes in URLs. +#+</description> +#+<syntax>MergeSlashes ON|OFF</syntax> +#+<default>MergeSlashes ON</default> +#+<contextlist><context>server config</context><context>virtual host</context> +#+</contextlist> +#+<compatibility>Added in 2.5.1</compatibility> +#+ +#+<usage> +#+ <p>By default, the server merges (or collapses) multiple consecutive slash +#+ ('/') characters in the path component of the request URL.</p> +#+ +#+ <p>When mapping URL's to the filesystem, these multiple slashes are not +#+ significant. However, URL's handled other ways, such as by CGI or proxy, +#+ might prefer to retain the significance of multiple consecutive slashes. +#+ In these cases <directive>MergeSlashes</directive> can be set to +#+ <em>OFF</em> to retain the multiple consecutive slashes. In these +#+ configurations, regular expressions used in the configuration file that match +#+ the path component of the URL (<directive>LocationMatch</directive>, +#+ <directive>RewriteRule</directive>, ...) need to take into account multiple +#+ consecutive slashes.</p> +#+</usage> +#+</directivesynopsis> +#+ +# </modulesynopsis> +diff --git a/include/ap_mmn.h b/include/ap_mmn.h +index 2167baa0325..4739f7f64d3 100644 +--- a/include/ap_mmn.h ++++ b/include/ap_mmn.h +@@ -523,6 +523,8 @@ + * 20120211.82 (2.4.35-dev) Add optional function declaration for + * ap_proxy_balancer_get_best_worker to mod_proxy.h. + * 20120211.83 (2.4.35-dev) Add client64 field to worker_score struct ++ * 20120211.84 (2.4.35-dev) Add ap_no2slash_ex() and merge_slashes to ++ * core_server_conf. + * + */ + +@@ -531,7 +533,7 @@ + #ifndef MODULE_MAGIC_NUMBER_MAJOR + #define MODULE_MAGIC_NUMBER_MAJOR 20120211 + #endif +-#define MODULE_MAGIC_NUMBER_MINOR 83 /* 0...n */ ++#define MODULE_MAGIC_NUMBER_MINOR 84 /* 0...n */ + + /** + * Determine if the server's current MODULE_MAGIC_NUMBER is at least a +diff --git a/include/http_core.h b/include/http_core.h +index 35df5dc9601..8e109882244 100644 +--- a/include/http_core.h ++++ b/include/http_core.h +@@ -740,7 +740,7 @@ typedef struct { + #define AP_HTTP_METHODS_LENIENT 1 + #define AP_HTTP_METHODS_REGISTERED 2 + char http_methods; +- ++ unsigned int merge_slashes; + } core_server_config; + + /* for AddOutputFiltersByType in core.c */ +diff --git a/include/httpd.h b/include/httpd.h +index 65392f83546..99f7f041aea 100644 +--- a/include/httpd.h ++++ b/include/httpd.h +@@ -1697,11 +1697,21 @@ AP_DECLARE(int) ap_unescape_url_keep2f(char *url, int decode_slashes); + AP_DECLARE(int) ap_unescape_urlencoded(char *query); + + /** +- * Convert all double slashes to single slashes +- * @param name The string to convert ++ * Convert all double slashes to single slashes, except where significant ++ * to the filesystem on the current platform. ++ * @param name The string to convert, assumed to be a filesystem path + */ + AP_DECLARE(void) ap_no2slash(char *name); + ++/** ++ * Convert all double slashes to single slashes, except where significant ++ * to the filesystem on the current platform. ++ * @param name The string to convert ++ * @param is_fs_path if set to 0, the significance of any double-slashes is ++ * ignored. ++ */ ++AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path); ++ + /** + * Remove all ./ and xx/../ substrings from a file name. Also remove + * any leading ../ or /../ substrings. +diff --git a/server/core.c b/server/core.c +index e2a91c7a0c6..eacb54fecec 100644 +--- a/server/core.c ++++ b/server/core.c +@@ -490,6 +490,7 @@ static void *create_core_server_config(apr_pool_t *a, server_rec *s) + + conf->protocols = apr_array_make(a, 5, sizeof(const char *)); + conf->protocols_honor_order = -1; ++ conf->merge_slashes = AP_CORE_CONFIG_UNSET; + + return (void *)conf; + } +@@ -555,6 +556,7 @@ static void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv) + conf->protocols_honor_order = ((virt->protocols_honor_order < 0)? + base->protocols_honor_order : + virt->protocols_honor_order); ++ AP_CORE_MERGE_FLAG(merge_slashes, conf, base, virt); + + return conf; + } +@@ -1863,6 +1865,13 @@ static const char *set_qualify_redirect_url(cmd_parms *cmd, void *d_, int flag) + return NULL; + } + ++static const char *set_core_server_flag(cmd_parms *cmd, void *s_, int flag) ++{ ++ core_server_config *conf = ++ ap_get_core_module_config(cmd->server->module_config); ++ return ap_set_flag_slot(cmd, conf, flag); ++} ++ + static const char *set_override_list(cmd_parms *cmd, void *d_, int argc, char *const argv[]) + { + core_dir_config *d = d_; +@@ -4562,6 +4571,10 @@ AP_INIT_ITERATE("HttpProtocolOptions", set_http_protocol_options, NULL, RSRC_CON + "'Unsafe' or 'Strict' (default). Sets HTTP acceptance rules"), + AP_INIT_ITERATE("RegisterHttpMethod", set_http_method, NULL, RSRC_CONF, + "Registers non-standard HTTP methods"), ++AP_INIT_FLAG("MergeSlashes", set_core_server_flag, ++ (void *)APR_OFFSETOF(core_server_config, merge_slashes), ++ RSRC_CONF, ++ "Controls whether consecutive slashes in the URI path are merged"), + { NULL } + }; + +diff --git a/server/request.c b/server/request.c +index dbe3e07f150..1ce8908824b 100644 +--- a/server/request.c ++++ b/server/request.c +@@ -167,6 +167,8 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r) + int file_req = (r->main && r->filename); + int access_status; + core_dir_config *d; ++ core_server_config *sconf = ++ ap_get_core_module_config(r->server->module_config); + + /* Ignore embedded %2F's in path for proxy requests */ + if (!r->proxyreq && r->parsed_uri.path) { +@@ -191,6 +193,10 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r) + } + + ap_getparents(r->uri); /* OK --- shrinking transformations... */ ++ if (sconf->merge_slashes != AP_CORE_CONFIG_OFF) { ++ ap_no2slash(r->uri); ++ ap_no2slash(r->parsed_uri.path); ++ } + + /* All file subrequests are a huge pain... they cannot bubble through the + * next several steps. Only file subrequests are allowed an empty uri, +@@ -1411,20 +1417,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r) + + cache = prep_walk_cache(AP_NOTE_LOCATION_WALK, r); + cached = (cache->cached != NULL); +- +- /* Location and LocationMatch differ on their behaviour w.r.t. multiple +- * slashes. Location matches multiple slashes with a single slash, +- * LocationMatch doesn't. An exception, for backwards brokenness is +- * absoluteURIs... in which case neither match multiple slashes. +- */ +- if (r->uri[0] != '/') { +- entry_uri = r->uri; +- } +- else { +- char *uri = apr_pstrdup(r->pool, r->uri); +- ap_no2slash(uri); +- entry_uri = uri; +- } ++ entry_uri = r->uri; + + /* If we have an cache->cached location that matches r->uri, + * and the vhost's list of locations hasn't changed, we can skip +@@ -1491,7 +1484,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r) + pmatch = apr_palloc(rxpool, nmatch*sizeof(ap_regmatch_t)); + } + +- if (ap_regexec(entry_core->r, r->uri, nmatch, pmatch, 0)) { ++ if (ap_regexec(entry_core->r, entry_uri, nmatch, pmatch, 0)) { + continue; + } + +@@ -1501,7 +1494,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r) + apr_table_setn(r->subprocess_env, + ((const char **)entry_core->refs->elts)[i], + apr_pstrndup(r->pool, +- r->uri + pmatch[i].rm_so, ++ entry_uri + pmatch[i].rm_so, + pmatch[i].rm_eo - pmatch[i].rm_so)); + } + } +diff --git a/server/util.c b/server/util.c +index fd7a0a14763..607c4850d86 100644 +--- a/server/util.c ++++ b/server/util.c +@@ -561,16 +561,16 @@ AP_DECLARE(void) ap_getparents(char *name) + name[l] = '\0'; + } + } +- +-AP_DECLARE(void) ap_no2slash(char *name) ++AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path) + { ++ + char *d, *s; + + s = d = name; + + #ifdef HAVE_UNC_PATHS + /* Check for UNC names. Leave leading two slashes. */ +- if (s[0] == '/' && s[1] == '/') ++ if (is_fs_path && s[0] == '/' && s[1] == '/') + *d++ = *s++; + #endif + +@@ -587,6 +587,10 @@ AP_DECLARE(void) ap_no2slash(char *name) + *d = '\0'; + } + ++AP_DECLARE(void) ap_no2slash(char *name) ++{ ++ ap_no2slash_ex(name, 1); ++} + + /* + * copy at most n leading directories of s into d diff -Nru apache2-2.4.38/debian/patches/CVE-2019-0220-2.patch apache2-2.4.38/debian/patches/CVE-2019-0220-2.patch --- apache2-2.4.38/debian/patches/CVE-2019-0220-2.patch 1970-01-01 01:00:00.000000000 +0100 +++ apache2-2.4.38/debian/patches/CVE-2019-0220-2.patch 2019-04-07 19:37:55.000000000 +0200 @@ -0,0 +1,50 @@ +From c4ef468b25718a26f2b92cbea3ca093729b79331 Mon Sep 17 00:00:00 2001 +From: Eric Covener <cove...@apache.org> +Date: Mon, 18 Mar 2019 12:10:15 +0000 +Subject: [PATCH] merge 1855743,1855744 ^/httpd/httpd/trunk . + +r->parsed_uri.path safety in recent backport + +*) core: fix SEGFAULT in CONNECT with recent change + 2.4.x: svn merge -c 1855743,1855744 ^/httpd/httpd/trunk . + +1: rpluem, icing, covener + + + + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1855751 13f79535-47bb-0310-9956-ffa450edef68 +--- + server/request.c | 4 +++- + server/util.c | 4 ++++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/server/request.c b/server/request.c +index 1ce8908824b..d5c558afa30 100644 +--- a/server/request.c ++++ b/server/request.c +@@ -195,7 +195,9 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r) + ap_getparents(r->uri); /* OK --- shrinking transformations... */ + if (sconf->merge_slashes != AP_CORE_CONFIG_OFF) { + ap_no2slash(r->uri); +- ap_no2slash(r->parsed_uri.path); ++ if (r->parsed_uri.path) { ++ ap_no2slash(r->parsed_uri.path); ++ } + } + + /* All file subrequests are a huge pain... they cannot bubble through the +diff --git a/server/util.c b/server/util.c +index 607c4850d86..f3b17f1581e 100644 +--- a/server/util.c ++++ b/server/util.c +@@ -566,6 +566,10 @@ AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path) + + char *d, *s; + ++ if (!name || !*name) { ++ return; ++ } ++ + s = d = name; + + #ifdef HAVE_UNC_PATHS diff -Nru apache2-2.4.38/debian/patches/CVE-2019-0220-3.patch apache2-2.4.38/debian/patches/CVE-2019-0220-3.patch --- apache2-2.4.38/debian/patches/CVE-2019-0220-3.patch 1970-01-01 01:00:00.000000000 +0100 +++ apache2-2.4.38/debian/patches/CVE-2019-0220-3.patch 2019-04-07 19:37:55.000000000 +0200 @@ -0,0 +1,43 @@ +From 3451fc2bf8708b0dc8cd6a7d0ac0fe5b6401befc Mon Sep 17 00:00:00 2001 +From: Eric Covener <cove...@apache.org> +Date: Tue, 19 Mar 2019 18:01:21 +0000 +Subject: [PATCH] *) maintainer mode fix for util.c no2slash_ex trunk + patch: http://svn.apache.org/r1855755 2.4.x patch svn merge -c 1855755 + ^/httpd/httpd/trunk . +1: covener, rpluem, jim, ylavic + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1855853 13f79535-47bb-0310-9956-ffa450edef68 +--- + STATUS | 6 ------ + server/util.c | 2 +- + 2 files changed, 1 insertion(+), 7 deletions(-) + +#diff --git a/STATUS b/STATUS +#index ffe5d22550c..1f8cb2f7884 100644 +#--- a/STATUS +#+++ b/STATUS +#@@ -126,12 +126,6 @@ RELEASE SHOWSTOPPERS: +# PATCHES ACCEPTED TO BACKPORT FROM TRUNK: +# [ start all new proposals below, under PATCHES PROPOSED. ] +# +#- *) maintainer mode fix for util.c no2slash_ex +#- trunk patch: http://svn.apache.org/r1855755 +#- 2.4.x patch svn merge -c 1855755 ^/httpd/httpd/trunk . +#- +1: covener, rpluem, jim, ylavic +#- +#- +# PATCHES PROPOSED TO BACKPORT FROM TRUNK: +# [ New proposals should be added at the end of the list ] +# +diff --git a/server/util.c b/server/util.c +index f3b17f1581e..e0c558cee2d 100644 +--- a/server/util.c ++++ b/server/util.c +@@ -566,7 +566,7 @@ AP_DECLARE(void) ap_no2slash_ex(char *name, int is_fs_path) + + char *d, *s; + +- if (!name || !*name) { ++ if (!*name) { + return; + } + diff -Nru apache2-2.4.38/debian/patches/series apache2-2.4.38/debian/patches/series --- apache2-2.4.38/debian/patches/series 2019-01-22 21:40:23.000000000 +0100 +++ apache2-2.4.38/debian/patches/series 2019-04-07 19:45:58.000000000 +0200 @@ -8,3 +8,12 @@ # This patch is applied manually #suexec-custom.patch spelling-errors.patch + +CVE-2019-0196.patch +CVE-2019-0211.patch +CVE-2019-0215.patch +CVE-2019-0217.patch +CVE-2019-0220-1.patch +CVE-2019-0220-2.patch +CVE-2019-0220-3.patch +CVE-2019-0197.patch