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.

+
  • 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
      +
      + ++ ++
      top
      ++

      SSLVHostSNIPolicy Directive

      ++ ++ ++ ++ ++ ++ ++ ++ ++
      Description:Set compatibility policy for SNI client access to virtual hosts.
      Syntax:SSLVHostSNIPolicy strict|secure|authonly|insecure
      Default:SSLVHostSNIPolicy secure
      Context:server config
      Status:Extension
      Module:mod_ssl
      Compatibility:Available in httpd 2.4.65 and later

      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: ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
      Policy modeAny VirtualHost mismatchServer certificate/key,
      or protocol/cipher restrictions
      Client verification/
      authentication settings
      strictblockedblockedblocked
      secureallowedblockedblocked
      authonlyallowedblockedallowed
      insecureallowedallowedallowed
      ++

      ++

      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
      -
      - -+ -+
      top
      -+

      SSLVHostSNIPolicy Directive

      -+ -+ -+ -+ -+ -+ -+ -+ -+
      Description:Set compatibility policy for SNI client access to virtual hosts.
      Syntax:SSLVHostSNIPolicy strict|secure|authonly|insecure
      Default:SSLVHostSNIPolicy secure
      Context:server config
      Status:Extension
      Module:mod_ssl
      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 -+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: -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+
      Policy modeAny VirtualHost mismatchServer certificate/key,
      or protocol/cipher restrictions
      Client verification/
      authentication settings
      strictblockedblockedblocked
      secureallowedblockedblocked
      authonlyallowedblockedallowed
      insecureallowedallowedallowed
      -+

      -+

      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