From: Wietse Z Venema
Date: Fri, 6 Jun 2025 05:00:00 +0000 (-0500)
Subject: postfix-3.11-20250606
X-Git-Tag: v3.11.0-RC1~43
X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=32475272ffd1d92ecb03f60bf445ef17669205b7;p=thirdparty%2Fpostfix.git
postfix-3.11-20250606
---
diff --git a/postfix/.indent.pro b/postfix/.indent.pro
index f1671a6ec..86522dfde 100644
--- a/postfix/.indent.pro
+++ b/postfix/.indent.pro
@@ -248,6 +248,7 @@
-TNBBIO
-TNVTABLE_INFO
-TOPTIONS
+-TOSSL_DGST
-TPCF_DBMS_INFO
-TPCF_DEPR_PARAM_INFO
-TPCF_EVAL_CTX
diff --git a/postfix/HISTORY b/postfix/HISTORY
index 489e0f9e9..13b6b27d6 100644
--- a/postfix/HISTORY
+++ b/postfix/HISTORY
@@ -29031,7 +29031,7 @@ Apologies for any names omitted.
causing information to become garbled. Fix by Michael
Tokarev. File: postconf/postconf_edit.c.
-20259317
+20250317
Documentation: added text to clarify the difference between
SMTP connection reuse and TLS session resumption, and that
@@ -29095,10 +29095,102 @@ Apologies for any names omitted.
20250418
- Code health: added unit tests for connection address and
+ Code health: added 16 unit tests for connection address and
port information received through haproxy or postscreen,
and improved error handling. Files: smtpd/smtpd_peer.c,
smtpd/smtpd_haproxy.c, smtpd/smtpd_peer_test.c.
Unit tests for 'direct' connections are deferred pending
support to mock or intercept system library function calls.
+
+20250419
+
+ Documentation: Postfix LMDB locking protocol description.
+ File: proto/lmdb_table.
+
+20250504
+
+ Logging: the memcache client truncated a memcached server
+ error message too aggressively. File: global/dict_memcache.c.
+
+ Code health: the dict_cache module did not expose a database
+ error to the caller. Files: util/dict_cache.[hc].
+
+ Code health: the verify(8) daemon now replies with 'address
+ verification status unavailable' when cache lookup fails
+ due to a database error, instead of replying with 'address
+ verification in progress'. File: verify/verify.c.
+
+ Code health: the verify(8) daemon no longer schedules an
+ address verification probe after a cache lookup for that
+ address failed due to a database error. File: verify/verify.c.
+
+20250523
+
+ Documentation: load balancer workaround for Postfix <= 3.9.
+ Files: proto/mysql_table, proto/pgsql_table.
+
+20250425
+
+ Documentation: TLSRPT_README typofix by Paul Menzel. File:
+ proto/TLSRPT_README.html.
+
+20250509
+
+ Documentation: in "enable_idna2003_compatibility" descriptions,
+ confused zeta with final sigma. Geert Hendrickx. Files:
+ proto/SMTPUTF8_README, proto/postconf.proto.
+
+ Feature: specify "key_digest = name-of-openssl-digest" to
+ run memcache lookup keys through the named OpenSSL digest
+ and convert the result to lowercase hexadecimal characters,
+ after processing the key_format feature. This prevents a
+ database access error when keys may exceed the memcache
+ server's key length limit (usually, 250 bytes). Files:
+
+20250523
+
+ Workaround: tweaked the timeout setting in postconf.proto
+ javascript. File: proto/postconf.html.prolog
+
+20250525
+
+ Code health: don't allow the postmap or postalias "-i"
+ option together with one of the (-d, -q, or -s) options on
+ the command line. Files: postmap/postmap.c, postalias/postalias.c,
+ postmap/mode_conflict_test.*, postalias/mode_conflict_test.*.
+
+ Testing: some postalias and postmap tests depended on the
+ installed main.cf file. Files: postalias/Makefile.in,
+ postmap/Makefile.in.
+
+ Testing: 'nosleep' preload module to eliminate the delay
+ after logging a fatal error and before terminating a program.
+ Files: testing/Makefile.in, testing/nosleep.c,
+ postalias/Makefile.in, postmap/Makefile.in
+
+20250526
+
+ Bugfix (defect introduced: Postfix 0.7.0, date 19990118):
+ postmap and postalias supported "-i" incremental updates
+ only for databases that support "bulk" create. With other
+ databases, the "-i" option was rejected with a misleading
+ error message "no 'map create' support". File: util/mkmap_open.c.
+
+ Usability: improved error message when a CDB table refuses
+ a delete or incremental update request (it complained about
+ some obscure POSIX open() flags). File: util/dict_cdb.c.
+
+ Cleanup: remove unnecessary newline characters in debug
+ logging. File: util/dict_db.c.
+
+ Debugging: added debug logging to the myflock() function.
+ File: util/myflock.c.
+
+20250601
+
+ Changed the default smtp_tlsrpt_skip_reused_handshakes
+ setting from "yes" to "no". The new default is enabled with
+ compatibility level >= 3.11. Files: smtp/smtp_tlsrpt.c,
+ global/mail_params.[hc], proto/COMPATIBILITY_README.html.
+ proto/memcache_table, global/dict_memcache.c, util/hex_code.[hc].
diff --git a/postfix/Makefile.in b/postfix/Makefile.in
index 12789cad7..fc7be7386 100644
--- a/postfix/Makefile.in
+++ b/postfix/Makefile.in
@@ -12,7 +12,7 @@ DIRS = src/util src/global src/dns src/tls src/xsasl src/master src/milter \
src/postsuper src/qmqpd src/spawn src/flush src/verify \
src/virtual src/proxymap src/anvil src/scache src/discard src/tlsmgr \
src/postmulti src/postscreen src/dnsblog src/tlsproxy \
- src/posttls-finger src/postlogd
+ src/posttls-finger src/postlogd src/testing
MANDIRS = proto man html
LIBEXEC = libexec/post-install libexec/postfix-script libexec/postfix-wrapper \
libexec/postmulti-script libexec/postfix-tls-script
diff --git a/postfix/README_FILES/COMPATIBILITY_README b/postfix/README_FILES/COMPATIBILITY_README
index aa9e7f6a7..e06ef17eb 100644
--- a/postfix/README_FILES/COMPATIBILITY_README
+++ b/postfix/README_FILES/COMPATIBILITY_README
@@ -57,6 +57,11 @@ Logged with compatibility_level < 3.6:
* Using backwards-compatible default setting respectful_logging=no
+Logged with compatibility_level < 3.11:
+
+ * using backwards-compatible default setting
+ smtp_tlsrpt_skip_reused_handshakes=yes
+
If such a message is logged in the context of a legitimate request, the system
administrator should make the backwards-compatible setting permanent in main.cf
or master.cf, as detailed in the sections that follow.
@@ -72,9 +77,9 @@ could result in unexpected non-delivery of email after Postfix is updated from
an older version. The backwards-compatibility safety net is designed to prevent
such surprises.
-As long as the append_dot_mydomain parameter is left at its implicit default
-value, and the compatibility_level setting is less than 1, Postfix may log one
-of the following messages:
+As long as the append_dot_mydomain parameter is left unspecified at its
+implicit default value, and the compatibility_level setting is less than 1,
+Postfix may log one of the following messages:
* Messages about missing "localhost" in mydestination or other address class:
@@ -110,9 +115,9 @@ the chroot feature enabled after updating Postfix from an older version. The
backwards-compatibility safety net is designed allow the administrator to
choose if they want to keep the old behavior.
-As long as a master.cf chroot field is left at its implicit default value, and
-the compatibility_level setting is less than 1, Postfix may log the following
-message while it reads the master.cf file:
+As long as a master.cf chroot field is left unspecified at its implicit default
+value, and the compatibility_level setting is less than 1, Postfix may log the
+following message while it reads the master.cf file:
postfix/master[27664]: /etc/postfix/master.cf: line 72: using
backwards-compatible default setting chroot=y
@@ -137,8 +142,8 @@ denied' errors after Postfix is updated from an older Postfix version. The
backwards-compatibility safety net is designed to prevent such surprises.
When the compatibility_level less than 1, and the smtpd_relay_restrictions
-parameter is left at its implicit default setting, Postfix may log the
-following message:
+parameter is left unspecified at its implicit default setting, Postfix may log
+the following message:
postfix/smtpd[38463]: using backwards-compatible default setting
"smtpd_relay_restrictions = (empty)" to avoid "Relay access
@@ -160,10 +165,10 @@ that don't request SMTPUTF8 support, after Postfix is updated from an older
version. The backwards-compatibility safety net is designed to prevent such
surprises.
-As long as the smtputf8_enable parameter is left at its implicit default value,
-and the compatibility_level setting is less than 1, Postfix logs a warning each
-time an SMTP command uses a non-ASCII address localpart without requesting
-SMTPUTF8 support:
+As long as the smtputf8_enable parameter is left unspecified at its implicit
+default value, and the compatibility_level setting is less than 1, Postfix logs
+a warning each time an SMTP command uses a non-ASCII address localpart without
+requesting SMTPUTF8 support:
postfix/smtpd[27560]: using backwards-compatible default setting
smtputf8_enable=no to accept non-ASCII sender address
@@ -188,9 +193,9 @@ could cause unexpected 'access denied' errors after Postfix is updated from an
older version. The backwards-compatibility safety net is designed to prevent
such surprises.
-As long as the mynetworks and mynetworks_style parameters are left at their
-implicit default values, and the compatibility_level setting is less than 2,
-the Postfix SMTP server may log one of the following messages:
+As long as the mynetworks and mynetworks_style parameters are left unspecified
+at their implicit default values, and the compatibility_level setting is less
+than 2, the Postfix SMTP server may log one of the following messages:
postfix/smtpd[17375]: using backwards-compatible default setting
mynetworks_style=subnet to permit request from client
@@ -214,9 +219,9 @@ value. This could result in unexpected 'Relay access denied' errors or ETRN
errors after Postfix is updated from an older version. The backwards-
compatibility safety net is designed to prevent such surprises.
-As long as the relay_domains parameter is left at its implicit default value,
-and the compatibility_level setting is less than 2, Postfix may log one of the
-following messages.
+As long as the relay_domains parameter is left unspecified at its implicit
+default value, and the compatibility_level setting is less than 2, Postfix may
+log one of the following messages.
* Messages about accepting mail for a remote domain:
@@ -263,10 +268,10 @@ deprecated) setting, you should consider switching to "sha256". This will
require updating any associated lookup table keys with the "sha256" digests of
the expected client certificate or public key.
-As long as the smtpd_tls_fingerprint_digest parameter is left at its implicit
-default value, and the compatibility_level setting is less than 3.6, Postfix
-logs a warning each time a client certificate or public key fingerprint is
-(potentially) used for access control:
+As long as the smtpd_tls_fingerprint_digest parameter is left unspecified at
+its implicit default value, and the compatibility_level setting is less than
+3.6, Postfix logs a warning each time a client certificate or public key
+fingerprint is (potentially) used for access control:
postfix/smtpd[27560]: using backwards-compatible default setting
smtpd_tls_fingerprint_digest=md5 to compute certificate fingerprints
@@ -299,10 +304,10 @@ table to specify matching "sha256" digests of the expected server certificates
or public keys.
As long as the smtp_tls_fingerprint_digest (or LMTP equivalent) parameter is
-left at its implicit default value, and the compatibility_level setting is less
-than 3.6, Postfix logs a warning each time the "fingerprint" security level is
-used to specify matching "md5" digests of trusted server certificates or public
-keys:
+left unspecified at its implicit default value, and the compatibility_level
+setting is less than 3.6, Postfix logs a warning each time the "fingerprint"
+security level is used to specify matching "md5" digests of trusted server
+certificates or public keys:
postfix/smtp[27560]: using backwards-compatible default setting
smtp_tls_fingerprint_digest=md5 to compute certificate fingerprints
@@ -332,8 +337,8 @@ behavior.
To maintain compatibility with earlier versions, Postfix will keep evaluating
smtpd_recipient_restrictions before smtpd_relay_restrictions, as long as the
compatibility_level is less than 3.6, and the
-smtpd_relay_before_recipient_restrictions parameter is left at its implicit
-default setting. As a reminder, Postfix may log the following message:
+smtpd_relay_before_recipient_restrictions parameter is left unspecified at its
+implicit default setting. As a reminder, Postfix may log the following message:
postfix/smtpd[54696]: using backwards-compatible default setting
smtpd_relay_before_recipient_restrictions=no to reject recipient
@@ -356,10 +361,10 @@ backwards-compatible default values, the changes in logging could affect
logfile analysis tools.
To avoid breaking existing logfile analysis tools, Postfix will keep logging
-the deprecated form, as long as the respectful_logging parameter is left at its
-implicit default value, and the compatibility_level setting is less than 3.6.
-As a reminder, Postfix may log the following when a remote SMTP client is
-allowlisted or denylisted:
+the deprecated form, as long as the respectful_logging parameter is left
+unspecified at its implicit default value, and the compatibility_level setting
+is less than 3.6. As a reminder, Postfix may log the following when a remote
+SMTP client is allowlisted or denylisted:
postfix/postscreen[22642]: Using backwards-compatible default setting
respectful_logging=no for client [address]:port
@@ -371,6 +376,29 @@ administrator should make the backwards-compatible setting "respectful_logging
# ppoossttccoonnff ""rreessppeeccttffuull__llooggggiinngg == nnoo""
# ppoossttffiixx rreellooaadd
+UUssiinngg bbaacckkwwaarrddss--ccoommppaattiibbllee ddeeffaauulltt sseettttiinngg
+ssmmttpp__ttllssrrpptt__sskkiipp__rreeuusseedd__hhaannddsshhaakkeess==yyeess
+
+Postfix version 3.11 changes the default value for
+smtp_tlsrpt_skip_reused_handshakes from "yes" to "no". The backwards-
+compatibility safety net is designed to prevent an unexpected change in
+reporting behavior when Postfix is updated from an older version.
+
+As long as the smtp_tlsrpt_skip_reused_handshakes parameter is left unspecified
+at its implicit default value, and the compatibility_level setting is less than
+3.11, Postfix will log a reminder that it is using the backwards-compatible
+default:
+
+ postfix/smtp[388157] using backwards-compatible default setting
+ smtp_tlsrpt_skip_reused_handshakes=yes
+
+To keep the old default setting, the system administrator should make the
+backwards-compatible setting "smtp_tlsrpt_skip_reused_handshakes = yes"
+permanent in main.cf:
+
+ # ppoossttccoonnff ssmmttpp__ttllssrrpptt__sskkiipp__rreeuusseedd__hhaannddsshhaakkeess==yyeess
+ # ppoossttffiixx rreellooaadd
+
TTuurrnniinngg ooffff tthhee bbaacckkwwaarrddss--ccoommppaattiibbiilliittyy ssaaffeettyy nneett
Backwards compatibility is turned off by updating the compatibility_level
diff --git a/postfix/README_FILES/SMTPUTF8_README b/postfix/README_FILES/SMTPUTF8_README
index 0b07374b8..42170970f 100644
--- a/postfix/README_FILES/SMTPUTF8_README
+++ b/postfix/README_FILES/SMTPUTF8_README
@@ -278,8 +278,8 @@ current versions of the Firefox and Chrome web browsers. Specify
"enable_idna2003_compatibility = yes" to get the historical behavior.
This affects the conversion of domain names that contain for example the German
-sz (Ã) and the Greek zeta (Ï). See https://unicode.org/cldr/utility/idna.jsp
-for more examples.
+sz (Ã) and the Greek (final) sigma (Ï). See https://unicode.org/cldr/utility/
+idna.jsp for more examples.
CCrreeddiittss
diff --git a/postfix/README_FILES/TLSRPT_README b/postfix/README_FILES/TLSRPT_README
index 4a2e88f35..e4a00ee81 100644
--- a/postfix/README_FILES/TLSRPT_README
+++ b/postfix/README_FILES/TLSRPT_README
@@ -188,11 +188,11 @@ Notes:
Untrusted TTLLSS ccoonnnneeccttiioonn rreeuusseedd to mail.example.com[ipaddr]:25:
TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
- * By default, Postfix does not report the TLSRPT status for a TLS handshake
- that reuses a previously-negotiated TLS session (there would be no new
- information to report). Specify "smtp_tlsrpt_skip_reused_handshakes = no"
- to report the TLSRPT status for all TLS handshakes. This may be useful for
- troubleshooting.
+ * With TLSRPT enabled, the Postfix SMTP client reports the TLSRPT status for
+ all TLS handshakes (the default as of Postfix 3.11). Specify
+ "smtp_tlsrpt_skip_reused_handshakes = yes" (the default with Postfix 3.10)
+ to skip reporting TLS handshakes that reuse a previously-negotiated TLS
+ session as there would be no new information to report.
* Postfix logging for certificate verification failures may differ between
new or reused TLS sessions.
@@ -256,7 +256,7 @@ Options:
MMTTAA--SSTTSS SSuuppppoorrtt vviiaa ssmmttpp__ttllss__ppoolliiccyy__mmaappss
-Postfix supports MTA-STS though an smtp_tls_policy_maps policy plugin, which
+Postfix supports MTA-STS through an smtp_tls_policy_maps policy plugin, which
replies with a TLS security level and name=value attributes with certificate
matching requirements. Postfix 3.10 and later extend the policy plugin response
with additional name=value attributes that are needed for TLSRPT.
diff --git a/postfix/html/COMPATIBILITY_README.html b/postfix/html/COMPATIBILITY_README.html
index f2cf4c2d5..29446db7e 100644
--- a/postfix/html/COMPATIBILITY_README.html
+++ b/postfix/html/COMPATIBILITY_README.html
@@ -102,6 +102,17 @@ default setting respectful_logging=no
+ Logged with compatibility_level < 3.11:
+
+
+
+
+
If such a message is logged in the context of a legitimate
request, the system administrator should make the backwards-compatible
setting permanent in main.cf or master.cf, as detailed in the
@@ -120,7 +131,8 @@ to "no". This could result in unexpected non-delivery of email after
Postfix is updated from an older version. The backwards-compatibility
safety net is designed to prevent such surprises.
- As long as the append_dot_mydomain parameter is left at
+
As long as the append_dot_mydomain parameter is left unspecified
+at
its implicit default value, and the compatibility_level setting is
less than 1, Postfix may log one of the following messages:
@@ -178,7 +190,7 @@ after updating Postfix from an older version. The backwards-compatibility
safety net is designed allow the administrator to choose if they
want to keep the old behavior.
- As long as a master.cf chroot field is left at its
+
As long as a master.cf chroot field is left unspecified at its
implicit default value, and the compatibility_level setting
is less than 1, Postfix may log the following message while it
reads the master.cf file:
@@ -218,7 +230,8 @@ from an older Postfix version. The backwards-compatibility safety
net is designed to prevent such surprises.
When the compatibility_level less than 1, and the
-smtpd_relay_restrictions parameter is left at its implicit default
+smtpd_relay_restrictions parameter is left unspecified at its
+implicit default
setting, Postfix may log the following message:
@@ -250,7 +263,8 @@ addresses from clients that don't request SMTPUTF8 support, after
Postfix is updated from an older version. The backwards-compatibility
safety net is designed to prevent such surprises.
- As long as the smtputf8_enable parameter is left at its implicit
+
As long as the smtputf8_enable parameter is left unspecified
+at its implicit
default value, and the compatibility_level setting is
less than 1, Postfix logs a warning each time an SMTP command uses a
non-ASCII address localpart without requesting SMTPUTF8 support:
@@ -293,7 +307,8 @@ Postfix is updated from an older version. The backwards-compatibility
safety net is designed to prevent such surprises.
As long as the mynetworks and mynetworks_style parameters are
-left at their implicit default values, and the compatibility_level
+left unspecified at their implicit default values, and the
+compatibility_level
setting is less than 2, the Postfix SMTP server may log one of the
following messages:
@@ -333,7 +348,8 @@ denied' errors or ETRN errors after Postfix is updated from an older
version. The backwards-compatibility safety net is designed to
prevent such surprises.
- As long as the relay_domains parameter is left at its implicit
+
As long as the relay_domains parameter is left unspecified at
+its implicit
default value, and the compatibility_level setting is less than 2,
Postfix may log one of the following messages.
@@ -408,7 +424,8 @@ secure digest of the client certificate.
with the "sha256" digests of the expected client certificate or public
key.
- As long as the smtpd_tls_fingerprint_digest parameter is left at its
+
As long as the smtpd_tls_fingerprint_digest parameter is left
+unspecified at its
implicit default value, and the compatibility_level setting is less than
3.6, Postfix logs a warning each time a client certificate or public key
fingerprint is (potentially) used for access control:
@@ -455,7 +472,8 @@ policies in the TLS policy table to specify matching "sha256" digests of
the expected server certificates or public keys.
As long as the smtp_tls_fingerprint_digest (or LMTP equivalent)
-parameter is left at its implicit default value, and the
+parameter is left unspecified at its implicit default value, and
+the
compatibility_level setting is less than 3.6, Postfix logs a warning each
time the "fingerprint" security level is used to specify matching "md5"
digests of trusted server certificates or public keys:
@@ -499,7 +517,8 @@ command, and both support the same features.
keep evaluating smtpd_recipient_restrictions before
smtpd_relay_restrictions, as long as the compatibility_level is
less than 3.6, and the smtpd_relay_before_recipient_restrictions
-parameter is left at its implicit default setting. As a reminder,
+parameter is left unspecified at its implicit default setting. As
+a reminder,
Postfix may log the following message:
@@ -533,7 +552,8 @@ the changes in logging could affect logfile analysis tools.
To avoid breaking existing logfile analysis tools, Postfix will keep
logging the deprecated form, as long as the respectful_logging parameter
-is left at its implicit default value, and the compatibility_level
+is left unspecified at its implicit default value, and the
+compatibility_level
setting is less than 3.6. As a reminder, Postfix may log the following
when a remote SMTP client is allowlisted or denylisted:
@@ -555,6 +575,38 @@ system administrator should make the backwards-compatible setting
+
+
+ Postfix version 3.11 changes the default value for
+smtp_tlsrpt_skip_reused_handshakes from "yes" to "no". The
+backwards-compatibility safety net is designed to prevent an
+unexpected change in reporting behavior when Postfix is updated
+from an older version.
+
+ As long as the smtp_tlsrpt_skip_reused_handshakes parameter is
+left unspecified at its implicit default value, and the compatibility_level
+setting is less than 3.11, Postfix will log a reminder that it is
+using the backwards-compatible default:
+
+
+
+postfix/smtp[388157] using backwards-compatible default setting
+ smtp_tlsrpt_skip_reused_handshakes=yes
+
+
+
+ To keep the old default setting, the system administrator should
+make the backwards-compatible setting "smtp_tlsrpt_skip_reused_handshakes
+= yes" permanent in main.cf:
+
+
+
+# postconf smtp_tlsrpt_skip_reused_handshakes=yes
+# postfix reload
+
+
+
Backwards compatibility is turned off by updating the
diff --git a/postfix/html/SMTPUTF8_README.html b/postfix/html/SMTPUTF8_README.html
index 10f22e4e6..cb42d06a0 100644
--- a/postfix/html/SMTPUTF8_README.html
+++ b/postfix/html/SMTPUTF8_README.html
@@ -375,7 +375,7 @@ Firefox and Chrome web browsers. Specify "
This affects the conversion of domain names that contain for
-example the German sz (Ã) and the Greek zeta (Ï). See
+example the German sz (Ã) and the Greek (final) sigma (Ï). See
https://unicode.org/cldr/utility/idna.jsp for more examples.
diff --git a/postfix/html/TLSRPT_README.html b/postfix/html/TLSRPT_README.html
index 6d3746e4c..3a361d712 100644
--- a/postfix/html/TLSRPT_README.html
+++ b/postfix/html/TLSRPT_README.html
@@ -286,12 +286,12 @@ Untrusted TLS connection reused to mail.example.com[ipaddr]:25:
TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
- By default, Postfix does not report the TLSRPT status for
-a TLS handshake that reuses a previously-negotiated TLS session
-(there would be no new information to report). Specify
-"smtp_tlsrpt_skip_reused_handshakes = no" to report the TLSRPT
-status for all TLS handshakes. This may be useful for troubleshooting.
-
+ With TLSRPT enabled, the Postfix SMTP client reports the
+TLSRPT status for all TLS handshakes (the default as of Postfix
+3.11). Specify "smtp_tlsrpt_skip_reused_handshakes = yes" (the
+default with Postfix 3.10) to skip reporting TLS handshakes that
+reuse a previously-negotiated TLS session as there would be no new
+information to report.
Postfix logging for certificate verification failures may
differ between new or reused TLS sessions.
@@ -373,7 +373,7 @@ generator's sender address):
- Postfix supports MTA-STS though an smtp_tls_policy_maps policy
+
Postfix supports MTA-STS through an smtp_tls_policy_maps policy
plugin, which replies with a TLS security level and name=value
attributes with certificate matching requirements. Postfix 3.10 and
later extend the policy plugin response with additional name=value
diff --git a/postfix/html/lmdb_table.5.html b/postfix/html/lmdb_table.5.html
index 60624494e..ac0221335 100644
--- a/postfix/html/lmdb_table.5.html
+++ b/postfix/html/lmdb_table.5.html
@@ -56,24 +56,25 @@ LMDB_TABLE(5) LMDB_TABLE(5)
SYNCHRONIZATION
The Postfix LMDB adapter does not use LMDB's built-in locking scheme,
- because that would require world-writable lockfiles and would violate
- the Postfix security model. Instead, Postfix uses fcntl(2) locks with
- whole-file granularity. Programs that use LMDB's built-in locking pro-
- tocol will corrupt a Postfix LMDB database or will read garbage.
+ because that would require world-writable lockfiles and therefore vio-
+ late the Postfix security model. Instead, Postfix uses fcntl(2) locks
+ with whole-file granularity. Programs that use LMDB's built-in locking
+ protocol will corrupt a Postfix LMDB database or will read garbage.
Every Postfix LMDB database read or write transaction must be protected
- from start to end with a shared or exclusive fcntl(2) lock. A writer
- may atomically downgrade an exclusive lock to a shared lock, but it
- must hold an exclusive lock while opening another write transaction.
-
- Note that fcntl(2) locks do not protect transactions within the same
- process against each other. If a program cannot avoid making simulta-
- neous database requests, then it must protect its transactions with
+ from start to end with a shared or exclusive fcntl(2) lock. A process
+ may atomically downgrade an exclusive lock to a shared lock before
+ opening a database read transaction, but it must hold an exclusive lock
+ while opening a write transaction.
+
+ Note that fcntl(2) locks do not protect transactions within the same
+ process against each other. If a program cannot avoid making simulta-
+ neous database requests, then it must protect its transactions with
in-process locks, in addition to the per-process fcntl(2) locks.
CONFIGURATION PARAMETERS
- Short-lived programs automatically pick up changes to main.cf. With
- long-running daemon programs, Use the command "postfix reload" after a
+ Short-lived programs automatically pick up changes to main.cf. With
+ long-running daemon programs, Use the command "postfix reload" after a
configuration change.
lmdb_map_size (16777216)
diff --git a/postfix/html/memcache_table.5.html b/postfix/html/memcache_table.5.html
index 42796b717..47c9aa396 100644
--- a/postfix/html/memcache_table.5.html
+++ b/postfix/html/memcache_table.5.html
@@ -99,18 +99,30 @@ MEMCACHE_TABLE(5) MEMCACHE_TABLE(5)
time. Smaller values are relative to the time of the update.
MEMCACHE KEY PARAMETERS
+ key_digest (default: empty)
+ After processing the key_format setting, and before sending a
+ request to the memcache server, run the key through the named
+ message digest algorithm and convert the result to lowercase
+ hexadecimal characters. This prevents a database access error
+ when keys may exceed the memcache server's key length limit
+ (usually, 250 bytes). Specify the name of a message digest algo-
+ rithm that is supported by OpenSSL, for example, sha256.
+
+ This feature is available in Postfix 3.11 and later, and
+ requires that Postfix is built with TLS support.
+
key_format (default: %s)
- Format of the lookup and update keys that the Postfix memcache
- client sends to the memcache server. By default, these are the
- same as the lookup and update keys that the memcache client
+ Format of the lookup and update keys that the Postfix memcache
+ client sends to the memcache server. By default, these are the
+ same as the lookup and update keys that the memcache client
receives from Postfix applications.
- NOTE 1: The key_format feature is not used for backup database
+ NOTE 1: The key_format feature is not used for backup database
requests.
- NOTE 2: When multiple tables share the same memcache database,
- each table should prepend its own unique string to the lookup
- key. Otherwise, automatic postscreen(8) or verify(8) cache
+ NOTE 2: When multiple tables share the same memcache database,
+ each table should prepend its own unique string to the lookup
+ key. Otherwise, automatic postscreen(8) or verify(8) cache
cleanup may not work.
Examples:
@@ -126,37 +138,37 @@ MEMCACHE_TABLE(5) MEMCACHE_TABLE(5)
%s This is replaced by the memcache client input key.
%u When the input key is an address of the form user@domain,
- %u is replaced by the SQL quoted local part of the
- address. Otherwise, %u is replaced by the entire search
- string. If the localpart is empty, a lookup is silently
- suppressed and returns no results (an update is skipped
+ %u is replaced by the SQL quoted local part of the
+ address. Otherwise, %u is replaced by the entire search
+ string. If the localpart is empty, a lookup is silently
+ suppressed and returns no results (an update is skipped
with a warning).
%d When the input key is an address of the form user@domain,
%d is replaced by the domain part of the address. Other-
- wise, a lookup is silently suppressed and returns no
+ wise, a lookup is silently suppressed and returns no
results (an update is skipped with a warning).
%[SUD] The upper-case equivalents of the above expansions behave
- in the key_format parameter identically to their
+ in the key_format parameter identically to their
lower-case counter-parts.
- %[1-9] The patterns %1, %2, ... %9 are replaced by the corre-
- sponding most significant component of the input key's
- domain. If the input key is user@mail.example.com, then
+ %[1-9] The patterns %1, %2, ... %9 are replaced by the corre-
+ sponding most significant component of the input key's
+ domain. If the input key is user@mail.example.com, then
%1 is com, %2 is example and %3 is mail. If the input key
- is unqualified or does not have enough domain components
- to satisfy all the specified patterns, a lookup is
- silently suppressed and returns no results (an update is
+ is unqualified or does not have enough domain components
+ to satisfy all the specified patterns, a lookup is
+ silently suppressed and returns no results (an update is
skipped with a warning).
domain (default: no domain list)
- This feature can significantly reduce database server load.
- Specify a list of domain names, paths to files, or "type:table"
- databases. When specified, only fully qualified search keys
- with a *non-empty* localpart and a matching domain are eligible
- for lookup or update: bare 'user' lookups, bare domain lookups
- and "@domain" lookups are silently skipped (updates are skipped
+ This feature can significantly reduce database server load.
+ Specify a list of domain names, paths to files, or "type:table"
+ databases. When specified, only fully qualified search keys
+ with a *non-empty* localpart and a matching domain are eligible
+ for lookup or update: bare 'user' lookups, bare domain lookups
+ and "@domain" lookups are silently skipped (updates are skipped
with a warning). Example:
domain = example.com, hash:/etc/postfix/searchdomains
@@ -169,30 +181,30 @@ MEMCACHE_TABLE(5) MEMCACHE_TABLE(5)
The maximal memcache reply line length in bytes.
max_try (default: 2)
- The number of times to try a memcache command before giving up.
- The memcache client does not retry a command when the memcache
+ The number of times to try a memcache command before giving up.
+ The memcache client does not retry a command when the memcache
server accepts no connection.
retry_pause (default: 1)
The time in seconds before retrying a failed memcache command.
timeout (default: 2)
- The time limit for sending a memcache command and for receiving
+ The time limit for sending a memcache command and for receiving
a memcache reply.
BUGS
- The Postfix memcache client cannot be used for security-sensitive
+ The Postfix memcache client cannot be used for security-sensitive
tables such as alias_maps (these may contain "|command and "/file/name"
- destinations), or virtual_uid_maps, virtual_gid_maps and virtual_mail-
- box_maps (these specify UNIX process privileges or "/file/name" desti-
- nations). In a typical deployment a memcache database is writable by
- any process that can talk to the memcache server; in contrast, secu-
- rity-sensitive tables must never be writable by the unprivileged Post-
+ destinations), or virtual_uid_maps, virtual_gid_maps and virtual_mail-
+ box_maps (these specify UNIX process privileges for "/file/name" desti-
+ nations). In a typical deployment a memcache database is writable by
+ any process that can talk to the memcache server; in contrast, secu-
+ rity-sensitive tables must never be writable by the unprivileged Post-
fix user.
The Postfix memcache client requires additional configuration when used
- as postscreen(8) or verify(8) cache. For details see the backup and
- ttl parameter discussions in the MEMCACHE MAIN PARAMETERS section
+ as postscreen(8) or verify(8) cache. For details see the backup and
+ ttl parameter discussions in the MEMCACHE MAIN PARAMETERS section
above.
SEE ALSO
diff --git a/postfix/html/mysql_table.5.html b/postfix/html/mysql_table.5.html
index c75906641..8c8e5588e 100644
--- a/postfix/html/mysql_table.5.html
+++ b/postfix/html/mysql_table.5.html
@@ -61,16 +61,15 @@ MYSQL_TABLE(5) MYSQL_TABLE(5)
TCP you have to specify
hosts = 127.0.0.1
- NOTE: if the hosts setting specifies one server, this client
- assumes that the target is a load balancer and will reconnect
- immediately after a single failure, instead of failing all
- requests temporarily. With older versions of this client, spec-
- ify the same server twice.
+ NOTE: if the hosts setting specifies only one server, this
+ client assumes that the target is a load balancer and will
+ reconnect immediately after a single failure. With Postfix ver-
+ sions 3.9 and earlier, specify the same server twice.
user
password
- The user name and password to log into the mysql server. Exam-
+ The user name and password to log into the mysql server. Exam-
ple:
user = someone
password = some_password
@@ -79,15 +78,15 @@ MYSQL_TABLE(5) MYSQL_TABLE(5)
dbname = customer_database
charset (default: utf8mb4)
- The default MySQL client character set; this also implies the
+ The default MySQL client character set; this also implies the
collation order.
- This parameter is available with Postfix 3.9 and later. With
- earlier Postfix versions, the default was chosen by the MySQL
+ This parameter is available with Postfix 3.9 and later. With
+ earlier Postfix versions, the default was chosen by the MySQL
implementation (utf8mb4 as of MySQL 8.0, latin1 historically).
idle_interval (default: 60)
- The number of seconds after which an idle database connection
+ The number of seconds after which an idle database connection
will be closed.
This feature is available in Postfix 3.9 and later.
@@ -96,11 +95,10 @@ MYSQL_TABLE(5) MYSQL_TABLE(5)
The number of seconds that a database connection will be skipped
after an error.
- NOTE: if the hosts setting specifies one server, this client
- assumes that the target is a load balancer and will reconnect
- immediately after a single failure, instead of failing all
- requests temporarily. With older versions of this client, spec-
- ify the same server twice.
+ NOTE: if the hosts setting specifies only one server, this
+ client assumes that the target is a load balancer and will
+ reconnect immediately after a single failure. With Postfix ver-
+ sions 3.9 and earlier, specify the same server twice.
This feature is available in Postfix 3.9 and later.
diff --git a/postfix/html/pgsql_table.5.html b/postfix/html/pgsql_table.5.html
index e44279000..cab95ff89 100644
--- a/postfix/html/pgsql_table.5.html
+++ b/postfix/html/pgsql_table.5.html
@@ -65,16 +65,15 @@ PGSQL_TABLE(5) PGSQL_TABLE(5)
URI, the Postfix PostgreSQL client will ignore the dbname, user,
and password settings for that connection.
- NOTE: if the hosts setting specifies one server, this client
- assumes that the target is a load balancer and will reconnect
- immediately after a single failure, instead of failing all
- requests temporarily. With older versions of this client, spec-
- ify the same server twice.
+ NOTE: if the hosts setting specifies only one server, this
+ client assumes that the target is a load balancer and will
+ reconnect immediately after a single failure. With Postfix ver-
+ sions 3.9 and earlier, specify the same server twice.
user
password
- The user name and password to log into the pgsql server. Exam-
+ The user name and password to log into the pgsql server. Exam-
ple:
user = someone
password = some_password
@@ -85,25 +84,25 @@ PGSQL_TABLE(5) PGSQL_TABLE(5)
dbname The database name on the servers. Example:
dbname = customer_database
- The dbname setting is ignored for hosts connections that are
+ The dbname setting is ignored for hosts connections that are
specified as an URI.
The dbname setting is required with Postfix 3.10 and later, when
- hosts specifies any non-URI connection; it is always required
+ hosts specifies any non-URI connection; it is always required
with earlier Postfix versions.
encoding
- The encoding used by the database client. The default setting
+ The encoding used by the database client. The default setting
is:
encoding = UTF8
- Historically, the database client was hard coded to use LATIN1
+ Historically, the database client was hard coded to use LATIN1
in an attempt to disable multibyte character support.
This feature is available in Postfix 3.8 and later.
idle_interval (default: 60)
- The number of seconds after which an idle database connection
+ The number of seconds after which an idle database connection
will be closed.
This feature is available in Postfix 3.9 and later.
@@ -112,11 +111,10 @@ PGSQL_TABLE(5) PGSQL_TABLE(5)
The number of seconds that a database connection will be skipped
after an error.
- NOTE: if the hosts setting specifies one server, this client
- assumes that the target is a load balancer and will reconnect
- immediately after a single failure, instead of failing all
- requests temporarily. With older versions of this client, spec-
- ify the same server twice.
+ NOTE: if the hosts setting specifies only one server, this
+ client assumes that the target is a load balancer and will
+ reconnect immediately after a single failure. With Postfix ver-
+ sions 3.9 and earlier, specify the same server twice.
This feature is available in Postfix 3.9 and later.
diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html
index 03d029cd0..0d63f28ee 100644
--- a/postfix/html/postconf.5.html
+++ b/postfix/html/postconf.5.html
@@ -20,7 +20,7 @@ if (hash && isChrome) {
setTimeout(function() {
window.location.hash = "";
window.location.hash = hash;
- }, 1000);
+ }, 1500);
}
@@ -3349,7 +3349,7 @@ with older Postfix versions).
when converting UTF-8 domain names to/from the ASCII form that is
used for DNS lookups. Specify "yes" for compatibility with Postfix
≤ 3.1 (not recommended). This affects the conversion of domain
-names that contain for example the German sz and the Greek zeta.
+names that contain for example the German sz and the Greek sigma.
See https://unicode.org/cldr/utility/idna.jsp for more examples.
@@ -14870,13 +14870,11 @@ requirements for MTA-STS smtp_tls
smtp_tlsrpt_skip_reused_handshakes
-(default: yes)
+(default: Postfix ≥ 3.11: no, Postfix 3.10: yes)
- Do not report the TLSRPT status for TLS protocol handshakes
-that reuse a previously-negotiated TLS session (there is no new
-information to report). Report the TLSRPT status only for "new" TLS
-sessions. Set this to "no" to log the TLSRPT status of all TLS
-handshakes, for example to troubleshoot Postfix TLSRPT support.
+
When set to "yes", report the TLSRPT status only for "new" TLS
+sessions. When set to "no", also report the TLSRPT status for TLS
+protocol handshakes that reuse a previously-negotiated TLS session.
Note: if an SMTP over TLS connection is reused, there is no
diff --git a/postfix/man/man5/lmdb_table.5 b/postfix/man/man5/lmdb_table.5
index c4c74d634..eec44147f 100644
--- a/postfix/man/man5/lmdb_table.5
+++ b/postfix/man/man5/lmdb_table.5
@@ -72,16 +72,17 @@ postscreen(8) services.
.fi
The Postfix LMDB adapter does not use LMDB's built\-in locking
scheme, because that would require world\-writable lockfiles
-and would violate the Postfix security model. Instead,
+and therefore violate the Postfix security model. Instead,
Postfix uses fcntl(2) locks with whole\-file granularity.
Programs that use LMDB's built\-in locking protocol will
corrupt a Postfix LMDB database or will read garbage.
Every Postfix LMDB database read or write transaction must
be protected from start to end with a shared or exclusive
-fcntl(2) lock. A writer may atomically downgrade an exclusive
-lock to a shared lock, but it must hold an exclusive lock
-while opening another write transaction.
+fcntl(2) lock. A process may atomically downgrade an exclusive
+lock to a shared lock before opening a database read transaction,
+but it must hold an exclusive lock while opening a write
+transaction.
Note that fcntl(2) locks do not protect transactions within
the same process against each other. If a program cannot
diff --git a/postfix/man/man5/memcache_table.5 b/postfix/man/man5/memcache_table.5
index 430f73c51..8d90a3df3 100644
--- a/postfix/man/man5/memcache_table.5
+++ b/postfix/man/man5/memcache_table.5
@@ -112,6 +112,17 @@ time. Smaller values are relative to the time of the update.
.nf
.ad
.fi
+.IP "\fBkey_digest (default: empty)\fB"
+After processing the \fBkey_format\fR setting, and before sending
+a request to the memcache server, run the key through the named
+message digest algorithm and convert the result to lowercase
+hexadecimal characters. This prevents a database access error
+when keys may exceed the memcache server's key length limit
+(usually, 250 bytes). Specify the name of a message digest
+algorithm that is supported by OpenSSL, for example, \fBsha256\fR.
+
+This feature is available in Postfix 3.11 and later, and requires
+that Postfix is built with TLS support.
.IP "\fBkey_format (default: %s)\fB"
Format of the lookup and update keys that the Postfix
memcache client sends to the memcache server.
@@ -207,7 +218,7 @@ tables such as \fBalias_maps\fR (these may contain
"\fI|command\fR and "\fI/file/name\fR" destinations), or
\fBvirtual_uid_maps\fR, \fBvirtual_gid_maps\fR and
\fBvirtual_mailbox_maps\fR (these specify UNIX process
-privileges or "\fI/file/name\fR" destinations). In a typical
+privileges for "\fI/file/name\fR" destinations). In a typical
deployment a memcache database is writable by any process
that can talk to the memcache server; in contrast,
security\-sensitive tables must never be writable by the
diff --git a/postfix/man/man5/mysql_table.5 b/postfix/man/man5/mysql_table.5
index 865f9d07f..3cca85eb2 100644
--- a/postfix/man/man5/mysql_table.5
+++ b/postfix/man/man5/mysql_table.5
@@ -77,11 +77,10 @@ localhost over TCP you have to specify
hosts = 127.0.0.1
.fi
-NOTE: if the \fBhosts\fR setting specifies one server, this client
-assumes that the target is a load balancer and will reconnect
-immediately after a single failure, instead of failing all
-requests temporarily. With older versions of this client,
-specify the same server twice.
+NOTE: if the \fBhosts\fR setting specifies only one server,
+this client assumes that the target is a load balancer and
+will reconnect immediately after a single failure. With Postfix
+versions 3.9 and earlier, specify the same server twice.
.IP "\fBuser\fR"
.IP "\fBpassword\fR"
The user name and password to log into the mysql server.
@@ -112,11 +111,10 @@ This feature is available in Postfix 3.9 and later.
The number of seconds that a database connection will be
skipped after an error.
-NOTE: if the \fBhosts\fR setting specifies one server, this client
-assumes that the target is a load balancer and will reconnect
-immediately after a single failure, instead of failing all
-requests temporarily. With older versions of this client,
-specify the same server twice.
+NOTE: if the \fBhosts\fR setting specifies only one server,
+this client assumes that the target is a load balancer and
+will reconnect immediately after a single failure. With Postfix
+versions 3.9 and earlier, specify the same server twice.
This feature is available in Postfix 3.9 and later.
.IP "\fBquery\fR"
diff --git a/postfix/man/man5/pgsql_table.5 b/postfix/man/man5/pgsql_table.5
index 51df7338e..1deaa3fe8 100644
--- a/postfix/man/man5/pgsql_table.5
+++ b/postfix/man/man5/pgsql_table.5
@@ -81,11 +81,10 @@ NOTE: if the \fBhosts\fR setting specifies a PostgreSQL connection
URI, the Postfix PostgreSQL client will ignore the \fBdbname\fR,
\fBuser\fR, and \fBpassword\fR settings for that connection.
-NOTE: if the \fBhosts\fR setting specifies one server, this client
-assumes that the target is a load balancer and will reconnect
-immediately after a single failure, instead of failing all
-requests temporarily. With older versions of this client,
-specify the same server twice.
+NOTE: if the \fBhosts\fR setting specifies only one server,
+this client assumes that the target is a load balancer and
+will reconnect immediately after a single failure. With Postfix
+versions 3.9 and earlier, specify the same server twice.
.IP "\fBuser\fR"
.IP "\fBpassword\fR"
The user name and password to log into the pgsql server.
@@ -129,11 +128,10 @@ This feature is available in Postfix 3.9 and later.
The number of seconds that a database connection will be
skipped after an error.
-NOTE: if the \fBhosts\fR setting specifies one server, this client
-assumes that the target is a load balancer and will reconnect
-immediately after a single failure, instead of failing all
-requests temporarily. With older versions of this client,
-specify the same server twice.
+NOTE: if the \fBhosts\fR setting specifies only one server,
+this client assumes that the target is a load balancer and
+will reconnect immediately after a single failure. With Postfix
+versions 3.9 and earlier, specify the same server twice.
This feature is available in Postfix 3.9 and later.
.IP "\fBquery\fR"
diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5
index afb9cc97b..24351183c 100644
--- a/postfix/man/man5/postconf.5
+++ b/postfix/man/man5/postconf.5
@@ -2079,7 +2079,7 @@ Enable 'transitional' compatibility between IDNA2003 and IDNA2008,
when converting UTF\-8 domain names to/from the ASCII form that is
used for DNS lookups. Specify "yes" for compatibility with Postfix
<= 3.1 (not recommended). This affects the conversion of domain
-names that contain for example the German sz and the Greek zeta.
+names that contain for example the German sz and the Greek sigma.
See https://unicode.org/cldr/utility/idna.jsp for more examples.
.PP
This feature is available in Postfix 3.2 and later.
@@ -9921,12 +9921,10 @@ See TLSRPT_README for configuration examples and additional
requirements for MTA\-STS smtp_tls_policy_maps plugins.
.PP
This feature is available in Postfix >= 3.10.
-.SH smtp_tlsrpt_skip_reused_handshakes (default: yes)
-Do not report the TLSRPT status for TLS protocol handshakes
-that reuse a previously\-negotiated TLS session (there is no new
-information to report). Report the TLSRPT status only for "new" TLS
-sessions. Set this to "no" to log the TLSRPT status of all TLS
-handshakes, for example to troubleshoot Postfix TLSRPT support.
+.SH smtp_tlsrpt_skip_reused_handshakes (default: Postfix >= 3.11: no, Postfix 3.10: yes)
+When set to "yes", report the TLSRPT status only for "new" TLS
+sessions. When set to "no", also report the TLSRPT status for TLS
+protocol handshakes that reuse a previously\-negotiated TLS session.
.PP
Note: if an SMTP over TLS connection is reused, there is no
second etc. TLS handshake to report.
diff --git a/postfix/proto/COMPATIBILITY_README.html b/postfix/proto/COMPATIBILITY_README.html
index 801d0d9a5..d0fd5d902 100644
--- a/postfix/proto/COMPATIBILITY_README.html
+++ b/postfix/proto/COMPATIBILITY_README.html
@@ -102,6 +102,17 @@ default setting respectful_logging=no
+ Logged with compatibility_level < 3.11:
+
+
+
+
+
If such a message is logged in the context of a legitimate
request, the system administrator should make the backwards-compatible
setting permanent in main.cf or master.cf, as detailed in the
@@ -120,7 +131,8 @@ to "no". This could result in unexpected non-delivery of email after
Postfix is updated from an older version. The backwards-compatibility
safety net is designed to prevent such surprises.
- As long as the append_dot_mydomain parameter is left at
+
As long as the append_dot_mydomain parameter is left unspecified
+at
its implicit default value, and the compatibility_level setting is
less than 1, Postfix may log one of the following messages:
@@ -178,7 +190,7 @@ after updating Postfix from an older version. The backwards-compatibility
safety net is designed allow the administrator to choose if they
want to keep the old behavior.
- As long as a master.cf chroot field is left at its
+
As long as a master.cf chroot field is left unspecified at its
implicit default value, and the compatibility_level setting
is less than 1, Postfix may log the following message while it
reads the master.cf file:
@@ -218,7 +230,8 @@ from an older Postfix version. The backwards-compatibility safety
net is designed to prevent such surprises.
When the compatibility_level less than 1, and the
-smtpd_relay_restrictions parameter is left at its implicit default
+smtpd_relay_restrictions parameter is left unspecified at its
+implicit default
setting, Postfix may log the following message:
@@ -250,7 +263,8 @@ addresses from clients that don't request SMTPUTF8 support, after
Postfix is updated from an older version. The backwards-compatibility
safety net is designed to prevent such surprises.
- As long as the smtputf8_enable parameter is left at its implicit
+
As long as the smtputf8_enable parameter is left unspecified
+at its implicit
default value, and the compatibility_level setting is
less than 1, Postfix logs a warning each time an SMTP command uses a
non-ASCII address localpart without requesting SMTPUTF8 support:
@@ -293,7 +307,8 @@ Postfix is updated from an older version. The backwards-compatibility
safety net is designed to prevent such surprises.
As long as the mynetworks and mynetworks_style parameters are
-left at their implicit default values, and the compatibility_level
+left unspecified at their implicit default values, and the
+compatibility_level
setting is less than 2, the Postfix SMTP server may log one of the
following messages:
@@ -333,7 +348,8 @@ denied' errors or ETRN errors after Postfix is updated from an older
version. The backwards-compatibility safety net is designed to
prevent such surprises.
- As long as the relay_domains parameter is left at its implicit
+
As long as the relay_domains parameter is left unspecified at
+its implicit
default value, and the compatibility_level setting is less than 2,
Postfix may log one of the following messages.
@@ -408,7 +424,8 @@ secure digest of the client certificate.
with the "sha256" digests of the expected client certificate or public
key.
- As long as the smtpd_tls_fingerprint_digest parameter is left at its
+
As long as the smtpd_tls_fingerprint_digest parameter is left
+unspecified at its
implicit default value, and the compatibility_level setting is less than
3.6, Postfix logs a warning each time a client certificate or public key
fingerprint is (potentially) used for access control:
@@ -455,7 +472,8 @@ policies in the TLS policy table to specify matching "sha256" digests of
the expected server certificates or public keys.
As long as the smtp_tls_fingerprint_digest (or LMTP equivalent)
-parameter is left at its implicit default value, and the
+parameter is left unspecified at its implicit default value, and
+the
compatibility_level setting is less than 3.6, Postfix logs a warning each
time the "fingerprint" security level is used to specify matching "md5"
digests of trusted server certificates or public keys:
@@ -499,7 +517,8 @@ command, and both support the same features.
keep evaluating smtpd_recipient_restrictions before
smtpd_relay_restrictions, as long as the compatibility_level is
less than 3.6, and the smtpd_relay_before_recipient_restrictions
-parameter is left at its implicit default setting. As a reminder,
+parameter is left unspecified at its implicit default setting. As
+a reminder,
Postfix may log the following message:
@@ -533,7 +552,8 @@ the changes in logging could affect logfile analysis tools.
To avoid breaking existing logfile analysis tools, Postfix will keep
logging the deprecated form, as long as the respectful_logging parameter
-is left at its implicit default value, and the compatibility_level
+is left unspecified at its implicit default value, and the
+compatibility_level
setting is less than 3.6. As a reminder, Postfix may log the following
when a remote SMTP client is allowlisted or denylisted:
@@ -555,6 +575,38 @@ system administrator should make the backwards-compatible setting
+
+
+ Postfix version 3.11 changes the default value for
+smtp_tlsrpt_skip_reused_handshakes from "yes" to "no". The
+backwards-compatibility safety net is designed to prevent an
+unexpected change in reporting behavior when Postfix is updated
+from an older version.
+
+ As long as the smtp_tlsrpt_skip_reused_handshakes parameter is
+left unspecified at its implicit default value, and the compatibility_level
+setting is less than 3.11, Postfix will log a reminder that it is
+using the backwards-compatible default:
+
+
+
+postfix/smtp[388157] using backwards-compatible default setting
+ smtp_tlsrpt_skip_reused_handshakes=yes
+
+
+
+ To keep the old default setting, the system administrator should
+make the backwards-compatible setting "smtp_tlsrpt_skip_reused_handshakes
+= yes" permanent in main.cf:
+
+
+
+# postconf smtp_tlsrpt_skip_reused_handshakes=yes
+# postfix reload
+
+
+
Backwards compatibility is turned off by updating the
diff --git a/postfix/proto/SMTPUTF8_README.html b/postfix/proto/SMTPUTF8_README.html
index 5948f85fc..e2713c41b 100644
--- a/postfix/proto/SMTPUTF8_README.html
+++ b/postfix/proto/SMTPUTF8_README.html
@@ -375,7 +375,7 @@ Firefox and Chrome web browsers. Specify "enable_idna2003_compatibility
= yes" to get the historical behavior.
This affects the conversion of domain names that contain for
-example the German sz (Ã) and the Greek zeta (Ï). See
+example the German sz (Ã) and the Greek (final) sigma (Ï). See
https://unicode.org/cldr/utility/idna.jsp for more examples.
diff --git a/postfix/proto/TLSRPT_README.html b/postfix/proto/TLSRPT_README.html
index 0531b0381..755b5e3ee 100644
--- a/postfix/proto/TLSRPT_README.html
+++ b/postfix/proto/TLSRPT_README.html
@@ -286,12 +286,12 @@ Untrusted TLS connection reused to mail.example.com[ipaddr]:25:
TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
- By default, Postfix does not report the TLSRPT status for
-a TLS handshake that reuses a previously-negotiated TLS session
-(there would be no new information to report). Specify
-"smtp_tlsrpt_skip_reused_handshakes = no" to report the TLSRPT
-status for all TLS handshakes. This may be useful for troubleshooting.
-
+ With TLSRPT enabled, the Postfix SMTP client reports the
+TLSRPT status for all TLS handshakes (the default as of Postfix
+3.11). Specify "smtp_tlsrpt_skip_reused_handshakes = yes" (the
+default with Postfix 3.10) to skip reporting TLS handshakes that
+reuse a previously-negotiated TLS session as there would be no new
+information to report.
Postfix logging for certificate verification failures may
differ between new or reused TLS sessions.
@@ -373,7 +373,7 @@ generator's sender address):
- Postfix supports MTA-STS though an smtp_tls_policy_maps policy
+
Postfix supports MTA-STS through an smtp_tls_policy_maps policy
plugin, which replies with a TLS security level and name=value
attributes with certificate matching requirements. Postfix 3.10 and
later extend the policy plugin response with additional name=value
diff --git a/postfix/proto/lmdb_table b/postfix/proto/lmdb_table
index 5bbbc14d3..ad81a4622 100644
--- a/postfix/proto/lmdb_table
+++ b/postfix/proto/lmdb_table
@@ -60,16 +60,17 @@
# .fi
# The Postfix LMDB adapter does not use LMDB's built-in locking
# scheme, because that would require world-writable lockfiles
-# and would violate the Postfix security model. Instead,
+# and therefore violate the Postfix security model. Instead,
# Postfix uses fcntl(2) locks with whole-file granularity.
# Programs that use LMDB's built-in locking protocol will
# corrupt a Postfix LMDB database or will read garbage.
#
# Every Postfix LMDB database read or write transaction must
# be protected from start to end with a shared or exclusive
-# fcntl(2) lock. A writer may atomically downgrade an exclusive
-# lock to a shared lock, but it must hold an exclusive lock
-# while opening another write transaction.
+# fcntl(2) lock. A process may atomically downgrade an exclusive
+# lock to a shared lock before opening a database read transaction,
+# but it must hold an exclusive lock while opening a write
+# transaction.
#
# Note that fcntl(2) locks do not protect transactions within
# the same process against each other. If a program cannot
diff --git a/postfix/proto/memcache_table b/postfix/proto/memcache_table
index c97a9b449..6d4240394 100644
--- a/postfix/proto/memcache_table
+++ b/postfix/proto/memcache_table
@@ -102,6 +102,17 @@
# MEMCACHE KEY PARAMETERS
# .ad
# .fi
+# .IP "\fBkey_digest (default: empty)\fB"
+# After processing the \fBkey_format\fR setting, and before sending
+# a request to the memcache server, run the key through the named
+# message digest algorithm and convert the result to lowercase
+# hexadecimal characters. This prevents a database access error
+# when keys may exceed the memcache server's key length limit
+# (usually, 250 bytes). Specify the name of a message digest
+# algorithm that is supported by OpenSSL, for example, \fBsha256\fR.
+#
+# This feature is available in Postfix 3.11 and later, and requires
+# that Postfix is built with TLS support.
# .IP "\fBkey_format (default: %s)\fB"
# Format of the lookup and update keys that the Postfix
# memcache client sends to the memcache server.
@@ -193,7 +204,7 @@
# "\fI|command\fR and "\fI/file/name\fR" destinations), or
# \fBvirtual_uid_maps\fR, \fBvirtual_gid_maps\fR and
# \fBvirtual_mailbox_maps\fR (these specify UNIX process
-# privileges or "\fI/file/name\fR" destinations). In a typical
+# privileges for "\fI/file/name\fR" destinations). In a typical
# deployment a memcache database is writable by any process
# that can talk to the memcache server; in contrast,
# security-sensitive tables must never be writable by the
diff --git a/postfix/proto/mysql_table b/postfix/proto/mysql_table
index fc1c238c8..d93d405a8 100644
--- a/postfix/proto/mysql_table
+++ b/postfix/proto/mysql_table
@@ -67,11 +67,10 @@
# hosts = 127.0.0.1
# .fi
#
-# NOTE: if the \fBhosts\fR setting specifies one server, this client
-# assumes that the target is a load balancer and will reconnect
-# immediately after a single failure, instead of failing all
-# requests temporarily. With older versions of this client,
-# specify the same server twice.
+# NOTE: if the \fBhosts\fR setting specifies only one server,
+# this client assumes that the target is a load balancer and
+# will reconnect immediately after a single failure. With Postfix
+# versions 3.9 and earlier, specify the same server twice.
# .IP "\fBuser\fR"
# .IP "\fBpassword\fR"
# The user name and password to log into the mysql server.
@@ -102,11 +101,10 @@
# The number of seconds that a database connection will be
# skipped after an error.
#
-# NOTE: if the \fBhosts\fR setting specifies one server, this client
-# assumes that the target is a load balancer and will reconnect
-# immediately after a single failure, instead of failing all
-# requests temporarily. With older versions of this client,
-# specify the same server twice.
+# NOTE: if the \fBhosts\fR setting specifies only one server,
+# this client assumes that the target is a load balancer and
+# will reconnect immediately after a single failure. With Postfix
+# versions 3.9 and earlier, specify the same server twice.
#
# This feature is available in Postfix 3.9 and later.
# .IP "\fBquery\fR"
diff --git a/postfix/proto/pgsql_table b/postfix/proto/pgsql_table
index cba9e45f4..edc50b619 100644
--- a/postfix/proto/pgsql_table
+++ b/postfix/proto/pgsql_table
@@ -71,11 +71,10 @@
# URI, the Postfix PostgreSQL client will ignore the \fBdbname\fR,
# \fBuser\fR, and \fBpassword\fR settings for that connection.
#
-# NOTE: if the \fBhosts\fR setting specifies one server, this client
-# assumes that the target is a load balancer and will reconnect
-# immediately after a single failure, instead of failing all
-# requests temporarily. With older versions of this client,
-# specify the same server twice.
+# NOTE: if the \fBhosts\fR setting specifies only one server,
+# this client assumes that the target is a load balancer and
+# will reconnect immediately after a single failure. With Postfix
+# versions 3.9 and earlier, specify the same server twice.
# .IP "\fBuser\fR"
# .IP "\fBpassword\fR"
# The user name and password to log into the pgsql server.
@@ -119,11 +118,10 @@
# The number of seconds that a database connection will be
# skipped after an error.
#
-# NOTE: if the \fBhosts\fR setting specifies one server, this client
-# assumes that the target is a load balancer and will reconnect
-# immediately after a single failure, instead of failing all
-# requests temporarily. With older versions of this client,
-# specify the same server twice.
+# NOTE: if the \fBhosts\fR setting specifies only one server,
+# this client assumes that the target is a load balancer and
+# will reconnect immediately after a single failure. With Postfix
+# versions 3.9 and earlier, specify the same server twice.
#
# This feature is available in Postfix 3.9 and later.
# .IP "\fBquery\fR"
diff --git a/postfix/proto/postconf.html.prolog b/postfix/proto/postconf.html.prolog
index cb91af190..73cfb1607 100644
--- a/postfix/proto/postconf.html.prolog
+++ b/postfix/proto/postconf.html.prolog
@@ -20,7 +20,7 @@ if (hash && isChrome) {
setTimeout(function() {
window.location.hash = "";
window.location.hash = hash;
- }, 1000);
+ }, 1500);
}
diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto
index 4aef0b2d3..b1130e134 100644
--- a/postfix/proto/postconf.proto
+++ b/postfix/proto/postconf.proto
@@ -17765,7 +17765,7 @@ Milter support should be disabled.
when converting UTF-8 domain names to/from the ASCII form that is
used for DNS lookups. Specify "yes" for compatibility with Postfix
≤ 3.1 (not recommended). This affects the conversion of domain
-names that contain for example the German sz and the Greek zeta.
+names that contain for example the German sz and the Greek sigma.
See https://unicode.org/cldr/utility/idna.jsp for more examples.
@@ -19521,13 +19521,11 @@ requirements for MTA-STS smtp_tls_policy_maps plugins.
This feature is available in Postfix ≥ 3.10.
-%PARAM smtp_tlsrpt_skip_reused_handshakes yes
+%PARAM smtp_tlsrpt_skip_reused_handshakes Postfix ≥ 3.11: no, Postfix 3.10: yes
- Do not report the TLSRPT status for TLS protocol handshakes
-that reuse a previously-negotiated TLS session (there is no new
-information to report). Report the TLSRPT status only for "new" TLS
-sessions. Set this to "no" to log the TLSRPT status of all TLS
-handshakes, for example to troubleshoot Postfix TLSRPT support.
+
When set to "yes", report the TLSRPT status only for "new" TLS
+sessions. When set to "no", also report the TLSRPT status for TLS
+protocol handshakes that reuse a previously-negotiated TLS session.
Note: if an SMTP over TLS connection is reused, there is no
diff --git a/postfix/proto/stop b/postfix/proto/stop
index 7c06d7ee4..ef6aab0a2 100644
--- a/postfix/proto/stop
+++ b/postfix/proto/stop
@@ -1674,3 +1674,11 @@ MLKEM
cleartext
redacted
subclassed
+nosleep
+preload
+memcached
+Geert
+Hendrickx
+typofix
+LD
+PRELOAD
diff --git a/postfix/proto/stop.double-cc b/postfix/proto/stop.double-cc
index e80d33312..0179fe90f 100644
--- a/postfix/proto/stop.double-cc
+++ b/postfix/proto/stop.double-cc
@@ -343,3 +343,4 @@ additional_info additional_info
ignored ignored
USE_TLSRPT USE_TLSRPT
encoded encoded text can contain only alpha digit
+ossl_digest_new ossl_digest_new returns NULL after error ossl_digest_data
diff --git a/postfix/proto/stop.double-history b/postfix/proto/stop.double-history
index 62e45e6b2..782732fda 100644
--- a/postfix/proto/stop.double-history
+++ b/postfix/proto/stop.double-history
@@ -166,3 +166,8 @@ proto proto socketmap_table
global mail_params h smtpd smtpd c
global mail_params h proto postconf proto smtp smtp c
proto postconf proto proto TLS_README html
+ the command line Files postmap postmap c postalias postalias c
+ verification in progress File verify verify c
++ address failed File verify verify c
+ address failed File verify verify c
+ address failed due to a database error File verify verify c
diff --git a/postfix/proto/stop.spell-cc b/postfix/proto/stop.spell-cc
index 3fa8e9528..506c2d2c8 100644
--- a/postfix/proto/stop.spell-cc
+++ b/postfix/proto/stop.spell-cc
@@ -1860,3 +1860,7 @@ XXXSENDOPTS
xtra
HAPROXY
SRVR
+DGST
+DIGEST
+OSSL
+ossl
diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in
index 8a2e26ca0..dfc28b631 100644
--- a/postfix/src/global/Makefile.in
+++ b/postfix/src/global/Makefile.in
@@ -1223,10 +1223,12 @@ dict_memcache.o: ../../include/argv.h
dict_memcache.o: ../../include/auto_clnt.h
dict_memcache.o: ../../include/check_arg.h
dict_memcache.o: ../../include/dict.h
+dict_memcache.o: ../../include/hex_code.h
dict_memcache.o: ../../include/match_list.h
dict_memcache.o: ../../include/msg.h
dict_memcache.o: ../../include/myflock.h
dict_memcache.o: ../../include/mymalloc.h
+dict_memcache.o: ../../include/ossl_digest.h
dict_memcache.o: ../../include/stringops.h
dict_memcache.o: ../../include/sys_defs.h
dict_memcache.o: ../../include/vbuf.h
diff --git a/postfix/src/global/dict_memcache.c b/postfix/src/global/dict_memcache.c
index f249f68e9..09c5cb658 100644
--- a/postfix/src/global/dict_memcache.c
+++ b/postfix/src/global/dict_memcache.c
@@ -50,9 +50,11 @@
/* Utility library. */
+#include
#include
#include
#include
+#include
#include
#include
#include
@@ -75,6 +77,9 @@ typedef struct {
DICT dict; /* parent class */
CFG_PARSER *parser; /* common parameter parser */
void *dbc_ctxt; /* db_common context */
+ char *key_digest; /* digest the query key */
+ OSSL_DGST *key_dgst_eng; /* digest engine */
+ VSTRING *key_dgst_out; /* digest result */
char *key_format; /* query key translation */
int timeout; /* client timeout */
int mc_ttl; /* memcache update expiration */
@@ -99,6 +104,7 @@ typedef struct {
#define DICT_MC_DEF_PORT "11211"
#define DICT_MC_DEF_MEMCACHE "inet:" DICT_MC_DEF_HOST ":" DICT_MC_DEF_PORT
#define DICT_MC_DEF_KEY_FMT "%s"
+#define DICT_MC_DEF_KEY_DGST ""
#define DICT_MC_DEF_MC_TTL 3600
#define DICT_MC_DEF_MC_TIMEOUT 2
#define DICT_MC_DEF_MC_FLAGS 0
@@ -109,6 +115,7 @@ typedef struct {
#define DICT_MC_NAME_MEMCACHE "memcache"
#define DICT_MC_NAME_BACKUP "backup"
+#define DICT_MC_NAME_KEY_DGST "key_digest"
#define DICT_MC_NAME_KEY_FMT "key_format"
#define DICT_MC_NAME_MC_TTL "ttl"
#define DICT_MC_NAME_MC_TIMEOUT "timeout"
@@ -163,7 +170,7 @@ static int dict_memcache_set(DICT_MC *dict_mc, const char *value, int ttl)
DICT_TYPE_MEMCACHE, dict_mc->dict.name);
} else if (strcmp(STR(dict_mc->clnt_buf), "STORED") != 0) {
if (count > 0)
- msg_warn("database %s:%s: update failed: %.30s",
+ msg_warn("database %s:%s: update failed: %.100s",
DICT_TYPE_MEMCACHE, dict_mc->dict.name,
STR(dict_mc->clnt_buf));
} else {
@@ -285,6 +292,18 @@ static ssize_t dict_memcache_prepare_key(DICT_MC *dict_mc, const char *name)
} else {
vstring_strcpy(dict_mc->key_buf, name);
}
+ if (dict_mc->key_dgst_eng) {
+ if (ossl_digest_data(dict_mc->key_dgst_eng, STR(dict_mc->key_buf),
+ LEN(dict_mc->key_buf), dict_mc->key_dgst_out) < 0) {
+ ossl_digest_log_errors(msg_warn);
+ msg_warn("%s:%s: %s message digest failed",
+ DICT_TYPE_MEMCACHE, dict_mc->dict.name,
+ dict_mc->key_digest);
+ return (-1);
+ }
+ hex_encode_opt(dict_mc->key_buf, STR(dict_mc->key_dgst_out),
+ LEN(dict_mc->key_dgst_out), HEX_ENCODE_FLAG_LOWERCASE);
+ }
/*
* The length indicates whether the expansion is empty or not.
@@ -315,8 +334,10 @@ static int dict_memcache_valid_key(DICT_MC *dict_mc,
DICT_MC_SKIP("domain mismatch");
if (rc < 0)
DICT_ERR_VAL_RETURN(dict_mc, rc, 0);
- if (dict_memcache_prepare_key(dict_mc, name) == 0)
+ if ((rc = dict_memcache_prepare_key(dict_mc, name)) == 0)
DICT_MC_SKIP("empty lookup key expansion");
+ if (rc < 0)
+ DICT_ERR_VAL_RETURN(dict_mc, rc, 0);
for (cp = (unsigned char *) STR(dict_mc->key_buf); *cp; cp++)
if (isascii(*cp) && isspace(*cp))
DICT_MC_SKIP("name contains space");
@@ -480,6 +501,12 @@ static void dict_memcache_close(DICT *dict)
cfg_parser_free(dict_mc->parser);
db_common_free_ctx(dict_mc->dbc_ctxt);
+ if (dict_mc->key_digest)
+ myfree(dict_mc->key_digest);
+ if (dict_mc->key_dgst_eng)
+ ossl_digest_free(dict_mc->key_dgst_eng);
+ if (dict_mc->key_dgst_out)
+ vstring_free(dict_mc->key_dgst_out);
if (dict_mc->key_format)
myfree(dict_mc->key_format);
myfree(dict_mc->memcache);
@@ -542,6 +569,17 @@ DICT *dict_memcache_open(const char *name, int open_flags, int dict_flags)
* Parse the configuration file.
*/
dict_mc->parser = parser;
+ dict_mc->key_digest = cfg_get_str(dict_mc->parser, DICT_MC_NAME_KEY_DGST,
+ DICT_MC_DEF_KEY_DGST, 0, 0);
+ if (*dict_mc->key_digest) {
+ if ((dict_mc->key_dgst_eng = ossl_digest_new(dict_mc->key_digest)) == 0)
+ /* See below for dict_surrogate() error propagation. */
+ ossl_digest_log_errors(msg_warn);
+ dict_mc->key_dgst_out = vstring_alloc(1);
+ } else {
+ dict_mc->key_dgst_eng = 0;
+ dict_mc->key_dgst_out = 0;
+ }
dict_mc->key_format = cfg_get_str(dict_mc->parser, DICT_MC_NAME_KEY_FMT,
DICT_MC_DEF_KEY_FMT, 0, 0);
dict_mc->timeout = cfg_get_int(dict_mc->parser, DICT_MC_NAME_MC_TIMEOUT,
@@ -594,5 +632,15 @@ DICT *dict_memcache_open(const char *name, int open_flags, int dict_flags)
dict_mc->dict.flags |= DICT_FLAG_MULTI_WRITER;
+ if (*dict_mc->key_digest && dict_mc->key_dgst_eng == 0) {
+ /* See above for ossl_digest_new() error detection. */
+ DICT *d = dict_surrogate(DICT_TYPE_MEMCACHE, name,
+ open_flags, dict_flags,
+ "open %s: key digest %s is not available",
+ name, dict_mc->key_digest);
+
+ dict_memcache_close(&dict_mc->dict);
+ return (d);
+ }
return (&dict_mc->dict);
}
diff --git a/postfix/src/global/mail_params.c b/postfix/src/global/mail_params.c
index 5d2171d0a..6032ea39a 100644
--- a/postfix/src/global/mail_params.c
+++ b/postfix/src/global/mail_params.c
@@ -390,6 +390,11 @@ char *var_known_tcp_ports;
const char null_format_string[1] = "";
+ /*
+ * Compatibility level 3.11.
+ */
+int warn_compat_break_smtp_tlsrpt_skip_reused_hs;
+
/*
* Compatibility level 3.6.
*/
@@ -662,6 +667,15 @@ static void check_legacy_defaults(void)
* bits.
*/
+ /*
+ * Look for specific parameters whose default changed when the
+ * compatibility level changed to 3.11.
+ */
+ if (compat_level < compat_level_from_string(COMPAT_LEVEL_3_11, msg_panic)) {
+ if (mail_conf_lookup(VAR_SMTP_TLSRPT_SKIP_REUSED_HS) == 0)
+ warn_compat_break_smtp_tlsrpt_skip_reused_hs = 1;
+ }
+
/*
* Look for specific parameters whose default changed when the
* compatibility level changed to 3.6.
diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h
index 0aa05ba00..40aa5c2ba 100644
--- a/postfix/src/global/mail_params.h
+++ b/postfix/src/global/mail_params.h
@@ -51,10 +51,11 @@ extern bool var_show_unk_rcpt_table;
* updating the current compatibility level.
*/
#define COMPAT_LEVEL_0 "0"
-#define COMPAT_LEVEL_1 "1"
-#define COMPAT_LEVEL_2 "2"
+#define COMPAT_LEVEL_1 "1" /* Introduced: Postfix 3.0 */
+#define COMPAT_LEVEL_2 "2" /* Introduced: Postfix 3.0 */
#define COMPAT_LEVEL_3_6 "3.6"
-#define LAST_COMPAT_LEVEL COMPAT_LEVEL_3_6
+#define COMPAT_LEVEL_3_11 "3.11"
+#define LAST_COMPAT_LEVEL COMPAT_LEVEL_3_11
#define VAR_COMPAT_LEVEL "compatibility_level"
#define DEF_COMPAT_LEVEL COMPAT_LEVEL_0
@@ -75,6 +76,8 @@ extern int warn_compat_break_lmtp_tls_fpt_dgst;
extern int warn_compat_relay_before_rcpt_checks;
extern int warn_compat_respectful_logging;
+extern int warn_compat_break_smtp_tlsrpt_skip_reused_hs;
+
extern long compat_level;
/*
@@ -4483,7 +4486,7 @@ extern bool var_smtp_tlsrpt_enable;
extern char *var_smtp_tlsrpt_sockname;
#define VAR_SMTP_TLSRPT_SKIP_REUSED_HS "smtp_tlsrpt_skip_reused_handshakes"
-#define DEF_SMTP_TLSRPT_SKIP_REUSED_HS "yes"
+#define DEF_SMTP_TLSRPT_SKIP_REUSED_HS "no"
#define VAR_LMTP_TLSRPT_SKIP_REUSED_HS "lmtp_tlsrpt_skip_reused_handshakes"
#define DEF_LMTP_TLSRPT_SKIP_REUSED_HS DEF_SMTP_TLSRPT_SKIP_REUSED_HS
extern int var_smtp_tlsrpt_skip_reused_hs;
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index 1d3ab0d81..102c9cd24 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 "20250418"
+#define MAIL_RELEASE_DATE "20250606"
#define MAIL_VERSION_NUMBER "3.11"
#ifdef SNAPSHOT
diff --git a/postfix/src/postalias/Makefile.in b/postfix/src/postalias/Makefile.in
index 5ed9bbb2c..751a55995 100644
--- a/postfix/src/postalias/Makefile.in
+++ b/postfix/src/postalias/Makefile.in
@@ -10,6 +10,7 @@ PROG = postalias
INC_DIR = ../../include
LIBS = ../../lib/lib$(LIB_PREFIX)global$(LIB_SUFFIX) \
../../lib/lib$(LIB_PREFIX)util$(LIB_SUFFIX)
+NOSLEEP = LD_PRELOAD=../../lib/nosleep.so
.c.o:; $(CC) $(CFLAGS) -c $*.c
@@ -23,42 +24,55 @@ Makefile: Makefile.in
update: ../../bin/$(PROG)
-tests: test1 test2 fail_test
+tests: test1 test2 fail_test mode_conflict_test
root_tests:
test1: $(PROG) map.in map-abc1.ref map-ghi1.ref map-uABC1.ref
- ${SHLIB_ENV} ${VALGRIND} ./$(PROG) map.in
+ rm -f main.cf
+ touch -t 197101010000 main.cf
+ ${SHLIB_ENV} ${VALGRIND} ./$(PROG) -c . map.in
for key in abc ghi; \
do \
- ${SHLIB_ENV} ${VALGRIND} ./$(PROG) -q $${key} map.in | diff map-$${key}1.ref -; \
+ ${SHLIB_ENV} ${VALGRIND} ./$(PROG) -c . -q $${key} map.in | diff map-$${key}1.ref -; \
done
- ${SHLIB_ENV} ${VALGRIND} ./$(PROG) -f map.in
+ ${SHLIB_ENV} ${VALGRIND} ./$(PROG) -c . -f map.in
for key in ABC; \
do \
- ${SHLIB_ENV} ${VALGRIND} ./$(PROG) -fq $${key} map.in | diff map-u$${key}1.ref -; \
+ ${SHLIB_ENV} ${VALGRIND} ./$(PROG) -c . -fq $${key} map.in | diff map-u$${key}1.ref -; \
done
- rm -f map.in.db
+ rm -f map.in.db main.cf
test2: $(PROG) map.in map-abc2.ref map-ghi2.ref map-uABC2.ref
- ${SHLIB_ENV} ${VALGRIND} ./$(PROG) map.in
+ rm -f main.cf
+ touch -t 197101010000 main.cf
+ ${SHLIB_ENV} ${VALGRIND} ./$(PROG) -c . map.in
for key in abc ghi; \
do \
- echo $${key} | ${SHLIB_ENV} ${VALGRIND} ./$(PROG) -q - map.in | diff map-$${key}2.ref -; \
+ echo $${key} | ${SHLIB_ENV} ${VALGRIND} ./$(PROG) -c . -q - map.in | diff map-$${key}2.ref -; \
done
- ${SHLIB_ENV} ${VALGRIND} ./$(PROG) -f map.in
+ ${SHLIB_ENV} ${VALGRIND} ./$(PROG) -c . -f map.in
for key in ABC; \
do \
- echo $${key} | ${SHLIB_ENV} ${VALGRIND} ./$(PROG) -fq - map.in | diff map-u$${key}2.ref -; \
+ echo $${key} | ${SHLIB_ENV} ${VALGRIND} ./$(PROG) -c . -fq - map.in | diff map-u$${key}2.ref -; \
done
- rm -f map.in.db
+ rm -f map.in.db main.cf
fail_test: $(PROG) aliases fail_test.in fail_test.ref
- -(${SHLIB_ENV} sh fail_test.in 2>&1 || exit 0) | sed \
+ rm -f main.cf
+ touch -t 197101010000 main.cf
+ -(${SHLIB_ENV} MAIL_CONFIG=. $(NOSLEEP) sh fail_test.in 2>&1 || exit 0) | sed \
-e 's/No error:/Unknown error:/' \
-e 's/Success/Unknown error: 0/' > fail_test.tmp
diff fail_test.ref fail_test.tmp
- rm -f fail_test.tmp
+ rm -f fail_test.tmp main.cf
+
+mode_conflict_test: $(PROG) mode_conflict_test.in mode_conflict_test.ref
+ rm -f main.cf
+ touch -t 197101010000 main.cf
+ $(SHLIB_ENV) MAIL_CONFIG=. $(NOSLEEP) sh -x mode_conflict_test.in >mode_conflict_test.tmp 2>&1
+ diff mode_conflict_test.ref mode_conflict_test.tmp
+ rm -f mode_conflict_test.tmp main.cf
../../bin/$(PROG): $(PROG)
cp $(PROG) ../../bin
diff --git a/postfix/src/postalias/mode_conflict_test.in b/postfix/src/postalias/mode_conflict_test.in
new file mode 100644
index 000000000..552c19de0
--- /dev/null
+++ b/postfix/src/postalias/mode_conflict_test.in
@@ -0,0 +1,21 @@
+${VALGRIND} ./postalias -d yy -d xx whatever:whatever && exit 1
+${VALGRIND} ./postalias -d yy -i whatever:whatever && exit 1
+${VALGRIND} ./postalias -d yy -q xx whatever:whatever && exit 1
+${VALGRIND} ./postalias -d yy -s whatever:whatever && exit 1
+
+${VALGRIND} ./postalias -i -d xx whatever:whatever && exit 1
+${VALGRIND} ./postalias -i -i whatever:whatever && exit 1
+${VALGRIND} ./postalias -i -q xx whatever:whatever && exit 1
+${VALGRIND} ./postalias -i -s whatever:whatever && exit 1
+
+${VALGRIND} ./postalias -q yy -d xx whatever:whatever && exit 1
+${VALGRIND} ./postalias -q yy -i whatever:whatever && exit 1
+${VALGRIND} ./postalias -q yy -q xx whatever:whatever && exit 1
+${VALGRIND} ./postalias -q yy -s whatever:whatever && exit 1
+
+${VALGRIND} ./postalias -s -d xx whatever:whatever && exit 1
+${VALGRIND} ./postalias -s -i whatever:whatever && exit 1
+${VALGRIND} ./postalias -s -q xx whatever:whatever && exit 1
+${VALGRIND} ./postalias -s -s whatever:whatever && exit 1
+
+exit 0
diff --git a/postfix/src/postalias/mode_conflict_test.ref b/postfix/src/postalias/mode_conflict_test.ref
new file mode 100644
index 000000000..da3d7b8a9
--- /dev/null
+++ b/postfix/src/postalias/mode_conflict_test.ref
@@ -0,0 +1,33 @@
++ ./postalias -d yy -d xx whatever:whatever
+postalias: fatal: specify only one of -d -i -q or -s
++ ./postalias -d yy -i whatever:whatever
+postalias: fatal: specify only one of -d -i -q or -s
++ ./postalias -d yy -q xx whatever:whatever
+postalias: fatal: specify only one of -d -i -q or -s
++ ./postalias -d yy -s whatever:whatever
+postalias: fatal: specify only one of -d -i -q or -s
++ ./postalias -i -d xx whatever:whatever
+postalias: fatal: specify only one of -d -i -q or -s
++ ./postalias -i -i whatever:whatever
+postalias: fatal: specify only one of -d -i -q or -s
++ ./postalias -i -q xx whatever:whatever
+postalias: fatal: specify only one of -d -i -q or -s
++ ./postalias -i -s whatever:whatever
+postalias: fatal: specify only one of -d -i -q or -s
++ ./postalias -q yy -d xx whatever:whatever
+postalias: fatal: specify only one of -d -i -q or -s
++ ./postalias -q yy -i whatever:whatever
+postalias: fatal: specify only one of -d -i -q or -s
++ ./postalias -q yy -q xx whatever:whatever
+postalias: fatal: specify only one of -d -i -q or -s
++ ./postalias -q yy -s whatever:whatever
+postalias: fatal: specify only one of -d -i -q or -s
++ ./postalias -s -d xx whatever:whatever
+postalias: fatal: specify only one of -d -i -q or -s
++ ./postalias -s -i whatever:whatever
+postalias: fatal: specify only one of -d -i -q or -s
++ ./postalias -s -q xx whatever:whatever
+postalias: fatal: specify only one of -d -i -q or -s
++ ./postalias -s -s whatever:whatever
+postalias: fatal: specify only one of -d -i -q or -s
++ exit 0
diff --git a/postfix/src/postalias/postalias.c b/postfix/src/postalias/postalias.c
index 5033f9da2..c17b6a1d6 100644
--- a/postfix/src/postalias/postalias.c
+++ b/postfix/src/postalias/postalias.c
@@ -734,6 +734,7 @@ int main(int argc, char **argv)
int open_flags = O_RDWR | O_CREAT | O_TRUNC;
int dict_flags = (DICT_FLAG_DUP_WARN | DICT_FLAG_FOLD_FIX
| DICT_FLAG_UTF8_REQUEST);
+ int update = 0;
char *query = 0;
char *delkey = 0;
int sequence = 0;
@@ -798,14 +799,17 @@ int main(int argc, char **argv)
msg_fatal("out of memory");
break;
case 'd':
- if (sequence || query || delkey)
- msg_fatal("specify only one of -s -q or -d");
+ if (update || sequence || query || delkey)
+ msg_fatal("specify only one of -d -i -q or -s");
delkey = optarg;
break;
case 'f':
dict_flags &= ~DICT_FLAG_FOLD_FIX;
break;
case 'i':
+ if (update || sequence || query || delkey)
+ msg_fatal("specify only one of -d -i -q or -s");
+ update = 1;
open_flags &= ~O_TRUNC;
break;
case 'n':
@@ -819,8 +823,8 @@ int main(int argc, char **argv)
postalias_flags &= ~POSTALIAS_FLAG_SAVE_PERM;
break;
case 'q':
- if (sequence || query || delkey)
- msg_fatal("specify only one of -s -q or -d");
+ if (update || sequence || query || delkey)
+ msg_fatal("specify only one of -d -i -q or -s");
query = optarg;
break;
case 'r':
@@ -828,8 +832,8 @@ int main(int argc, char **argv)
dict_flags |= DICT_FLAG_DUP_REPLACE;
break;
case 's':
- if (query || delkey)
- msg_fatal("specify only one of -s or -q or -d");
+ if (update || sequence || query || delkey)
+ msg_fatal("specify only one of -d -i -q or -s");
sequence = 1;
break;
case 'u':
diff --git a/postfix/src/postmap/Makefile.in b/postfix/src/postmap/Makefile.in
index 4f114f504..b415d57b1 100644
--- a/postfix/src/postmap/Makefile.in
+++ b/postfix/src/postmap/Makefile.in
@@ -10,6 +10,7 @@ PROG = postmap
INC_DIR = ../../include
LIBS = ../../lib/lib$(LIB_PREFIX)global$(LIB_SUFFIX) \
../../lib/lib$(LIB_PREFIX)util$(LIB_SUFFIX)
+NOSLEEP = LD_PRELOAD=../../lib/nosleep.so
.c.o:; $(CC) $(CFLAGS) -c $*.c
@@ -27,52 +28,70 @@ update: ../../bin/$(PROG)
cp $(PROG) ../../bin
tests: test1 test2 fail_test quote_test file_test lmdb_abb_test \
- lmdb_bulk_test lmdb_incr_test cdb_bulk_test
+ lmdb_bulk_test lmdb_incr_test cdb_bulk_test mode_conflict_test
root_tests:
test1: $(PROG) map.in map-abc1.ref map-ghi1.ref map-uABC1.ref
- $(SHLIB_ENV) $(VALGRIND) ./$(PROG) map.in
+ rm -f main.cf
+ touch -t 197101010000 main.cf
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c . map.in
for key in abc ghi; \
do \
- $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -q $${key} map.in | diff map-$${key}1.ref -; \
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c . -q $${key} map.in | diff map-$${key}1.ref -; \
done
- $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -f map.in
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c . -f map.in
for key in ABC; \
do \
- $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -fq $${key} map.in | diff map-u$${key}1.ref -; \
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c . -fq $${key} map.in | diff map-u$${key}1.ref -; \
done
- rm -f map.in.db
+ rm -f map.in.db main.cf
test2: $(PROG) map.in map-abc2.ref map-ghi2.ref map-uABC2.ref
- $(SHLIB_ENV) $(VALGRIND) ./$(PROG) map.in
+ rm -f main.cf
+ touch -t 197101010000 main.cf
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c . map.in
for key in abc ghi; \
do \
- echo $${key} | $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -q - map.in | diff map-$${key}2.ref -; \
+ echo $${key} | $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c . -q - map.in | diff map-$${key}2.ref -; \
done
- $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -f map.in
+ $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c . -f map.in
for key in ABC; \
do \
- echo $${key} | $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -fq - map.in | diff map-u$${key}2.ref -; \
+ echo $${key} | $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -c . -fq - map.in | diff map-u$${key}2.ref -; \
done
- rm -f map.in.db
+ rm -f map.in.db main.cf
fail_test: $(PROG) aliases fail_test.in fail_test.ref
- -($(SHLIB_ENV) sh fail_test.in || exit 0) >fail_test.tmp 2>&1
+ rm -f main.cf
+ touch -t 197101010000 main.cf
+ -($(SHLIB_ENV) MAIL_CONFIG=. $(NOSLEEP) sh fail_test.in || exit 0) >fail_test.tmp 2>&1
diff fail_test.ref fail_test.tmp
- rm -f fail_test.tmp
+ rm -f fail_test.tmp main.cf
quote_test: $(PROG) aliases quote_test.in quote_test.ref
+ rm -f main.cf
+ touch -t 197101010000 main.cf
rm -f quote_test_map.*
- $(SHLIB_ENV) sh quote_test.in >quote_test.tmp 2>&1
+ $(SHLIB_ENV) MAIL_CONFIG=. sh quote_test.in >quote_test.tmp 2>&1
diff quote_test.ref quote_test.tmp
- rm -f quote_test.tmp quote_test_map.*
+ rm -f quote_test.tmp quote_test_map.* main.cf
file_test: $(PROG) file_test.in file_test.ref
+ rm -f main.cf
+ touch -t 197101010000 main.cf
rm -f file_test_map.* postmap-file-1 postmap-file-2
- $(SHLIB_ENV) sh file_test.in >file_test.tmp 2>&1
+ $(SHLIB_ENV) MAIL_CONFIG=. $(NOSLEEP) sh file_test.in >file_test.tmp 2>&1
diff file_test.ref file_test.tmp
- rm -f file_test.tmp file_test_map.* postmap-file-1 postmap-file-2
+ rm -f file_test.tmp file_test_map.* postmap-file-1 postmap-file-2 \
+ main.cf
+
+mode_conflict_test: $(PROG) mode_conflict_test.in mode_conflict_test.ref
+ rm -f main.cf
+ touch -t 197101010000 main.cf
+ $(SHLIB_ENV) MAIL_CONFIG=. $(NOSLEEP) sh -x mode_conflict_test.in >mode_conflict_test.tmp 2>&1
+ diff mode_conflict_test.ref mode_conflict_test.tmp
+ rm -f mode_conflict_test.tmp main.cf
cdb_bulk_test: $(PROG)
rm -f cdb_bulk.cdb main.cf
@@ -80,15 +99,17 @@ cdb_bulk_test: $(PROG)
sed -e 's/.*/& &/' -e 10000q| LANG=C sort -u >cdb_bulk
touch -t 197101010000 main.cf
($(SHLIB_ENV) $(VALGRIND) ./postmap -c . cdb:cdb_bulk; \
- $(SHLIB_ENV) $(VALGRIND) ./postmap -s cdb:cdb_bulk | \
+ $(SHLIB_ENV) $(VALGRIND) ./postmap -c . -s cdb:cdb_bulk | \
LANG=C sort > cdb_bulk.tmp)
cmp cdb_bulk cdb_bulk.tmp
rm -f cdb_bulk cdb_bulk.tmp cdb_bulk.cdb main.cf
lmdb_abb_test: $(PROG) lmdb_abb lmdb_abb.ref
+ rm -f main.cf
+ touch -t 197101010000 main.cf
rm -f lmdb_abb.lmdb
- ($(SHLIB_ENV) $(VALGRIND) ./postmap lmdb:lmdb_abb; \
- $(SHLIB_ENV) $(VALGRIND) ./postmap -s lmdb:lmdb_abb | sort) >lmdb_abb.tmp 2>&1
+ ($(SHLIB_ENV) $(VALGRIND) ./postmap -c . lmdb:lmdb_abb; \
+ $(SHLIB_ENV) $(VALGRIND) ./postmap -c . -s lmdb:lmdb_abb | sort) >lmdb_abb.tmp 2>&1
diff lmdb_abb.ref lmdb_abb.tmp
rm -f lmdb_abb.tmp lmdb_abb.lmdb
@@ -99,7 +120,7 @@ lmdb_bulk_test: $(PROG)
echo lmdb_map_size=10240 >main.cf
touch -t 197101010000 main.cf
($(SHLIB_ENV) $(VALGRIND) ./postmap -c . lmdb:lmdb_retry; \
- $(SHLIB_ENV) $(VALGRIND) ./postmap -s lmdb:lmdb_retry | \
+ $(SHLIB_ENV) $(VALGRIND) ./postmap -c . -s lmdb:lmdb_retry | \
LANG=C sort > lmdb_retry.tmp)
cmp lmdb_retry lmdb_retry.tmp
rm -f lmdb_retry lmdb_retry.tmp lmdb_retry.lmdb main.cf
@@ -111,13 +132,13 @@ lmdb_incr_test: $(PROG)
echo lmdb_map_size=10240 >main.cf
touch -t 197101010000 main.cf
($(SHLIB_ENV) $(VALGRIND) ./postmap -ic . lmdb:lmdb_retry lmdb_retry.tmp)
cmp lmdb_retry lmdb_retry.tmp
rm -f lmdb_retry lmdb_retry.tmp lmdb_retry.lmdb main.cf
clean:
- rm -f *.o *core $(PROG) $(TESTPROG) *.tmp junk *.db
+ rm -f *.o *core $(PROG) $(TESTPROG) *.tmp junk *.db main.cf master.cf
tidy: clean
diff --git a/postfix/src/postmap/mode_conflict_test.in b/postfix/src/postmap/mode_conflict_test.in
new file mode 100644
index 000000000..8ccdad0c7
--- /dev/null
+++ b/postfix/src/postmap/mode_conflict_test.in
@@ -0,0 +1,21 @@
+${VALGRIND} ./postmap -d yy -d xx whatever:whatever && exit 1
+${VALGRIND} ./postmap -d yy -i whatever:whatever && exit 1
+${VALGRIND} ./postmap -d yy -q xx whatever:whatever && exit 1
+${VALGRIND} ./postmap -d yy -s whatever:whatever && exit 1
+
+${VALGRIND} ./postmap -i -d xx whatever:whatever && exit 1
+${VALGRIND} ./postmap -i -i whatever:whatever && exit 1
+${VALGRIND} ./postmap -i -q xx whatever:whatever && exit 1
+${VALGRIND} ./postmap -i -s whatever:whatever && exit 1
+
+${VALGRIND} ./postmap -q yy -d xx whatever:whatever && exit 1
+${VALGRIND} ./postmap -q yy -i whatever:whatever && exit 1
+${VALGRIND} ./postmap -q yy -q xx whatever:whatever && exit 1
+${VALGRIND} ./postmap -q yy -s whatever:whatever && exit 1
+
+${VALGRIND} ./postmap -s -d xx whatever:whatever && exit 1
+${VALGRIND} ./postmap -s -i whatever:whatever && exit 1
+${VALGRIND} ./postmap -s -q xx whatever:whatever && exit 1
+${VALGRIND} ./postmap -s -s whatever:whatever && exit 1
+
+exit 0
diff --git a/postfix/src/postmap/mode_conflict_test.ref b/postfix/src/postmap/mode_conflict_test.ref
new file mode 100644
index 000000000..89827dbe5
--- /dev/null
+++ b/postfix/src/postmap/mode_conflict_test.ref
@@ -0,0 +1,33 @@
++ ./postmap -d yy -d xx whatever:whatever
+postmap: fatal: specify only one of -d -i -q or -s
++ ./postmap -d yy -i whatever:whatever
+postmap: fatal: specify only one of -d -i -q or -s
++ ./postmap -d yy -q xx whatever:whatever
+postmap: fatal: specify only one of -d -i -q or -s
++ ./postmap -d yy -s whatever:whatever
+postmap: fatal: specify only one of -d -i -q or -s
++ ./postmap -i -d xx whatever:whatever
+postmap: fatal: specify only one of -d -i -q or -s
++ ./postmap -i -i whatever:whatever
+postmap: fatal: specify only one of -d -i -q or -s
++ ./postmap -i -q xx whatever:whatever
+postmap: fatal: specify only one of -d -i -q or -s
++ ./postmap -i -s whatever:whatever
+postmap: fatal: specify only one of -d -i -q or -s
++ ./postmap -q yy -d xx whatever:whatever
+postmap: fatal: specify only one of -d -i -q or -s
++ ./postmap -q yy -i whatever:whatever
+postmap: fatal: specify only one of -d -i -q or -s
++ ./postmap -q yy -q xx whatever:whatever
+postmap: fatal: specify only one of -d -i -q or -s
++ ./postmap -q yy -s whatever:whatever
+postmap: fatal: specify only one of -d -i -q or -s
++ ./postmap -s -d xx whatever:whatever
+postmap: fatal: specify only one of -d -i -q or -s
++ ./postmap -s -i whatever:whatever
+postmap: fatal: specify only one of -d -i -q or -s
++ ./postmap -s -q xx whatever:whatever
+postmap: fatal: specify only one of -d -i -q or -s
++ ./postmap -s -s whatever:whatever
+postmap: fatal: specify only one of -d -i -q or -s
++ exit 0
diff --git a/postfix/src/postmap/postmap.c b/postfix/src/postmap/postmap.c
index 739045081..9e8c78381 100644
--- a/postfix/src/postmap/postmap.c
+++ b/postfix/src/postmap/postmap.c
@@ -957,6 +957,7 @@ int main(int argc, char **argv)
int open_flags = O_RDWR | O_CREAT | O_TRUNC;
int dict_flags = (DICT_FLAG_DUP_WARN | DICT_FLAG_FOLD_FIX
| DICT_FLAG_UTF8_REQUEST);
+ int update = 0;
char *query = 0;
char *delkey = 0;
int sequence = 0;
@@ -1025,8 +1026,8 @@ int main(int argc, char **argv)
msg_fatal("out of memory");
break;
case 'd':
- if (sequence || query || delkey)
- msg_fatal("specify only one of -s -q or -d");
+ if (update || sequence || query || delkey)
+ msg_fatal("specify only one of -d -i -q or -s");
delkey = optarg;
break;
case 'f':
@@ -1039,6 +1040,9 @@ int main(int argc, char **argv)
postmap_flags |= POSTMAP_FLAG_HEADER_KEY;
break;
case 'i':
+ if (update || sequence || query || delkey)
+ msg_fatal("specify only one of -d -i -q or -s");
+ update = 1;
open_flags &= ~O_TRUNC;
break;
case 'm':
@@ -1055,8 +1059,8 @@ int main(int argc, char **argv)
postmap_flags &= ~POSTMAP_FLAG_SAVE_PERM;
break;
case 'q':
- if (sequence || query || delkey)
- msg_fatal("specify only one of -s -q or -d");
+ if (update || sequence || query || delkey)
+ msg_fatal("specify only one of -d -i -q or -s");
query = optarg;
break;
case 'r':
@@ -1064,8 +1068,8 @@ int main(int argc, char **argv)
dict_flags |= DICT_FLAG_DUP_REPLACE;
break;
case 's':
- if (query || delkey)
- msg_fatal("specify only one of -s or -q or -d");
+ if (update || sequence || query || delkey)
+ msg_fatal("specify only one of -d -i -q or -s");
sequence = 1;
break;
case 'u':
diff --git a/postfix/src/smtp/smtp_tlsrpt.c b/postfix/src/smtp/smtp_tlsrpt.c
index cef46d5cd..b22be52c3 100644
--- a/postfix/src/smtp/smtp_tlsrpt.c
+++ b/postfix/src/smtp/smtp_tlsrpt.c
@@ -250,6 +250,12 @@ void smtp_tlsrpt_create_wrapper(SMTP_STATE *state, const char *domain)
if (msg_verbose)
msg_info("%s: domain %s has policy %.100s",
smtp_tlsrpt_support, domain, rr->data);
+ if (warn_compat_break_smtp_tlsrpt_skip_reused_hs) {
+ msg_info("using using backwards-compatible default setting "
+ VAR_SMTP_TLSRPT_SKIP_REUSED_HS "=yes");
+ var_smtp_tlsrpt_skip_reused_hs = 1;
+ warn_compat_break_smtp_tlsrpt_skip_reused_hs = 0;
+ }
state->tlsrpt = trw_create(
/* rpt_socket_name= */ var_smtp_tlsrpt_sockname,
/* rpt_policy_domain= */ adomain,
diff --git a/postfix/src/testing/.indent.pro b/postfix/src/testing/.indent.pro
new file mode 120000
index 000000000..5c837eca6
--- /dev/null
+++ b/postfix/src/testing/.indent.pro
@@ -0,0 +1 @@
+../../.indent.pro
\ No newline at end of file
diff --git a/postfix/src/testing/Makefile.in b/postfix/src/testing/Makefile.in
new file mode 100644
index 000000000..ad624de78
--- /dev/null
+++ b/postfix/src/testing/Makefile.in
@@ -0,0 +1,35 @@
+LIB_SO = nosleep.so
+LIB_DIR = ../../lib
+INC_DIR = ../../include
+
+all: $(LIB_SO)
+
+Makefile: Makefile.in
+ cat ../../conf/makedefs.out $? >$@
+
+nosleep.so: nosleep.c
+ $(CC) $(CFLAGS) -fPIC -shared -o $@ $?
+
+update: lib_so_update
+
+lib_so_update: $(LIB_SO)
+ for i in $(LIB_SO); do \
+ cmp -s $$i $(LIB_DIR)/$$i 2>/dev/null || cp $$i $(LIB_DIR); \
+ done
+
+clean:
+ rm -f $(LIB_SO) *.o
+
+tidy: clean
+
+depend: $(MAKES)
+ (sed '1,/^# do not edit/!d' Makefile.in; \
+ set -e; for i in [a-z][a-z0-9]*.c; do \
+ $(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
+ -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' \
+ -e 's/o: \.\//o: /' -e p -e '}' ; \
+ done | LANG=C sort -u) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
+ @$(EXPORT) make -f Makefile.in Makefile 1>&2
+
+# do not edit below this line - it is generated by 'make depend'
+nosleep.o: nosleep.c
diff --git a/postfix/src/testing/nosleep.c b/postfix/src/testing/nosleep.c
new file mode 100644
index 000000000..dbbe40baf
--- /dev/null
+++ b/postfix/src/testing/nosleep.c
@@ -0,0 +1,29 @@
+/*++
+/* NAME
+/* nosleep 3
+/* SUMMARY
+/* override the system sleep(3) implementation
+/* SYNOPSIS
+/* LD_PRELOAD=/path/to/nosleep.so command....
+/*
+/* int sleep(unsigned int seconds)
+/* DESCRIPTION
+/* This sleep(3) implementation returns zero immediately. The purpose
+/* is to speed up error handler tests by skipping the delay between
+/* reporting a fatal error and before terminating the process.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+#include
+
+unsigned int sleep(unsigned int seconds)
+{
+ /* Don't sleep. */
+ return (0);
+}
diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in
index e749eb0db..7c99ae23a 100644
--- a/postfix/src/util/Makefile.in
+++ b/postfix/src/util/Makefile.in
@@ -47,7 +47,7 @@ SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \
mkmap_fail.c mkmap_lmdb.c mkmap_open.c mkmap_sdbm.c inet_prefix_top.c \
inet_addr_sizes.c quote_for_json.c mystrerror.c \
sane_sockaddr_to_hostaddr.c normalize_ws.c valid_uri_scheme.c \
- clean_ascii_cntrl_space.c normalize_v4mapped_addr.c
+ clean_ascii_cntrl_space.c normalize_v4mapped_addr.c ossl_digest.c
OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
@@ -96,7 +96,7 @@ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
mkmap_fail.o mkmap_open.o inet_prefix_top.o inet_addr_sizes.o \
quote_for_json.o mystrerror.o sane_sockaddr_to_hostaddr.o \
normalize_ws.o valid_uri_scheme.o clean_ascii_cntrl_space.o \
- normalize_v4mapped_addr.o
+ normalize_v4mapped_addr.o ossl_digest.o
# MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf.
# When hard-linking these, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ),
# otherwise it sets the PLUGIN_* macros.
@@ -129,7 +129,7 @@ HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
check_arg.h argv_attr.h msg_logger.h logwriter.h byte_mask.h \
known_tcp_ports.h sane_strtol.h hash_fnv.h ldseed.h mkmap.h \
inet_prefix_top.h inet_addr_sizes.h valid_uri_scheme.h \
- clean_ascii_cntrl_space.h normalize_v4mapped_addr.h
+ clean_ascii_cntrl_space.h normalize_v4mapped_addr.h ossl_digest.h
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
stream_test.c dup2_pass_on_exec.c
DEFS = -I. -D$(SYSTYPE)
@@ -153,7 +153,7 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
known_tcp_ports dict_stream find_inet binhash hash_fnv argv \
clean_env inet_prefix_top printable readlline quote_for_json \
normalize_ws valid_uri_scheme clean_ascii_cntrl_space \
- normalize_v4mapped_addr_test
+ normalize_v4mapped_addr_test ossl_digest_test
PLUGIN_MAP_SO = $(LIB_PREFIX)pcre$(LIB_SUFFIX) $(LIB_PREFIX)lmdb$(LIB_SUFFIX) \
$(LIB_PREFIX)cdb$(LIB_SUFFIX) $(LIB_PREFIX)sdbm$(LIB_SUFFIX)
HTABLE_FIX = NORANDOMIZE=1
@@ -635,6 +635,9 @@ clean_ascii_cntrl_space: $(LIB)
normalize_v4mapped_addr_test: normalize_v4mapped_addr_test.c $(LIB)
$(CC) $(CFLAGS) -o $@ normalize_v4mapped_addr_test.c $(LIB) $(SYSLIBS)
+ossl_digest_test: ossl_digest_test.c $(LIB)
+ $(CC) $(CFLAGS) -o $@ $@.c $(LIB) $(SYSLIBS)
+
tests: all valid_hostname_test mac_expand_test dict_test unescape_test \
hex_quote_test ctable_test inet_addr_list_test base64_code_test \
attr_scan64_test attr_scan0_test host_port_test dict_tests \
@@ -647,7 +650,7 @@ tests: all valid_hostname_test mac_expand_test dict_test unescape_test \
binhash_test argv_test inet_prefix_top_test printable_test \
valid_utf8_string_test readlline_test quote_for_json_test \
normalize_ws_test valid_uri_scheme_test clean_ascii_cntrl_space_test \
- test_normalize_v4mapped_addr
+ test_normalize_v4mapped_addr test_ossl_digest
dict_tests: all dict_test \
dict_pcre_tests dict_cidr_test dict_thash_test dict_static_test \
@@ -1136,6 +1139,9 @@ clean_ascii_cntrl_space_test: clean_ascii_cntrl_space
test_normalize_v4mapped_addr: update normalize_v4mapped_addr_test
$(SHLIB_ENV) ${VALGRIND} ./normalize_v4mapped_addr_test
+test_ossl_digest: update ossl_digest_test
+ $(SHLIB_ENV) ${VALGRIND} ./ossl_digest_test
+
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
@@ -2480,10 +2486,14 @@ myaddrinfo.o: sys_defs.h
myaddrinfo.o: valid_hostname.h
myaddrinfo.o: vbuf.h
myaddrinfo.o: vstring.h
+myflock.o: check_arg.h
myflock.o: msg.h
myflock.o: myflock.c
myflock.o: myflock.h
+myflock.o: name_mask.h
myflock.o: sys_defs.h
+myflock.o: vbuf.h
+myflock.o: vstring.h
mymalloc.o: msg.h
mymalloc.o: mymalloc.c
mymalloc.o: mymalloc.h
diff --git a/postfix/src/util/dict_cache.c b/postfix/src/util/dict_cache.c
index 4a24089f3..f87c83e53 100644
--- a/postfix/src/util/dict_cache.c
+++ b/postfix/src/util/dict_cache.c
@@ -32,6 +32,9 @@
/* int first_next;
/* const char **cache_key;
/* const char **cache_val;
+/*
+/* int dict_cache_error(cache)
+/* DICT_CACHE *cache;
/* AUXILIARY FUNCTIONS
/* void dict_cache_control(cache, name, value, ...)
/* DICT_CACHE *cache;
@@ -122,6 +125,9 @@
/* .PP
/* dict_cache_name() returns the name of the specified cache.
/*
+/* dict_cache_error() returns the error status for the underlying
+/* dictionary.
+/*
/* Arguments:
/* .IP "dbname, open_flags, dict_flags"
/* These are passed unchanged to dict_open(). The cache must
@@ -681,14 +687,21 @@ const char *dict_cache_name(DICT_CACHE *cp)
{
/*
- * This is used for verbose logging or warning messages, so the cost of
- * call is only made where needed (well sort off - code that does not
+ * This is used for verbose logging or warning messages, so the cost of a
+ * call is only made where needed (well sort of - code that does not
* execute still presents overhead for the processor pipeline, processor
* cache, etc).
*/
return (cp->name);
}
+/* dict_cache_error - get the dictionary error status */
+
+int dict_cache_error(DICT_CACHE *cp)
+{
+ return (cp->error);
+}
+
/*
* Test driver with support for interleaved access. First, enter a number of
* requests to look up, update or delete a sequence of cache entries, then
diff --git a/postfix/src/util/dict_cache.h b/postfix/src/util/dict_cache.h
index 2d403b529..ff5859679 100644
--- a/postfix/src/util/dict_cache.h
+++ b/postfix/src/util/dict_cache.h
@@ -31,6 +31,7 @@ extern int dict_cache_delete(DICT_CACHE *, const char *);
extern int dict_cache_sequence(DICT_CACHE *, int, const char **, const char **);
extern void dict_cache_control(DICT_CACHE *,...);
extern const char *dict_cache_name(DICT_CACHE *);
+extern int dict_cache_error(DICT_CACHE *);
#define DICT_CACHE_FLAG_VERBOSE (1<<0) /* verbose operation */
#define DICT_CACHE_FLAG_STATISTICS (1<<1) /* log cache statistics */
diff --git a/postfix/src/util/dict_cdb.c b/postfix/src/util/dict_cdb.c
index ea98363ff..885efc289 100644
--- a/postfix/src/util/dict_cdb.c
+++ b/postfix/src/util/dict_cdb.c
@@ -494,12 +494,18 @@ static DICT *dict_cdbm_open(const char *path, int dict_flags)
DICT *dict_cdb_open(const char *path, int open_flags, int dict_flags)
{
switch (open_flags & (O_RDONLY | O_RDWR | O_WRONLY | O_CREAT | O_TRUNC)) {
- case O_RDONLY: /* query mode */
+ case O_RDONLY: /* query mode */
return dict_cdbq_open(path, dict_flags);
case O_WRONLY | O_CREAT | O_TRUNC: /* create mode */
case O_RDWR | O_CREAT | O_TRUNC: /* sloppiness */
return dict_cdbm_open(path, dict_flags);
+ case O_RDWR | O_CREAT:
+ case O_RDWR:
+ /* User error. */
+ return (dict_surrogate(DICT_TYPE_CDB, path, open_flags, dict_flags,
+ "unsupported non-bulk change request"));
default:
+ /* Programmer error. */
msg_fatal("dict_cdb_open: inappropriate open flags for cdb database"
" - specify O_RDONLY or O_WRONLY|O_CREAT|O_TRUNC");
}
diff --git a/postfix/src/util/dict_db.c b/postfix/src/util/dict_db.c
index b2d0c336f..0a3a87afb 100644
--- a/postfix/src/util/dict_db.c
+++ b/postfix/src/util/dict_db.c
@@ -650,9 +650,9 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
major_version, minor_version, patch_version));
if (msg_verbose) {
- msg_info("Compiled against Berkeley DB: %d.%d.%d\n",
+ msg_info("Compiled against Berkeley DB: %d.%d.%d",
DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH);
- msg_info("Run-time linked against Berkeley DB: %d.%d.%d\n",
+ msg_info("Run-time linked against Berkeley DB: %d.%d.%d",
major_version, minor_version, patch_version);
}
#else
diff --git a/postfix/src/util/hex_code.c b/postfix/src/util/hex_code.c
index 07d224895..2abf9511a 100644
--- a/postfix/src/util/hex_code.c
+++ b/postfix/src/util/hex_code.c
@@ -46,6 +46,8 @@
/* Inserts one ":" between bytes.
/* .IP HEX_ENCODE_FLAG_APPEND
/* Append output to the buffer.
+/* .IP HEX_ENCODE_FLAG_LOWERCASE
+/* Output lowercase characters.
/* .PP
/* hex_decode_opt() enables extended functionality as controlled
/* with \fIflags\fR.
@@ -91,7 +93,8 @@
/* Application-specific. */
-static const unsigned char hex_chars[] = "0123456789ABCDEF";
+static const unsigned char lower_hex_chars[] = "0123456789abcdef";
+static const unsigned char upper_hex_chars[] = "0123456789ABCDEF";
#define UCHAR_PTR(x) ((const unsigned char *)(x))
@@ -108,12 +111,17 @@ VSTRING *hex_encode(VSTRING *result, const char *in, ssize_t len)
VSTRING *hex_encode_opt(VSTRING *result, const char *in, ssize_t len, int flags)
{
+ const unsigned char *hex_chars;
const unsigned char *cp;
int ch;
ssize_t count;
if ((flags & HEX_ENCODE_FLAG_APPEND) == 0)
VSTRING_RESET(result);
+ if ((flags & HEX_ENCODE_FLAG_LOWERCASE) != 0)
+ hex_chars = lower_hex_chars;
+ else
+ hex_chars = upper_hex_chars;
for (cp = UCHAR_PTR(in), count = len; count > 0; count--, cp++) {
ch = *cp;
VSTRING_ADDCH(result, hex_chars[(ch >> 4) & 0xf]);
@@ -256,6 +264,34 @@ static const TEST_CASE test_cases[] = {
0,
0,
},
+ {"hex_encode_to_lowercase", hex_encode_opt,
+ "\377\376\375\374\373\372",
+ sizeof("\377\376\375\374\373\372") - 1,
+ HEX_ENCODE_FLAG_LOWERCASE,
+ "fffefdfcfbfa",
+ sizeof("fffefdfcfbfa") - 1,
+ },
+ {"hex_decode_from_lowercase", hex_decode_opt,
+ "fffefdfcfbfa",
+ sizeof("fffefdfcfbfa") - 1,
+ 0,
+ "\377\376\375\374\373\372",
+ sizeof("\377\376\375\374\373\372") - 1,
+ },
+ {"hex_encode_to_uppercase", hex_encode_opt,
+ "\377\376\375\374\373\372",
+ sizeof("\377\376\375\374\373\372") - 1,
+ 0,
+ "FFFEFDFCFBFA",
+ sizeof("FFFEFDFCFBFA") - 1,
+ },
+ {"hex_decode_from_uppercase", hex_decode_opt,
+ "FFFEFDFCFBFA",
+ sizeof("FFFEFDFCFBFA") - 1,
+ 0,
+ "\377\376\375\374\373\372",
+ sizeof("\377\376\375\374\373\372") - 1,
+ },
{0},
};
diff --git a/postfix/src/util/hex_code.h b/postfix/src/util/hex_code.h
index ad923c9e2..c9a3e0c97 100644
--- a/postfix/src/util/hex_code.h
+++ b/postfix/src/util/hex_code.h
@@ -22,6 +22,7 @@
#define HEX_ENCODE_FLAG_NONE (0)
#define HEX_ENCODE_FLAG_USE_COLON (1<<0)
#define HEX_ENCODE_FLAG_APPEND (1<<1)
+#define HEX_ENCODE_FLAG_LOWERCASE (1<<2)
#define HEX_DECODE_FLAG_NONE (0)
#define HEX_DECODE_FLAG_ALLOW_COLON (1<<0)
diff --git a/postfix/src/util/mkmap_open.c b/postfix/src/util/mkmap_open.c
index 961f54403..64cb5bedd 100644
--- a/postfix/src/util/mkmap_open.c
+++ b/postfix/src/util/mkmap_open.c
@@ -29,24 +29,33 @@
/* void mkmap_close(mkmap)
/* MKMAP *mkmap;
/* DESCRIPTION
-/* This module implements support for creating Postfix databases.
-/* It is a dict(3) wrapper that adds global locking to dict-level
-/* routines where appropriate.
+/* This module adds support for creating Postfix databases from
+/* scratch. See dict(3) for a description of the \fBopen_flags\fR
+/* and \fBdict_flags\fR arguments.
/*
-/* mkmap_open() creates or truncates the named database, after
-/* appending the appropriate suffixes to the specified filename.
-/* Before the database is updated, it is locked for exclusive
-/* access, and signal delivery is suspended.
-/* See dict(3) for a description of \fBopen_flags\fR and
-/* \fBdict_flags\fR. All errors are fatal.
+/* To create a database from scratch (open_flags contains O_TRUNC),
+/* the plugin code for the database type must provide a
+/* mkmap__open() function that maintains a global lock for
+/* exclusive access until the database is closed.
+/*
+/* To access a database type that has no global locking support
+/* (no mkmap__open() function), mkmap_open() opens the database
+/* requesting its dict(3) built-in per-update locking.
+/*
+/* mkmap_open() suspends signal delivery before opening a database
+/* and resumes signal delivery when it is safe: before the first
+/* update if the database implements transaction safety, otherwise
+/* after the database is closed.
+/*
+/* All mkmap_open() errors are fatal.
/*
/* mkmap_append() appends the named (key, value) pair to the
/* database. Update errors are fatal; duplicate keys are ignored
-/* (but a warning is issued).
-/* \fBlineno\fR is used for diagnostics.
+/* (but a warning is issued). The \fBlineno\fR argument is used
+/* for diagnostic messages.
/*
-/* mkmap_close() closes the database, releases any locks,
-/* and resumes signal delivery. All errors are fatal.
+/* mkmap_close() closes the database, releases any locks, and
+/* resumes signal delivery. All errors are fatal.
/* SEE ALSO
/* sigdelay(3) suspend/resume signal delivery
/* LICENSE
@@ -63,6 +72,9 @@
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
+/*
+/* Wietse Venema
+/* porcupine.org
/*--*/
/* System library. */
@@ -125,7 +137,7 @@ MKMAP *mkmap_open(const char *type, const char *path,
*/
if ((dp = dict_open_lookup(type)) == 0)
msg_fatal("unsupported map type: %s", type);
- if (dp->mkmap_fn == 0)
+ if (dp->mkmap_fn == 0 && (open_flags & O_TRUNC) != 0)
msg_fatal("no 'map create' support for this type: %s", type);
if (msg_verbose)
msg_info("open %s %s", type, path);
@@ -136,7 +148,8 @@ MKMAP *mkmap_open(const char *type, const char *path,
* dict modules implement locking only for individual record operations,
* because most Postfix applications don't need global exclusive locks.
*/
- mkmap = dp->mkmap_fn(path);
+ if (dp->mkmap_fn != 0)
+ mkmap = dp->mkmap_fn(path);
/*
* Delay signal delivery, so that we won't leave the database in an
@@ -145,16 +158,28 @@ MKMAP *mkmap_open(const char *type, const char *path,
sigdelay();
/*
- * Truncate the database upon open, and update it. Read-write mode is
- * needed because the underlying routines read as well as write. We
- * explicitly clobber lock_fd to trigger a fatal error when a map wants
- * to unlock the database after individual transactions: that would
- * result in race condition problems. We clobbber stat_fd as well,
- * because that, too, is used only for individual-transaction clients.
+ * Create or open a database that supports global locking. We explicitly
+ * clobber the per-table lock_fd to trigger a fatal error when a table
+ * wants to release its lock after an individual transaction. We clobber
+ * stat_fd as well, because that, too, is used only for non-bulk
+ * applications.
+ */
+ if (dp->mkmap_fn != 0) { /* Global lock */
+ mkmap->dict = mkmap->open(path, open_flags, dict_flags);
+ mkmap->dict->lock_fd = -1; /* XXX just in case */
+ mkmap->dict->stat_fd = -1; /* XXX just in case */
+ }
+
+ /*
+ * Otherwise, craft a surrogate MKMAP structure and request per-update
+ * locks.
*/
- mkmap->dict = mkmap->open(path, open_flags, dict_flags);
- mkmap->dict->lock_fd = -1; /* XXX just in case */
- mkmap->dict->stat_fd = -1; /* XXX just in case */
+ else { /* Per-update lock */
+ mkmap = (MKMAP *) mymalloc(sizeof(*mkmap));
+ mkmap->dict = dp->dict_fn(path, open_flags, dict_flags | DICT_FLAG_LOCK);
+ mkmap->after_open = 0; /* No global lock */
+ mkmap->after_close = 0; /* No global unlock */
+ }
mkmap->dict->flags |= DICT_FLAG_DUP_WARN;
mkmap->multi_writer = (mkmap->dict->flags & DICT_FLAG_MULTI_WRITER);
diff --git a/postfix/src/util/myflock.c b/postfix/src/util/myflock.c
index bd903ee70..2c8ad5d8a 100644
--- a/postfix/src/util/myflock.c
+++ b/postfix/src/util/myflock.c
@@ -81,12 +81,39 @@
#include "msg.h"
#include "myflock.h"
+#include "name_mask.h"
+#include "vstring.h"
/* myflock - lock/unlock entire open file */
int myflock(int fd, int lock_style, int operation)
{
int status;
+ const static NAME_MASK lock_masks[] = {
+ "MYFLOCK_STYLE_FLOCK", MYFLOCK_STYLE_FLOCK,
+ "MYFLOCK_STYLE_FCNTL", MYFLOCK_STYLE_FCNTL,
+ 0,
+ };
+ const static NAME_MASK op_masks[] = {
+ "MYFLOCK_OP_SHARED", MYFLOCK_OP_SHARED,
+ "MYFLOCK_OP_EXCLUSIVE", MYFLOCK_OP_EXCLUSIVE,
+ "MYFLOCK_OP_NOWAIT", MYFLOCK_OP_NOWAIT,
+ 0,
+ };
+
+ if (msg_verbose) {
+ VSTRING *style_buf = vstring_alloc(100);
+ VSTRING *op_buf = vstring_alloc(100);
+
+ msg_info("myflock(%d, %s, %s)", fd,
+ str_name_mask_opt(style_buf, "lock_style", lock_masks,
+ lock_style, NAME_MASK_PIPE | NAME_MASK_NUMBER),
+ operation == MYFLOCK_OP_NONE ? "MYFLOCK_OP_NONE" :
+ str_name_mask_opt(op_buf, "operation", op_masks,
+ operation, NAME_MASK_PIPE | NAME_MASK_NUMBER));
+ vstring_free(style_buf);
+ vstring_free(op_buf);
+ }
/*
* Sanity check.
@@ -139,13 +166,15 @@ int myflock(int fd, int lock_style, int operation)
default:
msg_panic("myflock: unsupported lock style: 0x%x", lock_style);
}
+ if (msg_verbose)
+ msg_info("myflock() returns %d", status);
/*
* Return a consistent result. Some systems return EACCES when a lock is
* taken by someone else, and that would complicate error processing.
*/
if (status < 0 && (operation & MYFLOCK_OP_NOWAIT) != 0)
- if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EACCES)
+ if (errno == EWOULDBLOCK || errno == EACCES)
errno = EAGAIN;
return (status);
diff --git a/postfix/src/util/ossl_digest.c b/postfix/src/util/ossl_digest.c
new file mode 100644
index 000000000..61746953b
--- /dev/null
+++ b/postfix/src/util/ossl_digest.c
@@ -0,0 +1,244 @@
+/*++
+/* NAME
+/* ossl_digest 3
+/* SUMMARY
+/* OpenSSL message digest wrapper
+/* SYNOPSIS
+/* #define USE_TLS
+/*
+/* #include
+/*
+/* OSSL_DGST *ossl_digest_new(
+/* const char *alg_name)
+/*
+/* int ossl_digest_data(
+/* OSSL_DGST *dgst,
+/* const void *data,
+/* ssize_t data_len,
+/* VSTRING *out);
+/*
+/* ARGV *ossl_digest_get_errors(void)
+/*
+/* ARGV *ossl_digest_log_errors(
+/* void (*logger)(const char *,...))
+/*
+/* ssize_t ossl_digest_get_size(
+/* OSSL_DGST *dgst)
+/*
+/* void ossl_digest_free(
+/* OSSL_DGST *dgst)
+/* DESCRIPTION
+/* ossl_digest_new() allocates a wrapper for the named message
+/* digest algorithm. This wrapper can be used in multiple successive
+/* calls to compute a digest, and can be disposed of with
+/* ossl_digest_free().
+/*
+/* ossl_digest_data() uses the specified message digest wrapper to
+/* compute a digest over the specified data.
+/*
+/* ossl_digest_get_errors() dumps and clears the OpenSSL error stack.
+/* Each stack entry is copied to one ARGV element. NOTE: The caller
+/* should be prepared for the call to return an empty result,
+/* and always report their own error info.
+/*
+/* ossl_digest_log_errors() logs and clears the OpenSSL error stack.
+/* Each stack entry is logged by the specified function. NOTE:
+/* The caller should be prepared for the call to return an empty
+/* result, and log their own error message.
+/*
+/* ossl_digest_get_size() returns the output byte count for the
+/* specified message digest wrapper.
+/*
+/* ossl_digest_free() releases storage allocated for or by the
+/* specified message wrapper.
+/* DIAGNOSTICS
+/* Panic: ossl_digest_data() was called with an invalid data_len
+/* argument; an ossl_digest_free() argument was not created with
+/* ossl_digest_new().
+/*
+/* ossl_digest_new() returns NULL after error. ossl_digest_data()
+/* returns 0 after success, -1 after error.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+#ifdef USE_TLS
+
+ /*
+ * System library.
+ */
+#include
+
+ /*
+ * OpenSSL library.
+ */
+#include
+#include
+
+ /*
+ * Utility library.
+ */
+#include
+#include
+#include
+#include
+
+#ifndef OPENSSL_VERSION_PREREQ
+#define OPENSSL_VERSION_PREREQ(m,n) 0
+#endif
+
+ /*
+ * OpenSSL 1.1.1 compatibility crutches. Note: EVP_get_digestbyname()
+ * returns const EVP_MD * which can't be passed to EVP_MD_free(EVP_MD *).
+ */
+#if !OPENSSL_VERSION_PREREQ(3,0)
+#define EVP_MD_fetch(ct, alg_name, pr) EVP_get_digestbyname(alg_name)
+#define BC_CONST const
+#define EVP_MD_free(m) /* */
+#define EVP_MD_get_size EVP_MD_size
+#else
+#define BC_CONST /* */
+#endif
+
+ /*
+ * Opaque object.
+ */
+struct OSSL_DGST {
+ EVP_MD_CTX *mdctx;
+ BC_CONST EVP_MD *dgst_alg;
+};
+
+ /*
+ * SLMs.
+ */
+#define STR(x) vstring_str(x)
+#define LEN(x) VSTRING_LEN(x)
+
+/* ossl_digest_new - create OpenSSL digest wrapper */
+
+OSSL_DGST *ossl_digest_new(const char *alg_name)
+{
+ OSSL_DGST *dgst = (OSSL_DGST *) mymalloc(sizeof(*dgst));
+
+ /*
+ * https://docs.openssl.org/3.3/man7/ossl-guide-libcrypto-introduction
+ * "If you perform the same operation many times with the same algorithm
+ * then it is recommended to use a single explicit fetch of the algorithm
+ * and then reuse the explicitly fetched algorithm each subsequent time.
+ * This will typically be faster than implicitly fetching the algorithm
+ * every time you use it".
+ *
+ * That same text mentions that calling, for example, EVP_sha256(3), uses
+ * implicit fetching.
+ */
+ if ((dgst->dgst_alg = EVP_MD_fetch(NULL, alg_name, NULL)) != 0) {
+ if ((dgst->mdctx = EVP_MD_CTX_new()) != 0) {
+ /* Success. */
+ return (dgst);
+ }
+ EVP_MD_free(dgst->dgst_alg);
+ }
+ /* Failure. */
+ myfree(dgst);
+ return (0);
+}
+
+/* ossl_digest_data - digest one data buffer */
+
+int ossl_digest_data(OSSL_DGST *dgst, const void *data,
+ ssize_t data_len, VSTRING *out)
+{
+ unsigned int out_len;
+
+ if (data_len < 0)
+ msg_panic("ossl_digest_data: bad data_len %ld", (long) data_len);
+
+ VSTRING_RESET(out);
+ VSTRING_SPACE(out, EVP_MD_get_size(dgst->dgst_alg));
+ if (EVP_DigestInit_ex(dgst->mdctx, dgst->dgst_alg, 0) != 1
+ || EVP_DigestUpdate(dgst->mdctx, data, data_len) != 1
+ || EVP_DigestFinal_ex(dgst->mdctx, (void *) STR(out),
+ &out_len) != 1)
+ return (-1);
+ vstring_set_payload_size(out, out_len);
+ return (0);
+}
+
+/* ossl_digest_get_size - determine digest output byte count */
+
+ssize_t ossl_digest_get_size(OSSL_DGST *dgst)
+{
+ return (EVP_MD_get_size(dgst->dgst_alg));
+}
+
+/* ossl_digest_get_errors - export and clear OpenSSL error stack */
+
+ARGV *ossl_digest_get_errors(void)
+{
+ ARGV *argv = argv_alloc(1);
+ VSTRING *tmp = vstring_alloc(100);
+ unsigned long err;
+ char buffer[1024]; /* XXX */
+ const char *file;
+ const char *data;
+ int line;
+ int flags;
+
+ /*
+ * Shamelessly copied from Postfix TLS library.
+ */
+#if OPENSSL_VERSION_PREREQ(3,0)
+/* XXX: We're ignoring the function name, do we want to log it? */
+#define ERRGET(fi, l, d, fl) ERR_get_error_all(fi, l, 0, d, fl)
+#else
+#define ERRGET(fi, l, d, fl) ERR_get_error_line_data(fi, l, d, fl)
+#endif
+
+ while ((err = ERRGET(&file, &line, &data, &flags)) != 0) {
+ ERR_error_string_n(err, buffer, sizeof(buffer));
+ if (flags & ERR_TXT_STRING)
+ vstring_sprintf(tmp, "%s:%s:%d:%s:",
+ buffer, file, line, data);
+ else
+ vstring_sprintf(tmp, "%s:%s:%d:", buffer, file, line);
+ argv_add(argv, STR(tmp), (char *) 0);
+ }
+ vstring_free(tmp);
+ return (argv);
+}
+
+/* ossl_digest_log_errors - log and clear OpenSSL error stack */
+
+void ossl_digest_log_errors(void (*logger)(const char *, ...))
+{
+ unsigned long err;
+ char buffer[1024]; /* XXX */
+ const char *file;
+ const char *data;
+ int line;
+ int flags;
+
+ while ((err = ERRGET(&file, &line, &data, &flags)) != 0) {
+ ERR_error_string_n(err, buffer, sizeof(buffer));
+ if (flags & ERR_TXT_STRING)
+ logger("%s:%s:%d:%s:", buffer, file, line, data);
+ else
+ logger("%s:%s:%d:", buffer, file, line);
+ }
+}
+
+/* ossl_digest_free - dispose of digest wrapper */
+
+void ossl_digest_free(OSSL_DGST *dgst)
+{
+ EVP_MD_CTX_destroy(dgst->mdctx);
+ EVP_MD_free(dgst->dgst_alg);
+ myfree(dgst);
+}
+
+#endif /* USE_TLS */
diff --git a/postfix/src/util/ossl_digest.h b/postfix/src/util/ossl_digest.h
new file mode 100644
index 000000000..746517293
--- /dev/null
+++ b/postfix/src/util/ossl_digest.h
@@ -0,0 +1,51 @@
+#ifndef _OSSL_DIGEST_H_INCLUDED_
+#define _OSSL_DIGEST_H_INCLUDED_
+
+#ifdef USE_TLS
+
+/*++
+/* NAME
+/* ossl_digest 3h
+/* SUMMARY
+/* OpenSSL message digest wrapper
+/* SYNOPSIS
+/* #include
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * System library.
+ */
+#include
+
+/*
+ * Utility library.
+ */
+#include
+#include
+
+/*
+ * External interface.
+ */
+typedef struct OSSL_DGST OSSL_DGST;
+
+extern OSSL_DGST *ossl_digest_new(const char *);
+extern int ossl_digest_data(OSSL_DGST *, const void *data, ssize_t data_len,
+ VSTRING *out);
+extern ARGV *ossl_digest_get_errors(void);
+extern void ossl_digest_log_errors(void (*logger) (const char *,...));
+extern ssize_t ossl_digest_get_size(OSSL_DGST *);
+extern void ossl_digest_free(OSSL_DGST *);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+#endif /* USE_TLS */
+
+#endif /* _OSSL_DIGEST_H_INCLUDED_ */
diff --git a/postfix/src/util/ossl_digest_test.c b/postfix/src/util/ossl_digest_test.c
new file mode 100644
index 000000000..721e6bb92
--- /dev/null
+++ b/postfix/src/util/ossl_digest_test.c
@@ -0,0 +1,204 @@
+/*++
+/* NAME
+/* ossl_digest_test 1t
+/* SUMMARY
+/* ossl_digest unit tests
+/* SYNOPSIS
+/* ./ossl_digest_test
+/* DESCRIPTION
+/* ossl_digest_test runs and logs each configured test, reports if
+/* a test is a PASS or FAIL, and returns an exit status of zero if
+/* all tests are a PASS.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include
+#include
+#include
+#include
+
+ /*
+ * Utility library.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef USE_TLS
+
+#define LEN(x) VSTRING_LEN(x)
+#define STR(x) vstring_str(x)
+
+#define PASS 1
+#define FAIL 0
+
+/* get_error_string - return error info as one string */
+
+static char *get_error_string(void)
+{
+ VSTRING *err_string;
+ ARGV *err_list;
+
+ err_list = ossl_digest_get_errors();
+ err_string = vstring_alloc(100);
+ argv_join(err_string, err_list, '\n');
+ argv_free(err_list);
+ return (vstring_export(err_string));
+}
+
+static int reports_bad_digest_name(void)
+{
+ const char *bad_digest_name = "doesnotexist";
+ OSSL_DGST *dgst;
+ int status = PASS;
+
+ if ((dgst = ossl_digest_new(bad_digest_name)) != 0) {
+ msg_warn("want: NULL, got: %p", (void *) dgst);
+ ossl_digest_free(dgst);
+ status = FAIL;
+ } else {
+ char *err_string;
+
+ err_string = get_error_string();
+ if (strstr(err_string, bad_digest_name) == 0) {
+ status = FAIL;
+ msg_warn("want: '%s', got: '%s'", bad_digest_name, err_string);
+ }
+ myfree(err_string);
+ }
+ return (status);
+}
+
+static int computes_sha256_digests(void)
+{
+ OSSL_DGST *dgst;
+ struct DGST_TEST {
+ const char *in;
+ const char *want_hex;
+ };
+ static const struct DGST_TEST sha256_tests[] = {
+ {"",
+ "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ },
+ {"one",
+ "7692c3ad3540bb803c020b3aee66cd8887123234ea0c6e7143c0add73ff431ed",
+ },
+ {"two",
+ "3fc4ccfe745870e2c0d99f71f30ff0656c8dedd41cc1d7d3d376b0dbe685e2f3",
+ },
+ {0},
+ };
+ const struct DGST_TEST *dp;
+ int status = PASS;
+
+ if ((dgst = ossl_digest_new("sha256")) == 0) {
+ char *err_string = get_error_string();
+
+ msg_warn("want: noerror, got: '%s'", err_string);
+ myfree(err_string);
+ status = FAIL;
+ } else {
+ VSTRING *out = vstring_alloc(10);
+ VSTRING *got_hex = vstring_alloc(10);
+
+ for (dp = sha256_tests; dp->in != 0; dp++) {
+ if (ossl_digest_data(dgst, dp->in, strlen(dp->in), out) < 0) {
+ char *err_string = get_error_string();
+
+ msg_warn("want: noerror, got: '%s'", err_string);
+ myfree(err_string);
+ status = FAIL;
+ continue;
+ }
+ hex_encode(got_hex, STR(out), LEN(out));
+ lowercase(STR(got_hex));
+ if (strcmp(STR(got_hex), dp->want_hex) != 0) {
+ msg_warn("got: '%s', want: '%s'", STR(got_hex), dp->want_hex);
+ status = FAIL;
+ continue;
+ }
+ }
+ ossl_digest_free(dgst);
+ vstring_free(got_hex);
+ vstring_free(out);
+ }
+ return (status);
+}
+
+static int returns_sha256_output_size(void)
+{
+ OSSL_DGST *dgst;
+ ssize_t got_size, want_size = 256 / 8;
+ int status = PASS;
+
+ if ((dgst = ossl_digest_new("sha256")) == 0) {
+ char *err_string;
+
+ err_string = get_error_string();
+ msg_warn("want: noerror, got: '%s'", err_string);
+ myfree(err_string);
+ status = FAIL;
+ } else {
+ if ((got_size = ossl_digest_get_size(dgst)) != want_size) {
+ msg_warn("want: %ld, got: %ld", (long) got_size, (long) want_size);
+ status = FAIL;
+ }
+ ossl_digest_free(dgst);
+ }
+ return (status);
+}
+
+struct TEST_CASE {
+ const char *label;
+ int (*action) (void);
+};
+
+static const struct TEST_CASE test_cases[] = {
+ {"reports_bad_digest_name", reports_bad_digest_name,},
+ /* TODO(wietse) test ossl_digest_log_errors() */
+ {"computes_sha256_digests", computes_sha256_digests,},
+ {"returns_sha256_output_size", returns_sha256_output_size,},
+ {0},
+};
+
+int main(int argc, char **argv)
+{
+ static int tests_passed = 0;
+ static int tests_failed = 0;
+ const struct TEST_CASE *tp;
+
+ for (tp = test_cases; tp->label; tp++) {
+ msg_info("RUN %s", tp->label);
+ if (tp->action() == PASS) {
+ msg_info("PASS %s", tp->label);
+ tests_passed += 1;
+ } else {
+ msg_info("FAIL %s", tp->label);
+ tests_failed += 1;
+ }
+ }
+ msg_info("PASS=%d FAIL=%d", tests_passed, tests_failed);
+ exit(tests_failed != 0);
+}
+
+#else
+
+int main(int argc, char **argv)
+{
+ msg_fatal("this program requires `#define USE_TLS'");
+}
+
+#endif
diff --git a/postfix/src/verify/verify.c b/postfix/src/verify/verify.c
index 8e8dd2517..e18c6c246 100644
--- a/postfix/src/verify/verify.c
+++ b/postfix/src/verify/verify.c
@@ -481,14 +481,20 @@ static void verify_query_service(VSTREAM *client_stream)
/* FIX 200501 IPv6 patch did not neuter ":" in address literals. */
translit(STR(addr), ":", "_");
- if ((raw_data = dict_cache_lookup(verify_map, STR(addr))) == 0 /* not found */
- || ((get_buf = vstring_alloc(10)),
- vstring_strcpy(get_buf, raw_data), /* malformed */
- verify_parse_entry(STR(get_buf), &addr_status, &probed,
- &updated, &text) < 0)
- || (now - probed > PROBE_TTL /* safe to probe */
- && (POSITIVE_ENTRY_EXPIRED(addr_status, updated)
- || NEGATIVE_ENTRY_EXPIRED(addr_status, updated)))) {
+ raw_data = dict_cache_lookup(verify_map, STR(addr));
+ if (dict_cache_error(verify_map) != 0) {
+ addr_status = DEL_RCPT_STAT_DEFER;
+ probed = 0;
+ updated = 0;
+ text = "Address verification status unavailable";
+ } else if (raw_data == 0 /* not found */
+ || ((get_buf = vstring_alloc(10)),
+ vstring_strcpy(get_buf, raw_data), /* malformed */
+ verify_parse_entry(STR(get_buf), &addr_status, &probed,
+ &updated, &text) < 0)
+ || (now - probed > PROBE_TTL /* safe to probe */
+ && (POSITIVE_ENTRY_EXPIRED(addr_status, updated)
+ || NEGATIVE_ENTRY_EXPIRED(addr_status, updated)))) {
addr_status = DEL_RCPT_STAT_TODO;
probed = 0;
updated = 0;
@@ -525,7 +531,7 @@ static void verify_query_service(VSTREAM *client_stream)
#define NEGATIVE_REFRESH_NEEDED(addr_status, updated) \
(addr_status != DEL_RCPT_STAT_OK && updated + var_verify_neg_try < now)
- if (now - probed > PROBE_TTL
+ if (dict_cache_error(verify_map) == 0 && now - probed > PROBE_TTL
&& (POSITIVE_REFRESH_NEEDED(addr_status, updated)
|| NEGATIVE_REFRESH_NEEDED(addr_status, updated))) {
if (msg_verbose)
@@ -534,7 +540,7 @@ static void verify_query_service(VSTREAM *client_stream)
post_mail_fopen_async(make_verify_sender_addr(), STR(addr),
MAIL_SRC_MASK_VERIFY,
DEL_REQ_FLAG_MTA_VRFY,
- /* TODO(wietse) disable REQUIRETLS? */
+ /* TODO(wietse) disable REQUIRETLS? */
SMTPUTF8_FLAG_NONE,
(VSTRING *) 0,
verify_post_mail_action,