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
+

Using backwards-compatible +default setting smtp_tlsrpt_skip_reused_handshakes=yes

+ +

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
+
+
+

Turning off the backwards-compatibility safety net

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.

Credits

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):

    MTA-STS Support via smtp_tls_policy_maps

    -

    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. + 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 + 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
    +

    Using backwards-compatible +default setting smtp_tlsrpt_skip_reused_handshakes=yes

    + +

    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
    +
    +
    +

    Turning off the backwards-compatibility safety net

    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.

    Credits

    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):

    MTA-STS Support via smtp_tls_policy_maps

    -

    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. */ - 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 */ + 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. + */ + 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,