Version in base suite: 3.10.4-1~deb13u1 Base version: postfix_3.10.4-1~deb13u1 Target version: postfix_3.10.5-1~deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/p/postfix/postfix_3.10.4-1~deb13u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/p/postfix/postfix_3.10.5-1~deb13u1.dsc HISTORY | 86 +++++++++++++++++++++++++++++++++++ conf/main.cf | 2 debian/changelog | 48 +++++++++++++++++++ debian/configure-instance.in | 2 debian/patches/debian-defaults.patch | 81 +++++++++++++------------------- html/lmtp.8.html | 7 ++ html/postconf.5.html | 21 ++++++++ html/smtp.8.html | 7 ++ man/man5/postconf.5 | 15 ++++++ man/man8/smtp.8 | 7 ++ mantools/postlink | 1 proto/postconf.proto | 17 ++++++ src/global/mail_params.h | 6 ++ src/global/mail_version.h | 4 - src/postcat/postcat.c | 4 + src/postconf/postconf_edit.c | 15 +++++- src/posttls-finger/posttls-finger.c | 2 src/showq/showq.c | 3 - src/smtp/Makefile.in | 2 src/smtp/lmtp_params.c | 3 + src/smtp/smtp.c | 8 +++ src/smtp/smtp.h | 11 +++- src/smtp/smtp_connect.c | 5 ++ src/smtp/smtp_key.c | 24 +++++++++ src/smtp/smtp_params.c | 3 + src/smtp/smtp_proto.c | 7 ++ src/smtp/smtp_tls_policy.c | 64 ++++++++++++++++++++++++++ src/smtpd/smtpd.c | 12 ++++ src/tls/tlsrpt_wrapper.c | 7 ++ src/util/dict_db.c | 1 src/util/dict_dbm.c | 3 - src/util/dict_lmdb.c | 1 src/util/dict_sdbm.c | 1 33 files changed, 419 insertions(+), 61 deletions(-) diff -Nru postfix-3.10.4/HISTORY postfix-3.10.5/HISTORY --- postfix-3.10.4/HISTORY 2025-08-18 22:44:50.000000000 +0000 +++ postfix-3.10.5/HISTORY 2025-10-24 15:06:14.000000000 +0000 @@ -29122,3 +29122,89 @@ messages that contain a "TLS-Required: no" header. This can prevent TLSRPT notifications for TLSRPT notifications. Files: smtp/smtp_connect.c, smtp_tls_policy.c. + +20250816 + + Bugfix (defect introduced: Postfix 3.0, date 20140731): the + smtpd 'disconnect' command counts did not count malformed + commands with "bad syntax" and "bad UTF-8 syntax" errors. + File: smtpd/smtpd.c. + +20250819 + + Bugfix: the 20250717 workaround broke DBM library support + which is still needed on Solaris. File: util/dict_dbm.c. + +20250823 + + Bugfix (defect introduced: Postfix 3.9, date 20230517): + posttls-finger logged a zero port number. Viktor Dukhovni. + File: posttls-finger/posttls-finger.c. + +20250829 + + Postfix 3.11 forward compatibility: allow a partial 'size' + record in maildrop queue files created with Postfix 3.11 + or later, instead of logging an ugly warning. Files: + showq/showq.c, postcat/postcat.c. + +20250906 + + Workaround for an interface mis-match between the Postfix + SMTP client and MTA-STS policy plugins. This introduces a + new parameter "smtp_tls_enforce_sts_mx_patterns" (default: + "yes"). The MTA-STS plugin configuration needs to enable + TLSRPT support, so that it forwards STS policy attributes + to Postfix. This works even if Postfix TLSRPT support is + disabled at build time or at runtime. + + With the above two configurations, the Postfix SMTP client + will connect to an MX host only if its name matches any STS + policy MX host pattern, and will match a server certificate + against the MX hostname. Otherwise, the old behavior stays + in effect: connect to any MX host listed in DNS, and match + a server certificate against any STS policy MX host pattern. + Files: mantools/postlink, 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. + +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. + +20250919 + + Bugfix (defect introduced: Postfix 3.8, date 20220128): the + 'postconf -e' output order for new main.cf entries was no + longer deterministic. Problem reported by Oleksandr Natalenko, + diagnosis by Eray Aslan. File: postconf/postconf_edit.c. + + Add missing meta_directory and shlib_directory settings to + the stock main.cf file. Problem diagnosed by Eray Aslan. + File: conf/main.cf. + +20240924 + + TLSRPT Workaround: when policies[*].policy.policy-type is + "no-policy-found", report the TLSRPT policy domain name as + the policies[*].policy.policy-domain value. This ignores + that TLSA policies must be reported with different policy-domain + values than STS policies. File: tls/tlsrpt_wrapper.c. + +20251021 + + Cleanup: the change at 20250717 could result in warnings + with "database X is older than source file Y". Files: + util/dict.c, util/dict_db.c, util/dict_dbm.c, util/dict_lmdb.c, + util/dict_sdbm.c. diff -Nru postfix-3.10.4/conf/main.cf postfix-3.10.5/conf/main.cf --- postfix-3.10.4/conf/main.cf 2024-11-21 17:49:05.000000000 +0000 +++ postfix-3.10.5/conf/main.cf 2025-10-23 19:51:44.000000000 +0000 @@ -683,3 +683,5 @@ # readme_directory = inet_protocols = ipv4 +shlib_directory = /usr/lib/postfix/${mail_version} +meta_directory = /etc/postfix diff -Nru postfix-3.10.4/debian/changelog postfix-3.10.5/debian/changelog --- postfix-3.10.4/debian/changelog 2025-08-22 06:51:46.000000000 +0000 +++ postfix-3.10.5/debian/changelog 2025-10-28 10:24:35.000000000 +0000 @@ -1,3 +1,51 @@ +postfix (3.10.5-1~deb13u1) trixie; urgency=medium + + * new upstream stable/bugfix 3.10.5 release, with multiple fixes. + From the upstream release notes: + - Workaround for an interface mis-match between the Postfix SMTP client + and MTA-STS policy plugins. + * The existing behavior is to connect to any MX host listed in DNS, and + to match the server certificate against any STS policy MX host pattern. + * The corrected behavior is to connect to an MX host only if its + name matches any STS policy MX host pattern, and to match the server + certificate against the MX hostname. + The corrected behavior must be enabled in two places: in Postfix with a + new parameter "smtp_tls_enforce_sts_mx_patterns" (default: "yes") and in + an MTA-STS plugin by enabling TLSRPT support, so that the plugin forwards + STS policy attributes to Postfix. This works even if Postfix TLSRPT + support is disabled at build time or at runtime. + - TLSRPT Workaround: when a TLSRPT policy-type value is "no-policy-found", + pretend that the TLSRPT policy domain value is equal to the recipient + domain. This ignores that different policy types (TLSA, STS) use different + policy domains. But this is what Microsoft does, and therefore, + what other tools expect. + - 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 + 1) to store sessions with different SMTPUTF8 requirements + under distinct connection cache storage keys, and + 2) to not cache a connection when SMTPUTF8 is required + but the server does not support that feature + - Bugfix (defect introduced: Postfix 3.0, date 20140731): + the smtpd 'disconnect' command statistics did not count commands + with "bad syntax" and "bad UTF-8 syntax" errors + - Postfix 3.11 forward compatibility: to avoid ugly warnings when + Postfix 3.11 is rolled back to an older version, allow a preliminary + 'size' record in maildrop queue files created with Postfix 3.11 or later + - Bugfix (defect introduced: Postfix 3.8, date 20220128): + non-reproducible build, because the 'postconf -e' output order + for new main.cf entries was no longer deterministic + - To make builds predictable, add missing meta_directory and + shlib_directory settings to the stock main.cf file + - Bugfix (defect introduced: Postfix 3.9, date 20230517): + posttls-finger(1) logged an incorrectly-formatted port number + * debian/patches/debian-defaults.patch: refresh, update for 2 new + parameters (with defaults) in main.cf, and make it with less context + * configure-instance.in: fix typo which caused recreating + cadir in chroot and excessive logging (Closes: #1115412) + + -- Michael Tokarev Tue, 28 Oct 2025 13:24:35 +0300 + postfix (3.10.4-1~deb13u1) trixie; urgency=medium * New upstream stable/bugfix version 3.10.4, with a handful of fixes. diff -Nru postfix-3.10.4/debian/configure-instance.in postfix-3.10.5/debian/configure-instance.in --- postfix-3.10.4/debian/configure-instance.in 2025-08-10 16:31:17.000000000 +0000 +++ postfix-3.10.5/debian/configure-instance.in 2025-09-17 09:42:58.000000000 +0000 @@ -155,7 +155,7 @@ -o -delete \ \) | while read file; do # ..and remove files which don't exist in source anymore - [ -f "$caddr/$file" ] || rm -f "$file" + [ -f "$cadir/$file" ] || rm -f "$file" done ) fi find -L $cadir -maxdepth 1 -name '[0-9a-f]*.[0-9]' -type f \ diff -Nru postfix-3.10.4/debian/patches/debian-defaults.patch postfix-3.10.5/debian/patches/debian-defaults.patch --- postfix-3.10.4/debian/patches/debian-defaults.patch 2025-04-24 07:52:30.000000000 +0000 +++ postfix-3.10.5/debian/patches/debian-defaults.patch 2025-10-28 10:06:59.000000000 +0000 @@ -1,6 +1,7 @@ From: Michael Tokarev Subject: Debian-specific defaults for main.cf and master.cf Date: Thu, 19 Dec 2024 22:37:11 +0300 +Updated: Tue, 28 Oct 2025 10:01:59 +0300 Forwarded: not-needed Change a few parameters to match Debian defaults. @@ -8,42 +9,32 @@ diff --git a/conf/main.cf b/conf/main.cf --- a/conf/main.cf +++ b/conf/main.cf -@@ -52,10 +52,10 @@ compatibility_level = 3.9 - # environments on different UNIX systems. +@@ -53,3 +53,3 @@ compatibility_level = 3.10 # -queue_directory = /var/spool/postfix +#queue_directory = /var/spool/postfix - # The command_directory parameter specifies the location of all - # postXXX commands. +@@ -58,3 +58,3 @@ queue_directory = /var/spool/postfix # -command_directory = /usr/sbin +#command_directory = /usr/sbin - # The daemon_directory parameter specifies the location of all Postfix -@@ -63,5 +63,5 @@ command_directory = /usr/sbin - # directory must be owned by root. +@@ -64,3 +64,3 @@ command_directory = /usr/sbin # -daemon_directory = /usr/libexec/postfix +#daemon_directory = /usr/lib/postfix/sbin - # The data_directory parameter specifies the location of Postfix-writable -@@ -69,5 +69,5 @@ daemon_directory = /usr/libexec/postfix - # by the mail_owner account (see below). +@@ -70,3 +70,3 @@ daemon_directory = /usr/libexec/postfix # -data_directory = /var/lib/postfix +#data_directory = /var/lib/postfix - # QUEUE AND PROCESS OWNERSHIP -@@ -80,5 +80,5 @@ data_directory = /var/lib/postfix - # USER. +@@ -81,3 +81,3 @@ data_directory = /var/lib/postfix # -mail_owner = postfix +#mail_owner = postfix - # The default_privs parameter specifies the default rights used by -@@ -89,4 +89,12 @@ mail_owner = postfix - #default_privs = nobody +@@ -90,2 +90,10 @@ mail_owner = postfix +# The Internet protocols Postfix will attempt to use when making or +# accepting connections. Specify one or more of "ipv4" or "ipv6", @@ -54,9 +45,7 @@ +inet_protocols = all + # INTERNET HOST AND DOMAIN NAMES - # -@@ -119,4 +127,9 @@ mail_owner = postfix - # to recipient addresses that have no @domain part. +@@ -120,2 +128,7 @@ mail_owner = postfix # +# Debian specific: Specifying a file name here will cause the first +# line of that file to be used as the name. The Debian default is @@ -64,81 +53,77 @@ +# +myorigin = /etc/mailname #myorigin = $myhostname - #myorigin = $mydomain -@@ -469,6 +482,6 @@ unknown_local_recipient_reject_code = 550 - # ALIAS THAT FORWARDS MAIL FOR ROOT TO A REAL USER. +@@ -470,4 +483,4 @@ unknown_local_recipient_reject_code = 550 # -#mailbox_command = /some/where/procmail -#mailbox_command = /some/where/procmail -a "$EXTENSION" +#mailbox_command = /usr/bin/procmail +#mailbox_command = /usr/bin/procmail -a "$EXTENSION" - # The mailbox_transport specifies the optional transport in master.cf -@@ -577,4 +590,5 @@ unknown_local_recipient_reject_code = 550 - #smtpd_banner = $myhostname ESMTP $mail_name +@@ -578,2 +591,3 @@ unknown_local_recipient_reject_code = 550 #smtpd_banner = $myhostname ESMTP $mail_name ($mail_version) +smtpd_banner = $myhostname ESMTP $mail_name (@DEB_VENDOR@) - # PARALLEL DELIVERY TO THE SAME DESTINATION -@@ -649,15 +663,15 @@ debugger_command = - # This is the Sendmail-compatible mail posting interface. +@@ -650,3 +664,3 @@ debugger_command = # -sendmail_path = +#sendmail_path = /usr/sbin/sendmail - # newaliases_path: The full pathname of the Postfix newaliases command. - # This is the Sendmail-compatible command to build alias databases. +@@ -655,3 +669,3 @@ sendmail_path = # -newaliases_path = +#newaliases_path = /usr/bin/newaliases - # mailq_path: The full pathname of the Postfix mailq command. This - # is the Sendmail-compatible mail queue listing command. +@@ -660,3 +674,3 @@ newaliases_path = # -mailq_path = +#mailq_path = /usr/bin/mailq - # setgid_group: The group for mail submission and queue management -@@ -665,21 +679,15 @@ mailq_path = - # is not shared with other accounts, not even with the Postfix account. +@@ -666,3 +680,3 @@ mailq_path = # -setgid_group = +#setgid_group = postdrop - # html_directory: The location of the Postfix HTML documentation. +@@ -670,3 +684,3 @@ setgid_group = # -html_directory = +#html_directory = /usr/share/doc/postfix/html - # manpage_directory: The location of the Postfix on-line manual pages. +@@ -674,14 +688,15 @@ html_directory = # -manpage_directory = -- ++#manpage_directory = /usr/share/man + -# sample_directory: The location of the Postfix sample configuration files. -# This parameter is obsolete as of Postfix 2.1. --# ++# readme_directory: The location of the Postfix README files. + # -sample_directory = -+#manpage_directory = /usr/share/man ++#readme_directory = /usr/share/doc/postfix - # readme_directory: The location of the Postfix README files. +-# readme_directory: The location of the Postfix README files. ++# shlib_directory: The location of the Postfix dynamically-linked libraries. ++# ++#shlib_directory = /usr/lib/postfix ++ ++# meta_directory: The location of the Postfix non-executable files ++# that are shared among all instances. # -readme_directory = -inet_protocols = ipv4 -+#readme_directory = /usr/share/doc/postfix +-shlib_directory = /usr/lib/postfix/${mail_version} +-meta_directory = /etc/postfix ++#meta_directory = /etc/postfix diff --git a/conf/master.cf b/conf/master.cf --- a/conf/master.cf +++ b/conf/master.cf -@@ -94,5 +94,5 @@ postlog unix-dgram n - n - 1 postlogd - # +@@ -99,3 +99,3 @@ postlog unix-dgram n - n - 1 postlogd #maildrop unix - n n - - pipe -# flags=DRXhu user=vmail argv=/usr/local/bin/maildrop -d ${recipient} +# flags=DRXhu user=vmail argv=/usr/bin/maildrop -d ${recipient} # - # ==================================================================== -@@ -137,5 +137,5 @@ postlog unix-dgram n - n - 1 postlogd - # +@@ -142,3 +142,3 @@ postlog unix-dgram n - n - 1 postlogd #bsmtp unix - n n - - pipe -# flags=Fq. user=bsmtp argv=/usr/local/sbin/bsmtp -f $sender $nexthop $recipient +# flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -f $sender $nexthop $recipient # - #scalemail-backend unix - n n - 2 pipe diff -Nru postfix-3.10.4/html/lmtp.8.html postfix-3.10.5/html/lmtp.8.html --- postfix-3.10.4/html/lmtp.8.html 2025-02-15 20:21:59.000000000 +0000 +++ postfix-3.10.5/html/lmtp.8.html 2025-10-26 22:56:06.000000000 +0000 @@ -766,6 +766,13 @@ Enable support for the "TLS-Required: no" message header, defined in RFC 8689. + Available in Postfix version 3.10.5 and later: + + smtp_tls_enforce_sts_mx_patterns (yes) + Transform the TLS policy from an STS policy plugin: connect to + an MX host only if its name matches any STS policy MX host pat- + tern, and match the server certificate against the MX hostname. + OBSOLETE STARTTLS CONTROLS The following configuration parameters exist for compatibility with Postfix versions before 2.3. Support for these will be removed in a diff -Nru postfix-3.10.4/html/postconf.5.html postfix-3.10.5/html/postconf.5.html --- postfix-3.10.4/html/postconf.5.html 2025-02-17 17:57:52.000000000 +0000 +++ postfix-3.10.5/html/postconf.5.html 2025-10-26 22:52:23.000000000 +0000 @@ -13502,6 +13502,27 @@ +
smtp_tls_enforce_sts_mx_patterns +(default: yes)
+ +

