-TNBBIO
-TNVTABLE_INFO
-TOPTIONS
+-TOSSL_DGST
-TPCF_DBMS_INFO
-TPCF_DEPR_PARAM_INFO
-TPCF_EVAL_CTX
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
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].
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
* 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.
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:
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
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
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
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
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:
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
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
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
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
# p\bpo\bos\bst\btc\bco\bon\bnf\bf "\b"r\bre\bes\bsp\bpe\bec\bct\btf\bfu\bul\bl_\b_l\blo\bog\bgg\bgi\bin\bng\bg =\b= n\bno\bo"\b"
# p\bpo\bos\bst\btf\bfi\bix\bx r\bre\bel\blo\boa\bad\bd
+U\bUs\bsi\bin\bng\bg b\bba\bac\bck\bkw\bwa\bar\brd\bds\bs-\b-c\bco\bom\bmp\bpa\bat\bti\bib\bbl\ble\be d\bde\bef\bfa\bau\bul\blt\bt s\bse\bet\btt\bti\bin\bng\bg
+s\bsm\bmt\btp\bp_\b_t\btl\bls\bsr\brp\bpt\bt_\b_s\bsk\bki\bip\bp_\b_r\bre\beu\bus\bse\bed\bd_\b_h\bha\ban\bnd\bds\bsh\bha\bak\bke\bes\bs=\b=y\bye\bes\bs
+
+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:
+
+ # p\bpo\bos\bst\btc\bco\bon\bnf\bf s\bsm\bmt\btp\bp_\b_t\btl\bls\bsr\brp\bpt\bt_\b_s\bsk\bki\bip\bp_\b_r\bre\beu\bus\bse\bed\bd_\b_h\bha\ban\bnd\bds\bsh\bha\bak\bke\bes\bs=\b=y\bye\bes\bs
+ # p\bpo\bos\bst\btf\bfi\bix\bx r\bre\bel\blo\boa\bad\bd
+
T\bTu\bur\brn\bni\bin\bng\bg o\bof\bff\bf t\bth\bhe\be b\bba\bac\bck\bkw\bwa\bar\brd\bds\bs-\b-c\bco\bom\bmp\bpa\bat\bti\bib\bbi\bil\bli\bit\bty\by s\bsa\baf\bfe\bet\bty\by n\bne\bet\bt
Backwards compatibility is turned off by updating the compatibility_level
"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.
C\bCr\bre\bed\bdi\bit\bts\bs
Untrusted T\bTL\bLS\bS c\bco\bon\bnn\bne\bec\bct\bti\bio\bon\bn r\bre\beu\bus\bse\bed\bd 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.
M\bMT\bTA\bA-\b-S\bST\bTS\bS S\bSu\bup\bpp\bpo\bor\brt\bt v\bvi\bia\ba s\bsm\bmt\btp\bp_\b_t\btl\bls\bs_\b_p\bpo\bol\bli\bic\bcy\by_\b_m\bma\bap\bps\bs
-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.
</ul>
+<p> Logged with <a href="postconf.5.html#compatibility_level">compatibility_level</a> < 3.11: </p>
+
+<ul>
+
+<li> <p> <a href="#tlsrpt_reused"> using backwards-compatible default
+setting smtp_tlsrpt_skip_reused_handshakes=yes</a> </p>
+
+</ul>
+
+<p>
+
<p> If such a message is logged in the context of a legitimate
request, the system administrator should make the backwards-compatible
setting permanent in <a href="postconf.5.html">main.cf</a> or <a href="master.5.html">master.cf</a>, as detailed in the
Postfix is updated from an older version. The backwards-compatibility
safety net is designed to prevent such surprises. </p>
-<p> As long as the <a href="postconf.5.html#append_dot_mydomain">append_dot_mydomain</a> parameter is left at
+<p> As long as the <a href="postconf.5.html#append_dot_mydomain">append_dot_mydomain</a> parameter is left unspecified
+at
its implicit default value, and the <a href="postconf.5.html#compatibility_level">compatibility_level</a> setting is
less than 1, Postfix may log one of the following messages:</p>
safety net is designed allow the administrator to choose if they
want to keep the old behavior. </p>
-<p> As long as a <a href="master.5.html">master.cf</a> chroot field is left at its
+<p> As long as a <a href="master.5.html">master.cf</a> chroot field is left unspecified at its
implicit default value, and the <a href="postconf.5.html#compatibility_level">compatibility_level</a> setting
is less than 1, Postfix may log the following message while it
reads the <a href="master.5.html">master.cf</a> file: </p>
net is designed to prevent such surprises. </p>
<p> When the <a href="postconf.5.html#compatibility_level">compatibility_level</a> less than 1, and the
-<a href="postconf.5.html#smtpd_relay_restrictions">smtpd_relay_restrictions</a> parameter is left at its implicit default
+<a href="postconf.5.html#smtpd_relay_restrictions">smtpd_relay_restrictions</a> parameter is left unspecified at its
+implicit default
setting, Postfix may log the following message: </p>
<blockquote>
Postfix is updated from an older version. The backwards-compatibility
safety net is designed to prevent such surprises. </p>
-<p> As long as the <a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> parameter is left at its implicit
+<p> As long as the <a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> parameter is left unspecified
+at its implicit
default value, and the <a href="postconf.5.html#compatibility_level">compatibility_level</a> setting is
less than 1, Postfix logs a warning each time an SMTP command uses a
non-ASCII address localpart without requesting SMTPUTF8 support: </p>
safety net is designed to prevent such surprises. </p>
<p> As long as the <a href="postconf.5.html#mynetworks">mynetworks</a> and <a href="postconf.5.html#mynetworks_style">mynetworks_style</a> parameters are
-left at their implicit default values, and the <a href="postconf.5.html#compatibility_level">compatibility_level</a>
+left unspecified at their implicit default values, and the
+<a href="postconf.5.html#compatibility_level">compatibility_level</a>
setting is less than 2, the Postfix SMTP server may log one of the
following messages: </p>
version. The backwards-compatibility safety net is designed to
prevent such surprises. </p>
-<p> As long as the <a href="postconf.5.html#relay_domains">relay_domains</a> parameter is left at its implicit
+<p> As long as the <a href="postconf.5.html#relay_domains">relay_domains</a> parameter is left unspecified at
+its implicit
default value, and the <a href="postconf.5.html#compatibility_level">compatibility_level</a> setting is less than 2,
Postfix may log one of the following messages. </p>
with the "sha256" digests of the expected client certificate or public
key. </p>
-<p> As long as the <a href="postconf.5.html#smtpd_tls_fingerprint_digest">smtpd_tls_fingerprint_digest</a> parameter is left at its
+<p> As long as the <a href="postconf.5.html#smtpd_tls_fingerprint_digest">smtpd_tls_fingerprint_digest</a> parameter is left
+unspecified at its
implicit default value, and the <a href="postconf.5.html#compatibility_level">compatibility_level</a> 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: </p>
the expected server certificates or public keys. </p>
<p> As long as the <a href="postconf.5.html#smtp_tls_fingerprint_digest">smtp_tls_fingerprint_digest</a> (or LMTP equivalent)
-parameter is left at its implicit default value, and the
+parameter is left unspecified at its implicit default value, and
+the
<a href="postconf.5.html#compatibility_level">compatibility_level</a> 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: </p>
keep evaluating <a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> before
<a href="postconf.5.html#smtpd_relay_restrictions">smtpd_relay_restrictions</a>, as long as the <a href="postconf.5.html#compatibility_level">compatibility_level</a> is
less than 3.6, and the <a href="postconf.5.html#smtpd_relay_before_recipient_restrictions">smtpd_relay_before_recipient_restrictions</a>
-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: </p>
<blockquote>
<p> To avoid breaking existing logfile analysis tools, Postfix will keep
logging the deprecated form, as long as the <a href="postconf.5.html#respectful_logging">respectful_logging</a> parameter
-is left at its implicit default value, and the <a href="postconf.5.html#compatibility_level">compatibility_level</a>
+is left unspecified at its implicit default value, and the
+<a href="postconf.5.html#compatibility_level">compatibility_level</a>
setting is less than 3.6. As a reminder, Postfix may log the following
when a remote SMTP client is allowlisted or denylisted: </p>
</pre>
</blockquote>
+<h2> <a name="tlsrpt_reused"> Using backwards-compatible
+default setting smtp_tlsrpt_skip_reused_handshakes=yes</a> </h2>
+
+<p> Postfix version 3.11 changes the default value for
+<a href="postconf.5.html#smtp_tlsrpt_skip_reused_handshakes">smtp_tlsrpt_skip_reused_handshakes</a> 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. </p>
+
+<p> As long as the <a href="postconf.5.html#smtp_tlsrpt_skip_reused_handshakes">smtp_tlsrpt_skip_reused_handshakes</a> parameter is
+left unspecified at its implicit default value, and the <a href="postconf.5.html#compatibility_level">compatibility_level</a>
+setting is less than 3.11, Postfix will log a reminder that it is
+using the backwards-compatible default: </p>
+
+<blockquote>
+<pre>
+postfix/smtp[388157] using backwards-compatible default setting
+ <a href="postconf.5.html#smtp_tlsrpt_skip_reused_handshakes">smtp_tlsrpt_skip_reused_handshakes</a>=yes
+</pre>
+</blockquote>
+
+<p> To keep the old default setting, the system administrator should
+make the backwards-compatible setting "<a href="postconf.5.html#smtp_tlsrpt_skip_reused_handshakes">smtp_tlsrpt_skip_reused_handshakes</a>
+= yes" permanent in <a href="postconf.5.html">main.cf</a>:
+
+<blockquote>
+<pre>
+# <b>postconf <a href="postconf.5.html#smtp_tlsrpt_skip_reused_handshakes">smtp_tlsrpt_skip_reused_handshakes</a>=yes</b>
+# <b>postfix reload</b>
+</pre>
+</blockquote>
+
<h2> <a name="turnoff">Turning off the backwards-compatibility safety net</a> </h2>
<p> Backwards compatibility is turned off by updating the
= yes" to get the historical behavior. </p>
<p> 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
<a href="https://unicode.org/cldr/utility/idna.jsp">https://unicode.org/cldr/utility/idna.jsp</a> for more examples. </p>
<h2> <a name="credits">Credits</a> </h2>
TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
</pre>
-<li> <p> 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
-"<a href="postconf.5.html#smtp_tlsrpt_skip_reused_handshakes">smtp_tlsrpt_skip_reused_handshakes</a> = no" to report the TLSRPT
-status for all TLS handshakes. This may be useful for troubleshooting.
-</p>
+<li> <p> With TLSRPT enabled, the Postfix SMTP client reports the
+TLSRPT status for all TLS handshakes (the default as of Postfix
+3.11). Specify "<a href="postconf.5.html#smtp_tlsrpt_skip_reused_handshakes">smtp_tlsrpt_skip_reused_handshakes</a> = 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. </p>
<li> <p> Postfix logging for certificate verification failures may
differ between new or reused TLS sessions. </p>
<h2> <a name="mta-sts"> MTA-STS Support via smtp_tls_policy_maps
</a></h2>
-<p> Postfix supports MTA-STS though an <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> policy
+<p> Postfix supports MTA-STS through an <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> 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
<b><a name="synchronization">SYNCHRONIZATION</a></b>
The Postfix LMDB adapter does not use LMDB's built-in locking scheme,
- because that would require world-writable lockfiles and would violate
- the Postfix security model. Instead, Postfix uses fcntl(2) locks with
- whole-file granularity. Programs that use LMDB's built-in locking pro-
- tocol will corrupt a Postfix LMDB database or will read garbage.
+ because that would require world-writable lockfiles and therefore vio-
+ late the Postfix security model. Instead, Postfix uses fcntl(2) locks
+ with whole-file granularity. Programs that use LMDB's built-in locking
+ protocol will corrupt a Postfix LMDB database or will read garbage.
Every Postfix LMDB database read or write transaction must be protected
- from start to end with a shared or exclusive fcntl(2) lock. A writer
- may atomically downgrade an exclusive lock to a shared lock, but it
- must hold an exclusive lock while opening another write transaction.
-
- Note that fcntl(2) locks do not protect transactions within the same
- process against each other. If a program cannot avoid making simulta-
- neous database requests, then it must protect its transactions with
+ from start to end with a shared or exclusive fcntl(2) lock. A process
+ may atomically downgrade an exclusive lock to a shared lock before
+ opening a database read transaction, but it must hold an exclusive lock
+ while opening a write transaction.
+
+ Note that fcntl(2) locks do not protect transactions within the same
+ process against each other. If a program cannot avoid making simulta-
+ neous database requests, then it must protect its transactions with
in-process locks, in addition to the per-process fcntl(2) locks.
<b><a name="configuration_parameters">CONFIGURATION PARAMETERS</a></b>
- Short-lived programs automatically pick up changes to <a href="postconf.5.html">main.cf</a>. With
- long-running daemon programs, Use the command "<b>postfix reload</b>" after a
+ Short-lived programs automatically pick up changes to <a href="postconf.5.html">main.cf</a>. With
+ long-running daemon programs, Use the command "<b>postfix reload</b>" after a
configuration change.
<b><a href="postconf.5.html#lmdb_map_size">lmdb_map_size</a> (16777216)</b>
time. Smaller values are relative to the time of the update.
<b><a name="memcache_key_parameters">MEMCACHE KEY PARAMETERS</a></b>
+ <b>key_digest (default: empty)</b>
+ After processing the <b>key_format</b> 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, <b>sha256</b>.
+
+ This feature is available in Postfix 3.11 and later, and
+ requires that Postfix is built with TLS support.
+
<b>key_format (default: %s)</b>
- 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 <b>key_format</b> feature is not used for <b>backup</b> database
+ NOTE 1: The <b>key_format</b> feature is not used for <b>backup</b> 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 <a href="postscreen.8.html"><b>postscreen</b>(8)</a> or <a href="verify.8.html"><b>verify</b>(8)</a> 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 <a href="postscreen.8.html"><b>postscreen</b>(8)</a> or <a href="verify.8.html"><b>verify</b>(8)</a> cache
cleanup may not work.
Examples:
<b>%s</b> This is replaced by the memcache client input key.
<b>%u</b> When the input key is an address of the form user@domain,
- <b>%u</b> is replaced by the SQL quoted local part of the
- address. Otherwise, <b>%u</b> 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
+ <b>%u</b> is replaced by the SQL quoted local part of the
+ address. Otherwise, <b>%u</b> 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).
<b>%d</b> When the input key is an address of the form user@domain,
<b>%d</b> 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).
<b>%[SUD]</b> The upper-case equivalents of the above expansions behave
- in the <b>key_format</b> parameter identically to their
+ in the <b>key_format</b> parameter identically to their
lower-case counter-parts.
- <b>%[1-9]</b> 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 <i>user@mail.example.com</i>, then
+ <b>%[1-9]</b> 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 <i>user@mail.example.com</i>, then
%1 is <b>com</b>, %2 is <b>example</b> and %3 is <b>mail</b>. 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).
<b>domain (default: no domain list)</b>
- This feature can significantly reduce database server load.
- Specify a list of domain names, paths to files, or "<a href="DATABASE_README.html">type:table</a>"
- 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 "<a href="DATABASE_README.html">type:table</a>"
+ 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, <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/searchdomains
The maximal memcache reply line length in bytes.
<b>max_try (default: 2)</b>
- 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.
<b>retry_pause (default: 1)</b>
The time in seconds before retrying a failed memcache command.
<b>timeout (default: 2)</b>
- 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.
<b><a name="bugs">BUGS</a></b>
- The Postfix memcache client cannot be used for security-sensitive
+ The Postfix memcache client cannot be used for security-sensitive
tables such as <b><a href="postconf.5.html#alias_maps">alias_maps</a></b> (these may contain "<i>|command</i> and "<i>/file/name</i>"
- destinations), or <b><a href="postconf.5.html#virtual_uid_maps">virtual_uid_maps</a></b>, <b><a href="postconf.5.html#virtual_gid_maps">virtual_gid_maps</a></b> and <b><a href="postconf.5.html#virtual_mailbox_maps">virtual_mail</a>-</b>
- <b><a href="postconf.5.html#virtual_mailbox_maps">box_maps</a></b> (these specify UNIX process privileges or "<i>/file/name</i>" 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 <b><a href="postconf.5.html#virtual_uid_maps">virtual_uid_maps</a></b>, <b><a href="postconf.5.html#virtual_gid_maps">virtual_gid_maps</a></b> and <b><a href="postconf.5.html#virtual_mailbox_maps">virtual_mail</a>-</b>
+ <b><a href="postconf.5.html#virtual_mailbox_maps">box_maps</a></b> (these specify UNIX process privileges for "<i>/file/name</i>" 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 <a href="postscreen.8.html"><b>postscreen</b>(8)</a> or <a href="verify.8.html"><b>verify</b>(8)</a> cache. For details see the <b>backup</b> and
- <b>ttl</b> parameter discussions in the MEMCACHE MAIN PARAMETERS section
+ as <a href="postscreen.8.html"><b>postscreen</b>(8)</a> or <a href="verify.8.html"><b>verify</b>(8)</a> cache. For details see the <b>backup</b> and
+ <b>ttl</b> parameter discussions in the MEMCACHE MAIN PARAMETERS section
above.
<b><a name="see_also">SEE ALSO</a></b>
TCP you have to specify
hosts = 127.0.0.1
- NOTE: if the <b>hosts</b> 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 <b>hosts</b> 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.
<b>user</b>
<b>password</b>
- 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
dbname = customer_database
<b>charset (default: utf8mb4)</b>
- 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 (<b>utf8mb4</b> as of MySQL 8.0, <b>latin1</b> historically).
<b>idle_interval (default: 60)</b>
- 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.
The number of seconds that a database connection will be skipped
after an error.
- NOTE: if the <b>hosts</b> 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 <b>hosts</b> 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.
URI, the Postfix PostgreSQL client will ignore the <b>dbname</b>, <b>user</b>,
and <b>password</b> settings for that connection.
- NOTE: if the <b>hosts</b> 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 <b>hosts</b> 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.
<b>user</b>
<b>password</b>
- 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
<b>dbname</b> The database name on the servers. Example:
dbname = customer_database
- The <b>dbname</b> setting is ignored for <b>hosts</b> connections that are
+ The <b>dbname</b> setting is ignored for <b>hosts</b> connections that are
specified as an URI.
The <b>dbname</b> setting is required with Postfix 3.10 and later, when
- <b>hosts</b> specifies any non-URI connection; it is always required
+ <b>hosts</b> specifies any non-URI connection; it is always required
with earlier Postfix versions.
<b>encoding</b>
- 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.
<b>idle_interval (default: 60)</b>
- 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.
The number of seconds that a database connection will be skipped
after an error.
- NOTE: if the <b>hosts</b> 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 <b>hosts</b> 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.
setTimeout(function() {
window.location.hash = "";
window.location.hash = hash;
- }, 1000);
+ }, 1500);
}
</script>
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 <a href="https://unicode.org/cldr/utility/idna.jsp">https://unicode.org/cldr/utility/idna.jsp</a> for more examples.
</p>
</DD>
<DT><b><a name="smtp_tlsrpt_skip_reused_handshakes">smtp_tlsrpt_skip_reused_handshakes</a>
-(default: yes)</b></DT><DD>
+(default: Postfix ≥ 3.11: no, Postfix 3.10: yes)</b></DT><DD>
-<p> 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.
+<p> 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.
</p>
<p> Note: if an SMTP over TLS connection is reused, there is no
.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
.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.
"\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
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.
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"
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.
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"
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.
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.
</ul>
+<p> Logged with compatibility_level < 3.11: </p>
+
+<ul>
+
+<li> <p> <a href="#tlsrpt_reused"> using backwards-compatible default
+setting smtp_tlsrpt_skip_reused_handshakes=yes</a> </p>
+
+</ul>
+
+<p>
+
<p> 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
Postfix is updated from an older version. The backwards-compatibility
safety net is designed to prevent such surprises. </p>
-<p> As long as the append_dot_mydomain parameter is left at
+<p> 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:</p>
safety net is designed allow the administrator to choose if they
want to keep the old behavior. </p>
-<p> As long as a master.cf chroot field is left at its
+<p> 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: </p>
net is designed to prevent such surprises. </p>
<p> 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: </p>
<blockquote>
Postfix is updated from an older version. The backwards-compatibility
safety net is designed to prevent such surprises. </p>
-<p> As long as the smtputf8_enable parameter is left at its implicit
+<p> 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: </p>
safety net is designed to prevent such surprises. </p>
<p> 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: </p>
version. The backwards-compatibility safety net is designed to
prevent such surprises. </p>
-<p> As long as the relay_domains parameter is left at its implicit
+<p> 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. </p>
with the "sha256" digests of the expected client certificate or public
key. </p>
-<p> As long as the smtpd_tls_fingerprint_digest parameter is left at its
+<p> 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: </p>
the expected server certificates or public keys. </p>
<p> 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: </p>
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: </p>
<blockquote>
<p> 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: </p>
</pre>
</blockquote>
+<h2> <a name="tlsrpt_reused"> Using backwards-compatible
+default setting smtp_tlsrpt_skip_reused_handshakes=yes</a> </h2>
+
+<p> 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. </p>
+
+<p> 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: </p>
+
+<blockquote>
+<pre>
+postfix/smtp[388157] using backwards-compatible default setting
+ smtp_tlsrpt_skip_reused_handshakes=yes
+</pre>
+</blockquote>
+
+<p> 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:
+
+<blockquote>
+<pre>
+# <b>postconf smtp_tlsrpt_skip_reused_handshakes=yes</b>
+# <b>postfix reload</b>
+</pre>
+</blockquote>
+
<h2> <a name="turnoff">Turning off the backwards-compatibility safety net</a> </h2>
<p> Backwards compatibility is turned off by updating the
= yes" to get the historical behavior. </p>
<p> 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. </p>
<h2> <a name="credits">Credits</a> </h2>
TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
</pre>
-<li> <p> 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.
-</p>
+<li> <p> 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. </p>
<li> <p> Postfix logging for certificate verification failures may
differ between new or reused TLS sessions. </p>
<h2> <a name="mta-sts"> MTA-STS Support via smtp_tls_policy_maps
</a></h2>
-<p> Postfix supports MTA-STS though an smtp_tls_policy_maps policy
+<p> 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
# .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
# 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.
# "\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
# 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.
# 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"
# 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.
# 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"
setTimeout(function() {
window.location.hash = "";
window.location.hash = hash;
- }, 1000);
+ }, 1500);
}
</script>
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.
</p>
<p> This feature is available in Postfix ≥ 3.10. </p>
-%PARAM smtp_tlsrpt_skip_reused_handshakes yes
+%PARAM smtp_tlsrpt_skip_reused_handshakes Postfix ≥ 3.11: no, Postfix 3.10: yes
-<p> 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.
+<p> 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.
</p>
<p> Note: if an SMTP over TLS connection is reused, there is no
cleartext
redacted
subclassed
+nosleep
+preload
+memcached
+Geert
+Hendrickx
+typofix
+LD
+PRELOAD
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
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
xtra
HAPROXY
SRVR
+DGST
+DIGEST
+OSSL
+ossl
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
/* Utility library. */
+#include <hex_code.h>
#include <msg.h>
#include <mymalloc.h>
#include <dict.h>
+#include <ossl_digest.h>
#include <vstring.h>
#include <stringops.h>
#include <auto_clnt.h>
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 */
#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
#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"
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 {
} 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.
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");
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);
* 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,
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);
}
const char null_format_string[1] = "";
+ /*
+ * Compatibility level 3.11.
+ */
+int warn_compat_break_smtp_tlsrpt_skip_reused_hs;
+
/*
* Compatibility level 3.6.
*/
* 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.
* 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
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;
/*
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;
* 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
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
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
--- /dev/null
+${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
--- /dev/null
++ ./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
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;
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':
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':
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':
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
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
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
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
echo lmdb_map_size=10240 >main.cf
touch -t 197101010000 main.cf
($(SHLIB_ENV) $(VALGRIND) ./postmap -ic . lmdb:lmdb_retry <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
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
--- /dev/null
+${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
--- /dev/null
++ ./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
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;
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':
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':
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':
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':
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,
--- /dev/null
+../../.indent.pro
\ No newline at end of file
--- /dev/null
+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
--- /dev/null
+/*++
+/* 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 <unistd.h>
+
+unsigned int sleep(unsigned int seconds)
+{
+ /* Don't sleep. */
+ return (0);
+}
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 \
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.
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)
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
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 \
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 \
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 \
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
/* 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;
/* .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
{
/*
- * 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
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 */
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");
}
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
/* 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.
/* 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))
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]);
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},
};
#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)
/* 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_<type>_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_<type>_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
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
+/*
+/* Wietse Venema
+/* porcupine.org
/*--*/
/* System library. */
*/
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);
* 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
sigdelay();
/*
- * Truncate the database upon open, and update it. Read-write mode is
- * needed because the underlying routines read as well as write. We
- * explicitly clobber lock_fd to trigger a fatal error when a map wants
- * to unlock the database after individual transactions: that would
- * result in race condition problems. We clobbber stat_fd as well,
- * because that, too, is used only for individual-transaction clients.
+ * Create or open a database that supports global locking. We explicitly
+ * clobber the per-table lock_fd to trigger a fatal error when a table
+ * wants to release its lock after an individual transaction. We clobber
+ * stat_fd as well, because that, too, is used only for non-bulk
+ * applications.
+ */
+ if (dp->mkmap_fn != 0) { /* Global lock */
+ mkmap->dict = mkmap->open(path, open_flags, dict_flags);
+ mkmap->dict->lock_fd = -1; /* XXX just in case */
+ mkmap->dict->stat_fd = -1; /* XXX just in case */
+ }
+
+ /*
+ * Otherwise, craft a surrogate MKMAP structure and request per-update
+ * locks.
*/
- mkmap->dict = mkmap->open(path, open_flags, dict_flags);
- mkmap->dict->lock_fd = -1; /* XXX just in case */
- mkmap->dict->stat_fd = -1; /* XXX just in case */
+ else { /* Per-update lock */
+ mkmap = (MKMAP *) mymalloc(sizeof(*mkmap));
+ mkmap->dict = dp->dict_fn(path, open_flags, dict_flags | DICT_FLAG_LOCK);
+ mkmap->after_open = 0; /* No global lock */
+ mkmap->after_close = 0; /* No global unlock */
+ }
mkmap->dict->flags |= DICT_FLAG_DUP_WARN;
mkmap->multi_writer = (mkmap->dict->flags & DICT_FLAG_MULTI_WRITER);
#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.
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);
--- /dev/null
+/*++
+/* NAME
+/* ossl_digest 3
+/* SUMMARY
+/* OpenSSL message digest wrapper
+/* SYNOPSIS
+/* #define USE_TLS
+/*
+/* #include <ossl_digest.h>
+/*
+/* 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 <sys_defs.h>
+
+ /*
+ * OpenSSL library.
+ */
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
+ /*
+ * Utility library.
+ */
+#include <msg.h>
+#include <mymalloc.h>
+#include <ossl_digest.h>
+#include <vstring.h>
+
+#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 */
--- /dev/null
+#ifndef _OSSL_DIGEST_H_INCLUDED_
+#define _OSSL_DIGEST_H_INCLUDED_
+
+#ifdef USE_TLS
+
+/*++
+/* NAME
+/* ossl_digest 3h
+/* SUMMARY
+/* OpenSSL message digest wrapper
+/* SYNOPSIS
+/* #include <ossl_digest.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+
+/*
+ * Utility library.
+ */
+#include <argv.h>
+#include <vstring.h>
+
+/*
+ * 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_ */
--- /dev/null
+/*++
+/* 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 <sys_defs.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+ /*
+ * Utility library.
+ */
+#include <argv.h>
+#include <hex_code.h>
+#include <msg.h>
+#include <mymalloc.h>
+#include <ossl_digest.h>
+#include <stringops.h>
+#include <vstring.h>
+
+#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
/* 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;
#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)
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,