2 Commits

Author SHA256 Message Date
356bfd0a6f Fix 4 bugs/CVEs.
- Fix the following bugs and CVEs:
  * bsc#1254511 / CVE-2025-55753
  * bsc#1254512 / CVE-2025-58098
  * bsc#1254514 / CVE-2025-65082
  * bsc#1254515 / CVE-2025-66200
- Add patches:
  * CVE-2025-55753.patch
  * CVE-2025-58098.patch
  * CVE-2025-65082.patch
  * CVE-2025-66200.patch
2025-12-16 21:16:44 +01:00
1aaedef3aa Sync changes to SLFO-1.2 branch 2025-08-20 09:03:01 +02:00
21 changed files with 5666 additions and 133 deletions

303
CVE-2024-42516.patch Normal file
View File

@@ -0,0 +1,303 @@
From a7a9d814c7c23e990283277230ddd5a9efec27c7 Mon Sep 17 00:00:00 2001
From: Eric Covener <covener@apache.org>
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
---
modules/http/http_filters.c | 248 +++++++++++++++++++-----------------
1 file changed, 128 insertions(+), 120 deletions(-)
Index: httpd-2.4.58/modules/http/http_filters.c
===================================================================
--- httpd-2.4.58.orig/modules/http/http_filters.c
+++ httpd-2.4.58/modules/http/http_filters.c
@@ -1300,107 +1300,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
@@ -1430,6 +1333,9 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_
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
@@ -1449,10 +1355,6 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_
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");
@@ -1520,30 +1422,136 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_
&& conf->http_cl_head_zero != AP_HTTP_CL_HEAD_ZERO_ENABLE) {
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;

37
CVE-2024-43204.patch Normal file
View File

@@ -0,0 +1,37 @@
From b3d3ded288815bea063c3bf77dd80b26446f76ce Mon Sep 17 00:00:00 2001
From: Eric Covener <covener@apache.org>
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
---
modules/metadata/mod_headers.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
Index: httpd-2.4.51/modules/metadata/mod_headers.c
===================================================================
--- httpd-2.4.51.orig/modules/metadata/mod_headers.c
+++ httpd-2.4.51/modules/metadata/mod_headers.c
@@ -783,14 +783,14 @@ static int do_headers_fixup(request_rec
break;
case hdr_set:
if (!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;
case hdr_setifempty:
if (NULL == apr_table_get(headers, hdr->header)) {
if (!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));
}

44
CVE-2024-47252.patch Normal file
View File

@@ -0,0 +1,44 @@
From c01e60707048be14a510f0a92128a5227923215c Mon Sep 17 00:00:00 2001
From: Eric Covener <covener@apache.org>
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
---
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 418d849e00e..4060c0f6a63 100644
--- a/modules/ssl/ssl_engine_vars.c
+++ b/modules/ssl/ssl_engine_vars.c
@@ -1208,8 +1208,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;
}
@@ -1222,8 +1223,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;
}

62
CVE-2025-23048.patch Normal file
View File

@@ -0,0 +1,62 @@
From c4cfa50c9068e8b8134c530ab21674e77d1278a2 Mon Sep 17 00:00:00 2001
From: Eric Covener <covener@apache.org>
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
---
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 9c510218441..d912a874dd9 100644
--- a/modules/ssl/ssl_engine_kernel.c
+++ b/modules/ssl/ssl_engine_kernel.c
@@ -371,19 +371,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)
@@ -404,6 +391,21 @@ int ssl_hook_ReadReq(request_rec *r)
"which is required to access this server.<br />\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);

39
CVE-2025-49630.patch Normal file
View File

