mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-22 18:07:41 +00:00
postfix-2.11-20131120
This commit is contained in:
parent
f5ad0386b9
commit
4e73c4a049
@ -19168,18 +19168,44 @@ Apologies for any names omitted.
|
||||
|
||||
20131119
|
||||
|
||||
Bugfix (introduced: 20111211): the Postfix memcache client
|
||||
did not propagate a persistent "open()" lock to the optional
|
||||
backup database. File: global/dict_memcache.c.
|
||||
|
||||
Feature: a Postfix LMDB database can now be used as shared
|
||||
cache. Until now only the Postfix memcache database could
|
||||
be used in this manner. This is implemented by allowing a
|
||||
database to downgrade the permanent DICT_FLAG_OPEN_LOCK
|
||||
method to the temporary DICT_FLAG_LOCK method. Files:
|
||||
util/dict.h, util/dict_alloc.c, util/dict_open.c,
|
||||
util/dict_lmdb.c.
|
||||
persistent cache with multiple postscreen(8) or verify(8)
|
||||
daemons (but not both), without the need for a shared
|
||||
proxymap server. Files: util/dict.h, util/dict_alloc.c,
|
||||
util/dict_open.c, util/dict_lmdb.c.
|
||||
|
||||
Internal: DNS client support to report reply RCODE information,
|
||||
in addition to the simplified DNS_NOTFOUND, DNS_RETRY etc.
|
||||
Portability note: this requires the C99 __VA_ARGS__ feature.
|
||||
Files: dns/dns.h. dns/dns_lookup.c, dns/test_dns_lookup.c.
|
||||
|
||||
20131120
|
||||
|
||||
Cleanup: reduced the code footprint for the LMDB < 0.9.10
|
||||
heap-to-file information leak workaround, and simplified
|
||||
the implementation to "good enough". Files: util/dict.h,
|
||||
util/dict.c, util/dict_lmdb.c, postalias/postalias.c,
|
||||
postmap/postmap.c.
|
||||
|
||||
Cleanup: reduced the code footprint for the handling of
|
||||
multi-writer safe maps. A map only needs to assert that it
|
||||
is multi-writer safe, and the rest just happens. Files:
|
||||
util/dict.h, util/dict_open.c, util/dict_lmdb.c,
|
||||
global/dict_memcache.c.
|
||||
|
||||
Cleanup: Postfix daemons no longer restart when a multi-writer
|
||||
safe map is updated. File: util/dict.c.
|
||||
|
||||
Documentation: sharing an LMDB cache between multiple
|
||||
verify(8) or postscreen(8) servers (but not both). Files:
|
||||
proto/ADDRESS_VERIFICATION_README.html,
|
||||
proto/POSTSCREEN_README.html.
|
||||
|
||||
Cleanup: improve suppression of TLSA lookups in insecure
|
||||
zones. This is now applied not only to non-MX destinations,
|
||||
but also to each MX record. Viktor Dukhovni. Files:
|
||||
src/posttls-finger/posttls-finger.c, src/smtp/smtp_tls_policy.c,
|
||||
src/tls/tls.h, src/tls/tls_dane.c.
|
||||
|
||||
Workaround: increased the 5s connection timeout to 30s.
|
||||
Viktor Dukhovni. File: posttls-finger/posttls-finger.c.
|
||||
|
@ -292,23 +292,35 @@ parameter specifies persistent storage for sender or recipient address
|
||||
verification results. If you specify an empty value, all address verification
|
||||
results are lost after "postfix reload" or "postfix stop".
|
||||
|
||||
/etc/postfix/main.cf:
|
||||
# Default setting for Postfix 2.7 and later.
|
||||
# Example 1: Default setting for Postfix 2.7 and later.
|
||||
# Note: avoid hash files here. Use btree instead.
|
||||
/etc/postfix/main.cf:
|
||||
address_verify_map = btree:$data_directory/verify_cache
|
||||
|
||||
# Shared persistent cache (requires Postfix 2.9 or later).
|
||||
address_verify_map = proxy:btree:$data_directory/verify_cache
|
||||
# Example 2: Shared persistent lmdb: cache (Postfix 2.11 or later).
|
||||
# Disable automatic cache cleanup in all Postfix instances except
|
||||
# for one instance that will be responsible for cache cleanup.
|
||||
/etc/postfix/main.cf:
|
||||
address_verify_map = lmdb:$data_directory/verify_cache
|
||||
# address_verify_cache_cleanup_interval = 0
|
||||
|
||||
# Shared memory cache (requires Postfix 2.9 or later).
|
||||
# See memcache_table(5) for details.
|
||||
address_verify_map = memcache:/etc/postfix/verify-memcache.cf
|
||||
# Example 3: Shared persistent btree: cache (Postfix 2.9 or later).
|
||||
# Disable automatic cache cleanup in all Postfix instances except
|
||||
# for one instance that will be responsible for cache cleanup.
|
||||
/etc/postfix/main.cf:
|
||||
address_verify_map = proxy:btree:$data_directory/verify_cache
|
||||
# address_verify_cache_cleanup_interval = 0
|
||||
|
||||
# Default setting for Postfix 2.6 and earlier.
|
||||
# Example 4: Shared memory cache (requires Postfix 2.9 or later).
|
||||
# Disable automatic cache cleanup in all Postfix instances.
|
||||
# See memcache_table(5) for details.
|
||||
/etc/postfix/main.cf:
|
||||
address_verify_map = memcache:/etc/postfix/verify-memcache.cf
|
||||
address_verify_cache_cleanup_interval = 0
|
||||
|
||||
# Example 5: Default setting for Postfix 2.6 and earlier.
|
||||
# This uses non-persistent storage only.
|
||||
/etc/postfix/main.cf:
|
||||
address_verify_map =
|
||||
|
||||
NOTE 1: The database file should be stored under a Postfix-owned directory,
|
||||
|
@ -165,17 +165,8 @@ postscreen_cache_map parameter specifies the location of the temporary
|
||||
whitelist. The temporary whitelist is not used for SMTP client addresses that
|
||||
appear on the permanent access list.
|
||||
|
||||
NOTE: To share a postscreen(8) cache between multiple postscreen(8)
|
||||
instances under the same master(8) daemon, use "postscreen_cache_map =
|
||||
proxy:btree:$data_directory/postscreen_cache", and disable cache cleanup
|
||||
(postscreen_cache_cleanup_interval = 0) in all postscreen(8) instances
|
||||
except one that is responsible for cache cleanup.
|
||||
|
||||
postscreen(8) cache sharing requires Postfix 2.9 or later; earlier proxymap
|
||||
(8) implementations don't support cache cleanup.
|
||||
|
||||
For an alternative postscreen(8) cache sharing approach, see the
|
||||
memcache_table(5) manpage.
|
||||
By default the temporary whitelist is not shared with other postscreen(8)
|
||||
daemons. See Sharing the temporary whitelist below for alternatives.
|
||||
|
||||
When the SMTP client address appears on the temporary whitelist, postscreen(8)
|
||||
logs this with the client address and port number as:
|
||||
@ -551,6 +542,7 @@ systems.
|
||||
* postscreen(8) TLS configuration
|
||||
* Blocking mail with postscreen(8)
|
||||
* Turning off postscreen(8)
|
||||
* Sharing the temporary whitelist
|
||||
|
||||
TTuurrnniinngg oonn ppoossttssccrreeeenn((88)) wwiitthhoouutt bblloocckkiinngg mmaaiill
|
||||
|
||||
@ -754,6 +746,72 @@ processes:
|
||||
|
||||
6. Read the new configuration with "postfix reload".
|
||||
|
||||
SShhaarriinngg tthhee tteemmppoorraarryy wwhhiitteelliisstt
|
||||
|
||||
By default, the temporary whitelist is not shared between multiple postscreen
|
||||
(8) daemons. To enable sharing, choose one of the following options:
|
||||
|
||||
* A non-persistent memcache: temporary whitelist can be shared between
|
||||
postscreen(8) daemons on the same host or different hosts. Disable cache
|
||||
cleanup (postscreen_cache_cleanup_interval = 0) in all postscreen(8)
|
||||
daemons because memcache: does not implement this (but see example 4 below
|
||||
for memcache: with persistent backup). This requires Postfix 2.9 or later.
|
||||
|
||||
# Example 1: non-persistent memcache: whitelist.
|
||||
/etc/postfix/main.cf:
|
||||
postscreen_cache_map = memcache:/etc/postfix/postscreen_cache
|
||||
postscreen_cache_cleanup_interval = 0
|
||||
|
||||
/etc/postfix/postscreen_cache:
|
||||
memcache = inet:127.0.0.1:11211
|
||||
key_format = postscreen:%s
|
||||
|
||||
* A persistent lmdb: temporary whitelist can be shared between postscreen(8)
|
||||
daemons that run under the same master(8) daemon, or under different master
|
||||
(8) daemons on the same host. Disable cache cleanup
|
||||
(postscreen_cache_cleanup_interval = 0) in all postscreen(8) daemons except
|
||||
one that is responsible for cache cleanup. This requires Postfix 2.11 or
|
||||
later.
|
||||
|
||||
# Example 2: persistent lmdb: whitelist.
|
||||
/etc/postfix/main.cf:
|
||||
postscreen_cache_map = lmdb:$data_directory/postscreen_cache
|
||||
# See note 1 below.
|
||||
# postscreen_cache_cleanup_interval = 0
|
||||
|
||||
* Other kinds of persistent temporary whitelist can be shared only between
|
||||
postscreen(8) daemons that run under the same master(8) daemon. In this
|
||||
case, temporary whitelist access must be shared through the proxymap(8)
|
||||
daemon. This requires Postfix 2.9 or later.
|
||||
|
||||
# Example 3: proxied btree: whitelist.
|
||||
/etc/postfix/main.cf:
|
||||
postscreen_cache_map =
|
||||
proxy:btree:/var/lib/postfix/postscreen_cache
|
||||
# See note 1 below.
|
||||
# postscreen_cache_cleanup_interval = 0
|
||||
|
||||
# Example 4: proxied btree: whitelist with memcache: accelerator.
|
||||
/etc/postfix/main.cf:
|
||||
postscreen_cache_map = memcache:/etc/postfix/postscreen_cache
|
||||
proxy_write_maps =
|
||||
proxy:btree:/var/lib/postfix/postscreen_cache
|
||||
... other proxied tables ...
|
||||
# See note 1 below.
|
||||
# postscreen_cache_cleanup_interval = 0
|
||||
|
||||
/etc/postfix/postscreen_cache:
|
||||
# Note: the $data_directory macro is not defined in this context.
|
||||
memcache = inet:127.0.0.1:11211
|
||||
backup = proxy:btree:/var/lib/postfix/postscreen_cache
|
||||
key_format = postscreen:%s
|
||||
|
||||
Note 1: disable cache cleanup (postscreen_cache_cleanup_interval = 0) in
|
||||
all postscreen(8) daemons except one that is responsible for cache cleanup.
|
||||
|
||||
Note 2: postscreen(8) cache sharing via proxymap(8) requires Postfix 2.9 or
|
||||
later; earlier proxymap(8) implementations don't support cache cleanup.
|
||||
|
||||
HHiissttoorriiccaall nnootteess aanndd ccrreeddiittss
|
||||
|
||||
Many ideas in postscreen(8) were explored in earlier work by Michael Tokarev,
|
||||
|
@ -454,23 +454,35 @@ results are lost after "postfix reload" or "postfix stop". </p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
# Default setting for Postfix 2.7 and later.
|
||||
# Example 1: Default setting for Postfix 2.7 and later.
|
||||
# Note: avoid hash files here. Use btree instead.
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = btree:$<a href="postconf.5.html#data_directory">data_directory</a>/verify_cache
|
||||
|
||||
# Shared persistent cache (requires Postfix 2.9 or later).
|
||||
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="proxymap.8.html">proxy</a>:btree:$<a href="postconf.5.html#data_directory">data_directory</a>/verify_cache
|
||||
# Example 2: Shared persistent <a href="LMDB_README.html">lmdb</a>: cache (Postfix 2.11 or later).
|
||||
# Disable automatic cache cleanup in all Postfix instances except
|
||||
# for one instance that will be responsible for cache cleanup.
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="LMDB_README.html">lmdb</a>:$<a href="postconf.5.html#data_directory">data_directory</a>/verify_cache
|
||||
# <a href="postconf.5.html#address_verify_cache_cleanup_interval">address_verify_cache_cleanup_interval</a> = 0
|
||||
|
||||
# Shared memory cache (requires Postfix 2.9 or later).
|
||||
# See <a href="memcache_table.5.html">memcache_table(5)</a> for details.
|
||||
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="memcache_table.5.html">memcache</a>:/etc/postfix/verify-memcache.cf
|
||||
# Example 3: Shared persistent btree: cache (Postfix 2.9 or later).
|
||||
# Disable automatic cache cleanup in all Postfix instances except
|
||||
# for one instance that will be responsible for cache cleanup.
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="proxymap.8.html">proxy</a>:btree:$<a href="postconf.5.html#data_directory">data_directory</a>/verify_cache
|
||||
# <a href="postconf.5.html#address_verify_cache_cleanup_interval">address_verify_cache_cleanup_interval</a> = 0
|
||||
|
||||
# Default setting for Postfix 2.6 and earlier.
|
||||
# Example 4: Shared memory cache (requires Postfix 2.9 or later).
|
||||
# Disable automatic cache cleanup in all Postfix instances.
|
||||
# See <a href="memcache_table.5.html">memcache_table(5)</a> for details.
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="memcache_table.5.html">memcache</a>:/etc/postfix/verify-memcache.cf
|
||||
<a href="postconf.5.html#address_verify_cache_cleanup_interval">address_verify_cache_cleanup_interval</a> = 0
|
||||
|
||||
# Example 5: Default setting for Postfix 2.6 and earlier.
|
||||
# This uses non-persistent storage only.
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#address_verify_map">address_verify_map</a> =
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
@ -227,24 +227,9 @@ specifies the location of the temporary whitelist. The
|
||||
temporary whitelist is not used for SMTP client addresses
|
||||
that appear on the <i>permanent</i> access list. </p>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p> NOTE: To share a <a href="postscreen.8.html">postscreen(8)</a> cache between multiple
|
||||
<a href="postscreen.8.html">postscreen(8)</a> instances under the same <a href="master.8.html">master(8)</a> daemon, use
|
||||
"<tt><a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> =
|
||||
<a href="proxymap.8.html">proxy</a>:btree:$<a href="postconf.5.html#data_directory">data_directory</a>/postscreen_cache</tt>", and disable
|
||||
cache cleanup (<a href="postconf.5.html#postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a> = 0) in all
|
||||
<a href="postscreen.8.html">postscreen(8)</a> instances except one that is responsible for cache
|
||||
cleanup. </p>
|
||||
|
||||
<p> <a href="postscreen.8.html">postscreen(8)</a> cache sharing requires Postfix 2.9 or later;
|
||||
earlier <a href="proxymap.8.html">proxymap(8)</a> implementations don't support cache cleanup.
|
||||
</p>
|
||||
|
||||
<p> For an alternative <a href="postscreen.8.html">postscreen(8)</a> cache sharing approach,
|
||||
see the <a href="memcache_table.5.html">memcache_table(5)</a> manpage. </p>
|
||||
|
||||
</blockquote>
|
||||
<p> By default the temporary whitelist is not shared with other
|
||||
postscreen(8) daemons. See <a href="#temp_white_sharing"> Sharing
|
||||
the temporary whitelist </a> below for alternatives. </p>
|
||||
|
||||
<p> When the SMTP client address appears on the temporary
|
||||
whitelist, <a href="postscreen.8.html">postscreen(8)</a> logs this with the client address and port
|
||||
@ -775,6 +760,9 @@ mail</a>
|
||||
|
||||
<li> <a href="#turnoff"> Turning off postscreen(8) </a>
|
||||
|
||||
<li> <a href="#temp_white_sharing"> Sharing the temporary whitelist
|
||||
</a>
|
||||
|
||||
</ul>
|
||||
|
||||
<h3> <a name="enable"> Turning on postscreen(8) without blocking mail</a> </h3>
|
||||
@ -1057,6 +1045,87 @@ may follow. </p>
|
||||
|
||||
</ol>
|
||||
|
||||
<h3> <a name="temp_white_sharing"> Sharing the temporary whitelist </a> </h3>
|
||||
|
||||
<p> By default, the temporary whitelist is not shared between
|
||||
multiple <a href="postscreen.8.html">postscreen(8)</a> daemons. To enable sharing, choose one
|
||||
of the following options: </p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li> <p> A non-persistent <a href="memcache_table.5.html">memcache</a>: temporary whitelist can be shared
|
||||
between <a href="postscreen.8.html">postscreen(8)</a> daemons on the same host or different
|
||||
hosts. Disable cache cleanup (<a href="postconf.5.html#postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a>
|
||||
= 0) in all <a href="postscreen.8.html">postscreen(8)</a> daemons because <a href="memcache_table.5.html">memcache</a>: does not
|
||||
implement this (but see example 4 below for <a href="memcache_table.5.html">memcache</a>: with
|
||||
persistent backup). This requires Postfix 2.9 or later. </p>
|
||||
|
||||
<pre>
|
||||
# Example 1: non-persistent <a href="memcache_table.5.html">memcache</a>: whitelist.
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> = <a href="memcache_table.5.html">memcache</a>:/etc/postfix/postscreen_cache
|
||||
<a href="postconf.5.html#postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a> = 0
|
||||
|
||||
/etc/postfix/postscreen_cache:
|
||||
memcache = inet:127.0.0.1:11211
|
||||
key_format = postscreen:%s
|
||||
</pre>
|
||||
|
||||
<li> <p> A persistent <a href="LMDB_README.html">lmdb</a>: temporary whitelist can be shared between
|
||||
<a href="postscreen.8.html">postscreen(8)</a> daemons that run under the same <a href="master.8.html">master(8)</a> daemon,
|
||||
or under different <a href="master.8.html">master(8)</a> daemons on the same host. Disable
|
||||
cache cleanup (<a href="postconf.5.html#postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a> = 0) in all
|
||||
<a href="postscreen.8.html">postscreen(8)</a> daemons except one that is responsible for cache
|
||||
cleanup. This requires Postfix 2.11 or later. </p>
|
||||
|
||||
<pre>
|
||||
# Example 2: persistent <a href="LMDB_README.html">lmdb</a>: whitelist.
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> = <a href="LMDB_README.html">lmdb</a>:$<a href="postconf.5.html#data_directory">data_directory</a>/postscreen_cache
|
||||
# See note 1 below.
|
||||
# <a href="postconf.5.html#postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a> = 0
|
||||
</pre>
|
||||
|
||||
<li> <p> Other kinds of persistent temporary whitelist can be shared
|
||||
only between <a href="postscreen.8.html">postscreen(8)</a> daemons that run under the same
|
||||
<a href="master.8.html">master(8)</a> daemon. In this case, temporary whitelist access must
|
||||
be shared through the <a href="proxymap.8.html">proxymap(8)</a> daemon. This requires Postfix
|
||||
2.9 or later. </p>
|
||||
|
||||
<pre>
|
||||
# Example 3: proxied btree: whitelist.
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> =
|
||||
<a href="proxymap.8.html">proxy</a>:btree:/var/lib/postfix/postscreen_cache
|
||||
# See note 1 below.
|
||||
# <a href="postconf.5.html#postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a> = 0
|
||||
|
||||
# Example 4: proxied btree: whitelist with <a href="memcache_table.5.html">memcache</a>: accelerator.
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> = <a href="memcache_table.5.html">memcache</a>:/etc/postfix/postscreen_cache
|
||||
<a href="postconf.5.html#proxy_write_maps">proxy_write_maps</a> =
|
||||
<a href="proxymap.8.html">proxy</a>:btree:/var/lib/postfix/postscreen_cache
|
||||
... other proxied tables ...
|
||||
# See note 1 below.
|
||||
# <a href="postconf.5.html#postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a> = 0
|
||||
|
||||
/etc/postfix/postscreen_cache:
|
||||
# Note: the $<a href="postconf.5.html#data_directory">data_directory</a> macro is not defined in this context.
|
||||
memcache = inet:127.0.0.1:11211
|
||||
backup = <a href="proxymap.8.html">proxy</a>:btree:/var/lib/postfix/postscreen_cache
|
||||
key_format = postscreen:%s
|
||||
</pre>
|
||||
|
||||
<p> Note 1: disable cache cleanup (<a href="postconf.5.html#postscreen_cache_cleanup_interval">postscreen_cache_cleanup_interval</a>
|
||||
= 0) in all <a href="postscreen.8.html">postscreen(8)</a> daemons except one that is responsible
|
||||
for cache cleanup. </p>
|
||||
|
||||
<p> Note 2: <a href="postscreen.8.html">postscreen(8)</a> cache sharing via <a href="proxymap.8.html">proxymap(8)</a> requires Postfix
|
||||
2.9 or later; earlier <a href="proxymap.8.html">proxymap(8)</a> implementations don't support
|
||||
cache cleanup. </p>
|
||||
|
||||
</ul>
|
||||
|
||||
<h2> <a name="historical"> Historical notes and credits </a> </h2>
|
||||
|
||||
<p> Many ideas in <a href="postscreen.8.html">postscreen(8)</a> were explored in earlier work by
|
||||
|
@ -286,7 +286,7 @@ POSTTLS-FINGER(1) POSTTLS-FINGER(1)
|
||||
tive ports can specified by appending "<i>:service-</i>
|
||||
<i>name</i>" or ":<i>portnumber</i>" to the destination argument.
|
||||
|
||||
<b>-t</b> <i>timeout</i> (default: <b>5</b>)
|
||||
<b>-t</b> <i>timeout</i> (default: <b>30</b>)
|
||||
The TCP connection timeout to use. This is also
|
||||
the timeout for reading the remote server's 220
|
||||
banner.
|
||||
|
@ -226,7 +226,7 @@ Disable SMTP; that is, connect to an LMTP server. The default port for
|
||||
LMTP over TCP is 24. Alternative ports can specified by appending
|
||||
"\fI:servicename\fR" or ":\fIportnumber\fR" to the destination
|
||||
argument.
|
||||
.IP "\fB-t \fItimeout\fR (default: \fB5\fR)"
|
||||
.IP "\fB-t \fItimeout\fR (default: \fB30\fR)"
|
||||
The TCP connection timeout to use. This is also the timeout for
|
||||
reading the remote server's 220 banner.
|
||||
.IP "\fB-T \fItimeout\fR (default: \fB30\fR)"
|
||||
|
@ -454,23 +454,35 @@ results are lost after "postfix reload" or "postfix stop". </p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
/etc/postfix/main.cf:
|
||||
# Default setting for Postfix 2.7 and later.
|
||||
# Example 1: Default setting for Postfix 2.7 and later.
|
||||
# Note: avoid hash files here. Use btree instead.
|
||||
/etc/postfix/main.cf:
|
||||
address_verify_map = btree:$data_directory/verify_cache
|
||||
|
||||
# Shared persistent cache (requires Postfix 2.9 or later).
|
||||
address_verify_map = proxy:btree:$data_directory/verify_cache
|
||||
# Example 2: Shared persistent lmdb: cache (Postfix 2.11 or later).
|
||||
# Disable automatic cache cleanup in all Postfix instances except
|
||||
# for one instance that will be responsible for cache cleanup.
|
||||
/etc/postfix/main.cf:
|
||||
address_verify_map = lmdb:$data_directory/verify_cache
|
||||
# address_verify_cache_cleanup_interval = 0
|
||||
|
||||
# Shared memory cache (requires Postfix 2.9 or later).
|
||||
# See memcache_table(5) for details.
|
||||
address_verify_map = memcache:/etc/postfix/verify-memcache.cf
|
||||
# Example 3: Shared persistent btree: cache (Postfix 2.9 or later).
|
||||
# Disable automatic cache cleanup in all Postfix instances except
|
||||
# for one instance that will be responsible for cache cleanup.
|
||||
/etc/postfix/main.cf:
|
||||
address_verify_map = proxy:btree:$data_directory/verify_cache
|
||||
# address_verify_cache_cleanup_interval = 0
|
||||
|
||||
# Default setting for Postfix 2.6 and earlier.
|
||||
# Example 4: Shared memory cache (requires Postfix 2.9 or later).
|
||||
# Disable automatic cache cleanup in all Postfix instances.
|
||||
# See memcache_table(5) for details.
|
||||
/etc/postfix/main.cf:
|
||||
address_verify_map = memcache:/etc/postfix/verify-memcache.cf
|
||||
address_verify_cache_cleanup_interval = 0
|
||||
|
||||
# Example 5: Default setting for Postfix 2.6 and earlier.
|
||||
# This uses non-persistent storage only.
|
||||
/etc/postfix/main.cf:
|
||||
address_verify_map =
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
@ -227,24 +227,9 @@ specifies the location of the temporary whitelist. The
|
||||
temporary whitelist is not used for SMTP client addresses
|
||||
that appear on the <i>permanent</i> access list. </p>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p> NOTE: To share a postscreen(8) cache between multiple
|
||||
postscreen(8) instances under the same master(8) daemon, use
|
||||
"<tt>postscreen_cache_map =
|
||||
proxy:btree:$data_directory/postscreen_cache</tt>", and disable
|
||||
cache cleanup (postscreen_cache_cleanup_interval = 0) in all
|
||||
postscreen(8) instances except one that is responsible for cache
|
||||
cleanup. </p>
|
||||
|
||||
<p> postscreen(8) cache sharing requires Postfix 2.9 or later;
|
||||
earlier proxymap(8) implementations don't support cache cleanup.
|
||||
</p>
|
||||
|
||||
<p> For an alternative postscreen(8) cache sharing approach,
|
||||
see the memcache_table(5) manpage. </p>
|
||||
|
||||
</blockquote>
|
||||
<p> By default the temporary whitelist is not shared with other
|
||||
postscreen(8) daemons. See <a href="#temp_white_sharing"> Sharing
|
||||
the temporary whitelist </a> below for alternatives. </p>
|
||||
|
||||
<p> When the SMTP client address appears on the temporary
|
||||
whitelist, postscreen(8) logs this with the client address and port
|
||||
@ -775,6 +760,9 @@ mail</a>
|
||||
|
||||
<li> <a href="#turnoff"> Turning off postscreen(8) </a>
|
||||
|
||||
<li> <a href="#temp_white_sharing"> Sharing the temporary whitelist
|
||||
</a>
|
||||
|
||||
</ul>
|
||||
|
||||
<h3> <a name="enable"> Turning on postscreen(8) without blocking mail</a> </h3>
|
||||
@ -1057,6 +1045,87 @@ may follow. </p>
|
||||
|
||||
</ol>
|
||||
|
||||
<h3> <a name="temp_white_sharing"> Sharing the temporary whitelist </a> </h3>
|
||||
|
||||
<p> By default, the temporary whitelist is not shared between
|
||||
multiple postscreen(8) daemons. To enable sharing, choose one
|
||||
of the following options: </p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li> <p> A non-persistent memcache: temporary whitelist can be shared
|
||||
between postscreen(8) daemons on the same host or different
|
||||
hosts. Disable cache cleanup (postscreen_cache_cleanup_interval
|
||||
= 0) in all postscreen(8) daemons because memcache: does not
|
||||
implement this (but see example 4 below for memcache: with
|
||||
persistent backup). This requires Postfix 2.9 or later. </p>
|
||||
|
||||
<pre>
|
||||
# Example 1: non-persistent memcache: whitelist.
|
||||
/etc/postfix/main.cf:
|
||||
postscreen_cache_map = memcache:/etc/postfix/postscreen_cache
|
||||
postscreen_cache_cleanup_interval = 0
|
||||
|
||||
/etc/postfix/postscreen_cache:
|
||||
memcache = inet:127.0.0.1:11211
|
||||
key_format = postscreen:%s
|
||||
</pre>
|
||||
|
||||
<li> <p> A persistent lmdb: temporary whitelist can be shared between
|
||||
postscreen(8) daemons that run under the same master(8) daemon,
|
||||
or under different master(8) daemons on the same host. Disable
|
||||
cache cleanup (postscreen_cache_cleanup_interval = 0) in all
|
||||
postscreen(8) daemons except one that is responsible for cache
|
||||
cleanup. This requires Postfix 2.11 or later. </p>
|
||||
|
||||
<pre>
|
||||
# Example 2: persistent lmdb: whitelist.
|
||||
/etc/postfix/main.cf:
|
||||
postscreen_cache_map = lmdb:$data_directory/postscreen_cache
|
||||
# See note 1 below.
|
||||
# postscreen_cache_cleanup_interval = 0
|
||||
</pre>
|
||||
|
||||
<li> <p> Other kinds of persistent temporary whitelist can be shared
|
||||
only between postscreen(8) daemons that run under the same
|
||||
master(8) daemon. In this case, temporary whitelist access must
|
||||
be shared through the proxymap(8) daemon. This requires Postfix
|
||||
2.9 or later. </p>
|
||||
|
||||
<pre>
|
||||
# Example 3: proxied btree: whitelist.
|
||||
/etc/postfix/main.cf:
|
||||
postscreen_cache_map =
|
||||
proxy:btree:/var/lib/postfix/postscreen_cache
|
||||
# See note 1 below.
|
||||
# postscreen_cache_cleanup_interval = 0
|
||||
|
||||
# Example 4: proxied btree: whitelist with memcache: accelerator.
|
||||
/etc/postfix/main.cf:
|
||||
postscreen_cache_map = memcache:/etc/postfix/postscreen_cache
|
||||
proxy_write_maps =
|
||||
proxy:btree:/var/lib/postfix/postscreen_cache
|
||||
... other proxied tables ...
|
||||
# See note 1 below.
|
||||
# postscreen_cache_cleanup_interval = 0
|
||||
|
||||
/etc/postfix/postscreen_cache:
|
||||
# Note: the $data_directory macro is not defined in this context.
|
||||
memcache = inet:127.0.0.1:11211
|
||||
backup = proxy:btree:/var/lib/postfix/postscreen_cache
|
||||
key_format = postscreen:%s
|
||||
</pre>
|
||||
|
||||
<p> Note 1: disable cache cleanup (postscreen_cache_cleanup_interval
|
||||
= 0) in all postscreen(8) daemons except one that is responsible
|
||||
for cache cleanup. </p>
|
||||
|
||||
<p> Note 2: postscreen(8) cache sharing via proxymap(8) requires Postfix
|
||||
2.9 or later; earlier proxymap(8) implementations don't support
|
||||
cache cleanup. </p>
|
||||
|
||||
</ul>
|
||||
|
||||
<h2> <a name="historical"> Historical notes and credits </a> </h2>
|
||||
|
||||
<p> Many ideas in postscreen(8) were explored in earlier work by
|
||||
|
@ -98,9 +98,6 @@
|
||||
/* Request DNSSEC validation. This flag is silently ignored
|
||||
/* when the system stub resolver API, resolver(3), does not
|
||||
/* implement DNSSEC.
|
||||
/* .IP
|
||||
/* Pointer to storage for the reply RCODE value. This gives
|
||||
/* more detailed information than DNS_FAIL, DNS_RETRY, etc.
|
||||
/* .RE
|
||||
/* .IP lflags
|
||||
/* Multi-type request control for dns_lookup_l() and dns_lookup_v().
|
||||
@ -132,6 +129,9 @@
|
||||
/* name found for \fIname\fR.
|
||||
/* .IP why
|
||||
/* A null pointer, or storage for the reason for failure.
|
||||
/* .IP rcode
|
||||
/* Pointer to storage for the reply RCODE value. This gives
|
||||
/* more detailed information than DNS_FAIL, DNS_RETRY, etc.
|
||||
/* DIAGNOSTICS
|
||||
/* dns_lookup() returns one of the following codes and sets the
|
||||
/* \fIwhy\fR argument accordingly:
|
||||
|
@ -574,29 +574,10 @@ DICT *dict_memcache_open(const char *name, int open_flags, int dict_flags)
|
||||
(char *) 0, 0, 0);
|
||||
if (backup) {
|
||||
dict_mc->backup = dict_open(backup, open_flags, dict_flags);
|
||||
/* Expose backup lock and status to caller. */
|
||||
dict_mc->dict.lock = dict_mc->backup->lock;
|
||||
dict_mc->dict.lock_type = dict_mc->backup->lock_type;
|
||||
dict_mc->dict.lock_fd = dict_mc->backup->lock_fd;
|
||||
dict_mc->dict.stat_fd = dict_mc->backup->stat_fd;
|
||||
myfree(backup);
|
||||
} else
|
||||
dict_mc->backup = 0;
|
||||
|
||||
/*
|
||||
* Memcached is write-share safe. If the backup database is also
|
||||
* write-share safe, e.g. it has downgraded its persistent lock to
|
||||
* temporary, then expose that downgraded lock to the caller.
|
||||
*/
|
||||
if ((dict_flags & DICT_FLAG_OPEN_LOCK) != 0
|
||||
&& (dict_mc->backup == 0
|
||||
|| dict_mc->backup->lock_fd < 0
|
||||
|| ((dict_mc->backup->flags & DICT_FLAG_OPEN_LOCK) == 0
|
||||
&& (dict_mc->backup->flags & DICT_FLAG_LOCK) != 0))) {
|
||||
dict_mc->dict.flags &= ~DICT_FLAG_OPEN_LOCK;
|
||||
dict_mc->dict.flags |= DICT_FLAG_LOCK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse templates and common database parameters. Maps that use
|
||||
* substring keys should only be used with the full input key.
|
||||
@ -611,5 +592,7 @@ DICT *dict_memcache_open(const char *name, int open_flags, int dict_flags)
|
||||
else
|
||||
dict_mc->dict.flags |= DICT_FLAG_FIXED;
|
||||
|
||||
dict_mc->dict.flags |= DICT_FLAG_MULTI_WRITER;
|
||||
|
||||
return (&dict_mc->dict);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
* Patches change both the patchlevel and the release date. Snapshots have no
|
||||
* patchlevel; they change the release date only.
|
||||
*/
|
||||
#define MAIL_RELEASE_DATE "20131119"
|
||||
#define MAIL_RELEASE_DATE "20131120"
|
||||
#define MAIL_VERSION_NUMBER "2.11"
|
||||
|
||||
#ifdef SNAPSHOT
|
||||
|
@ -290,7 +290,6 @@ static void postalias(char *map_type, char *path_name, int postalias_flags,
|
||||
if ((source_fp = vstream_fopen(path_name, O_RDONLY, 0)) == 0)
|
||||
msg_fatal("open %s: %m", path_name);
|
||||
}
|
||||
dict_flags |= DICT_FLAG_WORLD_READ;
|
||||
if (fstat(vstream_fileno(source_fp), &st) < 0)
|
||||
msg_fatal("fstat %s: %m", path_name);
|
||||
|
||||
|
@ -353,7 +353,6 @@ static void postmap(char *map_type, char *path_name, int postmap_flags,
|
||||
if ((source_fp = vstream_fopen(path_name, O_RDONLY, 0)) == 0)
|
||||
msg_fatal("open %s: %m", path_name);
|
||||
}
|
||||
dict_flags |= DICT_FLAG_WORLD_READ;
|
||||
if (fstat(vstream_fileno(source_fp), &st) < 0)
|
||||
msg_fatal("fstat %s: %m", path_name);
|
||||
|
||||
|
@ -220,7 +220,7 @@
|
||||
/* LMTP over TCP is 24. Alternative ports can specified by appending
|
||||
/* "\fI:servicename\fR" or ":\fIportnumber\fR" to the destination
|
||||
/* argument.
|
||||
/* .IP "\fB-t \fItimeout\fR (default: \fB5\fR)"
|
||||
/* .IP "\fB-t \fItimeout\fR (default: \fB30\fR)"
|
||||
/* The TCP connection timeout to use. This is also the timeout for
|
||||
/* reading the remote server's 220 banner.
|
||||
/* .IP "\fB-T \fItimeout\fR (default: \fB30\fR)"
|
||||
@ -358,7 +358,7 @@
|
||||
*/
|
||||
#include "tlsmgrmem.h"
|
||||
|
||||
static int conn_tmout = 5;
|
||||
static int conn_tmout = 30;
|
||||
static int smtp_tmout = 30;
|
||||
|
||||
#define HOST_FLAG_DNS (1<<0)
|
||||
@ -1163,26 +1163,10 @@ static DNS_RR *host_addr(STATE *state, const char *host)
|
||||
static int dane_host_level(STATE *state, DNS_RR *addr)
|
||||
{
|
||||
int level = state->level;
|
||||
int valid;
|
||||
int mxvalid;
|
||||
|
||||
#ifdef USE_TLS
|
||||
if (level == TLS_LEV_DANE) {
|
||||
|
||||
/*
|
||||
* Suppress TLSA lookups for non-DNSSEC + non-MX + non-CNAME hosts.
|
||||
* If the host address is not DNSSEC validated, the TLSA RRset is
|
||||
* safely assumed to not be in a DNSSEC Look-aside Validation child
|
||||
* zone.
|
||||
*/
|
||||
mxvalid = state->mx == 0 || state->mx->dnssec_valid;
|
||||
valid = addr->dnssec_valid;
|
||||
if (!state->force_tlsa
|
||||
&& !valid
|
||||
&& state->mx == 0
|
||||
&& strcmp(addr->qname, addr->rname) == 0)
|
||||
mxvalid = 0;
|
||||
if (mxvalid) {
|
||||
if (state->mx == 0 || state->mx->dnssec_valid) {
|
||||
if (state->log_mask & (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE))
|
||||
tls_dane_verbose(1);
|
||||
else
|
||||
@ -1192,18 +1176,18 @@ static int dane_host_level(STATE *state, DNS_RR *addr)
|
||||
if (state->ddane)
|
||||
tls_dane_free(state->ddane);
|
||||
|
||||
/* When TLSA lookups fail, next host */
|
||||
state->ddane = tls_dane_resolve(addr->qname,
|
||||
valid ? addr->rname : 0,
|
||||
"tcp", state->port);
|
||||
/*
|
||||
* When TLSA lookups fail, next host. If unusable or not found,
|
||||
* fallback to "secure"
|
||||
*/
|
||||
state->ddane = tls_dane_resolve(state->port, "tcp", addr,
|
||||
state->force_tlsa);
|
||||
if (!state->ddane) {
|
||||
dsb_simple(state->why, "4.7.5",
|
||||
"TLSA lookup error for %s:%u",
|
||||
HNAME(addr), ntohs(state->port));
|
||||
return (TLS_LEV_INVALID);
|
||||
}
|
||||
/* If unusable or not found, same fallback to "secure" */
|
||||
if (tls_dane_notfound(state->ddane)
|
||||
level = TLS_LEV_INVALID;
|
||||
} else if (tls_dane_notfound(state->ddane)
|
||||
|| tls_dane_unusable(state->ddane)) {
|
||||
if (msg_verbose)
|
||||
msg_info("no %sTLSA records found, "
|
||||
|
@ -712,8 +712,6 @@ static int global_tls_level(void)
|
||||
static void dane_init(SMTP_TLS_POLICY *tls, SMTP_ITERATOR *iter)
|
||||
{
|
||||
TLS_DANE *dane;
|
||||
int valid;
|
||||
int mxvalid;
|
||||
|
||||
if (!iter->port) {
|
||||
msg_warn("%s: the \"dane\" security level is invalid for delivery via"
|
||||
@ -764,20 +762,8 @@ static void dane_init(SMTP_TLS_POLICY *tls, SMTP_ITERATOR *iter)
|
||||
* nexthop domain, or if the MX RRset is DNS validated, we can at least
|
||||
* try DANE with the destination host prior to CNAME expansion, but we
|
||||
* prefer CNAME expanded MX hosts if those are also secure.
|
||||
*
|
||||
* By default suppress TLSA lookups for non-DNSSEC + non-MX + non-CNAME
|
||||
* hosts. If the host address is not DNSSEC validated, the TLSA RRset is
|
||||
* safely assumed to not be in a DNSSEC Look-aside Validation child zone.
|
||||
*/
|
||||
mxvalid = iter->mx == 0 || iter->mx->dnssec_valid;
|
||||
valid = iter->rr && iter->rr->dnssec_valid;
|
||||
if (!var_smtp_tls_force_tlsa
|
||||
&& !valid
|
||||
&& iter->mx == 0
|
||||
&& strcmp(iter->rr->qname, iter->rr->rname) == 0)
|
||||
mxvalid = 0;
|
||||
|
||||
if (!mxvalid) {
|
||||
if (iter->mx && !iter->mx->dnssec_valid) {
|
||||
if (tls->level == TLS_LEV_DANE) {
|
||||
tls->level = TLS_LEV_MAY;
|
||||
if (msg_verbose)
|
||||
@ -789,8 +775,8 @@ static void dane_init(SMTP_TLS_POLICY *tls, SMTP_ITERATOR *iter)
|
||||
return;
|
||||
}
|
||||
/* When TLSA lookups fail, we defer the message */
|
||||
if ((dane = tls_dane_resolve(iter->rr->qname, valid ? iter->rr->rname : 0,
|
||||
"tcp", iter->port)) == 0) {
|
||||
if ((dane = tls_dane_resolve(iter->port, "tcp", iter->rr,
|
||||
var_smtp_tls_force_tlsa)) == 0) {
|
||||
tls->level = TLS_LEV_INVALID;
|
||||
dsb_simple(tls->why, "4.7.5", "TLSA lookup error for %s:%u",
|
||||
STR(iter->host), ntohs(iter->port));
|
||||
|
@ -90,6 +90,7 @@ extern const NAME_CODE tls_level_table[];
|
||||
#include <vstream.h>
|
||||
#include <name_mask.h>
|
||||
#include <name_code.h>
|
||||
#include <dns.h>
|
||||
|
||||
/*
|
||||
* Names of valid tlsmgr(8) session caches.
|
||||
@ -173,8 +174,7 @@ extern TLS_DANE *tls_dane_alloc(int);
|
||||
extern void tls_dane_split(TLS_DANE *, int, int, const char *, const char *,
|
||||
const char *);
|
||||
extern void tls_dane_free(TLS_DANE *);
|
||||
extern TLS_DANE *tls_dane_resolve(const char *, const char *, const char *,
|
||||
unsigned);
|
||||
extern TLS_DANE *tls_dane_resolve(unsigned, const char *, DNS_RR *, int);
|
||||
extern int tls_dane_load_trustfile(TLS_DANE *, const char *);
|
||||
|
||||
/*
|
||||
|
@ -41,11 +41,11 @@
|
||||
/* SSL_CTX *ssl_ctx;
|
||||
/* TLS_SESS_STATE *TLScontext;
|
||||
/*
|
||||
/* TLS_DANE *tls_dane_resolve(qname, rname, proto, port)
|
||||
/* const char *qname;
|
||||
/* const char *rname;
|
||||
/* const char *proto;
|
||||
/* TLS_DANE *tls_dane_resolve(port, proto, hostrr, forcetlsa)
|
||||
/* unsigned port;
|
||||
/* const char *proto;
|
||||
/* DNS_RR *hostrr;
|
||||
/* int forcetlsa;
|
||||
/*
|
||||
/* int tls_dane_unusable(dane)
|
||||
/* const TLS_DANE *dane;
|
||||
@ -96,7 +96,7 @@
|
||||
/* anchors always override the legacy public CA PKI. Otherwise, the
|
||||
/* callback MUST be cleared.
|
||||
/*
|
||||
/* tls_dane_resolve() maps a (qname, rname, protocol, port) tuple to a
|
||||
/* tls_dane_resolve() maps a (port, protocol, hostrr) tuple to a
|
||||
/* a corresponding TLS_DANE policy structure found in the DNS. The port
|
||||
/* argument is in network byte order. A null pointer is returned when
|
||||
/* the DNS query for the TLSA record tempfailed. In all other cases the
|
||||
@ -117,14 +117,17 @@
|
||||
/* .IP dane
|
||||
/* Pointer to a TLS_DANE structure that lists the valid trust-anchor
|
||||
/* and end-entity full-certificate and/or public-key digests.
|
||||
/* .IP qname
|
||||
/* FQDN of target service (original input form).
|
||||
/* .IP rname
|
||||
/* DNSSEC validated (cname resolved) FQDN of target service.
|
||||
/* .IP proto
|
||||
/* Almost certainly "tcp".
|
||||
/* .IP port
|
||||
/* The TCP port in network byte order.
|
||||
/* .IP proto
|
||||
/* Almost certainly "tcp".
|
||||
/* .IP hostrr
|
||||
/* DNS_RR pointer to TLSA base domain data. When dnssec_valid is false,
|
||||
/* the rname (and the qname if same as rname) are insecure.
|
||||
/* .IP forcetlsa
|
||||
/* When true, TLSA lookups are performed even when the qname and rname
|
||||
/* are insecure. This is only useful in the unlikely case that DLV is
|
||||
/* used to secure the TLSA RRset in an otherwise insecure zone.
|
||||
/* .IP flags
|
||||
/* Only one flag is part of the public interface at this time:
|
||||
/* .IP TLScontext
|
||||
@ -314,7 +317,7 @@ static EVP_PKEY *gencakey(void)
|
||||
|
||||
#ifdef WRAP_SIGNED
|
||||
EC_KEY *eckey;
|
||||
EC_GROUP *group;
|
||||
EC_GROUP *group = 0;
|
||||
|
||||
ERR_clear_error();
|
||||
|
||||
@ -676,14 +679,14 @@ static void parse_tlsa_rrs(TLS_DANE *dane, DNS_RR *rr)
|
||||
for ( /* nop */ ; rr; rr = rr->next) {
|
||||
const char *mdalg = 0;
|
||||
char *digest;
|
||||
int same = (strcasecmp(rr->rname, rr->qname) == 0);
|
||||
int iscname = strcasecmp(rr->rname, rr->qname);
|
||||
uint8_t *ip = (uint8_t *) rr->data;
|
||||
X509 *x = 0; /* OpenSSL tries to re-use *x if x!=0 */
|
||||
EVP_PKEY *k = 0; /* OpenSSL tries to re-use *k if k!=0 */
|
||||
digest_info *di;
|
||||
|
||||
#define rcname(rr) (same ? "" : rr->qname)
|
||||
#define rarrow(rr) (same ? "" : " -> ")
|
||||
#define rcname(rr) (iscname ? rr->qname : "")
|
||||
#define rarrow(rr) (iscname ? " -> " : "")
|
||||
|
||||
if (rr->type != T_TLSA)
|
||||
msg_panic("unexpected non-TLSA RR type %u for %s%s%s", rr->type,
|
||||
@ -946,6 +949,8 @@ static TLS_DANE *resolve_host(const char *host, const char *proto,
|
||||
dane = (TLS_DANE *) ctable_refresh(dane_cache, STR(query_domain));
|
||||
if (dane->base_domain == 0)
|
||||
dane->base_domain = mystrdup(host);
|
||||
/* Increment ref-count of cached entry */
|
||||
++dane->refs;
|
||||
return (dane);
|
||||
}
|
||||
|
||||
@ -953,10 +958,11 @@ static TLS_DANE *resolve_host(const char *host, const char *proto,
|
||||
|
||||
/* tls_dane_resolve - cached map: (name, proto, port) -> TLS_DANE */
|
||||
|
||||
TLS_DANE *tls_dane_resolve(const char *qname, const char *rname,
|
||||
const char *proto, unsigned port)
|
||||
TLS_DANE *tls_dane_resolve(unsigned port, const char *proto, DNS_RR *hostrr,
|
||||
int forcetlsa)
|
||||
{
|
||||
TLS_DANE *dane = 0;
|
||||
int iscname;
|
||||
|
||||
#ifdef DANE_TLSA_SUPPORT
|
||||
if (!tls_dane_avail())
|
||||
@ -966,19 +972,32 @@ TLS_DANE *tls_dane_resolve(const char *qname, const char *rname,
|
||||
dane_cache = ctable_create(CACHE_SIZE, dane_lookup, dane_free, 0);
|
||||
|
||||
/*
|
||||
* Try the rname first, if nothing there, try the qname. Note, lookup
|
||||
* errors are distinct from success with nothing found. If the rname
|
||||
* lookup fails we don't try the qname. The rname may be null when only
|
||||
* the qname is in a secure zone.
|
||||
* By default suppress TLSA lookups for non-DNSSEC + non-CNAME hosts. If
|
||||
* the host address is not DNSSEC validated, the TLSA RRset is safely
|
||||
* assumed to not be in a DNSSEC Look-aside Validation child zone.
|
||||
*/
|
||||
if (rname)
|
||||
dane = resolve_host(rname, proto, port);
|
||||
if (!rname || (tls_dane_notfound(dane) && strcmp(qname, rname) != 0))
|
||||
dane = resolve_host(qname, proto, port);
|
||||
if (dane->flags & TLS_DANE_FLAG_ERROR)
|
||||
return (0);
|
||||
iscname = strcasecmp(hostrr->rname, hostrr->qname);
|
||||
if (!forcetlsa && !hostrr->dnssec_valid && !iscname) {
|
||||
dane = tls_dane_alloc(0);
|
||||
dane->flags = TLS_DANE_FLAG_NORRS;
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Try the rname first, if nothing there, try the qname. Note,
|
||||
* lookup errors are distinct from success with nothing found. If
|
||||
* the rname lookup fails we don't try the qname.
|
||||
*/
|
||||
if (hostrr->dnssec_valid)
|
||||
dane = resolve_host(hostrr->rname, proto, port);
|
||||
if (!dane || (iscname && tls_dane_notfound(dane)))
|
||||
dane = resolve_host(hostrr->qname, proto, port);
|
||||
if (dane->flags & TLS_DANE_FLAG_ERROR) {
|
||||
/* We don't return this object. */
|
||||
tls_dane_free(dane);
|
||||
dane = 0;
|
||||
}
|
||||
}
|
||||
|
||||
++dane->refs;
|
||||
#endif
|
||||
return (dane);
|
||||
}
|
||||
|
@ -555,7 +555,9 @@ const char *dict_changed_name(void)
|
||||
msg_warn("%s: table %s: null time stamp", myname, h->key);
|
||||
if (fstat(dict->stat_fd, &st) < 0)
|
||||
msg_fatal("%s: fstat: %m", myname);
|
||||
if (st.st_mtime != dict->mtime || st.st_nlink == 0)
|
||||
if (((dict->flags & DICT_FLAG_MULTI_WRITER) == 0
|
||||
&& st.st_mtime != dict->mtime)
|
||||
|| st.st_nlink == 0)
|
||||
status = h->key;
|
||||
}
|
||||
myfree((char *) ht_info_list);
|
||||
@ -590,7 +592,7 @@ static const NAME_MASK dict_mask[] = {
|
||||
"fold_mul", DICT_FLAG_FOLD_MUL, /* case-fold with multi-case key map */
|
||||
"open_lock", DICT_FLAG_OPEN_LOCK, /* permanent lock upon open */
|
||||
"bulk_update", DICT_FLAG_BULK_UPDATE, /* bulk update if supported */
|
||||
"world_read", DICT_FLAG_WORLD_READ, /* assume writer != reader */
|
||||
"multi_writer", DICT_FLAG_MULTI_WRITER, /* multi-writer safe */
|
||||
0,
|
||||
};
|
||||
|
||||
|
@ -97,7 +97,7 @@ extern DICT *dict_debug(DICT *);
|
||||
#define DICT_FLAG_FOLD_ANY (DICT_FLAG_FOLD_FIX | DICT_FLAG_FOLD_MUL)
|
||||
#define DICT_FLAG_OPEN_LOCK (1<<16) /* perm lock if not multi-writer safe */
|
||||
#define DICT_FLAG_BULK_UPDATE (1<<17) /* optimize for bulk updates */
|
||||
#define DICT_FLAG_WORLD_READ (1<<18) /* assume writer != reader */
|
||||
#define DICT_FLAG_MULTI_WRITER (1<<18) /* multi-writer safe map */
|
||||
|
||||
/* IMPORTANT: Update the dict_mask[] table when the above changes */
|
||||
|
||||
@ -124,7 +124,8 @@ extern DICT *dict_debug(DICT *);
|
||||
*/
|
||||
#define DICT_FLAG_PARANOID \
|
||||
(DICT_FLAG_NO_REGSUB | DICT_FLAG_NO_PROXY | DICT_FLAG_NO_UNAUTH)
|
||||
#define DICT_FLAG_IMPL_MASK (DICT_FLAG_FIXED | DICT_FLAG_PATTERN)
|
||||
#define DICT_FLAG_IMPL_MASK (DICT_FLAG_FIXED | DICT_FLAG_PATTERN | \
|
||||
DICT_FLAG_MULTI_WRITER)
|
||||
#define DICT_FLAG_RQST_MASK (DICT_FLAG_FOLD_ANY | DICT_FLAG_LOCK | \
|
||||
DICT_FLAG_DUP_REPLACE | DICT_FLAG_DUP_WARN | \
|
||||
DICT_FLAG_DUP_IGNORE | DICT_FLAG_SYNC_UPDATE | \
|
||||
|
@ -591,16 +591,16 @@ DICT *dict_lmdb_open(const char *path, int open_flags, int dict_flags)
|
||||
*
|
||||
* As a workaround the postmap(1) and postalias(1) commands turn on
|
||||
* MDB_WRITEMAP which disables the use of malloc() in LMDB. However, that
|
||||
* does not address several disclosures of stack memory. Other Postfix
|
||||
* databases are maintained by Postfix daemon processes, and are
|
||||
* accessible only by the postfix user.
|
||||
* does not address several disclosures of stack memory. We don't enable
|
||||
* this workaround for Postfix databases are maintained by Postfix daemon
|
||||
* processes, because those are accessible only by the postfix user.
|
||||
*
|
||||
* LMDB 0.9.10 by default does not write uninitialized heap memory to file
|
||||
* (specify MDB_NOMEMINIT to revert that change). We use the MDB_WRITEMAP
|
||||
* workaround for older LMDB versions.
|
||||
*/
|
||||
#ifndef MDB_NOMEMINIT
|
||||
if (dict_flags & DICT_FLAG_WORLD_READ)
|
||||
if (dict_flags & DICT_FLAG_BULK_UPDATE) /* XXX Good enough */
|
||||
mdb_flags |= MDB_WRITEMAP;
|
||||
#endif
|
||||
|
||||
@ -664,7 +664,9 @@ DICT *dict_lmdb_open(const char *path, int open_flags, int dict_flags)
|
||||
&& st.st_mtime < time((time_t *) 0) - 100)
|
||||
msg_warn("database %s is older than source file %s", mdb_path, path);
|
||||
|
||||
dict_lmdb->dict.flags = dict_flags | DICT_FLAG_FIXED;
|
||||
#define DICT_LMDB_IMPL_FLAGS (DICT_FLAG_FIXED | DICT_FLAG_MULTI_WRITER)
|
||||
|
||||
dict_lmdb->dict.flags = dict_flags | DICT_LMDB_IMPL_FLAGS;
|
||||
if ((dict_flags & (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL)) == 0)
|
||||
dict_lmdb->dict.flags |= (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL);
|
||||
if (dict_flags & DICT_FLAG_FOLD_FIX)
|
||||
@ -673,12 +675,6 @@ DICT *dict_lmdb_open(const char *path, int open_flags, int dict_flags)
|
||||
if (dict_flags & DICT_FLAG_BULK_UPDATE)
|
||||
dict_jmp_alloc(&dict_lmdb->dict);
|
||||
|
||||
/* LMDB is write-share safe; downgrade a persistent lock to temporary. */
|
||||
if (dict_flags & DICT_FLAG_OPEN_LOCK) {
|
||||
dict_lmdb->dict.flags &= ~DICT_FLAG_OPEN_LOCK;
|
||||
dict_lmdb->dict.flags |= DICT_FLAG_LOCK;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following requests return an error result only if we have serious
|
||||
* memory corruption problem.
|
||||
|
@ -92,13 +92,17 @@
|
||||
/* before writing, and acquire a shared lock before reading.
|
||||
/* Release the lock when the operation completes.
|
||||
/* .IP DICT_FLAG_OPEN_LOCK
|
||||
/* With databases that are not multi-writer safe, request that
|
||||
/* dict_open() acquires an exclusive lock, or that it terminates
|
||||
/* with a fatal run-time error.
|
||||
/* The behavior of this flag depends on whether a database
|
||||
/* sets the DICT_FLAG_MULTI_WRITER flag to indicate that it
|
||||
/* is multi-writer safe.
|
||||
/*
|
||||
/* With databases that are multi-writer safe, downgrade from
|
||||
/* DICT_FLAG_OPEN_LOCK (persistent lock) to DICT_FLAG_LOCK
|
||||
/* (temporary lock).
|
||||
/* With databases that are not multi-writer safe, dict_open()
|
||||
/* acquires a persistent exclusive lock, or it terminates with
|
||||
/* a fatal run-time error.
|
||||
/*
|
||||
/* With databases that are multi-writer safe, dict_open()
|
||||
/* downgrades the DICT_FLAG_OPEN_LOCK flag (persistent lock)
|
||||
/* to DICT_FLAG_LOCK (temporary lock).
|
||||
/* .IP DICT_FLAG_FOLD_FIX
|
||||
/* With databases whose lookup fields are fixed-case strings,
|
||||
/* fold the search string to lower case before accessing the
|
||||
@ -131,9 +135,6 @@
|
||||
/* Enable preliminary code for bulk-mode database updates.
|
||||
/* The caller must create an exception handler with dict_jmp_alloc()
|
||||
/* and must trap exceptions from the database client with dict_setjmp().
|
||||
/* .IP DICT_FLAG_WORLD_READ
|
||||
/* Assume that the database file will be read by users other
|
||||
/* than the writer.
|
||||
/* .IP DICT_FLAG_DEBUG
|
||||
/* Enable additional logging.
|
||||
/* .PP
|
||||
@ -389,13 +390,18 @@ DICT *dict_open3(const char *dict_type, const char *dict_name,
|
||||
"cannot open %s:%s: %m", dict_type, dict_name));
|
||||
if (msg_verbose)
|
||||
msg_info("%s: %s:%s", myname, dict_type, dict_name);
|
||||
/* Write-share safe maps may downgrade a persistent lock to temporary. */
|
||||
/* XXX The choice between wait-for-lock or no-wait is hard-coded. */
|
||||
if (dict->flags & DICT_FLAG_OPEN_LOCK) {
|
||||
if (dict->flags & DICT_FLAG_LOCK)
|
||||
msg_panic("%s: attempt to open %s:%s with both \"open\" lock and \"access\" lock",
|
||||
myname, dict_type, dict_name);
|
||||
if (dict->lock(dict, MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT) < 0)
|
||||
/* Multi-writer safe map: downgrade persistent lock to temporary. */
|
||||
if (dict->flags & DICT_FLAG_MULTI_WRITER) {
|
||||
dict->flags &= ~DICT_FLAG_OPEN_LOCK;
|
||||
dict->flags |= DICT_FLAG_LOCK;
|
||||
}
|
||||
/* Multi-writer unsafe map: acquire exclusive lock or bust. */
|
||||
else if (dict->lock(dict, MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT) < 0)
|
||||
msg_fatal("%s:%s: unable to get exclusive lock: %m",
|
||||
dict_type, dict_name);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user