]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.11-20251102
authorWietse Z Venema <wietse@porcupine.org>
Sun, 2 Nov 2025 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <ietf-dane@dukhovni.org>
Sun, 2 Nov 2025 23:52:56 +0000 (10:52 +1100)
postfix/HISTORY
postfix/html/postconf.5.html
postfix/man/man5/postconf.5
postfix/proto/postconf.proto
postfix/src/global/mail_params.h
postfix/src/global/mail_version.h
postfix/src/smtp/smtp_tls_policy.c
postfix/src/smtp/smtp_tls_policy_test.c

index e9017bb139f475a7a1dabbabd46d0b9e6432f3c8..eba515c894fa957624d56f5d070c673a190b7a36 100644 (file)
@@ -29765,3 +29765,23 @@ Apologies for any names omitted.
        Debugging: depending on OpenSSL build options, "posttls-finger
        -L ssl-debug" will decode TLS handshake messages. Viktor
        Dukhovni. File: posttls-finger/posttls-finger.c
+
+20241031
+
+       Bugfix (defect introduced: Postfix 3.10, date 20250117):
+       support for "TLS-Required: no" broke client-side TLS wrappermode
+       support, by downgrading a connection to TLS security level 'may'.
+       The solution is to change the downgrade level for wrappermode
+       connections to 'encrypt'. Rationale: by design, TLS can be
+       optional only for connections that use STARTTLS. The downgrade
+       to unauthenticated 'encrypt' allows a sender to avoid an email
+       delivery problem. Problem reported by Joshua Tyler Cochran.
+       Files: smtp/smtp_tls_policy.c, smtp/smtp_tls_policy_test.c.
+
+20251102
+
+       Post-quantum cryptography support (with OpenSSL 3.5 and
+       later): change the tls_eecdh_auto_curves default value to
+       avoid problems with infrastructure that mis-handles TLS
+       hello messages larger than one (Ethernet) TCP segment.
+       Viktor Dukhovni. Files: global/mail_params.h, proto/postconf.proto.
index 359e046b6b38f6677560cf7759dc7bce8e3705ad..de47f73e7726c0b6092813d96a092d8cd0657793 100644 (file)
@@ -20255,8 +20255,9 @@ MinProtocol = TLSv1
 <a href="postconf.5.html">main.cf</a>:
     <a href="postconf.5.html#tls_config_file">tls_config_file</a> = ${<a href="postconf.5.html#config_directory">config_directory</a>}/openssl.cnf
     <a href="postconf.5.html#tls_config_name">tls_config_name</a> = postfix
-    # Clear Postfix curve/group settings to let OpenSSL settings take
-    # effect.
+    # Clear Postfix curve/group settings to let custom OpenSSL
+    # configuration settings take effect.  For most users, the
+    # default Postfix settings are strongly recommended.
     <a href="postconf.5.html#tls_eecdh_auto_curves">tls_eecdh_auto_curves</a> =
     <a href="postconf.5.html#tls_ffdhe_auto_groups">tls_ffdhe_auto_groups</a> =
 </pre>
@@ -20283,14 +20284,14 @@ openssl.cnf:
     #
     # Groups = X25519:X448:prime256v1:secp384r1:secp521r1:ffdhe2048:ffdhe3072
     #
-    Groups = *X25519MLKEM768 / *X25519:X448 / P-256:P-384
+    Groups = ?X25519MLKEM768 / ?*X25519:?secp256r1 / ?X448:?secp384r1:?secp521r1 / ?ffdhe2048:?ffdhe3072
 </pre>
 
-<p> Caution: It is typically best to just use the default OpenSSL
-group settings, by setting "<a href="postconf.5.html#tls_config_file">tls_config_file</a> = none". Overly strict
-system-wide TLS settings will conflict with Postfix's opportunistic
-TLS, where being less restrictive is better than downgrading to
-cleartext SMTP. </p>
+<p> Caution: It is typically best to just use the compiled-in default
+OpenSSL group settings, by setting "<a href="postconf.5.html#tls_config_file">tls_config_file</a> = none". Overly
+strict system-wide TLS settings will conflict with Postfix's
+opportunistic TLS, where being less restrictive is better than
+downgrading to cleartext SMTP. </p>
 
 <p> This feature is available in Postfix &ge; 3.9, 3.8.1, 3.7.6,
 3.6.10, and 3.5.20. </p>
