On Thu, Jun 19, 2025 at 09:53:38PM +1000, Viktor Dukhovni via Postfix-users 
wrote:

> However, there's a problematic interaction with DANE TLSA records.
> Patch below.

I should not have trimmed the patch context so radically, better patch
below, in case your sources are slightly older or newer.  The patch
merge base is 3.11-20250606.

-- 
    Viktor.

--- a/src/smtp/smtp.h
+++ b/src/smtp/smtp.h
@@ -57,10 +57,11 @@ typedef struct SMTP_ITERATOR {
     VSTRING *request_nexthop;          /* delivery request nexhop or empty */
     VSTRING *dest;                     /* current nexthop */
     VSTRING *host;                     /* hostname or empty */
     VSTRING *addr;                     /* printable address or empty */
     unsigned port;                     /* network byte order or null */
+    int     tlsreqno;                  /* "TLS-Required: no" */
     struct DNS_RR *rr;                 /* DNS resource record or null */
     struct DNS_RR *mx;                 /* DNS resource record or null */
     /* Private members. */
     VSTRING *saved_dest;               /* saved current nexthop */
     struct SMTP_STATE *parent;         /* parent linkage */
@@ -69,10 +70,11 @@ typedef struct SMTP_ITERATOR {
 #define SMTP_ITER_INIT(iter, _dest, _host, _addr, _port, state) do { \
        vstring_strcpy((iter)->dest, (_dest)); \
        vstring_strcpy((iter)->host, (_host)); \
        vstring_strcpy((iter)->addr, (_addr)); \
        (iter)->port = (_port); \
+       (iter)->tlsreqno = 0; \
        (iter)->mx = (iter)->rr = 0; \
        vstring_strcpy((iter)->saved_dest, ""); \
        (iter)->parent = (state); \
     } while (0)
 
--- a/src/smtp/smtp_connect.c
+++ b/src/smtp/smtp_connect.c
@@ -505,10 +505,23 @@ static void smtp_cache_policy(SMTP_STATE *state, const 
char *dest)
 static int smtp_get_effective_tls_level(DSN_BUF *why, SMTP_STATE *state)
 {
     SMTP_ITERATOR *iter = state->iterator;
     SMTP_TLS_POLICY *tls = state->tls;
 
+    /*
+     * If the message contains a "TLS-Required: no" header, update the iterator
+     * to cap the policy at TLS_LEV_MAY.
+     *
+     * We must do this early to avoid possible failure if TLSA record lookups
+     * fail, of if TLSA records are found, but can't be activated because the
+     * security level has been reset to "may".
+     */
+    if (var_tls_required_enable
+            && (state->request->sendopts & SOPT_REQUIRETLS_HEADER)) {
+       iter->tlsreqno = 1;
+    }
+
     /*
      * Determine the TLS level for this destination.
      */
     if (!smtp_tls_policy_cache_query(why, tls, iter)) {
        return (0);
@@ -527,20 +540,10 @@ static int smtp_get_effective_tls_level(DSN_BUF *why, 
SMTP_STATE *state)
            return (0);
        }
     }
 #endif
 
-    /*
-     * Otherwise, if the TLS level is not TLS_LEV_NONE or some non-level, and
-     * the message contains a "TLS-Required: no" header, limit the level to
-     * TLS_LEV_MAY.
-     */
-    else if (var_tls_required_enable && tls->level > TLS_LEV_NONE
-            && (state->request->sendopts & SOPT_REQUIRETLS_HEADER)) {
-       tls->level = TLS_LEV_MAY;
-    }
-
     /*
      * Success.
      */
     return (1);
 }
--- a/src/smtp/smtp_tls_policy.c
+++ b/src/smtp/smtp_tls_policy.c
@@ -649,11 +649,14 @@ static void *policy_create(const char *unused_key, void 
*context)
      * and next-hop policies.
      */
     tls->level = global_tls_level();
     site_level = TLS_LEV_NOTFOUND;
 
-    if (tls_policy) {
+    if (iter->tlsreqno) {
+        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) {
        tls_site_lookup(tls, &site_level, dest, "next-hop destination");
        if (site_level != TLS_LEV_INVALID
            && strcasecmp_utf8(dest, host) != 0)
_______________________________________________
Postfix-users mailing list -- postfix-users@postfix.org
To unsubscribe send an email to postfix-users-le...@postfix.org

Reply via email to