-TMATCH_OPS
-TMBLOCK
-TMBOX
+-TMDB_env
-TMDB_txn
-TMDB_val
-TMILTER
-Tssize_t
-Tssl_cipher_stack_t
-Tssl_comp_stack_t
+-Tstat
-Ttime_t
-Ttlsa_filter
-Tx509_extension_stack_t
Shockingly, LMDB terminates the postscreen daemon without
logfile record. File: util/dict_cache.c.
- Because of the above behavior, LMDB cannot be supported in
- the stable Postfix 2.11 release.
-
20140102
Bugfix: close the LMDB database cursor's read transaction
smtp_rcpt.c, smtp_session.c, smtp_chat.c, smtp_proto.c,
smtp_connect.c.
-20130104
+20140104
Feature: support for optional configuration files
"$daemon-directory/postfix-files.d/*". These are processed
in sorted order after "$daemon-directory/postfix-files",
This avoids breaking "postfix set-permissions" etc. when a
- Postfix distributions comes in multiple packages. File:
+ Postfix distribution comes in multiple packages. File:
conf/post-install.
+
+20140107
+
+ Feature: LMDB 0.9.11 allows Postfix daemons to log an LMDB
+ error message, instead of falling out of the sky without
+ any notification. Files: util/slmdb.[hc], util/dict_lmdb.c.
+
+20140108
+
+ Bugfix: every Postfix LMDB transaction is now protected by
+ an external lock for its entire life time. File: util/slmdb.c.
+
+20140109
+
+ Cleanup: turn off DNSSEC lookup after CNAME redirection to
+ an insecure zone. This is an optimization for resolvers
+ that do not automatically resolve CNAME chains. Viktor
+ Dukhovni. File: dns/dns_lookup.c.
+
+ Cleanup: do not salt the SMTP TLS policy lookup cache key
+ with the DNSSEC status. The DNSSEC status will not change
+ when the same nexthop/host pair is looked up repeatedly.
+ Viktor Dukhovni. File: smtp/smtp_tls_policy.c.
+
+ Robustness: Suppress TLSA lookups only when the qname zone
+ is insecure, not just because the rname zone is insecure.
+ This requires an extra T_CNAME lookup for the qname, since
+ nameservers are often "too helpful" and report CNAME records
+ together with the CNAME targets. When the targets are
+ insecure the whole reply is marked as insecure. Viktor
+ Dukhovni. File: tls/tls_dane.c.
+
+ Cleanup: Unify/simplify reporting of configuration or other
+ conditions that prevent DANE security. Viktor Dukhovni.
+ Files: global/dsn_buf.[hc], tls/tls_dane.c, smtp/smtp_tls_policy.c.
* P\bPr\bri\bim\bme\be-\b-f\bfi\bie\bel\bld\bd g\bgr\bro\bou\bup\bps\bs (\b(E\bED\bDH\bH)\b):\b: The server needs to be configured with a
suitably-large prime and a corresponding "generator". The acronym for
forward secrecy over prime fields is EDH for Ephemeral Diffie-Hellman (also
- abbreviated as DHE for Diffie-Hellman Exchange).
+ abbreviated as DHE).
* E\bEl\bll\bli\bip\bpt\bti\bic\bc-\b-c\bcu\bur\brv\bve\be g\bgr\bro\bou\bup\bps\bs (\b(E\bEE\bEC\bCD\bDH\bH)\b):\b: The server needs to be configured with a
"named curve". These offer better security at lower computational cost than
prime field groups, but are not as widely implemented. The acronym for the
elliptic curve version is EECDH which is short for Ephemeral Elliptic Curve
- Diffie-Hellman (also abbreviated as ECDHE for Elliptic Curve Diffie-Hellman
- Exchange).
+ Diffie-Hellman (also abbreviated as ECDHE).
It is not essential to know what these are, but one does need to know that
OpenSSL supports EECDH with version 1.0.0 or later. Thus the configuration
E\bEE\bEC\bCD\bDH\bH C\bCl\bli\bie\ben\bnt\bt a\ban\bnd\bd s\bse\ber\brv\bve\ber\br s\bsu\bup\bpp\bpo\bor\brt\bt (\b(P\bPo\bos\bst\btf\bfi\bix\bx >\b>=\b= 2\b2.\b.6\b6 w\bwi\bit\bth\bh O\bOp\bpe\ben\bnS\bSS\bSL\bL >\b>=\b= 1\b1.\b.0\b0.\b.0\b0)\b)
With Postfix 2.6 and 2.7, enable elliptic-curve support in the Postfix SMTP
-client and server. This is the default with Postfix >= 2.8.
+client and server. This is the default with Postfix >= 2.8. Note, however, that
+elliptic-curve support may be disabled by the vendor, as in some versions of
+RedHat Linux.
/etc/postfix/main.cf:
# Postfix 2.6 or 2.7 only. This is default with Postfix 2.8 and later.
E\bED\bDH\bH C\bCl\bli\bie\ben\bnt\bt s\bsu\bup\bpp\bpo\bor\brt\bt (\b(P\bPo\bos\bst\btf\bfi\bix\bx >\b>=\b= 2\b2.\b.2\b2)\b)
-This space intentionally left blank.
+This works "out of the box" without additional configuration.
E\bED\bDH\bH S\bSe\ber\brv\bve\ber\br s\bsu\bup\bpp\bpo\bor\brt\bt (\b(P\bPo\bos\bst\btf\bfi\bix\bx >\b>=\b= 2\b2.\b.2\b2)\b)
-------------------------------------------------------------------------------
-N\bNo\bot\bte\be
-
-LMDB is not supported in the stable Postfix release. It will spontaneously
-terminate a Postfix daemon process without allowing Postfix to 1) report the
-problem to the maillog file, and to 2) provide reduced service where this is
-appropriate.
-
I\bIn\bnt\btr\bro\bod\bdu\buc\bct\bti\bio\bon\bn
Postfix uses databases of various kinds to store and look up information.
-Postfix databases are specified as "type:name". OpenLDAP LMDB implements the
-Postfix database type "lmdb". The name of a Postfix OpenLDAP LMDB database is
-the name of the database file without the ".lmdb" suffix.
+Postfix databases are specified as "type:name". OpenLDAP LMDB (called "LMDB"
+from here on) implements the Postfix database type "lmdb". The name of a
+Postfix LMDB database is the name of the database file without the ".lmdb"
+suffix.
This document describes:
- 1. How to build Postfix with OpenLDAP LMDB support.
+ * Building Postfix with LMDB support.
- 2. How to configure LMDB settings.
+ * Configuring LMDB settings.
- 3. Missing pthread library trouble.
+ * Supported minimum LMDB patchlevel.
- 4. Unexpected failure modes that don't exist with other Postfix databases.
+B\bBu\bui\bil\bld\bdi\bin\bng\bg P\bPo\bos\bst\btf\bfi\bix\bx w\bwi\bit\bth\bh L\bLM\bMD\bDB\bB s\bsu\bup\bpp\bpo\bor\brt\bt
-B\bBu\bui\bil\bld\bdi\bin\bng\bg P\bPo\bos\bst\btf\bfi\bix\bx w\bwi\bit\bth\bh O\bOp\bpe\ben\bnL\bLD\bDA\bAP\bP L\bLM\bMD\bDB\bB s\bsu\bup\bpp\bpo\bor\brt\bt
-
-Postfix normally does not enable OpenLDAP LMDB support. To build Postfix with
-OpenLDAP LMDB support, use something like:
+Postfix normally does not enable LMDB support. To build Postfix with LMDB
+support, use something like:
% make makefiles CCARGS="-DHAS_LMDB -I/usr/local/include" \
AUXLIBS="-L/usr/local/lib -llmdb"
AUXLIBS="-R/usr/local/lib -L/usr/local/lib -llmdb"
% make
-The exact pathnames depend on how OpenLDAP LMDB was installed.
-
-C\bCo\bon\bnf\bfi\big\bgu\bur\bre\be L\bLM\bMD\bDB\bB s\bse\bet\btt\bti\bin\bng\bgs\bs
-
-Postfix provides one configuration parameter that controls OpenLDAP LMDB
-database behavior.
-
- * lmdb_map_size (default: 16777216). This setting specifies the initial
- OpenLDAP LMDB database size limit in bytes. Each time a database becomes
- full, its size limit is doubled. The maximum size is the largest signed
- integer value of "long".
-
-M\bMi\bis\bss\bsi\bin\bng\bg p\bpt\bth\bhr\bre\bea\bad\bd l\bli\bib\bbr\bra\bar\bry\by t\btr\bro\bou\bub\bbl\ble\be
+The exact pathnames depend on how LMDB was installed.
When building Postfix fails with:
% make makefiles .... AUXLIBS="... -lpthread"
-Source code for OpenLDAP LMDB is available at http://www.openldap.org. More
-information is available at http://highlandsun.com/hyc/mdb/.
-
-U\bUn\bne\bex\bxp\bpe\bec\bct\bte\bed\bd f\bfa\bai\bil\blu\bur\bre\be m\bmo\bod\bde\bes\bs o\bof\bf P\bPo\bos\bst\btf\bfi\bix\bx L\bLM\bMD\bDB\bB d\bda\bat\bta\bab\bba\bas\bse\bes\bs.\b.
+C\bCo\bon\bnf\bfi\big\bgu\bur\bri\bin\bng\bg L\bLM\bMD\bDB\bB s\bse\bet\btt\bti\bin\bng\bgs\bs
-As documented below, conversion to LMDB introduces a number of failure modes
-that don't exist with other Postfix databases. Some failure modes have been
-eliminated in the course of time. The writeup below reflects the status as of
-LMDB 0.9.9.
+Postfix provides one configuration parameter that controls LMDB database
+behavior.
-N\bNo\bon\bn-\b-o\bob\bbv\bvi\bio\bou\bus\bs r\bre\bec\bco\bov\bve\ber\bry\by w\bwi\bit\bth\bh p\bpo\bos\bst\btm\bma\bap\bp(\b(1\b1)\b),\b, p\bpo\bos\bst\bta\bal\bli\bia\bas\bs(\b(1\b1)\b),\b, o\bor\br t\btl\bls\bsm\bmg\bgr\br(\b(8\b8)\b) f\bfr\bro\bom\bm a\ba
-c\bco\bor\brr\bru\bup\bpt\bte\bed\bd d\bda\bat\bta\bab\bba\bas\bse\be.\b.
+ * lmdb_map_size (default: 16777216). This setting specifies the initial LMDB
+ database size limit in bytes. Each time a database becomes full, its size
+ limit is doubled. The maximum size is the largest signed integer value of
+ "long".
-Problem:
- A corrupted LMDB database can't be rebuilt simply by re-running postmap(1)
- or postalias(1), or by waiting until a tlsmgr(8) daemon restarts. This
- problem does not exist with other Postfix databases.
+S\bSu\bup\bpp\bpo\bor\brt\bte\bed\bd m\bmi\bin\bni\bim\bmu\bum\bm L\bLM\bMD\bDB\bB p\bpa\bat\btc\bch\bhl\ble\bev\bve\bel\bl
-Background:
- The Postfix LMDB database client does not truncate the database file.
- Instead it attempts to create a transaction for a "drop" request plus
- subsequent "store" requests. That is obviously not possible with a
- corrupted database file.
+Currently, Postfix supports LMDB 0.9.11 or later. The supported minimum LMDB
+patchlevel has evolved over time, as the result of deployment experience with
+Postfix.
-Impact:
- Postfix does not process mail until someone fixes the problem.
+ * LMDB 0.9.11 allows Postfix daemons to log an LMDB error message, instead of
+ falling out of the sky without any notification.
-Recovery:
- First delete the ".lmdb" file by hand. Then rebuild the file with the
- postmap(1) or postalias(1) command if the file was created with those
- commands, or restart postfix daemons if the file is maintained by tlsmgr
- (8).
+ * LMDB 0.9.10 closes an information leak where LMDB was writing up to 4kbyte-
+ chunks of uninitialized heap memory to the database, persisting information
+ that was not meant to be persisted, or sharing information that was not
+ meant to be shared.
-Prevention:
- Arrange your file systems such that they never run out of free space.
+ * LMDB 0.9.8 allows Postfix to use external (fcntl()-based) locks, instead of
+ having to use world-writable LMDB lock files.
- Use ECC memory to detect and correct silent corruption of in-memory file
- system data and metadata.
+ * LMDB 0.9.8 allows an application to recover from a "database full" error
+ without having to close the database, by adding support to update the
+ database size limit on-the-fly; and it adds support for an application to
+ adopt someone elses change to the database size limit, without having to
+ close the database.
- Use a file system such as ZFS to detect and correct silent corruption of
- on-disk file system data and metadata. DO NOT use ZFS on systems without
- ECC memory error correction.
+ * LMDB 0.9.7 allows the postmap and postalias commands to use a bulk-mode
+ transaction larger than the amount of physical memory. This is necessary
+ because LMDB supports databases larger than physical memory.
# Legacy syntax:
smtpd_tls_mandatory_protocols = TLSv1
-If you want to take advantage of ciphers with ephemeral Diffie-Hellman (EDH)
-key exchange (this offers "forward-secrecy"), DH parameters are needed. Instead
-of using the built-in DH parameters for both 1024-bit (non-export ciphers) and
-512-bit (export ciphers), it is better to generate your own parameters, since
-otherwise it would "pay" for a possible attacker to start a brute force attack
-against parameters that are used by everybody. Postfix defaults to compiled-in
-parameters that are shared by all Postfix users who don't generate their own
-settings.
-
-To generate your own set of DH parameters, use:
-
- % o\bop\bpe\ben\bns\bss\bsl\bl g\bge\ben\bnd\bdh\bh -\b-o\bou\but\bt /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/d\bdh\bh_\b_5\b51\b12\b2.\b.p\bpe\bem\bm -\b-2\b2 5\b51\b12\b2
- % o\bop\bpe\ben\bns\bss\bsl\bl g\bge\ben\bnd\bdh\bh -\b-o\bou\but\bt /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/d\bdh\bh_\b_1\b10\b02\b24\b4.\b.p\bpe\bem\bm -\b-2\b2 1\b10\b02\b24\b4
-
-Support for elliptic curve cryptography is available with Postfix 2.6 and
-OpenSSL 1.0.0 or later. To enable ephemeral elliptic curve Diffie-Hellman
-(EECDH) key-exchange, set "smtpd_tls_eecdh_grade = strong" or
-"smtpd_tls_eecdh_grade = ultra". The "ultra" setting is substantially more CPU
-intensive, and "strong" is sufficiently secure for most situations.
-
-Examples:
-
- /etc/postfix/main.cf:
- smtpd_tls_dh1024_param_file = /etc/postfix/dh_1024.pem
- smtpd_tls_dh512_param_file = /etc/postfix/dh_512.pem
- # Postfix >= 2.6:
- smtpd_tls_eecdh_grade = strong
+If you want to take maximal advantage of ciphers that offer forward secrecy see
+the Getting started section of FORWARD_SECRECY_README. The full document
+conveniently presents all information about Postfix "perfect" forward secrecy
+support in one place: what forward secrecy is, how to tweak settings, and what
+you can expect to see when Postfix uses ciphers with forward secrecy.
Postfix 2.8 and later, in combination with OpenSSL 0.9.7 and later allows TLS
servers to preempt the TLS client's cipher-suite preference list. This is
smtp_tls_exclude_ciphers = aNULL
# Preferred form with Postfix >= 2.5:
smtp_tls_mandatory_protocols = !SSLv2
- # Legacy form for Postifx < 2.5:
+ # Legacy form for Postfix < 2.5:
smtp_tls_mandatory_protocols = SSLv3, TLSv1
# Also available with Postfix >= 2.6:
smtp_tls_ciphers = export
-This is the Postfix 2.12 (experimental) branch.
+This is the Postfix 2.12 (experimental) release.
The stable Postfix release is called postfix-2.11.x where 2=major
release number, 11=minor release number, x=patchlevel. The stable
a certificate that allows its government to play man-in-the-middle
on TLS traffic and observe the plaintext.
+Major changes - LMDB database support
+-------------------------------------
+
+LMDB is a memory-mapped database that was originally developed as
+part of OpenLDAP. The Postfix LMDB driver was originally written
+by Howard Chu, LMDB's creator. Support for LMDB has evolved throughout
+the Postfix 2.11 development cycle.
+
+LMDB can be used for all Postfix lookup table and cache storage.
+It is the first persistent Postfix database that can be shared among
+multiple writers such as postscreen daemons (Postfix already supported
+non-persistent memcached caches). See lmdb_table(5) and LMDB_README
+for further information.
+
+Postfix currently supports LMDB version 0.9.11 and later. The minimum
+version may change over time in the light of deployment experience.
+
Major changes - postscreen whitelisting
---------------------------------------
------------------------------------
[Feature 20131031] The check_sasl_access feature can be used to
-block hijacked logins. Like other check_mumble_acces features it
+block hijacked logins. Like other check_mumble_access features it
queries a lookup table (in this case with the SASL login name), and
it supports the same actions as any Postfix access(5) table.
server. See <a href="TLS_README.html">TLS_README</a> for a general
description of Postfix TLS support. </p>
-<h2> What is Forward Secrecy </h2>
+<h2><a name="dfn_fs">What is Forward Secrecy</a></h2>
<p> The term "Forward Secrecy" (or sometimes "Perfect Forward Secrecy")
is used to describe security protocols in which the confidentiality
<li> <p> <b> Prime-field groups (EDH):</b> The server needs to be
configured with a suitably-large prime and a corresponding "generator".
The acronym for forward secrecy over prime fields is EDH for Ephemeral
-Diffie-Hellman (also abbreviated as DHE for Diffie-Hellman Exchange).
+Diffie-Hellman (also abbreviated as DHE).
</p>
<li> <p> <b> Elliptic-curve groups (EECDH): </b> The server needs
at lower computational cost than prime field groups, but are not
as widely implemented. The acronym for the elliptic curve version
is EECDH which is short for Ephemeral Elliptic Curve Diffie-Hellman
-(also abbreviated as ECDHE for Elliptic Curve Diffie-Hellman
-Exchange). </p>
+(also abbreviated as ECDHE). </p>
</ul>
<p> With Postfix 2.6 and 2.7, enable elliptic-curve support in the
Postfix SMTP client and server. This is the default with Postfix
-≥ 2.8.
+≥ 2.8. Note, however, that elliptic-curve support may be disabled
+by the vendor, as in some versions of RedHat Linux. </p>
<blockquote>
<pre>
<h3> EDH Client support (Postfix ≥ 2.2) </h3>
-<p> This space intentionally left blank. </p>
+<p> This works "out of the box" without additional configuration. </p>
<h3> EDH Server support (Postfix ≥ 2.2) </h3>
<hr>
-<h2>Note</h2>
-
-<p> LMDB is not supported in the stable Postfix release. It will
-spontaneously terminate a Postfix daemon process without allowing
-Postfix to 1) report the problem to the maillog file, and to 2)
-provide reduced service where this is appropriate. </p>
-
<h2>Introduction</h2>
<p> Postfix uses databases of various kinds to store and look up
-information. Postfix databases are specified as "type:name".
-OpenLDAP LMDB implements the Postfix database type "lmdb".
-The name of a Postfix OpenLDAP LMDB database is the name
-of the database file without the ".lmdb" suffix. </p>
+information. Postfix databases are specified as "type:name". OpenLDAP
+LMDB (called "LMDB" from here on) implements the Postfix database
+type "lmdb". The name of a Postfix LMDB database is the name of
+the database file without the ".lmdb" suffix. </p>
<p> This document describes: </p>
-<ol>
-
-<li> <p> How to build Postfix <a href="#with_lmdb">with OpenLDAP
-LMDB support</a>. </p>
+<ul>
-<li> <p> How to <a href="#configure">configure</a> LMDB settings. </p>
+<li> <p> <a href="#with_lmdb">Building Postfix with LMDB support</a>.
+</p>
-<li> <p> Missing <a href="#pthread">pthread</a> library trouble. </p>
+<li> <p> <a href="#configure">Configuring LMDB settings</a>. </p>
-<li> <p> Unexpected <a href="#limitations">failure modes</a> that
-don't exist with other Postfix databases. </p>
+<li> <p> <a href="#supported"> Supported minimum LMDB patchlevel</a>. </p>
-</ol>
+</ul>
-<h2><a name="with_lmdb">Building Postfix with OpenLDAP LMDB support</a></h2>
+<h2><a name="with_lmdb">Building Postfix with LMDB support</a></h2>
-<p> Postfix normally does not enable OpenLDAP LMDB support. To
-build Postfix with OpenLDAP LMDB support, use something like: </p>
+<p> Postfix normally does not enable LMDB support. To
+build Postfix with LMDB support, use something like: </p>
<blockquote>
<pre>
</pre>
</blockquote>
-<p> The exact pathnames depend on how OpenLDAP LMDB was installed. </p>
-
-<h2><a name="configure">Configure LMDB settings</a></h2>
-
-<p> Postfix provides one configuration parameter that controls
-OpenLDAP LMDB database behavior. </p>
-
-<ul>
-
-<li> <p> <a href="postconf.5.html#lmdb_map_size">lmdb_map_size</a> (default: 16777216). This setting specifies
-the initial OpenLDAP LMDB database size limit in bytes. Each time
-a database becomes full, its size limit is doubled. The maximum
-size is the largest signed integer value of "long". </p>
-
-</ul>
-
-<h2><a name="pthread">Missing pthread library trouble</a></h2>
+<p> The exact pathnames depend on how LMDB was installed. </p>
<p> When building Postfix fails with: </p>
</pre>
</blockquote>
-<p> Source code for OpenLDAP LMDB is available at
-<a href="http://www.openldap.org">http://www.openldap.org</a>.
-More information is available at
-<a href="http://highlandsun.com/hyc/mdb/">http://highlandsun.com/hyc/mdb/</a>. </p>
+<h2><a name="configure">Configuring LMDB settings</a></h2>
+
+<p> Postfix provides one configuration parameter that controls
+LMDB database behavior. </p>
+
+<ul>
+
+<li> <p> <a href="postconf.5.html#lmdb_map_size">lmdb_map_size</a> (default: 16777216). This setting specifies
+the initial LMDB database size limit in bytes. Each time
+a database becomes full, its size limit is doubled. The maximum
+size is the largest signed integer value of "long". </p>
+
+</ul>
+
+<h2> <a name="supported"> Supported minimum LMDB patchlevel </a> </h2>
+
+<p> Currently, Postfix supports LMDB 0.9.11 or later. The supported
+minimum LMDB patchlevel has evolved over time, as the result of
+deployment experience with Postfix. </p>
+
+<ul>
+
+<li> <p> LMDB 0.9.11 allows Postfix daemons to log an LMDB error
+message, instead of falling out of the sky without any notification.
+</p>
+
+<li> <p> LMDB 0.9.10 closes an information leak where LMDB was
+writing up to 4kbyte-chunks of uninitialized heap memory to the
+database, persisting information that was not meant to be persisted,
+or sharing information that was not meant to be shared. </p>
+
+<li> <p> LMDB 0.9.8 allows Postfix to use external (fcntl()-based)
+locks, instead of having to use world-writable LMDB lock files.
+</p>
+
+<li> <p> LMDB 0.9.8 allows an application to recover from a "database
+full" error without having to close the database, by adding support
+to update the database size limit on-the-fly; and it adds support
+for an application to adopt someone elses change to the database
+size limit, without having to close the database. </p>
+
+<li> <p> LMDB 0.9.7 allows the postmap and postalias commands to
+use a bulk-mode transaction larger than the amount of physical
+memory. This is necessary because LMDB supports databases larger
+than physical memory. </p>
+
+</ul>
+
+<!--
<h2><a name="limitations">Unexpected failure modes of Postfix LMDB
databases. </a> </h2>
failure modes have been eliminated in the course of time.
The writeup below reflects the status as of LMDB 0.9.9. </p>
+-->
+
<!--
<p> <strong>Unexpected "Permission denied" errors. </strong></p>
-->
+<!--
+
<p> <strong>Non-obvious recovery with <a href="postmap.1.html">postmap(1)</a>, <a href="postalias.1.html">postalias(1)</a>, or
<a href="tlsmgr.8.html">tlsmgr(8)</a> from a corrupted database. </strong></p>
use ZFS on systems without ECC memory error correction. </p>
</dd> </dl>
+
+-->
+
+</body>
+
+</html>
</pre>
</blockquote>
-<p> If you want to take advantage of ciphers with ephemeral Diffie-Hellman
-(EDH) key exchange (this offers "forward-secrecy"), DH parameters are
-needed. Instead of using the built-in DH parameters for both 1024-bit
-(non-export ciphers) and 512-bit (export ciphers), it is better to
-generate your own parameters, since otherwise it would "pay" for a
-possible attacker to start a brute force attack against parameters that
-are used by everybody. Postfix defaults to compiled-in parameters
-that are shared by all Postfix users who don't generate their own
-settings. </p>
-
-<p> To generate your own set of DH parameters, use: </p>
-
-<blockquote>
-<pre>
-% <b>openssl gendh -out /etc/postfix/dh_512.pem -2 512</b>
-% <b>openssl gendh -out /etc/postfix/dh_1024.pem -2 1024</b>
-</pre>
-</blockquote>
-
-<p> Support for elliptic curve cryptography is available with Postfix
-2.6 and OpenSSL 1.0.0 or later. To enable ephemeral elliptic curve
-Diffie-Hellman (EECDH) key-exchange, set "<a href="postconf.5.html#smtpd_tls_eecdh_grade">smtpd_tls_eecdh_grade</a> =
-strong" or "<a href="postconf.5.html#smtpd_tls_eecdh_grade">smtpd_tls_eecdh_grade</a> = ultra". The "ultra" setting is
-substantially more CPU intensive, and "strong" is sufficiently
-secure for most situations. </p>
-
-<p> Examples: </p>
-
-<blockquote>
-<pre>
-/etc/postfix/<a href="postconf.5.html">main.cf</a>:
- <a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a> = /etc/postfix/dh_1024.pem
- <a href="postconf.5.html#smtpd_tls_dh512_param_file">smtpd_tls_dh512_param_file</a> = /etc/postfix/dh_512.pem
- # Postfix ≥ 2.6:
- <a href="postconf.5.html#smtpd_tls_eecdh_grade">smtpd_tls_eecdh_grade</a> = strong
-</pre>
-</blockquote>
+<p> If you want to take maximal advantage of ciphers that offer <a
+href="FORWARD_SECRECY_README.html#dfn_fs">forward secrecy</a> see
+the <a href="FORWARD_SECRECY_README.html#quick-start">Getting
+started</a> section of <a
+href="FORWARD_SECRECY_README.html">FORWARD_SECRECY_README</a>. The
+full document conveniently presents all information about Postfix
+"perfect" forward secrecy support in one place: what forward secrecy
+is, how to tweak settings, and what you can expect to see when
+Postfix uses ciphers with forward secrecy. </p>
<p> Postfix 2.8 and later, in combination with OpenSSL 0.9.7 and later
allows TLS servers to preempt the TLS client's cipher-suite preference list.
<a href="postconf.5.html#smtp_tls_exclude_ciphers">smtp_tls_exclude_ciphers</a> = aNULL
# Preferred form with Postfix ≥ 2.5:
<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a> = !SSLv2
- # Legacy form for Postifx < 2.5:
+ # Legacy form for Postfix < 2.5:
<a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a> = SSLv3, TLSv1
# Also available with Postfix ≥ 2.6:
<a href="postconf.5.html#smtp_tls_ciphers">smtp_tls_ciphers</a> = export
<b>postmap -q - <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/</b><i>filename</i> <<i>inputfile</i>
<b>DESCRIPTION</b>
- LMDB is not supported in the stable Postfix release. It will sponta-
- neously terminate a Postfix daemon process without allowing Postfix to
- 1) report the problem to the maillog file, and to 2) provide reduced
- service where this is appropriate.
-
- The Postfix LMDB adapter provides access to a persistent, memory-
+ The Postfix LMDB adapter provides access to a persistent, memory-
mapped, key-value store. The database size is limited only by the size
- of the memory address space and file system.
+ of the memory address space (typically 32 or 64 bits) and by the avail-
+ able file system space.
<b>REQUESTS</b>
The LMDB adapter supports all Postfix lookup table operations. This
configuration change.
<b><a href="postconf.5.html#lmdb_map_size">lmdb_map_size</a> (default: 16777216)</b>
- The initial OpenLDAP LMDB database size limit in bytes.
+ The initial LMDB database size limit in bytes.
<b>SEE ALSO</b>
<a href="postconf.1.html">postconf(1)</a>, Postfix supported lookup tables
<b>README FILES</b>
<a href="DATABASE_README.html">DATABASE_README</a>, Postfix lookup table overview
- <a href="LMDB_README.html">LMDB_README</a>, Postfix LMDB howto
+ <a href="LMDB_README.html">LMDB_README</a>, Postfix OpenLDAP LMDB howto
<b>LICENSE</b>
The Secure Mailer license must be distributed with this software.
<DT><b><a name="smtp_cname_overrides_servername">smtp_cname_overrides_servername</a>
(default: version dependent)</b></DT><DD>
-<p> Allow DNS CNAME records to override the servername that the
-Postfix SMTP client uses for logging, SASL password lookup, TLS
+<p> When the remote SMTP servername is a DNS CNAME, replace the
+servername with the result from CNAME expansion for the purpose of
+logging, SASL password lookup, TLS
policy decisions, or TLS certificate verification. The value "no"
hardens Postfix <a href="postconf.5.html#smtp_tls_per_site">smtp_tls_per_site</a> hostname-based policies against
false hostname information in DNS CNAME records, and makes SASL
to the domain owner to configure their MX hosts and their DNS
sensibly. To configure the Postfix SMTP client for DNSSEC lookups
see the documentation for the <a href="postconf.5.html#smtp_dns_support_level">smtp_dns_support_level</a> <a href="postconf.5.html">main.cf</a>
-parameter. When TLSA records are not found or are all unusable the
-effective security level is "may" or "encrypt" respectively. For
+parameter. When DNSSEC-validated TLSA records are not found the
+effective tls security level is "may". When TLSA records are found,
+but are all unusable the effective security level is "encrypt". For
purposes of protocol and cipher selection, the "dane" security level
is treated like a "mandatory" TLS security level, and weak ciphers
and protocols are disabled. Since DANE authenticates server
(default: empty)</b></DT><DD>
<p> File with DH parameters that the Postfix SMTP server should
-use with EDH ciphers. </p>
+use with non-export EDH ciphers. </p>
<p> Instead of using the exact same parameter sets as distributed
with other TLS packages, it is more secure to generate your own
-set of parameters with something like the following command: </p>
+set of parameters with something like the following commands: </p>
<blockquote>
<pre>
-openssl gendh -out /etc/postfix/dh_1024.pem -2 1024
+openssl dhparam -out /etc/postfix/dh512.pem 512
+openssl dhparam -out /etc/postfix/dh1024.pem 1024
+openssl dhparam -out /etc/postfix/dh2048.pem 2048
</pre>
</blockquote>
-<p> Your actual source for entropy may differ. Some systems have
-/dev/random; on other system you may consider using the "Entropy
-Gathering Daemon EGD", available at <a href="http://egd.sourceforge.net/">http://egd.sourceforge.net/</a>
-</p>
+<p> It is safe to share the same DH parameters between multiple
+Postfix instances. If you prefer, you can generate separate
+parameters for each instance. </p>
+
+<p> If you want to take maximal advantage of ciphers that offer <a
+href="FORWARD_SECRECY_README.html#dfn_fs">forward secrecy</a> see
+the <a href="FORWARD_SECRECY_README.html#quick-start">Getting
+started</a> section of <a
+href="FORWARD_SECRECY_README.html">FORWARD_SECRECY_README</a>. The
+full document conveniently presents all information about Postfix
+"perfect" forward secrecy support in one place: what forward secrecy
+is, how to tweak settings, and what you can expect to see when
+Postfix uses ciphers with forward secrecy. </p>
<p> Example: </p>
<pre>
-<a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a> = /etc/postfix/dh_1024.pem
+<a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a> = /etc/postfix/dh2048.pem
</pre>
<p>This feature is available with Postfix version 2.2.</p>
(default: empty)</b></DT><DD>
<p> File with DH parameters that the Postfix SMTP server should
-use with EDH ciphers. </p>
+use with export-grade EDH ciphers. </p>
<p> See also the discussion under the <a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a>
configuration parameter. </p>
</dl>
+<p> If you want to take maximal advantage of ciphers that offer <a
+href="FORWARD_SECRECY_README.html#dfn_fs">forward secrecy</a> see
+the <a href="FORWARD_SECRECY_README.html#quick-start">Getting
+started</a> section of <a
+href="FORWARD_SECRECY_README.html">FORWARD_SECRECY_README</a>. The
+full document conveniently presents all information about Postfix
+"perfect" forward secrecy support in one place: what forward secrecy
+is, how to tweak settings, and what you can expect to see when
+Postfix uses ciphers with forward secrecy. </p>
+
<p> This feature is available in Postfix 2.6 and later, when it is
-compiled and linked with OpenSSL 1.0.0 or later. </p>
+compiled and linked with OpenSSL 1.0.0 or later on platforms
+where EC algorithms have not been disabled by the vendor. </p>
</DD>
attacks. The selected curve must be implemented by OpenSSL (as
reported by ecparam(1) with the "-list_curves" option) and be one
of the curves listed in Section 5.1.1 of <a href="http://tools.ietf.org/html/rfc4492">RFC 4492</a>. You should not
-generally change this setting. </p>
+generally change this setting. Remote SMTP client implementations
+must support this curve for EECDH key exchange to take place. It
+is unwise to choose an "exotic" curve supported by only a small subset
+of clients. </p>
-<p> This default curve is specified in NSA "Suite B" Cryptography
-(see <a href="http://www.nsa.gov/ia/industry/crypto_suite_b.cfm">http://www.nsa.gov/ia/industry/crypto_suite_b.cfm</a>) for
-information classified as SECRET. </p>
+<p> The default "strong" curve is rated in NSA <a
+href="http://www.nsa.gov/ia/programs/suiteb_cryptography/">Suite
+B</a> for information classified up to SECRET. </p>
<p> Note: elliptic curve names are poorly standardized; different
standards groups are assigning different names to the same underlying
under the SECG name "secp256r1", but OpenSSL does not recognize the
latter name. </p>
+<p> If you want to take maximal advantage of ciphers that offer <a
+href="FORWARD_SECRECY_README.html#dfn_fs">forward secrecy</a> see
+the <a href="FORWARD_SECRECY_README.html#quick-start">Getting
+started</a> section of <a
+href="FORWARD_SECRECY_README.html">FORWARD_SECRECY_README</a>. The
+full document conveniently presents all information about Postfix
+"perfect" forward secrecy support in one place: what forward secrecy
+is, how to tweak settings, and what you can expect to see when
+Postfix uses ciphers with forward secrecy. </p>
+
<p> This feature is available in Postfix 2.6 and later, when it is
-compiled and linked with OpenSSL 1.0.0 or later. </p>
+compiled and linked with OpenSSL 1.0.0 or later on platforms where
+EC algorithms have not been disabled by the vendor. </p>
</DD>
"-list_curves" option) and be one of the curves listed in Section 5.1.1
of <a href="http://tools.ietf.org/html/rfc4492">RFC 4492</a>. You should not generally change this setting. </p>
-<p> This default "ultra" curve is specified in NSA "Suite B" Cryptography
-(see <a href="http://www.nsa.gov/ia/industry/crypto_suite_b.cfm">http://www.nsa.gov/ia/industry/crypto_suite_b.cfm</a>) for information
-classified as TOP SECRET. </p>
+<p> This default "ultra" curve is rated in NSA <a
+href="http://www.nsa.gov/ia/programs/suiteb_cryptography/">Suite
+B</a> for information classified up to TOP SECRET. </p>
+
+<p> If you want to take maximal advantage of ciphers that offer <a
+href="FORWARD_SECRECY_README.html#dfn_fs">forward secrecy</a> see
+the <a href="FORWARD_SECRECY_README.html#quick-start">Getting
+started</a> section of <a
+href="FORWARD_SECRECY_README.html">FORWARD_SECRECY_README</a>. The
+full document conveniently presents all information about Postfix
+"perfect" forward secrecy support in one place: what forward secrecy
+is, how to tweak settings, and what you can expect to see when
+Postfix uses ciphers with forward secrecy. </p>
<p> This feature is available in Postfix 2.6 and later, when it is
-compiled and linked with OpenSSL 1.0.0 or later. </p>
+compiled and linked with OpenSSL 1.0.0 or later on platforms where
+EC algorithms have not been disabled by the vendor. </p>
</DD>
(default: $<a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a>)</b></DT><DD>
<p> File with DH parameters that the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server
-should use with EDH ciphers. See <a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a> for
-further details. </p>
+should use with non-export EDH ciphers. See <a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a>
+for further details. </p>
<p> This feature is available in Postfix 2.8 and later. </p>
(default: $<a href="postconf.5.html#smtpd_tls_dh512_param_file">smtpd_tls_dh512_param_file</a>)</b></DT><DD>
<p> File with DH parameters that the Postfix <a href="tlsproxy.8.html">tlsproxy(8)</a> server
-should use with EDH ciphers. See <a href="postconf.5.html#smtpd_tls_dh512_param_file">smtpd_tls_dh512_param_file</a> for
-further details. </p>
+should use with export-grade EDH ciphers. See <a href="postconf.5.html#smtpd_tls_dh512_param_file">smtpd_tls_dh512_param_file</a>
+for further details. </p>
<p> This feature is available in Postfix 2.8 and later. </p>
<b><a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a> (empty)</b>
File with DH parameters that the Postfix SMTP server should use
- with EDH ciphers.
+ with non-export EDH ciphers.
<b><a href="postconf.5.html#smtpd_tls_dh512_param_file">smtpd_tls_dh512_param_file</a> (empty)</b>
File with DH parameters that the Postfix SMTP server should use
- with EDH ciphers.
+ with export-grade EDH ciphers.
<b><a href="postconf.5.html#smtpd_tls_dkey_file">smtpd_tls_dkey_file</a> ($<a href="postconf.5.html#smtpd_tls_dcert_file">smtpd_tls_dcert_file</a>)</b>
File with the Postfix SMTP server DSA private key in PEM format.
<b><a href="postconf.5.html#tlsproxy_tls_dh1024_param_file">tlsproxy_tls_dh1024_param_file</a> ($<a href="postconf.5.html#smtpd_tls_dh1024_param_file">smtpd_tls_dh1024_param_file</a>)</b>
File with DH parameters that the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server
- should use with EDH ciphers.
+ should use with non-export EDH ciphers.
<b><a href="postconf.5.html#tlsproxy_tls_dh512_param_file">tlsproxy_tls_dh512_param_file</a> ($<a href="postconf.5.html#smtpd_tls_dh512_param_file">smtpd_tls_dh512_param_file</a>)</b>
File with DH parameters that the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server
- should use with EDH ciphers.
+ should use with export-grade EDH ciphers.
<b><a href="postconf.5.html#tlsproxy_tls_dkey_file">tlsproxy_tls_dkey_file</a> ($<a href="postconf.5.html#smtpd_tls_dkey_file">smtpd_tls_dkey_file</a>)</b>
File with the Postfix <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> server DSA private key in PEM
.SH DESCRIPTION
.ad
.fi
-LMDB is not supported in the stable Postfix release. It
-will spontaneously terminate a Postfix daemon process without
-allowing Postfix to 1) report the problem to the maillog
-file, and to 2) provide reduced service where this is
-appropriate.
-
The Postfix LMDB adapter provides access to a persistent,
memory-mapped, key-value store. The database size is limited
-only by the size of the memory address space and file system.
+only by the size of the memory address space (typically 32
+or 64 bits) and by the available file system space.
.SH "REQUESTS"
.na
.nf
main.cf. With long-running daemon programs, Use the command
"\fBpostfix reload\fR" after a configuration change.
.IP "\fBlmdb_map_size (default: 16777216)\fR"
-The initial OpenLDAP LMDB database size limit in bytes.
+The initial LMDB database size limit in bytes.
.SH "SEE ALSO"
.na
.nf
.na
.nf
DATABASE_README, Postfix lookup table overview
-LMDB_README, Postfix LMDB howto
+LMDB_README, Postfix OpenLDAP LMDB howto
.SH "LICENSE"
.na
.nf
.PP
This feature is available in Postfix 2.5 and later.
.SH smtp_cname_overrides_servername (default: version dependent)
-Allow DNS CNAME records to override the servername that the
-Postfix SMTP client uses for logging, SASL password lookup, TLS
+When the remote SMTP servername is a DNS CNAME, replace the
+servername with the result from CNAME expansion for the purpose of
+logging, SASL password lookup, TLS
policy decisions, or TLS certificate verification. The value "no"
hardens Postfix smtp_tls_per_site hostname-based policies against
false hostname information in DNS CNAME records, and makes SASL
to the domain owner to configure their MX hosts and their DNS
sensibly. To configure the Postfix SMTP client for DNSSEC lookups
see the documentation for the smtp_dns_support_level main.cf
-parameter. When TLSA records are not found or are all unusable the
-effective security level is "may" or "encrypt" respectively. For
+parameter. When DNSSEC-validated TLSA records are not found the
+effective tls security level is "may". When TLSA records are found,
+but are all unusable the effective security level is "encrypt". For
purposes of protocol and cipher selection, the "dane" security level
is treated like a "mandatory" TLS security level, and weak ciphers
and protocols are disabled. Since DANE authenticates server
This feature is available in Postfix 2.2 and later.
.SH smtpd_tls_dh1024_param_file (default: empty)
File with DH parameters that the Postfix SMTP server should
-use with EDH ciphers.
+use with non-export EDH ciphers.
.PP
Instead of using the exact same parameter sets as distributed
with other TLS packages, it is more secure to generate your own
-set of parameters with something like the following command:
+set of parameters with something like the following commands:
.sp
.in +4
.nf
.na
.ft C
-openssl gendh -out /etc/postfix/dh_1024.pem -2 1024
+openssl dhparam -out /etc/postfix/dh512.pem 512
+openssl dhparam -out /etc/postfix/dh1024.pem 1024
+openssl dhparam -out /etc/postfix/dh2048.pem 2048
.fi
.ad
.ft R
.in -4
.PP
-Your actual source for entropy may differ. Some systems have
-/dev/random; on other system you may consider using the "Entropy
-Gathering Daemon EGD", available at http://egd.sourceforge.net/
+It is safe to share the same DH parameters between multiple
+Postfix instances. If you prefer, you can generate separate
+parameters for each instance.
+.PP
+If you want to take maximal advantage of ciphers that offer forward secrecy see
+the Getting
+started section of FORWARD_SECRECY_README. The
+full document conveniently presents all information about Postfix
+"perfect" forward secrecy support in one place: what forward secrecy
+is, how to tweak settings, and what you can expect to see when
+Postfix uses ciphers with forward secrecy.
.PP
Example:
.PP
.nf
.na
.ft C
-smtpd_tls_dh1024_param_file = /etc/postfix/dh_1024.pem
+smtpd_tls_dh1024_param_file = /etc/postfix/dh2048.pem
.fi
.ad
.ft R
This feature is available with Postfix version 2.2.
.SH smtpd_tls_dh512_param_file (default: empty)
File with DH parameters that the Postfix SMTP server should
-use with EDH ciphers.
+use with export-grade EDH ciphers.
.PP
See also the discussion under the smtpd_tls_dh1024_param_file
configuration parameter.
.br
.br
.PP
+If you want to take maximal advantage of ciphers that offer forward secrecy see
+the Getting
+started section of FORWARD_SECRECY_README. The
+full document conveniently presents all information about Postfix
+"perfect" forward secrecy support in one place: what forward secrecy
+is, how to tweak settings, and what you can expect to see when
+Postfix uses ciphers with forward secrecy.
+.PP
This feature is available in Postfix 2.6 and later, when it is
-compiled and linked with OpenSSL 1.0.0 or later.
+compiled and linked with OpenSSL 1.0.0 or later on platforms
+where EC algorithms have not been disabled by the vendor.
.SH smtpd_tls_exclude_ciphers (default: empty)
List of ciphers or cipher types to exclude from the SMTP server
cipher list at all TLS security levels. Excluding valid ciphers
attacks. The selected curve must be implemented by OpenSSL (as
reported by \fBecparam\fR(1) with the "-list_curves" option) and be one
of the curves listed in Section 5.1.1 of RFC 4492. You should not
-generally change this setting.
+generally change this setting. Remote SMTP client implementations
+must support this curve for EECDH key exchange to take place. It
+is unwise to choose an "exotic" curve supported by only a small subset
+of clients.
.PP
-This default curve is specified in NSA "Suite B" Cryptography
-(see http://www.nsa.gov/ia/industry/crypto_suite_b.cfm) for
-information classified as SECRET.
+The default "strong" curve is rated in NSA Suite
+B for information classified up to SECRET.
.PP
Note: elliptic curve names are poorly standardized; different
standards groups are assigning different names to the same underlying
under the SECG name "secp256r1", but OpenSSL does not recognize the
latter name.
.PP
+If you want to take maximal advantage of ciphers that offer forward secrecy see
+the Getting
+started section of FORWARD_SECRECY_README. The
+full document conveniently presents all information about Postfix
+"perfect" forward secrecy support in one place: what forward secrecy
+is, how to tweak settings, and what you can expect to see when
+Postfix uses ciphers with forward secrecy.
+.PP
This feature is available in Postfix 2.6 and later, when it is
-compiled and linked with OpenSSL 1.0.0 or later.
+compiled and linked with OpenSSL 1.0.0 or later on platforms where
+EC algorithms have not been disabled by the vendor.
.SH tls_eecdh_ultra_curve (default: secp384r1)
The elliptic curve used by the Postfix SMTP server for maximally
strong
"-list_curves" option) and be one of the curves listed in Section 5.1.1
of RFC 4492. You should not generally change this setting.
.PP
-This default "ultra" curve is specified in NSA "Suite B" Cryptography
-(see http://www.nsa.gov/ia/industry/crypto_suite_b.cfm) for information
-classified as TOP SECRET.
+This default "ultra" curve is rated in NSA Suite
+B for information classified up to TOP SECRET.
+.PP
+If you want to take maximal advantage of ciphers that offer forward secrecy see
+the Getting
+started section of FORWARD_SECRECY_README. The
+full document conveniently presents all information about Postfix
+"perfect" forward secrecy support in one place: what forward secrecy
+is, how to tweak settings, and what you can expect to see when
+Postfix uses ciphers with forward secrecy.
.PP
This feature is available in Postfix 2.6 and later, when it is
-compiled and linked with OpenSSL 1.0.0 or later.
+compiled and linked with OpenSSL 1.0.0 or later on platforms where
+EC algorithms have not been disabled by the vendor.
.SH tls_export_cipherlist (default: ALL:+RC4:@STRENGTH)
The OpenSSL cipherlist for "EXPORT" or higher grade ciphers. This
defines the meaning of the "export" setting in smtpd_tls_mandatory_ciphers,
This feature is available in Postfix 2.8 and later.
.SH tlsproxy_tls_dh1024_param_file (default: $smtpd_tls_dh1024_param_file)
File with DH parameters that the Postfix \fBtlsproxy\fR(8) server
-should use with EDH ciphers. See smtpd_tls_dh1024_param_file for
-further details.
+should use with non-export EDH ciphers. See smtpd_tls_dh1024_param_file
+for further details.
.PP
This feature is available in Postfix 2.8 and later.
.SH tlsproxy_tls_dh512_param_file (default: $smtpd_tls_dh512_param_file)
File with DH parameters that the Postfix \fBtlsproxy\fR(8) server
-should use with EDH ciphers. See smtpd_tls_dh512_param_file for
-further details.
+should use with export-grade EDH ciphers. See smtpd_tls_dh512_param_file
+for further details.
.PP
This feature is available in Postfix 2.8 and later.
.SH tlsproxy_tls_dkey_file (default: $smtpd_tls_dkey_file)
File with the Postfix SMTP server DSA certificate in PEM format.
.IP "\fBsmtpd_tls_dh1024_param_file (empty)\fR"
File with DH parameters that the Postfix SMTP server should
-use with EDH ciphers.
+use with non-export EDH ciphers.
.IP "\fBsmtpd_tls_dh512_param_file (empty)\fR"
File with DH parameters that the Postfix SMTP server should
-use with EDH ciphers.
+use with export-grade EDH ciphers.
.IP "\fBsmtpd_tls_dkey_file ($smtpd_tls_dcert_file)\fR"
File with the Postfix SMTP server DSA private key in PEM format.
.IP "\fBsmtpd_tls_key_file ($smtpd_tls_cert_file)\fR"
format.
.IP "\fBtlsproxy_tls_dh1024_param_file ($smtpd_tls_dh1024_param_file)\fR"
File with DH parameters that the Postfix \fBtlsproxy\fR(8) server
-should use with EDH ciphers.
+should use with non-export EDH ciphers.
.IP "\fBtlsproxy_tls_dh512_param_file ($smtpd_tls_dh512_param_file)\fR"
File with DH parameters that the Postfix \fBtlsproxy\fR(8) server
-should use with EDH ciphers.
+should use with export-grade EDH ciphers.
.IP "\fBtlsproxy_tls_dkey_file ($smtpd_tls_dkey_file)\fR"
File with the Postfix \fBtlsproxy\fR(8) server DSA private key in PEM
format.
server. See <a href="TLS_README.html">TLS_README</a> for a general
description of Postfix TLS support. </p>
-<h2> What is Forward Secrecy </h2>
+<h2><a name="dfn_fs">What is Forward Secrecy</a></h2>
<p> The term "Forward Secrecy" (or sometimes "Perfect Forward Secrecy")
is used to describe security protocols in which the confidentiality
<li> <p> <b> Prime-field groups (EDH):</b> The server needs to be
configured with a suitably-large prime and a corresponding "generator".
The acronym for forward secrecy over prime fields is EDH for Ephemeral
-Diffie-Hellman (also abbreviated as DHE for Diffie-Hellman Exchange).
+Diffie-Hellman (also abbreviated as DHE).
</p>
<li> <p> <b> Elliptic-curve groups (EECDH): </b> The server needs
at lower computational cost than prime field groups, but are not
as widely implemented. The acronym for the elliptic curve version
is EECDH which is short for Ephemeral Elliptic Curve Diffie-Hellman
-(also abbreviated as ECDHE for Elliptic Curve Diffie-Hellman
-Exchange). </p>
+(also abbreviated as ECDHE). </p>
</ul>
<p> With Postfix 2.6 and 2.7, enable elliptic-curve support in the
Postfix SMTP client and server. This is the default with Postfix
-≥ 2.8.
+≥ 2.8. Note, however, that elliptic-curve support may be disabled
+by the vendor, as in some versions of RedHat Linux. </p>
<blockquote>
<pre>
<h3> EDH Client support (Postfix ≥ 2.2) </h3>
-<p> This space intentionally left blank. </p>
+<p> This works "out of the box" without additional configuration. </p>
<h3> EDH Server support (Postfix ≥ 2.2) </h3>
<hr>
-<h2>Note</h2>
-
-<p> LMDB is not supported in the stable Postfix release. It will
-spontaneously terminate a Postfix daemon process without allowing
-Postfix to 1) report the problem to the maillog file, and to 2)
-provide reduced service where this is appropriate. </p>
-
<h2>Introduction</h2>
<p> Postfix uses databases of various kinds to store and look up
-information. Postfix databases are specified as "type:name".
-OpenLDAP LMDB implements the Postfix database type "lmdb".
-The name of a Postfix OpenLDAP LMDB database is the name
-of the database file without the ".lmdb" suffix. </p>
+information. Postfix databases are specified as "type:name". OpenLDAP
+LMDB (called "LMDB" from here on) implements the Postfix database
+type "lmdb". The name of a Postfix LMDB database is the name of
+the database file without the ".lmdb" suffix. </p>
<p> This document describes: </p>
-<ol>
-
-<li> <p> How to build Postfix <a href="#with_lmdb">with OpenLDAP
-LMDB support</a>. </p>
+<ul>
-<li> <p> How to <a href="#configure">configure</a> LMDB settings. </p>
+<li> <p> <a href="#with_lmdb">Building Postfix with LMDB support</a>.
+</p>
-<li> <p> Missing <a href="#pthread">pthread</a> library trouble. </p>
+<li> <p> <a href="#configure">Configuring LMDB settings</a>. </p>
-<li> <p> Unexpected <a href="#limitations">failure modes</a> that
-don't exist with other Postfix databases. </p>
+<li> <p> <a href="#supported"> Supported minimum LMDB patchlevel</a>. </p>
-</ol>
+</ul>
-<h2><a name="with_lmdb">Building Postfix with OpenLDAP LMDB support</a></h2>
+<h2><a name="with_lmdb">Building Postfix with LMDB support</a></h2>
-<p> Postfix normally does not enable OpenLDAP LMDB support. To
-build Postfix with OpenLDAP LMDB support, use something like: </p>
+<p> Postfix normally does not enable LMDB support. To
+build Postfix with LMDB support, use something like: </p>
<blockquote>
<pre>
</pre>
</blockquote>
-<p> The exact pathnames depend on how OpenLDAP LMDB was installed. </p>
-
-<h2><a name="configure">Configure LMDB settings</a></h2>
-
-<p> Postfix provides one configuration parameter that controls
-OpenLDAP LMDB database behavior. </p>
-
-<ul>
-
-<li> <p> lmdb_map_size (default: 16777216). This setting specifies
-the initial OpenLDAP LMDB database size limit in bytes. Each time
-a database becomes full, its size limit is doubled. The maximum
-size is the largest signed integer value of "long". </p>
-
-</ul>
-
-<h2><a name="pthread">Missing pthread library trouble</a></h2>
+<p> The exact pathnames depend on how LMDB was installed. </p>
<p> When building Postfix fails with: </p>
</pre>
</blockquote>
-<p> Source code for OpenLDAP LMDB is available at
-http://www.openldap.org.
-More information is available at
-http://highlandsun.com/hyc/mdb/. </p>
+<h2><a name="configure">Configuring LMDB settings</a></h2>
+
+<p> Postfix provides one configuration parameter that controls
+LMDB database behavior. </p>
+
+<ul>
+
+<li> <p> lmdb_map_size (default: 16777216). This setting specifies
+the initial LMDB database size limit in bytes. Each time
+a database becomes full, its size limit is doubled. The maximum
+size is the largest signed integer value of "long". </p>
+
+</ul>
+
+<h2> <a name="supported"> Supported minimum LMDB patchlevel </a> </h2>
+
+<p> Currently, Postfix supports LMDB 0.9.11 or later. The supported
+minimum LMDB patchlevel has evolved over time, as the result of
+deployment experience with Postfix. </p>
+
+<ul>
+
+<li> <p> LMDB 0.9.11 allows Postfix daemons to log an LMDB error
+message, instead of falling out of the sky without any notification.
+</p>
+
+<li> <p> LMDB 0.9.10 closes an information leak where LMDB was
+writing up to 4kbyte-chunks of uninitialized heap memory to the
+database, persisting information that was not meant to be persisted,
+or sharing information that was not meant to be shared. </p>
+
+<li> <p> LMDB 0.9.8 allows Postfix to use external (fcntl()-based)
+locks, instead of having to use world-writable LMDB lock files.
+</p>
+
+<li> <p> LMDB 0.9.8 allows an application to recover from a "database
+full" error without having to close the database, by adding support
+to update the database size limit on-the-fly; and it adds support
+for an application to adopt someone elses change to the database
+size limit, without having to close the database. </p>
+
+<li> <p> LMDB 0.9.7 allows the postmap and postalias commands to
+use a bulk-mode transaction larger than the amount of physical
+memory. This is necessary because LMDB supports databases larger
+than physical memory. </p>
+
+</ul>
+
+<!--
<h2><a name="limitations">Unexpected failure modes of Postfix LMDB
databases. </a> </h2>
failure modes have been eliminated in the course of time.
The writeup below reflects the status as of LMDB 0.9.9. </p>
+-->
+
<!--
<p> <strong>Unexpected "Permission denied" errors. </strong></p>
-->
+<!--
+
<p> <strong>Non-obvious recovery with postmap(1), postalias(1), or
tlsmgr(8) from a corrupted database. </strong></p>
use ZFS on systems without ECC memory error correction. </p>
</dd> </dl>
+
+-->
+
+</body>
+
+</html>
</pre>
</blockquote>
-<p> If you want to take advantage of ciphers with ephemeral Diffie-Hellman
-(EDH) key exchange (this offers "forward-secrecy"), DH parameters are
-needed. Instead of using the built-in DH parameters for both 1024-bit
-(non-export ciphers) and 512-bit (export ciphers), it is better to
-generate your own parameters, since otherwise it would "pay" for a
-possible attacker to start a brute force attack against parameters that
-are used by everybody. Postfix defaults to compiled-in parameters
-that are shared by all Postfix users who don't generate their own
-settings. </p>
-
-<p> To generate your own set of DH parameters, use: </p>
-
-<blockquote>
-<pre>
-% <b>openssl gendh -out /etc/postfix/dh_512.pem -2 512</b>
-% <b>openssl gendh -out /etc/postfix/dh_1024.pem -2 1024</b>
-</pre>
-</blockquote>
-
-<p> Support for elliptic curve cryptography is available with Postfix
-2.6 and OpenSSL 1.0.0 or later. To enable ephemeral elliptic curve
-Diffie-Hellman (EECDH) key-exchange, set "smtpd_tls_eecdh_grade =
-strong" or "smtpd_tls_eecdh_grade = ultra". The "ultra" setting is
-substantially more CPU intensive, and "strong" is sufficiently
-secure for most situations. </p>
-
-<p> Examples: </p>
-
-<blockquote>
-<pre>
-/etc/postfix/main.cf:
- smtpd_tls_dh1024_param_file = /etc/postfix/dh_1024.pem
- smtpd_tls_dh512_param_file = /etc/postfix/dh_512.pem
- # Postfix ≥ 2.6:
- smtpd_tls_eecdh_grade = strong
-</pre>
-</blockquote>
+<p> If you want to take maximal advantage of ciphers that offer <a
+href="FORWARD_SECRECY_README.html#dfn_fs">forward secrecy</a> see
+the <a href="FORWARD_SECRECY_README.html#quick-start">Getting
+started</a> section of <a
+href="FORWARD_SECRECY_README.html">FORWARD_SECRECY_README</a>. The
+full document conveniently presents all information about Postfix
+"perfect" forward secrecy support in one place: what forward secrecy
+is, how to tweak settings, and what you can expect to see when
+Postfix uses ciphers with forward secrecy. </p>
<p> Postfix 2.8 and later, in combination with OpenSSL 0.9.7 and later
allows TLS servers to preempt the TLS client's cipher-suite preference list.
smtp_tls_exclude_ciphers = aNULL
# Preferred form with Postfix ≥ 2.5:
smtp_tls_mandatory_protocols = !SSLv2
- # Legacy form for Postifx < 2.5:
+ # Legacy form for Postfix < 2.5:
smtp_tls_mandatory_protocols = SSLv3, TLSv1
# Also available with Postfix ≥ 2.6:
smtp_tls_ciphers = export
# .br
# \fBpostmap -q - lmdb:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
# DESCRIPTION
-# LMDB is not supported in the stable Postfix release. It
-# will spontaneously terminate a Postfix daemon process without
-# allowing Postfix to 1) report the problem to the maillog
-# file, and to 2) provide reduced service where this is
-# appropriate.
-#
# The Postfix LMDB adapter provides access to a persistent,
# memory-mapped, key-value store. The database size is limited
-# only by the size of the memory address space and file system.
+# only by the size of the memory address space (typically 32
+# or 64 bits) and by the available file system space.
# REQUESTS
# .ad
# .fi
# main.cf. With long-running daemon programs, Use the command
# "\fBpostfix reload\fR" after a configuration change.
# .IP "\fBlmdb_map_size (default: 16777216)\fR"
-# The initial OpenLDAP LMDB database size limit in bytes.
+# The initial LMDB database size limit in bytes.
# SEE ALSO
# postconf(1), Postfix supported lookup tables
# postmap(1), Postfix lookup table maintenance
# .na
# .nf
# DATABASE_README, Postfix lookup table overview
-# LMDB_README, Postfix LMDB howto
+# LMDB_README, Postfix OpenLDAP LMDB howto
# LICENSE
# .ad
# .fi
%PARAM smtpd_tls_dh1024_param_file
<p> File with DH parameters that the Postfix SMTP server should
-use with EDH ciphers. </p>
+use with non-export EDH ciphers. </p>
<p> Instead of using the exact same parameter sets as distributed
with other TLS packages, it is more secure to generate your own
-set of parameters with something like the following command: </p>
+set of parameters with something like the following commands: </p>
<blockquote>
<pre>
-openssl gendh -out /etc/postfix/dh_1024.pem -2 1024
+openssl dhparam -out /etc/postfix/dh512.pem 512
+openssl dhparam -out /etc/postfix/dh1024.pem 1024
+openssl dhparam -out /etc/postfix/dh2048.pem 2048
</pre>
</blockquote>
-<p> Your actual source for entropy may differ. Some systems have
-/dev/random; on other system you may consider using the "Entropy
-Gathering Daemon EGD", available at http://egd.sourceforge.net/
-</p>
+<p> It is safe to share the same DH parameters between multiple
+Postfix instances. If you prefer, you can generate separate
+parameters for each instance. </p>
+
+<p> If you want to take maximal advantage of ciphers that offer <a
+href="FORWARD_SECRECY_README.html#dfn_fs">forward secrecy</a> see
+the <a href="FORWARD_SECRECY_README.html#quick-start">Getting
+started</a> section of <a
+href="FORWARD_SECRECY_README.html">FORWARD_SECRECY_README</a>. The
+full document conveniently presents all information about Postfix
+"perfect" forward secrecy support in one place: what forward secrecy
+is, how to tweak settings, and what you can expect to see when
+Postfix uses ciphers with forward secrecy. </p>
<p> Example: </p>
<pre>
-smtpd_tls_dh1024_param_file = /etc/postfix/dh_1024.pem
+smtpd_tls_dh1024_param_file = /etc/postfix/dh2048.pem
</pre>
<p>This feature is available with Postfix version 2.2.</p>
%PARAM smtpd_tls_dh512_param_file
<p> File with DH parameters that the Postfix SMTP server should
-use with EDH ciphers. </p>
+use with export-grade EDH ciphers. </p>
<p> See also the discussion under the smtpd_tls_dh1024_param_file
configuration parameter. </p>
%PARAM smtp_cname_overrides_servername version dependent
-<p> Allow DNS CNAME records to override the servername that the
-Postfix SMTP client uses for logging, SASL password lookup, TLS
+<p> When the remote SMTP servername is a DNS CNAME, replace the
+servername with the result from CNAME expansion for the purpose of
+logging, SASL password lookup, TLS
policy decisions, or TLS certificate verification. The value "no"
hardens Postfix smtp_tls_per_site hostname-based policies against
false hostname information in DNS CNAME records, and makes SASL
to the domain owner to configure their MX hosts and their DNS
sensibly. To configure the Postfix SMTP client for DNSSEC lookups
see the documentation for the smtp_dns_support_level main.cf
-parameter. When TLSA records are not found or are all unusable the
-effective security level is "may" or "encrypt" respectively. For
+parameter. When DNSSEC-validated TLSA records are not found the
+effective tls security level is "may". When TLSA records are found,
+but are all unusable the effective security level is "encrypt". For
purposes of protocol and cipher selection, the "dane" security level
is treated like a "mandatory" TLS security level, and weak ciphers
and protocols are disabled. Since DANE authenticates server
at this level, no need to configure this manually. RFC 6698 (DANE)
TLS authentication is available with Postfix 2.11 and later. </dd>
-
<dt><b><a href="TLS_README.html#client_tls_dane">dane-only</a></b></dt>
<dd>Mandatory DANE TLS. This is just like "dane" above, but DANE
TLSA authentication is required. There is no fallback to "may" or
attacks. The selected curve must be implemented by OpenSSL (as
reported by ecparam(1) with the "-list_curves" option) and be one
of the curves listed in Section 5.1.1 of RFC 4492. You should not
-generally change this setting. </p>
+generally change this setting. Remote SMTP client implementations
+must support this curve for EECDH key exchange to take place. It
+is unwise to choose an "exotic" curve supported by only a small subset
+of clients. </p>
-<p> This default curve is specified in NSA "Suite B" Cryptography
-(see http://www.nsa.gov/ia/industry/crypto_suite_b.cfm) for
-information classified as SECRET. </p>
+<p> The default "strong" curve is rated in NSA <a
+href="http://www.nsa.gov/ia/programs/suiteb_cryptography/">Suite
+B</a> for information classified up to SECRET. </p>
<p> Note: elliptic curve names are poorly standardized; different
standards groups are assigning different names to the same underlying
under the SECG name "secp256r1", but OpenSSL does not recognize the
latter name. </p>
+<p> If you want to take maximal advantage of ciphers that offer <a
+href="FORWARD_SECRECY_README.html#dfn_fs">forward secrecy</a> see
+the <a href="FORWARD_SECRECY_README.html#quick-start">Getting
+started</a> section of <a
+href="FORWARD_SECRECY_README.html">FORWARD_SECRECY_README</a>. The
+full document conveniently presents all information about Postfix
+"perfect" forward secrecy support in one place: what forward secrecy
+is, how to tweak settings, and what you can expect to see when
+Postfix uses ciphers with forward secrecy. </p>
+
<p> This feature is available in Postfix 2.6 and later, when it is
-compiled and linked with OpenSSL 1.0.0 or later. </p>
+compiled and linked with OpenSSL 1.0.0 or later on platforms where
+EC algorithms have not been disabled by the vendor. </p>
%PARAM tls_eecdh_ultra_curve secp384r1
"-list_curves" option) and be one of the curves listed in Section 5.1.1
of RFC 4492. You should not generally change this setting. </p>
-<p> This default "ultra" curve is specified in NSA "Suite B" Cryptography
-(see http://www.nsa.gov/ia/industry/crypto_suite_b.cfm) for information
-classified as TOP SECRET. </p>
+<p> This default "ultra" curve is rated in NSA <a
+href="http://www.nsa.gov/ia/programs/suiteb_cryptography/">Suite
+B</a> for information classified up to TOP SECRET. </p>
+
+<p> If you want to take maximal advantage of ciphers that offer <a
+href="FORWARD_SECRECY_README.html#dfn_fs">forward secrecy</a> see
+the <a href="FORWARD_SECRECY_README.html#quick-start">Getting
+started</a> section of <a
+href="FORWARD_SECRECY_README.html">FORWARD_SECRECY_README</a>. The
+full document conveniently presents all information about Postfix
+"perfect" forward secrecy support in one place: what forward secrecy
+is, how to tweak settings, and what you can expect to see when
+Postfix uses ciphers with forward secrecy. </p>
<p> This feature is available in Postfix 2.6 and later, when it is
-compiled and linked with OpenSSL 1.0.0 or later. </p>
+compiled and linked with OpenSSL 1.0.0 or later on platforms where
+EC algorithms have not been disabled by the vendor. </p>
%PARAM smtpd_tls_eecdh_grade see "postconf -d" output
</dl>
+<p> If you want to take maximal advantage of ciphers that offer <a
+href="FORWARD_SECRECY_README.html#dfn_fs">forward secrecy</a> see
+the <a href="FORWARD_SECRECY_README.html#quick-start">Getting
+started</a> section of <a
+href="FORWARD_SECRECY_README.html">FORWARD_SECRECY_README</a>. The
+full document conveniently presents all information about Postfix
+"perfect" forward secrecy support in one place: what forward secrecy
+is, how to tweak settings, and what you can expect to see when
+Postfix uses ciphers with forward secrecy. </p>
+
<p> This feature is available in Postfix 2.6 and later, when it is
-compiled and linked with OpenSSL 1.0.0 or later. </p>
+compiled and linked with OpenSSL 1.0.0 or later on platforms
+where EC algorithms have not been disabled by the vendor. </p>
%PARAM smtpd_tls_eccert_file
%PARAM tlsproxy_tls_dh1024_param_file $smtpd_tls_dh1024_param_file
<p> File with DH parameters that the Postfix tlsproxy(8) server
-should use with EDH ciphers. See smtpd_tls_dh1024_param_file for
-further details. </p>
+should use with non-export EDH ciphers. See smtpd_tls_dh1024_param_file
+for further details. </p>
<p> This feature is available in Postfix 2.8 and later. </p>
%PARAM tlsproxy_tls_dh512_param_file $smtpd_tls_dh512_param_file
<p> File with DH parameters that the Postfix tlsproxy(8) server
-should use with EDH ciphers. See smtpd_tls_dh512_param_file for
-further details. </p>
+should use with export-grade EDH ciphers. See smtpd_tls_dh512_param_file
+for further details. </p>
<p> This feature is available in Postfix 2.8 and later. </p>
ZZZ
kEECDH
EXIM
+DLV
+IANA
+RRs
+RRset
+RRsets
+SNI
+tlsa
+TSIG
+ciphersuite
+ciphersuites
+nlnetlabs
+resolver's
+tempfails
unsigned char *buf; /* raw reply data */
size_t buf_len; /* reply buffer length */
int rcode; /* unfiltered reply code */
- int dnssec_valid; /* DNSSEC AD bit */
+ int dnssec_ad; /* DNSSEC AD bit */
int query_count; /* number of queries */
int answer_count; /* number of answers */
unsigned char *query_start; /* start of query data */
/*
* Initialize the reply structure. Some structure members are filled on
- * the fly while the reply is being parsed.
+ * the fly while the reply is being parsed. Coerce AD bit to boolean.
*/
#if RES_USE_DNSSEC != 0
- reply->dnssec_valid = (flags & RES_USE_DNSSEC) ? reply_header->ad : 0;
+ reply->dnssec_ad = (flags & RES_USE_DNSSEC) ? !!reply_header->ad : 0;
#else
- reply->dnssec_valid = 0;
+ reply->dnssec_ad = 0;
#endif
reply->end = reply->buf + len;
reply->query_start = reply->buf + sizeof(HEADER);
static int dns_get_answer(const char *orig_name, DNS_REPLY *reply, int type,
DNS_RR **rrlist, VSTRING *fqdn, char *cname, int c_len,
- int *validate_mask)
+ int *maybe_secure)
{
char rr_name[DNS_NAME_LEN];
unsigned char *pos;
if ((status = dns_get_rr(&rr, orig_name, reply, pos, rr_name,
&fixed)) == DNS_OK) {
resource_found++;
- rr->dnssec_valid = (reply->dnssec_valid & *validate_mask);
+ rr->dnssec_valid = *maybe_secure ? reply->dnssec_ad : 0;
*rrlist = dns_rr_append(*rrlist, rr);
} else if (not_found_status != DNS_RETRY)
not_found_status = status;
if (cname && c_len > 0)
if ((status = dns_get_alias(reply, pos, &fixed, cname, c_len)) != DNS_OK)
CORRUPT(status);
- *validate_mask &= reply->dnssec_valid;
+ if (!reply->dnssec_ad)
+ *maybe_secure = 0;
}
pos += fixed.length;
}
static DNS_REPLY reply;
int count;
int status;
- int validate_mask = 1; /* May reset to 0 via CNAME expansion */
+ int maybe_secure = 1; /* Query name presumed secure */
const char *orig_name = name;
/*
/*
* Extract resource records of the requested type. Pick up CNAME
- * information just in case the requested data is not found. If any
- * CNAME result is not validated, all consequent RRs are deemed not
- * validated (the validate_mask is set to 0).
+ * information just in case the requested data is not found.
*/
status = dns_get_answer(orig_name, &reply, type, rrlist, fqdn,
- cname, c_len, &validate_mask);
+ cname, c_len, &maybe_secure);
switch (status) {
default:
if (why)
case DNS_RECURSE:
if (msg_verbose)
msg_info("dns_lookup: %s aliased to %s", name, cname);
+#if RES_USE_DNSSEC
+
+ /*
+ * Once an intermediate CNAME reply is not validated, all
+ * consequent RRs are deemed not validated, so we don't ask for
+ * further DNSSEC replies.
+ */
+ if (maybe_secure == 0)
+ flags &= ~RES_USE_DNSSEC;
+#endif
name = cname;
}
}
/*
/* Arguments:
/* .IP hostname
-/* The resource record host name.
+/* The resource record host name. This will be both the qname
+/* and the rname in the synthetic DNS resource record.
/* .IP pref
/* The resource record MX host preference, if applicable.
/* .IP sa
size_t i;
while (rr) {
- printf("%s: ad: %d, ttl: %9d ", rr->rname, rr->dnssec_valid, rr->ttl);
+ printf("%s: ad: %u, ttl: %9u ", rr->rname, rr->dnssec_valid, rr->ttl);
switch (rr->type) {
case T_A:
#ifdef T_AAAA
return (dsb);
}
-/* dsb_simple - update status and informal text */
+/* vdsb_simple - update status and informal text, va_list form */
-DSN_BUF *dsb_simple(DSN_BUF *dsb, const char *status, const char *format,...)
+DSN_BUF *vdsb_simple(DSN_BUF *dsb, const char *status, const char *format,
+ va_list ap)
{
- va_list ap;
-
vstring_strcpy(dsb->status, status);
DSB_TRUNCATE(dsb->action);
DSB_TRUNCATE(dsb->mtype);
DSB_TRUNCATE(dsb->mname);
DSB_TRUNCATE(dsb->dtype);
DSB_TRUNCATE(dsb->dtext);
- va_start(ap, format);
vstring_vsprintf(dsb->reason, format, ap);
- va_end(ap);
return (dsb);
}
+/* dsb_simple - update status and informal text */
+
+DSN_BUF *dsb_simple(DSN_BUF *dsb, const char *status, const char *format,...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ (void) vdsb_simple(dsb, status, format, ap);
+ va_end(ap);
+ return (dsb);
+}
+
/* dsb_unix - update status, UNIX diagnostic and informal text */
DSN_BUF *dsb_unix(DSN_BUF *dsb, const char *status,
extern DSN_BUF *dsb_create(void);
extern DSN_BUF *PRINTFLIKE(8, 9) dsb_update(DSN_BUF *, const char *, const char *, const char *, const char *, const char *, const char *, const char *,...);
+extern DSN_BUF *vdsb_simple(DSN_BUF *, const char *, const char *, va_list);
extern DSN_BUF *PRINTFLIKE(3, 4) dsb_simple(DSN_BUF *, const char *, const char *,...);
extern DSN_BUF *PRINTFLIKE(4, 5) dsb_unix(DSN_BUF *, const char *, const char *, const char *,...);
extern DSN_BUF *dsb_formal(DSN_BUF *, const char *, const char *, const char *, const char *, const char *, const char *);
#ifdef HAS_DB
#include <dict_db.h>
#endif
-#if defined(SNAPSHOT) && defined(HAS_LMDB)
+#ifdef HAS_LMDB
#include <dict_lmdb.h>
#endif
#include <inet_proto.h>
#ifdef HAS_DB
dict_db_cache_size = var_db_read_buf;
#endif
-#if defined(SNAPSHOT) && defined(HAS_LMDB)
+#ifdef HAS_LMDB
dict_lmdb_map_size = var_lmdb_map_size;
#endif
inet_windowsize = var_inet_windowsize;
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20140105"
+#define MAIL_RELEASE_DATE "20140109"
#define MAIL_VERSION_NUMBER "2.12"
#ifdef SNAPSHOT
#include <myflock.h>
#include <warn_stat.h>
-#if defined(SNAPSHOT) && defined(HAS_LMDB)
+#ifdef HAS_LMDB
#ifdef PATH_LMDB_H
#include PATH_LMDB_H
#else
DICT_TYPE_HASH, mkmap_hash_open,
DICT_TYPE_BTREE, mkmap_btree_open,
#endif
-#if defined(SNAPSHOT) && defined(HAS_LMDB)
+#ifdef HAS_LMDB
DICT_TYPE_LMDB, mkmap_lmdb_open,
#endif
DICT_TYPE_FAIL, mkmap_fail_open,
fprintf(stderr,
"usage: %s [-dv] \n"
"\t[-a action] non-default action\n"
- "\t[-b body_text] replace body\n",
+ "\t[-b body_text] replace body\n"
"\t[-c command] non-default action trigger\n"
"\t[-h 'index label value'] replace header\n"
"\t[-i 'index label value'] insert header\n"
#include <mail_params.h>
#include <maps.h>
+#include <dsn_buf.h>
/* DNS library. */
SMTP_ITERATOR *iter)
{
VSTRING *key;
- int valid = iter->rr && iter->rr->dnssec_valid;
- int mxvalid = iter->mx == 0 || iter->mx->dnssec_valid;
/*
* Create an empty TLS Policy cache on the fly.
smtp_key_prefix(key, ":", iter, SMTP_KEY_FLAG_NEXTHOP
| SMTP_KEY_FLAG_HOSTNAME
| SMTP_KEY_FLAG_PORT);
- vstring_sprintf_append(key, "%d:%d", !!valid, !!mxvalid);
ctable_newcontext(policy_cache, (void *) iter);
*tls = *(SMTP_TLS_POLICY *) ctable_locate(policy_cache, STR(key));
vstring_free(key);
return l;
}
+#define NONDANE_CONFIG 0 /* Administrator's fault */
+#define NONDANE_DEST 1 /* Remote server's fault */
+
+static void PRINTFLIKE(4, 5) dane_incompat(SMTP_TLS_POLICY *tls,
+ SMTP_ITERATOR *iter,
+ int errtype,
+ const char *fmt,...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ if (tls->level == TLS_LEV_DANE) {
+ tls->level = TLS_LEV_MAY;
+ if (errtype == NONDANE_CONFIG)
+ vmsg_warn(fmt, ap);
+ else if (msg_verbose)
+ vmsg_info(fmt, ap);
+ } else {
+ if (errtype == NONDANE_CONFIG) {
+ vmsg_warn(fmt, ap);
+ MARK_INVALID(tls->why, &tls->level);
+ } else {
+ tls->level = TLS_LEV_INVALID;
+ vdsb_simple(tls->why, "4.7.5", fmt, ap);
+ }
+ }
+ va_end(ap);
+}
+
/* dane_init - special initialization for "dane" security level */
static void dane_init(SMTP_TLS_POLICY *tls, SMTP_ITERATOR *iter)
MARK_INVALID(tls->why, &tls->level);
return;
}
-
- /*
- * To use DANE security the requisite features must be provided by the
- * OpenSSL (runtime) and DNS resolver (compile-time) libraries. Also,
- * "smtp_host_lookup = dns" and "smtp_dns_support_level = dnssec" are
- * required.
- */
-#define DANEMSG(msg_func, reason, iter, tls) \
- msg_func("%s: %s, the security level for delivery via %s:%u will " \
- "degrade to \"%s\"", STR((iter)->dest), reason, \
- STR((iter)->host), ntohs((iter)->port), \
- policy_name((tls)->level))
-#define DANEWARN(reason, iter, tls) DANEMSG(msg_warn, (reason), (iter), (tls))
-
if (!tls_dane_avail()) {
- if (tls->level == TLS_LEV_DANE) {
- tls->level = TLS_LEV_MAY;
- DANEWARN("DANE not available", iter, tls);
- } else {
- msg_warn("%s: \"%s\" requested without requisite library support",
- STR(iter->dest), policy_name(tls->level));
- MARK_INVALID(tls->why, &tls->level);
- }
+ dane_incompat(tls, iter, NONDANE_CONFIG,
+ "%s: %s configured, but no requisite library support",
+ STR(iter->dest), policy_name(tls->level));
return;
}
if (!(smtp_host_lookup_mask & SMTP_HOST_FLAG_DNS)
|| smtp_dns_support != SMTP_DNS_DNSSEC) {
- if (tls->level == TLS_LEV_DANE) {
- tls->level = TLS_LEV_MAY;
- DANEWARN("DNSSEC hostname lookups not enabled", iter, tls);
- } else {
- msg_warn("%s: \"%s\" requested with dnssec lookups disabled",
- STR(iter->dest), policy_name(tls->level));
- MARK_INVALID(tls->why, &tls->level);
- }
+ dane_incompat(tls, iter, NONDANE_CONFIG,
+ "%s: %s configured with dnssec lookups disabled",
+ STR(iter->dest), policy_name(tls->level));
return;
}
/*
- * If there were no MX records and the destination host is the original
- * 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.
+ * If we ignore MX lookup errors, we also ignore DNSSEC security problems
+ * and thus avoid any reasonable expectation that we get the right DANE
+ * key material.
*/
+ if (smtp_mode && var_ign_mx_lookup_err) {
+ dane_incompat(tls, iter, NONDANE_CONFIG,
+ "%s: %s configured with MX lookup errors ignored",
+ STR(iter->dest), policy_name(tls->level));
+ return;
+ }
+
+ /*
+ * This is not optional, code in tls_dane.c assumes that the nexthop
+ * qname is already an fqdn. If we're using these flags to go from qname
+ * to rname, the assumption is invalid. Likewise we cannot add the qname
+ * to certificate name checks, ...
+ */
+ if (smtp_dns_res_opt & (RES_DEFNAMES | RES_DNSRCH)) {
+ dane_incompat(tls, iter, NONDANE_CONFIG,
+ "%s: dns resolver options incompatible with %s TLS",
+ STR(iter->dest), policy_name(tls->level));
+ return;
+ }
+ /* When the MX name is present and insecure, DANE does not apply. */
if (iter->mx && !iter->mx->dnssec_valid) {
- if (tls->level == TLS_LEV_DANE) {
- tls->level = TLS_LEV_MAY;
- if (msg_verbose)
- DANEMSG(msg_info, "non DNSSEC destination", iter, tls);
- } else {
- tls->level = TLS_LEV_INVALID;
- dsb_simple(tls->why, "4.7.5", "non DNSSEC destination");
- }
+ dane_incompat(tls, iter, NONDANE_DEST, "non DNSSEC destination");
return;
}
/* When TLSA lookups fail, we defer the message */
return;
}
if (tls_dane_notfound(dane)) {
- if (tls->level == TLS_LEV_DANE) {
- tls->level = TLS_LEV_MAY;
- if (msg_verbose)
- DANEMSG(msg_info, "no TLSA records found", iter, tls);
- } else {
- tls->level = TLS_LEV_INVALID;
- dsb_simple(tls->why, "4.7.5", "no TLSA records found");
- }
+ dane_incompat(tls, iter, NONDANE_DEST, "no TLSA records found");
tls_dane_free(dane);
return;
}
* given verifier some of the CAs are surely not trustworthy).
*/
if (tls_dane_unusable(dane)) {
- if (tls->level == TLS_LEV_DANE) {
- tls->level = TLS_LEV_ENCRYPT;
- if (msg_verbose)
- DANEWARN("TLSA records unusable", iter, tls);
- } else {
- tls->level = TLS_LEV_INVALID;
- dsb_simple(tls->why, "4.7.5", "TLSA records unusable");
- }
- tls_dane_free(dane);
+ dane_incompat(tls, iter, NONDANE_DEST, "TLSA records unusable");
return;
}
/* File with the Postfix SMTP server DSA certificate in PEM format.
/* .IP "\fBsmtpd_tls_dh1024_param_file (empty)\fR"
/* File with DH parameters that the Postfix SMTP server should
-/* use with EDH ciphers.
+/* use with non-export EDH ciphers.
/* .IP "\fBsmtpd_tls_dh512_param_file (empty)\fR"
/* File with DH parameters that the Postfix SMTP server should
-/* use with EDH ciphers.
+/* use with export-grade EDH ciphers.
/* .IP "\fBsmtpd_tls_dkey_file ($smtpd_tls_dcert_file)\fR"
/* File with the Postfix SMTP server DSA private key in PEM format.
/* .IP "\fBsmtpd_tls_key_file ($smtpd_tls_cert_file)\fR"
/* .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.
+/* DNS_RR pointer to TLSA base domain data.
/* .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
return (dane);
}
+/* qname_secure - Lookup qname DNSSEC status */
+
+static int qname_secure(const char *qname)
+{
+ static VSTRING *why;
+ int ret = 0;
+ DNS_RR *rrs;
+
+ if (!why)
+ why = vstring_alloc(10);
+
+ /*
+ * We assume that qname is already an fqdn, and does not need any
+ * suffixes from RES_DEFNAME or RES_DNSRCH. This is typically the name
+ * of an MX host, and must be a complete DNS name. DANE initialization
+ * code in the SMTP client is responsible for checking that the default
+ * resolver flags do not include RES_DEFNAME and RES_DNSRCH.
+ */
+ ret = dns_lookup(qname, T_CNAME, RES_USE_DNSSEC, &rrs, 0, why);
+ if (ret == DNS_OK) {
+ ret = rrs->dnssec_valid;
+ dns_rr_free(rrs);
+ return (ret);
+ }
+ if (ret == DNS_NOTFOUND)
+ vstring_sprintf(why, "no longer a CNAME");
+ msg_warn("DNSSEC status lookup error for %s: %s", qname, STR(why));
+ return (-1);
+}
+
/* tls_dane_resolve - cached map: (name, proto, port) -> TLS_DANE */
TLS_DANE *tls_dane_resolve(unsigned port, const char *proto, DNS_RR *hostrr,
int forcetlsa)
{
TLS_DANE *dane = 0;
- int iscname;
+ int iscname = strcasecmp(hostrr->rname, hostrr->qname);
+ int isvalid = 1;
if (!tls_dane_avail())
- return (dane);
-
- if (!dane_cache)
- dane_cache = ctable_create(CACHE_SIZE, dane_lookup, dane_free, 0);
+ return (0); /* Error */
/*
- * 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.
+ * By default suppress TLSA lookups for hosts in non-DNSSEC zones. If
+ * the host zone is not DNSSEC validated, the TLSA qname sub-domain is
+ * safely assumed to not be in a DNSSEC Look-aside Validation child zone.
*/
- iscname = strcasecmp(hostrr->rname, hostrr->qname);
- if (!forcetlsa && !hostrr->dnssec_valid && !iscname) {
+ if (!forcetlsa && !hostrr->dnssec_valid) {
+ isvalid = iscname ? qname_secure(hostrr->qname) : 0;
+ if (isvalid < 0)
+ return (0); /* Error */
+ }
+ if (!isvalid) {
dane = tls_dane_alloc();
dane->flags = TLS_DANE_FLAG_NORRS;
} else {
+ if (!dane_cache)
+ 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.
+ * Try the rname first if secure, if nothing there, try the qname if
+ * different. 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)
+ if (hostrr->dnssec_valid) {
dane = resolve_host(hostrr->rname, proto, port);
- if (!dane || (iscname && tls_dane_notfound(dane)))
+ if (tls_dane_notfound(dane) && iscname) {
+ tls_dane_free(dane);
+ dane = 0;
+ }
+ }
+ if (!dane)
dane = resolve_host(hostrr->qname, proto, port);
if (dane->flags & TLS_DANE_FLAG_ERROR) {
/* We don't return this object. */
/* format.
/* .IP "\fBtlsproxy_tls_dh1024_param_file ($smtpd_tls_dh1024_param_file)\fR"
/* File with DH parameters that the Postfix \fBtlsproxy\fR(8) server
-/* should use with EDH ciphers.
+/* should use with non-export EDH ciphers.
/* .IP "\fBtlsproxy_tls_dh512_param_file ($smtpd_tls_dh512_param_file)\fR"
/* File with DH parameters that the Postfix \fBtlsproxy\fR(8) server
-/* should use with EDH ciphers.
+/* should use with export-grade EDH ciphers.
/* .IP "\fBtlsproxy_tls_dkey_file ($smtpd_tls_dkey_file)\fR"
/* File with the Postfix \fBtlsproxy\fR(8) server DSA private key in PEM
/* format.
int show_elapsed = 1; /* show elapsed time */
-#if defined(SNAPSHOT) && defined(HAS_LMDB)
+#ifdef HAS_LMDB
extern size_t dict_lmdb_map_size; /* LMDB-specific */
#endif
{
DICT_CACHE_SREQ *cp;
-#if defined(SNAPSHOT) && defined(HAS_LMDB)
+#ifdef HAS_LMDB
vstream_printf("lmdb_map_size\t%ld\n", (long) dict_lmdb_map_size);
#endif
vstream_printf("cache\t%s\n", dp ? dp->name : "(none)");
msg_verbose = atoi(args->argv[1]);
} else if (strcmp(args->argv[0], "elapsed") == 0 && args->argc == 2) {
show_elapsed = atoi(args->argv[1]);
-#if defined(SNAPSHOT) && defined(HAS_LMDB)
+#ifdef HAS_LMDB
} else if (strcmp(args->argv[0], "lmdb_map_size") == 0 && args->argc == 2) {
dict_lmdb_map_size = atol(args->argv[1]);
#endif
#include <sys_defs.h>
-#if defined(SNAPSHOT) && defined(HAS_LMDB)
+#ifdef HAS_LMDB
/* System library. */
va_end(ap);
}
+/* dict_lmdb_assert - report LMDB internal assertion failure */
+
+static void dict_lmdb_assert(void *context, const char *text)
+{
+ DICT_LMDB *dict_lmdb = (DICT_LMDB *) context;
+
+ msg_fatal("%s:%s: internal error: %s",
+ dict_lmdb->dict.type, dict_lmdb->dict.name, text);
+}
+
/* dict_lmdb_open - open LMDB data base */
DICT *dict_lmdb_open(const char *path, int open_flags, int dict_flags)
DICT_LMDB_SIZE_MAX)) != 0
|| (status = slmdb_open(&slmdb, mdb_path, open_flags, mdb_flags,
slmdb_flags)) != 0) {
+ /* This leaks a little memory that would have been used otherwise. */
dict = dict_surrogate(DICT_TYPE_LMDB, path, open_flags, dict_flags,
"open database %s: %s", mdb_path, mdb_strerror(status));
DICT_LMDB_OPEN_RETURN(dict);
}
/*
- * Bundle up.
+ * Bundle up. From here on no more assignments to slmdb.
*/
dict_lmdb = (DICT_LMDB *) dict_alloc(DICT_TYPE_LMDB, path, sizeof(*dict_lmdb));
+ dict_lmdb->slmdb = slmdb;
dict_lmdb->dict.lookup = dict_lmdb_lookup;
dict_lmdb->dict.update = dict_lmdb_update;
dict_lmdb->dict.delete = dict_lmdb_delete;
* The following requests return an error result only if we have serious
* memory corruption problem.
*/
- slmdb_control(&slmdb,
- SLMDB_CTL_API_RETRY_LIMIT, DICT_LMDB_API_RETRY_LIMIT,
- SLMDB_CTL_BULK_RETRY_LIMIT, DICT_LMDB_BULK_RETRY_LIMIT,
- SLMDB_CTL_LONGJMP_FN, dict_lmdb_longjmp,
- SLMDB_CTL_CONTEXT, (void *) dict_lmdb,
- SLMDB_CTL_END);
- if (msg_verbose) {
- slmdb_control(&slmdb,
- SLMDB_CTL_NOTIFY_FN, dict_lmdb_notify,
- SLMDB_CTL_END);
+ if (slmdb_control(&dict_lmdb->slmdb,
+ SLMDB_CTL_API_RETRY_LIMIT, DICT_LMDB_API_RETRY_LIMIT,
+ SLMDB_CTL_BULK_RETRY_LIMIT, DICT_LMDB_BULK_RETRY_LIMIT,
+ SLMDB_CTL_LONGJMP_FN, dict_lmdb_longjmp,
+ SLMDB_CTL_NOTIFY_FN, msg_verbose ?
+ dict_lmdb_notify : (SLMDB_NOTIFY_FN) 0,
+ SLMDB_CTL_ASSERT_FN, dict_lmdb_assert,
+ SLMDB_CTL_CB_CONTEXT, (void *) dict_lmdb,
+ SLMDB_CTL_END) != 0)
+ msg_panic("dict_lmdb_open: slmdb_control: %m");
+
+ if (msg_verbose)
dict_lmdb_notify((void *) dict_lmdb, MDB_SUCCESS,
- slmdb_curr_limit(&slmdb));
- }
-
- /*
- * From here on no direct assignments to slmdb.
- */
- dict_lmdb->slmdb = slmdb;
+ slmdb_curr_limit(&dict_lmdb->slmdb));
DICT_LMDB_OPEN_RETURN(DICT_DEBUG (&dict_lmdb->dict));
}
DICT_TYPE_HASH, dict_hash_open,
DICT_TYPE_BTREE, dict_btree_open,
#endif
-#if defined(SNAPSHOT) && defined(HAS_LMDB)
+#ifdef HAS_LMDB
DICT_TYPE_LMDB, dict_lmdb_open,
#endif
#ifdef HAS_NIS
+++ /dev/null
-#!/bin/sh
-
-set -e
-
-rm -f foo.lmdb
-
-./dict_cache <<EOF
-cache lmdb:foo
-update x ${1-2000}
-run
-update y ${1-2000}
-purge x
-run
-purge y
-run
-EOF
-
-../../bin/postmap -s lmdb:foo | diff /dev/null -
-rm -f foo.lmdb
--- /dev/null
+#!/bin/sh
+
+# Torture test: run update and purge operations in parallel processes.
+# This will result in some purge operations not finding all entries,
+# but the final sequential purge should eliminate all.
+
+set -e
+
+rm -f foo.lmdb
+./dict_cache <<EOF
+lmdb_map_size 20000
+cache lmdb:foo
+EOF
+
+(./dict_cache <<EOF
+cache lmdb:foo
+update x ${1-10000}
+run
+update y ${1-10000}
+purge x
+run
+purge y
+run
+EOF
+) &
+
+(./dict_cache <<EOF
+cache lmdb:foo
+update a ${1-10000}
+run
+update b ${1-10000}
+purge a
+run
+purge b
+run
+EOF
+) &
+
+wait
+
+./dict_cache <<EOF
+cache lmdb:foo
+purge a
+run
+purge b
+run
+purge x
+run
+purge y
+run
+EOF
+
+../../bin/postmap -s lmdb:foo | diff /dev/null -
+
+rm -f foo.lmdb
--- /dev/null
+#!/bin/sh
+
+# Torture test: run update and delete ${1-10000}perations in
+# parallel processes. None should remain.
+
+set -e
+
+rm -f foo.lmdb
+./dict_cache <<EOF
+lmdb_map_size 20000
+cache lmdb:foo
+EOF
+
+(./dict_cache <<EOF
+cache lmdb:foo
+update x ${1-10000}
+run
+update y ${1-10000}
+delete x ${1-10000}
+run
+delete y ${1-10000}
+run
+EOF
+) &
+
+(./dict_cache <<EOF
+cache lmdb:foo
+update a ${1-10000}
+run
+update b ${1-10000}
+delete a ${1-10000}
+run
+delete b ${1-10000}
+run
+EOF
+) &
+
+wait
+
+../../bin/postmap -s lmdb:foo | diff /dev/null -
+
+rm -f foo.lmdb
if (*cp != '\0' || errno == ERANGE)
return (0);
- if (ulp)
- *ulp = (result & mask);
+ *ulp = (result & mask);
return (*ulp == result);
}
/* for the specified database.
/*
/* slmdb_control() specifies optional features. The result is
-/* 0 in case of success, or -1 with errno indicating the nature
-/* of the problem.
+/* an LMDB status code (zero in case of success).
/*
/* Arguments:
/* .IP slmdb
/* Flags that control file open operations. Do not specify
/* locking flags here.
/* .IP lmdb_flags
-/* Flags that control the LMDB environment.
+/* Flags that control the LMDB environment. If MDB_NOLOCK is
+/* specified, then each slmdb_get() or slmdb_cursor_get() call
+/* must be protected with a shared (or stronger) external lock,
+/* and each slmdb_put() or slmdb_del() call must be protected
+/* with an exclusive external lock. The locks may be released
+/* after the call returns.
/* .IP slmdb_flags
/* Bit-wise OR of zero or more of the following:
/* .RS
/* .IP SLMDB_FLAG_BULK
-/* Open the database for a "bulk" transaction that is not
-/* committed until the database is closed.
+/* Open the database and create a "bulk" transaction that is
+/* committed when the database is closed. If MDB_NOLOCK is
+/* specified, then the entire transaction must be protected
+/* with a persistent exclusive external lock (the lock may be
+/* atomically downgraded to a shared lock to permit concurrent
+/* read-only access). All slmdb_get(), slmdb_put() and slmdb_del()
+/* requests will be directed to the "bulk" transaction. The effect
+/* of calling slmdb_cursor_get() is undefined.
/* .RE
/* .IP mdb_key
/* Pointer to caller-provided lookup key storage.
/* request names and the corresponding value types.
/* .RS
/* .IP "SLMDB_CTL_LONGJMP_FN (void (*)(void *, int))
-/* Application long-jump call-back function pointer. The
-/* function must not return and is called to repeat a failed
-/* bulk-mode transaction from the start. The arguments are the
-/* application context and the setjmp() or sigsetjmp() result
-/* value.
+/* Call-back function pointer. The function is called to repeat
+/* a failed bulk-mode transaction from the start. The arguments
+/* are the application context and the setjmp() or sigsetjmp()
+/* result value.
/* .IP "SLMDB_CTL_NOTIFY_FN (void (*)(void *, int, ...))"
-/* Application notification call-back function pointer. The
-/* function is called after succesful error recovery with
-/* arguments the application context, the MDB error code, and
-/* additional arguments that depend on the error code. Details
-/* are given in the section "ERROR RECOVERY".
-/* .IP "SLMDB_CTL_CONTEXT (void *)"
-/* Application context that is passed in application notification
-/* and long-jump call-back function calls.
+/* Call-back function pointer. The function is called to report
+/* succesful error recovery. The arguments are the application
+/* context, the MDB error code, and additional arguments that
+/* depend on the error code. Details are given in the section
+/* "ERROR RECOVERY".
+/* .IP "SLMDB_CTL_ASSERT_FN (void (*)(void *, const char *))"
+/* Call-back function pointer. The function is called to
+/* report an LMDB internal assertion failure. The arguments
+/* are the application context, and text that describes the
+/* problem.
+/* .IP "SLMDB_CTL_CB_CONTEXT (void *)"
+/* Application context that is passed in call-back function
+/* calls.
/* .IP "SLMDB_CTL_API_RETRY_LIMIT (int)"
/* How many times to recover from LMDB errors within the
/* execution of a single slmdb(3) API call before giving up.
/* memory mapping. According to LMDB documentation this
/* requires that there is no concurrent activity in the same
/* database by other threads in the same memory address space.
+/*
+/* When a database is opened with MDB_NOLOCK, and the external
+/* lock is based on fcntl() or the like, there is no protection
+/* against concurrent activity in the same process.
/* SEE ALSO
/* lmdb(3) API manpage (currently, non-existent).
-/* LICENSE
-/* .ad
-/* .fi
-/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Howard Chu
/* Symas Corporation
/* Yorktown Heights, NY 10598, USA
/*--*/
-#if defined(SNAPSHOT) && defined(HAS_LMDB)
+ /*
+ * DO NOT include other Postfix-specific header files. This LMDB wrapper
+ * must be usable outside Postfix.
+ */
+
+#ifdef HAS_LMDB
/* System library. */
#include <slmdb.h>
/*
- * Supported LMDB versions.
+ * Minimum LMDB patchlevel.
+ *
+ * LMDB 0.9.11 allows Postfix daemons to log an LMDB error message instead of
+ * falling out of the sky without any explanation. Without such logging,
+ * Postfix with LMDB would be too hard to support.
+ *
+ * LMDB 0.9.10 fixes an information leak where LMDB wrote chunks of up to 4096
+ * bytes of uninitialized heap memory to a database. This was a security
+ * violation because it made information persistent that was not meant to be
+ * persisted, or it was sharing information that was not meant to be shared.
*
* LMDB 0.9.8 allows the application to update the database size limit
- * on-the-fly, so that it can recover from an MDB_MAP_FULL error; it also
- * allows an application to "pick up" a new database size limit on-the-fly,
- * so that it can recover from an MDB_MAP_RESIZED error. The database size
- * limit that remains is imposed by the hardware address space. The
- * implementation is supposed to handle databases larger than physical
- * memory. However, this is not necessarily guaranteed for (bulk)
+ * on-the-fly, so that it can recover from an MDB_MAP_FULL error without
+ * having to close the database. It also allows an application to "pick up"
+ * a new database size limit on-the-fly, so that it can recover from an
+ * MDB_MAP_RESIZED error without having to close the database. Finally, it
+ * avoids the need for world-writable lockfiles, by using MDB_NOLOCK.
+ *
+ * The database size limit that remains is imposed by the hardware address
+ * space. The implementation is supposed to handle databases larger than
+ * physical memory. However, this is not necessarily guaranteed for (bulk)
* transactions larger than physical memory.
*/
-#if MDB_VERSION_FULL < MDB_VERINT(0, 9, 8)
-#error "Build with LMDB version 0.9.8 or later"
+#if MDB_VERSION_FULL < MDB_VERINT(0, 9, 11)
+#error "This Postfix version requires LMDB version 0.9.11 or later"
#endif
/*
* call for non-bulk transactions. We allow a number of bulk-transaction
* retries that is proportional to the memory address space.
*/
-#define SLMDB_DEF_API_RETRY_LIMIT 2 /* Retries per slmdb(3) API call */
+#define SLMDB_DEF_API_RETRY_LIMIT 30 /* Retries per slmdb(3) API call */
#define SLMDB_DEF_BULK_RETRY_LIMIT \
(2 * sizeof(size_t) * CHAR_BIT) /* Retries per bulk-mode transaction */
} while (0)
/*
- * We must close the cursor's read transaction before writing to the
- * database with MDB_NOLOCK, and before changing the memory map size. Our
- * database iterator saves the key under the last cursor position, and
- * restores the cursor if needed. This supports only one cursor per
- * database.
+ * With MDB_NOLOCK, the iterator must close the cursor's read transaction
+ * before returning the (key, value) to the caller. See ITS#7774 and
+ * followups.
*/
/* slmdb_cursor_close - close cursor and its read transaction */
MDB_envinfo info;
/*
- * Close the cursor and its read transaction before changing the memory
- * map size. We can restore it later from the saved key information.
+ * This may be needed in non-MDB_NOLOCK mode. Recovery is rare enough that
+ * we don't care about a few wasted cycles.
*/
if (slmdb->cursor != 0)
slmdb_cursor_close(slmdb);
else if ((status = slmdb_txn_begin(slmdb, 0, &txn)) != 0)
SLMDB_API_RETURN(slmdb, status);
- /*
- * Before doing a non-bulk write transaction in MDB_NOLOCK mode, close a
- * cursor and its read transaction. We can restore it later with the
- * saved key information.
- */
- if (slmdb->cursor != 0 && slmdb->txn == 0
- && (slmdb->lmdb_flags & MDB_NOLOCK))
- slmdb_cursor_close(slmdb);
-
/*
* Do the update.
*/
else if ((status = slmdb_txn_begin(slmdb, 0, &txn)) != 0)
SLMDB_API_RETURN(slmdb, status);
- /*
- * Before doing a non-bulk write transaction in MDB_NOLOCK mode, close a
- * cursor and its read transaction. We can restore it later from the
- * saved key information.
- */
- if (slmdb->cursor != 0 && slmdb->txn == 0
- && (slmdb->lmdb_flags & MDB_NOLOCK))
- slmdb_cursor_close(slmdb);
-
/*
* Do the update.
*/
MDB_val *mdb_value, MDB_cursor_op op)
{
MDB_txn *txn;
- int status;
+ int status = 0;
/*
* Open a read transaction and cursor if needed.
/*
* Restore the cursor position from the saved key information.
*/
- if (HAVE_SLMDB_SAVED_KEY(slmdb) && op != MDB_FIRST) {
- if ((status = mdb_cursor_get(slmdb->cursor, &slmdb->saved_key,
- (MDB_val *) 0, MDB_SET)) != 0) {
- slmdb_cursor_close(slmdb);
- if ((status = slmdb_recover(slmdb, status)) == 0)
- status = slmdb_cursor_get(slmdb, mdb_key, mdb_value, op);
- SLMDB_API_RETURN(slmdb, status);
- }
- }
+ if (HAVE_SLMDB_SAVED_KEY(slmdb) && op != MDB_FIRST)
+ status = mdb_cursor_get(slmdb->cursor, &slmdb->saved_key,
+ (MDB_val *) 0, MDB_SET);
}
/*
* Database lookup.
*/
- status = mdb_cursor_get(slmdb->cursor, mdb_key, mdb_value, op);
+ if (status == 0)
+ status = mdb_cursor_get(slmdb->cursor, mdb_key, mdb_value, op);
/*
- * Save the cursor position. This can fail only with ENOMEM.
+ * Save the cursor position if successful. This can fail only with
+ * ENOMEM.
+ *
+ * Close the cursor read transaction if in MDB_NOLOCK mode, because the
+ * caller may release the external lock after we return.
*/
- if (status == 0)
+ if (status == 0) {
status = slmdb_saved_key_assign(slmdb, mdb_key);
+ if (slmdb->lmdb_flags & MDB_NOLOCK)
+ slmdb_cursor_close(slmdb);
+ }
/*
* Handle end-of-database or other error.
*/
else {
+ /* Do not hand-optimize out the slmdb_cursor_close() calls below. */
if (status == MDB_NOTFOUND) {
slmdb_cursor_close(slmdb);
if (HAVE_SLMDB_SAVED_KEY(slmdb))
slmdb_saved_key_free(slmdb);
} else {
+ slmdb_cursor_close(slmdb);
if ((status = slmdb_recover(slmdb, status)) == 0)
status = slmdb_cursor_get(slmdb, mdb_key, mdb_value, op);
SLMDB_API_RETURN(slmdb, status);
SLMDB_API_RETURN(slmdb, status);
}
+/* slmdb_assert_cb - report LMDB assertion failure */
+
+static void slmdb_assert_cb(MDB_env *env, const char *text)
+{
+ SLMDB *slmdb = (SLMDB *) mdb_env_get_userctx(env);
+
+ if (slmdb->assert_fn)
+ slmdb->assert_fn(slmdb->cb_context, text);
+}
+
/* slmdb_control - control optional settings */
int slmdb_control(SLMDB *slmdb, int first,...)
va_list ap;
int status = 0;
int reqno;
+ int rc;
va_start(ap, first);
for (reqno = first; status == 0 && reqno != SLMDB_CTL_END; reqno = va_arg(ap, int)) {
case SLMDB_CTL_NOTIFY_FN:
slmdb->notify_fn = va_arg(ap, SLMDB_NOTIFY_FN);
break;
- case SLMDB_CTL_CONTEXT:
+ case SLMDB_CTL_ASSERT_FN:
+ slmdb->assert_fn = va_arg(ap, SLMDB_ASSERT_FN);
+ if ((rc = mdb_env_set_userctx(slmdb->env, (void *) slmdb)) != 0
+ || (rc = mdb_env_set_assert(slmdb->env, slmdb_assert_cb)) != 0)
+ status = rc;
+ break;
+ case SLMDB_CTL_CB_CONTEXT:
slmdb->cb_context = va_arg(ap, void *);
break;
case SLMDB_CTL_API_RETRY_LIMIT:
slmdb->bulk_retry_limit = va_arg(ap, int);
break;
default:
- errno = EINVAL;
- status = -1;
+ status = errno = EINVAL;
break;
}
}
slmdb->bulk_retry_limit = SLMDB_DEF_BULK_RETRY_LIMIT;
slmdb->longjmp_fn = 0;
slmdb->notify_fn = 0;
+ slmdb->assert_fn = 0;
slmdb->cb_context = 0;
slmdb->txn = txn;
return (status);
}
-#endif
-
- /*
- * Implementation-dependent workaround to debug LMDB assert() failures. The
- * code below prevents daemons from disappearing without logfile record.
- */
-#ifdef LMDB_ASSERT_WORKAROUND
-
-#include <assert.h>
-
-void __assert(const char *func, const char *file, int line, const char *text)
-{
- msg_panic("Assertion failed: %s, function %s, file %s, line %d.",
- text, func, file, line);
-}
-
#endif
size_t saved_key_size; /* saved cursor key buffer size */
void (*longjmp_fn) (void *, int);/* exception handling */
void (*notify_fn) (void *, int,...); /* workaround notification */
+ void (*assert_fn) (void *, const char *); /* assert notification */
void *cb_context; /* call-back context */
int api_retry_count; /* slmdb(3) API call retry count */
int bulk_retry_count; /* bulk_mode retry count */
#define SLMDB_CTL_END 0
#define SLMDB_CTL_LONGJMP_FN 1 /* exception handling */
#define SLMDB_CTL_NOTIFY_FN 2 /* debug logging function */
-#define SLMDB_CTL_CONTEXT 3 /* exception/debug logging context */
+#define SLMDB_CTL_CB_CONTEXT 3 /* call-back context */
#define SLMDB_CTL_HARD_LIMIT 4 /* hard database size limit */
#define SLMDB_CTL_API_RETRY_LIMIT 5 /* per slmdb(3) API call */
#define SLMDB_CTL_BULK_RETRY_LIMIT 6 /* per bulk update */
+#define SLMDB_CTL_ASSERT_FN 7 /* report assertion failure */
typedef void (*SLMDB_NOTIFY_FN) (void *, int,...);
typedef void (*SLMDB_LONGJMP_FN) (void *, int);
+typedef void (*SLMDB_ASSERT_FN) (void *, const char *);
/* LICENSE
/* .ad