From 4797340d3d5d3ed81b86cc82bafb3a654df93a54 Mon Sep 17 00:00:00 2001
From: Stephen Gallagher
Date: Wed, 6 Aug 2025 14:26:22 -0400
Subject: [PATCH 1/9] genssl: Disable dhparams generation
SSCG 3.0.3+ has a --no-dhparams-file argument, which we should use
instead of creating an unused one in a private /tmp path.
Signed-off-by: Stephen Gallagher
---
httpd-ssl-gencerts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/httpd-ssl-gencerts b/httpd-ssl-gencerts
index 5c271f7..5a3d8ed 100755
--- a/httpd-ssl-gencerts
+++ b/httpd-ssl-gencerts
@@ -33,7 +33,7 @@ sscg -q \
--cert-file /etc/pki/tls/certs/localhost.crt \
--cert-key-file /etc/pki/tls/private/localhost.key \
--ca-file /etc/pki/tls/certs/localhost.crt \
- --dhparams-file /tmp/dhparams.pem \
+ --no-dhparams-file \
--lifetime 365 \
--hostname $FQDN \
--email root@$FQDN
From 817134c70cec8e5f183de160cface9d46dc27893 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lubo=C5=A1=20Uhliarik?=
Date: Mon, 8 Sep 2025 16:29:34 +0200
Subject: [PATCH 2/9] Add tmpfiles.d rules for /var directories (bootc
compatibility)
---
httpd.spec | 5 ++++-
httpd.tmpfiles | 7 +++++++
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/httpd.spec b/httpd.spec
index 2952a56..20d6771 100644
--- a/httpd.spec
+++ b/httpd.spec
@@ -31,7 +31,7 @@
Summary: Apache HTTP Server
Name: httpd
Version: 2.4.64
-Release: 3%{?dist}
+Release: 4%{?dist}
URL: https://httpd.apache.org/
Source0: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2
Source1: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2.asc
@@ -847,6 +847,9 @@ exit $rv
%{_rpmconfigdir}/macros.d/macros.httpd
%changelog
+* Mon Sep 08 2025 Luboš Uhliarik - 2.4.64-4
+- Add tmpfiles.d rules for /var directories (bootc compatibility)
+
* Thu Jul 24 2025 Fedora Release Engineering - 2.4.64-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild
diff --git a/httpd.tmpfiles b/httpd.tmpfiles
index f148886..a845ab5 100644
--- a/httpd.tmpfiles
+++ b/httpd.tmpfiles
@@ -1,2 +1,9 @@
d /run/httpd 710 root apache
d /run/httpd/htcacheclean 700 apache apache
+d /var/log/httpd 700 root root -
+d /var/www 755 root root -
+d /var/www/html 755 root root -
+d /var/www/cgi-bin 755 root root -
+d /var/lib/httpd 700 apache apache -
+d /var/cache/httpd 700 apache apache -
+d /var/cache/httpd/proxy 700 apache apache -
From 04d6a208061cc5627fb7af9db8b9c6a8383ffbb6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lubo=C5=A1=20Uhliarik?=
Date: Sat, 18 Oct 2025 03:30:41 +0200
Subject: [PATCH 3/9] new version 2.4.65
mod_proxy_hcheck: reschedule health checks after child process restart
---
.gitignore | 1 +
httpd-2.4.64-r1927270.patch | 25 -------------
httpd-2.4.65-hcheck-stuck.patch | 66 +++++++++++++++++++++++++++++++++
httpd.spec | 11 ++++--
sources | 4 +-
5 files changed, 76 insertions(+), 31 deletions(-)
delete mode 100644 httpd-2.4.64-r1927270.patch
create mode 100644 httpd-2.4.65-hcheck-stuck.patch
diff --git a/.gitignore b/.gitignore
index 0453dd4..f2fccfd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -54,3 +54,4 @@ x86_64
/httpd-2.4.62.tar.bz2.asc
/httpd-2.4.63.tar.bz2.asc
/httpd-2.4.64.tar.bz2.asc
+/httpd-2.4.65.tar.bz2.asc
diff --git a/httpd-2.4.64-r1927270.patch b/httpd-2.4.64-r1927270.patch
deleted file mode 100644
index 21b2b9d..0000000
--- a/httpd-2.4.64-r1927270.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 6e59b124221014bd1c23053e9bb63fb3362387d9 Mon Sep 17 00:00:00 2001
-From: Eric Covener
-Date: Wed, 16 Jul 2025 17:33:21 +0000
-Subject: [PATCH] rc already is set by result of expression eval
-
-git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1927270 13f79535-47bb-0310-9956-ffa450edef68
----
- modules/mappers/mod_rewrite.c | 3 ---
- 1 file changed, 3 deletions(-)
-
-diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c
-index a6c35a0be1f..a71110bc76e 100644
---- a/modules/mappers/mod_rewrite.c
-+++ b/modules/mappers/mod_rewrite.c
-@@ -4283,9 +4283,6 @@ static cond_return_type apply_rewrite_cond(rewritecond_entry *p, rewrite_ctx *ct
- p->pattern - p->pskip, err);
- rc = COND_RC_NOMATCH;
- }
-- else {
-- rc = COND_RC_MATCH;
-- }
- /* update briRC backref info */
- if (rc && !(p->flags & CONDFLAG_NOTMATCH)) {
- ctx->briRC.source = source;
-
diff --git a/httpd-2.4.65-hcheck-stuck.patch b/httpd-2.4.65-hcheck-stuck.patch
new file mode 100644
index 0000000..315b9c2
--- /dev/null
+++ b/httpd-2.4.65-hcheck-stuck.patch
@@ -0,0 +1,66 @@
+--- a/modules/proxy/mod_proxy_hcheck.c
++++ b/modules/proxy/mod_proxy_hcheck.c
+@@ -989,12 +989,30 @@ static apr_status_t hc_watchdog_callback(int state
+ sctx_t *ctx = (sctx_t *)data;
+ server_rec *s = ctx->s;
+ proxy_server_conf *conf;
++ proxy_worker **workers;
++ proxy_worker *worker;
++ apr_time_t now;
++ int i, n;
+
++ conf = (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module);
++ balancer = (proxy_balancer *)conf->balancers->elts;
++
+ switch (state) {
+ case AP_WATCHDOG_STATE_STARTING:
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(03258)
+ "%s watchdog started.",
+ HCHECK_WATHCHDOG_NAME);
++ /* set last update time for all workers */
++ now = apr_time_now();
++ for (i = 0; i < conf->balancers->nelts; i++, balancer++) {
++ workers = (proxy_worker **)balancer->workers->elts;
++ for (n = 0; n < balancer->workers->nelts; n++, ++workers) {
++ worker = *workers;
++ if (worker->s->updated == 0) {
++ worker->s->updated = now;
++ }
++ }
++ }
+ #if HC_USE_THREADS
+ if (tpsize && hctp == NULL) {
+ rv = apr_thread_pool_create(&hctp, tpsize,
+@@ -1020,21 +1038,13 @@ static apr_status_t hc_watchdog_callback(int state
+
+ case AP_WATCHDOG_STATE_RUNNING:
+ /* loop thru all workers */
+- if (s) {
+- int i;
+- conf = (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module);
+- balancer = (proxy_balancer *)conf->balancers->elts;
+- ctx->s = s;
++ {
++ now = apr_time_now();
+ for (i = 0; i < conf->balancers->nelts; i++, balancer++) {
+- int n;
+- apr_time_t now;
+- proxy_worker **workers;
+- proxy_worker *worker;
+ /* Have any new balancers or workers been added dynamically? */
+ ap_proxy_sync_balancer(balancer, s, conf);
+ workers = (proxy_worker **)balancer->workers->elts;
+- now = apr_time_now();
+- for (n = 0; n < balancer->workers->nelts; n++) {
++ for (n = 0; n < balancer->workers->nelts; n++, workers++) {
+ worker = *workers;
+ if (!PROXY_WORKER_IS(worker, PROXY_WORKER_STOPPED) &&
+ (worker->s->method != NONE) &&
+@@ -1074,7 +1084,6 @@ static apr_status_t hc_watchdog_callback(int state
+ hc_check(NULL, baton);
+ }
+ }
+- workers++;
+ }
+ }
+ }
diff --git a/httpd.spec b/httpd.spec
index 20d6771..9d718a5 100644
--- a/httpd.spec
+++ b/httpd.spec
@@ -30,8 +30,8 @@
Summary: Apache HTTP Server
Name: httpd
-Version: 2.4.64
-Release: 4%{?dist}
+Version: 2.4.65
+Release: 1%{?dist}
URL: https://httpd.apache.org/
Source0: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2
Source1: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2.asc
@@ -103,8 +103,7 @@ Patch30: httpd-2.4.64-separate-systemd-fns.patch
# Bug fixes
# https://bugzilla.redhat.com/show_bug.cgi?id=1397243
Patch60: httpd-2.4.43-enable-sslv3.patch
-# https://bz.apache.org/bugzilla/show_bug.cgi?id=69745
-Patch61: httpd-2.4.64-r1927270.patch
+Patch61: httpd-2.4.65-hcheck-stuck.patch
# Security fixes
# Patch200: ...
@@ -847,6 +846,10 @@ exit $rv
%{_rpmconfigdir}/macros.d/macros.httpd
%changelog
+* Sat Oct 18 2025 Luboš Uhliarik - 2.4.65-1
+- new version 2.4.65
+- mod_proxy_hcheck: reschedule health checks after child process restart
+
* Mon Sep 08 2025 Luboš Uhliarik - 2.4.64-4
- Add tmpfiles.d rules for /var directories (bootc compatibility)
diff --git a/sources b/sources
index c5568c0..8d4165c 100644
--- a/sources
+++ b/sources
@@ -1,3 +1,3 @@
-SHA512 (httpd-2.4.64.tar.bz2) = 299cb0d87a7e0e0a99d22bba7349b6b07c69222897410f9670af29896288d1f4e1da81d22ac9e1d8d6ea096e88044ab1dd34555b40a4b1b1cb3fd4b1d1897a7a
-SHA512 (httpd-2.4.64.tar.bz2.asc) = 1a28214c8468288477f706422ab3419e186ef37dc1eb55760a7e951605e08e295230b6d828948693a9d5ba247e352b205254c999763fa6845dab2f703152e1d8
+SHA512 (httpd-2.4.65.tar.bz2) = 202f8bfe2aafcfbcd7315191d466e9c10b9a8c0abafb7864510b6e1abe4cb660aaacc2456aa77d43e48ef7a49e591d0b54170d3daf67abc3e06c3da1c63fdffc
+SHA512 (httpd-2.4.65.tar.bz2.asc) = edcf02be97567fb28fef78f757e3355802575782ab452eaea79da70812b20ef4ba49a609e409a9664ec2546720b303deebbd563f3079ce4e77d67b91816210d1
SHA512 (KEYS) = 88c848b7ab9e4915d6625dcad3e8328673b0448f2ce76f2c44eecc612cf6afbce3287a4ee7219a44c6fcc61d5ecb2a1a8545456a4a16b90400263d7249cbf192
From 23f7eb497eefd8e1fba1494b946e39757ec46e51 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lubo=C5=A1=20Uhliarik?=
Date: Tue, 4 Nov 2025 12:08:54 +0100
Subject: [PATCH 4/9] mod_ssl: Add SSLVHostSNIPolicy directive to set the
compatibility level
required for VirtualHost matching.
---
httpd-2.4.65-sslvhostsnipolicy.patch | 545 +++++++++++++++++++++++++++
httpd.spec | 7 +-
2 files changed, 551 insertions(+), 1 deletion(-)
create mode 100644 httpd-2.4.65-sslvhostsnipolicy.patch
diff --git a/httpd-2.4.65-sslvhostsnipolicy.patch b/httpd-2.4.65-sslvhostsnipolicy.patch
new file mode 100644
index 0000000..401882a
--- /dev/null
+++ b/httpd-2.4.65-sslvhostsnipolicy.patch
@@ -0,0 +1,545 @@
+From 0e0995bef84a66c9dabe75d6e81376896cc819bd Mon Sep 17 00:00:00 2001
+From: Joe Orton
+Date: Tue, 4 Nov 2025 12:05:05 +0100
+Subject: [PATCH] [PATCH] mod_ssl: Add SSLVHostSNIPolicy directive to set the
+ compatibility level required for VirtualHost matching.
+
+For "secure" and "authonly" modes, a hash of the policy-relevant vhost
+configuration is created and stored in the post_config hooks, reducing
+the runtime code complexity (and overhead).
+
+* modules/ssl/ssl_engine_kernel.c (ssl_check_vhost_sni_policy): New
+ function, replacing ssl_server_compatible et al.
+
+* modules/ssl/ssl_engine_config.c (ssl_cmd_SSLVHostSNIPolicy): New
+ function.
+
+* modules/ssl/ssl_engine_init.c (md5_strarray_cmp, md5_strarray_hash,
+ hash_sni_policy_pk, hash_sni_policy_auth, create_sni_policy_hash):
+ New functions.
+ (ssl_init_Module): Invoke create_sni_policy_hash to store the hash
+ for every SSLSrvConfigRec.
+
+* modules/ssl/ssl_private.h (SSLModConfigRec): Add snivh_policy field.
+ (SSLSrvConfigRec): Add sni_policy_hash field.
+
+PR: 69743
+GitHub: closes #561
+---
+ docs/manual/mod/mod_ssl.html.en | 77 +++++++++++++++++++
+ modules/ssl/mod_ssl.c | 2 +
+ modules/ssl/ssl_engine_config.c | 41 ++++++++++
+ modules/ssl/ssl_engine_init.c | 106 ++++++++++++++++++++++++++
+ modules/ssl/ssl_engine_kernel.c | 131 ++++++--------------------------
+ modules/ssl/ssl_private.h | 17 +++++
+ 6 files changed, 265 insertions(+), 109 deletions(-)
+
+diff --git a/docs/manual/mod/mod_ssl.html.en b/docs/manual/mod/mod_ssl.html.en
+index e2a4a99..95f0667 100644
+--- a/docs/manual/mod/mod_ssl.html.en
++++ b/docs/manual/mod/mod_ssl.html.en
+@@ -125,6 +125,7 @@ to provide the cryptography engine.
+
+@@ -2863,6 +2864,82 @@ known to the server (i.e. the CA's certificate is under
+ Example
SSLVerifyDepth 10
+
+
++
++
++
++
This directive sets the policy applied when checking whether the
++<VirtualHost>
++identified by the Host request header in an HTTP request
++is compatible with the <VirtualHost> identified from the SNI
++extension sent during the initial TLS connection handshake. If an HTTP
++request is associated with a virtual host which has an incompatible
++SSL/TLS configuration under the policy used, an HTTP error response
++with status code 421 ("Misdirected Request") will be sent.
++
++
The policy also applies to TLS connections where an SNI extension
++is not sent during the handshake, implicitly using the default or
++first virtual host definition. If the Host header in an HTTP request
++on such a connection identifies any other non-default virtual host,
++the compatibility policy is tested.
++
++
The strict policy blocks all HTTP requests which are
++identified with a different virtual host to that identifed by SNI.
++The insecure policy allows all HTTP requests regardless
++of virtual host identified; such a configuration may be vulnerable to
++CVE-2025-23048.
++
++
++
The (default) secure, and authonly
++policies compare specific aspects of the SSL configuration for the two
++virtual hosts, which are grouped into two categories:
++
++
++
++This table illustrates whether an HTTP request will be blocked or
++allowed when the virtual host configurations differ as described,
++under each different policy setting:
++
++
++
++ strict | blocked | blocked | blocked |
++
++
++ secure | allowed | blocked | blocked |
++
++
++ authonly | allowed | blocked | allowed |
++
++
++ insecure | allowed | allowed | allowed |
++
++
++
++
Example
SSLVHostSNIPolicy authonly
++
++
++
+
+
+
+diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c
+index fb66d18..c0fdafd 100644
+--- a/modules/ssl/mod_ssl.c
++++ b/modules/ssl/mod_ssl.c
+@@ -80,6 +80,8 @@ static const command_rec ssl_config_cmds[] = {
+ SSL_CMD_SRV(RandomSeed, TAKE23,
+ "SSL Pseudo Random Number Generator (PRNG) seeding source "
+ "('startup|connect builtin|file:/path|exec:/path [bytes]')")
++ SSL_CMD_SRV(VHostSNIPolicy, TAKE1,
++ "SSL VirtualHost SNI compatibility policy setting")
+
+ /*
+ * Per-server context configuration directives
+diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c
+index c5dce7f..31a1942 100644
+--- a/modules/ssl/ssl_engine_config.c
++++ b/modules/ssl/ssl_engine_config.c
+@@ -82,6 +82,9 @@ SSLModConfigRec *ssl_config_global_create(server_rec *s)
+ #ifdef HAVE_FIPS
+ mc->fips = UNSET;
+ #endif
++#ifdef HAVE_TLSEXT
++ mc->snivh_policy = MODSSL_SNIVH_SECURE;
++#endi
+
+ apr_pool_userdata_set(mc, SSL_MOD_CONFIG_KEY,
+ apr_pool_cleanup_null,
+@@ -1918,6 +1921,44 @@ const char *ssl_cmd_SSLStrictSNIVHostCheck(cmd_parms *cmd, void *dcfg, int flag
+ #endif
+ }
+
++const char *ssl_cmd_SSLVHostSNIPolicy(cmd_parms *cmd, void *dcfg, const char *arg)
++{
++#ifdef HAVE_TLSEXT
++ SSLModConfigRec *mc = myModConfig(cmd->server);
++ const char *err;
++
++ if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
++ return err;
++ }
++ if (!mc) {
++ return "SSLVHostSNIPolicy cannot be used inside SSLPolicyDefine";
++ }
++
++ if (strcEQ(arg, "secure")) {
++ mc->snivh_policy = MODSSL_SNIVH_SECURE;
++ }
++ else if (strcEQ(arg, "strict")) {
++ mc->snivh_policy = MODSSL_SNIVH_STRICT;
++ }
++ else if (strcEQ(arg, "insecure")) {
++ mc->snivh_policy = MODSSL_SNIVH_INSECURE;
++ }
++ else if (strcEQ(arg, "authonly")) {
++ mc->snivh_policy = MODSSL_SNIVH_AUTHONLY;
++ }
++ else {
++ return apr_psprintf(cmd->pool, "Invalid SSLVhostSNIPolicy "
++ "argument '%s'", arg);
++ }
++
++ return NULL;
++#else
++ return "SSLVHostSNIPolicy cannot be used, OpenSSL is not built with "
++ "support for TLS extensions and SNI indication. Refer to the "
++ "documentation, and build a compatible version of OpenSSL."
++#endif
++}
++
+ #ifdef HAVE_OCSP_STAPLING
+
+ const char *ssl_cmd_SSLStaplingCache(cmd_parms *cmd,
+diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
+index 2fbd076..64a9f32 100644
+--- a/modules/ssl/ssl_engine_init.c
++++ b/modules/ssl/ssl_engine_init.c
+@@ -186,6 +186,110 @@ static void ssl_add_version_components(apr_pool_t *ptemp, apr_pool_t *pconf,
+ modver, AP_SERVER_BASEVERSION, incver);
+ }
+
++#ifdef HAVE_TLSEXT
++/* Helper functions to create the SNI vhost policy hash. The policy
++ * hash captures the configuration elements relevant to the mode
++ * selected at runtime by SSLVHostSNIPolicy. */
++
++#define md5_str_update(ctx_, pfx_, str_) do { apr_md5_update(ctx_, pfx_, strlen(pfx_)); apr_md5_update(ctx_, str_, strlen(str_)); } while (0)
++#define md5_ifstr_update(ctx_, pfx_, str_) do { apr_md5_update(ctx_, pfx_, strlen(pfx_)); if (str_) apr_md5_update(ctx_, str_, strlen(str_)); } while (0)
++#define md5_fmt_update(ctx_, fmt_, i_) do { char s_[128]; apr_snprintf(s_, sizeof s_, fmt_, i_); \
++ apr_md5_update(ctx_, s_, strlen(s_)); } while (0)
++
++static int md5_strarray_cmp(const void *p1, const void *p2)
++{
++ return strcmp(*(char **)p1, *(char **)p2);
++}
++
++/* Hashes an array of strings in sorted order. */
++static void md5_strarray_hash(apr_pool_t *ptemp, apr_md5_ctx_t *hash,
++ const char *pfx, apr_array_header_t *s)
++{
++ char **elts = apr_pmemdup(ptemp, s->elts, s->nelts * sizeof *elts);
++ int i;
++
++ qsort(elts, s->nelts, sizeof(char *), md5_strarray_cmp);
++
++ apr_md5_update(hash, pfx, strlen(pfx));
++ for (i = 0; i < s->nelts; i++) {
++ md5_str_update(hash, "elm:", elts[i]);
++ }
++}
++
++static void hash_sni_policy_pk(apr_pool_t *ptemp, apr_md5_ctx_t *hash, modssl_ctx_t *ctx)
++{
++ md5_fmt_update(hash, "protocol:%d", ctx->protocol);
++
++ md5_ifstr_update(hash, "ciphers:", ctx->auth.cipher_suite);
++ md5_ifstr_update(hash, "tls13_ciphers:", ctx->auth.tls13_ciphers);
++
++ md5_strarray_hash(ptemp, hash, "cert_files:", ctx->pks->cert_files);
++ md5_strarray_hash(ptemp, hash, "key_files:", ctx->pks->key_files);
++}
++
++static void hash_sni_policy_auth(apr_md5_ctx_t *hash, modssl_ctx_t *ctx)
++{
++ modssl_pk_server_t *pks = ctx->pks;
++ modssl_auth_ctx_t *a = &ctx->auth;
++
++ md5_fmt_update(hash, "verify_depth:%d", a->verify_depth);
++ md5_fmt_update(hash, "verify_mode:%d", a->verify_mode);
++
++ md5_ifstr_update(hash, "ca_name_path:", pks->ca_name_path);
++ md5_ifstr_update(hash, "ca_name_file:", pks->ca_name_file);
++ md5_ifstr_update(hash, "ca_cert_path:", a->ca_cert_path);
++ md5_ifstr_update(hash, "ca_cert_file:", a->ca_cert_file);
++ md5_ifstr_update(hash, "crl_path:", ctx->crl_path);
++ md5_ifstr_update(hash, "crl_file:", ctx->crl_file);
++ md5_fmt_update(hash, "crl_check_mask:%d", ctx->crl_check_mask);
++ md5_fmt_update(hash, "ocsp_mask:%d", ctx->ocsp_mask);
++ md5_fmt_update(hash, "ocsp_force_default:%d", ctx->ocsp_force_default);
++ md5_ifstr_update(hash, "ocsp_responder:", ctx->ocsp_responder);
++
++#ifdef HAVE_SRP
++ md5_ifstr_update(hash, "srp_vfile:", ctx->srp_vfile);
++#endif
++
++#ifdef HAVE_SSL_CONF_CMD
++ {
++ apr_array_header_t *parms = ctx->ssl_ctx_param;
++ int n;
++
++ for (n = 0; n < parms->nelts; n++) {
++ ssl_ctx_param_t *p = &APR_ARRAY_IDX(parms, n, ssl_ctx_param_t);
++
++ md5_str_update(hash, "param:", p->name);
++ md5_str_update(hash, "value:", p->value);
++ }
++ }
++#endif
++}
++#endif
++
++static char *create_sni_policy_hash(apr_pool_t *p, apr_pool_t *ptemp,
++ modssl_snivhpolicy_t policy,
++ SSLSrvConfigRec *sc)
++{
++ char *rv = NULL;
++#ifdef HAVE_TLSEXT
++ if (policy != MODSSL_SNIVH_STRICT && policy != MODSSL_SNIVH_INSECURE) {
++ apr_md5_ctx_t hash;
++ unsigned char digest[APR_MD5_DIGESTSIZE];
++
++ /* Create the vhost policy hash for comparison later. */
++ apr_md5_init(&hash);
++ hash_sni_policy_auth(&hash, sc->server);
++ if (policy == MODSSL_SNIVH_SECURE)
++ hash_sni_policy_pk(ptemp, &hash, sc->server);
++ apr_md5_final(digest, &hash);
++
++ rv = apr_palloc(p, 2 * APR_MD5_DIGESTSIZE + 1);
++ ap_bin2hex(digest, APR_MD5_DIGESTSIZE, rv); /* sets final '\0' */
++ }
++#endif
++ return rv;
++}
++
+ /* _________________________________________________________________
+ **
+ ** Let other answer special connection attempts.
+@@ -439,6 +543,8 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
+ return rv;
+ }
+ }
++
++ sc->sni_policy_hash = create_sni_policy_hash(p, ptemp, mc->snivh_policy, sc);
+ }
+
+ /*
+diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
+index 33aa1f7..a6af633 100644
+--- a/modules/ssl/ssl_engine_kernel.c
++++ b/modules/ssl/ssl_engine_kernel.c
+@@ -101,112 +101,28 @@ static int fill_reneg_buffer(request_rec *r, SSLDirConfigRec *dc)
+ }
+
+ #ifdef HAVE_TLSEXT
+-static int ap_array_same_str_set(apr_array_header_t *s1, apr_array_header_t *s2)
++/* Check whether a transition from vhost sc1 to sc2 from SNI to Host:
++ * vhost selection is permitted according to the SSLVHostSNIPolicy
++ * setting. Returns 1 if the policy treats the vhosts as compatible,
++ * else 0. */
++static int ssl_check_vhost_sni_policy(SSLSrvConfigRec *sc1,
++ SSLSrvConfigRec *sc2)
+ {
+- int i;
+- const char *c;
+-
+- if (s1 == s2) {
++ modssl_snivhpolicy_t policy = sc1->mc->snivh_policy;
++
++ /* Policy: insecure => allow everything. */
++ if (policy == MODSSL_SNIVH_INSECURE)
+ return 1;
+- }
+- else if (!s1 || !s2 || (s1->nelts != s2->nelts)) {
+- return 0;
+- }
+
+- for (i = 0; i < s1->nelts; i++) {
+- c = APR_ARRAY_IDX(s1, i, const char *);
+- if (!c || !ap_array_str_contains(s2, c)) {
+- return 0;
+- }
+- }
+- return 1;
+-}
+-
+-static int ssl_pk_server_compatible(modssl_pk_server_t *pks1,
+- modssl_pk_server_t *pks2)
+-{
+- if (!pks1 || !pks2) {
+- return 0;
+- }
+- /* both have the same certificates? */
+- if ((pks1->ca_name_path != pks2->ca_name_path)
+- && (!pks1->ca_name_path || !pks2->ca_name_path
+- || strcmp(pks1->ca_name_path, pks2->ca_name_path))) {
+- return 0;
+- }
+- if ((pks1->ca_name_file != pks2->ca_name_file)
+- && (!pks1->ca_name_file || !pks2->ca_name_file
+- || strcmp(pks1->ca_name_file, pks2->ca_name_file))) {
+- return 0;
+- }
+- if (!ap_array_same_str_set(pks1->cert_files, pks2->cert_files)
+- || !ap_array_same_str_set(pks1->key_files, pks2->key_files)) {
+- return 0;
+- }
+- return 1;
+-}
+-
+-static int ssl_auth_compatible(modssl_auth_ctx_t *a1,
+- modssl_auth_ctx_t *a2)
+-{
+- if (!a1 || !a2) {
+- return 0;
+- }
+- /* both have the same verification */
+- if ((a1->verify_depth != a2->verify_depth)
+- || (a1->verify_mode != a2->verify_mode)) {
+- return 0;
+- }
+- /* both have the same ca path/file */
+- if ((a1->ca_cert_path != a2->ca_cert_path)
+- && (!a1->ca_cert_path || !a2->ca_cert_path
+- || strcmp(a1->ca_cert_path, a2->ca_cert_path))) {
+- return 0;
+- }
+- if ((a1->ca_cert_file != a2->ca_cert_file)
+- && (!a1->ca_cert_file || !a2->ca_cert_file
+- || strcmp(a1->ca_cert_file, a2->ca_cert_file))) {
+- return 0;
+- }
+- /* both have the same ca cipher suite string */
+- if ((a1->cipher_suite != a2->cipher_suite)
+- && (!a1->cipher_suite || !a2->cipher_suite
+- || strcmp(a1->cipher_suite, a2->cipher_suite))) {
+- return 0;
+- }
+- /* both have the same ca cipher suite string */
+- if ((a1->tls13_ciphers != a2->tls13_ciphers)
+- && (!a1->tls13_ciphers || !a2->tls13_ciphers
+- || strcmp(a1->tls13_ciphers, a2->tls13_ciphers))) {
+- return 0;
+- }
+- return 1;
+-}
+-
+-static int ssl_ctx_compatible(modssl_ctx_t *ctx1,
+- modssl_ctx_t *ctx2)
+-{
+- if (!ctx1 || !ctx2
+- || (ctx1->protocol != ctx2->protocol)
+- || !ssl_auth_compatible(&ctx1->auth, &ctx2->auth)
+- || !ssl_pk_server_compatible(ctx1->pks, ctx2->pks)) {
++ /* Policy: strict => fail for any vhost transition. */
++ if (policy == MODSSL_SNIVH_STRICT && sc1 != sc2)
+ return 0;
+- }
+- return 1;
+-}
+
+-static int ssl_server_compatible(server_rec *s1, server_rec *s2)
+-{
+- SSLSrvConfigRec *sc1 = s1? mySrvConfig(s1) : NULL;
+- SSLSrvConfigRec *sc2 = s2? mySrvConfig(s2) : NULL;
++ /* For authonly/secure policy, compare the hash. */
++ AP_DEBUG_ASSERT(sc1->sni_policy_hash);
++ AP_DEBUG_ASSERT(sc2->sni_policy_hash);
+
+- /* both use the same TLS protocol? */
+- if (!sc1 || !sc2
+- || !ssl_ctx_compatible(sc1->server, sc2->server)) {
+- return 0;
+- }
+-
+- return 1;
++ return strcmp(sc1->sni_policy_hash, sc2->sni_policy_hash) == 0;
+ }
+ #endif
+
+@@ -275,6 +191,8 @@ int ssl_hook_ReadReq(request_rec *r)
+ server_rec *handshakeserver = sslconn->server;
+ SSLSrvConfigRec *hssc = mySrvConfig(handshakeserver);
+
++ AP_DEBUG_ASSERT(hssc);
++
+ if ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
+ /*
+ * The SNI extension supplied a hostname. So don't accept requests
+@@ -315,19 +233,14 @@ int ssl_hook_ReadReq(request_rec *r)
+ "which is required to access this server.
\n");
+ return HTTP_FORBIDDEN;
+ }
+- if (r->server != handshakeserver
+- && !ssl_server_compatible(sslconn->server, r->server)) {
+- /*
+- * The request does not select the virtual host that was
+- * selected for handshaking and its SSL parameters are different
+- */
+-
++ /* Enforce SSL SNI vhost compatibility policy. */
++ if (!ssl_check_vhost_sni_policy(sc, hssc)) {
+ 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",
++ " via HTTP have no compatible SSL setup for policy '%s'",
+ servername ? servername : handshakeserver->server_hostname,
+ servername ? "provided via SNI" : "(default host as no SNI was provided)",
+- r->hostname);
++ r->hostname, MODSSL_SNIVH_NAME(sc->mc->snivh_policy));
+ return HTTP_MISDIRECTED_REQUEST;
+ }
+ }
+diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
+index 2b18189..dbef182 100644
+--- a/modules/ssl/ssl_private.h
++++ b/modules/ssl/ssl_private.h
+@@ -556,6 +556,19 @@ typedef struct {
+ int nBytes;
+ } ssl_randseed_t;
+
++/* SNI vhost compatibility policy. */
++typedef enum {
++ MODSSL_SNIVH_STRICT = 0,
++ MODSSL_SNIVH_SECURE = 1,
++ MODSSL_SNIVH_AUTHONLY = 2,
++ MODSSL_SNIVH_INSECURE = 3
++} modssl_snivhpolicy_t;
++
++/* Maps modssl_snivhpolicy_t back into a config option string. */
++#define MODSSL_SNIVH_NAME(p_) ((p_) == MODSSL_SNIVH_STRICT ? "strict" : \
++ ((p_) == MODSSL_SNIVH_SECURE ? "secure" : \
++ ((p_) == MODSSL_SNIVH_AUTHONLY ? "authonly" : "insecure" )))
++
+ /**
+ * Define the structure of an ASN.1 anything
+ */
+@@ -689,6 +702,8 @@ typedef struct {
+ #ifdef HAVE_FIPS
+ BOOL fips;
+ #endif
++
++ modssl_snivhpolicy_t snivh_policy;
+ } SSLModConfigRec;
+
+ /** Structure representing configured filenames for certs and keys for
+@@ -843,6 +858,7 @@ struct SSLSrvConfigRec {
+ modssl_ctx_t *server;
+ #ifdef HAVE_TLSEXT
+ ssl_enabled_t strict_sni_vhost_check;
++ const char *sni_policy_hash;
+ #endif
+ #ifndef OPENSSL_NO_COMP
+ BOOL compression;
+@@ -918,6 +934,7 @@ const char *ssl_cmd_SSLRequire(cmd_parms *, void *, const char *);
+ const char *ssl_cmd_SSLUserName(cmd_parms *, void *, const char *);
+ const char *ssl_cmd_SSLRenegBufferSize(cmd_parms *cmd, void *dcfg, const char *arg);
+ const char *ssl_cmd_SSLStrictSNIVHostCheck(cmd_parms *cmd, void *dcfg, int flag);
++const char *ssl_cmd_SSLVHostSNIPolicy(cmd_parms *cmd, void *dcfg, const char *arg);
+ const char *ssl_cmd_SSLInsecureRenegotiation(cmd_parms *cmd, void *dcfg, int flag);
+
+ const char *ssl_cmd_SSLProxyEngine(cmd_parms *cmd, void *dcfg, int flag);
+--
+2.44.0
+
diff --git a/httpd.spec b/httpd.spec
index 9d718a5..6d06795 100644
--- a/httpd.spec
+++ b/httpd.spec
@@ -31,7 +31,7 @@
Summary: Apache HTTP Server
Name: httpd
Version: 2.4.65
-Release: 1%{?dist}
+Release: 2%{?dist}
URL: https://httpd.apache.org/
Source0: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2
Source1: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2.asc
@@ -99,6 +99,7 @@ Patch27: httpd-2.4.64-sslprotdefault.patch
Patch28: httpd-2.4.43-logjournal.patch
Patch29: httpd-2.4.63-r1912477+.patch
Patch30: httpd-2.4.64-separate-systemd-fns.patch
+Patch31: httpd-2.4.65-sslvhostsnipolicy.patch
# Bug fixes
# https://bugzilla.redhat.com/show_bug.cgi?id=1397243
@@ -846,6 +847,10 @@ exit $rv
%{_rpmconfigdir}/macros.d/macros.httpd
%changelog
+* Tue Nov 04 2025 Luboš Uhliarik
- 2.4.65-2
+- mod_ssl: Add SSLVHostSNIPolicy directive to set the compatibility level
+ required for VirtualHost matching.
+
* Sat Oct 18 2025 Luboš Uhliarik - 2.4.65-1
- new version 2.4.65
- mod_proxy_hcheck: reschedule health checks after child process restart
From 943e0af2d4905f60d87dc4bb49e886b79fed3909 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lubo=C5=A1=20Uhliarik?=
Date: Tue, 4 Nov 2025 13:14:49 +0100
Subject: [PATCH 5/9] Fix typo in patch + include util_md5.h
mod_ssl: Add SSLVHostSNIPolicy directive to set the compatibility level
required for VirtualHost matching.
---
httpd-2.4.65-sslvhostsnipolicy.patch | 30 ++++++++++++++++++----------
1 file changed, 19 insertions(+), 11 deletions(-)
diff --git a/httpd-2.4.65-sslvhostsnipolicy.patch b/httpd-2.4.65-sslvhostsnipolicy.patch
index 401882a..6767cbc 100644
--- a/httpd-2.4.65-sslvhostsnipolicy.patch
+++ b/httpd-2.4.65-sslvhostsnipolicy.patch
@@ -1,7 +1,7 @@
-From 0e0995bef84a66c9dabe75d6e81376896cc819bd Mon Sep 17 00:00:00 2001
-From: Joe Orton
-Date: Tue, 4 Nov 2025 12:05:05 +0100
-Subject: [PATCH] [PATCH] mod_ssl: Add SSLVHostSNIPolicy directive to set the
+From ba168444686368377c6e69373e20e6dae8ebb702 Mon Sep 17 00:00:00 2001
+From: Joe Orton
+Date: Tue, 4 Nov 2025 12:49:36 +0100
+Subject: [PATCH] [PATCH] mod_ssl: Add SSLVHostSNIPolicy directive to set the
compatibility level required for VirtualHost matching.
For "secure" and "authonly" modes, a hash of the policy-relevant vhost
@@ -29,10 +29,10 @@ GitHub: closes #561
docs/manual/mod/mod_ssl.html.en | 77 +++++++++++++++++++
modules/ssl/mod_ssl.c | 2 +
modules/ssl/ssl_engine_config.c | 41 ++++++++++
- modules/ssl/ssl_engine_init.c | 106 ++++++++++++++++++++++++++
+ modules/ssl/ssl_engine_init.c | 107 ++++++++++++++++++++++++++
modules/ssl/ssl_engine_kernel.c | 131 ++++++--------------------------
modules/ssl/ssl_private.h | 17 +++++
- 6 files changed, 265 insertions(+), 109 deletions(-)
+ 6 files changed, 266 insertions(+), 109 deletions(-)
diff --git a/docs/manual/mod/mod_ssl.html.en b/docs/manual/mod/mod_ssl.html.en
index e2a4a99..95f0667 100644
@@ -143,7 +143,7 @@ index fb66d18..c0fdafd 100644
/*
* Per-server context configuration directives
diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c
-index c5dce7f..31a1942 100644
+index c5dce7f..f856b18 100644
--- a/modules/ssl/ssl_engine_config.c
+++ b/modules/ssl/ssl_engine_config.c
@@ -82,6 +82,9 @@ SSLModConfigRec *ssl_config_global_create(server_rec *s)
@@ -152,7 +152,7 @@ index c5dce7f..31a1942 100644
#endif
+#ifdef HAVE_TLSEXT
+ mc->snivh_policy = MODSSL_SNIVH_SECURE;
-+#endi
++#endif
apr_pool_userdata_set(mc, SSL_MOD_CONFIG_KEY,
apr_pool_cleanup_null,
@@ -202,10 +202,18 @@ index c5dce7f..31a1942 100644
const char *ssl_cmd_SSLStaplingCache(cmd_parms *cmd,
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
-index 2fbd076..64a9f32 100644
+index 2fbd076..1bf6ac4 100644
--- a/modules/ssl/ssl_engine_init.c
+++ b/modules/ssl/ssl_engine_init.c
-@@ -186,6 +186,110 @@ static void ssl_add_version_components(apr_pool_t *ptemp, apr_pool_t *pconf,
+@@ -30,6 +30,7 @@
+
+ #include "mpm_common.h"
+ #include "mod_md.h"
++#include "util_md5.h"
+
+ static apr_status_t ssl_init_ca_cert_path(server_rec *, apr_pool_t *, const char *,
+ STACK_OF(X509_NAME) *, STACK_OF(X509_INFO) *);
+@@ -186,6 +187,110 @@ static void ssl_add_version_components(apr_pool_t *ptemp, apr_pool_t *pconf,
modver, AP_SERVER_BASEVERSION, incver);
}
@@ -316,7 +324,7 @@ index 2fbd076..64a9f32 100644
/* _________________________________________________________________
**
** Let other answer special connection attempts.
-@@ -439,6 +543,8 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
+@@ -439,6 +544,8 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
return rv;
}
}
From fb46d5df49d5e1b081507d639f028fd2fda0d267 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lubo=C5=A1=20Uhliarik?=
Date: Wed, 12 Nov 2025 11:16:19 +0100
Subject: [PATCH 6/9] mod_ssl: SSLVHostSNIPolicy - Fix handling of STRICT mode
---
httpd-2.4.65-sslvhostsnipolicy.patch | 41 ++++++++++++++--------------
httpd.spec | 5 +++-
2 files changed, 25 insertions(+), 21 deletions(-)
diff --git a/httpd-2.4.65-sslvhostsnipolicy.patch b/httpd-2.4.65-sslvhostsnipolicy.patch
index 6767cbc..0831efc 100644
--- a/httpd-2.4.65-sslvhostsnipolicy.patch
+++ b/httpd-2.4.65-sslvhostsnipolicy.patch
@@ -1,7 +1,7 @@
-From ba168444686368377c6e69373e20e6dae8ebb702 Mon Sep 17 00:00:00 2001
+From 0263d1e290bc029c5c059fdaa4f21ca9885f9c84 Mon Sep 17 00:00:00 2001
From: Joe Orton
-Date: Tue, 4 Nov 2025 12:49:36 +0100
-Subject: [PATCH] [PATCH] mod_ssl: Add SSLVHostSNIPolicy directive to set the
+Date: Wed, 12 Nov 2025 11:11:41 +0100
+Subject: [PATCH] mod_ssl: Add SSLVHostSNIPolicy directive to set the
compatibility level required for VirtualHost matching.
For "secure" and "authonly" modes, a hash of the policy-relevant vhost
@@ -26,13 +26,13 @@ the runtime code complexity (and overhead).
PR: 69743
GitHub: closes #561
---
- docs/manual/mod/mod_ssl.html.en | 77 +++++++++++++++++++
+ docs/manual/mod/mod_ssl.html.en | 77 ++++++++++++++++++
modules/ssl/mod_ssl.c | 2 +
modules/ssl/ssl_engine_config.c | 41 ++++++++++
- modules/ssl/ssl_engine_init.c | 107 ++++++++++++++++++++++++++
- modules/ssl/ssl_engine_kernel.c | 131 ++++++--------------------------
- modules/ssl/ssl_private.h | 17 +++++
- 6 files changed, 266 insertions(+), 109 deletions(-)
+ modules/ssl/ssl_engine_init.c | 107 +++++++++++++++++++++++++
+ modules/ssl/ssl_engine_kernel.c | 133 ++++++--------------------------
+ modules/ssl/ssl_private.h | 17 ++++
+ 6 files changed, 267 insertions(+), 110 deletions(-)
diff --git a/docs/manual/mod/mod_ssl.html.en b/docs/manual/mod/mod_ssl.html.en
index e2a4a99..95f0667 100644
@@ -60,7 +60,7 @@ index e2a4a99..95f0667 100644
+| Context: | server config |
+| Status: | Extension |
+| Module: | mod_ssl |
-+| Compatibility: | Available in httpd 2.4.65 and later |
++| Compatibility: | Available in httpd 2.4.65 in Fedora Linux |
+This directive sets the policy applied when checking whether the
+<VirtualHost>
+identified by the Host request header in an HTTP request
@@ -334,7 +334,7 @@ index 2fbd076..1bf6ac4 100644
/*
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
-index 33aa1f7..a6af633 100644
+index 33aa1f7..83ae90e 100644
--- a/modules/ssl/ssl_engine_kernel.c
+++ b/modules/ssl/ssl_engine_kernel.c
@@ -101,112 +101,28 @@ static int fill_reneg_buffer(request_rec *r, SSLDirConfigRec *dc)
@@ -371,7 +371,10 @@ index 33aa1f7..a6af633 100644
- }
- return 1;
-}
--
++ /* Policy: strict => fail for any vhost transition. */
++ if (policy == MODSSL_SNIVH_STRICT)
++ return sc1 == sc2;
+
-static int ssl_pk_server_compatible(modssl_pk_server_t *pks1,
- modssl_pk_server_t *pks2)
-{
@@ -395,7 +398,10 @@ index 33aa1f7..a6af633 100644
- }
- return 1;
-}
--
++ /* For authonly/secure policy, compare the hash. */
++ AP_DEBUG_ASSERT(sc1->sni_policy_hash);
++ AP_DEBUG_ASSERT(sc2->sni_policy_hash);
+
-static int ssl_auth_compatible(modssl_auth_ctx_t *a1,
- modssl_auth_ctx_t *a2)
-{
@@ -440,21 +446,16 @@ index 33aa1f7..a6af633 100644
- || (ctx1->protocol != ctx2->protocol)
- || !ssl_auth_compatible(&ctx1->auth, &ctx2->auth)
- || !ssl_pk_server_compatible(ctx1->pks, ctx2->pks)) {
-+ /* Policy: strict => fail for any vhost transition. */
-+ if (policy == MODSSL_SNIVH_STRICT && sc1 != sc2)
- return 0;
+- return 0;
- }
- return 1;
-}
-
+-
-static int ssl_server_compatible(server_rec *s1, server_rec *s2)
-{
- SSLSrvConfigRec *sc1 = s1? mySrvConfig(s1) : NULL;
- SSLSrvConfigRec *sc2 = s2? mySrvConfig(s2) : NULL;
-+ /* For authonly/secure policy, compare the hash. */
-+ AP_DEBUG_ASSERT(sc1->sni_policy_hash);
-+ AP_DEBUG_ASSERT(sc2->sni_policy_hash);
-
+-
- /* both use the same TLS protocol? */
- if (!sc1 || !sc2
- || !ssl_ctx_compatible(sc1->server, sc2->server)) {
diff --git a/httpd.spec b/httpd.spec
index 6d06795..9d762d8 100644
--- a/httpd.spec
+++ b/httpd.spec
@@ -31,7 +31,7 @@
Summary: Apache HTTP Server
Name: httpd
Version: 2.4.65
-Release: 2%{?dist}
+Release: 3%{?dist}
URL: https://httpd.apache.org/
Source0: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2
Source1: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2.asc
@@ -847,6 +847,9 @@ exit $rv
%{_rpmconfigdir}/macros.d/macros.httpd
%changelog
+* Wed Nov 12 2025 Luboš Uhliarik - 2.4.65-3
+- mod_ssl: SSLVHostSNIPolicy - Fix handling of STRICT mode
+
* Tue Nov 04 2025 Luboš Uhliarik - 2.4.65-2
- mod_ssl: Add SSLVHostSNIPolicy directive to set the compatibility level
required for VirtualHost matching.
From f3e631b085b7583155b87f52d5f6b3096d3d4ffd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lubo=C5=A1=20Uhliarik?=
Date: Thu, 27 Nov 2025 16:40:28 +0100
Subject: [PATCH 7/9] Improve default httpd LogFormats for better support
diagnostics
---
httpd.conf | 4 ++--
httpd.spec | 5 ++++-
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/httpd.conf b/httpd.conf
index e49ab6a..2be277d 100644
--- a/httpd.conf
+++ b/httpd.conf
@@ -198,8 +198,8 @@ LogLevel warn
# The following directives define some format nicknames for use with
# a CustomLog directive (see below).
#
- LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
- LogFormat "%h %l %u %t \"%r\" %>s %b" common
+ LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" PID: %P %{tid}P %T" combined
+ LogFormat "%h %l %u %t \"%r\" %>s %b PID: %P %{tid}P %T" common
# You need to enable mod_logio.c to use %I and %O
diff --git a/httpd.spec b/httpd.spec
index 9d762d8..151bac6 100644
--- a/httpd.spec
+++ b/httpd.spec
@@ -31,7 +31,7 @@
Summary: Apache HTTP Server
Name: httpd
Version: 2.4.65
-Release: 3%{?dist}
+Release: 4%{?dist}
URL: https://httpd.apache.org/
Source0: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2
Source1: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2.asc
@@ -847,6 +847,9 @@ exit $rv
%{_rpmconfigdir}/macros.d/macros.httpd
%changelog
+* Thu Nov 27 2025 Luboš Uhliarik - 2.4.65-4
+- Improve default httpd LogFormats for better support diagnostics
+
* Wed Nov 12 2025 Luboš Uhliarik - 2.4.65-3
- mod_ssl: SSLVHostSNIPolicy - Fix handling of STRICT mode
From 0914a96ecc2516806333cb0e8b11cce87eb07110 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lubo=C5=A1=20Uhliarik?=
Date: Mon, 1 Dec 2025 12:58:07 +0100
Subject: [PATCH 8/9] Improve default httpd LogFormats for better support
diagnostics
---
httpd.conf | 12 +++++++-----
httpd.spec | 4 ++--
2 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/httpd.conf b/httpd.conf
index 2be277d..ad5c7ee 100644
--- a/httpd.conf
+++ b/httpd.conf
@@ -198,8 +198,9 @@ LogLevel warn
# The following directives define some format nicknames for use with
# a CustomLog directive (see below).
#
- LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" PID: %P %{tid}P %T" combined
- LogFormat "%h %l %u %t \"%r\" %>s %b PID: %P %{tid}P %T" common
+ LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+ LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" PID: %P %{tid}P %T" combined_ext
+ LogFormat "%h %l %u %t \"%r\" %>s %b" common
# You need to enable mod_logio.c to use %I and %O
@@ -216,10 +217,11 @@ LogLevel warn
#CustomLog "logs/access_log" common
#
- # If you prefer a logfile with access, agent, and referer information
- # (Combined Logfile Format) you can use the following directive.
+ # If you prefer a logfile with access, agent, referer, and process/thread
+ # information (an extended Combined Logfile Format), you can use the
+ # following directive.
#
- CustomLog "logs/access_log" combined
+ CustomLog "logs/access_log" combined_ext
diff --git a/httpd.spec b/httpd.spec
index 151bac6..91c8d2f 100644
--- a/httpd.spec
+++ b/httpd.spec
@@ -31,7 +31,7 @@
Summary: Apache HTTP Server
Name: httpd
Version: 2.4.65
-Release: 4%{?dist}
+Release: 5%{?dist}
URL: https://httpd.apache.org/
Source0: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2
Source1: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2.asc
@@ -847,7 +847,7 @@ exit $rv
%{_rpmconfigdir}/macros.d/macros.httpd
%changelog
-* Thu Nov 27 2025 Luboš Uhliarik - 2.4.65-4
+* Thu Nov 27 2025 Luboš Uhliarik - 2.4.65-5
- Improve default httpd LogFormats for better support diagnostics
* Wed Nov 12 2025 Luboš Uhliarik - 2.4.65-3
From 0c203aeed682395c663f7afef328f754fa629b6a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lubo=C5=A1=20Uhliarik?=
Date: Tue, 9 Dec 2025 12:48:50 +0100
Subject: [PATCH 9/9] new version 2.4.66
---
.gitignore | 1 +
httpd-2.4.65-sslvhostsnipolicy.patch | 554 ---------------------------
httpd.spec | 8 +-
sources | 4 +-
4 files changed, 8 insertions(+), 559 deletions(-)
delete mode 100644 httpd-2.4.65-sslvhostsnipolicy.patch
diff --git a/.gitignore b/.gitignore
index f2fccfd..8df7f18 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,3 +55,4 @@ x86_64
/httpd-2.4.63.tar.bz2.asc
/httpd-2.4.64.tar.bz2.asc
/httpd-2.4.65.tar.bz2.asc
+/httpd-2.4.66.tar.bz2.asc
diff --git a/httpd-2.4.65-sslvhostsnipolicy.patch b/httpd-2.4.65-sslvhostsnipolicy.patch
deleted file mode 100644
index 0831efc..0000000
--- a/httpd-2.4.65-sslvhostsnipolicy.patch
+++ /dev/null
@@ -1,554 +0,0 @@
-From 0263d1e290bc029c5c059fdaa4f21ca9885f9c84 Mon Sep 17 00:00:00 2001
-From: Joe Orton
-Date: Wed, 12 Nov 2025 11:11:41 +0100
-Subject: [PATCH] mod_ssl: Add SSLVHostSNIPolicy directive to set the
- compatibility level required for VirtualHost matching.
-
-For "secure" and "authonly" modes, a hash of the policy-relevant vhost
-configuration is created and stored in the post_config hooks, reducing
-the runtime code complexity (and overhead).
-
-* modules/ssl/ssl_engine_kernel.c (ssl_check_vhost_sni_policy): New
- function, replacing ssl_server_compatible et al.
-
-* modules/ssl/ssl_engine_config.c (ssl_cmd_SSLVHostSNIPolicy): New
- function.
-
-* modules/ssl/ssl_engine_init.c (md5_strarray_cmp, md5_strarray_hash,
- hash_sni_policy_pk, hash_sni_policy_auth, create_sni_policy_hash):
- New functions.
- (ssl_init_Module): Invoke create_sni_policy_hash to store the hash
- for every SSLSrvConfigRec.
-
-* modules/ssl/ssl_private.h (SSLModConfigRec): Add snivh_policy field.
- (SSLSrvConfigRec): Add sni_policy_hash field.
-
-PR: 69743
-GitHub: closes #561
----
- docs/manual/mod/mod_ssl.html.en | 77 ++++++++++++++++++
- modules/ssl/mod_ssl.c | 2 +
- modules/ssl/ssl_engine_config.c | 41 ++++++++++
- modules/ssl/ssl_engine_init.c | 107 +++++++++++++++++++++++++
- modules/ssl/ssl_engine_kernel.c | 133 ++++++--------------------------
- modules/ssl/ssl_private.h | 17 ++++
- 6 files changed, 267 insertions(+), 110 deletions(-)
-
-diff --git a/docs/manual/mod/mod_ssl.html.en b/docs/manual/mod/mod_ssl.html.en
-index e2a4a99..95f0667 100644
---- a/docs/manual/mod/mod_ssl.html.en
-+++ b/docs/manual/mod/mod_ssl.html.en
-@@ -125,6 +125,7 @@ to provide the cryptography engine.
-
SSLUseStapling
-
SSLVerifyClient
-
SSLVerifyDepth
-+
SSLVHostSNIPolicy
-
- Bugfix checklist
See also
-
-@@ -2863,6 +2864,82 @@ known to the server (i.e. the CA's certificate is under
- Example
SSLVerifyDepth 10
-
-
-+
-+
-+
-+
This directive sets the policy applied when checking whether the
-+<VirtualHost>
-+identified by the Host request header in an HTTP request
-+is compatible with the <VirtualHost> identified from the SNI
-+extension sent during the initial TLS connection handshake. If an HTTP
-+request is associated with a virtual host which has an incompatible
-+SSL/TLS configuration under the policy used, an HTTP error response
-+with status code 421 ("Misdirected Request") will be sent.
-+
-+
The policy also applies to TLS connections where an SNI extension
-+is not sent during the handshake, implicitly using the default or
-+first virtual host definition. If the Host header in an HTTP request
-+on such a connection identifies any other non-default virtual host,
-+the compatibility policy is tested.
-+
-+
The strict policy blocks all HTTP requests which are
-+identified with a different virtual host to that identifed by SNI.
-+The insecure policy allows all HTTP requests regardless
-+of virtual host identified; such a configuration may be vulnerable to
-+CVE-2025-23048.
-+
-+
-+
The (default) secure, and authonly
-+policies compare specific aspects of the SSL configuration for the two
-+virtual hosts, which are grouped into two categories:
-+
-+
-+
-+This table illustrates whether an HTTP request will be blocked or
-+allowed when the virtual host configurations differ as described,
-+under each different policy setting:
-+
-+
-+
-+ strict | blocked | blocked | blocked |
-+
-+
-+ secure | allowed | blocked | blocked |
-+
-+
-+ authonly | allowed | blocked | allowed |
-+
-+
-+ insecure | allowed | allowed | allowed |
-+
-+
-+
-+
Example
SSLVHostSNIPolicy authonly
-+
-+
-+
-
-
-
-diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c
-index fb66d18..c0fdafd 100644
---- a/modules/ssl/mod_ssl.c
-+++ b/modules/ssl/mod_ssl.c
-@@ -80,6 +80,8 @@ static const command_rec ssl_config_cmds[] = {
- SSL_CMD_SRV(RandomSeed, TAKE23,
- "SSL Pseudo Random Number Generator (PRNG) seeding source "
- "('startup|connect builtin|file:/path|exec:/path [bytes]')")
-+ SSL_CMD_SRV(VHostSNIPolicy, TAKE1,
-+ "SSL VirtualHost SNI compatibility policy setting")
-
- /*
- * Per-server context configuration directives
-diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c
-index c5dce7f..f856b18 100644
---- a/modules/ssl/ssl_engine_config.c
-+++ b/modules/ssl/ssl_engine_config.c
-@@ -82,6 +82,9 @@ SSLModConfigRec *ssl_config_global_create(server_rec *s)
- #ifdef HAVE_FIPS
- mc->fips = UNSET;
- #endif
-+#ifdef HAVE_TLSEXT
-+ mc->snivh_policy = MODSSL_SNIVH_SECURE;
-+#endif
-
- apr_pool_userdata_set(mc, SSL_MOD_CONFIG_KEY,
- apr_pool_cleanup_null,
-@@ -1918,6 +1921,44 @@ const char *ssl_cmd_SSLStrictSNIVHostCheck(cmd_parms *cmd, void *dcfg, int flag
- #endif
- }
-
-+const char *ssl_cmd_SSLVHostSNIPolicy(cmd_parms *cmd, void *dcfg, const char *arg)
-+{
-+#ifdef HAVE_TLSEXT
-+ SSLModConfigRec *mc = myModConfig(cmd->server);
-+ const char *err;
-+
-+ if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
-+ return err;
-+ }
-+ if (!mc) {
-+ return "SSLVHostSNIPolicy cannot be used inside SSLPolicyDefine";
-+ }
-+
-+ if (strcEQ(arg, "secure")) {
-+ mc->snivh_policy = MODSSL_SNIVH_SECURE;
-+ }
-+ else if (strcEQ(arg, "strict")) {
-+ mc->snivh_policy = MODSSL_SNIVH_STRICT;
-+ }
-+ else if (strcEQ(arg, "insecure")) {
-+ mc->snivh_policy = MODSSL_SNIVH_INSECURE;
-+ }
-+ else if (strcEQ(arg, "authonly")) {
-+ mc->snivh_policy = MODSSL_SNIVH_AUTHONLY;
-+ }
-+ else {
-+ return apr_psprintf(cmd->pool, "Invalid SSLVhostSNIPolicy "
-+ "argument '%s'", arg);
-+ }
-+
-+ return NULL;
-+#else
-+ return "SSLVHostSNIPolicy cannot be used, OpenSSL is not built with "
-+ "support for TLS extensions and SNI indication. Refer to the "
-+ "documentation, and build a compatible version of OpenSSL."
-+#endif
-+}
-+
- #ifdef HAVE_OCSP_STAPLING
-
- const char *ssl_cmd_SSLStaplingCache(cmd_parms *cmd,
-diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
-index 2fbd076..1bf6ac4 100644
---- a/modules/ssl/ssl_engine_init.c
-+++ b/modules/ssl/ssl_engine_init.c
-@@ -30,6 +30,7 @@
-
- #include "mpm_common.h"
- #include "mod_md.h"
-+#include "util_md5.h"
-
- static apr_status_t ssl_init_ca_cert_path(server_rec *, apr_pool_t *, const char *,
- STACK_OF(X509_NAME) *, STACK_OF(X509_INFO) *);
-@@ -186,6 +187,110 @@ static void ssl_add_version_components(apr_pool_t *ptemp, apr_pool_t *pconf,
- modver, AP_SERVER_BASEVERSION, incver);
- }
-
-+#ifdef HAVE_TLSEXT
-+/* Helper functions to create the SNI vhost policy hash. The policy
-+ * hash captures the configuration elements relevant to the mode
-+ * selected at runtime by SSLVHostSNIPolicy. */
-+
-+#define md5_str_update(ctx_, pfx_, str_) do { apr_md5_update(ctx_, pfx_, strlen(pfx_)); apr_md5_update(ctx_, str_, strlen(str_)); } while (0)
-+#define md5_ifstr_update(ctx_, pfx_, str_) do { apr_md5_update(ctx_, pfx_, strlen(pfx_)); if (str_) apr_md5_update(ctx_, str_, strlen(str_)); } while (0)
-+#define md5_fmt_update(ctx_, fmt_, i_) do { char s_[128]; apr_snprintf(s_, sizeof s_, fmt_, i_); \
-+ apr_md5_update(ctx_, s_, strlen(s_)); } while (0)
-+
-+static int md5_strarray_cmp(const void *p1, const void *p2)
-+{
-+ return strcmp(*(char **)p1, *(char **)p2);
-+}
-+
-+/* Hashes an array of strings in sorted order. */
-+static void md5_strarray_hash(apr_pool_t *ptemp, apr_md5_ctx_t *hash,
-+ const char *pfx, apr_array_header_t *s)
-+{
-+ char **elts = apr_pmemdup(ptemp, s->elts, s->nelts * sizeof *elts);
-+ int i;
-+
-+ qsort(elts, s->nelts, sizeof(char *), md5_strarray_cmp);
-+
-+ apr_md5_update(hash, pfx, strlen(pfx));
-+ for (i = 0; i < s->nelts; i++) {
-+ md5_str_update(hash, "elm:", elts[i]);
-+ }
-+}
-+
-+static void hash_sni_policy_pk(apr_pool_t *ptemp, apr_md5_ctx_t *hash, modssl_ctx_t *ctx)
-+{
-+ md5_fmt_update(hash, "protocol:%d", ctx->protocol);
-+
-+ md5_ifstr_update(hash, "ciphers:", ctx->auth.cipher_suite);
-+ md5_ifstr_update(hash, "tls13_ciphers:", ctx->auth.tls13_ciphers);
-+
-+ md5_strarray_hash(ptemp, hash, "cert_files:", ctx->pks->cert_files);
-+ md5_strarray_hash(ptemp, hash, "key_files:", ctx->pks->key_files);
-+}
-+
-+static void hash_sni_policy_auth(apr_md5_ctx_t *hash, modssl_ctx_t *ctx)
-+{
-+ modssl_pk_server_t *pks = ctx->pks;
-+ modssl_auth_ctx_t *a = &ctx->auth;
-+
-+ md5_fmt_update(hash, "verify_depth:%d", a->verify_depth);
-+ md5_fmt_update(hash, "verify_mode:%d", a->verify_mode);
-+
-+ md5_ifstr_update(hash, "ca_name_path:", pks->ca_name_path);
-+ md5_ifstr_update(hash, "ca_name_file:", pks->ca_name_file);
-+ md5_ifstr_update(hash, "ca_cert_path:", a->ca_cert_path);
-+ md5_ifstr_update(hash, "ca_cert_file:", a->ca_cert_file);
-+ md5_ifstr_update(hash, "crl_path:", ctx->crl_path);
-+ md5_ifstr_update(hash, "crl_file:", ctx->crl_file);
-+ md5_fmt_update(hash, "crl_check_mask:%d", ctx->crl_check_mask);
-+ md5_fmt_update(hash, "ocsp_mask:%d", ctx->ocsp_mask);
-+ md5_fmt_update(hash, "ocsp_force_default:%d", ctx->ocsp_force_default);
-+ md5_ifstr_update(hash, "ocsp_responder:", ctx->ocsp_responder);
-+
-+#ifdef HAVE_SRP
-+ md5_ifstr_update(hash, "srp_vfile:", ctx->srp_vfile);
-+#endif
-+
-+#ifdef HAVE_SSL_CONF_CMD
-+ {
-+ apr_array_header_t *parms = ctx->ssl_ctx_param;
-+ int n;
-+
-+ for (n = 0; n < parms->nelts; n++) {
-+ ssl_ctx_param_t *p = &APR_ARRAY_IDX(parms, n, ssl_ctx_param_t);
-+
-+ md5_str_update(hash, "param:", p->name);
-+ md5_str_update(hash, "value:", p->value);
-+ }
-+ }
-+#endif
-+}
-+#endif
-+
-+static char *create_sni_policy_hash(apr_pool_t *p, apr_pool_t *ptemp,
-+ modssl_snivhpolicy_t policy,
-+ SSLSrvConfigRec *sc)
-+{
-+ char *rv = NULL;
-+#ifdef HAVE_TLSEXT
-+ if (policy != MODSSL_SNIVH_STRICT && policy != MODSSL_SNIVH_INSECURE) {
-+ apr_md5_ctx_t hash;
-+ unsigned char digest[APR_MD5_DIGESTSIZE];
-+
-+ /* Create the vhost policy hash for comparison later. */
-+ apr_md5_init(&hash);
-+ hash_sni_policy_auth(&hash, sc->server);
-+ if (policy == MODSSL_SNIVH_SECURE)
-+ hash_sni_policy_pk(ptemp, &hash, sc->server);
-+ apr_md5_final(digest, &hash);
-+
-+ rv = apr_palloc(p, 2 * APR_MD5_DIGESTSIZE + 1);
-+ ap_bin2hex(digest, APR_MD5_DIGESTSIZE, rv); /* sets final '\0' */
-+ }
-+#endif
-+ return rv;
-+}
-+
- /* _________________________________________________________________
- **
- ** Let other answer special connection attempts.
-@@ -439,6 +544,8 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
- return rv;
- }
- }
-+
-+ sc->sni_policy_hash = create_sni_policy_hash(p, ptemp, mc->snivh_policy, sc);
- }
-
- /*
-diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
-index 33aa1f7..83ae90e 100644
---- a/modules/ssl/ssl_engine_kernel.c
-+++ b/modules/ssl/ssl_engine_kernel.c
-@@ -101,112 +101,28 @@ static int fill_reneg_buffer(request_rec *r, SSLDirConfigRec *dc)
- }
-
- #ifdef HAVE_TLSEXT
--static int ap_array_same_str_set(apr_array_header_t *s1, apr_array_header_t *s2)
-+/* Check whether a transition from vhost sc1 to sc2 from SNI to Host:
-+ * vhost selection is permitted according to the SSLVHostSNIPolicy
-+ * setting. Returns 1 if the policy treats the vhosts as compatible,
-+ * else 0. */
-+static int ssl_check_vhost_sni_policy(SSLSrvConfigRec *sc1,
-+ SSLSrvConfigRec *sc2)
- {
-- int i;
-- const char *c;
--
-- if (s1 == s2) {
-+ modssl_snivhpolicy_t policy = sc1->mc->snivh_policy;
-+
-+ /* Policy: insecure => allow everything. */
-+ if (policy == MODSSL_SNIVH_INSECURE)
- return 1;
-- }
-- else if (!s1 || !s2 || (s1->nelts != s2->nelts)) {
-- return 0;
-- }
-
-- for (i = 0; i < s1->nelts; i++) {
-- c = APR_ARRAY_IDX(s1, i, const char *);
-- if (!c || !ap_array_str_contains(s2, c)) {
-- return 0;
-- }
-- }
-- return 1;
--}
-+ /* Policy: strict => fail for any vhost transition. */
-+ if (policy == MODSSL_SNIVH_STRICT)
-+ return sc1 == sc2;
-
--static int ssl_pk_server_compatible(modssl_pk_server_t *pks1,
-- modssl_pk_server_t *pks2)
--{
-- if (!pks1 || !pks2) {
-- return 0;
-- }
-- /* both have the same certificates? */
-- if ((pks1->ca_name_path != pks2->ca_name_path)
-- && (!pks1->ca_name_path || !pks2->ca_name_path
-- || strcmp(pks1->ca_name_path, pks2->ca_name_path))) {
-- return 0;
-- }
-- if ((pks1->ca_name_file != pks2->ca_name_file)
-- && (!pks1->ca_name_file || !pks2->ca_name_file
-- || strcmp(pks1->ca_name_file, pks2->ca_name_file))) {
-- return 0;
-- }
-- if (!ap_array_same_str_set(pks1->cert_files, pks2->cert_files)
-- || !ap_array_same_str_set(pks1->key_files, pks2->key_files)) {
-- return 0;
-- }
-- return 1;
--}
-+ /* For authonly/secure policy, compare the hash. */
-+ AP_DEBUG_ASSERT(sc1->sni_policy_hash);
-+ AP_DEBUG_ASSERT(sc2->sni_policy_hash);
-
--static int ssl_auth_compatible(modssl_auth_ctx_t *a1,
-- modssl_auth_ctx_t *a2)
--{
-- if (!a1 || !a2) {
-- return 0;
-- }
-- /* both have the same verification */
-- if ((a1->verify_depth != a2->verify_depth)
-- || (a1->verify_mode != a2->verify_mode)) {
-- return 0;
-- }
-- /* both have the same ca path/file */
-- if ((a1->ca_cert_path != a2->ca_cert_path)
-- && (!a1->ca_cert_path || !a2->ca_cert_path
-- || strcmp(a1->ca_cert_path, a2->ca_cert_path))) {
-- return 0;
-- }
-- if ((a1->ca_cert_file != a2->ca_cert_file)
-- && (!a1->ca_cert_file || !a2->ca_cert_file
-- || strcmp(a1->ca_cert_file, a2->ca_cert_file))) {
-- return 0;
-- }
-- /* both have the same ca cipher suite string */
-- if ((a1->cipher_suite != a2->cipher_suite)
-- && (!a1->cipher_suite || !a2->cipher_suite
-- || strcmp(a1->cipher_suite, a2->cipher_suite))) {
-- return 0;
-- }
-- /* both have the same ca cipher suite string */
-- if ((a1->tls13_ciphers != a2->tls13_ciphers)
-- && (!a1->tls13_ciphers || !a2->tls13_ciphers
-- || strcmp(a1->tls13_ciphers, a2->tls13_ciphers))) {
-- return 0;
-- }
-- return 1;
--}
--
--static int ssl_ctx_compatible(modssl_ctx_t *ctx1,
-- modssl_ctx_t *ctx2)
--{
-- if (!ctx1 || !ctx2
-- || (ctx1->protocol != ctx2->protocol)
-- || !ssl_auth_compatible(&ctx1->auth, &ctx2->auth)
-- || !ssl_pk_server_compatible(ctx1->pks, ctx2->pks)) {
-- return 0;
-- }
-- return 1;
--}
--
--static int ssl_server_compatible(server_rec *s1, server_rec *s2)
--{
-- SSLSrvConfigRec *sc1 = s1? mySrvConfig(s1) : NULL;
-- SSLSrvConfigRec *sc2 = s2? mySrvConfig(s2) : NULL;
--
-- /* both use the same TLS protocol? */
-- if (!sc1 || !sc2
-- || !ssl_ctx_compatible(sc1->server, sc2->server)) {
-- return 0;
-- }
--
-- return 1;
-+ return strcmp(sc1->sni_policy_hash, sc2->sni_policy_hash) == 0;
- }
- #endif
-
-@@ -275,6 +191,8 @@ int ssl_hook_ReadReq(request_rec *r)
- server_rec *handshakeserver = sslconn->server;
- SSLSrvConfigRec *hssc = mySrvConfig(handshakeserver);
-
-+ AP_DEBUG_ASSERT(hssc);
-+
- if ((servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
- /*
- * The SNI extension supplied a hostname. So don't accept requests
-@@ -315,19 +233,14 @@ int ssl_hook_ReadReq(request_rec *r)
- "which is required to access this server.
\n");
- return HTTP_FORBIDDEN;
- }
-- if (r->server != handshakeserver
-- && !ssl_server_compatible(sslconn->server, r->server)) {
-- /*
-- * The request does not select the virtual host that was
-- * selected for handshaking and its SSL parameters are different
-- */
--
-+ /* Enforce SSL SNI vhost compatibility policy. */
-+ if (!ssl_check_vhost_sni_policy(sc, hssc)) {
- 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",
-+ " via HTTP have no compatible SSL setup for policy '%s'",
- servername ? servername : handshakeserver->server_hostname,
- servername ? "provided via SNI" : "(default host as no SNI was provided)",
-- r->hostname);
-+ r->hostname, MODSSL_SNIVH_NAME(sc->mc->snivh_policy));
- return HTTP_MISDIRECTED_REQUEST;
- }
- }
-diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
-index 2b18189..dbef182 100644
---- a/modules/ssl/ssl_private.h
-+++ b/modules/ssl/ssl_private.h
-@@ -556,6 +556,19 @@ typedef struct {
- int nBytes;
- } ssl_randseed_t;
-
-+/* SNI vhost compatibility policy. */
-+typedef enum {
-+ MODSSL_SNIVH_STRICT = 0,
-+ MODSSL_SNIVH_SECURE = 1,
-+ MODSSL_SNIVH_AUTHONLY = 2,
-+ MODSSL_SNIVH_INSECURE = 3
-+} modssl_snivhpolicy_t;
-+
-+/* Maps modssl_snivhpolicy_t back into a config option string. */
-+#define MODSSL_SNIVH_NAME(p_) ((p_) == MODSSL_SNIVH_STRICT ? "strict" : \
-+ ((p_) == MODSSL_SNIVH_SECURE ? "secure" : \
-+ ((p_) == MODSSL_SNIVH_AUTHONLY ? "authonly" : "insecure" )))
-+
- /**
- * Define the structure of an ASN.1 anything
- */
-@@ -689,6 +702,8 @@ typedef struct {
- #ifdef HAVE_FIPS
- BOOL fips;
- #endif
-+
-+ modssl_snivhpolicy_t snivh_policy;
- } SSLModConfigRec;
-
- /** Structure representing configured filenames for certs and keys for
-@@ -843,6 +858,7 @@ struct SSLSrvConfigRec {
- modssl_ctx_t *server;
- #ifdef HAVE_TLSEXT
- ssl_enabled_t strict_sni_vhost_check;
-+ const char *sni_policy_hash;
- #endif
- #ifndef OPENSSL_NO_COMP
- BOOL compression;
-@@ -918,6 +934,7 @@ const char *ssl_cmd_SSLRequire(cmd_parms *, void *, const char *);
- const char *ssl_cmd_SSLUserName(cmd_parms *, void *, const char *);
- const char *ssl_cmd_SSLRenegBufferSize(cmd_parms *cmd, void *dcfg, const char *arg);
- const char *ssl_cmd_SSLStrictSNIVHostCheck(cmd_parms *cmd, void *dcfg, int flag);
-+const char *ssl_cmd_SSLVHostSNIPolicy(cmd_parms *cmd, void *dcfg, const char *arg);
- const char *ssl_cmd_SSLInsecureRenegotiation(cmd_parms *cmd, void *dcfg, int flag);
-
- const char *ssl_cmd_SSLProxyEngine(cmd_parms *cmd, void *dcfg, int flag);
---
-2.44.0
-
diff --git a/httpd.spec b/httpd.spec
index 91c8d2f..45f21c9 100644
--- a/httpd.spec
+++ b/httpd.spec
@@ -30,8 +30,8 @@
Summary: Apache HTTP Server
Name: httpd
-Version: 2.4.65
-Release: 5%{?dist}
+Version: 2.4.66
+Release: 1%{?dist}
URL: https://httpd.apache.org/
Source0: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2
Source1: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2.asc
@@ -99,7 +99,6 @@ Patch27: httpd-2.4.64-sslprotdefault.patch
Patch28: httpd-2.4.43-logjournal.patch
Patch29: httpd-2.4.63-r1912477+.patch
Patch30: httpd-2.4.64-separate-systemd-fns.patch
-Patch31: httpd-2.4.65-sslvhostsnipolicy.patch
# Bug fixes
# https://bugzilla.redhat.com/show_bug.cgi?id=1397243
@@ -847,6 +846,9 @@ exit $rv
%{_rpmconfigdir}/macros.d/macros.httpd
%changelog
+* Tue Dec 09 2025 Luboš Uhliarik - 2.4.66-1
+- new version 2.4.66
+
* Thu Nov 27 2025 Luboš Uhliarik - 2.4.65-5
- Improve default httpd LogFormats for better support diagnostics
diff --git a/sources b/sources
index 8d4165c..d84ddb9 100644
--- a/sources
+++ b/sources
@@ -1,3 +1,3 @@
-SHA512 (httpd-2.4.65.tar.bz2) = 202f8bfe2aafcfbcd7315191d466e9c10b9a8c0abafb7864510b6e1abe4cb660aaacc2456aa77d43e48ef7a49e591d0b54170d3daf67abc3e06c3da1c63fdffc
-SHA512 (httpd-2.4.65.tar.bz2.asc) = edcf02be97567fb28fef78f757e3355802575782ab452eaea79da70812b20ef4ba49a609e409a9664ec2546720b303deebbd563f3079ce4e77d67b91816210d1
+SHA512 (httpd-2.4.66.tar.bz2) = 49031a3465d956ee3b755e65810b6c35561ddd5fac2c624a273b733c238e115b914cd7b246837e5a3090ccfded6e0b8b3059bfd1f8ce4419081c805a38d05a4b
+SHA512 (httpd-2.4.66.tar.bz2.asc) = 3fc7a4c6c0705adc3f8223ed3d6ebc45f09b7a19ab63a8b4d359835d2b592cf11f0fd0438a40b5a43c0684b36602484bb908bf46b0c068dd22bacc2c194e7fbd
SHA512 (KEYS) = 88c848b7ab9e4915d6625dcad3e8328673b0448f2ce76f2c44eecc612cf6afbce3287a4ee7219a44c6fcc61d5ecb2a1a8545456a4a16b90400263d7249cbf192