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
|
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
|
Feature: a Postfix LMDB database can now be used as shared
|
||||||
cache. Until now only the Postfix memcache database could
|
persistent cache with multiple postscreen(8) or verify(8)
|
||||||
be used in this manner. This is implemented by allowing a
|
daemons (but not both), without the need for a shared
|
||||||
database to downgrade the permanent DICT_FLAG_OPEN_LOCK
|
proxymap server. Files: util/dict.h, util/dict_alloc.c,
|
||||||
method to the temporary DICT_FLAG_LOCK method. Files:
|
util/dict_open.c, util/dict_lmdb.c.
|
||||||
util/dict.h, util/dict_alloc.c, util/dict_open.c,
|
|
||||||
util/dict_lmdb.c.
|
|
||||||
|
|
||||||
Internal: DNS client support to report reply RCODE information,
|
Internal: DNS client support to report reply RCODE information,
|
||||||
in addition to the simplified DNS_NOTFOUND, DNS_RETRY etc.
|
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.
|
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
|
verification results. If you specify an empty value, all address verification
|
||||||
results are lost after "postfix reload" or "postfix stop".
|
results are lost after "postfix reload" or "postfix stop".
|
||||||
|
|
||||||
|
# Example 1: Default setting for Postfix 2.7 and later.
|
||||||
|
# Note: avoid hash files here. Use btree instead.
|
||||||
/etc/postfix/main.cf:
|
/etc/postfix/main.cf:
|
||||||
# Default setting for Postfix 2.7 and later.
|
|
||||||
# Note: avoid hash files here. Use btree instead.
|
|
||||||
address_verify_map = btree:$data_directory/verify_cache
|
address_verify_map = btree:$data_directory/verify_cache
|
||||||
|
|
||||||
# Shared persistent cache (requires Postfix 2.9 or later).
|
# Example 2: Shared persistent lmdb: cache (Postfix 2.11 or later).
|
||||||
address_verify_map = proxy:btree:$data_directory/verify_cache
|
# Disable automatic cache cleanup in all Postfix instances except
|
||||||
# Disable automatic cache cleanup in all Postfix instances except
|
# for one instance that will be responsible for cache cleanup.
|
||||||
# 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
|
# address_verify_cache_cleanup_interval = 0
|
||||||
|
|
||||||
# Shared memory cache (requires Postfix 2.9 or later).
|
# Example 3: Shared persistent btree: cache (Postfix 2.9 or later).
|
||||||
# See memcache_table(5) for details.
|
# Disable automatic cache cleanup in all Postfix instances except
|
||||||
address_verify_map = memcache:/etc/postfix/verify-memcache.cf
|
# 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).
|
||||||
# This uses non-persistent storage only.
|
# 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 =
|
address_verify_map =
|
||||||
|
|
||||||
NOTE 1: The database file should be stored under a Postfix-owned directory,
|
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
|
whitelist. The temporary whitelist is not used for SMTP client addresses that
|
||||||
appear on the permanent access list.
|
appear on the permanent access list.
|
||||||
|
|
||||||
NOTE: To share a postscreen(8) cache between multiple postscreen(8)
|
By default the temporary whitelist is not shared with other postscreen(8)
|
||||||
instances under the same master(8) daemon, use "postscreen_cache_map =
|
daemons. See Sharing the temporary whitelist below for alternatives.
|
||||||
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.
|
|
||||||
|
|
||||||
When the SMTP client address appears on the temporary whitelist, postscreen(8)
|
When the SMTP client address appears on the temporary whitelist, postscreen(8)
|
||||||
logs this with the client address and port number as:
|
logs this with the client address and port number as:
|
||||||
@ -551,6 +542,7 @@ systems.
|
|||||||
* postscreen(8) TLS configuration
|
* postscreen(8) TLS configuration
|
||||||
* Blocking mail with postscreen(8)
|
* Blocking mail with postscreen(8)
|
||||||
* Turning off postscreen(8)
|
* Turning off postscreen(8)
|
||||||
|
* Sharing the temporary whitelist
|
||||||
|
|
||||||
TTuurrnniinngg oonn ppoossttssccrreeeenn((88)) wwiitthhoouutt bblloocckkiinngg mmaaiill
|
TTuurrnniinngg oonn ppoossttssccrreeeenn((88)) wwiitthhoouutt bblloocckkiinngg mmaaiill
|
||||||
|
|
||||||
@ -754,6 +746,72 @@ processes:
|
|||||||
|
|
||||||
6. Read the new configuration with "postfix reload".
|
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
|
HHiissttoorriiccaall nnootteess aanndd ccrreeddiittss
|
||||||
|
|
||||||
Many ideas in postscreen(8) were explored in earlier work by Michael Tokarev,
|
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>
|
<blockquote>
|
||||||
<pre>
|
<pre>
|
||||||
|
# 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>:
|
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||||
# Default setting for Postfix 2.7 and later.
|
|
||||||
# Note: avoid hash files here. Use btree instead.
|
|
||||||
<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
|
<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).
|
# Example 2: Shared persistent <a href="LMDB_README.html">lmdb</a>: cache (Postfix 2.11 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
|
# Disable automatic cache cleanup in all Postfix instances except
|
||||||
# Disable automatic cache cleanup in all Postfix instances except
|
# for one instance that will be responsible for cache cleanup.
|
||||||
# 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
|
# <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).
|
# Example 3: Shared persistent btree: cache (Postfix 2.9 or later).
|
||||||
# See <a href="memcache_table.5.html">memcache_table(5)</a> for details.
|
# Disable automatic cache cleanup in all Postfix instances except
|
||||||
<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
|
# 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).
|
||||||
# This uses non-persistent storage only.
|
# 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> =
|
<a href="postconf.5.html#address_verify_map">address_verify_map</a> =
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
@ -227,24 +227,9 @@ specifies the location of the temporary whitelist. The
|
|||||||
temporary whitelist is not used for SMTP client addresses
|
temporary whitelist is not used for SMTP client addresses
|
||||||
that appear on the <i>permanent</i> access list. </p>
|
that appear on the <i>permanent</i> access list. </p>
|
||||||
|
|
||||||
<blockquote>
|
<p> By default the temporary whitelist is not shared with other
|
||||||
|
postscreen(8) daemons. See <a href="#temp_white_sharing"> Sharing
|
||||||
<p> NOTE: To share a <a href="postscreen.8.html">postscreen(8)</a> cache between multiple
|
the temporary whitelist </a> below for alternatives. </p>
|
||||||
<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> When the SMTP client address appears on the temporary
|
<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
|
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="#turnoff"> Turning off postscreen(8) </a>
|
||||||
|
|
||||||
|
<li> <a href="#temp_white_sharing"> Sharing the temporary whitelist
|
||||||
|
</a>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3> <a name="enable"> Turning on postscreen(8) without blocking mail</a> </h3>
|
<h3> <a name="enable"> Turning on postscreen(8) without blocking mail</a> </h3>
|
||||||
@ -1057,6 +1045,87 @@ may follow. </p>
|
|||||||
|
|
||||||
</ol>
|
</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>
|
<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
|
<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>
|
tive ports can specified by appending "<i>:service-</i>
|
||||||
<i>name</i>" or ":<i>portnumber</i>" to the destination argument.
|
<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 TCP connection timeout to use. This is also
|
||||||
the timeout for reading the remote server's 220
|
the timeout for reading the remote server's 220
|
||||||
banner.
|
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
|
LMTP over TCP is 24. Alternative ports can specified by appending
|
||||||
"\fI:servicename\fR" or ":\fIportnumber\fR" to the destination
|
"\fI:servicename\fR" or ":\fIportnumber\fR" to the destination
|
||||||
argument.
|
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
|
The TCP connection timeout to use. This is also the timeout for
|
||||||
reading the remote server's 220 banner.
|
reading the remote server's 220 banner.
|
||||||
.IP "\fB-T \fItimeout\fR (default: \fB30\fR)"
|
.IP "\fB-T \fItimeout\fR (default: \fB30\fR)"
|
||||||
|
@ -454,23 +454,35 @@ results are lost after "postfix reload" or "postfix stop". </p>
|
|||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>
|
<pre>
|
||||||
|
# Example 1: Default setting for Postfix 2.7 and later.
|
||||||
|
# Note: avoid hash files here. Use btree instead.
|
||||||
/etc/postfix/main.cf:
|
/etc/postfix/main.cf:
|
||||||
# Default setting for Postfix 2.7 and later.
|
|
||||||
# Note: avoid hash files here. Use btree instead.
|
|
||||||
address_verify_map = btree:$data_directory/verify_cache
|
address_verify_map = btree:$data_directory/verify_cache
|
||||||
|
|
||||||
# Shared persistent cache (requires Postfix 2.9 or later).
|
# Example 2: Shared persistent lmdb: cache (Postfix 2.11 or later).
|
||||||
address_verify_map = proxy:btree:$data_directory/verify_cache
|
# Disable automatic cache cleanup in all Postfix instances except
|
||||||
# Disable automatic cache cleanup in all Postfix instances except
|
# for one instance that will be responsible for cache cleanup.
|
||||||
# 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
|
# address_verify_cache_cleanup_interval = 0
|
||||||
|
|
||||||
# Shared memory cache (requires Postfix 2.9 or later).
|
# Example 3: Shared persistent btree: cache (Postfix 2.9 or later).
|
||||||
# See memcache_table(5) for details.
|
# Disable automatic cache cleanup in all Postfix instances except
|
||||||
address_verify_map = memcache:/etc/postfix/verify-memcache.cf
|
# 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).
|
||||||
# This uses non-persistent storage only.
|
# 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 =
|
address_verify_map =
|
||||||
</pre>
|
</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
@ -227,24 +227,9 @@ specifies the location of the temporary whitelist. The
|
|||||||
temporary whitelist is not used for SMTP client addresses
|
temporary whitelist is not used for SMTP client addresses
|
||||||
that appear on the <i>permanent</i> access list. </p>
|
that appear on the <i>permanent</i> access list. </p>
|
||||||
|
|
||||||
<blockquote>
|
<p> By default the temporary whitelist is not shared with other
|
||||||
|
postscreen(8) daemons. See <a href="#temp_white_sharing"> Sharing
|
||||||
<p> NOTE: To share a postscreen(8) cache between multiple
|
the temporary whitelist </a> below for alternatives. </p>
|
||||||
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> When the SMTP client address appears on the temporary
|
<p> When the SMTP client address appears on the temporary
|
||||||
whitelist, postscreen(8) logs this with the client address and port
|
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="#turnoff"> Turning off postscreen(8) </a>
|
||||||
|
|
||||||
|
<li> <a href="#temp_white_sharing"> Sharing the temporary whitelist
|
||||||
|
</a>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3> <a name="enable"> Turning on postscreen(8) without blocking mail</a> </h3>
|
<h3> <a name="enable"> Turning on postscreen(8) without blocking mail</a> </h3>
|
||||||
@ -1057,6 +1045,87 @@ may follow. </p>
|
|||||||
|
|
||||||
</ol>
|
</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>
|
<h2> <a name="historical"> Historical notes and credits </a> </h2>
|
||||||
|
|
||||||
<p> Many ideas in postscreen(8) were explored in earlier work by
|
<p> Many ideas in postscreen(8) were explored in earlier work by
|
||||||
|
@ -98,9 +98,6 @@
|
|||||||
/* Request DNSSEC validation. This flag is silently ignored
|
/* Request DNSSEC validation. This flag is silently ignored
|
||||||
/* when the system stub resolver API, resolver(3), does not
|
/* when the system stub resolver API, resolver(3), does not
|
||||||
/* implement DNSSEC.
|
/* implement DNSSEC.
|
||||||
/* .IP
|
|
||||||
/* Pointer to storage for the reply RCODE value. This gives
|
|
||||||
/* more detailed information than DNS_FAIL, DNS_RETRY, etc.
|
|
||||||
/* .RE
|
/* .RE
|
||||||
/* .IP lflags
|
/* .IP lflags
|
||||||
/* Multi-type request control for dns_lookup_l() and dns_lookup_v().
|
/* Multi-type request control for dns_lookup_l() and dns_lookup_v().
|
||||||
@ -132,6 +129,9 @@
|
|||||||
/* name found for \fIname\fR.
|
/* name found for \fIname\fR.
|
||||||
/* .IP why
|
/* .IP why
|
||||||
/* A null pointer, or storage for the reason for failure.
|
/* 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
|
/* DIAGNOSTICS
|
||||||
/* dns_lookup() returns one of the following codes and sets the
|
/* dns_lookup() returns one of the following codes and sets the
|
||||||
/* \fIwhy\fR argument accordingly:
|
/* \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);
|
(char *) 0, 0, 0);
|
||||||
if (backup) {
|
if (backup) {
|
||||||
dict_mc->backup = dict_open(backup, open_flags, dict_flags);
|
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);
|
myfree(backup);
|
||||||
} else
|
} else
|
||||||
dict_mc->backup = 0;
|
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
|
* Parse templates and common database parameters. Maps that use
|
||||||
* substring keys should only be used with the full input key.
|
* 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
|
else
|
||||||
dict_mc->dict.flags |= DICT_FLAG_FIXED;
|
dict_mc->dict.flags |= DICT_FLAG_FIXED;
|
||||||
|
|
||||||
|
dict_mc->dict.flags |= DICT_FLAG_MULTI_WRITER;
|
||||||
|
|
||||||
return (&dict_mc->dict);
|
return (&dict_mc->dict);
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
* Patches change both the patchlevel and the release date. Snapshots have no
|
* Patches change both the patchlevel and the release date. Snapshots have no
|
||||||
* patchlevel; they change the release date only.
|
* patchlevel; they change the release date only.
|
||||||
*/
|
*/
|
||||||
#define MAIL_RELEASE_DATE "20131119"
|
#define MAIL_RELEASE_DATE "20131120"
|
||||||
#define MAIL_VERSION_NUMBER "2.11"
|
#define MAIL_VERSION_NUMBER "2.11"
|
||||||
|
|
||||||
#ifdef SNAPSHOT
|
#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)
|
if ((source_fp = vstream_fopen(path_name, O_RDONLY, 0)) == 0)
|
||||||
msg_fatal("open %s: %m", path_name);
|
msg_fatal("open %s: %m", path_name);
|
||||||
}
|
}
|
||||||
dict_flags |= DICT_FLAG_WORLD_READ;
|
|
||||||
if (fstat(vstream_fileno(source_fp), &st) < 0)
|
if (fstat(vstream_fileno(source_fp), &st) < 0)
|
||||||
msg_fatal("fstat %s: %m", path_name);
|
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)
|
if ((source_fp = vstream_fopen(path_name, O_RDONLY, 0)) == 0)
|
||||||
msg_fatal("open %s: %m", path_name);
|
msg_fatal("open %s: %m", path_name);
|
||||||
}
|
}
|
||||||
dict_flags |= DICT_FLAG_WORLD_READ;
|
|
||||||
if (fstat(vstream_fileno(source_fp), &st) < 0)
|
if (fstat(vstream_fileno(source_fp), &st) < 0)
|
||||||
msg_fatal("fstat %s: %m", path_name);
|
msg_fatal("fstat %s: %m", path_name);
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@
|
|||||||
/* LMTP over TCP is 24. Alternative ports can specified by appending
|
/* LMTP over TCP is 24. Alternative ports can specified by appending
|
||||||
/* "\fI:servicename\fR" or ":\fIportnumber\fR" to the destination
|
/* "\fI:servicename\fR" or ":\fIportnumber\fR" to the destination
|
||||||
/* argument.
|
/* 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
|
/* The TCP connection timeout to use. This is also the timeout for
|
||||||
/* reading the remote server's 220 banner.
|
/* reading the remote server's 220 banner.
|
||||||
/* .IP "\fB-T \fItimeout\fR (default: \fB30\fR)"
|
/* .IP "\fB-T \fItimeout\fR (default: \fB30\fR)"
|
||||||
@ -358,7 +358,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "tlsmgrmem.h"
|
#include "tlsmgrmem.h"
|
||||||
|
|
||||||
static int conn_tmout = 5;
|
static int conn_tmout = 30;
|
||||||
static int smtp_tmout = 30;
|
static int smtp_tmout = 30;
|
||||||
|
|
||||||
#define HOST_FLAG_DNS (1<<0)
|
#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)
|
static int dane_host_level(STATE *state, DNS_RR *addr)
|
||||||
{
|
{
|
||||||
int level = state->level;
|
int level = state->level;
|
||||||
int valid;
|
|
||||||
int mxvalid;
|
|
||||||
|
|
||||||
#ifdef USE_TLS
|
#ifdef USE_TLS
|
||||||
if (level == TLS_LEV_DANE) {
|
if (level == TLS_LEV_DANE) {
|
||||||
|
if (state->mx == 0 || state->mx->dnssec_valid) {
|
||||||
/*
|
|
||||||
* 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->log_mask & (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE))
|
if (state->log_mask & (TLS_LOG_CERTMATCH | TLS_LOG_VERBOSE))
|
||||||
tls_dane_verbose(1);
|
tls_dane_verbose(1);
|
||||||
else
|
else
|
||||||
@ -1192,19 +1176,19 @@ static int dane_host_level(STATE *state, DNS_RR *addr)
|
|||||||
if (state->ddane)
|
if (state->ddane)
|
||||||
tls_dane_free(state->ddane);
|
tls_dane_free(state->ddane);
|
||||||
|
|
||||||
/* When TLSA lookups fail, next host */
|
/*
|
||||||
state->ddane = tls_dane_resolve(addr->qname,
|
* When TLSA lookups fail, next host. If unusable or not found,
|
||||||
valid ? addr->rname : 0,
|
* fallback to "secure"
|
||||||
"tcp", state->port);
|
*/
|
||||||
|
state->ddane = tls_dane_resolve(state->port, "tcp", addr,
|
||||||
|
state->force_tlsa);
|
||||||
if (!state->ddane) {
|
if (!state->ddane) {
|
||||||
dsb_simple(state->why, "4.7.5",
|
dsb_simple(state->why, "4.7.5",
|
||||||
"TLSA lookup error for %s:%u",
|
"TLSA lookup error for %s:%u",
|
||||||
HNAME(addr), ntohs(state->port));
|
HNAME(addr), ntohs(state->port));
|
||||||
return (TLS_LEV_INVALID);
|
level = TLS_LEV_INVALID;
|
||||||
}
|
} else if (tls_dane_notfound(state->ddane)
|
||||||
/* If unusable or not found, same fallback to "secure" */
|
|| tls_dane_unusable(state->ddane)) {
|
||||||
if (tls_dane_notfound(state->ddane)
|
|
||||||
|| tls_dane_unusable(state->ddane)) {
|
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("no %sTLSA records found, "
|
msg_info("no %sTLSA records found, "
|
||||||
"resorting to \"secure\"",
|
"resorting to \"secure\"",
|
||||||
|
@ -712,8 +712,6 @@ static int global_tls_level(void)
|
|||||||
static void dane_init(SMTP_TLS_POLICY *tls, SMTP_ITERATOR *iter)
|
static void dane_init(SMTP_TLS_POLICY *tls, SMTP_ITERATOR *iter)
|
||||||
{
|
{
|
||||||
TLS_DANE *dane;
|
TLS_DANE *dane;
|
||||||
int valid;
|
|
||||||
int mxvalid;
|
|
||||||
|
|
||||||
if (!iter->port) {
|
if (!iter->port) {
|
||||||
msg_warn("%s: the \"dane\" security level is invalid for delivery via"
|
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
|
* 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
|
* try DANE with the destination host prior to CNAME expansion, but we
|
||||||
* prefer CNAME expanded MX hosts if those are also secure.
|
* 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;
|
if (iter->mx && !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 (tls->level == TLS_LEV_DANE) {
|
if (tls->level == TLS_LEV_DANE) {
|
||||||
tls->level = TLS_LEV_MAY;
|
tls->level = TLS_LEV_MAY;
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
@ -789,8 +775,8 @@ static void dane_init(SMTP_TLS_POLICY *tls, SMTP_ITERATOR *iter)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* When TLSA lookups fail, we defer the message */
|
/* When TLSA lookups fail, we defer the message */
|
||||||
if ((dane = tls_dane_resolve(iter->rr->qname, valid ? iter->rr->rname : 0,
|
if ((dane = tls_dane_resolve(iter->port, "tcp", iter->rr,
|
||||||
"tcp", iter->port)) == 0) {
|
var_smtp_tls_force_tlsa)) == 0) {
|
||||||
tls->level = TLS_LEV_INVALID;
|
tls->level = TLS_LEV_INVALID;
|
||||||
dsb_simple(tls->why, "4.7.5", "TLSA lookup error for %s:%u",
|
dsb_simple(tls->why, "4.7.5", "TLSA lookup error for %s:%u",
|
||||||
STR(iter->host), ntohs(iter->port));
|
STR(iter->host), ntohs(iter->port));
|
||||||
|
@ -90,6 +90,7 @@ extern const NAME_CODE tls_level_table[];
|
|||||||
#include <vstream.h>
|
#include <vstream.h>
|
||||||
#include <name_mask.h>
|
#include <name_mask.h>
|
||||||
#include <name_code.h>
|
#include <name_code.h>
|
||||||
|
#include <dns.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Names of valid tlsmgr(8) session caches.
|
* 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 *,
|
extern void tls_dane_split(TLS_DANE *, int, int, const char *, const char *,
|
||||||
const char *);
|
const char *);
|
||||||
extern void tls_dane_free(TLS_DANE *);
|
extern void tls_dane_free(TLS_DANE *);
|
||||||
extern TLS_DANE *tls_dane_resolve(const char *, const char *, const char *,
|
extern TLS_DANE *tls_dane_resolve(unsigned, const char *, DNS_RR *, int);
|
||||||
unsigned);
|
|
||||||
extern int tls_dane_load_trustfile(TLS_DANE *, const char *);
|
extern int tls_dane_load_trustfile(TLS_DANE *, const char *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -41,11 +41,11 @@
|
|||||||
/* SSL_CTX *ssl_ctx;
|
/* SSL_CTX *ssl_ctx;
|
||||||
/* TLS_SESS_STATE *TLScontext;
|
/* TLS_SESS_STATE *TLScontext;
|
||||||
/*
|
/*
|
||||||
/* TLS_DANE *tls_dane_resolve(qname, rname, proto, port)
|
/* TLS_DANE *tls_dane_resolve(port, proto, hostrr, forcetlsa)
|
||||||
/* const char *qname;
|
|
||||||
/* const char *rname;
|
|
||||||
/* const char *proto;
|
|
||||||
/* unsigned port;
|
/* unsigned port;
|
||||||
|
/* const char *proto;
|
||||||
|
/* DNS_RR *hostrr;
|
||||||
|
/* int forcetlsa;
|
||||||
/*
|
/*
|
||||||
/* int tls_dane_unusable(dane)
|
/* int tls_dane_unusable(dane)
|
||||||
/* const TLS_DANE *dane;
|
/* const TLS_DANE *dane;
|
||||||
@ -96,7 +96,7 @@
|
|||||||
/* anchors always override the legacy public CA PKI. Otherwise, the
|
/* anchors always override the legacy public CA PKI. Otherwise, the
|
||||||
/* callback MUST be cleared.
|
/* 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
|
/* a corresponding TLS_DANE policy structure found in the DNS. The port
|
||||||
/* argument is in network byte order. A null pointer is returned when
|
/* 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
|
/* the DNS query for the TLSA record tempfailed. In all other cases the
|
||||||
@ -117,14 +117,17 @@
|
|||||||
/* .IP dane
|
/* .IP dane
|
||||||
/* Pointer to a TLS_DANE structure that lists the valid trust-anchor
|
/* Pointer to a TLS_DANE structure that lists the valid trust-anchor
|
||||||
/* and end-entity full-certificate and/or public-key digests.
|
/* 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
|
/* .IP port
|
||||||
/* The TCP port in network byte order.
|
/* 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
|
/* .IP flags
|
||||||
/* Only one flag is part of the public interface at this time:
|
/* Only one flag is part of the public interface at this time:
|
||||||
/* .IP TLScontext
|
/* .IP TLScontext
|
||||||
@ -314,7 +317,7 @@ static EVP_PKEY *gencakey(void)
|
|||||||
|
|
||||||
#ifdef WRAP_SIGNED
|
#ifdef WRAP_SIGNED
|
||||||
EC_KEY *eckey;
|
EC_KEY *eckey;
|
||||||
EC_GROUP *group;
|
EC_GROUP *group = 0;
|
||||||
|
|
||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
|
|
||||||
@ -676,14 +679,14 @@ static void parse_tlsa_rrs(TLS_DANE *dane, DNS_RR *rr)
|
|||||||
for ( /* nop */ ; rr; rr = rr->next) {
|
for ( /* nop */ ; rr; rr = rr->next) {
|
||||||
const char *mdalg = 0;
|
const char *mdalg = 0;
|
||||||
char *digest;
|
char *digest;
|
||||||
int same = (strcasecmp(rr->rname, rr->qname) == 0);
|
int iscname = strcasecmp(rr->rname, rr->qname);
|
||||||
uint8_t *ip = (uint8_t *) rr->data;
|
uint8_t *ip = (uint8_t *) rr->data;
|
||||||
X509 *x = 0; /* OpenSSL tries to re-use *x if x!=0 */
|
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 */
|
EVP_PKEY *k = 0; /* OpenSSL tries to re-use *k if k!=0 */
|
||||||
digest_info *di;
|
digest_info *di;
|
||||||
|
|
||||||
#define rcname(rr) (same ? "" : rr->qname)
|
#define rcname(rr) (iscname ? rr->qname : "")
|
||||||
#define rarrow(rr) (same ? "" : " -> ")
|
#define rarrow(rr) (iscname ? " -> " : "")
|
||||||
|
|
||||||
if (rr->type != T_TLSA)
|
if (rr->type != T_TLSA)
|
||||||
msg_panic("unexpected non-TLSA RR type %u for %s%s%s", rr->type,
|
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));
|
dane = (TLS_DANE *) ctable_refresh(dane_cache, STR(query_domain));
|
||||||
if (dane->base_domain == 0)
|
if (dane->base_domain == 0)
|
||||||
dane->base_domain = mystrdup(host);
|
dane->base_domain = mystrdup(host);
|
||||||
|
/* Increment ref-count of cached entry */
|
||||||
|
++dane->refs;
|
||||||
return (dane);
|
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_resolve - cached map: (name, proto, port) -> TLS_DANE */
|
||||||
|
|
||||||
TLS_DANE *tls_dane_resolve(const char *qname, const char *rname,
|
TLS_DANE *tls_dane_resolve(unsigned port, const char *proto, DNS_RR *hostrr,
|
||||||
const char *proto, unsigned port)
|
int forcetlsa)
|
||||||
{
|
{
|
||||||
TLS_DANE *dane = 0;
|
TLS_DANE *dane = 0;
|
||||||
|
int iscname;
|
||||||
|
|
||||||
#ifdef DANE_TLSA_SUPPORT
|
#ifdef DANE_TLSA_SUPPORT
|
||||||
if (!tls_dane_avail())
|
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);
|
dane_cache = ctable_create(CACHE_SIZE, dane_lookup, dane_free, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try the rname first, if nothing there, try the qname. Note, lookup
|
* By default suppress TLSA lookups for non-DNSSEC + non-CNAME hosts. If
|
||||||
* errors are distinct from success with nothing found. If the rname
|
* the host address is not DNSSEC validated, the TLSA RRset is safely
|
||||||
* lookup fails we don't try the qname. The rname may be null when only
|
* assumed to not be in a DNSSEC Look-aside Validation child zone.
|
||||||
* the qname is in a secure zone.
|
|
||||||
*/
|
*/
|
||||||
if (rname)
|
iscname = strcasecmp(hostrr->rname, hostrr->qname);
|
||||||
dane = resolve_host(rname, proto, port);
|
if (!forcetlsa && !hostrr->dnssec_valid && !iscname) {
|
||||||
if (!rname || (tls_dane_notfound(dane) && strcmp(qname, rname) != 0))
|
dane = tls_dane_alloc(0);
|
||||||
dane = resolve_host(qname, proto, port);
|
dane->flags = TLS_DANE_FLAG_NORRS;
|
||||||
if (dane->flags & TLS_DANE_FLAG_ERROR)
|
} else {
|
||||||
return (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.
|
||||||
|
*/
|
||||||
|
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
|
#endif
|
||||||
return (dane);
|
return (dane);
|
||||||
}
|
}
|
||||||
|
@ -555,7 +555,9 @@ const char *dict_changed_name(void)
|
|||||||
msg_warn("%s: table %s: null time stamp", myname, h->key);
|
msg_warn("%s: table %s: null time stamp", myname, h->key);
|
||||||
if (fstat(dict->stat_fd, &st) < 0)
|
if (fstat(dict->stat_fd, &st) < 0)
|
||||||
msg_fatal("%s: fstat: %m", myname);
|
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;
|
status = h->key;
|
||||||
}
|
}
|
||||||
myfree((char *) ht_info_list);
|
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 */
|
"fold_mul", DICT_FLAG_FOLD_MUL, /* case-fold with multi-case key map */
|
||||||
"open_lock", DICT_FLAG_OPEN_LOCK, /* permanent lock upon open */
|
"open_lock", DICT_FLAG_OPEN_LOCK, /* permanent lock upon open */
|
||||||
"bulk_update", DICT_FLAG_BULK_UPDATE, /* bulk update if supported */
|
"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,
|
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_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_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_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 */
|
/* IMPORTANT: Update the dict_mask[] table when the above changes */
|
||||||
|
|
||||||
@ -124,7 +124,8 @@ extern DICT *dict_debug(DICT *);
|
|||||||
*/
|
*/
|
||||||
#define DICT_FLAG_PARANOID \
|
#define DICT_FLAG_PARANOID \
|
||||||
(DICT_FLAG_NO_REGSUB | DICT_FLAG_NO_PROXY | DICT_FLAG_NO_UNAUTH)
|
(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 | \
|
#define DICT_FLAG_RQST_MASK (DICT_FLAG_FOLD_ANY | DICT_FLAG_LOCK | \
|
||||||
DICT_FLAG_DUP_REPLACE | DICT_FLAG_DUP_WARN | \
|
DICT_FLAG_DUP_REPLACE | DICT_FLAG_DUP_WARN | \
|
||||||
DICT_FLAG_DUP_IGNORE | DICT_FLAG_SYNC_UPDATE | \
|
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
|
* As a workaround the postmap(1) and postalias(1) commands turn on
|
||||||
* MDB_WRITEMAP which disables the use of malloc() in LMDB. However, that
|
* MDB_WRITEMAP which disables the use of malloc() in LMDB. However, that
|
||||||
* does not address several disclosures of stack memory. Other Postfix
|
* does not address several disclosures of stack memory. We don't enable
|
||||||
* databases are maintained by Postfix daemon processes, and are
|
* this workaround for Postfix databases are maintained by Postfix daemon
|
||||||
* accessible only by the postfix user.
|
* processes, because those are accessible only by the postfix user.
|
||||||
*
|
*
|
||||||
* LMDB 0.9.10 by default does not write uninitialized heap memory to file
|
* 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
|
* (specify MDB_NOMEMINIT to revert that change). We use the MDB_WRITEMAP
|
||||||
* workaround for older LMDB versions.
|
* workaround for older LMDB versions.
|
||||||
*/
|
*/
|
||||||
#ifndef MDB_NOMEMINIT
|
#ifndef MDB_NOMEMINIT
|
||||||
if (dict_flags & DICT_FLAG_WORLD_READ)
|
if (dict_flags & DICT_FLAG_BULK_UPDATE) /* XXX Good enough */
|
||||||
mdb_flags |= MDB_WRITEMAP;
|
mdb_flags |= MDB_WRITEMAP;
|
||||||
#endif
|
#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)
|
&& st.st_mtime < time((time_t *) 0) - 100)
|
||||||
msg_warn("database %s is older than source file %s", mdb_path, path);
|
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)
|
if ((dict_flags & (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL)) == 0)
|
||||||
dict_lmdb->dict.flags |= (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL);
|
dict_lmdb->dict.flags |= (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL);
|
||||||
if (dict_flags & DICT_FLAG_FOLD_FIX)
|
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)
|
if (dict_flags & DICT_FLAG_BULK_UPDATE)
|
||||||
dict_jmp_alloc(&dict_lmdb->dict);
|
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
|
* The following requests return an error result only if we have serious
|
||||||
* memory corruption problem.
|
* memory corruption problem.
|
||||||
|
@ -92,13 +92,17 @@
|
|||||||
/* before writing, and acquire a shared lock before reading.
|
/* before writing, and acquire a shared lock before reading.
|
||||||
/* Release the lock when the operation completes.
|
/* Release the lock when the operation completes.
|
||||||
/* .IP DICT_FLAG_OPEN_LOCK
|
/* .IP DICT_FLAG_OPEN_LOCK
|
||||||
/* With databases that are not multi-writer safe, request that
|
/* The behavior of this flag depends on whether a database
|
||||||
/* dict_open() acquires an exclusive lock, or that it terminates
|
/* sets the DICT_FLAG_MULTI_WRITER flag to indicate that it
|
||||||
/* with a fatal run-time error.
|
/* is multi-writer safe.
|
||||||
/*
|
/*
|
||||||
/* With databases that are multi-writer safe, downgrade from
|
/* With databases that are not multi-writer safe, dict_open()
|
||||||
/* DICT_FLAG_OPEN_LOCK (persistent lock) to DICT_FLAG_LOCK
|
/* acquires a persistent exclusive lock, or it terminates with
|
||||||
/* (temporary lock).
|
/* 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
|
/* .IP DICT_FLAG_FOLD_FIX
|
||||||
/* With databases whose lookup fields are fixed-case strings,
|
/* With databases whose lookup fields are fixed-case strings,
|
||||||
/* fold the search string to lower case before accessing the
|
/* fold the search string to lower case before accessing the
|
||||||
@ -131,9 +135,6 @@
|
|||||||
/* Enable preliminary code for bulk-mode database updates.
|
/* Enable preliminary code for bulk-mode database updates.
|
||||||
/* The caller must create an exception handler with dict_jmp_alloc()
|
/* The caller must create an exception handler with dict_jmp_alloc()
|
||||||
/* and must trap exceptions from the database client with dict_setjmp().
|
/* 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
|
/* .IP DICT_FLAG_DEBUG
|
||||||
/* Enable additional logging.
|
/* Enable additional logging.
|
||||||
/* .PP
|
/* .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));
|
"cannot open %s:%s: %m", dict_type, dict_name));
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: %s:%s", myname, dict_type, dict_name);
|
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. */
|
/* 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_OPEN_LOCK) {
|
||||||
if (dict->flags & DICT_FLAG_LOCK)
|
if (dict->flags & DICT_FLAG_LOCK)
|
||||||
msg_panic("%s: attempt to open %s:%s with both \"open\" lock and \"access\" lock",
|
msg_panic("%s: attempt to open %s:%s with both \"open\" lock and \"access\" lock",
|
||||||
myname, dict_type, dict_name);
|
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",
|
msg_fatal("%s:%s: unable to get exclusive lock: %m",
|
||||||
dict_type, dict_name);
|
dict_type, dict_name);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user