From c7a45eb49e048236835a7b4eb3f080c4f796c39f Mon Sep 17 00:00:00 2001 From: yangl777 Date: Thu, 14 Aug 2025 03:20:26 +0000 Subject: [PATCH] fix CVE-2025-49812 CVE-2025-23048 CVE-2024-47252 CVE-2024-43204 CVE-2024-42516 and backport patches --- backport-CVE-2024-42516.patch | 310 ++++++++++++++++++ backport-CVE-2024-43204.patch | 41 +++ backport-CVE-2024-47252.patch | 51 +++ backport-CVE-2025-23048.patch | 69 ++++ backport-CVE-2025-49812.patch | 205 ++++++++++++ ...soin-that-caused-sticky-session-keys.patch | 65 ++++ ...ype-when-processing-a-Request_Header.patch | 69 ++++ ...ix-memory-handling-in-output-filters.patch | 76 +++++ ...et_cookie_name-ensure-correct-format.patch | 85 +++++ httpd.spec | 21 +- 10 files changed, 991 insertions(+), 1 deletion(-) create mode 100644 backport-CVE-2024-42516.patch create mode 100644 backport-CVE-2024-43204.patch create mode 100644 backport-CVE-2024-47252.patch create mode 100644 backport-CVE-2025-23048.patch create mode 100644 backport-CVE-2025-49812.patch create mode 100644 backport-Fix-a-regressoin-that-caused-sticky-session-keys.patch create mode 100644 backport-avoid_ap_set_content_type-when-processing-a-Request_Header.patch create mode 100644 backport-mod_lua-Fix-memory-handling-in-output-filters.patch create mode 100644 backport-set_cookie_name-ensure-correct-format.patch diff --git a/backport-CVE-2024-42516.patch b/backport-CVE-2024-42516.patch new file mode 100644 index 0000000..24b87f5 --- /dev/null +++ b/backport-CVE-2024-42516.patch @@ -0,0 +1,310 @@ +From a7a9d814c7c23e990283277230ddd5a9efec27c7 Mon Sep 17 00:00:00 2001 +From: Eric Covener +Date: Mon, 7 Jul 2025 11:59:38 +0000 +Subject: [PATCH] fix header merging + +Reviewed By: rpluem, jorton, ylavic + + + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1927039 13f79535-47bb-0310-9956-ffa450edef68 + +Conflict:NA +Reference:https://github.com/apache/httpd/commit/a7a9d814c7c23e990283277230ddd5a9efec27c7 + +--- + modules/http/http_filters.c | 248 +++++++++++++++++++----------------- + 1 file changed, 128 insertions(+), 120 deletions(-) + +diff --git a/modules/http/http_filters.c b/modules/http/http_filters.c +index b937db2..fd67a84 100644 +--- a/modules/http/http_filters.c ++++ b/modules/http/http_filters.c +@@ -1297,107 +1297,10 @@ typedef struct header_filter_ctx { + int headers_sent; + } header_filter_ctx; + +-AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, +- apr_bucket_brigade *b) ++static void merge_response_headers(request_rec *r, const char **protocol) + { +- request_rec *r = f->r; +- conn_rec *c = r->connection; +- const char *clheader; +- int header_only = (r->header_only || AP_STATUS_IS_HEADER_ONLY(r->status)); +- const char *protocol = NULL; +- apr_bucket *e; +- apr_bucket_brigade *b2; +- header_struct h; +- header_filter_ctx *ctx = f->ctx; +- const char *ctype; +- ap_bucket_error *eb = NULL; +- apr_status_t rv = APR_SUCCESS; +- int recursive_error = 0; +- +- AP_DEBUG_ASSERT(!r->main); +- +- if (!ctx) { +- ctx = f->ctx = apr_pcalloc(r->pool, sizeof(header_filter_ctx)); +- } +- else if (ctx->headers_sent) { +- /* Eat body if response must not have one. */ +- if (header_only) { +- /* Still next filters may be waiting for EOS, so pass it (alone) +- * when encountered and be done with this filter. +- */ +- e = APR_BRIGADE_LAST(b); +- if (e != APR_BRIGADE_SENTINEL(b) && APR_BUCKET_IS_EOS(e)) { +- APR_BUCKET_REMOVE(e); +- apr_brigade_cleanup(b); +- APR_BRIGADE_INSERT_HEAD(b, e); +- ap_remove_output_filter(f); +- rv = ap_pass_brigade(f->next, b); +- } +- apr_brigade_cleanup(b); +- return rv; +- } +- } +- +- for (e = APR_BRIGADE_FIRST(b); +- e != APR_BRIGADE_SENTINEL(b); +- e = APR_BUCKET_NEXT(e)) +- { +- if (AP_BUCKET_IS_ERROR(e) && !eb) { +- eb = e->data; +- continue; +- } +- /* +- * If we see an EOC bucket it is a signal that we should get out +- * of the way doing nothing. +- */ +- if (AP_BUCKET_IS_EOC(e)) { +- ap_remove_output_filter(f); +- return ap_pass_brigade(f->next, b); +- } +- } +- +- if (!ctx->headers_sent && !check_headers(r)) { +- /* We may come back here from ap_die() below, +- * so clear anything from this response. +- */ +- apr_table_clear(r->headers_out); +- apr_table_clear(r->err_headers_out); +- r->content_type = r->content_encoding = NULL; +- r->content_languages = NULL; +- r->clength = r->chunked = 0; +- apr_brigade_cleanup(b); +- +- /* Don't recall ap_die() if we come back here (from its own internal +- * redirect or error response), otherwise we can end up in infinite +- * recursion; better fall through with 500, minimal headers and an +- * empty body (EOS only). +- */ +- if (!check_headers_recursion(r)) { +- ap_die(HTTP_INTERNAL_SERVER_ERROR, r); +- return AP_FILTER_ERROR; +- } +- r->status = HTTP_INTERNAL_SERVER_ERROR; +- e = ap_bucket_eoc_create(c->bucket_alloc); +- APR_BRIGADE_INSERT_TAIL(b, e); +- e = apr_bucket_eos_create(c->bucket_alloc); +- APR_BRIGADE_INSERT_TAIL(b, e); +- ap_set_content_length(r, 0); +- recursive_error = 1; +- } +- else if (eb) { +- int status; +- status = eb->status; +- apr_brigade_cleanup(b); +- ap_die(status, r); +- return AP_FILTER_ERROR; +- } +- +- if (r->assbackwards) { +- r->sent_bodyct = 1; +- ap_remove_output_filter(f); +- rv = ap_pass_brigade(f->next, b); +- goto out; +- } ++ const char *ctype = NULL; ++ const char *clheader = NULL; + + /* + * Now that we are ready to send a response, we need to combine the two +@@ -1427,6 +1330,9 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, + fixup_vary(r); + } + ++ /* determine the protocol and whether we should use keepalives. */ ++ basic_http_header_check(r, protocol); ++ ap_set_keepalive(r); + + /* + * Control cachability for non-cacheable responses if not already set by +@@ -1446,10 +1352,6 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, + apr_table_unset(r->headers_out, "ETag"); + } + +- /* determine the protocol and whether we should use keepalives. */ +- basic_http_header_check(r, &protocol); +- ap_set_keepalive(r); +- + /* 204/304 responses don't have content related headers */ + if (AP_STATUS_IS_HEADER_ONLY(r->status)) { + apr_table_unset(r->headers_out, "Transfer-Encoding"); +@@ -1510,30 +1412,136 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, + && !strcmp(clheader, "0")) { + apr_table_unset(r->headers_out, "Content-Length"); + } ++} + +- b2 = apr_brigade_create(r->pool, c->bucket_alloc); +- basic_http_header(r, b2, protocol); +- +- h.pool = r->pool; +- h.bb = b2; ++AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f, ++ apr_bucket_brigade *b) ++{ ++ request_rec *r = f->r; ++ conn_rec *c = r->connection; ++ int header_only = (r->header_only || AP_STATUS_IS_HEADER_ONLY(r->status)); ++ apr_bucket *e; ++ apr_bucket_brigade *b2; ++ header_struct h; ++ header_filter_ctx *ctx = f->ctx; ++ ap_bucket_error *eb = NULL; ++ apr_status_t rv = APR_SUCCESS; ++ int recursive_error = 0; ++ const char *protocol; + +- send_all_header_fields(&h, r); ++ AP_DEBUG_ASSERT(!r->main); + +- terminate_header(b2); ++ if (!ctx) { ++ ctx = f->ctx = apr_pcalloc(r->pool, sizeof(header_filter_ctx)); ++ } ++ else if (ctx->headers_sent) { ++ /* Eat body if response must not have one. */ ++ if (header_only) { ++ /* Still next filters may be waiting for EOS, so pass it (alone) ++ * when encountered and be done with this filter. ++ */ ++ e = APR_BRIGADE_LAST(b); ++ if (e != APR_BRIGADE_SENTINEL(b) && APR_BUCKET_IS_EOS(e)) { ++ APR_BUCKET_REMOVE(e); ++ apr_brigade_cleanup(b); ++ APR_BRIGADE_INSERT_HEAD(b, e); ++ ap_remove_output_filter(f); ++ rv = ap_pass_brigade(f->next, b); ++ } ++ apr_brigade_cleanup(b); ++ return rv; ++ } ++ } + +- if (header_only) { +- e = APR_BRIGADE_LAST(b); +- if (e != APR_BRIGADE_SENTINEL(b) && APR_BUCKET_IS_EOS(e)) { +- APR_BUCKET_REMOVE(e); +- APR_BRIGADE_INSERT_TAIL(b2, e); ++ for (e = APR_BRIGADE_FIRST(b); ++ e != APR_BRIGADE_SENTINEL(b); ++ e = APR_BUCKET_NEXT(e)) ++ { ++ if (AP_BUCKET_IS_ERROR(e) && !eb) { ++ eb = e->data; ++ continue; ++ } ++ /* ++ * If we see an EOC bucket it is a signal that we should get out ++ * of the way doing nothing. ++ */ ++ if (AP_BUCKET_IS_EOC(e)) { + ap_remove_output_filter(f); ++ return ap_pass_brigade(f->next, b); ++ } ++ } ++ ++ if (!ctx->headers_sent) { ++ merge_response_headers(r, &protocol); ++ if (!check_headers(r)) { ++ /* We may come back here from ap_die() below, ++ * so clear anything from this response. ++ */ ++ apr_table_clear(r->headers_out); ++ apr_table_clear(r->err_headers_out); ++ r->content_type = r->content_encoding = NULL; ++ r->content_languages = NULL; ++ r->clength = r->chunked = 0; ++ apr_brigade_cleanup(b); ++ ++ /* Don't recall ap_die() if we come back here (from its own internal ++ * redirect or error response), otherwise we can end up in infinite ++ * recursion; better fall through with 500, minimal headers and an ++ * empty body (EOS only). ++ */ ++ if (!check_headers_recursion(r)) { ++ ap_die(HTTP_INTERNAL_SERVER_ERROR, r); ++ return AP_FILTER_ERROR; ++ } ++ r->status = HTTP_INTERNAL_SERVER_ERROR; ++ e = ap_bucket_eoc_create(c->bucket_alloc); ++ APR_BRIGADE_INSERT_TAIL(b, e); ++ e = apr_bucket_eos_create(c->bucket_alloc); ++ APR_BRIGADE_INSERT_TAIL(b, e); ++ ap_set_content_length(r, 0); ++ recursive_error = 1; ++ } ++ else if (eb) { ++ int status; ++ status = eb->status; ++ apr_brigade_cleanup(b); ++ ap_die(status, r); ++ return AP_FILTER_ERROR; + } +- apr_brigade_cleanup(b); + } + +- rv = ap_pass_brigade(f->next, b2); +- apr_brigade_cleanup(b2); +- ctx->headers_sent = 1; ++ if (r->assbackwards) { ++ r->sent_bodyct = 1; ++ ap_remove_output_filter(f); ++ rv = ap_pass_brigade(f->next, b); ++ goto out; ++ } ++ ++ if (!ctx->headers_sent) { ++ b2 = apr_brigade_create(r->pool, c->bucket_alloc); ++ basic_http_header(r, b2, protocol); ++ ++ h.pool = r->pool; ++ h.bb = b2; ++ ++ send_all_header_fields(&h, r); ++ ++ terminate_header(b2); ++ ++ if (header_only) { ++ e = APR_BRIGADE_LAST(b); ++ if (e != APR_BRIGADE_SENTINEL(b) && APR_BUCKET_IS_EOS(e)) { ++ APR_BUCKET_REMOVE(e); ++ APR_BRIGADE_INSERT_TAIL(b2, e); ++ ap_remove_output_filter(f); ++ } ++ apr_brigade_cleanup(b); ++ } ++ ++ rv = ap_pass_brigade(f->next, b2); ++ apr_brigade_cleanup(b2); ++ ctx->headers_sent = 1; ++ } + + if (rv != APR_SUCCESS || header_only) { + goto out; +-- +2.33.0 + diff --git a/backport-CVE-2024-43204.patch b/backport-CVE-2024-43204.patch new file mode 100644 index 0000000..0455e5f --- /dev/null +++ b/backport-CVE-2024-43204.patch @@ -0,0 +1,41 @@ +From b3d3ded288815bea063c3bf77dd80b26446f76ce Mon Sep 17 00:00:00 2001 +From: Eric Covener +Date: Mon, 7 Jul 2025 12:01:02 +0000 +Subject: [PATCH] backport 1927032 from trunk + + header only + +Reviewed By: rpluem, jorton, ylavic + + + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1927040 13f79535-47bb-0310-9956-ffa450edef68 + +Conflict:NA +Reference:https://github.com/apache/httpd/commit/b3d3ded288815bea063c3bf77dd80b26446f76ce +--- + modules/metadata/mod_headers.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/modules/metadata/mod_headers.c b/modules/metadata/mod_headers.c +index 57da3fc538d..f08382d61f0 100644 +--- a/modules/metadata/mod_headers.c ++++ b/modules/metadata/mod_headers.c +@@ -784,7 +784,7 @@ static int do_headers_fixup(request_rec *r, apr_table_t *headers, + case hdr_set: + if (r->headers_in != headers && + !ap_cstr_casecmp(hdr->header, "Content-Type")) { +- ap_set_content_type_ex(r, process_tags(hdr, r), 1); ++ ap_set_content_type(r, process_tags(hdr, r)); + } + apr_table_setn(headers, hdr->header, process_tags(hdr, r)); + break; +@@ -792,7 +792,7 @@ static int do_headers_fixup(request_rec *r, apr_table_t *headers, + if (NULL == apr_table_get(headers, hdr->header)) { + if (r->headers_in != headers && + !ap_cstr_casecmp(hdr->header, "Content-Type")) { +- ap_set_content_type_ex(r, process_tags(hdr, r), 1); ++ ap_set_content_type(r, process_tags(hdr, r)); + } + apr_table_setn(headers, hdr->header, process_tags(hdr, r)); + } diff --git a/backport-CVE-2024-47252.patch b/backport-CVE-2024-47252.patch new file mode 100644 index 0000000..a991245 --- /dev/null +++ b/backport-CVE-2024-47252.patch @@ -0,0 +1,51 @@ +From c01e60707048be14a510f0a92128a5227923215c Mon Sep 17 00:00:00 2001 +From: Eric Covener +Date: Mon, 7 Jul 2025 12:03:42 +0000 +Subject: [PATCH] backport 1927034 from trunk + + escape ssl vars + +Reviewed By: rpluem, jorton, covener, ylavic + + + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1927042 13f79535-47bb-0310-9956-ffa450edef68 + +Conflict:NA +Reference:https://github.com/apache/httpd/commit/c01e60707048be14a510f0a92128a5227923215c + +--- + modules/ssl/ssl_engine_vars.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/modules/ssl/ssl_engine_vars.c b/modules/ssl/ssl_engine_vars.c +index 99b22a2..e3d399f 100644 +--- a/modules/ssl/ssl_engine_vars.c ++++ b/modules/ssl/ssl_engine_vars.c +@@ -1207,8 +1207,9 @@ static const char *ssl_var_log_handler_c(request_rec *r, char *a) + result = "-"; + else if (strEQ(a, "errstr")) + result = (char *)sslconn->verify_error; +- if (result != NULL && result[0] == NUL) +- result = NULL; ++ if (result) { ++ result = *result ? ap_escape_logitem(r->pool, result) : NULL; ++ } + return result; + } + +@@ -1221,8 +1222,9 @@ static const char *ssl_var_log_handler_x(request_rec *r, char *a) + char *result; + + result = ssl_var_lookup(r->pool, r->server, r->connection, r, a); +- if (result != NULL && result[0] == NUL) +- result = NULL; ++ if (result) { ++ result = *result ? ap_escape_logitem(r->pool, result) : NULL; ++ } + return result; + } + +-- +2.33.0 + diff --git a/backport-CVE-2025-23048.patch b/backport-CVE-2025-23048.patch new file mode 100644 index 0000000..da77355 --- /dev/null +++ b/backport-CVE-2025-23048.patch @@ -0,0 +1,69 @@ +From c4cfa50c9068e8b8134c530ab21674e77d1278a2 Mon Sep 17 00:00:00 2001 +From: Eric Covener +Date: Mon, 7 Jul 2025 12:04:49 +0000 +Subject: [PATCH] backport 1927035 from trunk + + update SNI validation + +Reviewed By: rpluem, jorton, covener, ylavic + + + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1927043 13f79535-47bb-0310-9956-ffa450edef68 + +Conflict:NA +Reference:https://github.com/apache/httpd/commit/c4cfa50c9068e8b8134c530ab21674e77d1278a2 + +--- + modules/ssl/ssl_engine_kernel.c | 28 +++++++++++++++------------- + 1 file changed, 15 insertions(+), 13 deletions(-) + +diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c +index fa70142..8b14e35 100644 +--- a/modules/ssl/ssl_engine_kernel.c ++++ b/modules/ssl/ssl_engine_kernel.c +@@ -295,19 +295,6 @@ int ssl_hook_ReadReq(request_rec *r) + " provided in HTTP request", servername); + return HTTP_BAD_REQUEST; + } +- if (r->server != handshakeserver +- && !ssl_server_compatible(sslconn->server, r->server)) { +- /* +- * The request does not select the virtual host that was +- * selected by the SNI and its SSL parameters are different +- */ +- +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02032) +- "Hostname %s provided via SNI and hostname %s provided" +- " via HTTP have no compatible SSL setup", +- servername, r->hostname); +- return HTTP_MISDIRECTED_REQUEST; +- } + } + else if (((sc->strict_sni_vhost_check == SSL_ENABLED_TRUE) + || hssc->strict_sni_vhost_check == SSL_ENABLED_TRUE) +@@ -328,6 +315,21 @@ int ssl_hook_ReadReq(request_rec *r) + "which is required to access this server.
\n"); + return HTTP_FORBIDDEN; + } ++ if (r->server != handshakeserver ++ && !ssl_server_compatible(sslconn->server, r->server)) { ++ /* ++ * The request does not select the virtual host that was ++ * selected for handshaking and its SSL parameters are different ++ */ ++ ++ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02032) ++ "Hostname %s %s and hostname %s provided" ++ " via HTTP have no compatible SSL setup", ++ servername ? servername : handshakeserver->server_hostname, ++ servername ? "provided via SNI" : "(default host as no SNI was provided)", ++ r->hostname); ++ return HTTP_MISDIRECTED_REQUEST; ++ } + } + #endif + modssl_set_app_data2(ssl, r); +-- +2.33.0 + diff --git a/backport-CVE-2025-49812.patch b/backport-CVE-2025-49812.patch new file mode 100644 index 0000000..73a48f4 --- /dev/null +++ b/backport-CVE-2025-49812.patch @@ -0,0 +1,205 @@ +From 87a7351c755c9ef8ab386e3090e44838c2a06d48 Mon Sep 17 00:00:00 2001 +From: Eric Covener +Date: Mon, 7 Jul 2025 12:09:30 +0000 +Subject: [PATCH] backport 1927037 from trunk + + remove antiquated 'SSLEngine optional' TLS upgrade + +Reviewed By: rpluem, jorton, covener + + + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1927045 13f79535-47bb-0310-9956-ffa450edef68 + +Conflict:NA +Reference:https://github.com/apache/httpd/commit/87a7351c755c9ef8ab386e3090e44838c2a06d48 + +--- + modules/ssl/ssl_engine_config.c | 6 ++- + modules/ssl/ssl_engine_init.c | 6 +-- + modules/ssl/ssl_engine_kernel.c | 86 --------------------------------- + modules/ssl/ssl_private.h | 1 - + 4 files changed, 7 insertions(+), 92 deletions(-) + +diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c +index 37ed854..d684b42 100644 +--- a/modules/ssl/ssl_engine_config.c ++++ b/modules/ssl/ssl_engine_config.c +@@ -739,11 +739,13 @@ const char *ssl_cmd_SSLEngine(cmd_parms *cmd, void *dcfg, const char *arg) + return NULL; + } + else if (!strcasecmp(arg, "Optional")) { +- sc->enabled = SSL_ENABLED_OPTIONAL; ++ sc->enabled = SSL_ENABLED_FALSE; ++ ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, cmd->server, APLOGNO(10510) ++ "'SSLEngine optional' is no longer supported"); + return NULL; + } + +- return "Argument must be On, Off, or Optional"; ++ return "Argument must be On or Off"; + } + + const char *ssl_cmd_SSLFIPS(cmd_parms *cmd, void *dcfg, int flag) +diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c +index b8150a9..fd833b7 100644 +--- a/modules/ssl/ssl_engine_init.c ++++ b/modules/ssl/ssl_engine_init.c +@@ -418,7 +418,7 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, + &ssl_module); + + sc = mySrvConfig(s); +- if (sc->enabled == SSL_ENABLED_TRUE || sc->enabled == SSL_ENABLED_OPTIONAL) { ++ if (sc->enabled == SSL_ENABLED_TRUE) { + if ((rv = ssl_run_init_server(s, p, 0, sc->server->ssl_ctx)) != APR_SUCCESS) { + return rv; + } +@@ -1984,9 +1984,9 @@ apr_status_t ssl_init_ConfigureServer(server_rec *s, + &ssl_module); + apr_status_t rv; + +- /* Initialize the server if SSL is enabled or optional. ++ /* Initialize the server if SSL is enabled. + */ +- if ((sc->enabled == SSL_ENABLED_TRUE) || (sc->enabled == SSL_ENABLED_OPTIONAL)) { ++ if (sc->enabled == SSL_ENABLED_TRUE) { + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, APLOGNO(01914) + "Configuring server %s for SSL protocol", sc->vhost_id); + if ((rv = ssl_init_server_ctx(s, p, ptemp, sc, pphrases)) +diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c +index 5211a0d..fa70142 100644 +--- a/modules/ssl/ssl_engine_kernel.c ++++ b/modules/ssl/ssl_engine_kernel.c +@@ -38,59 +38,6 @@ static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn); + static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s); + #endif + +-#define SWITCH_STATUS_LINE "HTTP/1.1 101 Switching Protocols" +-#define UPGRADE_HEADER "Upgrade: TLS/1.0, HTTP/1.1" +-#define CONNECTION_HEADER "Connection: Upgrade" +- +-/* Perform an upgrade-to-TLS for the given request, per RFC 2817. */ +-static apr_status_t upgrade_connection(request_rec *r) +-{ +- struct conn_rec *conn = r->connection; +- apr_bucket_brigade *bb; +- SSLConnRec *sslconn; +- apr_status_t rv; +- SSL *ssl; +- +- ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02028) +- "upgrading connection to TLS"); +- +- bb = apr_brigade_create(r->pool, conn->bucket_alloc); +- +- rv = ap_fputs(conn->output_filters, bb, SWITCH_STATUS_LINE CRLF +- UPGRADE_HEADER CRLF CONNECTION_HEADER CRLF CRLF); +- if (rv == APR_SUCCESS) { +- APR_BRIGADE_INSERT_TAIL(bb, +- apr_bucket_flush_create(conn->bucket_alloc)); +- rv = ap_pass_brigade(conn->output_filters, bb); +- } +- +- if (rv) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02029) +- "failed to send 101 interim response for connection " +- "upgrade"); +- return rv; +- } +- +- ssl_init_ssl_connection(conn, r); +- +- sslconn = myConnConfig(conn); +- ssl = sslconn->ssl; +- +- /* Perform initial SSL handshake. */ +- SSL_set_accept_state(ssl); +- SSL_do_handshake(ssl); +- +- if (!SSL_is_init_finished(ssl)) { +- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02030) +- "TLS upgrade handshake failed"); +- ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, r->server); +- +- return APR_ECONNABORTED; +- } +- +- return APR_SUCCESS; +-} +- + /* Perform a speculative (and non-blocking) read from the connection + * filters for the given request, to determine whether there is any + * pending data to read. Return non-zero if there is, else zero. */ +@@ -270,40 +217,17 @@ int ssl_hook_ReadReq(request_rec *r) + { + SSLSrvConfigRec *sc = mySrvConfig(r->server); + SSLConnRec *sslconn; +- const char *upgrade; + #ifdef HAVE_TLSEXT + const char *servername; + #endif + SSL *ssl; + +- /* Perform TLS upgrade here if "SSLEngine optional" is configured, +- * SSL is not already set up for this connection, and the client +- * has sent a suitable Upgrade header. */ +- if (sc->enabled == SSL_ENABLED_OPTIONAL && !myConnConfig(r->connection) +- && (upgrade = apr_table_get(r->headers_in, "Upgrade")) != NULL +- && ap_find_token(r->pool, upgrade, "TLS/1.0")) { +- if (upgrade_connection(r)) { +- return AP_FILTER_ERROR; +- } +- } +- + /* If we are on a slave connection, we do not expect to have an SSLConnRec, + * but our master connection might. */ + sslconn = myConnConfig(r->connection); + if (!(sslconn && sslconn->ssl) && r->connection->master) { + sslconn = myConnConfig(r->connection->master); + } +- +- /* If "SSLEngine optional" is configured, this is not an SSL +- * connection, and this isn't a subrequest, send an Upgrade +- * response header. Note this must happen before map_to_storage +- * and OPTIONS * request processing is completed. +- */ +- if (sc->enabled == SSL_ENABLED_OPTIONAL && !(sslconn && sslconn->ssl) +- && !r->main) { +- apr_table_setn(r->headers_out, "Upgrade", "TLS/1.0, HTTP/1.1"); +- apr_table_mergen(r->headers_out, "Connection", "upgrade"); +- } + + if (!sslconn) { + return DECLINED; +@@ -1239,16 +1163,6 @@ int ssl_hook_Access(request_rec *r) + * Support for SSLRequireSSL directive + */ + if (dc->bSSLRequired && !ssl) { +- if ((sc->enabled == SSL_ENABLED_OPTIONAL) && !r->connection->master) { +- /* This vhost was configured for optional SSL, just tell the +- * client that we need to upgrade. +- */ +- apr_table_setn(r->err_headers_out, "Upgrade", "TLS/1.0, HTTP/1.1"); +- apr_table_setn(r->err_headers_out, "Connection", "Upgrade"); +- +- return HTTP_UPGRADE_REQUIRED; +- } +- + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02219) + "access to %s failed, reason: %s", + r->filename, "SSL connection required"); +diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h +index c194270..12e1cc2 100644 +--- a/modules/ssl/ssl_private.h ++++ b/modules/ssl/ssl_private.h +@@ -470,7 +470,6 @@ typedef enum { + SSL_ENABLED_UNSET = UNSET, + SSL_ENABLED_FALSE = 0, + SSL_ENABLED_TRUE = 1, +- SSL_ENABLED_OPTIONAL = 3 + } ssl_enabled_t; + + /** +-- +2.33.0 + diff --git a/backport-Fix-a-regressoin-that-caused-sticky-session-keys.patch b/backport-Fix-a-regressoin-that-caused-sticky-session-keys.patch new file mode 100644 index 0000000..abe0d6a --- /dev/null +++ b/backport-Fix-a-regressoin-that-caused-sticky-session-keys.patch @@ -0,0 +1,65 @@ +From f82a9e886f42db063fb87c2973b33a88320ae65b Mon Sep 17 00:00:00 2001 +From: Ruediger Pluem +Date: Wed, 4 Jun 2025 07:36:11 +0000 +Subject: [PATCH] Merge r1925109 from trunk: + +* Temporarily add back the query string to the URL as it might contain the + routing information for sticky sessions. + +PR: 69443 + +Reviewed by: rpluem, covener, ylavic + + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1926107 13f79535-47bb-0310-9956-ffa450edef68 + +Conflict:changelog delete +Reference:https://github.com/apache/httpd/commit/f82a9e886f42db063fb87c2973b33a88320ae65b + +--- + changes-entries/pr69443.txt | 3 +++ + modules/proxy/mod_proxy_balancer.c | 14 +++++++++++++- + 2 files changed, 16 insertions(+), 1 deletion(-) + create mode 100644 changes-entries/pr69443.txt + +diff --git a/changes-entries/pr69443.txt b/changes-entries/pr69443.txt +new file mode 100644 +index 0000000..97de769 +--- /dev/null ++++ b/changes-entries/pr69443.txt +@@ -0,0 +1,3 @@ ++ *) mod_proxy_balancer: Fix a regression that caused stickysession keys no ++ longer be recognized if they are provided as query parameter in the URL. ++ PR 69443 [Ruediger Pluem] +diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c +index 3c0f5a8..4a89842 100644 +--- a/modules/proxy/mod_proxy_balancer.c ++++ b/modules/proxy/mod_proxy_balancer.c +@@ -315,11 +315,23 @@ static proxy_worker *find_session_route(proxy_balancer *balancer, + char **url) + { + proxy_worker *worker = NULL; ++ char *url_with_qs; + + if (!*balancer->s->sticky) + return NULL; ++ /* ++ * The route might be contained in the query string and *url is not ++ * supposed to contain the query string. Hence add it temporarily if ++ * present. ++ */ ++ if (r->args) { ++ url_with_qs = apr_pstrcat(r->pool, *url, "?", r->args, NULL); ++ } ++ else { ++ url_with_qs = *url; ++ } + /* Try to find the sticky route inside url */ +- *route = get_path_param(r->pool, *url, balancer->s->sticky_path, balancer->s->scolonsep); ++ *route = get_path_param(r->pool, url_with_qs, balancer->s->sticky_path, balancer->s->scolonsep); + if (*route) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01159) + "Found value %s for stickysession %s", +-- +2.33.0 + diff --git a/backport-avoid_ap_set_content_type-when-processing-a-Request_Header.patch b/backport-avoid_ap_set_content_type-when-processing-a-Request_Header.patch new file mode 100644 index 0000000..4ff3e93 --- /dev/null +++ b/backport-avoid_ap_set_content_type-when-processing-a-Request_Header.patch @@ -0,0 +1,69 @@ +From 6764774d51f3dcb07e79779c64a463d3c112b53f Mon Sep 17 00:00:00 2001 +From: Yann Ylavic +Date: Tue, 10 Jun 2025 10:58:15 +0000 +Subject: [PATCH] avoid ap_set_content_type when processing a _Request_Header + set|edit|unset Content-Type. + +identified by ylavic + + +Merges r1820750 from trunk +Submitted by: covener +Reviewed by: covener, rpluem, jorton + + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1926323 13f79535-47bb-0310-9956-ffa450edef68 + +Conflict:CHANGES delete +Reference:https://github.com/apache/httpd/commit/6764774d51f3dcb07e79779c64a463d3c112b53f + +--- + modules/metadata/mod_headers.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/modules/metadata/mod_headers.c b/modules/metadata/mod_headers.c +index 4838bd6..57da3fc 100644 +--- a/modules/metadata/mod_headers.c ++++ b/modules/metadata/mod_headers.c +@@ -782,14 +782,16 @@ static int do_headers_fixup(request_rec *r, apr_table_t *headers, + } + break; + case hdr_set: +- if (!ap_cstr_casecmp(hdr->header, "Content-Type")) { ++ if (r->headers_in != headers && ++ !ap_cstr_casecmp(hdr->header, "Content-Type")) { + ap_set_content_type_ex(r, process_tags(hdr, r), 1); + } + apr_table_setn(headers, hdr->header, process_tags(hdr, r)); + break; + case hdr_setifempty: + if (NULL == apr_table_get(headers, hdr->header)) { +- if (!ap_cstr_casecmp(hdr->header, "Content-Type")) { ++ if (r->headers_in != headers && ++ !ap_cstr_casecmp(hdr->header, "Content-Type")) { + ap_set_content_type_ex(r, process_tags(hdr, r), 1); + } + apr_table_setn(headers, hdr->header, process_tags(hdr, r)); +@@ -797,6 +799,10 @@ static int do_headers_fixup(request_rec *r, apr_table_t *headers, + break; + case hdr_unset: + apr_table_unset(headers, hdr->header); ++ if (r->headers_in != headers && ++ !ap_cstr_casecmp(hdr->header, "Content-Type")) { ++ ap_set_content_type(r, NULL); ++ } + break; + case hdr_echo: + v.r = r; +@@ -809,7 +815,7 @@ static int do_headers_fixup(request_rec *r, apr_table_t *headers, + const char *repl = process_regexp(hdr, r->content_type, r); + if (repl == NULL) + return 0; +- ap_set_content_type_ex(r, repl, 1); ++ if (r->headers_in != headers) ap_set_content_type_ex(r, repl, 1); + } + if (apr_table_get(headers, hdr->header)) { + edit_do ed; +-- +2.33.0 + diff --git a/backport-mod_lua-Fix-memory-handling-in-output-filters.patch b/backport-mod_lua-Fix-memory-handling-in-output-filters.patch new file mode 100644 index 0000000..f311bde --- /dev/null +++ b/backport-mod_lua-Fix-memory-handling-in-output-filters.patch @@ -0,0 +1,76 @@ +From 3dec975c92ed1e2d5e60c88bbc331edd37ab49d7 Mon Sep 17 00:00:00 2001 +From: Joe Orton +Date: Mon, 2 Jun 2025 14:48:53 +0000 +Subject: [PATCH] Merge r1924095 from trunk: + +mod_lua: Fix memory handling in output filters. + +* modules/lua/mod_lua.c (lua_output_filter_handle): Fix brigade + iteration to use constant memory. + +Submitted by: G.Grandes +PR: 69590 +Github: closes #517 +Reviewed by: jorton, rpluem, covener + + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1926063 13f79535-47bb-0310-9956-ffa450edef68 + +Conflict:NA +Reference:https://github.com/apache/httpd/commit/3dec975c92ed1e2d5e60c88bbc331edd37ab49d7 + +--- + changes-entries/pr69590.txt | 2 ++ + modules/lua/mod_lua.c | 13 ++++++++----- + 2 files changed, 10 insertions(+), 5 deletions(-) + create mode 100644 changes-entries/pr69590.txt + +diff --git a/changes-entries/pr69590.txt b/changes-entries/pr69590.txt +new file mode 100644 +index 0000000..ebf3f1a +--- /dev/null ++++ b/changes-entries/pr69590.txt +@@ -0,0 +1,2 @@ ++ *) mod_lua: Fix memory handling in LuaOutputFilter. PR 69590. ++ [Guillermo Grandes ] +diff --git a/modules/lua/mod_lua.c b/modules/lua/mod_lua.c +index 303890e..c38c557 100644 +--- a/modules/lua/mod_lua.c ++++ b/modules/lua/mod_lua.c +@@ -473,14 +473,16 @@ static apr_status_t lua_output_filter_handle(ap_filter_t *f, apr_bucket_brigade + L = ctx->L; + /* While the Lua function is still yielding, pass in buckets to the coroutine */ + if (!ctx->broken) { +- for (pbktIn = APR_BRIGADE_FIRST(pbbIn); +- pbktIn != APR_BRIGADE_SENTINEL(pbbIn); +- pbktIn = APR_BUCKET_NEXT(pbktIn)) +- { ++ while (!APR_BRIGADE_EMPTY(pbbIn)) { + const char *data; + apr_size_t len; + apr_bucket *pbktOut; + ++ pbktIn = APR_BRIGADE_FIRST(pbbIn); ++ if (APR_BUCKET_IS_EOS(pbktIn)) { ++ break; ++ } ++ + /* read the bucket */ + apr_bucket_read(pbktIn,&data,&len,APR_BLOCK_READ); + +@@ -514,10 +516,11 @@ static apr_status_t lua_output_filter_handle(ap_filter_t *f, apr_bucket_brigade + lua_tostring(L, -1)); + return HTTP_INTERNAL_SERVER_ERROR; + } ++ apr_bucket_delete(pbktIn); + } + /* If we've safely reached the end, do a final call to Lua to allow for any + finishing moves by the script, such as appending a tail. */ +- if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(pbbIn))) { ++ if (!APR_BRIGADE_EMPTY(pbbIn) && APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(pbbIn))) { + apr_bucket *pbktEOS; + lua_pushnil(L); + lua_setglobal(L, "bucket"); +-- +2.33.0 + diff --git a/backport-set_cookie_name-ensure-correct-format.patch b/backport-set_cookie_name-ensure-correct-format.patch new file mode 100644 index 0000000..fcca574 --- /dev/null +++ b/backport-set_cookie_name-ensure-correct-format.patch @@ -0,0 +1,85 @@ +From c4218c88fe078570e7439c652a21f4773a432a76 Mon Sep 17 00:00:00 2001 +From: Yann Ylavic +Date: Tue, 10 Jun 2025 11:00:37 +0000 +Subject: [PATCH] mod_session_dbd: set_cookie_name: ensure correct format + +If args is an empty string, apr_strtok will return NULL and *last will never get set which results in a SIGSEGV in apr_isspace check + +Submitted by: Thomas Meyer + +Github: closes #503 + + +Follow-up to r1922931. + +In set_cookie_name() and set_cookie_name2(), now that the empty 'name' argument is explicitly handled, the error message in check_string() can be simplified because the cookie name can't be empty anymore when this function is called. + + +Add a change entry to give credits to the author. + + +Merges r1922931, r1926188, r1926189 trunk +Submitted by: covener, jailletc36, jailletc36 +Reviewed by: jailletc36, rpluem, ylavic + + +git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1926325 13f79535-47bb-0310-9956-ffa450edef68 + +Conflict:NA +Reference:https://github.com/apache/httpd/commit/c4218c88fe078570e7439c652a21f4773a432a76 + +--- + changes-entries/SessionDBDCookieName.txt | 3 +++ + modules/session/mod_session_dbd.c | 12 +++++++++++- + 2 files changed, 14 insertions(+), 1 deletion(-) + create mode 100644 changes-entries/SessionDBDCookieName.txt + +diff --git a/changes-entries/SessionDBDCookieName.txt b/changes-entries/SessionDBDCookieName.txt +new file mode 100644 +index 0000000..76c0aa1 +--- /dev/null ++++ b/changes-entries/SessionDBDCookieName.txt +@@ -0,0 +1,3 @@ ++ *) mod_session_dbd: ensure format used with SessionDBDCookieName and ++ SessionDBDCookieName2 are correct. ++ Github #503 [Thomas Meyer ] +diff --git a/modules/session/mod_session_dbd.c b/modules/session/mod_session_dbd.c +index f683da2..65af937 100644 +--- a/modules/session/mod_session_dbd.c ++++ b/modules/session/mod_session_dbd.c +@@ -537,7 +537,7 @@ static const char *check_string(cmd_parms * cmd, const char *string) + { + if (APR_SUCCESS != ap_cookie_check_string(string)) { + return apr_pstrcat(cmd->pool, cmd->directive->directive, +- " cannot be empty, or contain '=', ';' or '&'.", ++ " cannot contain '=', ';' or '&'.", + NULL); + } + return NULL; +@@ -571,6 +571,11 @@ static const char *set_cookie_name(cmd_parms * cmd, void *config, const char *ar + char *line = apr_pstrdup(cmd->pool, args); + session_dbd_dir_conf *conf = (session_dbd_dir_conf *) config; + char *cookie = apr_strtok(line, " \t", &last); ++ if (!cookie) { ++ return apr_pstrcat(cmd->pool, cmd->directive->directive, ++ " requires at least one argument!", ++ NULL); ++ } + conf->name = cookie; + conf->name_set = 1; + while (apr_isspace(*last)) { +@@ -586,6 +591,11 @@ static const char *set_cookie_name2(cmd_parms * cmd, void *config, const char *a + char *line = apr_pstrdup(cmd->pool, args); + session_dbd_dir_conf *conf = (session_dbd_dir_conf *) config; + char *cookie = apr_strtok(line, " \t", &last); ++ if (!cookie) { ++ return apr_pstrcat(cmd->pool, cmd->directive->directive, ++ " requires at least one argument!", ++ NULL); ++ } + conf->name2 = cookie; + conf->name2_set = 1; + while (apr_isspace(*last)) { +-- +2.33.0 + diff --git a/httpd.spec b/httpd.spec index 188e9ae..d961dbc 100644 --- a/httpd.spec +++ b/httpd.spec @@ -8,7 +8,7 @@ Name: httpd Summary: Apache HTTP Server Version: 2.4.51 -Release: 24 +Release: 25 License: ASL 2.0 URL: https://httpd.apache.org/ Source0: https://archive.apache.org/dist/httpd/httpd-%{version}.tar.bz2 @@ -133,6 +133,15 @@ Patch79: backport-Fix-the-handling-of-the-stickysession-configuration-p Patch80: backport-Fix-possible-crash-on-error-path.patch Patch81: backport-Check-SSL_CTX_new-return-value.patch Patch82: backport-Report-invalid-Options-argument-when-parsing-AllowOverride-directives.patch +Patch83: backport-mod_lua-Fix-memory-handling-in-output-filters.patch +Patch84: backport-Fix-a-regressoin-that-caused-sticky-session-keys.patch +Patch85: backport-avoid_ap_set_content_type-when-processing-a-Request_Header.patch +Patch86: backport-set_cookie_name-ensure-correct-format.patch +Patch87: backport-CVE-2025-49812.patch +Patch88: backport-CVE-2025-23048.patch +patch89: backport-CVE-2024-47252.patch +Patch90: backport-CVE-2024-43204.patch +Patch91: backport-CVE-2024-42516.patch BuildRequires: gcc autoconf pkgconfig findutils xmlto perl-interpreter perl-generators systemd-devel BuildRequires: zlib-devel libselinux-devel lua-devel brotli-devel @@ -569,6 +578,16 @@ exit $rv %{_rpmconfigdir}/macros.d/macros.httpd %changelog +* Thu Aug 14 2025 yanglu - 2.4.51-25 +- Type:CVE +- CVE:CVE-2025-49812,CVE-2025-23048,CVE-2024-47252,CVE-2024-43204,CVE-2024-42516 +- SUG:NA +- DESC:fix CVE-2025-49812 CVE-2025-23048 CVE-2024-47252 CVE-2024-43204 CVE-2024-42516 + mod_lua: Fix memory handling in output filters. + Fix a regression that caused stickysession keys + avoid ap_set_content_type when processing a _Request_Header + set_cookie_name: ensure correct format + * Wed Apr 16 2025 xingwei - 2.4.51-24 - Type:bugfix - CVE:NA -- Gitee