proto/postconf.proto, global/mail_params.h, smtp/lmtp_params.c,
smtp/smtp.c, smtp/smtp.h, smtp/smtp_connect.c, smtp/smtp_params.c,
smtp/smtp_tls_policy.c, smtp/smtp_tls_policy_test.c.
+
+20250911
+
+ Bugfix (defect introduced: Postfix 3.0): the Postfix SMTP
+ client's connection reuse logic did not distinguish between
+ sessions that require SMTPUTF8 support, and sessions that
+ do not. The solution is to store sessions with different
+ SMTPUTF8 requirements under distinct connection cache storage
+ keys, and to preserve the availability of SMTPUTF8 support
+ in the connection cache, so that a reused connection will
+ be stored under the same keys as it was looked up with.
+ Finally, do not cache a connection when SMTPUTF8 is
+ required but the server does not support that feature.
+ Files: smtp/smtp.h, smtp/smtp_key.c, smtp/smtp_proto.c.
request Reported by John Doe File tlsproxy tlsproxy c
smtpd smtpd c smtpd smtpd_chat c global mail_params h
Files Makefile in smtp smtp h smtp smtp_connect c
+ smtp smtp c smtp smtp h smtp smtp_connect c smtp smtp_params c
+ Files smtp smtp h smtp smtp_key c smtp smtp_proto c
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20250906"
+#define MAIL_RELEASE_DATE "20250911"
#define MAIL_VERSION_NUMBER "3.11"
#ifdef SNAPSHOT
smtp_key.o: ../../include/resolve_clnt.h
smtp_key.o: ../../include/scache.h
smtp_key.o: ../../include/sendopts.h
+smtp_key.o: ../../include/smtputf8.h
smtp_key.o: ../../include/sock_addr.h
smtp_key.o: ../../include/string_list.h
smtp_key.o: ../../include/sys_defs.h
extern void smtp_tls_list_init(void);
extern int smtp_tls_policy_cache_query(DSN_BUF *, SMTP_TLS_POLICY *, SMTP_ITERATOR *);
extern void smtp_tls_policy_cache_flush(void);
-extern int smtp_tls_authorize_mx_hostname(SMTP_TLS_POLICY *, const char *);
+extern int smtp_tls_authorize_mx_hostname(SMTP_TLS_POLICY *, const char *);
/*
* Macros must use distinct names for local temporary variables, otherwise
#define SMTP_KEY_FLAG_ADDR (1<<5) /* remote address */
#define SMTP_KEY_FLAG_PORT (1<<6) /* remote port */
#define SMTP_KEY_FLAG_TLS_LEVEL (1<<7) /* requested TLS level */
+#define SMTP_KEY_FLAG_REQ_SMTPUTF8 (1<<8) /* SMTPUTF8 is required */
#define SMTP_KEY_MASK_ALL \
(SMTP_KEY_FLAG_SERVICE | SMTP_KEY_FLAG_SENDER | \
SMTP_KEY_FLAG_REQ_NEXTHOP | \
SMTP_KEY_FLAG_CUR_NEXTHOP | SMTP_KEY_FLAG_HOSTNAME | \
- SMTP_KEY_FLAG_ADDR | SMTP_KEY_FLAG_PORT | SMTP_KEY_FLAG_TLS_LEVEL)
+ SMTP_KEY_FLAG_ADDR | SMTP_KEY_FLAG_PORT | SMTP_KEY_FLAG_TLS_LEVEL | \
+ SMTP_KEY_FLAG_REQ_SMTPUTF8)
/*
* Conditional lookup-key flags for cached connections that may be
* (REQ_NEXTHOP) prevents false sharing of TLS identities (the destination
* key links only to appropriate endpoint lookup keys). The SERVICE
* attribute is a proxy for all request-independent configuration details.
+ *
+ * Be sure to include all features that are preserved in
+ * SMTP_FEATURE_ENDPOINT_MASK, otherwise a reused connection may be stored
+ * under the wrong key.
*/
#define SMTP_KEY_MASK_SCACHE_DEST_LABEL \
(SMTP_KEY_FLAG_SERVICE | COND_SASL_SMTP_KEY_FLAG_SENDER \
- | SMTP_KEY_FLAG_REQ_NEXTHOP | SMTP_KEY_FLAG_TLS_LEVEL)
+ | SMTP_KEY_FLAG_REQ_NEXTHOP | SMTP_KEY_FLAG_TLS_LEVEL \
+ | SMTP_KEY_FLAG_REQ_SMTPUTF8)
/*
* Connection-cache endpoint lookup key. The SENDER, CUR_NEXTHOP, HOSTNAME,
* when different SASL credentials or TLS identities may be required for
* different deliveries to the same IP address and port. The SERVICE
* attribute is a proxy for all request-independent configuration details.
+ *
+ * Be sure to include all features that are preserved in
+ * SMTP_FEATURE_ENDPOINT_MASK, otherwise a reused connection may be stored
+ * under the wrong key.
*/
#define SMTP_KEY_MASK_SCACHE_ENDP_LABEL \
(SMTP_KEY_FLAG_SERVICE | COND_SASL_SMTP_KEY_FLAG_SENDER \
| COND_SASL_SMTP_KEY_FLAG_CUR_NEXTHOP \
| COND_SASL_SMTP_KEY_FLAG_HOSTNAME \
- | COND_TLS_SMTP_KEY_FLAG_CUR_NEXTHOP | SMTP_KEY_FLAG_ADDR | \
- SMTP_KEY_FLAG_PORT | SMTP_KEY_FLAG_TLS_LEVEL)
+ | COND_TLS_SMTP_KEY_FLAG_CUR_NEXTHOP | SMTP_KEY_FLAG_ADDR \
+ | SMTP_KEY_FLAG_PORT | SMTP_KEY_FLAG_TLS_LEVEL \
+ | SMTP_KEY_FLAG_REQ_SMTPUTF8)
/*
* Silly little macros.
#endif /* USE_TLSRPT && USE_TLS */
+ /*
+ * This delivery requires SMTPUTF8 server support if the sender requested
+ * SMTPUTF8 support AND the delivery request involves at least one UTF-8
+ * envelope address or header value.
+ *
+ * If the sender requested SMTPUTF8 support but the delivery request involves
+ * no UTF-8 envelope address or header value, then we could still deliver
+ * such mail to a non-SMTPUTF8 server, except that we must either
+ * uxtext-encode ORCPT parameters or not send them. We cannot encode the
+ * ORCPT in xtext, because legacy SMTP requires that the unencoded address
+ * consist entirely of printable (graphic and white space) characters from
+ * the US-ASCII repertoire (RFC 3461 section 4). A correct uxtext encoder
+ * will produce a result that an xtext decoder will pass through unchanged.
+ */
+#define DELIVERY_REQUIRES_SMTPUTF8(request) \
+ (((request)->sendopts & SMTPUTF8_FLAG_REQUESTED) \
+ && ((request)->sendopts & SMTPUTF8_FLAG_DERIVED))
+
/* LICENSE
/* .ad
/* .fi
/* The current iterator's remote address.
/* .IP SMTP_KEY_FLAG_PORT
/* The current iterator's remote port.
+/* .IP SMTP_KEY_FLAG_TLS_LEVEL
+/* The requested TLS security level.
+/* .IP SMTP_KEY_FLAG_REQ_SMTPUTF8
+/* Whether SMTPUTF8 support is required.
/* .RE
/* DIAGNOSTICS
/* Panic: undefined flag or zero flags. Fatal: out of memory.
* Global library.
*/
#include <mail_params.h>
+#include <smtputf8.h>
/*
* Application-specific.
smtp_key_append_na(buffer, delim_na);
#endif
+ /*
+ * Require SMTPUTF8 support, if applicable. TODO(wietse) if a delivery
+ * request does not need SMTPUTF8, should we also search the connection
+ * cache for a connection that is known to support it? No, because the
+ * connection would be saved back under a key that does not require
+ * SMTPUTF8 support.
+ */
+ if (flags & SMTP_KEY_FLAG_REQ_SMTPUTF8)
+ smtp_key_append_uint(buffer,
+ DELIVERY_REQUIRES_SMTPUTF8(state->request),
+ delim_na);
+ else
+ smtp_key_append_na(buffer, delim_na);
+
VSTRING_TERMINATE(buffer);
return STR(buffer);
msg_info("server features: 0x%x size %.0f",
session->features, (double) session->size_limit);
- /*
- * Decide if this delivery requires SMTPUTF8 server support.
- *
- * For now, we require that the remote SMTP server supports SMTPUTF8 when
- * the sender requested SMTPUTF8 support.
- *
- * XXX EAI Refine this to: the sender requested SMTPUTF8 support AND the
- * delivery request involves at least one UTF-8 envelope address or
- * header value.
- *
- * If the sender requested SMTPUTF8 support but the delivery request
- * involves no UTF-8 envelope address or header value, then we could
- * still deliver such mail to a non-SMTPUTF8 server, except that we must
- * either uxtext-encode ORCPT parameters or not send them. We cannot
- * encode the ORCPT in xtext, because legacy SMTP requires that the
- * unencoded address consist entirely of printable (graphic and white
- * space) characters from the US-ASCII repertoire (RFC 3461 section 4). A
- * correct uxtext encoder will produce a result that an xtext decoder
- * will pass through unchanged.
- *
- * XXX Should we try to encode headers with RFC 2047 when delivering to a
- * non-SMTPUTF8 server? That could make life easier for mailing lists.
- */
-#define DELIVERY_REQUIRES_SMTPUTF8 \
- ((request->sendopts & SMTPUTF8_FLAG_REQUESTED) \
- && (request->sendopts & SMTPUTF8_FLAG_DERIVED))
-
/*
* Require that the server supports SMTPUTF8 when delivery requires
* SMTPUTF8.
*
* Fix 20140706: moved this before negotiating TLS, AUTH, and so on.
+ *
+ * Fix 20250911: do not cache this session because it does not satisfy the
+ * requirement expressed in the cache storage key.
*/
if ((session->features & SMTP_FEATURE_SMTPUTF8) == 0
- && DELIVERY_REQUIRES_SMTPUTF8)
+ && DELIVERY_REQUIRES_SMTPUTF8(request)) {
+ DONT_CACHE_THIS_SESSION;
return (smtp_mesg_fail(state, DSN_BY_LOCAL_MTA,
SMTP_RESP_FAKE(&fake, "5.6.7"),
"SMTPUTF8 is required, "
"but was not offered by host %s",
session->namaddr));
+ }
/*
* Fix 20140706: don't do silly things when the remote server announces