From af9996ce6998c4c343dc7ac5677fd4f159085480 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Dec 17 2014 08:25:50 +0000 Subject: core: fix bypassing of mod_headers rules via chunked requests (CVE-2013-5704) - mod_cache: fix NULL pointer dereference on empty Content-Type (CVE-2014-3581) - mod_proxy_fcgi: fix a potential crash with long headers (CVE-2014-3583) - mod_lua: fix handling of the Require line when a LuaAuthzProvider is used in multiple Require directives with different arguments (CVE-2014-8109) --- diff --git a/httpd-2.4.10-CVE-2014-3583.patch b/httpd-2.4.10-CVE-2014-3583.patch new file mode 100644 index 0000000..7794a3d --- /dev/null +++ b/httpd-2.4.10-CVE-2014-3583.patch @@ -0,0 +1,75 @@ +--- a/modules/proxy/mod_proxy_fcgi.c 2014/11/12 15:32:12 1638817 ++++ b/modules/proxy/mod_proxy_fcgi.c 2014/11/12 15:41:07 1638818 +@@ -18,6 +18,8 @@ + #include "util_fcgi.h" + #include "util_script.h" + ++#include "apr_lib.h" /* for apr_iscntrl() */ ++ + module AP_MODULE_DECLARE_DATA proxy_fcgi_module; + + /* +@@ -310,13 +312,12 @@ + * + * Returns 0 if it can't find the end of the headers, and 1 if it found the + * end of the headers. */ +-static int handle_headers(request_rec *r, +- int *state, +- char *readbuf) ++static int handle_headers(request_rec *r, int *state, ++ const char *readbuf, apr_size_t readlen) + { + const char *itr = readbuf; + +- while (*itr) { ++ while (readlen) { + if (*itr == '\r') { + switch (*state) { + case HDR_STATE_GOT_CRLF: +@@ -347,13 +348,17 @@ + break; + } + } +- else { ++ else if (*itr == '\t' || !apr_iscntrl(*itr)) { + *state = HDR_STATE_READING_HEADERS; + } ++ else { ++ return -1; ++ } + + if (*state == HDR_STATE_DONE_WITH_HEADERS) + break; + ++ --readlen; + ++itr; + } + +@@ -563,7 +568,14 @@ + APR_BRIGADE_INSERT_TAIL(ob, b); + + if (! seen_end_of_headers) { +- int st = handle_headers(r, &header_state, iobuf); ++ int st = handle_headers(r, &header_state, iobuf, ++ readbuflen); ++ ++ if (st == -1) { ++ *err = "parsing response headers"; ++ rv = APR_EINVAL; ++ break; ++ } + + if (st == 1) { + int status; +@@ -684,6 +696,11 @@ + break; + } + ++ if (*err) { ++ /* stop on error in the above switch */ ++ break; ++ } ++ + if (plen) { + rv = get_data_full(conn, iobuf, plen); + if (rv != APR_SUCCESS) { diff --git a/httpd-2.4.10-CVE-2014-8109.patch b/httpd-2.4.10-CVE-2014-8109.patch new file mode 100644 index 0000000..9a1ac4e --- /dev/null +++ b/httpd-2.4.10-CVE-2014-8109.patch @@ -0,0 +1,108 @@ +From 3f1693d558d0758f829c8b53993f1749ddf6ffcb Mon Sep 17 00:00:00 2001 +From: Jim Jagielski +Date: Tue, 2 Dec 2014 12:50:59 +0000 +Subject: [PATCH] Merge r1642499 from trunk: + + *) SECURITY: CVE-2014-8109 (cve.mitre.org) + mod_lua: Fix handling of the Require line when a LuaAuthzProvider is + used in multiple Require directives with different arguments. + PR57204 [Edward Lu ] + +Submitted By: Edward Lu +Committed By: covener + + +Submitted by: covener +Reviewed/backported by: jim + + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1642861 13f79535-47bb-0310-9956-ffa450edef68 +--- + CHANGES | 5 +++++ + STATUS | 7 ------- + modules/lua/mod_lua.c | 27 +++++++++++++++++---------- + 3 files changed, 22 insertions(+), 17 deletions(-) + +diff --git a/modules/lua/mod_lua.c b/modules/lua/mod_lua.c +index b2dca75..e6d2cfc 100644 +--- a/modules/lua/mod_lua.c ++++ b/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_parms *cmd, const char *require_line, + { + 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_parms *cmd, const char *require_line, + + 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(request_rec *r, const char *require_line, + &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(request_rec *r, const char *require_line, + 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); diff --git a/httpd-2.4.6-CVE-2013-5704.patch b/httpd-2.4.6-CVE-2013-5704.patch new file mode 100644 index 0000000..410ca21 --- /dev/null +++ b/httpd-2.4.6-CVE-2013-5704.patch @@ -0,0 +1,381 @@ +diff --git a/include/http_core.h b/include/http_core.h +index 3c47989..f6f4aa2 100644 +--- a/include/http_core.h ++++ b/include/http_core.h +@@ -663,6 +663,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 36cd58d..2e415f9 100644 +--- a/include/httpd.h ++++ b/include/httpd.h +@@ -1032,6 +1032,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 24a939a..2ae8f46 100644 +--- a/modules/http/http_filters.c ++++ b/modules/http/http_filters.c +@@ -214,6 +214,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 +@@ -223,6 +266,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; +@@ -230,6 +274,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); +@@ -403,13 +450,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); + } + } + } +@@ -509,13 +551,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 25f5030..b021dd3 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) + { +@@ -1686,6 +1706,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 7ae0fa4..05f33b4 100644 +--- a/modules/proxy/mod_proxy_http.c ++++ b/modules/proxy/mod_proxy_http.c +@@ -994,8 +994,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); + +@@ -1076,6 +1079,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; + + /* +@@ -1206,6 +1210,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, +@@ -1717,6 +1729,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 024bab6..7cfde63 100644 +--- a/server/core.c ++++ b/server/core.c +@@ -523,6 +523,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; + } + +@@ -3877,6 +3881,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 + */ +@@ -4124,6 +4138,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 } + }; + +@@ -4206,7 +4222,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 14329eb..46fc034 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); +@@ -1162,6 +1166,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 +@@ -1173,6 +1178,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; diff --git a/httpd-2.4.6-CVE-2014-3581.patch b/httpd-2.4.6-CVE-2014-3581.patch new file mode 100644 index 0000000..0702899 --- /dev/null +++ b/httpd-2.4.6-CVE-2014-3581.patch @@ -0,0 +1,17 @@ +diff --git a/modules/cache/cache_util.c b/modules/cache/cache_util.c +index 7b7fb45..fbebb1e 100644 +--- a/modules/cache/cache_util.c ++++ b/modules/cache/cache_util.c +@@ -1251,8 +1251,10 @@ CACHE_DECLARE(apr_table_t *)ap_cache_cacheable_headers_out(request_rec *r) + + if (r->content_type + && !apr_table_get(headers_out, "Content-Type")) { +- apr_table_setn(headers_out, "Content-Type", +- ap_make_content_type(r, r->content_type)); ++ const char *ctype = ap_make_content_type(r, r->content_type); ++ if (ctype) { ++ apr_table_setn(headers_out, "Content-Type", ctype); ++ } + } + + if (r->content_encoding diff --git a/httpd.spec b/httpd.spec index d88386f..8a63aa4 100644 --- a/httpd.spec +++ b/httpd.spec @@ -14,7 +14,7 @@ Summary: Apache HTTP Server Name: httpd Version: 2.4.10 -Release: 14%{?dist} +Release: 15%{?dist} URL: http://httpd.apache.org/ Source0: http://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2 Source1: index.html @@ -72,6 +72,11 @@ Patch35: httpd-2.4.10-sslciphdefault.patch Patch55: httpd-2.4.4-malformed-host.patch Patch56: httpd-2.4.4-mod_unique_id.patch Patch57: httpd-2.4.10-sigint.patch +# Security fixes +Patch100: httpd-2.4.6-CVE-2013-5704.patch +Patch101: httpd-2.4.6-CVE-2014-3581.patch +Patch102: httpd-2.4.10-CVE-2014-3583.patch +Patch103: httpd-2.4.10-CVE-2014-8109.patch License: ASL 2.0 Group: System Environment/Daemons BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root @@ -216,6 +221,11 @@ interface for storing and accessing per-user session data. %patch56 -p1 -b .uniqueid %patch57 -p1 -b .sigint +%patch100 -p1 -b cve20135704 +%patch101 -p1 -b cve20143581 +%patch102 -p1 -b cve20143583 +%patch103 -p1 -b cve20148109 + # Patch in the vendor string sed -i '/^#define PLATFORM/s/Unix/%{vstring}/' os/unix/os.h @@ -669,6 +679,13 @@ rm -rf $RPM_BUILD_ROOT %{_rpmconfigdir}/macros.d/macros.httpd %changelog +* Wed Dec 17 2014 Jan Kaluza - 2.4.10-15 +- core: fix bypassing of mod_headers rules via chunked requests (CVE-2013-5704) +- mod_cache: fix NULL pointer dereference on empty Content-Type (CVE-2014-3581) +- mod_proxy_fcgi: fix a potential crash with long headers (CVE-2014-3583) +- mod_lua: fix handling of the Require line when a LuaAuthzProvider is used + in multiple Require directives with different arguments (CVE-2014-8109) + * Tue Oct 14 2014 Joe Orton - 2.4.10-14 - require apr-util 1.5.x