@@ -20509,14 +20510,20 @@ is introduced with Postfix 3.8, when built against OpenSSL 3.0 or later.
 </p>
 
 <p> Post-quantum cryptography support: OpenSSL 3.5 introduces new
-configuration syntax that Postfix will not attempt to imitate.
-Instead, with Postfix 3.6.17, 3.7.13, 3.8.8, 3.9.2, and later, set
-both <a href="postconf.5.html#tls_eecdh_auto_curves">tls_eecdh_auto_curves</a> and if available <a href="postconf.5.html#tls_ffdhe_auto_groups">tls_ffdhe_auto_groups</a>
-to the empty value, to enable algorithm selection through OpenSSL
-configuration.  The empty value is the default setting for both as
-of Postfix 3.11, when compiled with OpenSSL 3.5 or later.  See
-<a href="postconf.5.html#tls_config_file">tls_config_file</a> for a configuration example.
-</p>
+configuration syntax that Postfix will not attempt to emulate.  That
+said, when compiled against OpenSSL 3.5 or later, the Postfix default
+setting is a minor adjustment of the OpenSSL compiled-in default
+setting, it just delays generation of the hybrid post-quantum
+<b>X25519MLKEM768</b> key-share until it is explicitly requested by the
+server.  This avoids interoperability issues with some SMTP servers that
+are unable to handle the resulting large TLS Client Hello. </p>
+
+<p> If, despite the strongly recommended defaults, you need fine-grained
+control over the supported groups, with Postfix 3.6.17, 3.7.13, 3.8.8,
+3.9.2, and later, set both <a href="postconf.5.html#tls_eecdh_auto_curves">tls_eecdh_auto_curves</a> and if available
+<a href="postconf.5.html#tls_ffdhe_auto_groups">tls_ffdhe_auto_groups</a> to the empty value, to enable algorithm selection
+through OpenSSL configuration.  See <a href="postconf.5.html#tls_config_file">tls_config_file</a> for a configuration
+example.  </p>
 
 <p> This feature is available in Postfix 3.2 and later, when it is
 compiled and linked with OpenSSL 1.0.2 or later on platforms where
@@ -20659,28 +20666,24 @@ are largely a backup, in case some peer does not support EC key
 exchange, or EC key exchange needs to be disabled for some pressing
 reason. </p>
 
-<p> Setting this parameter empty disables FFDHE support in TLS 1.3.
+<p> Setting this parameter empty disables FFDHE support in TLS 1.3,
+unless FFDHE groups are included in the "<a href="postconf.5.html#tls_eecdh_auto_curves">tls_eecdh_auto_curves</a>" setting,
+perhaps indirectly, as with the "DEFAULT" keyword available with OpenSSL
+3.5 or later.  In that case, prefixing each group name with a "-" has
+the effect of removing it from the list.
 Whether FFDHE key agreement is enabled in TLS 1.2 and earlier depends
 on whether any of the "kDHE" ciphers are included in the cipherlist.
 </p>
 
 <p> Conversely, setting "<a href="postconf.5.html#tls_eecdh_auto_curves">tls_eecdh_auto_curves</a>" empty disables TLS 1.3
 EC key agreement in OpenSSL 3.0 and later. If both are set empty,
-Postfix will fall back to OpenSSL preferences as described next. </p>
+Postfix will fall back to OpenSSL preferences as described in the
+documentation of "<a href="postconf.5.html#tls_eecdh_auto_curves">tls_eecdh_auto_curves</a>".
 
-<p> Post-quantum cryptography support: OpenSSL 3.5 introduces new
-configuration syntax that Postfix will not attempt to imitate.
-Instead, with Postfix 3.6.17, 3.7.13, 3.8.8, 3.9.2, and later, set
-both <a href="postconf.5.html#tls_eecdh_auto_curves">tls_eecdh_auto_curves</a> and <a href="postconf.5.html#tls_ffdhe_auto_groups">tls_ffdhe_auto_groups</a> to the empty
-value, to enable algorithm selection through OpenSSL configuration.
-The empty value is the default setting for both as of Postfix 3.11,
-when compiled with OpenSSL 3.5 or later.  See <a href="postconf.5.html#tls_config_file">tls_config_file</a> for a
-configuration example. </p>
-
-<p> All the default groups and EC curves should be sufficiently strong to make
-"pruning" the defaults unwise.  At a minimum, "x25519" and "prime256v1" (the
-OpenSSL name for "secp256r1", a.k.a. "P-256") should be among the enabled EC
-curves, while "dhe2048" and "dhe3072" should be among the FFDHE groups. </p>
+<p> The default list includes "ffdhe2048" and "ffdhe3072".  While
+it should not be necessary in most cases, you can add "ffdhe4096"
+to the list if you run into an exotic server that does not support
+ECDHE and insists on much stronger than sensible DHE parameters.  </p>
 
 <p> This feature is available in Postfix 3.8 and later, when it is
 compiled and linked with OpenSSL 3.0 or later. </p>