Transform the TLS policy from an STS policy plugin: connect to +an MX host only if its name matches any STS policy MX host pattern, +and match the server certificate against the MX hostname. This +setting takes effect only when an STS policy plugin has TLSRPT +support enabled, so that it forwards STS policy attributes to +Postfix. This works even if Postfix TLSRPT support is disabled at +build time or at runtime.

+ +

Without the above configuration settings for Postfix and STS +plugins, the old behavior stays in effect: connect to any MX host +listed in DNS, and match a server certificate against any STS policy +MX host pattern.

+ +

This feature is available in Postfix ≥ 3.10.5.

+ + +
+
smtp_tls_exclude_ciphers (default: empty)
diff -Nru postfix-3.10.4/html/smtp.8.html postfix-3.10.5/html/smtp.8.html --- postfix-3.10.4/html/smtp.8.html 2025-02-15 20:21:59.000000000 +0000 +++ postfix-3.10.5/html/smtp.8.html 2025-10-26 22:56:06.000000000 +0000 @@ -766,6 +766,13 @@ Enable support for the "TLS-Required: no" message header, defined in RFC 8689. + Available in Postfix version 3.10.5 and later: + + smtp_tls_enforce_sts_mx_patterns (yes) + Transform the TLS policy from an STS policy plugin: connect to + an MX host only if its name matches any STS policy MX host pat- + tern, and match the server certificate against the MX hostname. + OBSOLETE STARTTLS CONTROLS The following configuration parameters exist for compatibility with Postfix versions before 2.3. Support for these will be removed in a diff -Nru postfix-3.10.4/man/man5/postconf.5 postfix-3.10.5/man/man5/postconf.5 --- postfix-3.10.4/man/man5/postconf.5 2025-02-17 17:57:52.000000000 +0000 +++ postfix-3.10.5/man/man5/postconf.5 2025-10-26 22:52:23.000000000 +0000 @@ -8664,6 +8664,21 @@ .PP This feature is available in Postfix 2.2 and later. With Postfix 2.3 and later use smtp_tls_security_level instead. +.SH smtp_tls_enforce_sts_mx_patterns (default: yes) +Transform the TLS policy from an STS policy plugin: connect to +an MX host only if its name matches any STS policy MX host pattern, +and match the server certificate against the MX hostname. This +setting takes effect only when an STS policy plugin has TLSRPT +support enabled, so that it forwards STS policy attributes to +Postfix. This works even if Postfix TLSRPT support is disabled at +build time or at runtime. +.PP +Without the above configuration settings for Postfix and STS +plugins, the old behavior stays in effect: connect to any MX host +listed in DNS, and match a server certificate against any STS policy +MX host pattern. +.PP +This feature is available in Postfix >= 3.10.5. .SH smtp_tls_exclude_ciphers (default: empty) List of ciphers or cipher types to exclude from the Postfix SMTP client cipher diff -Nru postfix-3.10.4/man/man8/smtp.8 postfix-3.10.5/man/man8/smtp.8 --- postfix-3.10.4/man/man8/smtp.8 2025-02-15 20:21:58.000000000 +0000 +++ postfix-3.10.5/man/man8/smtp.8 2025-10-26 22:52:23.000000000 +0000 @@ -688,6 +688,13 @@ .IP "\fBtls_required_enable (yes)\fR" Enable support for the "TLS\-Required: no" message header, defined in RFC 8689. +.PP +Available in Postfix version 3.10.5 and later: +.IP "\fBsmtp_tls_enforce_sts_mx_patterns (yes)\fR" +Transform the TLS policy from an STS policy plugin: connect to +an MX host only if its name matches any STS policy MX host pattern, +and match the server certificate against the MX hostname. +.PP .SH "OBSOLETE STARTTLS CONTROLS" .na .nf diff -Nru postfix-3.10.4/mantools/postlink postfix-3.10.5/mantools/postlink --- postfix-3.10.4/mantools/postlink 2025-02-05 22:04:14.000000000 +0000 +++ postfix-3.10.5/mantools/postlink 2025-10-24 14:41:15.000000000 +0000 @@ -728,6 +728,7 @@ s;\blmtp_tlsrpt_enable\b;$&;g; s;\blmtp_tlsrpt_socket_name\b;$&;g; s;\blmtp_tlsrpt_skip_reused_handshakes\b;$&;g; + s;\bsmtp_tls_enforce_sts_mx_patterns\b;$&;g; s;\bsmtpd_enforce_tls\b;$&;g; s;\bsmtpd_sasl_tls_security_options\b;$&;g; s;\bsmtpd_sasl_type\b;$&;g; diff -Nru postfix-3.10.4/proto/postconf.proto postfix-3.10.5/proto/postconf.proto --- postfix-3.10.4/proto/postconf.proto 2025-02-17 16:55:50.000000000 +0000 +++ postfix-3.10.5/proto/postconf.proto 2025-10-24 14:41:15.000000000 +0000 @@ -19496,6 +19496,23 @@

