commit apache2 for openSUSE:Factory
Hello community, here is the log from the commit of package apache2 for openSUSE:Factory checked in at 2014-12-30 00:49:20 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/apache2 (Old) and /work/SRC/openSUSE:Factory/.apache2.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "apache2" Changes: -------- --- /work/SRC/openSUSE:Factory/apache2/apache2.changes 2014-12-09 09:16:44.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.apache2.new/apache2.changes 2014-12-30 00:49:23.000000000 +0100 @@ -1,0 +2,16 @@ +Mon Dec 15 17:29:28 UTC 2014 - kstreitova@suse.com + +- added httpd-2.4.x-bnc871310-CVE-2013-5704-mod_headers_chunked_requests.patch + to fix flaw in the way mod_headers handled chunked requests. Adds + "MergeTrailers" directive to restore legacy behavior + [bnc#871310], [CVE-2013-5704]. + +------------------------------------------------------------------- +Fri Dec 12 15:46:29 UTC 2014 - kstreitova@suse.com + +- added httpd-2.4.x-bnc909715-CVE-2014-8109-mod_lua_handling_of_Require_line.patch + that fixes handling of the Require line when a LuaAuthzProvider is + used in multiple Require directives with different arguments + [bnc#909715], [CVE-2014-8109]. + +------------------------------------------------------------------- New: ---- httpd-2.4.x-bnc871310-CVE-2013-5704-mod_headers_chunked_requests.patch httpd-2.4.x-bnc909715-CVE-2014-8109-mod_lua_handling_of_Require_line.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ apache2.spec ++++++ --- /var/tmp/diff_new_pack.FHwfiC/_old 2014-12-30 00:49:26.000000000 +0100 +++ /var/tmp/diff_new_pack.FHwfiC/_new 2014-12-30 00:49:26.000000000 +0100 @@ -166,6 +166,10 @@ Patch111: httpd-visibility.patch # PATCH-FIX-UPSTREAM bnc#899836 kstreitova@suse.com -- avoid a crash when Content-Type has an empty value Patch112: httpd-2.4.10-check_null_pointer_dereference.patch +# PATCH-FIX-UPSTREAM bnc#909715 kstreitova@suse.com -- Fix handling of the Require line when a LuaAuthzProvider is used in multiple Require directives with different arguments. +Patch113: httpd-2.4.x-bnc909715-CVE-2014-8109-mod_lua_handling_of_Require_line.patch +# PATCH-FIX-UPSTREAM bnc#871310 kstreitova@suse.com -- Fix the flaw in the way mod_headers handled chunked requests. +Patch114: httpd-2.4.x-bnc871310-CVE-2013-5704-mod_headers_chunked_requests.patch Url: http://httpd.apache.org/ Icon: Apache.xpm Summary: The Apache Web Server Version 2.4 @@ -346,6 +350,8 @@ %patch109 -p1 %patch111 -p1 %patch112 -p1 +%patch113 -p1 +%patch114 -p1 cat $RPM_SOURCE_DIR/SUSE-NOTICE >> NOTICE # install READMEs a=$(basename %{S:22}) ++++++ httpd-2.4.x-bnc871310-CVE-2013-5704-mod_headers_chunked_requests.patch ++++++
From 6688f9d102ad29d6bb4167d690ee495d709e47b6 Mon Sep 17 00:00:00 2001 From: "William A. Rowe Jr" <wrowe@apache.org> Date: Fri, 22 Aug 2014 18:18:08 +0000 Subject: [PATCH] SECURITY: CVE-2013-5704 (cve.mitre.org)
core: HTTP trailers could be used to replace HTTP headers late during request processing, potentially undoing or otherwise confusing modules that examined or modified request headers earlier. Adds "MergeTrailers" directive to restore legacy behavior. Submitted by: Edward Lu, Yann Ylavic, Joe Orton, Eric Covener Backports: r1610814 Reviewed by: covener, wrowe, ylavic git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1619884 13f79535-47bb-0310-9956-ffa450edef68 diff --git a/include/http_core.h b/include/http_core.h index 8730d1f..5cef622 100644 --- a/include/http_core.h +++ b/include/http_core.h @@ -667,6 +667,10 @@ typedef struct { #define AP_TRACE_ENABLE 1 #define AP_TRACE_EXTENDED 2 int trace_enable; +#define AP_MERGE_TRAILERS_UNSET 0 +#define AP_MERGE_TRAILERS_ENABLE 1 +#define AP_MERGE_TRAILERS_DISABLE 2 + int merge_trailers; } core_server_config; diff --git a/include/httpd.h b/include/httpd.h index e1510be..c6cd827 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -1035,6 +1035,11 @@ struct request_rec { */ apr_sockaddr_t *useragent_addr; char *useragent_ip; + + /** MIME trailer environment from the request */ + apr_table_t *trailers_in; + /** MIME trailer environment from the response */ + apr_table_t *trailers_out; }; /** diff --git a/modules/http/http_filters.c b/modules/http/http_filters.c index 2a0a979..0b86009 100644 --- a/modules/http/http_filters.c +++ b/modules/http/http_filters.c @@ -231,6 +231,49 @@ static apr_status_t get_chunk_line(http_ctx_t *ctx, apr_bucket_brigade *b, } +static apr_status_t read_chunked_trailers(http_ctx_t *ctx, ap_filter_t *f, + apr_bucket_brigade *b, int merge) +{ + int rv; + apr_bucket *e; + request_rec *r = f->r; + apr_table_t *saved_headers_in = r->headers_in; + int saved_status = r->status; + + r->status = HTTP_OK; + r->headers_in = r->trailers_in; + apr_table_clear(r->headers_in); + ctx->state = BODY_NONE; + ap_get_mime_headers(r); + + if(r->status == HTTP_OK) { + r->status = saved_status; + e = apr_bucket_eos_create(f->c->bucket_alloc); + APR_BRIGADE_INSERT_TAIL(b, e); + ctx->eos_sent = 1; + rv = APR_SUCCESS; + } + else { + const char *error_notes = apr_table_get(r->notes, + "error-notes"); + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + "Error while reading HTTP trailer: %i%s%s", + r->status, error_notes ? ": " : "", + error_notes ? error_notes : ""); + rv = APR_EINVAL; + } + + if(!merge) { + r->headers_in = saved_headers_in; + } + else { + r->headers_in = apr_table_overlay(r->pool, saved_headers_in, + r->trailers_in); + } + + return rv; +} + /* This is the HTTP_INPUT filter for HTTP requests and responses from * proxied servers (mod_proxy). It handles chunked and content-length * bodies. This can only be inserted/used after the headers @@ -240,6 +283,7 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_read_type_e block, apr_off_t readbytes) { + core_server_config *conf; apr_bucket *e; http_ctx_t *ctx = f->ctx; apr_status_t rv; @@ -247,6 +291,9 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, int http_error = HTTP_REQUEST_ENTITY_TOO_LARGE; apr_bucket_brigade *bb; + conf = (core_server_config *) + ap_get_module_config(f->r->server->module_config, &core_module); + /* just get out of the way of things we don't want. */ if (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE) { return ap_get_brigade(f->next, b, mode, block, readbytes); @@ -425,13 +472,8 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, } if (!ctx->remaining) { - /* Handle trailers by calling ap_get_mime_headers again! */ - ctx->state = BODY_NONE; - ap_get_mime_headers(f->r); - e = apr_bucket_eos_create(f->c->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(b, e); - ctx->eos_sent = 1; - return APR_SUCCESS; + return read_chunked_trailers(ctx, f, b, + conf->merge_trailers == AP_MERGE_TRAILERS_ENABLE); } } } @@ -534,13 +576,8 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, } if (!ctx->remaining) { - /* Handle trailers by calling ap_get_mime_headers again! */ - ctx->state = BODY_NONE; - ap_get_mime_headers(f->r); - e = apr_bucket_eos_create(f->c->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(b, e); - ctx->eos_sent = 1; - return APR_SUCCESS; + return read_chunked_trailers(ctx, f, b, + conf->merge_trailers == AP_MERGE_TRAILERS_ENABLE); } } break; diff --git a/modules/http/http_request.c b/modules/http/http_request.c index 796d506..cdfec8b 100644 --- a/modules/http/http_request.c +++ b/modules/http/http_request.c @@ -463,6 +463,7 @@ static request_rec *internal_internal_redirect(const char *new_uri, new->main = r->main; new->headers_in = r->headers_in; + new->trailers_in = r->trailers_in; new->headers_out = apr_table_make(r->pool, 12); if (ap_is_HTTP_REDIRECT(new->status)) { const char *location = apr_table_get(r->headers_out, "Location"); @@ -470,6 +471,7 @@ static request_rec *internal_internal_redirect(const char *new_uri, apr_table_setn(new->headers_out, "Location", location); } new->err_headers_out = r->err_headers_out; + new->trailers_out = apr_table_make(r->pool, 5); new->subprocess_env = rename_original_env(r->pool, r->subprocess_env); new->notes = apr_table_make(r->pool, 5); @@ -583,6 +585,8 @@ AP_DECLARE(void) ap_internal_fast_redirect(request_rec *rr, request_rec *r) r->headers_out); r->err_headers_out = apr_table_overlay(r->pool, rr->err_headers_out, r->err_headers_out); + r->trailers_out = apr_table_overlay(r->pool, rr->trailers_out, + r->trailers_out); r->subprocess_env = apr_table_overlay(r->pool, rr->subprocess_env, r->subprocess_env); diff --git a/modules/loggers/mod_log_config.c b/modules/loggers/mod_log_config.c index 792756d..c1b0e1b 100644 --- a/modules/loggers/mod_log_config.c +++ b/modules/loggers/mod_log_config.c @@ -431,6 +431,12 @@ static const char *log_header_in(request_rec *r, char *a) return ap_escape_logitem(r->pool, apr_table_get(r->headers_in, a)); } +static const char *log_trailer_in(request_rec *r, char *a) +{ + return ap_escape_logitem(r->pool, apr_table_get(r->trailers_in, a)); +} + + static APR_INLINE char *find_multiple_headers(apr_pool_t *pool, const apr_table_t *table, const char *key) @@ -514,6 +520,11 @@ static const char *log_header_out(request_rec *r, char *a) return ap_escape_logitem(r->pool, cp); } +static const char *log_trailer_out(request_rec *r, char *a) +{ + return ap_escape_logitem(r->pool, apr_table_get(r->trailers_out, a)); +} + static const char *log_note(request_rec *r, char *a) { return ap_escape_logitem(r->pool, apr_table_get(r->notes, a)); @@ -916,7 +927,7 @@ static char *parse_log_misc_string(apr_pool_t *p, log_format_item *it, static char *parse_log_item(apr_pool_t *p, log_format_item *it, const char **sa) { const char *s = *sa; - ap_log_handler *handler; + ap_log_handler *handler = NULL; if (*s != '%') { return parse_log_misc_string(p, it, sa); @@ -986,7 +997,16 @@ static char *parse_log_item(apr_pool_t *p, log_format_item *it, const char **sa) break; default: - handler = (ap_log_handler *)apr_hash_get(log_hash, s++, 1); + /* check for '^' + two character format first */ + if (*s == '^' && *(s+1) && *(s+2)) { + handler = (ap_log_handler *)apr_hash_get(log_hash, s, 3); + if (handler) { + s += 3; + } + } + if (!handler) { + handler = (ap_log_handler *)apr_hash_get(log_hash, s++, 1); + } if (!handler) { char dummy[2]; @@ -1516,7 +1536,7 @@ static void ap_register_log_handler(apr_pool_t *p, char *tag, log_struct->func = handler; log_struct->want_orig_default = def; - apr_hash_set(log_hash, tag, 1, (const void *)log_struct); + apr_hash_set(log_hash, tag, strlen(tag), (const void *)log_struct); } static ap_log_writer_init *ap_log_set_writer_init(ap_log_writer_init *handle) { @@ -1694,6 +1714,9 @@ static int log_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp) log_pfn_register(p, "U", log_request_uri, 1); log_pfn_register(p, "s", log_status, 1); log_pfn_register(p, "R", log_handler, 1); + + log_pfn_register(p, "^ti", log_trailer_in, 0); + log_pfn_register(p, "^to", log_trailer_out, 0); } /* reset to default conditions */ diff --git a/modules/proxy/mod_proxy_http.c b/modules/proxy/mod_proxy_http.c index 141452b..1a4d593 100644 --- a/modules/proxy/mod_proxy_http.c +++ b/modules/proxy/mod_proxy_http.c @@ -1011,8 +1011,11 @@ static request_rec *make_fake_req(conn_rec *c, request_rec *r) rp->status = HTTP_OK; rp->headers_in = apr_table_make(pool, 50); + rp->trailers_in = apr_table_make(pool, 5); + rp->subprocess_env = apr_table_make(pool, 50); rp->headers_out = apr_table_make(pool, 12); + rp->trailers_out = apr_table_make(pool, 5); rp->err_headers_out = apr_table_make(pool, 5); rp->notes = apr_table_make(pool, 5); @@ -1093,6 +1096,7 @@ static void ap_proxy_read_headers(request_rec *r, request_rec *rr, psc = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); r->headers_out = apr_table_make(r->pool, 20); + r->trailers_out = apr_table_make(r->pool, 5); *pread_len = 0; /* @@ -1223,6 +1227,14 @@ apr_status_t ap_proxygetline(apr_bucket_brigade *bb, char *s, int n, request_rec #define AP_MAX_INTERIM_RESPONSES 10 #endif +static int add_trailers(void *data, const char *key, const char *val) +{ + if (val) { + apr_table_add((apr_table_t*)data, key, val); + } + return 1; +} + static apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, proxy_conn_rec **backend_ptr, @@ -1735,6 +1747,12 @@ apr_status_t ap_proxy_http_process_response(apr_pool_t * p, request_rec *r, /* next time try a non-blocking read */ mode = APR_NONBLOCK_READ; + if (!apr_is_empty_table(backend->r->trailers_in)) { + apr_table_do(add_trailers, r->trailers_out, + backend->r->trailers_in, NULL); + apr_table_clear(backend->r->trailers_in); + } + apr_brigade_length(bb, 0, &readbytes); backend->worker->s->read += readbytes; #if DEBUGGING diff --git a/server/core.c b/server/core.c index dd1a375..613ffa4 100644 --- a/server/core.c +++ b/server/core.c @@ -520,6 +520,10 @@ static void *merge_core_server_configs(apr_pool_t *p, void *basev, void *virtv) if (virt->error_log_req) conf->error_log_req = virt->error_log_req; + conf->merge_trailers = (virt->merge_trailers != AP_MERGE_TRAILERS_UNSET) + ? virt->merge_trailers + : base->merge_trailers; + return conf; } @@ -3882,6 +3886,16 @@ AP_DECLARE(void) ap_register_errorlog_handler(apr_pool_t *p, char *tag, } +static const char *set_merge_trailers(cmd_parms *cmd, void *dummy, int arg) +{ + core_server_config *conf = ap_get_module_config(cmd->server->module_config, + &core_module); + conf->merge_trailers = (arg ? AP_MERGE_TRAILERS_ENABLE : + AP_MERGE_TRAILERS_DISABLE); + + return NULL; +} + /* Note --- ErrorDocument will now work from .htaccess files. * The AllowOverride of Fileinfo allows webmasters to turn it off */ @@ -4129,6 +4143,8 @@ AP_INIT_TAKE1("EnableExceptionHook", ap_mpm_set_exception_hook, NULL, RSRC_CONF, #endif AP_INIT_TAKE1("TraceEnable", set_trace_enable, NULL, RSRC_CONF, "'on' (default), 'off' or 'extended' to trace request body content"), +AP_INIT_FLAG("MergeTrailers", set_merge_trailers, NULL, RSRC_CONF, + "merge request trailers into request headers or not"), { NULL } }; @@ -4211,7 +4227,6 @@ static int core_map_to_storage(request_rec *r) static int do_nothing(request_rec *r) { return OK; } - static int core_override_type(request_rec *r) { core_dir_config *conf = diff --git a/server/protocol.c b/server/protocol.c index bf915a0..960117d 100644 --- a/server/protocol.c +++ b/server/protocol.c @@ -718,6 +718,8 @@ AP_DECLARE(void) ap_get_mime_headers_core(request_rec *r, apr_bucket_brigade *bb r->status = HTTP_REQUEST_TIME_OUT; } else { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, + "Failed to read request header line %s", field); r->status = HTTP_BAD_REQUEST; } @@ -917,9 +919,11 @@ request_rec *ap_read_request(conn_rec *conn) r->allowed_methods = ap_make_method_list(p, 2); r->headers_in = apr_table_make(r->pool, 25); + r->trailers_in = apr_table_make(r->pool, 5); r->subprocess_env = apr_table_make(r->pool, 25); r->headers_out = apr_table_make(r->pool, 12); r->err_headers_out = apr_table_make(r->pool, 5); + r->trailers_out = apr_table_make(r->pool, 5); r->notes = apr_table_make(r->pool, 5); r->request_config = ap_create_request_config(r->pool); @@ -1185,6 +1189,7 @@ AP_DECLARE(void) ap_set_sub_req_protocol(request_rec *rnew, rnew->status = HTTP_OK; rnew->headers_in = apr_table_copy(rnew->pool, r->headers_in); + rnew->trailers_in = apr_table_copy(rnew->pool, r->trailers_in); /* did the original request have a body? (e.g. POST w/SSI tags) * if so, make sure the subrequest doesn't inherit body headers @@ -1196,6 +1201,7 @@ AP_DECLARE(void) ap_set_sub_req_protocol(request_rec *rnew, rnew->subprocess_env = apr_table_copy(rnew->pool, r->subprocess_env); rnew->headers_out = apr_table_make(rnew->pool, 5); rnew->err_headers_out = apr_table_make(rnew->pool, 5); + rnew->trailers_out = apr_table_make(rnew->pool, 5); rnew->notes = apr_table_make(rnew->pool, 5); rnew->expecting_100 = r->expecting_100; ++++++ httpd-2.4.x-bnc909715-CVE-2014-8109-mod_lua_handling_of_Require_line.patch ++++++ Index: httpd-2.4.10/modules/lua/mod_lua.c =================================================================== --- httpd-2.4.10.orig/modules/lua/mod_lua.c +++ httpd-2.4.10/modules/lua/mod_lua.c @@ -66,9 +66,13 @@ typedef struct { const char *file_name; const char *function_name; ap_lua_vm_spec *spec; - apr_array_header_t *args; } lua_authz_provider_spec; +typedef struct { + lua_authz_provider_spec *spec; + apr_array_header_t *args; +} lua_authz_provider_func; + apr_hash_t *lua_authz_providers; typedef struct @@ -1692,6 +1696,7 @@ static const char *lua_authz_parse(cmd_p { const char *provider_name; lua_authz_provider_spec *spec; + lua_authz_provider_func *func = apr_pcalloc(cmd->pool, sizeof(lua_authz_provider_func)); apr_pool_userdata_get((void**)&provider_name, AUTHZ_PROVIDER_NAME_NOTE, cmd->temp_pool); @@ -1699,16 +1704,17 @@ static const char *lua_authz_parse(cmd_p spec = apr_hash_get(lua_authz_providers, provider_name, APR_HASH_KEY_STRING); ap_assert(spec != NULL); + func->spec = spec; if (require_line && *require_line) { const char *arg; - spec->args = apr_array_make(cmd->pool, 2, sizeof(const char *)); + func->args = apr_array_make(cmd->pool, 2, sizeof(const char *)); while ((arg = ap_getword_conf(cmd->pool, &require_line)) && *arg) { - APR_ARRAY_PUSH(spec->args, const char *) = arg; + APR_ARRAY_PUSH(func->args, const char *) = arg; } } - *parsed_require_line = spec; + *parsed_require_line = func; return NULL; } @@ -1722,7 +1728,8 @@ static authz_status lua_authz_check(requ &lua_module); const ap_lua_dir_cfg *cfg = ap_get_module_config(r->per_dir_config, &lua_module); - const lua_authz_provider_spec *prov_spec = parsed_require_line; + const lua_authz_provider_func *prov_func = parsed_require_line; + const lua_authz_provider_spec *prov_spec = prov_func->spec; int result; int nargs = 0; @@ -1744,19 +1751,19 @@ static authz_status lua_authz_check(requ return AUTHZ_GENERAL_ERROR; } ap_lua_run_lua_request(L, r); - if (prov_spec->args) { + if (prov_func->args) { int i; - if (!lua_checkstack(L, prov_spec->args->nelts)) { + if (!lua_checkstack(L, prov_func->args->nelts)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02315) "Error: authz provider %s: too many arguments", prov_spec->name); ap_lua_release_state(L, spec, r); return AUTHZ_GENERAL_ERROR; } - for (i = 0; i < prov_spec->args->nelts; i++) { - const char *arg = APR_ARRAY_IDX(prov_spec->args, i, const char *); + for (i = 0; i < prov_func->args->nelts; i++) { + const char *arg = APR_ARRAY_IDX(prov_func->args, i, const char *); lua_pushstring(L, arg); } - nargs = prov_spec->args->nelts; + nargs = prov_func->args->nelts; } if (lua_pcall(L, 1 + nargs, 1, 0)) { const char *err = lua_tostring(L, -1); -- To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-commit+help@opensuse.org
participants (1)
-
root@hilbert.suse.de