index 87d39ab8ea15dd290a474f2e2d62c5aade573952..819d18ae49acd4b55691d4771d8e326ab0e982c1 100644 (file)
@@ -14105,8 +14105,9 @@ Example: Custom OpenSSL group settings.
 main.cf:
     tls_config_file = ${config_directory}/openssl.cnf
     tls_config_name = postfix
-    # Clear Postfix curve/group settings to let OpenSSL settings take
-    # effect.
+    # Clear Postfix curve/group settings to let custom OpenSSL
+    # configuration settings take effect.  For most users, the
+    # default Postfix settings are strongly recommended.
     tls_eecdh_auto_curves =
     tls_ffdhe_auto_groups =
 .fi
@@ -14141,15 +14142,15 @@ openssl.cnf:
     #
     # Groups = X25519:X448:prime256v1:secp384r1:secp521r1:ffdhe2048:ffdhe3072
     #
-    Groups = *X25519MLKEM768 / *X25519:X448 / P\-256:P\-384
+    Groups = ?X25519MLKEM768 / ?*X25519:?secp256r1 / ?X448:?secp384r1:?secp521r1 / ?ffdhe2048:?ffdhe3072
 .fi
 .ad
 .PP
-Caution: It is typically best to just use the default OpenSSL
-group settings, by setting "tls_config_file = none". Overly strict
-system\-wide TLS settings will conflict with Postfix's opportunistic
-TLS, where being less restrictive is better than downgrading to
-cleartext SMTP.
+Caution: It is typically best to just use the compiled\-in default
+OpenSSL group settings, by setting "tls_config_file = none". Overly
+strict system\-wide TLS settings will conflict with Postfix's
+opportunistic TLS, where being less restrictive is better than
+downgrading to cleartext SMTP.
 .PP
 This feature is available in Postfix >= 3.9, 3.8.1, 3.7.6,
 3.6.10, and 3.5.20.
@@ -14336,13 +14337,20 @@ customizing the list of FFDHE groups enabled with TLS 1.3.  That setting
 is introduced with Postfix 3.8, when built against OpenSSL 3.0 or later.
 .PP
 Post\-quantum cryptography support: OpenSSL 3.5 introduces new
-configuration syntax that Postfix will not attempt to imitate.
-Instead, with Postfix 3.6.17, 3.7.13, 3.8.8, 3.9.2, and later, set
-both tls_eecdh_auto_curves and if available tls_ffdhe_auto_groups
-to the empty value, to enable algorithm selection through OpenSSL
-configuration.  The empty value is the default setting for both as
-of Postfix 3.11, when compiled with OpenSSL 3.5 or later.  See
-tls_config_file for a configuration example.
+configuration syntax that Postfix will not attempt to emulate.  That
+said, when compiled against OpenSSL 3.5 or later, the Postfix default
+setting is a minor adjustment of the OpenSSL compiled\-in default
+setting, it just delays generation of the hybrid post\-quantum
+\fBX25519MLKEM768\fR key\-share until it is explicitly requested by the
+server.  This avoids interoperability issues with some SMTP servers that
+are unable to handle the resulting large TLS Client Hello.
+.PP
+If, despite the strongly recommended defaults, you need fine\-grained
+control over the supported groups, with Postfix 3.6.17, 3.7.13, 3.8.8,
+3.9.2, and later, set both tls_eecdh_auto_curves and if available
+tls_ffdhe_auto_groups to the empty value, to enable algorithm selection
+through OpenSSL configuration.  See tls_config_file for a configuration
+example.
 .PP
 This feature is available in Postfix 3.2 and later, when it is
 compiled and linked with OpenSSL 1.0.2 or later on platforms where
