From: Wietse Z Venema Date: Thu, 11 Sep 2025 05:00:00 +0000 (-0500) Subject: postfix-3.11-20250911 X-Git-Tag: v3.11.0-RC1~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=df900959ebe8e1f9b950cd0568620676d2142f79;p=thirdparty%2Fpostfix.git postfix-3.11-20250911 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index bd2c2beec..c2bc3dca6 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -29604,3 +29604,17 @@ Apologies for any names omitted. 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. diff --git a/postfix/proto/stop.double-history b/postfix/proto/stop.double-history index 78427bde6..913a3083f 100644 --- a/postfix/proto/stop.double-history +++ b/postfix/proto/stop.double-history @@ -196,3 +196,5 @@ proto proto COMPATIBILITY_README html 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 diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 564e97222..14d4e2ad5 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -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 "20250906" +#define MAIL_RELEASE_DATE "20250911" #define MAIL_VERSION_NUMBER "3.11" #ifdef SNAPSHOT diff --git a/postfix/src/smtp/Makefile.in b/postfix/src/smtp/Makefile.in index 25002c658..9b812f50e 100644 --- a/postfix/src/smtp/Makefile.in +++ b/postfix/src/smtp/Makefile.in @@ -315,6 +315,7 @@ 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/smtputf8.h smtp_key.o: ../../include/sock_addr.h smtp_key.o: ../../include/string_list.h smtp_key.o: ../../include/sys_defs.h diff --git a/postfix/src/smtp/smtp.h b/postfix/src/smtp/smtp.h index 28cca83a4..5ce798d02 100644 --- a/postfix/src/smtp/smtp.h +++ b/postfix/src/smtp/smtp.h @@ -137,7 +137,7 @@ typedef struct SMTP_TLS_POLICY { 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 @@ -692,12 +692,14 @@ char *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int); #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 @@ -733,10 +735,15 @@ char *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int); * (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, @@ -745,13 +752,18 @@ char *smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int); * 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. @@ -808,6 +820,24 @@ extern void smtp_tlsrpt_set_ehlo_resp(SMTP_STATE *, const char *ehlo_resp); #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 diff --git a/postfix/src/smtp/smtp_key.c b/postfix/src/smtp/smtp_key.c index 643f4db7e..7f52f8298 100644 --- a/postfix/src/smtp/smtp_key.c +++ b/postfix/src/smtp/smtp_key.c @@ -65,6 +65,10 @@ /* 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. @@ -103,6 +107,7 @@ * Global library. */ #include +#include /* * Application-specific. @@ -209,6 +214,20 @@ char *smtp_key_prefix(VSTRING *buffer, const char *delim_na, 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); diff --git a/postfix/src/smtp/smtp_proto.c b/postfix/src/smtp/smtp_proto.c index b89686378..f93d57b5b 100644 --- a/postfix/src/smtp/smtp_proto.c +++ b/postfix/src/smtp/smtp_proto.c @@ -626,46 +626,24 @@ int smtp_helo(SMTP_STATE *state) 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