@@ -0,0 +1,39 @@
From 88304321841a2fe8bd5eacc70e69418b0b545ca5 Mon Sep 17 00:00:00 2001
From: Eric Covener <covener@apache.org>
Date: Mon, 7 Jul 2025 12:05:49 +0000
Subject: [PATCH] backport 1927036 from trunk
tolerate missing host header in h2 proxy
Reviewed By: jorton, icing, rpluem
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1927044 13f79535-47bb-0310-9956-ffa450edef68
---
modules/http2/h2_proxy_session.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/modules/http2/h2_proxy_session.c b/modules/http2/h2_proxy_session.c
index d5d0f9bc6bc..2cfbb5f5d4b 100644
--- a/modules/http2/h2_proxy_session.c
+++ b/modules/http2/h2_proxy_session.c
@@ -850,6 +850,18 @@ static apr_status_t open_stream(h2_proxy_session *session, const char *url,
dconf = ap_get_module_config(r->per_dir_config, &proxy_module);
if (dconf->preserve_host) {
authority = orig_host;
+ if (!authority) {
+ /* Duplicate mod_proxy behaviour if ProxyPreserveHost is
+ * used but an "HTTP/0.9" request is received without a
+ * Host: header */
+ authority = r->server->server_hostname;
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(10511)
+ "HTTP/0.9 request (with no host line) "
+ "on incoming request and preserve host set "
+ "forcing hostname to be %s for uri %s",
+ authority, r->uri);
+ apr_table_setn(r->headers_in, "Host", authority);
+ }
}
else {
authority = puri.hostname;

198
CVE-2025-49812.patch Normal file
View File

@@ -0,0 +1,198 @@
From 87a7351c755c9ef8ab386e3090e44838c2a06d48 Mon Sep 17 00:00:00 2001
From: Eric Covener <covener@apache.org>
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
---
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 9af6f70fd03..d1f4fad8e23 100644
--- a/modules/ssl/ssl_engine_config.c
+++ b/modules/ssl/ssl_engine_config.c
@@ -741,11 +741,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 f9eca79e462..94cc2772e01 100644
--- a/modules/ssl/ssl_engine_init.c
+++ b/modules/ssl/ssl_engine_init.c
@@ -427,7 +427,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;
}
@@ -2126,9 +2126,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 d912a874dd9..33aa1f71dc7 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;
@@ -1238,16 +1162,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 fb9edaa5eeb..794e51aa937 100644
--- a/modules/ssl/ssl_private.h
+++ b/modules/ssl/ssl_private.h
@@ -526,7 +526,6 @@ typedef enum {
SSL_ENABLED_UNSET = UNSET,
SSL_ENABLED_FALSE = 0,
SSL_ENABLED_TRUE = 1,
- SSL_ENABLED_OPTIONAL = 3
} ssl_enabled_t;
/**

496
CVE-2025-53020.patch Normal file
View File

@@ -0,0 +1,496 @@
From ef98f4f494ff2f99d736a3716cd31219688b46f5 Mon Sep 17 00:00:00 2001
From: Eric Covener <covener@apache.org>
Date: Mon, 7 Jul 2025 12:12:49 +0000
Subject: [PATCH] backport 1927038 from trunk
improve h2 header error handling
Rewviewed By: icing, covener, rpluem
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1927046 13f79535-47bb-0310-9956-ffa450edef68
---
modules/http2/h2_request.c | 12 ++--
modules/http2/h2_request.h | 8 ++-
modules/http2/h2_session.c | 31 ++++++++-
modules/http2/h2_session.h | 3 +
modules/http2/h2_stream.c | 69 ++++++++++++-------
modules/http2/h2_util.c | 51 ++++++++------
modules/http2/h2_util.h | 11 ++-
test/modules/http2/test_200_header_invalid.py | 4 +-
8 files changed, 130 insertions(+), 59 deletions(-)
diff --git a/modules/http2/h2_request.c b/modules/http2/h2_request.c
index 2713947c377..6373e0a244d 100644
--- a/modules/http2/h2_request.c
+++ b/modules/http2/h2_request.c
@@ -64,18 +64,20 @@ typedef struct {
apr_table_t *headers;
apr_pool_t *pool;
apr_status_t status;
+ h2_hd_scratch *scratch;
} h1_ctx;
static int set_h1_header(void *ctx, const char *key, const char *value)
{
h1_ctx *x = ctx;
int was_added;
- h2_req_add_header(x->headers, x->pool, key, strlen(key), value, strlen(value), 0, &was_added);
+ h2_req_add_header(x->headers, x->pool, key, strlen(key),
+ value, strlen(value), x->scratch, &was_added);
return 1;
}
apr_status_t h2_request_rcreate(h2_request **preq, apr_pool_t *pool,
- request_rec *r)
+ request_rec *r, h2_hd_scratch *scratch)
{
h2_request *req;
const char *scheme, *authority, *path;
@@ -125,6 +127,7 @@ apr_status_t h2_request_rcreate(h2_request **preq, apr_pool_t *pool,
x.pool = pool;
x.headers = req->headers;
x.status = APR_SUCCESS;
+ x.scratch = scratch;
apr_table_do(set_h1_header, &x, r->headers_in, NULL);
*preq = req;
@@ -134,7 +137,8 @@ apr_status_t h2_request_rcreate(h2_request **preq, apr_pool_t *pool,
apr_status_t h2_request_add_header(h2_request *req, apr_pool_t *pool,
const char *name, size_t nlen,
const char *value, size_t vlen,
- size_t max_field_len, int *pwas_added)
+ struct h2_hd_scratch *scratch,
+ int *pwas_added)
{
apr_status_t status = APR_SUCCESS;
@@ -185,7 +189,7 @@ apr_status_t h2_request_add_header(h2_request *req, apr_pool_t *pool,
else {
/* non-pseudo header, add to table */
status = h2_req_add_header(req->headers, pool, name, nlen, value, vlen,
- max_field_len, pwas_added);
+ scratch, pwas_added);
}
return status;
diff --git a/modules/http2/h2_request.h b/modules/http2/h2_request.h
index 7e20b697246..ae6b6a2510c 100644
--- a/modules/http2/h2_request.h
+++ b/modules/http2/h2_request.h
@@ -19,17 +19,21 @@
#include "h2.h"
+struct h2_hd_scratch;
+
h2_request *h2_request_create(int id, apr_pool_t *pool, const char *method,
const char *scheme, const char *authority,
const char *path, apr_table_t *header);
apr_status_t h2_request_rcreate(h2_request **preq, apr_pool_t *pool,
- request_rec *r);
+ request_rec *r,
+ struct h2_hd_scratch *scratch);
apr_status_t h2_request_add_header(h2_request *req, apr_pool_t *pool,
const char *name, size_t nlen,
const char *value, size_t vlen,
- size_t max_field_len, int *pwas_added);
+ struct h2_hd_scratch *scratch,
+ int *pwas_added);
apr_status_t h2_request_add_trailer(h2_request *req, apr_pool_t *pool,
const char *name, size_t nlen,
diff --git a/modules/http2/h2_session.c b/modules/http2/h2_session.c
index fc8b6119ae8..a5f1872bc20 100644
--- a/modules/http2/h2_session.c
+++ b/modules/http2/h2_session.c
@@ -109,13 +109,29 @@ static void cleanup_unprocessed_streams(h2_session *session)
h2_mplx_c1_streams_do(session->mplx, rst_unprocessed_stream, session);
}
+/* APR callback invoked if allocation fails. */
+static int abort_on_oom(int retcode)
+{
+ ap_abort_on_oom();
+ return retcode; /* unreachable, hopefully. */
+}
+
static h2_stream *h2_session_open_stream(h2_session *session, int stream_id,
int initiated_on)
{
h2_stream * stream;
+ apr_allocator_t *allocator;
apr_pool_t *stream_pool;
+ apr_status_t rv;
- apr_pool_create(&stream_pool, session->pool);
+ rv = apr_allocator_create(&allocator);
+ if (rv != APR_SUCCESS)
+ return NULL;
+
+ apr_allocator_max_free_set(allocator, ap_max_mem_free);
+ apr_pool_create_ex(&stream_pool, session->pool, NULL, allocator);
+ apr_allocator_owner_set(allocator, stream_pool);
+ apr_pool_abort_set(abort_on_oom, stream_pool);
apr_pool_tag(stream_pool, "h2_stream");
stream = h2_stream_create(stream_id, stream_pool, session,
@@ -972,6 +988,14 @@ apr_status_t h2_session_create(h2_session **psession, conn_rec *c, request_rec *
}
h2_c1_io_init(&session->io, session);
+ /* setup request header scratch buffers */
+ session->hd_scratch.max_len = session->s->limit_req_fieldsize?
+ session->s->limit_req_fieldsize : 8190;
+ session->hd_scratch.name =
+ apr_pcalloc(session->pool, session->hd_scratch.max_len + 1);
+ session->hd_scratch.value =
+ apr_pcalloc(session->pool, session->hd_scratch.max_len + 1);
+
session->padding_max = h2_config_sgeti(s, H2_CONF_PADDING_BITS);
if (session->padding_max) {
session->padding_max = (0x01 << session->padding_max) - 1;
@@ -1032,7 +1056,7 @@ apr_status_t h2_session_create(h2_session **psession, conn_rec *c, request_rec *
n = h2_config_sgeti(s, H2_CONF_PUSH_DIARY_SIZE);
session->push_diary = h2_push_diary_create(session->pool, n);
-
+
if (APLOGcdebug(c)) {
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c,
H2_SSSN_LOG(APLOGNO(03200), session,
@@ -1699,9 +1723,10 @@ static void on_stream_state_enter(void *ctx, h2_stream *stream)
break;
case H2_SS_CLEANUP:
nghttp2_session_set_stream_user_data(session->ngh2, stream->id, NULL);
+ update_child_status(session, SERVER_BUSY_WRITE, "done", stream);
h2_mplx_c1_stream_cleanup(session->mplx, stream, &session->open_streams);
+ stream = NULL;
++session->streams_done;
- update_child_status(session, SERVER_BUSY_WRITE, "done", stream);
break;
default:
break;
diff --git a/modules/http2/h2_session.h b/modules/http2/h2_session.h
index 2c8f334cce0..7932a9e2ccf 100644
--- a/modules/http2/h2_session.h
+++ b/modules/http2/h2_session.h
@@ -29,6 +29,7 @@
*/
#include "h2.h"
+#include "h2_util.h"
struct apr_thread_mutext_t;
struct apr_thread_cond_t;
@@ -118,6 +119,8 @@ typedef struct h2_session {
struct h2_iqueue *out_c1_blocked; /* all streams with output blocked on c1 buffer full */
struct h2_iqueue *ready_to_process; /* all streams ready for processing */
+ h2_hd_scratch hd_scratch;
+
} h2_session;
const char *h2_session_state_str(h2_session_state state);
diff --git a/modules/http2/h2_stream.c b/modules/http2/h2_stream.c
index 35b53860c03..f8214019404 100644
--- a/modules/http2/h2_stream.c
+++ b/modules/http2/h2_stream.c
@@ -659,7 +659,8 @@ apr_status_t h2_stream_set_request_rec(h2_stream *stream,
if (stream->rst_error) {
return APR_ECONNRESET;
}
- status = h2_request_rcreate(&req, stream->pool, r);
+ status = h2_request_rcreate(&req, stream->pool, r,
+ &stream->session->hd_scratch);
if (status == APR_SUCCESS) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, status, r,
H2_STRM_LOG(APLOGNO(03058), stream,
@@ -691,13 +692,11 @@ static void set_error_response(h2_stream *stream, int http_status)
static apr_status_t add_trailer(h2_stream *stream,
const char *name, size_t nlen,
const char *value, size_t vlen,
- size_t max_field_len, int *pwas_added)
+ h2_hd_scratch *scratch)
{
conn_rec *c = stream->session->c1;
- char *hname, *hvalue;
const char *existing;
- *pwas_added = 0;
if (nlen == 0 || name[0] == ':') {
ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_EINVAL, c,
H2_STRM_LOG(APLOGNO(03060), stream,
@@ -710,20 +709,35 @@ static apr_status_t add_trailer(h2_stream *stream,
if (!stream->trailers_in) {
stream->trailers_in = apr_table_make(stream->pool, 5);
}
- hname = apr_pstrndup(stream->pool, name, nlen);
- h2_util_camel_case_header(hname, nlen);
- existing = apr_table_get(stream->trailers_in, hname);
- if (max_field_len
- && ((existing? strlen(existing)+2 : 0) + vlen + nlen + 2 > max_field_len)) {
- /* "key: (oldval, )?nval" is too long */
+
+ if (((nlen + vlen + 2) > scratch->max_len))
return APR_EINVAL;
+
+ /* We need 0-terminated strings to operate on apr_table */
+ AP_DEBUG_ASSERT(nlen < scratch->max_len);
+ memcpy(scratch->name, name, nlen);
+ scratch->name[nlen] = 0;
+ AP_DEBUG_ASSERT(vlen < scratch->max_len);
+ memcpy(scratch->value, value, vlen);
+ scratch->value[vlen] = 0;
+
+ existing = apr_table_get(stream->trailers_in, scratch->name);
+ if(existing) {
+ if (!vlen) /* not adding a 0-length value to existing */
+ return APR_SUCCESS;
+ if ((strlen(existing) + 2 + vlen + nlen + 2 > scratch->max_len)) {
+ /* "name: existing, value" is too long */
+ return APR_EINVAL;
+ }
+ apr_table_merge(stream->trailers_in, scratch->name, scratch->value);
}
- if (!existing) *pwas_added = 1;
- hvalue = apr_pstrndup(stream->pool, value, vlen);
- apr_table_mergen(stream->trailers_in, hname, hvalue);
- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
- H2_STRM_MSG(stream, "added trailer '%s: %s'"), hname, hvalue);
-
+ else {
+ h2_util_camel_case_header(scratch->name, nlen);
+ apr_table_set(stream->trailers_in, scratch->name, scratch->value);
+ }
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
+ H2_STRM_MSG(stream, "added trailer '%s: %s'"),
+ scratch->name, scratch->value);
return APR_SUCCESS;
}
@@ -732,7 +746,7 @@ apr_status_t h2_stream_add_header(h2_stream *stream,
const char *value, size_t vlen)
{
h2_session *session = stream->session;
- int error = 0, was_added = 0;
+ int error = 0;
apr_status_t status = APR_SUCCESS;
H2_STRM_ASSERT_MAGIC(stream, H2_STRM_MAGIC_OK);
@@ -760,6 +774,7 @@ apr_status_t h2_stream_add_header(h2_stream *stream,
++stream->request_headers_added;
}
else if (H2_SS_IDLE == stream->state) {
+ int was_added;
if (!stream->rtmp) {
if (H2_STREAM_CLIENT_INITIATED(stream->id)) {
++stream->session->remote.emitted_count;
@@ -771,7 +786,7 @@ apr_status_t h2_stream_add_header(h2_stream *stream,
}
status = h2_request_add_header(stream->rtmp, stream->pool,
name, nlen, value, vlen,
- session->s->limit_req_fieldsize, &was_added);
+ &session->hd_scratch, &was_added);
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, session->c1,
H2_STRM_MSG(stream, "add_header: '%.*s: %.*s"),
(int)nlen, name, (int)vlen, value);
@@ -779,8 +794,8 @@ apr_status_t h2_stream_add_header(h2_stream *stream,
}
else if (H2_SS_OPEN == stream->state) {
status = add_trailer(stream, name, nlen, value, vlen,
- session->s->limit_req_fieldsize, &was_added);
- if (was_added) ++stream->request_headers_added;
+ &session->hd_scratch);
+ if (!status) ++stream->request_headers_added;
}
else {
status = APR_EINVAL;
@@ -789,16 +804,17 @@ apr_status_t h2_stream_add_header(h2_stream *stream,
if (APR_EINVAL == status) {
/* header too long */
- if (!h2_stream_is_ready(stream)) {
+ if (!h2_stream_is_ready(stream) && !stream->request_headers_failed) {
ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, session->c1,
- H2_STRM_LOG(APLOGNO(10180), stream,"Request header exceeds "
- "LimitRequestFieldSize: %.*s"),
+ H2_STRM_LOG(APLOGNO(10180), stream,
+ "Request header exceeds LimitRequestFieldSize(%d): %.*s"),
+ (int)session->hd_scratch.max_len,
(int)H2MIN(nlen, 80), name);
}
error = HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE;
goto cleanup;
}
-
+
if (session->s->limit_req_fields > 0
&& stream->request_headers_added > session->s->limit_req_fields) {
/* too many header lines */
@@ -810,12 +826,13 @@ apr_status_t h2_stream_add_header(h2_stream *stream,
if (!h2_stream_is_ready(stream)) {
ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, session->c1,
H2_STRM_LOG(APLOGNO(10181), stream, "Number of request headers "
- "exceeds LimitRequestFields"));
+ "exceeds LimitRequestFields(%d)"),
+ (int)session->s->limit_req_fields);
}
error = HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE;
goto cleanup;
}
-
+
cleanup:
if (error) {
++stream->request_headers_failed;
diff --git a/modules/http2/h2_util.c b/modules/http2/h2_util.c
index 8e53cebdf92..605c348ca12 100644
--- a/modules/http2/h2_util.c
+++ b/modules/http2/h2_util.c
@@ -1693,10 +1693,9 @@ int h2_ignore_resp_trailer(const char *name, size_t len)
}
static apr_status_t req_add_header(apr_table_t *headers, apr_pool_t *pool,
- nghttp2_nv *nv, size_t max_field_len,
+ nghttp2_nv *nv, h2_hd_scratch *scratch,
int *pwas_added)
{
- char *hname, *hvalue;
const char *existing;
*pwas_added = 0;
@@ -1712,15 +1711,14 @@ static apr_status_t req_add_header(apr_table_t *headers, apr_pool_t *pool,
/* Cookie header come separately in HTTP/2, but need
* to be merged by "; " (instead of default ", ")
*/
- if (max_field_len
- && strlen(existing) + nv->valuelen + nv->namelen + 4
- > max_field_len) {
+ if ((strlen(existing) + nv->valuelen + nv->namelen + 4)
+ > scratch->max_len) {
/* "key: oldval, nval" is too long */
return APR_EINVAL;
}
- hvalue = apr_pstrndup(pool, (const char*)nv->value, nv->valuelen);
apr_table_setn(headers, "Cookie",
- apr_psprintf(pool, "%s; %s", existing, hvalue));
+ apr_psprintf(pool, "%s; %.*s", existing,
+ (int)nv->valuelen, nv->value));
return APR_SUCCESS;
}
}
@@ -1731,27 +1729,40 @@ static apr_status_t req_add_header(apr_table_t *headers, apr_pool_t *pool,
}
}
- hname = apr_pstrndup(pool, (const char*)nv->name, nv->namelen);
- h2_util_camel_case_header(hname, nv->namelen);
- existing = apr_table_get(headers, hname);
- if (max_field_len) {
- if ((existing? strlen(existing)+2 : 0) + nv->valuelen + nv->namelen + 2
- > max_field_len) {
- /* "key: (oldval, )?nval" is too long */
+ if (((nv->namelen + nv->valuelen + 2) > scratch->max_len))
+ return APR_EINVAL;
+
+ /* We need 0-terminated strings to operate on apr_table */
+ AP_DEBUG_ASSERT(nv->namelen < scratch->max_len);
+ memcpy(scratch->name, nv->name, nv->namelen);
+ scratch->name[nv->namelen] = 0;
+ AP_DEBUG_ASSERT(nv->valuelen < scratch->max_len);
+ memcpy(scratch->value, nv->value, nv->valuelen);
+ scratch->value[nv->valuelen] = 0;
+
+ *pwas_added = 1;
+ existing = apr_table_get(headers, scratch->name);
+ if (existing) {
+ if (!nv->valuelen) /* not adding a 0-length value to existing */
+ return APR_SUCCESS;
+ if ((strlen(existing) + 2 + nv->valuelen + nv->namelen + 2)
+ > scratch->max_len) {
+ /* "name: existing, value" is too long */
return APR_EINVAL;
}
+ apr_table_merge(headers, scratch->name, scratch->value);
+ }
+ else {
+ h2_util_camel_case_header(scratch->name, nv->namelen);
+ apr_table_set(headers, scratch->name, scratch->value);
}
- if (!existing) *pwas_added = 1;
- hvalue = apr_pstrndup(pool, (const char*)nv->value, nv->valuelen);
- apr_table_mergen(headers, hname, hvalue);
-
return APR_SUCCESS;
}
apr_status_t h2_req_add_header(apr_table_t *headers, apr_pool_t *pool,
const char *name, size_t nlen,
const char *value, size_t vlen,
- size_t max_field_len, int *pwas_added)
+ h2_hd_scratch *scratch, int *pwas_added)
{
nghttp2_nv nv;
@@ -1759,7 +1770,7 @@ apr_status_t h2_req_add_header(apr_table_t *headers, apr_pool_t *pool,
nv.namelen = nlen;
nv.value = (uint8_t*)value;
nv.valuelen = vlen;
- return req_add_header(headers, pool, &nv, max_field_len, pwas_added);
+ return req_add_header(headers, pool, &nv, scratch, pwas_added);
}
/*******************************************************************************
diff --git a/modules/http2/h2_util.h b/modules/http2/h2_util.h
index d2e6548ba87..c2cab4afa45 100644
--- a/modules/http2/h2_util.h
+++ b/modules/http2/h2_util.h
@@ -397,14 +397,21 @@ apr_status_t h2_req_create_ngheader(h2_ngheader **ph, apr_pool_t *p,
const struct h2_request *req);
#endif
+typedef struct h2_hd_scratch {
+ size_t max_len; /* header field size name + ': ' + value */
+ char *name; /* max_len+1 sized */
+ char *value; /* max_len+1 sized */
+
+} h2_hd_scratch;
+
/**
* Add a HTTP/2 header and return the table key if it really was added
* and not ignored.
*/
-apr_status_t h2_req_add_header(apr_table_t *headers, apr_pool_t *pool,
+apr_status_t h2_req_add_header(apr_table_t *headers, apr_pool_t *pool,
const char *name, size_t nlen,
const char *value, size_t vlen,
- size_t max_field_len, int *pwas_added);
+ h2_hd_scratch *scratch, int *pwas_added);
/*******************************************************************************
* apr brigade helpers
diff --git a/test/modules/http2/test_200_header_invalid.py b/test/modules/http2/test_200_header_invalid.py
index 6b73301c282..1687e3d9818 100644
--- a/test/modules/http2/test_200_header_invalid.py
+++ b/test/modules/http2/test_200_header_invalid.py
@@ -133,7 +133,7 @@ def test_h2_200_11(self, env):
assert 431 == r.response["status"]
# test header field count, LimitRequestFields (default 100)
- # see #201: several headers with same name are mered and count only once
+ # see #201: several headers with same name are merged and counted
def test_h2_200_12(self, env):
url = env.mkurl("https", "cgi", "/")
opt = []
@@ -143,7 +143,7 @@ def test_h2_200_12(self, env):
r = env.curl_get(url, options=opt)
assert r.response["status"] == 200
r = env.curl_get(url, options=(opt + ["-H", "y: 2"]))
- assert r.response["status"] == 200
+ assert r.response["status"] == 431
# test header field count, LimitRequestFields (default 100)
# different header names count each

203
CVE-2025-55753.patch Normal file
View File

@@ -0,0 +1,203 @@
From ab9dd8e2cfe7d62efe5ff8925fbef1de756a2fc2 Mon Sep 17 00:00:00 2001
From: Stefan Eissing <icing@apache.org>
Date: Thu, 20 Nov 2025 13:00:23 +0000
Subject: [PATCH] Merged /httpd/httpd/trunk:r1929514,1929883
Update mod_md to v2.6.6
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1929884 13f79535-47bb-0310-9956-ffa450edef68
---
STATUS | 8 --------
changes-entries/md_v2.6.5.txt | 9 +++++++++
changes-entries/md_v2.6.6.txt | 3 +++
docs/manual/mod/mod_md.xml | 17 +++++++++++++++++
modules/md/md_crypt.c | 10 +++++++---
modules/md/md_curl.c | 14 ++++++++------
modules/md/md_ocsp.c | 3 ++-
modules/md/md_version.h | 4 ++--
modules/md/mod_md_config.c | 21 +++++++++++++++++++++
modules/md/mod_md_config.h | 1 +
modules/md/mod_md_drive.c | 2 +-
11 files changed, 71 insertions(+), 21 deletions(-)
create mode 100644 changes-entries/md_v2.6.5.txt
create mode 100644 changes-entries/md_v2.6.6.txt
Index: httpd-2.4.63/changes-entries/md_v2.6.5.txt
===================================================================
--- /dev/null
+++ httpd-2.4.63/changes-entries/md_v2.6.5.txt
@@ -0,0 +1,9 @@
+ *) mod_md: update to version 2.6.5
+ - New directive `MDInitialDelay`, controlling how longer to wait after
+ a server restart before checking certificates for renewal.
+ [Michael Kaufmann]
+ - Hardening: when build with OpenSSL older than 1.0.2 or old libressl
+ versions, the parsing of ASN.1 time strings did not do a length check.
+ - Hardening: when reading back OCSP responses stored in the local JSON
+ store, missing 'valid' key led to uninitialized values, resulting in
+ wrong refresh behaviour.
Index: httpd-2.4.63/changes-entries/md_v2.6.6.txt
===================================================================
--- /dev/null
+++ httpd-2.4.63/changes-entries/md_v2.6.6.txt
@@ -0,0 +1,3 @@
+ *) mod_md: update to version 2.6.6
+ - Fix a small memory leak when using OpenSSL's BIGNUMs. [Theo Buehler]
+ - Fix reuse of curl easy handles by resetting them. [Michael Kaufmann]
Index: httpd-2.4.63/modules/md/md_crypt.c
===================================================================
--- httpd-2.4.63.orig/modules/md/md_crypt.c
+++ httpd-2.4.63/modules/md/md_crypt.c
@@ -198,7 +198,7 @@ static int pem_passwd(char *buf, int siz
/* Get the apr time (micro seconds, since 1970) from an ASN1 time, as stored in X509
* certificates. OpenSSL now has a utility function, but other *SSL derivatives have
- * not caughts up yet or chose to ignore. An alternative is implemented, we prefer
+ * not caught up yet or chose to ignore. An alternative is implemented, we prefer
* however the *SSL to maintain such things.
*/
static apr_time_t md_asn1_time_get(const ASN1_TIME* time)
@@ -212,6 +212,10 @@ static apr_time_t md_asn1_time_get(const
const char* str = (const char*) time->data;
apr_size_t i = 0;
+ if ((time->length < 12) || (
+ (time->type == V_ASN1_GENERALIZEDTIME) && time->length < 16))
+ return 0;
+
memset(&t, 0, sizeof(t));
if (time->type == V_ASN1_UTCTIME) {/* two digit year */
@@ -1188,7 +1192,7 @@ const char *md_cert_get_serial_number(co
serial = BN_bn2hex(bn);
s = apr_pstrdup(p, serial);
OPENSSL_free((void*)serial);
- OPENSSL_free((void*)bn);
+ BN_free(bn);
}
return s;
}
Index: httpd-2.4.63/modules/md/md_curl.c
===================================================================
--- httpd-2.4.63.orig/modules/md/md_curl.c
+++ httpd-2.4.63/modules/md/md_curl.c
@@ -253,17 +253,19 @@ static apr_status_t internals_setup(md_h
rv = APR_EGENERAL;
goto leave;
}
- curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_cb);
- curl_easy_setopt(curl, CURLOPT_HEADERDATA, NULL);
- curl_easy_setopt(curl, CURLOPT_READFUNCTION, req_data_cb);
- curl_easy_setopt(curl, CURLOPT_READDATA, NULL);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, resp_data_cb);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, NULL);
}
else {
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, req->pool, "reusing curl instance from http");
+ curl_easy_reset(curl);
}
+ curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_cb);
+ curl_easy_setopt(curl, CURLOPT_HEADERDATA, NULL);
+ curl_easy_setopt(curl, CURLOPT_READFUNCTION, req_data_cb);
+ curl_easy_setopt(curl, CURLOPT_READDATA, NULL);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, resp_data_cb);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, NULL);
+
internals = apr_pcalloc(req->pool, sizeof(*internals));
internals->curl = curl;
Index: httpd-2.4.63/modules/md/md_ocsp.c
===================================================================
--- httpd-2.4.63.orig/modules/md/md_ocsp.c
+++ httpd-2.4.63/modules/md/md_ocsp.c
@@ -190,6 +190,7 @@ static apr_status_t ostat_from_json(md_o
md_timeperiod_t valid;
apr_status_t rv = APR_ENOENT;
+ memset(&valid, 0, sizeof(valid));
memset(resp_der, 0, sizeof(*resp_der));
memset(resp_valid, 0, sizeof(*resp_valid));
s = md_json_dups(p, json, MD_KEY_VALID, MD_KEY_FROM, NULL);
@@ -531,7 +532,7 @@ static const char *certid_summary(const
bn = ASN1_INTEGER_to_BN(aserial, NULL);
s = BN_bn2hex(bn);
serial = apr_pstrdup(p, s);
- OPENSSL_free((void*)bn);
+ BN_free(bn);
OPENSSL_free((void*)s);
}
return apr_psprintf(p, "certid[der=%s, issuer=%s, key=%s, serial=%s]",
Index: httpd-2.4.63/modules/md/mod_md_config.c
===================================================================
--- httpd-2.4.63.orig/modules/md/mod_md_config.c
+++ httpd-2.4.63/modules/md/mod_md_config.c
@@ -84,6 +84,7 @@ static md_mod_conf_t defmc = {
"crt.sh", /* default cert checker site name */
"https://crt.sh?q=", /* default cert checker site url */
NULL, /* CA cert file to use */
+ APR_TIME_C(0), /* initial cert check delay */
apr_time_from_sec(MD_SECS_PER_DAY/2), /* default time between cert checks */
apr_time_from_sec(5), /* minimum delay for retries */
13, /* retry_failover after 14 errors, with 5s delay ~ half a day */
@@ -625,6 +626,24 @@ static const char *md_config_set_base_se
return set_on_off(&config->mc->manage_base_server, value, cmd->pool);
}
+static const char *md_config_set_initial_delay(cmd_parms *cmd, void *dc, const char *value)
+{
+ md_srv_conf_t *config = md_config_get(cmd->server);
+ const char *err = md_conf_check_location(cmd, MD_LOC_NOT_MD);
+ apr_time_t delay;
+
+ (void)dc;
+ if (err) return err;
+ if (md_duration_parse(&delay, value, "s") != APR_SUCCESS) {
+ return "unrecognized duration format";
+ }
+ if (delay < 0) {
+ return "initial delay must not be negative";
+ }
+ config->mc->initial_delay = delay;
+ return NULL;
+}
+
static const char *md_config_set_check_interval(cmd_parms *cmd, void *dc, const char *value)
{
md_srv_conf_t *config = md_config_get(cmd->server);
@@ -1323,6 +1342,8 @@ const command_rec md_cmds[] = {
"Configure locking of store for updates."),
AP_INIT_TAKE1("MDMatchNames", md_config_set_match_mode, NULL, RSRC_CONF,
"Determines how DNS names are matched to vhosts."),
+ AP_INIT_TAKE1("MDInitialDelay", md_config_set_initial_delay, NULL, RSRC_CONF,
+ "How long to delay the first certificate check."),
AP_INIT_TAKE1("MDCheckInterval", md_config_set_check_interval, NULL, RSRC_CONF,
"Time between certificate checks."),
AP_INIT_TAKE1(NULL, NULL, NULL, RSRC_CONF, NULL)
Index: httpd-2.4.63/modules/md/mod_md_config.h
===================================================================
--- httpd-2.4.63.orig/modules/md/mod_md_config.h
+++ httpd-2.4.63/modules/md/mod_md_config.h
@@ -75,6 +75,7 @@ struct md_mod_conf_t {
const char *cert_check_name; /* name of the linked certificate check site */
const char *cert_check_url; /* url "template for" checking a certificate */
const char *ca_certs; /* root certificates to use for connections */
+ apr_time_t initial_delay; /* how long to delay the first cert renewal check */
apr_time_t check_interval; /* duration between cert renewal checks */
apr_time_t min_delay; /* minimum delay for retries */
int retry_failover; /* number of errors to trigger CA failover */
Index: httpd-2.4.63/modules/md/mod_md_drive.c
===================================================================
--- httpd-2.4.63.orig/modules/md/mod_md_drive.c
+++ httpd-2.4.63/modules/md/mod_md_drive.c
@@ -346,7 +346,7 @@ apr_status_t md_renew_start_watching(md_
"create md renew watchdog(%s)", MD_RENEW_WATCHDOG_NAME);
return rv;
}
- rv = wd_register_callback(dctx->watchdog, 0, dctx, run_watchdog);
+ rv = wd_register_callback(dctx->watchdog, mc->initial_delay, dctx, run_watchdog);
ap_log_error(APLOG_MARK, rv? APLOG_CRIT : APLOG_DEBUG, rv, s, APLOGNO(10067)
"register md renew watchdog(%s)", MD_RENEW_WATCHDOG_NAME);
return rv;

35
CVE-2025-58098.patch Normal file
View File

@@ -0,0 +1,35 @@
From ecc1b8f3817e3dcab9c1f24f905752d3c0a279af Mon Sep 17 00:00:00 2001
From: Eric Covener <covener@apache.org>
Date: Mon, 1 Dec 2025 12:00:14 +0000
Subject: [PATCH] don't pass args for SSI request
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1930161 13f79535-47bb-0310-9956-ffa450edef68
---
modules/generators/mod_cgid.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/modules/generators/mod_cgid.c b/modules/generators/mod_cgid.c
index b27dd802d80..94ad7ee8733 100644
--- a/modules/generators/mod_cgid.c
+++ b/modules/generators/mod_cgid.c
@@ -239,7 +239,7 @@ static char **create_argv(apr_pool_t *p, char *path, char *user, char *group,
char *w;
int idx = 0;
- if (!(*args) || ap_strchr_c(args, '=')) {
+ if (!args || !(*args) || ap_strchr_c(args, '=')) {
numwords = 0;
}
else {
@@ -932,7 +932,10 @@ static int cgid_server(void *data)
apr_pool_userdata_set(r, ERRFN_USERDATA_KEY, apr_pool_cleanup_null, ptrans);
}
- argv = (const char * const *)create_argv(r->pool, NULL, NULL, NULL, argv0, r->args);
+ /* Do not pass args in case of SSI requests */
+ argv = (const char * const *)create_argv(r->pool, NULL, NULL, NULL,
+ argv0,
+ cgid_req.req_type == SSI_REQ ? NULL : r->args);
/* We want to close sd2 for the new CGI process too.
* If it is left open it'll make ap_pass_brigade() block

63
CVE-2025-65082.patch Normal file
View File

@@ -0,0 +1,63 @@
From e4f00c5eb71d8a7aa1f52b5279832986f669d463 Mon Sep 17 00:00:00 2001
From: Eric Covener <covener@apache.org>
Date: Mon, 1 Dec 2025 12:03:12 +0000
Subject: [PATCH] envvars from HTTP headers low precedence
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1930163 13f79535-47bb-0310-9956-ffa450edef68
---
server/util_script.c | 26 +++++++++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)
diff --git a/server/util_script.c b/server/util_script.c
index 72175e75824..6a18aec8c90 100644
--- a/server/util_script.c
+++ b/server/util_script.c
@@ -126,6 +126,8 @@ AP_DECLARE(char **) ap_create_environment(apr_pool_t *p, apr_table_t *t)
}
}
for (i = 0; i < env_arr->nelts; ++i) {
+ int changed = 0;
+
if (!elts[i].key) {
continue;
}
@@ -133,18 +135,36 @@ AP_DECLARE(char **) ap_create_environment(apr_pool_t *p, apr_table_t *t)
whack = env[j];
if (apr_isdigit(*whack)) {
*whack++ = '_';
+ changed = 1;
}
while (*whack != '=') {
#ifdef WIN32
- if (!apr_isalnum(*whack) && *whack != '(' && *whack != ')') {
+ if (!apr_isalnum(*whack) && *whack != '_' && *whack != '(' && *whack != ')') {
#else
- if (!apr_isalnum(*whack)) {
+ if (!apr_isalnum(*whack) && *whack != '_') {
#endif
*whack = '_';
+ changed = 1;
}
++whack;
}
- ++j;
+ if (changed) {
+ *whack = '\0';
+ /*
+ * If after cleaning up the key the key is identical to an existing key
+ * in the table drop this environment variable. This also prevents
+ * to override CGI reserved environment variables with variables whose
+ * names have an invalid character instead of '_', but are otherwise
+ * equal to the names CGI reserved environment variables.
+ */
+ if (!apr_table_get(t, env[j])) {
+ ++j;
+ *whack = '=';
+ }
+ }
+ else {
+ ++j;
+ }
}
env[j] = NULL;

39
CVE-2025-66200.patch Normal file
View File

@@ -0,0 +1,39 @@
From 9d26b95787b229a3f6195d7beead774d131eeda1 Mon Sep 17 00:00:00 2001
From: Eric Covener <covener@apache.org>
Date: Mon, 1 Dec 2025 12:04:29 +0000
Subject: [PATCH] don't use request notes for suexec
also, stop accepting the obscure "note" option in
RequestHeader, it is only documented/described as being
meant for Header (output filter).
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1930164 13f79535-47bb-0310-9956-ffa450edef68
---
modules/mappers/mod_userdir.c | 4 ++--
modules/metadata/mod_headers.c | 6 +++++-
2 files changed, 7 insertions(+), 3 deletions(-)
Index: httpd-2.4.63/modules/mappers/mod_userdir.c
===================================================================
--- httpd-2.4.63.orig/modules/mappers/mod_userdir.c
+++ httpd-2.4.63/modules/mappers/mod_userdir.c
@@ -334,7 +334,7 @@ static int translate_userdir(request_rec
r->finfo = statbuf;
/* For use in the get_suexec_identity phase */
- apr_table_setn(r->notes, "mod_userdir_user", user);
+ ap_set_module_config(r->request_config, &userdir_module, (void *)user);
return OK;
}
@@ -348,7 +348,7 @@ static ap_unix_identity_t *get_suexec_id
{
ap_unix_identity_t *ugid = NULL;
#if APR_HAS_USER
- const char *username = apr_table_get(r->notes, "mod_userdir_user");
+ const char *username = (const char*) ap_get_module_config(r->request_config, &userdir_module);
if (username == NULL) {
return NULL;

View File

@@ -1,8 +1,8 @@
Index: httpd-2.4.64/httpd-framework/t/conf/extra.conf.in
Index: httpd-framework/t/conf/extra.conf.in
===================================================================
--- httpd-2.4.64.orig/httpd-framework/t/conf/extra.conf.in
+++ httpd-2.4.64/httpd-framework/t/conf/extra.conf.in
@@ -983,6 +983,7 @@ LimitRequestFields 32
--- a/httpd-framework/t/conf/extra.conf.in 2020-06-15 10:43:26.156701553 +0200
+++ b/httpd-framework/t/conf/extra.conf.in 2020-06-15 10:46:16.141693081 +0200
@@ -875,6 +875,7 @@ LimitRequestFields 32
</IfModule>
</Directory>
<Directory @SERVERROOT@/htdocs/modules/filter/bytype>

View File

@@ -1,8 +1,8 @@
Index: httpd-2.4.64/httpd-framework/t/ssl/varlookup.t
Index: httpd-framework/t/ssl/varlookup.t
===================================================================
--- httpd-2.4.64.orig/httpd-framework/t/ssl/varlookup.t
+++ httpd-2.4.64/httpd-framework/t/ssl/varlookup.t
@@ -227,9 +227,7 @@ SSL_SERVER_S_DN_UID
--- a/httpd-framework/t/ssl/varlookup.t 2016-10-25 14:30:54.250707932 +0200
+++ b/httpd-framework/t/ssl/varlookup.t 2016-10-27 15:38:52.440667690 +0200
@@ -210,9 +210,7 @@ SSL_SERVER_S_DN_UID
SSL_CLIENT_S_DN_Email "$client_dn{$email_field}"
SSL_SERVER_S_DN_Email "$server_dn{$email_field}"
SSL_CLIENT_SAN_Email_0 "$san_email"

View File

@@ -42,11 +42,11 @@ Conflicts:
server/protocol.c | 25 +++++++++++++++++--------
6 files changed, 77 insertions(+), 10 deletions(-)
Index: httpd-2.4.64/modules/http/http_filters.c
Index: httpd-2.4.49/modules/http/http_filters.c
===================================================================
--- httpd-2.4.64.orig/modules/http/http_filters.c
+++ httpd-2.4.64/modules/http/http_filters.c
@@ -1409,10 +1409,17 @@ static void merge_response_headers(reque
--- httpd-2.4.49.orig/modules/http/http_filters.c 2021-05-11 17:21:43.000000000 +0200
+++ httpd-2.4.49/modules/http/http_filters.c 2021-09-17 09:33:49.496853894 +0200
@@ -1488,10 +1488,17 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_
* zero C-L to the client. We can't just remove the C-L filter,
* because well behaved 2.0 handlers will send their data down the stack,
* and we will compute a real C-L for the head request. RBB
@@ -64,12 +64,12 @@ Index: httpd-2.4.64/modules/http/http_filters.c
+ && conf->http_cl_head_zero != AP_HTTP_CL_HEAD_ZERO_ENABLE) {
apr_table_unset(r->headers_out, "Content-Length");
}
}
Index: httpd-2.4.64/server/core.c
Index: httpd-2.4.49/server/core.c
===================================================================
--- httpd-2.4.64.orig/server/core.c
+++ httpd-2.4.64/server/core.c
@@ -564,6 +564,12 @@ static void *merge_core_server_configs(a
--- httpd-2.4.49.orig/server/core.c 2021-05-27 15:08:21.000000000 +0200
+++ httpd-2.4.49/server/core.c 2021-09-17 09:33:49.496853894 +0200
@@ -551,6 +551,12 @@ static void *merge_core_server_configs(a
if (virt->http_methods != AP_HTTP_METHODS_UNSET)
conf->http_methods = virt->http_methods;
@@ -82,7 +82,7 @@ Index: httpd-2.4.64/server/core.c
/* no action for virt->accf_map, not allowed per-vhost */
if (virt->protocol)
@@ -4166,6 +4172,32 @@ static const char *set_http_method(cmd_p
@@ -4142,6 +4148,32 @@ static const char *set_http_method(cmd_p
return NULL;
}
@@ -115,7 +115,7 @@ Index: httpd-2.4.64/server/core.c
static apr_hash_t *errorlog_hash;
static int log_constant_item(const ap_errorlog_info *info, const char *arg,
@@ -4732,6 +4764,10 @@ AP_INIT_TAKE1("TraceEnable", set_trace_e
@@ -4685,6 +4717,10 @@ AP_INIT_TAKE1("TraceEnable", set_trace_e
"'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"),
@@ -126,11 +126,11 @@ Index: httpd-2.4.64/server/core.c
AP_INIT_ITERATE("Protocols", set_protocols, NULL, RSRC_CONF,
"Controls which protocols are allowed"),
AP_INIT_TAKE1("ProtocolsHonorOrder", set_protocols_honor_order, NULL, RSRC_CONF,
Index: httpd-2.4.64/server/protocol.c
Index: httpd-2.4.49/server/protocol.c
===================================================================
--- httpd-2.4.64.orig/server/protocol.c
+++ httpd-2.4.64/server/protocol.c
@@ -1058,6 +1058,11 @@ AP_DECLARE(int) ap_check_request_header(
--- httpd-2.4.49.orig/server/protocol.c 2021-09-17 09:33:49.496853894 +0200
+++ httpd-2.4.49/server/protocol.c 2021-09-17 10:15:28.643596021 +0200
@@ -1056,6 +1056,11 @@ AP_DECLARE(int) ap_check_request_header(
if (ap_cstr_casecmp(expect, "100-continue") == 0) {
r->expecting_100 = 1;
}
@@ -142,11 +142,11 @@ Index: httpd-2.4.64/server/protocol.c
else {
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(00570)
"client sent an unrecognized expectation value "
Index: httpd-2.4.64/include/http_core.h
Index: httpd-2.4.49/include/http_core.h
===================================================================
--- httpd-2.4.64.orig/include/http_core.h
+++ httpd-2.4.64/include/http_core.h
@@ -734,6 +734,16 @@ typedef struct {
--- httpd-2.4.49.orig/include/http_core.h 2021-05-27 15:08:21.000000000 +0200
+++ httpd-2.4.49/include/http_core.h 2021-09-17 09:33:49.496853894 +0200
@@ -733,6 +733,16 @@ typedef struct {
#define AP_MERGE_TRAILERS_DISABLE 2
int merge_trailers;
@@ -163,7 +163,7 @@ Index: httpd-2.4.64/include/http_core.h
apr_array_header_t *protocols;
int protocols_honor_order;
@@ -780,7 +790,6 @@ apr_status_t ap_core_input_filter(ap_fil
@@ -776,7 +786,6 @@ apr_status_t ap_core_input_filter(ap_fil
apr_off_t readbytes);
apr_status_t ap_core_output_filter(ap_filter_t *f, apr_bucket_brigade *b);

View File

@@ -1,8 +1,8 @@
Index: httpd-2.4.64/server/util_script.c
Index: httpd-2.4.46/server/util_script.c
===================================================================
--- httpd-2.4.64.orig/server/util_script.c
+++ httpd-2.4.64/server/util_script.c
@@ -472,11 +472,20 @@ AP_DECLARE(int) ap_scan_script_header_er
--- httpd-2.4.46.orig/server/util_script.c 2020-07-20 07:58:49.000000000 +0200
+++ httpd-2.4.46/server/util_script.c 2020-11-10 16:10:54.525476516 +0100
@@ -468,11 +468,20 @@ AP_DECLARE(int) ap_scan_script_header_er
apr_table_t *cookie_table;
int trace_log = APLOG_R_MODULE_IS_LEVEL(r, module_index, APLOG_TRACE1);
int first_header = 1;
@@ -24,7 +24,7 @@ Index: httpd-2.4.64/server/util_script.c
/* temporary place to hold headers to merge in later */
merge = apr_table_make(r->pool, 10);
@@ -492,7 +501,7 @@ AP_DECLARE(int) ap_scan_script_header_er
@@ -488,7 +497,7 @@ AP_DECLARE(int) ap_scan_script_header_er
while (1) {
@@ -33,7 +33,7 @@ Index: httpd-2.4.64/server/util_script.c
if (rv == 0) {
const char *msg = "Premature end of script headers";
if (first_header)
@@ -607,10 +616,13 @@ AP_DECLARE(int) ap_scan_script_header_er
@@ -603,10 +612,13 @@ AP_DECLARE(int) ap_scan_script_header_er
if (!(l = strchr(w, ':'))) {
if (!buffer) {
/* Soak up all the script output - may save an outright kill */

File diff suppressed because it is too large Load Diff

View File

@@ -107,7 +107,7 @@
%define build_http2 1
Name: apache2%{psuffix}
Version: 2.4.65
Version: 2.4.63
Release: 0
Summary: The Apache HTTPD Server
License: Apache-2.0
@@ -181,6 +181,21 @@ Patch2: apache2-logresolve-tmp-security.patch
Patch3: apache2-LimitRequestFieldSize-limits-headers.patch
# [fate317766] backport of an upstream commit
Patch4: apache2-HttpContentLengthHeadZero-HttpExpectStrict.patch
# FIX-UPSTREAM: bsc#1246477 CVE-2024-42516: HTTP response splitting
Patch5: CVE-2024-42516.patch
# FIX-UPSTREAM: bsc#1246305 CVE-2024-43204: SSRF when mod_proxy is loaded allows an attacker to send outbound proxy requests to a URL controlled by them
Patch6: CVE-2024-43204.patch
# FIX-UPSTREAM: bsc#1246303 CVE-2024-47252: insufficient escaping of user-supplied data in mod_ssl allows an untrusted SSL/TLS client to insert escape characters into log files
Patch7: CVE-2024-47252.patch
# FIX-UPSTREAM: bsc#1246302 CVE-2025-23048: access control bypass by trusted clients through TLS 1.3 session resumption in some mod_ssl configurations
Patch8: CVE-2025-23048.patch
# FIX-UPSTREAM: bsc#1246307 CVE-2025-49630: denial of service can be triggered by untrusted clients causing an assertion in mod_proxy_http2
Patch9: CVE-2025-49630.patch
# FIX-UPSTREAM: bsc#1246169 CVE-2025-49812: Opossum Attack Application Layer Desynchronization using Opportunistic TLS
Patch10: CVE-2025-49812.patch
# FIX-UPSTREAM: bsc#1246306 CVE-2025-53020: HTTP/2 denial of service due to late release of memory after effective lifetime
Patch11: CVE-2025-53020.patch
# PATCH: https://marc.info/?l=apache-httpd-users&m=147448312531134&w=2
Patch100: apache-test-application-xml-type.patch
# PATCH: /test_ssl_var_lookup?SSL_SERVER_SAN_DNS_0 returns <build-host-name>
@@ -190,6 +205,15 @@ Patch100: apache-test-application-xml-type.patch
# even if in live system I do not experience this inconsistency, let's turn off
# these variables from the test
Patch101: apache-test-turn-off-variables-in-ssl-var-lookup.patch
#FIX-UPSTREAM: bsc#1254511 CVE-2025-55753
Patch102: CVE-2025-55753.patch
#FIX-UPSTREAM: bsc#1254512 CVE-2025-58098
Patch103: CVE-2025-58098.patch
#FIX-UPSTREAM: bsc#1254514 CVE-2025-65082
Patch104: CVE-2025-65082.patch
#FIX-UPSTREAM: bsc#1254515 CVE-2025-66200
Patch105: CVE-2025-66200.patch
BuildRequires: apache-rpm-macros-control
#Since 2.4.7 the event MPM requires apr 1.5.0 or later.
BuildRequires: apr-devel >= 1.5.0

BIN
httpd-2.4.63.tar.bz2 LFS Normal file

Binary file not shown.

16
httpd-2.4.63.tar.bz2.asc Normal file
View File

@@ -0,0 +1,16 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEqT1i7MPI6hLbIg7JNOp25nkUhagFAmeOpZMACgkQNOp25nkU
hajzCg/+I/j8u/tCFeaQAf5ZKyGZ8Kcpxf+/lP4Kr79emBwdROZFGP+ipfuyRpax
A8/WXTeVs6bWmg5edPIQAC1mDpj7rx2Pwa7xKV+/3/npQMPV4cqgbZfzgQD2NnoD
8Qs6pkjwF6ygn+4y/KQLF5MIh4G0lIkx/ddt+lHbt2FkJXT5JV1cyJ+kKrTLJdlB
RDMXcF2XleFFzApf9VCYWFPTlgmxAe4FG65JMwxh3WJeiX0vrLH+GnOyAXHotBOs
NbXQKQD5cM6/JzA3F4Jni/2co9Wsjg+zENx3hIjxJZvVtXRIC4BpmAJOeQIyoNwo
VVwe3Uo9Cz+ZFTYMecwnR/B5tm4IkQ0K9MXRK/jxxKds4CF/bnt0BClaSRqXrJJW
hwciu0Yw9nsCCQbz+vwMKVMRtQ1m2/Cl3+9K/9RYwdgfTQmNYcu3J+19trvRx2Vf
OVtwFNm2tps2YtOV1NAnr2huHt257WVis9ElCOwIpUqwJZvzLCG2VaSq0vlYZqP8
iQoQA25f9Ln34KdpF7BU2PO9LraFJNTHFIed3cd8L7U14H9iQ93mSUlibzY3HvK4
B3qeXmsn3YpJpgsvhOUPR7mTlhOsPSIdRW0vuLOrN5Rz3uVWRG8vpjCeZCYSYWBf
4KzbwEZ6n9dfc2D5N6Yx3uTdmKhAg1O1ryk7E6Sp+pVybFQrzsc=
=ttO/
-----END PGP SIGNATURE-----

View File

@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:58b8be97d9940ec17f7656c0c6b9f41b618aac468b894b534148e3296c53b8b3
size 7506711

View File

@@ -1,16 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEZbLUT+dL1ePeOsPwgngd5G1ZVPoFAmh+LjAACgkQgngd5G1Z
VPpCEBAAhEV+nx6pMPZ1AKIbJ8forT54bs2ZGyCycWPRxWF34gq9fiaIcNyFbNRi
3ziOqAJPt3sphorZYvcZ7K8Wx/tQbXdnKy+HkYzTgjb4JJU/NJZiiDcEcEVKoCXj
4dBPCgGflZji0lljP65SbdmelwCzjGZPbkKGTtWyN0HiOI7kcrh0F1Q7Mz2E63sW
ZxN9r2zmOEzTkxFvWm+JMoAQi5stf2XlNLIKmjg5sbhFu2qdbQ6RadkMEsXuSJbi
quzTmAVPDPFEwhSV4qtJDz8Dj2chLV+26f0sbaSSYa5G+ic4w6Vvyco4gE3K/yDz
tmPuQcH1nJIPMrglMEJnYWYXrkBBRWYXgWGVZPYvlahu86Vx0h9bZKmG4rxkSOsE
KGM4PebzhWxP9LKykY05X5AZgvrVuUaUo8WVIIvdIifX4GNzCdZFFwQTrO1AkQQY
2T4/2BuyS/Hx1hIdVnMY3uMYaIXemJDl2rid9h/pfYxfBqnvP03yV3Xb5t+0Nq8V
smdihF2G4Escts+WHTXyxBhG70QvBob6xYt9juu5UMX0PDrPNf61Dhnlur4aSA0u
NhlO+Z0KCdXexRZUdKFeNuXShfaVaGm5ouZ0NQPB0NIOlzhvDLeHJdyn6G5AkajP
r3A5DKDQmmd/bJqmi5y619o9hKx9lnmrhxj2LAGUqGycC5NBVUc=
=hWqc
-----END PGP SIGNATURE-----