@@ -14449,27 +14457,23 @@ are largely a backup, in case some peer does not support EC key
 exchange, or EC key exchange needs to be disabled for some pressing
 reason.
 .PP
-Setting this parameter empty disables FFDHE support in TLS 1.3.
+Setting this parameter empty disables FFDHE support in TLS 1.3,
+unless FFDHE groups are included in the "tls_eecdh_auto_curves" setting,
+perhaps indirectly, as with the "DEFAULT" keyword available with OpenSSL
+3.5 or later.  In that case, prefixing each group name with a "\-" has
+the effect of removing it from the list.
 Whether FFDHE key agreement is enabled in TLS 1.2 and earlier depends
 on whether any of the "kDHE" ciphers are included in the cipherlist.
 .PP
 Conversely, setting "tls_eecdh_auto_curves" empty disables TLS 1.3
 EC key agreement in OpenSSL 3.0 and later. If both are set empty,
-Postfix will fall back to OpenSSL preferences as described next.
+Postfix will fall back to OpenSSL preferences as described in the
+documentation of "tls_eecdh_auto_curves".
 .PP
-Post\-quantum cryptography support: OpenSSL 3.5 introduces new
-configuration syntax that Postfix will not attempt to imitate.
-Instead, with Postfix 3.6.17, 3.7.13, 3.8.8, 3.9.2, and later, set
-both tls_eecdh_auto_curves and tls_ffdhe_auto_groups to the empty
-value, to enable algorithm selection through OpenSSL configuration.
-The empty value is the default setting for both as of Postfix 3.11,
-when compiled with OpenSSL 3.5 or later.  See tls_config_file for a
-configuration example.
-.PP
-All the default groups and EC curves should be sufficiently strong to make
-"pruning" the defaults unwise.  At a minimum, "x25519" and "prime256v1" (the
-OpenSSL name for "secp256r1", a.k.a. "P\-256") should be among the enabled EC
-curves, while "dhe2048" and "dhe3072" should be among the FFDHE groups.
+The default list includes "ffdhe2048" and "ffdhe3072".  While
+it should not be necessary in most cases, you can add "ffdhe4096"
+to the list if you run into an exotic server that does not support
+ECDHE and insists on much stronger than sensible DHE parameters.
 .PP
 This feature is available in Postfix 3.8 and later, when it is
 compiled and linked with OpenSSL 3.0 or later.
index 5f94cb366cb4ecfd2b4f48b00762f7a894152fd2..33349122c83b340bdac2c86c83ae2c2577ed8606 100644 (file)
@@ -13439,14 +13439,20 @@ is introduced with Postfix 3.8, when built against OpenSSL 3.0 or later.
 </p>
 
 <p> Post-quantum cryptography support: OpenSSL 3.5 introduces new
-configuration syntax that Postfix will not attempt to imitate.
-Instead, with Postfix 3.6.17, 3.7.13, 3.8.8, 3.9.2, and later, set
-both tls_eecdh_auto_curves and if available tls_ffdhe_auto_groups
-to the empty value, to enable algorithm selection through OpenSSL
-configuration.  The empty value is the default setting for both as
-of Postfix 3.11, when compiled with OpenSSL 3.5 or later.  See
-tls_config_file for a configuration example.
-</p>
+configuration syntax that Postfix will not attempt to emulate.  That
+said, when compiled against OpenSSL 3.5 or later, the Postfix default
+setting is a minor adjustment of the OpenSSL compiled-in default
+setting, it just delays generation of the hybrid post-quantum
+<b>X25519MLKEM768</b> key-share until it is explicitly requested by the
+server.  This avoids interoperability issues with some SMTP servers that
+are unable to handle the resulting large TLS Client Hello. </p>
+
+<p> If, despite the strongly recommended defaults, you need fine-grained
+control over the supported groups, with Postfix 3.6.17, 3.7.13, 3.8.8,
+3.9.2, and later, set both tls_eecdh_auto_curves and if available
+tls_ffdhe_auto_groups to the empty value, to enable algorithm selection
+through OpenSSL configuration.  See tls_config_file for a configuration
+example.  </p>
 
 <p> This feature is available in Postfix 3.2 and later, when it is
 compiled and linked with OpenSSL 1.0.2 or later on platforms where
