forked from pool/apache2
Compare commits
17 Commits
| Author | SHA256 | Date | |
|---|---|---|---|
| 356bfd0a6f | |||
| 1aaedef3aa | |||
| 5e2a6b06f3 | |||
| 1177533e53 | |||
| 3a0ed9cf2d | |||
| e4531db3a3 | |||
| 26adddb99d | |||
| 285b0fe9bf | |||
| 4f979fbc59 | |||
| 0299bc148b | |||
| 2bde2c8dc7 | |||
| 7e57f4d1e3 | |||
| ff8f362dac | |||
| e7ac9d37d9 | |||
| 62e3b1fe7e | |||
| 9695f91e0b | |||
| 3684930e1f |
303
CVE-2024-42516.patch
Normal file
303
CVE-2024-42516.patch
Normal 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
37
CVE-2024-43204.patch
Normal 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
44
CVE-2024-47252.patch
Normal 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
62
CVE-2025-23048.patch
Normal 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
39
CVE-2025-49630.patch
Normal 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
198
CVE-2025-49812.patch
Normal 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
496
CVE-2025-53020.patch
Normal 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
203
CVE-2025-55753.patch
Normal 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
35
CVE-2025-58098.patch
Normal 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
63
CVE-2025-65082.patch
Normal 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
39
CVE-2025-66200.patch
Normal 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;
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 1996, 1997, 1998 S.u.S.E. GmbH
|
||||
# Copyright (c) 1998, 1999, 2000, 2001 SuSE GmbH
|
||||
|
||||
4172
apache2.changes
4172
apache2.changes
File diff suppressed because it is too large
Load Diff
45
apache2.spec
45
apache2.spec
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# spec file for package apache2
|
||||
#
|
||||
# Copyright (c) 2024 SUSE LLC
|
||||
# Copyright (c) 2025 SUSE LLC
|
||||
#
|
||||
# All modifications and additions to the file contributed by third parties
|
||||
# remain the property of their copyright owners, unless otherwise agreed
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
%global upstream_name httpd
|
||||
%global testsuite_name %{upstream_name}-framework
|
||||
%global tversion svn1901574
|
||||
%global tversion svn1921782
|
||||
%global flavor @BUILD_FLAVOR@%{nil}
|
||||
%define mpm %{nil}
|
||||
%if "%{flavor}" == "prefork" || "%{flavor}" == "test_prefork"
|
||||
@@ -107,7 +107,7 @@
|
||||
%define build_http2 1
|
||||
|
||||
Name: apache2%{psuffix}
|
||||
Version: 2.4.62
|
||||
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
|
||||
@@ -262,6 +286,7 @@ BuildRequires: netcfg
|
||||
# /SECTION
|
||||
%if "%{mpm}" != ""
|
||||
Provides: apache2-MPM
|
||||
Requires: apache2
|
||||
%endif
|
||||
%if "%{flavor}" == ""
|
||||
Requires: %{_sysconfdir}/mime.types
|
||||
@@ -549,6 +574,8 @@ mkdir -p %{buildroot}%{_sysconfdir}/apache2/sysconfig.d
|
||||
mkdir -p %{buildroot}/%{_fillupdir}
|
||||
install -m 644 %{SOURCE30} %{buildroot}%{_fillupdir}/sysconfig.apache2
|
||||
|
||||
# htdocsdir is used by default-server.conf
|
||||
mkdir -p %{buildroot}%{htdocsdir}
|
||||
mkdir -p %{buildroot}%{sysconfdir}
|
||||
mkdir -p %{buildroot}%{sysconfdir}/conf.d
|
||||
for c in default-server.conf \
|
||||
@@ -733,6 +760,8 @@ apxs -q CFLAGS | grep "\\%{optflags}"
|
||||
cp %{SOURCE21} mod_example.c
|
||||
apxs -c mod_example.c
|
||||
test_dir="$PWD/my-test-devel"
|
||||
# hack: %{_libdir} cannot be used in noarch packages, define shell variable _libdir, using apxs to find the real value
|
||||
_libexecdir=$(apxs -q libdir)/apache2
|
||||
echo "Try to load example module"
|
||||
mkdir $test_dir
|
||||
cat > $test_dir/httpd.conf << EOF
|
||||
@@ -743,7 +772,7 @@ User $(id -un)
|
||||
Group $(id -gn)
|
||||
Listen 60080
|
||||
DocumentRoot $test_dir
|
||||
LoadModule authz_core_module %{libexecdir}-%{default_mpm}/mod_authz_core.so
|
||||
LoadModule authz_core_module ${_libexecdir}-%{default_mpm}/mod_authz_core.so
|
||||
LoadModule example_module $PWD/.libs/mod_example.so
|
||||
<Location /hello>
|
||||
SetHandler example-handler
|
||||
@@ -778,15 +807,17 @@ function dep()
|
||||
}
|
||||
# create a conf loading all MPM's modules
|
||||
echo > $PWD/load-all-modules.conf
|
||||
# hack: %{_libdir} cannot be used in noarch packages, define shell variable _libdir, using apxs to find the real value
|
||||
_libdir=$(apxs -q libdir)
|
||||
# hack: sort -u to load mod_proxy before mod_proxy_http, mod_cache before mod_cache_disk, etc.
|
||||
modules=$(find %{_libdir}/apache2-%{mpm}/ %{_libdir}/apache2/ -name *.so | sed 's:.*/mod_\(.*\).so:\1:' | sort -u)
|
||||
modules=$(find ${_libdir}/apache2-%{mpm}/ ${_libdir}/apache2/ -name *.so | sed 's:.*/mod_\(.*\).so:\1:' | sort -u)
|
||||
# fix up dependencies
|
||||
dep "lbmethod_bybusyness" "proxy"
|
||||
dep "lbmethod_byrequests" "proxy"
|
||||
dep "lbmethod_bytraffic" "proxy"
|
||||
dep "lbmethod_heartbeat" "proxy"
|
||||
for m in $modules; do
|
||||
path=$(find %{_libdir}/apache2-%{mpm}/ %{_libdir}/apache2/ -name mod_$m.so | head -n 1)
|
||||
path=$(find ${_libdir}/apache2-%{mpm}/ ${_libdir}/apache2/ -name mod_$m.so | head -n 1)
|
||||
if ! grep -q "mod_$m.c" $PWD/load-all-modules.conf; then
|
||||
echo "<IfModule !mod_$m.c>" >> $PWD/load-all-modules.conf
|
||||
echo " LoadModule ${m}_module $path" >> $PWD/load-all-modules.conf
|
||||
@@ -834,6 +865,8 @@ exit 0
|
||||
%attr(750,root,root) %dir %{logfiledir}
|
||||
%attr(750,%{httpduser},root) %dir %{proxycachedir}
|
||||
%attr(750,%{httpduser},root) %dir %{localstatedir}
|
||||
%dir %{datadir}
|
||||
%dir %{htdocsdir}
|
||||
%dir %{libexecdir}
|
||||
%dir %{_libexecdir}
|
||||
%attr(755,root,root) %{_libexecdir}/apache2_MMN
|
||||
|
||||
BIN
httpd-2.4.62.tar.bz2
LFS
BIN
httpd-2.4.62.tar.bz2
LFS
Binary file not shown.
@@ -1,16 +0,0 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQIzBAABCgAdFiEEZbLUT+dL1ePeOsPwgngd5G1ZVPoFAmaVEjgACgkQgngd5G1Z
|
||||
VPqlUA//dMZ01CalmRf4Li2gDH+ETlQXkMST+2IYNCWZzV78g5wfjpZtApKOk+6O
|
||||
73WxdNSvnB15CJVIi/wXN/8ZQHu3u9kHCHw+ydDhOq7CiSAe1x5k0PcodR+me299
|
||||
PErBiAaBct+oJOnPCRdw5c5g3jomZgg1Nt5xS5NmI83UnbT9KHd92nNFdIjp6nFE
|
||||
mKzsQSWSSXkObj83inJ3HvT8ALGr5TpMjHSJAC/YP9B9FuTW4lQh0XFEESz6LcR/
|
||||
Z8GWAV0qfauRhNYcp5qYcVdreVAk0J9vfnruv9OdYsMI/sDM2PYAyDk9pCMuVIfv
|
||||
PuZd8n/EpMuQfeWBOLzkft2TjNYx0UAt0xLK0/FLQqbZSKgCxce3mnbm0N3qXl8h
|
||||
OpWYC86h4y4shaBOCAHI4oqRFbIlbf9bssMRSYfBYTJ1k8zmADWAhIsr5276A33G
|
||||
S8Z+Ah1XeYkvy1blSJDRqECAPLtAXgesLadpkTKTwu+9BmHXYllSmfdhW8D3v6SA
|
||||
Ab7RMonp7poBexO0o0mm14cEAwetffUhSrFfvGp7sTBjQYH3s309HtRBuLJOwmP2
|
||||
uZvAKo84nJVaZIe7TTjpA/om7sq08Jq8xdzGbEhfGnOrtg/34d3K5S9tDvBMkmDq
|
||||
HfYjFxCmfTbUDy4nqVNZcwno6jApweon+KAHbG/vJ2uMWozn2Bo=
|
||||
=Lelg
|
||||
-----END PGP SIGNATURE-----
|
||||
BIN
httpd-2.4.63.tar.bz2
LFS
Normal file
BIN
httpd-2.4.63.tar.bz2
LFS
Normal file
Binary file not shown.
16
httpd-2.4.63.tar.bz2.asc
Normal file
16
httpd-2.4.63.tar.bz2.asc
Normal 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-----
|
||||
Binary file not shown.
BIN
httpd-framework-svn1921782.tar.bz2
LFS
Normal file
BIN
httpd-framework-svn1921782.tar.bz2
LFS
Normal file
Binary file not shown.
Reference in New Issue
Block a user