[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1111798: marked as done (trixie-pu: package postfix/3.10.4-1~deb13u1)



Your message dated Sat, 06 Sep 2025 12:14:57 +0100
with message-id <165032e5317517556dd7fd8cf24843112a3fb6ac.camel@adam-barratt.org.uk>
and subject line Closing p-u requests for fixes included in 13.1
has caused the Debian Bug report #1111798,
regarding trixie-pu: package postfix/3.10.4-1~deb13u1
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
1111798: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1111798
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
Tags: trixie
X-Debbugs-Cc: postfix@packages.debian.org
Control: affects -1 + src:postfix
User: release.debian.org@packages.debian.org
Usertags: pu

[ Reason ]
There's an upstream stable/bugfix release fixing a handful of
issues found in 3.10.3 version of postfix.

Additionally there's a fix for chroot update procedure which
I wanted to do for quite some time, -- see #1100100 & #1110704.
I had to write a simple file copy procedure in perl because no
existing basic tools has what's needed.

[ Tests ]
There's a minimal internal postfix testsuite, which works.
Additionally, I use this release in production already, without
any issues.  The new file copy procedure has been tested in
forky already, also not causing issues.

[ Risks ]
Postfix upstream stable series has always been an excellent example
of stability (actually it's been this way with all postfix releases).
So I don't expect risks from the changes in postfix itself.

However, the new chroot sync procedure might cause effects, - it's
a large-ish change for debian stable series.  I did try to write it
in a most accurate way and verified it from various points of view,
though.

[ Checklist ]
  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in (old)stable
  [x] the issue is verified as fixed in unstable

[ Changes ]
Upstream chages comes in a form of release notes in d/changelog, below,
also in the diff for upstream HISTORY file.

The change in the chroot sync procedure is described in the commit
message and - briefly - in d/syncfiles.pl.  See
https://salsa.debian.org/postfix-team/postfix-dev/-/commit/d4e1171ae6a79d36e7121bb0698eef3bd3f2498b
for the commit in question.

Thanks,

/mjt

diff -Nru postfix-3.10.3/debian/changelog postfix-3.10.4/debian/changelog
--- postfix-3.10.3/debian/changelog	2025-07-11 00:50:43.000000000 +0300
+++ postfix-3.10.4/debian/changelog	2025-08-22 09:51:46.000000000 +0300
@@ -1,3 +1,65 @@
+postfix (3.10.4-1~deb13u1) trixie; urgency=medium
+
+  * New upstream stable/bugfix version 3.10.4, with a handful of fixes.
+    From the upstream release notes:
+    - Fixes for postscreen(8):
+      * Bugfix (defect introduced: Postfix 2.2, date 20050203): after
+        detecting a lookup table change, and after starting a new
+        postscreen process, the old postscreen process logged an ENOTSOCK
+        error while attempting to accept a connection on a socket that
+        it was no longer listening on. This error was introduced first
+        in the multi_server skeleton code, and was five years later
+        duplicated in the event_server skeleton that was created for
+        postscreen. Problem reported by Florian Piekert.
+      * Bugfix (defect introduced: Postfix 2.8, date 20101230):
+        after detecting a cache table change and before starting a new
+        postscreen process, the old postscreen process did not close the
+        postscreen_cache_map, and therefore kept an exclusive lock that
+        could prevent a new postscreen process from starting. Problem
+        reported by Florian Piekert.
+    - Fixes for tlsproxy(8):
+      * Bugfix (defect introduced: Postfix 3.7): incorrect backwards
+        compatible support for the legacy configuration parameters
+        tlsproxy_client_level and tlsproxy_client_policy. This
+        disabled the tlsproxy TLS client role when a legacy parameter
+        was set (instead of the newer tlsproxy_client_security_level
+        or tlsproxy_client_policy_maps). Reported by John Doe,
+        diagnosed by Viktor Dukhovni.
+      * Bugfix (defect introduced: Postfix 3.4): with the TLS client role
+        disabled by configuration, the tlsproxy daemon dereferenced a
+        null pointer while handling a tlsproxy client request. Reported by
+        John Doe.
+    - Reducing process churn: Postfix daemons no longer automatically
+      restart after a btree:, dbm:, hash:, lmdb:, or sdbm: table file
+      modification time change, when they opened that table for writing.
+    - Portability: deleted an <openssl/engine.h> build dependency,
+      because the feature is being removed from OpenSSL, and Postfix
+      no longer needs it.
+    - Cleanup: with "tls_required_enable = yes", the Postfix SMTP client
+      will no longer maintain TLSRPT statistics for messages that contain
+      a "TLS-Required: no" header. This can prevent TLSRPT notifications
+      for TLSRPT notifications.
+    - Bugfix (defect introduced: Postfix 3.6, date 20200710): Postfix TLS
+      client code logged "Untrusted TLS connection" (wrong) instead of
+      "Trusted TLS connection" (right), for a new or resumed TLS session,
+      when a server offered a trusted (valid PKI trust chain) certificate
+      that did not match the expected server name pattern. Fix by Viktor
+      Dukhovni.
+  * d/gbp.conf: debian-branch=debian/trixie
+  * configure-instance.in: fix typo
+  * configure-instance.in: limit maxdepth=1 in /etc/ssl/certs dirs
+  * configure-instance.in: use home-grown file copy procedure to sync chroot
+    There are a few issues with using cp(1) to update files in chroot, -
+    a file should be copied even if the source date is *less* than the
+    target date (eg, if a package has been downgraded), which is not done
+    by `cp -u` (#1110704), a file should be copied atomically (copy+rename,
+    not truncate+copy), and care should be taken with extra attributes
+    (#1100100).  Use a simple perl-based script (using just perl-base)
+    to update files instead, which fixes all this stuff.
+    (Closes: #1100100, #1110704)
+
+ -- Michael Tokarev <mjt@tls.msk.ru>  Fri, 22 Aug 2025 09:51:46 +0300
+
 postfix (3.10.3-2) unstable; urgency=medium
 
   * d/changelog: fix wrongly formatted previous changelog entry (double email)
diff -Nru postfix-3.10.3/debian/configure-instance.in postfix-3.10.4/debian/configure-instance.in
--- postfix-3.10.3/debian/configure-instance.in	2025-04-24 10:52:30.000000000 +0300
+++ postfix-3.10.4/debian/configure-instance.in	2025-08-10 19:31:17.000000000 +0300
@@ -88,7 +88,7 @@
     [ -f /$file ] && cp="$cp /$file" || rm="$rm ./$file"
 done
 [ -n "$rm" ] && rm -f $rm
-[ -n "$cp" ] && cp -pLuf --parents -t . -- $cp
+[ -n "$cp" ] && /usr/lib/postfix/syncfiles.pl $queue_directory $cp
 
 if [ -z "$need_chroot" ]; then
     [ ! -d etc/ssl/certs ] || rm -rf etc/ssl/certs
@@ -135,7 +135,7 @@
 	(/*) [ -d $cadir ] || continue;;
 	(*) continue;;
     esac
-    case "$cadis_copied " in
+    case "$cadirs_copied " in
 	(*" $cadir "*) continue ;;
     esac
     cadirs_copied="$cadirs_copied $cadir"
@@ -158,11 +158,8 @@
 		[ -f "$caddr/$file" ] || rm -f "$file"
 	    done
     ) fi
-    mkdir -p $dest
-    ( cd $cadir
-	find -L . -name '[0-9a-f]*.[0-9]' -type f \
-	    -exec cp -pLuf -t $dest '{}' +
-    )
+    find -L $cadir -maxdepth 1 -name '[0-9a-f]*.[0-9]' -type f \
+	    -exec /usr/lib/postfix/syncfiles.pl $queue_directory '{}' +
 done
 
 mkdir -p usr/lib/sasl2 # https://bugs.debian.org/426338
diff -Nru postfix-3.10.3/debian/gbp.conf postfix-3.10.4/debian/gbp.conf
--- postfix-3.10.3/debian/gbp.conf	2025-04-24 10:52:30.000000000 +0300
+++ postfix-3.10.4/debian/gbp.conf	2025-08-22 09:50:46.000000000 +0300
@@ -2,6 +2,6 @@
 sign-tags = True
 pristine-tar = True
 upstream-branch = stable/v3.10
-debian-branch = debian/master
+debian-branch = debian/trixie
 debian-tag = v%(version)s
 upstream-tag = v%(version)s
diff -Nru postfix-3.10.3/debian/rules postfix-3.10.4/debian/rules
--- postfix-3.10.3/debian/rules	2025-06-18 11:38:50.000000000 +0300
+++ postfix-3.10.4/debian/rules	2025-08-22 09:04:44.000000000 +0300
@@ -239,6 +239,7 @@
 	sed 's/@MULTIARCH@/${DEB_HOST_MULTIARCH}/' debian/configure-instance.in > \
 		${base}${prvlibdir}/configure-instance.sh
 	chmod 0755 ${base}${prvlibdir}/configure-instance.sh
+	install -m0755 debian/syncfiles.pl ${base}${prvlibdir}/
 	echo ${package}:Provides=$(if $(filter ${DEB_VENDOR},Ubuntu),default-mta) \
 		>> debian/${package}.substvars
 	install -m0644 debian/postfix.ufw.profile -DT ${base}/etc/ufw/applications.d/postfix
diff -Nru postfix-3.10.3/debian/syncfiles.pl postfix-3.10.4/debian/syncfiles.pl
--- postfix-3.10.3/debian/syncfiles.pl	1970-01-01 03:00:00.000000000 +0300
+++ postfix-3.10.4/debian/syncfiles.pl	2025-08-10 19:06:15.000000000 +0300
@@ -0,0 +1,67 @@
+#! /usr/bin/perl -W
+#
+# Update a set of files in the given chroot dir.
+# Decision to update is based on file size and date, -
+# if any of these don't match, whole file is copied
+# to a temp file and renamed into place.
+# In the destination, files are copied with full path.
+# Only regular files (or symlinks to regular files)
+# are copied.
+
+use strict;
+use Fcntl qw(O_RDONLY O_WRONLY O_EXCL O_CREAT S_IMODE S_ISREG);
+use Errno qw(EEXIST ENOENT);
+
+my $dest = shift @ARGV;
+
+-d "$dest" or die "not a directory: $dest\n";
+
+foreach my $snm (@ARGV) {
+
+  sysopen SRC, $snm, O_RDONLY
+    and my @sst = stat SRC
+      or die "unable to open $snm: $!\n";
+
+  my $dnm = "$dest/$snm";
+  if (my @dst = stat $dnm) {
+    next if $sst[7] == $dst[7] && $sst[9] == $dst[9];
+  }
+
+  die "$snm: not a regular file\n"
+    unless S_ISREG($sst[2]);
+
+  print "updating $snm => $dnm\n";
+
+  my $dtnm = "$dnm.tmp";
+  unlink "$dtnm";
+
+  while (!sysopen DST, $dtnm, O_WRONLY|O_EXCL|O_CREAT, 0600) {
+    $! == ENOENT or die "unable to create $dtnm: $!\n";
+    my @c = split /\/+/, $snm;
+    pop @c; # all but last component
+    my $dd = $dest;
+    foreach my $c (@c) {
+      $dd .= '/' . $c;
+      unless (mkdir $dd, 0755) {
+        die "unable to mkdir $dd: $!" unless $! == EEXIST;
+      }
+    }
+  }
+
+  my $r;
+  while($r = sysread(SRC,$_,64*1024)) {
+    syswrite(DST,$_) or die "error writing to $dtnm: $!\n";
+  }
+  $r == 0 or die "error reading from $snm: $!\n";
+  close SRC;
+
+  utime $sst[9], $sst[9], \*DST;
+  chmod S_IMODE($sst[2]), \*DST;
+  chown $sst[4], $sst[5], \*DST;
+
+  close DST and rename $dtnm, $dnm
+    or die "error renaming $dtnm to $dnm: $!\n";
+
+}
+
+exit 0;
diff -Nru postfix-3.10.3/HISTORY postfix-3.10.4/HISTORY
--- postfix-3.10.3/HISTORY	2025-07-10 00:56:05.000000000 +0300
+++ postfix-3.10.4/HISTORY	2025-08-19 01:44:50.000000000 +0300
@@ -29054,3 +29054,71 @@
 	with "TLS-Required: no". This could result in unnecessary
 	failures. Fix by Viktor Dukhovni & Wietse. Files: smtp/smtp.h,
 	smtp/smtp_policy.c, smtp/smtp_connect.c.
+
+20250710
+
+	Bugfix (defect introduced: postfix-2.2, date 20050203):
+	after detecting a lookup table change, and after starting
+	a new postscreen process, the old postscreen process logged
+	an ENOTSOCK error while attempting to accept a connection
+	on a socket that it was no longer listening on. This error
+	was introduced first in the multi_server skeleton code, and
+	was five years later duplicated in the event_server skeleton
+	that was created for postscreen. Problem reported by Florian
+	Piekert. Files: master/multi_server.c, master/event_server.c.
+
+20250714
+
+	Deleted an <openssl/engine.h> dependency, because the feature is
+	being removed from OpenSSL, and Postfix no longer needs it. File:
+	posttls-finger/posttls-finger.c.
+
+20250716
+
+	Bugfix (defect introduced: Postfix 2.8, date 20101230):
+	after detecting a cache table change and before starting a
+	new postscreen process, the old postscreen process did not
+	close the postscreen_cache_map, and therefore kept an
+	exclusive lock that could prevent a new postscreen process
+	from starting. Problem reported by Florian Piekert. File:
+	postscreen/postscreen.c.
+
+20250717
+
+	Workaround: Postfix daemons no longer automatically restart
+	after a btree:, dbm:, hash:, lmdb:, or sdbm: table file
+	modification time change, when they opened that table for
+	writing. Files: util/dict.c, util/dict_db.c, util/dict_dbm.c,
+	util/dict_lmdb.c, util/dict_sdbm.c.
+
+20250730
+
+	Bugfix (defect introduced: Postfix 3.6, date 20200710):
+	Postfix TLS client code logged "Untrusted TLS connection"
+	(wrong) instead of "Trusted TLS connection" (right), for a
+	new or resumed TLS session, when a server offered a trusted
+	(valid PKI trust chain) certificate that did not match the
+	expected server name pattern. Viktor Dukhovni. Files:
+	tls/tls_client.c, tls/tls_verify.c.
+
+20250801
+
+	Bugfix (defect introduced: Postfix 3.7): incorrect backwards
+	compatible support for the legacy configuration parameters
+	tlsproxy_client_level and tlsproxy_client_policy. This
+	disabled the tlsproxy TLS client role when a legacy parameter
+	was set. Reported by John Doe, diagnosed by Viktor Dukhovni.
+	File: global/mail_params.h.
+
+	Bugfix (defect introduced: Postfix 3.4): with the TLS client
+	role disabled by configuration, the tlsproxy daemon
+	dereferenced a null pointer while handling a tlsproxy client
+	request. Reported by John Doe. File: tlsproxy/tlsproxy.c.
+
+20250803
+
+	Cleanup: with "tls_required_enable = yes", the Postfix SMTP
+	client will no longer maintain TLSRPT statistics for
+	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.
diff -Nru postfix-3.10.3/src/global/mail_params.h postfix-3.10.4/src/global/mail_params.h
--- postfix-3.10.3/src/global/mail_params.h	2025-02-15 23:05:04.000000000 +0300
+++ postfix-3.10.4/src/global/mail_params.h	2025-08-18 23:06:41.000000000 +0300
@@ -4171,7 +4171,9 @@
 /* Migrate an incorrect name. */
 #define OBS_TLSP_CLNT_LEVEL		"tlsproxy_client_level"
 #define VAR_TLSP_CLNT_LEVEL		"tlsproxy_client_security_level"
-#define DEF_TLSP_CLNT_LEVEL		"${" OBS_TLSP_CLNT_LEVEL ":$" VAR_SMTP_TLS_LEVEL "}"
+#define DEF_TLSP_CLNT_LEVEL		"${" OBS_TLSP_CLNT_LEVEL "?{$" \
+					OBS_TLSP_CLNT_LEVEL "}:{$" \
+					VAR_SMTP_TLS_LEVEL "}}"
 extern char *var_tlsp_clnt_level;
 
 #define VAR_TLSP_CLNT_PER_SITE		"tlsproxy_client_per_site"
@@ -4181,7 +4183,9 @@
 /* Migrate an incorrect name. */
 #define OBS_TLSP_CLNT_POLICY		"tlsproxy_client_policy"
 #define VAR_TLSP_CLNT_POLICY		"tlsproxy_client_policy_maps"
-#define DEF_TLSP_CLNT_POLICY		"${" OBS_TLSP_CLNT_POLICY ":$" VAR_SMTP_TLS_POLICY "}"
+#define DEF_TLSP_CLNT_POLICY		"${" OBS_TLSP_CLNT_POLICY "?{$" \
+					OBS_TLSP_CLNT_POLICY "}:{$" \
+					VAR_SMTP_TLS_POLICY "}}"
 extern char *var_tlsp_clnt_policy;
 
  /*
diff -Nru postfix-3.10.3/src/global/mail_version.h postfix-3.10.4/src/global/mail_version.h
--- postfix-3.10.3/src/global/mail_version.h	2025-07-10 00:54:38.000000000 +0300
+++ postfix-3.10.4/src/global/mail_version.h	2025-08-18 22:55:36.000000000 +0300
@@ -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	"20250710"
-#define MAIL_VERSION_NUMBER	"3.10.3"
+#define MAIL_RELEASE_DATE	"20250818"
+#define MAIL_VERSION_NUMBER	"3.10.4"
 
 #ifdef SNAPSHOT
 #define MAIL_VERSION_DATE	"-" MAIL_RELEASE_DATE
diff -Nru postfix-3.10.3/src/master/event_server.c postfix-3.10.4/src/master/event_server.c
--- postfix-3.10.3/src/master/event_server.c	2021-12-19 17:48:14.000000000 +0300
+++ postfix-3.10.4/src/master/event_server.c	2025-08-18 22:51:23.000000000 +0300
@@ -273,6 +273,7 @@
 static void (*event_server_pre_disconn) (VSTREAM *, char *, char **);
 static void (*event_server_slow_exit) (char *, char **);
 static int event_server_watchdog = 1000;
+static int event_server_drain_was_called = 0;
 
 /* event_server_exit - normal termination */
 
@@ -327,6 +328,9 @@
     const char *myname = "event_server_drain";
     int     fd;
 
+    if (event_server_drain_was_called)
+	return (0);
+
     switch (fork()) {
 	/* Try again later. */
     case -1:
@@ -343,6 +347,7 @@
 		msg_warn("%s: dup2(%d, %d): %m", myname, STDIN_FILENO, fd);
 	}
 	var_use_limit = 1;
+	event_server_drain_was_called = 1;
 	return (0);
 	/* Let the master start a new process. */
     default:
@@ -445,6 +450,9 @@
     int     time_left = -1;
     int     fd;
 
+    if (event_server_drain_was_called)
+	return;
+
     /*
      * Be prepared for accept() to fail because some other process already
      * got the connection (the number of processes competing for clients is
@@ -457,6 +465,8 @@
 
     if (event_server_pre_accept)
 	event_server_pre_accept(event_server_name, event_server_argv);
+    if (event_server_drain_was_called)
+	return;
     fd = LOCAL_ACCEPT(listen_fd);
     if (event_server_lock != 0
 	&& myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK,
@@ -483,6 +493,9 @@
     int     fd;
     HTABLE *attr = 0;
 
+    if (event_server_drain_was_called)
+	return;
+
     /*
      * Be prepared for accept() to fail because some other process already
      * got the connection (the number of processes competing for clients is
@@ -495,6 +508,8 @@
 
     if (event_server_pre_accept)
 	event_server_pre_accept(event_server_name, event_server_argv);
+    if (event_server_drain_was_called)
+	return;
     fd = pass_accept_attr(listen_fd, &attr);
     if (event_server_lock != 0
 	&& myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK,
@@ -520,6 +535,9 @@
     int     time_left = -1;
     int     fd;
 
+    if (event_server_drain_was_called)
+	return;
+
     /*
      * Be prepared for accept() to fail because some other process already
      * got the connection (the number of processes competing for clients is
@@ -532,6 +550,8 @@
 
     if (event_server_pre_accept)
 	event_server_pre_accept(event_server_name, event_server_argv);
+    if (event_server_drain_was_called)
+	return;
     fd = inet_accept(listen_fd);
     if (event_server_lock != 0
 	&& myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK,
diff -Nru postfix-3.10.3/src/master/multi_server.c postfix-3.10.4/src/master/multi_server.c
--- postfix-3.10.3/src/master/multi_server.c	2021-12-19 17:48:14.000000000 +0300
+++ postfix-3.10.4/src/master/multi_server.c	2025-08-18 22:51:23.000000000 +0300
@@ -260,6 +260,7 @@
 static int multi_server_in_flow_delay;
 static unsigned multi_server_generation;
 static void (*multi_server_pre_disconn) (VSTREAM *, char *, char **);
+static int multi_server_drain_was_called = 0;
 
 /* multi_server_exit - normal termination */
 
@@ -295,6 +296,9 @@
     const char *myname = "multi_server_drain";
     int     fd;
 
+    if (multi_server_drain_was_called)
+	return (0);
+
     switch (fork()) {
 	/* Try again later. */
     case -1:
@@ -311,6 +315,7 @@
 		msg_warn("%s: dup2(%d, %d): %m", myname, STDIN_FILENO, fd);
 	}
 	var_use_limit = 1;
+	multi_server_drain_was_called = 1;
 	return (0);
 	/* Let the master start a new process. */
     default:
@@ -429,6 +434,9 @@
     int     time_left = -1;
     int     fd;
 
+    if (multi_server_drain_was_called)
+	return;
+
     /*
      * Be prepared for accept() to fail because some other process already
      * got the connection (the number of processes competing for clients is
@@ -441,6 +449,8 @@
 
     if (multi_server_pre_accept)
 	multi_server_pre_accept(multi_server_name, multi_server_argv);
+    if (multi_server_drain_was_called)
+	return;
     fd = LOCAL_ACCEPT(listen_fd);
     if (multi_server_lock != 0
 	&& myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
@@ -467,6 +477,9 @@
     int     fd;
     HTABLE *attr = 0;
 
+    if (multi_server_drain_was_called)
+	return;
+
     /*
      * Be prepared for accept() to fail because some other process already
      * got the connection (the number of processes competing for clients is
@@ -479,6 +492,8 @@
 
     if (multi_server_pre_accept)
 	multi_server_pre_accept(multi_server_name, multi_server_argv);
+    if (multi_server_drain_was_called)
+	return;
     fd = pass_accept_attr(listen_fd, &attr);
     if (multi_server_lock != 0
 	&& myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
@@ -504,6 +519,9 @@
     int     time_left = -1;
     int     fd;
 
+    if (multi_server_drain_was_called)
+	return;
+
     /*
      * Be prepared for accept() to fail because some other process already
      * got the connection (the number of processes competing for clients is
@@ -516,6 +534,8 @@
 
     if (multi_server_pre_accept)
 	multi_server_pre_accept(multi_server_name, multi_server_argv);
+    if (multi_server_drain_was_called)
+	return;
     fd = inet_accept(listen_fd);
     if (multi_server_lock != 0
 	&& myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
diff -Nru postfix-3.10.3/src/postscreen/postscreen.c postfix-3.10.4/src/postscreen/postscreen.c
--- postfix-3.10.3/src/postscreen/postscreen.c	2023-09-15 17:56:57.000000000 +0300
+++ postfix-3.10.4/src/postscreen/postscreen.c	2025-08-18 23:02:01.000000000 +0300
@@ -996,7 +996,7 @@
     if (new_event_time >= last_event_time + 1
 	&& (name = dict_changed_name()) != 0) {
 	msg_info("table %s has changed - finishing in the background", name);
-	event_server_drain();
+	psc_drain(unused_name, unused_argv);
     } else {
 	last_event_time = new_event_time;
     }
diff -Nru postfix-3.10.3/src/posttls-finger/posttls-finger.c postfix-3.10.4/src/posttls-finger/posttls-finger.c
--- postfix-3.10.3/src/posttls-finger/posttls-finger.c	2024-10-11 01:15:23.000000000 +0300
+++ postfix-3.10.4/src/posttls-finger/posttls-finger.c	2025-08-18 22:56:40.000000000 +0300
@@ -414,7 +414,6 @@
 
 #ifdef USE_TLS
 #include <tls_proxy.h>
-#include <openssl/engine.h>
 #endif
 
  /*
diff -Nru postfix-3.10.3/src/smtp/Makefile.in postfix-3.10.4/src/smtp/Makefile.in
--- postfix-3.10.3/src/smtp/Makefile.in	2025-01-16 22:12:41.000000000 +0300
+++ postfix-3.10.4/src/smtp/Makefile.in	2025-08-19 01:01:52.000000000 +0300
@@ -113,6 +113,7 @@
 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
@@ -158,6 +159,7 @@
 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
@@ -304,6 +306,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/sock_addr.h
 smtp_key.o: ../../include/string_list.h
 smtp_key.o: ../../include/sys_defs.h
@@ -344,6 +347,7 @@
 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
@@ -384,6 +388,7 @@
 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
@@ -491,6 +496,7 @@
 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
@@ -530,6 +536,7 @@
 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
@@ -572,6 +579,7 @@
 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
@@ -613,6 +621,7 @@
 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
@@ -657,6 +666,7 @@
 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
@@ -697,6 +707,7 @@
 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
@@ -737,6 +748,7 @@
 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
@@ -778,6 +790,7 @@
 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
@@ -821,6 +834,7 @@
 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
@@ -864,6 +878,7 @@
 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
@@ -903,6 +918,7 @@
 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
diff -Nru postfix-3.10.3/src/smtp/smtp.h postfix-3.10.4/src/smtp/smtp.h
--- postfix-3.10.3/src/smtp/smtp.h	2025-07-10 00:22:54.000000000 +0300
+++ postfix-3.10.4/src/smtp/smtp.h	2025-08-19 01:01:52.000000000 +0300
@@ -32,6 +32,7 @@
 #include <tok822.h>
 #include <dsn_buf.h>
 #include <header_body_checks.h>
+#include <sendopts.h>
 
  /*
   * Postfix TLS library.
@@ -59,9 +60,6 @@
     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. */
@@ -69,18 +67,11 @@
     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); \
@@ -248,6 +239,12 @@
     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).
diff -Nru postfix-3.10.3/src/smtp/smtp_connect.c postfix-3.10.4/src/smtp/smtp_connect.c
--- postfix-3.10.3/src/smtp/smtp_connect.c	2025-07-10 00:22:54.000000000 +0300
+++ postfix-3.10.4/src/smtp/smtp_connect.c	2025-08-19 01:01:52.000000000 +0300
@@ -508,24 +508,6 @@
     SMTP_TLS_POLICY *tls = state->tls;
 
     /*
-     * If the message contains a "TLS-Required: no" header, update the
-     * iterator to limit the policy at TLS_LEV_MAY.
-     * 
-     * We must do this early to avoid possible failure if TLSA record lookups
-     * fail, or if TLSA records are found, but can't be activated because the
-     * security level has been reset to "may".
-     * 
-     * 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
-
-    /*
      * Determine the TLS level for this destination.
      */
     if (!smtp_tls_policy_cache_query(why, tls, iter)) {
@@ -976,9 +958,15 @@
 	 * level of "may" to "encrypt"? This would disable falling back to
 	 * plaintext, and could break interoperability with receivers that
 	 * crank up security up to 11.
+	 * 
+	 * 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
+	    && 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);
diff -Nru postfix-3.10.3/src/smtp/smtp_tls_policy.c postfix-3.10.4/src/smtp/smtp_tls_policy.c
--- postfix-3.10.3/src/smtp/smtp_tls_policy.c	2025-07-10 00:22:54.000000000 +0300
+++ postfix-3.10.4/src/smtp/smtp_tls_policy.c	2025-08-19 01:01:52.000000000 +0300
@@ -647,11 +647,18 @@
      * 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)
diff -Nru postfix-3.10.3/src/tls/tls_client.c postfix-3.10.4/src/tls/tls_client.c
--- postfix-3.10.3/src/tls/tls_client.c	2024-10-11 01:15:24.000000000 +0300
+++ postfix-3.10.4/src/tls/tls_client.c	2025-08-19 00:59:45.000000000 +0300
@@ -313,6 +313,7 @@
 static void verify_x509(TLS_SESS_STATE *TLScontext, X509 *peercert,
 			        const TLS_CLIENT_START_PROPS *props)
 {
+    int     x509_err = SSL_get_verify_result(TLScontext->con);
 
     /*
      * On exit both peer_CN and issuer_CN should be set.
@@ -324,7 +325,7 @@
      * Is the certificate trust chain trusted and matched?  Any required name
      * checks are now performed internally in OpenSSL.
      */
-    if (SSL_get_verify_result(TLScontext->con) == X509_V_OK) {
+    if (x509_err == X509_V_OK) {
 	TLScontext->peer_status |= TLS_CERT_FLAG_TRUSTED;
 	if (TLScontext->must_fail) {
 	    msg_panic("%s: cert valid despite trust init failure",
@@ -356,6 +357,13 @@
 		tls_dane_log(TLScontext);
 	    }
 	}
+    } else if (TLS_MUST_MATCH(TLScontext->level) &&
+	       x509_err == X509_V_ERR_HOSTNAME_MISMATCH) {
+	/*
+	 * If the only error is a hostname mismatch, the certificate must have
+	 * been trusted.
+	 */
+	TLScontext->peer_status |= TLS_CERT_FLAG_TRUSTED;
     }
 
     /*
diff -Nru postfix-3.10.3/src/tls/tls_verify.c postfix-3.10.4/src/tls/tls_verify.c
--- postfix-3.10.3/src/tls/tls_verify.c	2025-02-17 19:53:16.000000000 +0300
+++ postfix-3.10.4/src/tls/tls_verify.c	2025-08-19 00:59:45.000000000 +0300
@@ -120,12 +120,26 @@
 
 /* update_error_state - safely stash away error state */
 
-static void update_error_state(TLS_SESS_STATE *TLScontext, int depth,
-			               X509 *errorcert, int errorcode)
+static void update_error_state(X509_STORE_CTX *ctx, TLS_SESS_STATE *TLScontext,
+			          int depth, X509 *errorcert, int errorcode)
 {
-    /* No news is good news */
-    if (TLScontext->errordepth >= 0 && TLScontext->errordepth <= depth)
-	return;
+
+    /*
+     * Report the error that is closest to the leaf certificate, any errors
+     * higher up the chain are immaterial until the "inner" errors are fixed.
+     * 
+     * We special-case "X509_V_ERR_HOSTNAME_MISMATCH" (at depth 0) in order to
+     * distinguish between untrusted certificates and trusted certificates
+     * with a hostname mismatch.  Any other error has a higher priority.
+     */
+    if (TLScontext->errordepth >= 0) {
+	if ((TLScontext->errordepth <= depth &&
+	     TLScontext->errorcode != X509_V_ERR_HOSTNAME_MISMATCH) ||
+	    errorcode == X509_V_ERR_HOSTNAME_MISMATCH) {
+	    X509_STORE_CTX_set_error(ctx, TLScontext->errorcode);
+	    return;
+	}
+    }
 
     /*
      * The certificate pointer is stable during the verification callback,
@@ -179,12 +193,12 @@
     if (TLScontext->must_fail) {
 	if (depth == 0) {
 	    X509_STORE_CTX_set_error(ctx, err = X509_V_ERR_UNSPECIFIED);
-	    update_error_state(TLScontext, depth, cert, err);
+	    update_error_state(ctx, TLScontext, depth, cert, err);
 	}
 	return (1);
     }
     if (ok == 0)
-	update_error_state(TLScontext, depth, cert, err);
+	update_error_state(ctx, TLScontext, depth, cert, err);
 
     if (TLScontext->log_mask & TLS_LOG_VERBOSE) {
 	if (cert) {
diff -Nru postfix-3.10.3/src/tlsproxy/tlsproxy.c postfix-3.10.4/src/tlsproxy/tlsproxy.c
--- postfix-3.10.3/src/tlsproxy/tlsproxy.c	2024-11-13 19:22:42.000000000 +0300
+++ postfix-3.10.4/src/tlsproxy/tlsproxy.c	2025-08-18 23:06:41.000000000 +0300
@@ -1267,6 +1267,12 @@
     init_buf = vstring_alloc(100);
     init_key = tls_proxy_client_init_serialize(attr_print_plain, init_buf,
 					       init_props);
+#define TLSP_CLIENT_INIT_RETURN(retval) do { \
+	vstring_free(init_buf); \
+	vstring_free(param_buf); \
+	return (retval); \
+    } while (0)
+
     if (tlsp_pre_jail_done == 0) {
 	if (tlsp_pre_jail_client_param_key == 0
 	    || tlsp_pre_jail_client_init_key == 0) {
@@ -1284,9 +1290,12 @@
      * TLS_APPL_STATE instance; this makes a mismatch of TLS_CLIENT_PARAMS
      * settings problematic.
      */
-    if (tlsp_pre_jail_done
-	&& !been_here_fixed(tlsp_params_mismatch_filter, param_key)
-	&& strcmp(tlsp_pre_jail_client_param_key, param_key) != 0) {
+    else if (tlsp_pre_jail_client_param_key == 0
+	     || tlsp_pre_jail_client_init_key == 0) {
+	msg_warn("TLS client role is disabled by configuration");
+	TLSP_CLIENT_INIT_RETURN(0);
+    } else if (!been_here_fixed(tlsp_params_mismatch_filter, param_key)
+	       && strcmp(tlsp_pre_jail_client_param_key, param_key) != 0) {
 	msg_warn("request from tlsproxy client with unexpected settings");
 	tlsp_log_config_diff(tlsp_pre_jail_client_param_key, param_key);
 	log_hints = 1;
@@ -1361,9 +1370,7 @@
 			 SSL_MODE_ENABLE_PARTIAL_WRITE
 			 | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
     }
-    vstring_free(init_buf);
-    vstring_free(param_buf);
-    return (appl_state);
+    TLSP_CLIENT_INIT_RETURN(appl_state);
 }
 
 /* tlsp_close_event - pre-handshake plaintext-client close event */
@@ -1497,6 +1504,7 @@
 				TLSP_INIT_TIMEOUT, (void *) state);
 	return;
     } else {
+	state->flags |= TLSP_FLAG_DO_HANDSHAKE;
 	tlsp_request_read_event(plaintext_fd, tlsp_get_fd_event,
 				TLSP_INIT_TIMEOUT, (void *) state);
 	return;
diff -Nru postfix-3.10.3/src/tlsproxy/tlsproxy_state.c postfix-3.10.4/src/tlsproxy/tlsproxy_state.c
--- postfix-3.10.3/src/tlsproxy/tlsproxy_state.c	2019-02-09 01:12:13.000000000 +0300
+++ postfix-3.10.4/src/tlsproxy/tlsproxy_state.c	2025-08-18 23:06:41.000000000 +0300
@@ -105,7 +105,7 @@
 {
     TLSP_STATE *state = (TLSP_STATE *) mymalloc(sizeof(*state));
 
-    state->flags = TLSP_FLAG_DO_HANDSHAKE;
+    state->flags = 0;
     state->service = mystrdup(service);
     state->plaintext_stream = plaintext_stream;
     state->plaintext_buf = 0;
diff -Nru postfix-3.10.3/src/util/dict.c postfix-3.10.4/src/util/dict.c
--- postfix-3.10.3/src/util/dict.c	2022-05-01 20:01:35.000000000 +0300
+++ postfix-3.10.4/src/util/dict.c	2025-08-18 23:02:53.000000000 +0300
@@ -147,8 +147,8 @@
 /* .IP "char *context"
 /*	Application context from the caller.
 /* .PP
-/*	dict_changed_name() returns non-zero when any dictionary needs to
-/*	be re-opened because it has changed or because it was unlinked.
+/*	dict_changed_name() returns non-zero when any dictionary is
+/*	opened read-only and has changed, or because it was unlinked.
 /*	A non-zero result is the name of a changed dictionary.
 /*
 /*	dict_load_file_xt() reads name-value entries from the named file.
@@ -601,11 +601,12 @@
 	dict = ((DICT_NODE *) h->value)->dict;
 	if (dict->stat_fd < 0)			/* not file-based */
 	    continue;
-	if (dict->mtime == 0)			/* not bloody likely */
-	    msg_warn("%s: table %s: null time stamp", myname, h->key);
+	if (dict->mtime < 0)			/* not bloody likely */
+	    msg_warn("%s: table %s: negative time stamp", myname, h->key);
 	if (fstat(dict->stat_fd, &st) < 0)
 	    msg_fatal("%s: fstat: %m", myname);
 	if (((dict->flags & DICT_FLAG_MULTI_WRITER) == 0
+	     && dict->mtime > 0
 	     && st.st_mtime != dict->mtime)
 	    || st.st_nlink == 0)
 	    status = h->key;
diff -Nru postfix-3.10.3/src/util/dict_db.c postfix-3.10.4/src/util/dict_db.c
--- postfix-3.10.3/src/util/dict_db.c	2022-02-02 20:43:27.000000000 +0300
+++ postfix-3.10.4/src/util/dict_db.c	2025-08-18 23:02:53.000000000 +0300
@@ -789,7 +789,8 @@
     dict_db->dict.stat_fd = dbfd;
     if (fstat(dict_db->dict.stat_fd, &st) < 0)
 	msg_fatal("dict_db_open: fstat: %m");
-    dict_db->dict.mtime = st.st_mtime;
+    if (open_flags == O_RDONLY)
+	dict_db->dict.mtime = st.st_mtime;
     dict_db->dict.owner.uid = st.st_uid;
     dict_db->dict.owner.status = (st.st_uid != 0);
 
diff -Nru postfix-3.10.3/src/util/dict_dbm.c postfix-3.10.4/src/util/dict_dbm.c
--- postfix-3.10.3/src/util/dict_dbm.c	2014-11-17 21:28:01.000000000 +0300
+++ postfix-3.10.4/src/util/dict_dbm.c	2025-08-18 23:02:53.000000000 +0300
@@ -472,7 +472,8 @@
 	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");
-    dict_dbm->dict.mtime = st.st_mtime;
+    if (open_mode == 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);
 
diff -Nru postfix-3.10.3/src/util/dict_lmdb.c postfix-3.10.4/src/util/dict_lmdb.c
--- postfix-3.10.3/src/util/dict_lmdb.c	2021-06-04 23:42:49.000000000 +0300
+++ postfix-3.10.4/src/util/dict_lmdb.c	2025-08-18 23:02:53.000000000 +0300
@@ -653,7 +653,8 @@
 	msg_fatal("dict_lmdb_open: fstat: %m");
     dict_lmdb->dict.lock_fd = dict_lmdb->dict.stat_fd = db_fd;
     dict_lmdb->dict.lock_type = MYFLOCK_STYLE_FCNTL;
-    dict_lmdb->dict.mtime = st.st_mtime;
+    if (open_flags == O_RDONLY)
+	dict_lmdb->dict.mtime = st.st_mtime;
     dict_lmdb->dict.owner.uid = st.st_uid;
     dict_lmdb->dict.owner.status = (st.st_uid != 0);
 
diff -Nru postfix-3.10.3/src/util/dict_sdbm.c postfix-3.10.4/src/util/dict_sdbm.c
--- postfix-3.10.3/src/util/dict_sdbm.c	2012-01-25 04:41:08.000000000 +0400
+++ postfix-3.10.4/src/util/dict_sdbm.c	2025-08-18 23:02:53.000000000 +0300
@@ -449,7 +449,8 @@
     dict_sdbm->dict.stat_fd = sdbm_pagfno(dbm);
     if (fstat(dict_sdbm->dict.stat_fd, &st) < 0)
 	msg_fatal("dict_sdbm_open: fstat: %m");
-    dict_sdbm->dict.mtime = st.st_mtime;
+    if (open_flags == O_RDONLY)
+	dict_sdbm->dict.mtime = st.st_mtime;
     dict_sdbm->dict.owner.uid = st.st_uid;
     dict_sdbm->dict.owner.status = (st.st_uid != 0);
 

--- End Message ---
--- Begin Message ---
Package: release.debian.org
Version: 13.1

Hi,

Each of the updates referenced by these requests was included in
today's 13.1 point release for trixie.

Regards,

Adam

--- End Message ---

Reply to: