]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.11-20131120
authorWietse Venema <wietse@porcupine.org>
Wed, 20 Nov 2013 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Thu, 21 Nov 2013 04:07:51 +0000 (23:07 -0500)
22 files changed:
postfix/HISTORY
postfix/README_FILES/ADDRESS_VERIFICATION_README
postfix/README_FILES/POSTSCREEN_README
postfix/html/ADDRESS_VERIFICATION_README.html
postfix/html/POSTSCREEN_README.html
postfix/html/posttls-finger.1.html
postfix/man/man1/posttls-finger.1
postfix/proto/ADDRESS_VERIFICATION_README.html
postfix/proto/POSTSCREEN_README.html
postfix/src/dns/dns_lookup.c
postfix/src/global/dict_memcache.c
postfix/src/global/mail_version.h
postfix/src/postalias/postalias.c
postfix/src/postmap/postmap.c
postfix/src/posttls-finger/posttls-finger.c
postfix/src/smtp/smtp_tls_policy.c
postfix/src/tls/tls.h
postfix/src/tls/tls_dane.c
postfix/src/util/dict.c
postfix/src/util/dict.h
postfix/src/util/dict_lmdb.c
postfix/src/util/dict_open.c

index cda458ed70f120b55b049435c983c70ef87e8e4a..67d718529f39a8675570e99890276b5c6de9f2a6 100644 (file)
@@ -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.
index 1241d875bf1a60fe152882f07a3558b008c17c9f..7aef096dd97b6218c1bd9099a00bcf6ca4d5464a 100644 (file)
@@ -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".
 
+    # Example 1: Default setting for Postfix 2.7 and later.
+    # Note: avoid hash files here. Use btree instead.
     /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
 
-        # Shared persistent cache (requires Postfix 2.9 or later).
+    # 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
+
+    # 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
-        # Disable automatic cache cleanup in all Postfix instances except
-        # for one instance that will be responsible for cache cleanup.
         # address_verify_cache_cleanup_interval = 0
 
-        # Shared memory cache (requires Postfix 2.9 or later).
-        # See memcache_table(5) for details.
+    # 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
 
-        # Default setting for Postfix 2.6 and earlier.
-        # This uses non-persistent storage only.
+    # 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,
index a7253c670fbb10c0960ad7d27fba66862a656403..1ca03a5c94753e9e1ce22b8bfeb6576e05de1187 100644 (file)
@@ -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
 
 T\bTu\bur\brn\bni\bin\bng\bg o\bon\bn p\bpo\bos\bst\bts\bsc\bcr\bre\bee\ben\bn(\b(8\b8)\b) w\bwi\bit\bth\bho\bou\but\bt b\bbl\blo\boc\bck\bki\bin\bng\bg m\bma\bai\bil\bl
 
@@ -754,6 +746,72 @@ processes:
 
  6. Read the new configuration with "postfix reload".
 
+S\bSh\bha\bar\bri\bin\bng\bg t\bth\bhe\be t\bte\bem\bmp\bpo\bor\bra\bar\bry\by w\bwh\bhi\bit\bte\bel\bli\bis\bst\bt
+
+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.
+
 H\bHi\bis\bst\bto\bor\bri\bic\bca\bal\bl n\bno\bot\bte\bes\bs a\ban\bnd\bd c\bcr\bre\bed\bdi\bit\bts\bs
 
 Many ideas in postscreen(8) were explored in earlier work by Michael Tokarev,
index 1aac0635736ead1709f929361a44902c908f8c6e..541c5561922b3e97454ded9333a96e6570755cf0 100644 (file)
@@ -454,23 +454,35 @@ results are lost after "postfix reload" or "postfix stop". </p>
 
 <blockquote>
 <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>:
-    # 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
 
-    # 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).  
+# 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
+
+# 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
-    # Disable automatic cache cleanup in all Postfix instances except
-    # for one instance that will be responsible for cache cleanup.
     # <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.
+# 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
 
-    # Default setting for Postfix 2.6 and earlier.
-    # This uses non-persistent storage only.
+# 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>
index ca007ed3fd490864b2676f37abc96ea2684ffb06..6aecf59483096bcf211c5ae3bc6a5fa9f5aeb806 100644 (file)
@@ -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
index 3e449ec61a24333a2f2c610c5bf030254e30feed..1848d6d249731a75a5a8d1b49512ca9f34e551f1 100644 (file)
@@ -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.
index 3ba4e7b433f1f98a203e9df7a7d91f4346b1df44..3848c9f8bc86f1a19101754a7977d22602aafef2 100644 (file)
@@ -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)"
index f79ebc672d314df58213eb7cac533f323deca2f8..c62ee75e62ff2d958dcd1227c65e61dfa825bb70 100644 (file)
@@ -454,23 +454,35 @@ results are lost after "postfix reload" or "postfix stop". </p>
 
 <blockquote>
 <pre>
+# Example 1: Default setting for Postfix 2.7 and later.
+# Note: avoid hash files here. Use btree instead.
 /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
 
-    # Shared persistent cache (requires Postfix 2.9 or later).  
+# 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
+
+# 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
-    # Disable automatic cache cleanup in all Postfix instances except
-    # for one instance that will be responsible for cache cleanup.
     # address_verify_cache_cleanup_interval = 0
 
-    # Shared memory cache (requires Postfix 2.9 or later).
-    # See memcache_table(5) for details.
+# 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
 
-    # Default setting for Postfix 2.6 and earlier.
-    # This uses non-persistent storage only.
+# 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>
index f91c63a96d6e308ef37f4a0945beda3bdbea3d50..8be94cbc4be85a25d4ec61ecb09d307142fb519d 100644 (file)
@@ -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
index 4fe4b2ef3b96a5d9f21f9a2455cd78944e72e405..0eb8ab4f488fa8cac0fdeb70219216cbaa92850f 100644 (file)
@@ -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().
 /*     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:
index 34c0a7383f595941e5c332b23c00f8424d17d838..161e0c880be8ce33769b8592c65742dce8a367b4 100644 (file)
@@ -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);
 }
index 3799c7bbf29dc26de5c3916b391a3c8df240ec0f..27001e164b06d5cc0e81f2c6e5054ff0a0eebfb8 100644 (file)
@@ -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
index fd535153471e739f202cbfe7cd9909e4d76f9505..430c156417d989e1744cd5d1b14812d9fd57b8a7 100644 (file)
@@ -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);
 
index 26348041ef03e9b2db8b2e1def14795634f0f899..e10ac166976467a1993e02631cc1e18c8ee4d7d4 100644 (file)
@@ -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);
 
index 2971c30b31cde2aa5225595c880489e075c577b5..82d3aeb7d8cafec6261c27ad56a38b91e2eeef00 100644 (file)
 /*     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)"
   */
 #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,19 +1176,19 @@ 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)
-               || tls_dane_unusable(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, "
                             "resorting to \"secure\"",
index 9d881903dd6f3ca2d2171bb9e817d7cd1b4da001..4f3fae10b92bc6fcb30107e6fbf6ff0c1159839a 100644 (file)
@@ -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));
index 9d1fde2f6ae6450f82fabfdae13e2997a839c58e..cd4c2fcd2eff2881f3c5acc1ff64916d601f4b80 100644 (file)
@@ -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 *);
 
  /*
index 640cb47bfcd5c40f2be44c8058102df349f3f8c7..4fb62ae31f8457f3940f13b6abe7cf79c029576f 100644 (file)
 /*     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
 /* .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);
 }
index e1e11cf4dbab6a8ac96db69394c849df9beb325d..f962fe6be082077d5e99dce6234afafe915d888e 100644 (file)
@@ -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,
 };
 
index 2efb1f5b4af4677544fbae8ae0af79a69dd5e7de..a217603e6b5501ac886a32c5697238d05e469c8c 100644 (file)
@@ -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 | \
index 5b079e374c0d8a12cce26514804b899a95f35276..0db22b937b2fed61cd6fe88e5688226348be4765 100644 (file)
@@ -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.
index d0a9bacff2b80f34a6b25ed3a13ac6a6b75787e4..c8706da4e602834d2ac44d19787c54b4fbd6b11d 100644 (file)
 /*     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
 /*     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);
     }