@@ -13472,28 +13478,24 @@ are largely a backup, in case some peer does not support EC key
 exchange, or EC key exchange needs to be disabled for some pressing
 reason. </p>
 
-<p> Setting this parameter empty disables FFDHE support in TLS 1.3.
+<p> Setting this parameter empty disables FFDHE support in TLS 1.3,
+unless FFDHE groups are included in the "tls_eecdh_auto_curves" setting,
+perhaps indirectly, as with the "DEFAULT" keyword available with OpenSSL
+3.5 or later.  In that case, prefixing each group name with a "-" has
+the effect of removing it from the list.
 Whether FFDHE key agreement is enabled in TLS 1.2 and earlier depends
 on whether any of the "kDHE" ciphers are included in the cipherlist.
 </p>
 
 <p> Conversely, setting "tls_eecdh_auto_curves" empty disables TLS 1.3
 EC key agreement in OpenSSL 3.0 and later. If both are set empty,
-Postfix will fall back to OpenSSL preferences as described next. </p>
+Postfix will fall back to OpenSSL preferences as described in the
+documentation of "tls_eecdh_auto_curves".
 
-<p> Post-quantum cryptography support: OpenSSL 3.5 introduces new
-configuration syntax that Postfix will not attempt to imitate.
-Instead, with Postfix 3.6.17, 3.7.13, 3.8.8, 3.9.2, and later, set
-both tls_eecdh_auto_curves and tls_ffdhe_auto_groups to the empty
-value, to enable algorithm selection through OpenSSL configuration.
-The empty value is the default setting for both as of Postfix 3.11,
-when compiled with OpenSSL 3.5 or later.  See tls_config_file for a
-configuration example. </p>
-
-<p> All the default groups and EC curves should be sufficiently strong to make
-"pruning" the defaults unwise.  At a minimum, "x25519" and "prime256v1" (the
-OpenSSL name for "secp256r1", a.k.a. "P-256") should be among the enabled EC
-curves, while "dhe2048" and "dhe3072" should be among the FFDHE groups. </p>
+<p> The default list includes "ffdhe2048" and "ffdhe3072".  While
+it should not be necessary in most cases, you can add "ffdhe4096"
+to the list if you run into an exotic server that does not support
+ECDHE and insists on much stronger than sensible DHE parameters.  </p>
 
 <p> This feature is available in Postfix 3.8 and later, when it is
 compiled and linked with OpenSSL 3.0 or later. </p>
@@ -19295,8 +19297,9 @@ MinProtocol = TLSv1
 main.cf:
     tls_config_file = ${config_directory}/openssl.cnf
     tls_config_name = postfix
-    # Clear Postfix curve/group settings to let OpenSSL settings take
-    # effect. 
+    # Clear Postfix curve/group settings to let custom OpenSSL
+    # configuration settings take effect.  For most users, the
+    # default Postfix settings are strongly recommended.
     tls_eecdh_auto_curves =
     tls_ffdhe_auto_groups =
 </pre>
@@ -19323,14 +19326,14 @@ openssl.cnf:
     #
     # Groups = X25519:X448:prime256v1:secp384r1:secp521r1:ffdhe2048:ffdhe3072
     #
-    Groups = *X25519MLKEM768 / *X25519:X448 / P-256:P-384
+    Groups = ?X25519MLKEM768 / ?*X25519:?secp256r1 / ?X448:?secp384r1:?secp521r1 / ?ffdhe2048:?ffdhe3072
 </pre>
 
-<p> Caution: It is typically best to just use the default OpenSSL
-group settings, by setting "tls_config_file = none". Overly strict
-system-wide TLS settings will conflict with Postfix's opportunistic
-TLS, where being less restrictive is better than downgrading to
-cleartext SMTP. </p>
+<p> Caution: It is typically best to just use the compiled-in default
+OpenSSL group settings, by setting "tls_config_file = none". Overly
+strict system-wide TLS settings will conflict with Postfix's
+opportunistic TLS, where being less restrictive is better than
+downgrading to cleartext SMTP. </p>
 
 <p> This feature is available in Postfix &ge; 3.9, 3.8.1, 3.7.6,
 3.6.10, and 3.5.20. </p>