This feature is available in Postfix ≥ 3.10.

+%PARAM smtp_tls_enforce_sts_mx_patterns yes + +

Transform the TLS policy from an STS policy plugin: connect to +an MX host only if its name matches any STS policy MX host pattern, +and match the server certificate against the MX hostname. This +setting takes effect only when an STS policy plugin has TLSRPT +support enabled, so that it forwards STS policy attributes to +Postfix. This works even if Postfix TLSRPT support is disabled at +build time or at runtime.

+ +

Without the above configuration settings for Postfix and STS +plugins, the old behavior stays in effect: connect to any MX host +listed in DNS, and match a server certificate against any STS policy +MX host pattern.

+ +

This feature is available in Postfix ≥ 3.10.5.

+ %PARAM full_name_encoding_charset utf-8

The character set name (also called "charset") that Postfix diff -Nru postfix-3.10.4/src/global/mail_params.h postfix-3.10.5/src/global/mail_params.h --- postfix-3.10.4/src/global/mail_params.h 2025-08-18 20:06:41.000000000 +0000 +++ postfix-3.10.5/src/global/mail_params.h 2025-10-24 14:41:15.000000000 +0000 @@ -4492,6 +4492,12 @@ #define DEF_LMTP_TLSRPT_SKIP_REUSED_HS DEF_SMTP_TLSRPT_SKIP_REUSED_HS extern int var_smtp_tlsrpt_skip_reused_hs; +#define VAR_SMTP_TLS_ENF_STS_MX_PAT "smtp_tls_enforce_sts_mx_patterns" +#define DEF_SMTP_TLS_ENF_STS_MX_PAT "yes" +#define VAR_LMTP_TLS_ENF_STS_MX_PAT "lmtp_tls_enforce_sts_mx_patterns" +#define DEF_LMTP_TLS_ENF_STS_MX_PAT "yes" +extern bool var_smtp_tls_enf_sts_mx_pat; + /* * RFC 2047 encoding of full name info. */ diff -Nru postfix-3.10.4/src/global/mail_version.h postfix-3.10.5/src/global/mail_version.h --- postfix-3.10.4/src/global/mail_version.h 2025-08-18 19:55:36.000000000 +0000 +++ postfix-3.10.5/src/global/mail_version.h 2025-10-26 22:48:02.000000000 +0000 @@ -20,8 +20,8 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20250818" -#define MAIL_VERSION_NUMBER "3.10.4" +#define MAIL_RELEASE_DATE "20251026" +#define MAIL_VERSION_NUMBER "3.10.5" #ifdef SNAPSHOT #define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE diff -Nru postfix-3.10.4/src/postcat/postcat.c postfix-3.10.5/src/postcat/postcat.c --- postfix-3.10.4/src/postcat/postcat.c 2024-09-25 14:27:30.000000000 +0000 +++ postfix-3.10.5/src/postcat/postcat.c 2025-10-23 19:58:17.000000000 +0000 @@ -348,6 +348,10 @@ /* Optional output (here before we update the state machine). */ if (do_print) PRINT_RECORD(flags, offset, rec_type, STR(buffer)); + /* Postfix 3.11 maildrop files may have preliminary SIZE record. */ + if (strncmp(VSTREAM_PATH(fp), MAIL_QUEUE_MAILDROP "/", + sizeof(MAIL_QUEUE_MAILDROP)) == 0) + continue; /* Read the message size/offset for the state machine optimizer. */ if (data_size >= 0 || data_offset >= 0) { msg_warn("file contains multiple size records"); diff -Nru postfix-3.10.4/src/postconf/postconf_edit.c postfix-3.10.5/src/postconf/postconf_edit.c --- postfix-3.10.4/src/postconf/postconf_edit.c 2025-04-21 20:54:07.000000000 +0000 +++ postfix-3.10.5/src/postconf/postconf_edit.c 2025-10-23 20:03:49.000000000 +0000 @@ -66,6 +66,7 @@ /* System library. */ #include +#include #include #include @@ -148,6 +149,16 @@ } } +/* pcf_cmp_ht_key - qsort helper for ht_info pointer array */ + +static int pcf_cmp_ht_key(const void *a, const void *b) +{ + HTABLE_INFO **ap = (HTABLE_INFO **) a; + HTABLE_INFO **bp = (HTABLE_INFO **) b; + + return (strcmp(ap[0]->key, bp[0]->key)); +} + /* pcf_edit_main - edit main.cf file */ void pcf_edit_main(int mode, int argc, char **argv) @@ -262,7 +273,9 @@ * Generate new entries for parameters that were not found. */ if (mode & PCF_EDIT_CONF) { - for (ht_info = ht = htable_list(table); *ht; ht++) { + ht_info = htable_list(table); + qsort((void *) ht_info, table->used, sizeof(*ht_info), pcf_cmp_ht_key); + for (ht = ht_info; *ht; ht++) { cvalue = (struct cvalue *) ht[0]->value; if (cvalue->found == 0) vstream_fprintf(dst, "%s = %s\n", ht[0]->key, cvalue->value); diff -Nru postfix-3.10.4/src/posttls-finger/posttls-finger.c postfix-3.10.5/src/posttls-finger/posttls-finger.c --- postfix-3.10.4/src/posttls-finger/posttls-finger.c 2025-08-18 19:56:40.000000000 +0000 +++ postfix-3.10.5/src/posttls-finger/posttls-finger.c 2025-10-23 16:47:49.000000000 +0000 @@ -1651,7 +1651,7 @@ if (level == TLS_LEV_INVALID || (state->stream = connect_addr(state, addr)) == 0) { msg_info("Failed to establish session to %s via %s:%u: %s", - dest, HNAME(addr), addr->port, + dest, HNAME(addr), ntohs(state->port), vstring_str(state->why->reason)); continue; } diff -Nru postfix-3.10.4/src/showq/showq.c postfix-3.10.5/src/showq/showq.c --- postfix-3.10.4/src/showq/showq.c 2022-02-20 22:27:31.000000000 +0000 +++ postfix-3.10.5/src/showq/showq.c 2025-10-23 19:58:17.000000000 +0000 @@ -213,7 +213,8 @@ arrival_time = atol(start); break; case REC_TYPE_SIZE: - if (msg_size_ok == 0) { + /* Postfix 3.11 maildrop files may have preliminary SIZE record. */ + if (msg_size_ok == 0 && strcmp(queue, MAIL_QUEUE_MAILDROP) != 0) { msg_size_ok = (start[strspn(start, "0123456789 ")] == 0 && (msg_size = atol(start)) >= 0); if (msg_size_ok == 0) { diff -Nru postfix-3.10.4/src/smtp/Makefile.in postfix-3.10.5/src/smtp/Makefile.in --- postfix-3.10.4/src/smtp/Makefile.in 2025-08-18 22:01:52.000000000 +0000 +++ postfix-3.10.5/src/smtp/Makefile.in 2025-10-24 14:41:15.000000000 +0000 @@ -307,6 +307,7 @@ 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 @@ -777,6 +778,7 @@ smtp_tls_policy.o: ../../include/mail_params.h smtp_tls_policy.o: ../../include/maps.h smtp_tls_policy.o: ../../include/match_list.h +smtp_tls_policy.o: ../../include/midna_domain.h smtp_tls_policy.o: ../../include/mime_state.h smtp_tls_policy.o: ../../include/msg.h smtp_tls_policy.o: ../../include/msg_stats.h diff -Nru postfix-3.10.4/src/smtp/lmtp_params.c postfix-3.10.5/src/smtp/lmtp_params.c --- postfix-3.10.4/src/smtp/lmtp_params.c 2024-09-27 16:18:47.000000000 +0000 +++ postfix-3.10.5/src/smtp/lmtp_params.c 2025-10-24 14:48:29.000000000 +0000 @@ -140,5 +140,8 @@ VAR_LMTP_REQ_DEADLINE, DEF_LMTP_REQ_DEADLINE, &var_smtp_req_deadline, VAR_LMTP_TLSRPT_ENABLE, DEF_LMTP_TLSRPT_ENABLE, &var_smtp_tlsrpt_enable, VAR_LMTP_TLSRPT_SKIP_REUSED_HS, DEF_LMTP_TLSRPT_SKIP_REUSED_HS, &var_smtp_tlsrpt_skip_reused_hs, +#ifdef USE_TLS + VAR_LMTP_TLS_ENF_STS_MX_PAT, DEF_LMTP_TLS_ENF_STS_MX_PAT, &var_smtp_tls_enf_sts_mx_pat, +#endif 0, }; diff -Nru postfix-3.10.4/src/smtp/smtp.c postfix-3.10.5/src/smtp/smtp.c --- postfix-3.10.4/src/smtp/smtp.c 2025-02-15 20:21:58.000000000 +0000 +++ postfix-3.10.5/src/smtp/smtp.c 2025-10-24 14:41:15.000000000 +0000 @@ -654,6 +654,13 @@ /* .IP "\fBtls_required_enable (yes)\fR" /* Enable support for the "TLS-Required: no" message header, defined /* in RFC 8689. +/* .PP +/* Available in Postfix version 3.10.5 and later: +/* .IP "\fBsmtp_tls_enforce_sts_mx_patterns (yes)\fR" +/* Transform the TLS policy from an STS policy plugin: connect to +/* an MX host only if its name matches any STS policy MX host pattern, +/* and match the server certificate against the MX hostname. +/* .PP /* OBSOLETE STARTTLS CONTROLS /* .ad /* .fi @@ -1133,6 +1140,7 @@ bool var_smtp_tls_force_tlsa; char *var_smtp_tls_insecure_mx_policy; bool var_smtp_tls_enable_rpk; +bool var_smtp_tls_enf_sts_mx_pat; #endif diff -Nru postfix-3.10.4/src/smtp/smtp.h postfix-3.10.5/src/smtp/smtp.h --- postfix-3.10.4/src/smtp/smtp.h 2025-08-18 22:01:52.000000000 +0000 +++ postfix-3.10.5/src/smtp/smtp.h 2025-10-24 14:41:15.000000000 +0000 @@ -137,6 +137,7 @@ 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 *); /* * Macros must use distinct names for local temporary variables, otherwise @@ -691,12 +692,14 @@ #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 @@ -735,7 +738,8 @@ */ #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, @@ -750,7 +754,8 @@ | 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) + SMTP_KEY_FLAG_PORT | SMTP_KEY_FLAG_TLS_LEVEL \ + | SMTP_KEY_FLAG_REQ_SMTPUTF8) /* * Silly little macros. diff -Nru postfix-3.10.4/src/smtp/smtp_connect.c postfix-3.10.5/src/smtp/smtp_connect.c --- postfix-3.10.4/src/smtp/smtp_connect.c 2025-08-18 22:01:52.000000000 +0000 +++ postfix-3.10.5/src/smtp/smtp_connect.c 2025-10-24 14:41:15.000000000 +0000 @@ -1124,6 +1124,11 @@ continue; /* XXX Assume there is no code at the end of this loop. */ } + /* Skip MX hosts that lack authorization. */ + if (!smtp_tls_authorize_mx_hostname(state->tls, SMTP_HNAME(addr))) { + continue; + /* XXX Assume there is no code at the end of this loop. */ + } /* Disable TLS when retrying after a handshake failure */ if (retry_plain) { state->tls->level = TLS_LEV_NONE; diff -Nru postfix-3.10.4/src/smtp/smtp_key.c postfix-3.10.5/src/smtp/smtp_key.c --- postfix-3.10.4/src/smtp/smtp_key.c 2018-11-20 12:25:40.000000000 +0000 +++ postfix-3.10.5/src/smtp/smtp_key.c 2025-10-23 18:17:45.000000000 +0000 @@ -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,12 +107,18 @@ * Global library. */ #include +#include /* * Application-specific. */ #include + /* Duplicated to minimze patch footprint. */ +#define DELIVERY_REQUIRES_SMTPUTF8(request) \ + (((request)->sendopts & SMTPUTF8_FLAG_REQUESTED) \ + && ((request)->sendopts & SMTPUTF8_FLAG_DERIVED)) + /* * We use a configurable field terminator and optional place holder for data * that is unavailable or inapplicable. We base64-encode content that @@ -209,6 +219,20 @@ 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 -Nru postfix-3.10.4/src/smtp/smtp_params.c postfix-3.10.5/src/smtp/smtp_params.c --- postfix-3.10.4/src/smtp/smtp_params.c 2024-09-27 16:18:46.000000000 +0000 +++ postfix-3.10.5/src/smtp/smtp_params.c 2025-10-24 14:48:03.000000000 +0000 @@ -144,5 +144,8 @@ VAR_SMTP_REQ_DEADLINE, DEF_SMTP_REQ_DEADLINE, &var_smtp_req_deadline, VAR_SMTP_TLSRPT_ENABLE, DEF_SMTP_TLSRPT_ENABLE, &var_smtp_tlsrpt_enable, VAR_SMTP_TLSRPT_SKIP_REUSED_HS, DEF_SMTP_TLSRPT_SKIP_REUSED_HS, &var_smtp_tlsrpt_skip_reused_hs, +#ifdef USE_TLS + VAR_SMTP_TLS_ENF_STS_MX_PAT, DEF_SMTP_TLS_ENF_STS_MX_PAT, &var_smtp_tls_enf_sts_mx_pat, +#endif 0, }; diff -Nru postfix-3.10.4/src/smtp/smtp_proto.c postfix-3.10.5/src/smtp/smtp_proto.c --- postfix-3.10.4/src/smtp/smtp_proto.c 2025-07-09 21:21:02.000000000 +0000 +++ postfix-3.10.5/src/smtp/smtp_proto.c 2025-10-23 18:17:45.000000000 +0000 @@ -658,14 +658,19 @@ * 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) { + 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 diff -Nru postfix-3.10.4/src/smtp/smtp_tls_policy.c postfix-3.10.5/src/smtp/smtp_tls_policy.c --- postfix-3.10.4/src/smtp/smtp_tls_policy.c 2025-08-18 22:01:52.000000000 +0000 +++ postfix-3.10.5/src/smtp/smtp_tls_policy.c 2025-10-24 14:41:15.000000000 +0000 @@ -17,6 +17,10 @@ /* SMTP_TLS_POLICY *tls; /* /* void smtp_tls_policy_cache_flush() +/* +/* int smtp_tls_authorize_mx_hostname(tls, qname) +/* SMTP_TLS_POLICY *tls; +/* const char *qname; /* DESCRIPTION /* smtp_tls_list_init() initializes lookup tables used by the TLS /* policy engine. @@ -31,6 +35,11 @@ /* When any required table or DNS lookups fail, the TLS level /* is set to TLS_LEV_INVALID, the "why" argument is updated /* with the error reason and the result value is zero (false). +/* When var_smtp_tls_enf_sts_mx_pat is not null, and a policy plugin +/* specifies a policy_type "sts" plus one or more mx_host_pattern +/* instances, transform the policy as follows: allow only MX hosts +/* that an match mx_host_pattern instance, and match a server +/* certificate against the server hostname. /* /* smtp_tls_policy_dummy() initializes a trivial, non-cached, /* policy with TLS disabled. @@ -38,6 +47,11 @@ /* smtp_tls_policy_cache_flush() destroys the TLS policy cache /* and contents. /* +/* smtp_tls_authorize_mx_hostname() authorizes an MX host if the +/* name used for host lookup satisfies a TLS policy MX name +/* constraint (for example, an STS policy MX pattern), or if the +/* TLS policy has no name constraint. +/* /* Arguments: /* .IP why /* A pointer to a DSN_BUF which holds error status information when @@ -107,6 +121,7 @@ #include #include #include +#include /* Global library. */ @@ -136,6 +151,51 @@ static MAPS *tls_policy; /* lookup table(s) */ static MAPS *tls_per_site; /* lookup table(s) */ +/* match_sts_mx_host_pattern - match hostname against STS policy MX pattern */ + +static int match_sts_mx_host_pattern(const char *pattern, const char *qname) +{ + const char *first_dot_in_qname; + + /* Caller guarantees that inputs are in ASCII form. */ + return (strcasecmp(qname, pattern) == 0 + || (pattern[0] == '*' && pattern[1] == '.' && pattern[2] != 0 + && (first_dot_in_qname = strchr(qname, '.')) != 0 + && first_dot_in_qname > qname + && strcasecmp(first_dot_in_qname + 1, pattern + 2) == 0)); +} + +/* smtp_tls_authorize_mx_hostname - enforce applicable MX hostname policy */ + +int smtp_tls_authorize_mx_hostname(SMTP_TLS_POLICY *tls, const char *name) +{ + +#define SAFE_FOR_SMTP_TLS_ENF_STS_MX_PAT(tls) (var_smtp_tls_enf_sts_mx_pat \ + && (tls)->ext_policy_type != 0 \ + && strcasecmp((tls)->ext_policy_type, "sts") == 0 \ + && (tls)->matchargv != 0 && (tls)->ext_mx_host_patterns != 0) + + /* Enforce STS policy MX patterns. */ + if (SAFE_FOR_SMTP_TLS_ENF_STS_MX_PAT(tls)) { + const char *aname; + char **pattp; + +#ifndef NO_EAI + if (!allascii(name) && (aname = midna_domain_to_ascii(name)) != 0) { + if (msg_verbose) + msg_info("%s asciified to %s", name, aname); + } else +#endif + aname = name; + for (pattp = tls->ext_mx_host_patterns->argv; *pattp; pattp++) + if (match_sts_mx_host_pattern(*pattp, aname)) + return (1); + return (0); + } + /* No applicable policy name patterns. */ + return (1); +} + /* smtp_tls_list_init - initialize per-site policy lists */ void smtp_tls_list_init(void) @@ -517,6 +577,10 @@ INVALID_RETURN(tls->why, site_level); } } + if (SAFE_FOR_SMTP_TLS_ENF_STS_MX_PAT(tls)) { + argv_truncate(tls->matchargv, 0); + argv_add(tls->matchargv, "hostname", (char *) 0); + } FREE_RETURN; } diff -Nru postfix-3.10.4/src/smtpd/smtpd.c postfix-3.10.5/src/smtpd/smtpd.c --- postfix-3.10.4/src/smtpd/smtpd.c 2025-02-05 22:04:14.000000000 +0000 +++ postfix-3.10.5/src/smtpd/smtpd.c 2025-10-23 16:45:51.000000000 +0000 @@ -5632,6 +5632,13 @@ {0,}, }; + /* + * In addition to counting unknown commands, the last table element also + * counts malformed commands (which aren't looked up in the command table). + */ +#define LAST_TABLE_PTR(table) ((table) + sizeof(table)/sizeof(*(table)) - 1) +static SMTPD_CMD *smtpd_cmdp_unknown = LAST_TABLE_PTR(smtpd_cmd_table); + static STRING_LIST *smtpd_noop_cmds; static STRING_LIST *smtpd_forbid_cmds; @@ -6000,6 +6007,8 @@ state->error_mask |= MAIL_ERROR_PROTOCOL; smtpd_chat_reply(state, "500 5.5.2 Error: bad UTF-8 syntax"); state->error_count++; + state->where = SMTPD_CMD_UNKNOWN; + smtpd_cmdp_unknown->total_count += 1; continue; } /* Move into smtpd_chat_query() and update session transcript. */ @@ -6021,6 +6030,8 @@ state->error_mask |= MAIL_ERROR_PROTOCOL; smtpd_chat_reply(state, "500 5.5.2 Error: bad syntax"); state->error_count++; + state->where = SMTPD_CMD_UNKNOWN; + smtpd_cmdp_unknown->total_count += 1; continue; } /* Ignore smtpd_noop_cmds lookup errors. Non-critical feature. */ @@ -6029,6 +6040,7 @@ smtpd_chat_reply(state, "250 2.0.0 Ok"); if (state->junk_cmds++ > var_smtpd_junk_cmd_limit) state->error_count++; + /* XXX We can't count these. */ continue; } for (cmdp = smtpd_cmd_table; cmdp->name != 0; cmdp++) diff -Nru postfix-3.10.4/src/tls/tlsrpt_wrapper.c postfix-3.10.5/src/tls/tlsrpt_wrapper.c --- postfix-3.10.4/src/tls/tlsrpt_wrapper.c 2025-02-17 16:49:23.000000000 +0000 +++ postfix-3.10.5/src/tls/tlsrpt_wrapper.c 2025-10-24 15:05:35.000000000 +0000 @@ -161,7 +161,8 @@ /* policies[].policy.policy-string[]. Ignored if the tls_policy_type /* value is TLSRPT_NO_POLICY_FOUND. /* .IP tls_policy_domain (may be null) -/* policies[].policy.policy-domain. +/* policies[].policy.policy-domain. If null, this defaults to the +/* TLSRPT policy domain. /* .IP mx_host_patterns (may be null) /* policies[].policy.mx-host[]. Ignored if the tls_policy_type /* value is TLSRPT_NO_POLICY_FOUND. @@ -403,10 +404,12 @@ PSTR_OR_NULL(mx_host_patterns)); trw->tls_policy_type = tls_policy_type; + if (tls_policy_domain == 0) + tls_policy_domain = trw->rpt_policy_domain; MYFREE_IF_SET_AND_COPY(trw->tls_policy_domain, tls_policy_domain); if (tls_policy_type == TLSRPT_NO_POLICY_FOUND) { ARGV_FREE_IF_SET_AND_CLEAR(trw->tls_policy_strings); - ARGV_FREE_IF_SET_AND_CLEAR(trw->tls_policy_strings); + ARGV_FREE_IF_SET_AND_CLEAR(trw->mx_host_patterns); } else { ARGV_FREE_IF_SET_AND_COPY(trw->tls_policy_strings, tls_policy_strings); ARGV_FREE_IF_SET_AND_COPY(trw->mx_host_patterns, mx_host_patterns); diff -Nru postfix-3.10.4/src/util/dict_db.c postfix-3.10.5/src/util/dict_db.c --- postfix-3.10.4/src/util/dict_db.c 2025-08-18 20:02:53.000000000 +0000 +++ postfix-3.10.5/src/util/dict_db.c 2025-10-23 20:00:35.000000000 +0000 @@ -799,6 +799,7 @@ * the source file changed only seconds ago. */ if ((dict_flags & DICT_FLAG_LOCK) != 0 + && open_flags == O_RDONLY && stat(path, &st) == 0 && st.st_mtime > dict_db->dict.mtime && st.st_mtime < time((time_t *) 0) - 100) diff -Nru postfix-3.10.4/src/util/dict_dbm.c postfix-3.10.5/src/util/dict_dbm.c --- postfix-3.10.4/src/util/dict_dbm.c 2025-08-18 20:02:53.000000000 +0000 +++ postfix-3.10.5/src/util/dict_dbm.c 2025-10-23 20:00:35.000000000 +0000 @@ -472,7 +472,7 @@ msg_fatal("open database %s: cannot support GDBM", path); if (fstat(dict_dbm->dict.stat_fd, &st) < 0) msg_fatal("dict_dbm_open: fstat: %m"); - if (open_mode == O_RDONLY) + if (open_flags == O_RDONLY) dict_dbm->dict.mtime = st.st_mtime; dict_dbm->dict.owner.uid = st.st_uid; dict_dbm->dict.owner.status = (st.st_uid != 0); @@ -482,6 +482,7 @@ * the source file changed only seconds ago. */ if ((dict_flags & DICT_FLAG_LOCK) != 0 + && open_flags == O_RDONLY && stat(path, &st) == 0 && st.st_mtime > dict_dbm->dict.mtime && st.st_mtime < time((time_t *) 0) - 100) diff -Nru postfix-3.10.4/src/util/dict_lmdb.c postfix-3.10.5/src/util/dict_lmdb.c --- postfix-3.10.4/src/util/dict_lmdb.c 2025-08-18 20:02:53.000000000 +0000 +++ postfix-3.10.5/src/util/dict_lmdb.c 2025-10-23 20:00:35.000000000 +0000 @@ -666,6 +666,7 @@ * the source file changed only seconds ago. */ if ((dict_flags & DICT_FLAG_LOCK) != 0 + && open_flags == O_RDONLY && stat(path, &st) == 0 && st.st_mtime > dict_lmdb->dict.mtime && st.st_mtime < time((time_t *) 0) - 100) diff -Nru postfix-3.10.4/src/util/dict_sdbm.c postfix-3.10.5/src/util/dict_sdbm.c --- postfix-3.10.4/src/util/dict_sdbm.c 2025-08-18 20:02:53.000000000 +0000 +++ postfix-3.10.5/src/util/dict_sdbm.c 2025-10-23 20:00:35.000000000 +0000 @@ -459,6 +459,7 @@ * the source file changed only seconds ago. */ if ((dict_flags & DICT_FLAG_LOCK) != 0 + && open_flags == O_RDONLY && stat(path, &st) == 0 && st.st_mtime > dict_sdbm->dict.mtime && st.st_mtime < time((time_t *) 0) - 100)