20250807
- Bugfix (defect introduced: 20250803): "TLS-Required: no" was
- no longer in effect for LMTP deliveries. Viktor Dukhovni.
+ Bugfix (defect introduced: 20250803): "TLS-Required: no"
+ was no longer in effect for deliveries over UNIX-domain
+ sockets (which are supported for LMTP only). Viktor Dukhovni.
File: smtp/smtp_connect.c.
+
+20250808
+
+ Cleanup: simplify the code to determine if "TLS-Required:
+ no" is in effect, and improve the tls_required_enable
+ documentation. This will be back-ported to Postfix 3.10.
+ Files: Makefile.in, smtp/smtp.h smtp/smtp_connect.c,
+ smtp/smtp_tls_policy.c, proto/postconf.proto.
<p> Enable support for the "TLS-Required: no" message header, defined
in <a href="https://tools.ietf.org/html/rfc8689">RFC 8689</a>. By adding this header to a message, a sender requests
-no enforcement of TLS policy. This limits the Postfix SMTP client
+no enforcement of TLS policy. This disables TLS policy lookup, and
+limits the Postfix SMTP client
TLS security level to "may", that is, do not verify remote SMTP
server certificates, and fall back to plaintext if TLS is unavailable.
If a message contains a "TLS-Required: no" header, then Postfix
.SH tls_required_enable (default: yes)
Enable support for the "TLS\-Required: no" message header, defined
in RFC 8689. By adding this header to a message, a sender requests
-no enforcement of TLS policy. This limits the Postfix SMTP client
+no enforcement of TLS policy. This disables TLS policy lookup, and
+limits the Postfix SMTP client
TLS security level to "may", that is, do not verify remote SMTP
server certificates, and fall back to plaintext if TLS is unavailable.
If a message contains a "TLS\-Required: no" header, then Postfix
<p> Enable support for the "TLS-Required: no" message header, defined
in RFC 8689. By adding this header to a message, a sender requests
-no enforcement of TLS policy. This limits the Postfix SMTP client
+no enforcement of TLS policy. This disables TLS policy lookup, and
+limits the Postfix SMTP client
TLS security level to "may", that is, do not verify remote SMTP
server certificates, and fall back to plaintext if TLS is unavailable.
If a message contains a "TLS-Required: no" header, then Postfix
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20250807"
+#define MAIL_RELEASE_DATE "20250808"
#define MAIL_VERSION_NUMBER "3.11"
#ifdef SNAPSHOT
smtp.o: ../../include/recipient_list.h
smtp.o: ../../include/resolve_clnt.h
smtp.o: ../../include/scache.h
+smtp.o: ../../include/sendopts.h
smtp.o: ../../include/sock_addr.h
smtp.o: ../../include/string_list.h
smtp.o: ../../include/stringops.h
smtp_addr.o: ../../include/recipient_list.h
smtp_addr.o: ../../include/resolve_clnt.h
smtp_addr.o: ../../include/scache.h
+smtp_addr.o: ../../include/sendopts.h
smtp_addr.o: ../../include/sock_addr.h
smtp_addr.o: ../../include/string_list.h
smtp_addr.o: ../../include/stringops.h
smtp_key.o: ../../include/recipient_list.h
smtp_key.o: ../../include/resolve_clnt.h
smtp_key.o: ../../include/scache.h
+smtp_key.o: ../../include/sendopts.h
smtp_key.o: ../../include/sock_addr.h
smtp_key.o: ../../include/string_list.h
smtp_key.o: ../../include/sys_defs.h
smtp_map11.o: ../../include/recipient_list.h
smtp_map11.o: ../../include/resolve_clnt.h
smtp_map11.o: ../../include/scache.h
+smtp_map11.o: ../../include/sendopts.h
smtp_map11.o: ../../include/sock_addr.h
smtp_map11.o: ../../include/string_list.h
smtp_map11.o: ../../include/sys_defs.h
smtp_misc.o: ../../include/recipient_list.h
smtp_misc.o: ../../include/resolve_clnt.h
smtp_misc.o: ../../include/scache.h
+smtp_misc.o: ../../include/sendopts.h
smtp_misc.o: ../../include/sock_addr.h
smtp_misc.o: ../../include/string_list.h
smtp_misc.o: ../../include/sys_defs.h
smtp_rcpt.o: ../../include/recipient_list.h
smtp_rcpt.o: ../../include/resolve_clnt.h
smtp_rcpt.o: ../../include/scache.h
+smtp_rcpt.o: ../../include/sendopts.h
smtp_rcpt.o: ../../include/sent.h
smtp_rcpt.o: ../../include/sock_addr.h
smtp_rcpt.o: ../../include/string_list.h
smtp_reuse.o: ../../include/recipient_list.h
smtp_reuse.o: ../../include/resolve_clnt.h
smtp_reuse.o: ../../include/scache.h
+smtp_reuse.o: ../../include/sendopts.h
smtp_reuse.o: ../../include/sock_addr.h
smtp_reuse.o: ../../include/string_list.h
smtp_reuse.o: ../../include/stringops.h
smtp_sasl_auth_cache.o: ../../include/recipient_list.h
smtp_sasl_auth_cache.o: ../../include/resolve_clnt.h
smtp_sasl_auth_cache.o: ../../include/scache.h
+smtp_sasl_auth_cache.o: ../../include/sendopts.h
smtp_sasl_auth_cache.o: ../../include/sock_addr.h
smtp_sasl_auth_cache.o: ../../include/string_list.h
smtp_sasl_auth_cache.o: ../../include/stringops.h
smtp_sasl_glue.o: ../../include/recipient_list.h
smtp_sasl_glue.o: ../../include/resolve_clnt.h
smtp_sasl_glue.o: ../../include/scache.h
+smtp_sasl_glue.o: ../../include/sendopts.h
smtp_sasl_glue.o: ../../include/smtp_stream.h
smtp_sasl_glue.o: ../../include/sock_addr.h
smtp_sasl_glue.o: ../../include/split_at.h
smtp_sasl_proto.o: ../../include/resolve_clnt.h
smtp_sasl_proto.o: ../../include/sasl_mech_filter.h
smtp_sasl_proto.o: ../../include/scache.h
+smtp_sasl_proto.o: ../../include/sendopts.h
smtp_sasl_proto.o: ../../include/sock_addr.h
smtp_sasl_proto.o: ../../include/string_list.h
smtp_sasl_proto.o: ../../include/stringops.h
smtp_session.o: ../../include/recipient_list.h
smtp_session.o: ../../include/resolve_clnt.h
smtp_session.o: ../../include/scache.h
+smtp_session.o: ../../include/sendopts.h
smtp_session.o: ../../include/sock_addr.h
smtp_session.o: ../../include/string_list.h
smtp_session.o: ../../include/stringops.h
smtp_state.o: ../../include/recipient_list.h
smtp_state.o: ../../include/resolve_clnt.h
smtp_state.o: ../../include/scache.h
+smtp_state.o: ../../include/sendopts.h
smtp_state.o: ../../include/sock_addr.h
smtp_state.o: ../../include/string_list.h
smtp_state.o: ../../include/sys_defs.h
smtp_tls_policy.o: ../../include/resolve_clnt.h
smtp_tls_policy.o: ../../include/sane_strtol.h
smtp_tls_policy.o: ../../include/scache.h
+smtp_tls_policy.o: ../../include/sendopts.h
smtp_tls_policy.o: ../../include/sock_addr.h
smtp_tls_policy.o: ../../include/string_list.h
smtp_tls_policy.o: ../../include/stringops.h
smtp_tlsrpt.o: ../../include/recipient_list.h
smtp_tlsrpt.o: ../../include/resolve_clnt.h
smtp_tlsrpt.o: ../../include/scache.h
+smtp_tlsrpt.o: ../../include/sendopts.h
smtp_tlsrpt.o: ../../include/sock_addr.h
smtp_tlsrpt.o: ../../include/string_list.h
smtp_tlsrpt.o: ../../include/stringops.h
smtp_trouble.o: ../../include/recipient_list.h
smtp_trouble.o: ../../include/resolve_clnt.h
smtp_trouble.o: ../../include/scache.h
+smtp_trouble.o: ../../include/sendopts.h
smtp_trouble.o: ../../include/smtp_stream.h
smtp_trouble.o: ../../include/sock_addr.h
smtp_trouble.o: ../../include/string_list.h
smtp_unalias.o: ../../include/recipient_list.h
smtp_unalias.o: ../../include/resolve_clnt.h
smtp_unalias.o: ../../include/scache.h
+smtp_unalias.o: ../../include/sendopts.h
smtp_unalias.o: ../../include/sock_addr.h
smtp_unalias.o: ../../include/string_list.h
smtp_unalias.o: ../../include/sys_defs.h
#include <tok822.h>
#include <dsn_buf.h>
#include <header_body_checks.h>
+#include <sendopts.h>
/*
* Postfix TLS library.
VSTRING *host; /* hostname or empty */
VSTRING *addr; /* printable address or empty */
unsigned port; /* network byte order or null */
-#ifdef USE_TLS
- int tlsreqno; /* "TLS-Required: no" */
-#endif
struct DNS_RR *rr; /* DNS resource record or null */
struct DNS_RR *mx; /* DNS resource record or null */
/* Private members. */
struct SMTP_STATE *parent; /* parent linkage */
} SMTP_ITERATOR;
-#ifdef USE_TLS
-#define IF_USE_TLS(...) (__VA_ARGS__)
-#else
-#define IF_USE_TLS(...)
-#endif
-
#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); \
- IF_USE_TLS((iter)->tlsreqno = 0); \
(iter)->mx = (iter)->rr = 0; \
vstring_strcpy((iter)->saved_dest, ""); \
(iter)->parent = (state); \
unsigned logged_line_length_limit:1;
} SMTP_STATE;
+#ifdef USE_TLS
+#define STATE_TLS_NOT_REQUIRED(state) \
+ (var_tls_required_enable && \
+ ((state)->request->sendopts & SOPT_REQUIRETLS_HEADER))
+#endif
+
/*
* Primitives to enable/disable/test connection caching and reuse based on
* the delivery request next-hop destination (i.e. not smtp_fallback_relay).
SMTP_ITER_INIT(iter, path, var_myhostname, path, NO_PORT, state);
- /*
- * If a "TLS-Required: no" header is in effect, update the iterator to
- * override TLS policy selection and to limit the security level to
- * "may". Do not reset the security level after policy selection, as that
- * would result in errors. For example, when TLSA records are looked up
- * for security level "dane", and then the security level is reset to
- * "may", the activation of those TLSA records will fail.
- *
- * Note that the REQUIRETLS verb in ESMTP overrides the "TLS-Required: no"
- * header.
- */
-#ifdef USE_TLS
- if (var_tls_required_enable
- && (state->request->sendopts & SOPT_REQUIRETLS_HEADER)) {
- iter->tlsreqno = 1;
- }
-#endif
-
/*
* Opportunistic TLS for unix domain sockets does not make much sense,
* since the channel is private, mere encryption without authentication
* willing to retry after TLS handshake failures here, we downgrade "may"
* no "none". Nothing is lost, and much waste is avoided.
*
- * We don't know who is authenticating whom, so if a client cert is
- * available, "encrypt" may be a sensible policy. Otherwise, we also
- * downgrade "encrypt" to "none", this time just to avoid waste.
+ * If a client cert is available, "encrypt" may be a sensible policy.
+ * Without client cert, "encrypt" and "may" over UNIX-domain sockets are
+ * not useful.
*
* We use smtp_reuse_nexthop() instead of smtp_reuse_addr(), so that we can
* reuse a SASL-authenticated connection (however unlikely this scenario
SMTP_ITER_INIT(iter, dest, NO_HOST, NO_ADDR, port, state);
- /*
- * If a "TLS-Required: no" header is in effect, update the iterator
- * to override TLS policy selection and to limit the security level
- * to "may". Do not reset the security level after policy selection,
- * as that would result in errors. For example, when TLSA records are
- * looked up for security level "dane", and then the security level
- * is reset to "may", the activation of those TLSA records will fail.
- *
- * Note that the REQUIRETLS verb in ESMTP overrides the "TLS-Required:
- * no" header.
- */
-#ifdef USE_TLS
- if (var_tls_required_enable
- && (state->request->sendopts & SOPT_REQUIRETLS_HEADER)) {
- iter->tlsreqno = 1;
- }
-#endif
-
/*
* TODO(wietse) If the domain publishes a TLSRPT policy, they expect
* that clients use SMTP over TLS. Should we upgrade a TLS security
* plaintext, and could break interoperability with receivers that
* crank up security up to 11.
*
- * As of change 20250803, with "TLS-Required: no", the SMTP client also
- * ignores the recipient-side policy mechanism TLSRPT, in addition to
- * the already ignored DANE and MTA-STS mechanisms. This prevents
- * TLSRPT notifications for all SMTP deliveries that do not require
- * TLS.
+ * With "TLS-Required: no" in effect, the SMTP client ignores the
+ * recipient-side policy mechanism TLSRPT, in addition to the already
+ * ignored DANE and MTA-STS mechanisms. This prevents TLSRPT
+ * notifications for all SMTP deliveries that do not require TLS.
*/
#ifdef USE_TLSRPT
if (smtp_mode && var_smtp_tlsrpt_enable
- && iter->tlsreqno == 0
+ && STATE_TLS_NOT_REQUIRED(state) == 0
&& tls_level_lookup(var_smtp_tls_level) > TLS_LEV_NONE
&& !valid_hostaddr(domain, DONT_GRIPE))
smtp_tlsrpt_create_wrapper(state, domain);
* Compute the per-site TLS enforcement level. For compatibility with the
* original TLS patch, this algorithm is gives equal precedence to host
* and next-hop policies.
+ *
+ * When "TLS-Required: no" is in effect, skip TLS policy lookup and limit
+ * the security level to "may". Do not reset the security level after
+ * policy lookup, as that would result in errors. For example, when TLSA
+ * records are looked up for security level "dane", and then the security
+ * level is reset to "may", the activation of those TLSA records will
+ * fail.
*/
tls->level = global_tls_level();
site_level = TLS_LEV_NOTFOUND;
- if (iter->tlsreqno) {
+ if (STATE_TLS_NOT_REQUIRED(iter->parent)) {
if (msg_verbose)
msg_info("%s: no tls policy lookup", __func__);
if (tls->level > TLS_LEV_MAY)