index de23c963702ee3f1683deac49ab0848e5c726d90..7583c8b556619a3c52b6317a0c883740c22a7382 100644 (file)
@@ -3421,7 +3421,7 @@ extern char *var_tls_null_clist;
 
 #define VAR_TLS_EECDH_AUTO     "tls_eecdh_auto_curves"
 #if OPENSSL_VERSION_PREREQ(3,5)
-#define DEF_TLS_EECDH_AUTO      ""
+#define DEF_TLS_EECDH_AUTO      "?X25519MLKEM768:DEFAULT"
 #else
 #if defined(SN_X25519) && defined(NID_X25519)
 #define DEF_TLS_EECDH_AUTO_1 SN_X25519 " "
index ec7d136fac38f24c45d140b219762cf5fde455ca..19e1a0cd0e10075f707468bc3ac9ef58e466a7a4 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20251030"
+#define MAIL_RELEASE_DATE      "20251102"
 #define MAIL_VERSION_NUMBER    "3.11"
 
 #ifdef SNAPSHOT
index 028f48c3239b2197f42d4439cd9c3411e4075b52..b234dd8fa5a9949eaa512135b56053ec448a5158 100644 (file)
@@ -191,12 +191,12 @@ int     smtp_tls_authorize_mx_hostname(SMTP_TLS_POLICY *tls, const char *name)
            if (match_sts_mx_host_pattern(*pattp, aname)) {
                if (msg_verbose)
                    msg_info("MX name '%s' matches STS MX pattern for '%s'",
-                   aname, tls->ext_policy_domain ? tls->ext_policy_domain : "");
+                            aname, tls->ext_policy_domain ? tls->ext_policy_domain : "");
                return (1);
            }
        }
        msg_warn("MX name '%s' does not match STS MX pattern for '%s'",
-                aname, tls->ext_policy_domain ? tls->ext_policy_domain : "");
+              aname, tls->ext_policy_domain ? tls->ext_policy_domain : "");
        return (0);
     }
     /* No applicable policy name patterns. */
@@ -732,8 +732,13 @@ static void *policy_create(const char *unused_key, void *context)
     if (STATE_TLS_NOT_REQUIRED(iter->parent)) {
        if (msg_verbose)
            msg_info("%s: no tls policy lookup", __func__);
-       if (tls->level > TLS_LEV_MAY)
-           tls->level = TLS_LEV_MAY;
+       if (var_smtp_tls_wrappermode) {
+           if (tls->level > TLS_LEV_ENCRYPT)
+               tls->level = TLS_LEV_ENCRYPT;
+       } else {
+           if (tls->level > TLS_LEV_MAY)
+               tls->level = TLS_LEV_MAY;
+       }
     } else if (tls_policy) {
        tls_policy_lookup(tls, &site_level, dest, "next-hop destination");
     } else if (tls_per_site) {
index f37ac9875544154822f3ef2149867596fa752583..dd9ac7b4e2846622c3c495c88f36afff3cca22cd 100644 (file)
@@ -84,6 +84,7 @@ char   *var_smtp_tls_vfy_cmatch;
 bool    var_smtp_use_tls;
 char   *var_smtp_tls_excl_ciph;
 bool    var_smtp_tls_enf_sts_mx_pat;
+bool    var_smtp_tls_wrappermode;
 
  /*
   * Other globals.
@@ -125,6 +126,8 @@ static void test_setup(void)
     var_smtp_use_tls = DEF_SMTP_USE_TLS;
     var_smtp_tls_excl_ciph = DEF_SMTP_TLS_EXCL_CIPH;
     var_smtp_tls_enf_sts_mx_pat = 1;
+    var_smtp_tls_wrappermode = 0;
+    var_tls_required_enable = 0;
 
     smtp_mode = 1;
 
@@ -462,10 +465,121 @@ static int test_hostname_authorization(const struct TEST_CASE *tp)
     return (match ? PASS : FAIL);
 }
 
+static int test_tls_reqd_no_sans_header(const struct TEST_CASE *tp)
+{
+    SMTP_STATE *state = smtp_state_alloc();
+    const char *domain = "example.com";
+    const char *host = "mail.example.com";
+    const char *addr = "10.0.1.1";
+    int     port = 25;
+    int     want_level;
+    int     ret = FAIL;
+
+    var_smtp_tls_level = "secure";
+    var_smtp_tls_policy = "static:none";
+
+    /* Test-dependent. */
+    state->request = &(DELIVER_REQUEST) {.sendopts = 0};
+    var_smtp_tls_wrappermode = 1;
+    var_tls_required_enable = 1;
+    want_level = TLS_LEV_NONE;
+
+    smtp_tls_list_init();
+    SMTP_ITER_INIT(state->iterator, domain, host, addr, port, state);
+    if (smtp_tls_policy_cache_query(state->why, state->tls,
+                                   state->iterator) == 0) {
+       msg_warn("smtp_tls_policy_cache_query failed: %s",
+                STR(state->why->reason));
+    } else if (state->tls->level != want_level) {
+       msg_warn("got TLS level '%s', want '%s'",
+              str_tls_level(state->tls->level), str_tls_level(want_level));
+    } else {
+       ret = PASS;
+    }
+    smtp_tls_policy_cache_flush();
+    smtp_state_free(state);
+    return (ret);
+}
+
+static int test_tls_reqd_no_with_wrappermode(const struct TEST_CASE *tp)
+{
+    SMTP_STATE *state = smtp_state_alloc();
+    const char *domain = "example.com";
+    const char *host = "mail.example.com";
+    const char *addr = "10.0.1.1";
+    int     port = 25;
+    int     want_level;
+    int     ret = FAIL;
+
+    var_smtp_tls_level = "secure";
+    var_smtp_tls_policy = "static:none";
+
+    /* Test-dependent. */
+    state->request = &(DELIVER_REQUEST) {.sendopts = SOPT_REQUIRETLS_HEADER};
+    var_smtp_tls_wrappermode = 1;
+    var_tls_required_enable = 1;
+    want_level = TLS_LEV_ENCRYPT;
+
+    smtp_tls_list_init();
+    SMTP_ITER_INIT(state->iterator, domain, host, addr, port, state);
+    if (smtp_tls_policy_cache_query(state->why, state->tls,
+                                   state->iterator) == 0) {
+       msg_warn("smtp_tls_policy_cache_query failed: %s",
+                STR(state->why->reason));
+    } else if (state->tls->level != want_level) {
+       msg_warn("got TLS level '%s', want '%s'",
+              str_tls_level(state->tls->level), str_tls_level(want_level));
+    } else {
+       ret = PASS;
+    }
+    smtp_tls_policy_cache_flush();
+    smtp_state_free(state);
+    return (ret);
+}
+
+static int test_tls_reqd_no_sans_wrappermode(const struct TEST_CASE *tp)
+{
+    SMTP_STATE *state = smtp_state_alloc();
+    const char *domain = "example.com";
+    const char *host = "mail.example.com";
+    const char *addr = "10.0.1.1";
+    int     port = 25;
+    int     want_level;
+    int     ret = FAIL;
+
+    var_smtp_tls_level = "secure";
+    var_smtp_tls_policy = "static:none";
+
+    /* Test-dependent. */
+    state->request = &(DELIVER_REQUEST) {.sendopts = SOPT_REQUIRETLS_HEADER};
+    var_smtp_tls_wrappermode = 0;
+    var_tls_required_enable = 1;
+    want_level = TLS_LEV_MAY;
+
+    smtp_tls_list_init();
+    SMTP_ITER_INIT(state->iterator, domain, host, addr, port, state);
+    if (smtp_tls_policy_cache_query(state->why, state->tls,
+                                   state->iterator) == 0) {
+       msg_warn("smtp_tls_policy_cache_query failed: %s",
+                STR(state->why->reason));
+    } else if (state->tls->level != want_level) {
+       msg_warn("got TLS level '%s', want '%s'",
+              str_tls_level(state->tls->level), str_tls_level(want_level));
+    } else {
+       ret = PASS;
+    }
+    smtp_tls_policy_cache_flush();
+    smtp_state_free(state);
+    return (ret);
+}
+
 static const struct TEST_CASE test_cases[] = {
     {"sts_policy_smoke_test", sts_policy_smoke_test,},
     {"obs_sts_policy_smoke_test", obs_sts_policy_smoke_test,},
     {"test_hostname_authorization", test_hostname_authorization},
+    {"test_tls_reqd_no_sans_header", test_tls_reqd_no_sans_header},
+    {"test_tls_reqd_no_with_wrappermode", test_tls_reqd_no_with_wrappermode},
+    {"test_tls_reqd_no_sans_wrappermode", test_tls_reqd_no_sans_wrappermode},
     {0},
 };