]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.12-20141013
authorWietse Venema <wietse@porcupine.org>
Mon, 13 Oct 2014 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Tue, 14 Oct 2014 03:58:29 +0000 (23:58 -0400)
25 files changed:
postfix/HISTORY
postfix/README_FILES/TLS_README
postfix/RELEASE_NOTES
postfix/html/TLS_README.html
postfix/html/lmtp.8.html
postfix/html/postconf.5.html
postfix/html/smtp.8.html
postfix/man/man5/postconf.5
postfix/man/man8/smtp.8
postfix/src/global/mail_parm_split.c
postfix/src/global/mail_version.h
postfix/src/master/master_ent.c
postfix/src/postalias/postalias.c
postfix/src/postconf/postconf_master.c
postfix/src/postmap/postmap.c
postfix/src/posttls-finger/posttls-finger.c
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd_proxy.c
postfix/src/util/dict.c
postfix/src/util/dict_cidr.c
postfix/src/util/dict_pcre.c
postfix/src/util/dict_regexp.c
postfix/src/util/dict_thash.c
postfix/src/util/readlline.c
postfix/src/util/readlline.h

index 97028e976c3d79407d1ed93d245bf59895741e98..c0cd97f12d5a752206c3de4a177492fa7449e05e 100644 (file)
@@ -20640,3 +20640,25 @@ Apologies for any names omitted.
        ./proto/postconf.proto, global/mail_params.h, smtp/lmtp_params.c,
        smtp/smtp.c, smtp/smtp.h, smtp/smtp_connect.c, smtp/smtp_params.c,
        smtp/smtp_proto.c, smtp/smtp_tls_policy.c, smtp/smtp_trouble.c.
+
+20141012
+
+       Cleanup: missing format-string checks. Files: master/master_ent.c,
+       posttls-finger/posttls-finger.c, smtpd/smtpd_proxy.c.
+
+       Bugfix: the PREPEND access/policy action added headers ABOVE
+       Postfix's own Received: header, exposing Postfix's own
+       Received: header to Milters (protocol violation) and hiding
+       the PREPENDed header from Milters. The latter caused problems
+       for DMARC implementations with SPF policy plus DKIM Milter.
+       PREPENDed headers are now added BELOW Postfix's own Received:
+       header and remain visible to Milters. File: smtpd/smtpd.c.
+
+20141013
+
+       Cleanup: configuration file line numbers in error/warning
+       messages could point to comment lines before or after the
+       problem. Files: util/readlline.[hc], master/master_ent.c,
+       postalias/postalias.c, postmap/postmap.c, util/dict.c,
+       util/dict_cidr.c, util/dict_pcre.e, util/dict_regexp.c,
+       util/dict_thash.c, postconf/postconf_master.c.
index adca4c825557f59f130dfdbc9fd4debe82423a4d..67a2e3f8c7559eb05db64f450b1f2ba4b5ac4b5a 100644 (file)
@@ -1027,8 +1027,11 @@ default. This is the recommended configuration for early adopters.
   * The "example.com" destination uses DANE, but if TLSA records are not
     present or are unusable, mail is deferred.
 
-  * The "example.org" destination uses DANE if possible, but if no TLSA records
-    are found opportunistic TLS is used.
+  * The "example.org" destination uses DANE if possible, but uses opportunistic
+    TLS if no TLSA records are found. The "fallback" attribute (Postfix >=
+    2.12) overrides the global main.cf smtp_tls_fallback_level parameter to
+    employ unauthenticated mandatory encryption if DANE authentication fails,
+    after logging a warning.
 
     main.cf:
         indexed = ${default_database_type}:${config_directory}/
@@ -1052,6 +1055,8 @@ default. This is the recommended configuration for early adopters.
 
     tls_policy:
         example.com dane-only
+        # Postfix >= 2.12, per-destination smtp_tls_fallback_level override
+        example.org dane fallback=encrypt
 
     master.cf:
         dane       unix  -       -       n       -       -       smtp
@@ -1632,7 +1637,9 @@ d\bda\ban\bne\be
     obtained for the remote SMTP server, SSLv2 is automatically disabled (see
     smtp_tls_mandatory_protocols), and the server certificate must match the
     TLSA records. RFC 6698 (DANE) TLS authentication and DNSSEC support is
-    available with Postfix 2.11 and later.
+    available with Postfix 2.11 and later. The optional "fallback" attribute
+    provides a per-site override of the main.cf smtp_tls_fallback_level
+    parameter (Postfix >= 2.12).
 d\bda\ban\bne\be-\b-o\bon\bnl\bly\by
     Mandatory DANE TLS. The TLS policy for the destination is obtained via TLSA
     records in DNSSEC. If no TLSA records are found, or none are usable, no
@@ -1640,7 +1647,9 @@ d\bda\ban\bne\be-\b-o\bon\bnl\bly\by
     the remote SMTP server, SSLv2 is automatically disabled (see
     smtp_tls_mandatory_protocols), and the server certificate must match the
     TLSA records. RFC 6698 (DANE) TLS authentication and DNSSEC support is
-    available with Postfix 2.11 and later.
+    available with Postfix 2.11 and later. The optional "fallback" attribute
+    provides a per-site override of the main.cf smtp_tls_fallback_level
+    parameter (Postfix >= 2.12).
 f\bfi\bin\bng\bge\ber\brp\bpr\bri\bin\bnt\bt
     Certificate fingerprint verification. Available with Postfix 2.5 and later.
     At this security level, there are no trusted certificate authorities. The
@@ -1653,7 +1662,8 @@ f\bfi\bin\bng\bge\ber\brp\bpr\bri\bin\bnt\bt
     combined with a "|" delimiter in a single match attribute, or multiple
     match attributes can be employed. The ":" character is not used as a
     delimiter as it occurs between each pair of fingerprint (hexadecimal)
-    digits.
+    digits. The optional "fallback" attribute provides a per-site override of
+    the main.cf smtp_tls_fallback_level parameter (Postfix >= 2.12).
 v\bve\ber\bri\bif\bfy\by
     Mandatory server certificate verification. Mail is delivered only if the
     TLS handshake succeeds, if the remote SMTP server certificate can be
@@ -1664,7 +1674,8 @@ v\bve\ber\bri\bif\bfy\by
     "tafile" attribute optionally modifies trust chain verification in the same
     manner as the "smtp_tls_trust_anchor_file" parameter. The "tafile"
     attribute may be specified multiple times to load multiple trust-anchor
-    files.
+    files. The optional "fallback" attribute provides a per-site override of
+    the main.cf smtp_tls_fallback_level parameter (Postfix >= 2.12).
 s\bse\bec\bcu\bur\bre\be
     Secure certificate verification. Mail is delivered only if the TLS
     handshake succeeds, if the remote SMTP server certificate can be validated
@@ -1674,7 +1685,9 @@ s\bse\bec\bcu\bur\bre\be
     "match" attribute is specified). With Postfix >= 2.11 the "tafile"
     attribute optionally modifies trust chain verification in the same manner
     as the "smtp_tls_trust_anchor_file" parameter. The "tafile" attribute may
-    be specified multiple times to load multiple trust-anchor files.
+    be specified multiple times to load multiple trust-anchor files. The
+    optional "fallback" attribute provides a per-site override of the main.cf
+    smtp_tls_fallback_level parameter (Postfix >= 2.12).
 Notes:
 
   * The "match" attribute is especially useful to verify TLS certificates for
@@ -1708,6 +1721,7 @@ Example:
         smtp_tls_policy_maps = hash:/etc/postfix/tls_policy
         # Postfix 2.5 and later
         smtp_tls_fingerprint_digest = md5
+
     /etc/postfix/tls_policy:
         example.edu             none
         example.mil             may
@@ -1723,6 +1737,8 @@ Example:
         # Postfix 2.6 and later
         example.info            may protocols=!SSLv2 ciphers=medium
     exclude=3DES
+        # Postfix 2.12 and later override of smtp_tls_fallback_level
+        fallback.example        secure fallback=encrypt
 
 N\bNo\bot\bte\be:\b: The "hostname" strategy if listed in a non-default setting of
 smtp_tls_secure_cert_match or in the "match" attribute in the policy table can
index cde2d69a23cfd8a9aa333761ee907608c5086ae1..99f22c5a180105eeb4847e9c747ea9faca8ed547 100644 (file)
@@ -59,6 +59,16 @@ Maintainers may also benefit from the makedefs documentation
 (mantools/srctoman - makedefs | nroff -man | less) with information
 about build options that are not described in the INSTALL instructions.
 
+Incompatible changes with snapshot 20141013
+===========================================
+
+Headers prepended with the access/policy PREPEND action are now
+added BELOW Postfix's own Recived: header. This ensures a) that
+Postfix's own Recived: header remains hidden from Milters as required
+by the Milter protocol, and b) that PREPENDed headers become visible
+to Milters, as expected by DMARC implementations based on SPF policy
+plus DKIM milter.
+
 Major changes with snapshot 20141011
 ====================================
 
@@ -73,7 +83,7 @@ Fallback to unauthenticated TLS is logged, so that downgrade attacks
 are "tamper-evident".  Fallback should be used only when testing,
 or temporarily when working around a known problem at a remote site.
 
-Incompatible changes with snapshot 20141008
+Incompatible changes with snapshot 20141009
 ===========================================
 
 The default settings have changed for relay_domains (new: empty,
index 2548b9f5761584241e216f36b255abe65d66ebc0..286bf394ca447ab48b6006efe9aa1052ed4bc80a 100644 (file)
@@ -1373,8 +1373,12 @@ for early adopters. <p>
 <li> <p> The "example.com" destination uses DANE, but if TLSA records
 are not present or are unusable, mail is deferred. </p>
 
-<li> <p> The "example.org" destination uses DANE if possible, but if no TLSA
-records are found opportunistic TLS is used. </p>
+<li> <p> The "example.org" destination uses DANE if possible, but
+uses opportunistic TLS if no TLSA records are found.  The
+"fallback" attribute (Postfix &ge; 2.12) overrides the global
+<a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a> parameter to employ unauthenticated
+mandatory encryption if DANE authentication fails, after logging a
+warning.  </p>
 </ul>
 
 <blockquote>
@@ -1394,26 +1398,16 @@ records are found opportunistic TLS is used. </p>
     # <a href="postconf.5.html#default_transport">default_transport</a> = smtp, but some destinations are special:
     #
     <a href="postconf.5.html#transport_maps">transport_maps</a> = ${indexed}transport
-</pre>
-</blockquote>
 
-<blockquote>
-<pre>
 transport:
     example.com dane
     example.org dane
-</pre>
-</blockquote>
 
-<blockquote>
-<pre>
 tls_policy:
     example.com dane-only
-</pre>
-</blockquote>
+    # Postfix &ge; 2.12, per-destination <a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a> override
+    example.org dane fallback=encrypt
 
-<blockquote>
-<pre>
 <a href="master.5.html">master.cf</a>:
     dane       unix  -       -       n       -       -       smtp
       -o <a href="postconf.5.html#smtp_dns_support_level">smtp_dns_support_level</a>=dnssec
@@ -2146,7 +2140,10 @@ href="#client_tls_encrypt">encrypt</a>.  When usable TLSA records
 are obtained for the remote SMTP server, SSLv2 is automatically
 disabled (see <a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a>), and the server certificate
 must match the TLSA records.  <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> (DANE) TLS authentication
-and DNSSEC support is available with Postfix 2.11 and later.  </dd>
+and DNSSEC support is available with Postfix 2.11 and later.  
+The optional "fallback" attribute provides a per-site override of
+the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a> parameter (Postfix &ge; 2.12).
+</dd>
 
 <dt><b>dane-only</b></dt> <dd><a href="#client_tls_dane">Mandatory DANE TLS</a>.
 The TLS policy for the destination is obtained via TLSA records in
@@ -2155,7 +2152,10 @@ connection is made to the server.  When usable TLSA records are
 obtained for the remote SMTP server, SSLv2 is automatically disabled
 (see <a href="postconf.5.html#smtp_tls_mandatory_protocols">smtp_tls_mandatory_protocols</a>), and the server certificate must
 match the TLSA records.  <a href="http://tools.ietf.org/html/rfc6698">RFC 6698</a> (DANE) TLS authentication and
-DNSSEC support is available with Postfix 2.11 and later.  </dd>
+DNSSEC support is available with Postfix 2.11 and later.  
+The optional "fallback" attribute provides a per-site override of
+the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a> parameter (Postfix &ge; 2.12).
+</dd>
 
 <dt><b>fingerprint</b></dt> <dd><a href="#client_tls_fprint">Certificate
 fingerprint verification.</a> Available with Postfix 2.5 and
@@ -2164,13 +2164,15 @@ authorities. The certificate trust chain, expiration date, ... are
 not checked. Instead, the optional <b>match</b> attribute, or else
 the <a href="postconf.5.html">main.cf</a> <b><a href="postconf.5.html#smtp_tls_fingerprint_cert_match">smtp_tls_fingerprint_cert_match</a></b> parameter, lists
 the server certificate fingerprints or public key fingerprints
-(Postfix 2.9 and later).  The
-digest algorithm used to calculate fingerprints is selected by the
-<b><a href="postconf.5.html#smtp_tls_fingerprint_digest">smtp_tls_fingerprint_digest</a></b> parameter. Multiple fingerprints can
-be combined with a "|" delimiter in a single match attribute, or multiple
-match attributes can be employed. The ":" character is not used as a
-delimiter as it occurs between each pair of fingerprint (hexadecimal)
-digits. </dd>
+(Postfix 2.9 and later).  The digest algorithm used to calculate
+fingerprints is selected by the <b><a href="postconf.5.html#smtp_tls_fingerprint_digest">smtp_tls_fingerprint_digest</a></b>
+parameter. Multiple fingerprints can be combined with a "|" delimiter
+in a single match attribute, or multiple match attributes can be
+employed. The ":" character is not used as a delimiter as it occurs
+between each pair of fingerprint (hexadecimal) digits.
+The optional "fallback" attribute provides a per-site override of
+the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a> parameter (Postfix &ge; 2.12).
+</dd>
 
 <dt><b>verify</b></dt> <dd><a href="#client_tls_verify">Mandatory
 server certificate verification</a>.  Mail is delivered only if the
@@ -2181,9 +2183,11 @@ the optional "match" attribute (or the <a href="postconf.5.html">main.cf</a> <a
 parameter value when no optional "match" attribute is specified).
 With Postfix &ge; 2.11 the "tafile" attribute optionally modifies
 trust chain verification in the same manner as the
-"<a href="postconf.5.html#smtp_tls_trust_anchor_file">smtp_tls_trust_anchor_file</a>" parameter.  The "tafile" attribute
-may be specified multiple times to load multiple trust-anchor
-files.  </dd>
+"<a href="postconf.5.html#smtp_tls_trust_anchor_file">smtp_tls_trust_anchor_file</a>" parameter.  The "tafile" attribute may
+be specified multiple times to load multiple trust-anchor files.
+The optional "fallback" attribute provides a per-site override of
+the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a> parameter (Postfix &ge; 2.12).
+</dd>
 
 <dt><b>secure</b></dt> <dd><a href="#client_tls_secure">Secure certificate
 verification.</a> Mail is delivered only if the TLS handshake succeeds,
@@ -2195,7 +2199,10 @@ server certificate name matches the optional "match" attribute (or the
 attribute optionally modifies trust chain verification in the same manner
 as the "<a href="postconf.5.html#smtp_tls_trust_anchor_file">smtp_tls_trust_anchor_file</a>" parameter.  The "tafile" attribute
 may be specified multiple times to load multiple trust-anchor
-files.  </dd>
+files.  
+The optional "fallback" attribute provides a per-site override of
+the <a href="postconf.5.html">main.cf</a> <a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a> parameter (Postfix &ge; 2.12).
+</dd>
 
 </dl>
 
@@ -2242,6 +2249,7 @@ Example:
     <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/tls_policy
     # Postfix 2.5 and later
     <a href="postconf.5.html#smtp_tls_fingerprint_digest">smtp_tls_fingerprint_digest</a> = md5
+
 /etc/postfix/tls_policy:
     example.edu             none
     example.mil             may
@@ -2256,6 +2264,8 @@ Example:
         match=3D:95:34:51:24:66:33:B9:D2:40:99:C0:C1:17:0B:D1
     # Postfix 2.6 and later
     example.info            may protocols=!SSLv2 ciphers=medium exclude=3DES
+    # Postfix 2.12 and later override of <a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a>
+    fallback.example        secure fallback=encrypt
 </pre>
 </blockquote>
 
index f07bc31f16c112485da0aca4733ae6e4f798cb45..2299c5cc506157e89178fd82f7a46b0a4a92efc1 100644 (file)
@@ -552,6 +552,11 @@ SMTP(8)                                                                SMTP(8)
        <b><a href="postconf.5.html#tlsmgr_service_name">tlsmgr_service_name</a> (tlsmgr)</b>
               The name of the <a href="tlsmgr.8.html"><b>tlsmgr</b>(8)</a> service entry in <a href="master.5.html">master.cf</a>.
 
+       Available in Postfix version 2.12 and later:
+
+       <b><a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a> (empty)</b>
+              Optional fallback levels for authenticated TLS levels.
+
 <b>OBSOLETE STARTTLS CONTROLS</b>
        The  following  configuration  parameters  exist for compatibility with
        Postfix versions before 2.3. Support for these will  be  removed  in  a
index e4e47d80dd6d898f478237bb36023c04b781c1c7..c40fe6f61751480f0494f76a0a124f84317bbcf8 100644 (file)
@@ -5027,6 +5027,17 @@ configuration parameter.  See there for details. </p>
 <p> This feature is available in Postfix 2.3 and later. </p>
 
 
+</DD>
+
+<DT><b><a name="lmtp_tls_fallback_level">lmtp_tls_fallback_level</a>
+(default: empty)</b></DT><DD>
+
+<p> The LMTP-specific version of the <a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a>
+configuration parameter.  See there for details. </p>
+
+<p> This feature is available in Postfix 2.12 and later. </p>
+
+
 </DD>
 
 <DT><b><a name="lmtp_tls_fingerprint_cert_match">lmtp_tls_fingerprint_cert_match</a>
@@ -11637,6 +11648,61 @@ key exchange with RSA authentication. </p>
 <p> This feature is available in Postfix 2.3 and later. </p>
 
 
+</DD>
+
+<DT><b><a name="smtp_tls_fallback_level">smtp_tls_fallback_level</a>
+(default: empty)</b></DT><DD>
+
+<p> Optional fallback levels for authenticated TLS levels.  Specify
+a white-space or comma-separated list of
+<b>policy_level</b>=<b>fallback_level</b> pairs.  The <b>policy_level</b>
+must require authentication (one of dane, dane-only, fingerprint,
+verify, secure).  The <b>fallback_level</b> must be "encrypt" or
+"may".  When an authenticated connection at some desired policy
+level cannot be established, delivery will proceed at the correponding
+fallback level if possible.  A warning will be logged
+indicating the fallback reason. </p>
+
+<p> The TLS <a href="TLS_README.html#client_tls_policy">policy</a> table
+can be used to specify a destination-specific fallback strategy via the
+"fallback" policy attribute.  The value of the "fallback" attribute, if
+specified, must be "may", "encrypt" or "none".  If not "none", this
+specifies the fallback level for the destination in question.  If the
+attribute value is "none", fallback is suppressed for the destination
+even if enabled via a global setting of <a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a>.  </p>
+
+<p> Example: </p>
+
+<blockquote>
+<pre>
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
+    # When authentication fails, log a warning and deliver anyway
+    # over an unauthenticated TLS connection.
+    #
+    <a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a> =
+        dane=encrypt,
+        dane-only=encrypt,
+        fingerprint=encrypt,
+        verify=encrypt,
+        secure=encrypt
+    indexed = ${<a href="postconf.5.html#default_database_type">default_database_type</a>}:${<a href="postconf.5.html#config_directory">config_directory</a>}/
+    <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> = ${indexed}tls-policy
+</pre>
+</blockquote>
+
+<blockquote>
+<pre>
+/etc/postfix/tls-policy:
+    # No fallback for example.com
+    example.com secure fallback=none
+    # For example.net tolerate cleartext fallback
+    example.net dane fallback=may
+</pre>
+</blockquote>
+
+<p> This feature is available in Postfix 2.12 and later. </p>
+
+
 </DD>
 
 <DT><b><a name="smtp_tls_fingerprint_cert_match">smtp_tls_fingerprint_cert_match</a>
index f07bc31f16c112485da0aca4733ae6e4f798cb45..2299c5cc506157e89178fd82f7a46b0a4a92efc1 100644 (file)
@@ -552,6 +552,11 @@ SMTP(8)                                                                SMTP(8)
        <b><a href="postconf.5.html#tlsmgr_service_name">tlsmgr_service_name</a> (tlsmgr)</b>
               The name of the <a href="tlsmgr.8.html"><b>tlsmgr</b>(8)</a> service entry in <a href="master.5.html">master.cf</a>.
 
+       Available in Postfix version 2.12 and later:
+
+       <b><a href="postconf.5.html#smtp_tls_fallback_level">smtp_tls_fallback_level</a> (empty)</b>
+              Optional fallback levels for authenticated TLS levels.
+
 <b>OBSOLETE STARTTLS CONTROLS</b>
        The  following  configuration  parameters  exist for compatibility with
        Postfix versions before 2.3. Support for these will  be  removed  in  a
index daeebcb9c361cfcc1dbec7d967cb55895f9e98ed..c8b16dfe017ae13a3cbd999b48a40bac4e64728f 100644 (file)
@@ -2970,6 +2970,11 @@ The LMTP-specific version of the smtp_tls_exclude_ciphers
 configuration parameter.  See there for details.
 .PP
 This feature is available in Postfix 2.3 and later.
+.SH lmtp_tls_fallback_level (default: empty)
+The LMTP-specific version of the smtp_tls_fallback_level
+configuration parameter.  See there for details.
+.PP
+This feature is available in Postfix 2.12 and later.
 .SH lmtp_tls_fingerprint_cert_match (default: empty)
 The LMTP-specific version of the smtp_tls_fingerprint_cert_match
 configuration parameter.  See there for details.
@@ -7304,6 +7309,63 @@ and "DES-CBC3-MD5". The last setting disables ciphers that use "EDH"
 key exchange with RSA authentication.
 .PP
 This feature is available in Postfix 2.3 and later.
+.SH smtp_tls_fallback_level (default: empty)
+Optional fallback levels for authenticated TLS levels.  Specify
+a white-space or comma-separated list of
+\fBpolicy_level\fR=\fBfallback_level\fR pairs.  The \fBpolicy_level\fR
+must require authentication (one of dane, dane-only, fingerprint,
+verify, secure).  The \fBfallback_level\fR must be "encrypt" or
+"may".  When an authenticated connection at some desired policy
+level cannot be established, delivery will proceed at the correponding
+fallback level if possible.  A warning will be logged
+indicating the fallback reason.
+.PP
+The TLS policy table
+can be used to specify a destination-specific fallback strategy via the
+"fallback" policy attribute.  The value of the "fallback" attribute, if
+specified, must be "may", "encrypt" or "none".  If not "none", this
+specifies the fallback level for the destination in question.  If the
+attribute value is "none", fallback is suppressed for the destination
+even if enabled via a global setting of smtp_tls_fallback_level.
+.PP
+Example:
+.sp
+.in +4
+.nf
+.na
+.ft C
+/etc/postfix/main.cf:
+    # When authentication fails, log a warning and deliver anyway
+    # over an unauthenticated TLS connection.
+    #
+    smtp_tls_fallback_level =
+        dane=encrypt,
+        dane-only=encrypt,
+        fingerprint=encrypt,
+        verify=encrypt,
+        secure=encrypt
+    indexed = ${default_database_type}:${config_directory}/
+    smtp_tls_policy_maps = ${indexed}tls-policy
+.fi
+.ad
+.ft R
+.in -4
+.sp
+.in +4
+.nf
+.na
+.ft C
+/etc/postfix/tls-policy:
+    # No fallback for example.com
+    example.com secure fallback=none
+    # For example.net tolerate cleartext fallback
+    example.net dane fallback=may
+.fi
+.ad
+.ft R
+.in -4
+.PP
+This feature is available in Postfix 2.12 and later.
 .SH smtp_tls_fingerprint_cert_match (default: empty)
 List of acceptable remote SMTP server certificate fingerprints for
 the "fingerprint" TLS security level (\fBsmtp_tls_security_level\fR =
index c0c3ed2bc72fd809f6b7597950828afdb85057d5..05ff23f2b2d907ac6ac0740b441c8d6f26e279b2 100644 (file)
@@ -492,6 +492,10 @@ not an alias and its address records lie in an unsigned zone.
 RFC 6698 trust-anchor digest support in the Postfix TLS library.
 .IP "\fBtlsmgr_service_name (tlsmgr)\fR"
 The name of the \fBtlsmgr\fR(8) service entry in master.cf.
+.PP
+Available in Postfix version 2.12 and later:
+.IP "\fBsmtp_tls_fallback_level (empty)\fR"
+Optional fallback levels for authenticated TLS levels.
 .SH "OBSOLETE STARTTLS CONTROLS"
 .na
 .nf
index 0b206d059e4f4a4326e196133e693de979c7ffdf..1c54ab0157469a84fc0379a666b0522fc3d4b0ca 100644 (file)
@@ -7,13 +7,13 @@
 /*     #include <mail_parm_split.h>
 /*
 /*     ARGV    *mail_parm_split(
-/*     cost char *name,
+/*     const char *name,
 /*     const char *value)
 /* DESCRIPTION
 /*     mail_parm_split() splits a parameter list value into its
-/*     elements, and extracts text from inside {}. It uses
-/*     CHARS_COMMA_SP as list element delimiters, and CHARS_BRACE
-/*     for grouping.
+/*     elements, and extracts text from elements that are entirely
+/*     enclosed in {}. It uses CHARS_COMMA_SP as list element
+/*     delimiters, and CHARS_BRACE for grouping.
 /*
 /*     Arguments:
 /* .IP name
@@ -22,7 +22,8 @@
 /* .IP value
 /*     Parameter value.
 /* DIAGNOSTICS
-/*     fatal: syntax error while extracting text from {}.
+/*     fatal: syntax error while extracting text from {}, such as:
+/*     missing closing brace, or text after closing brace.
 /* SEE ALSO
 /*     argv_splitq(3), string array utilities
 /*     extpar(3), extract text from parentheses
index 2b7e101ee0049f0cf98276de95aa80d0f7adf9eb..6c7a070785d18a4453c8c983f1b79363c8ec9b34 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20141011"
+#define MAIL_RELEASE_DATE      "20141013"
 #define MAIL_VERSION_NUMBER    "2.12"
 
 #ifdef SNAPSHOT
index 3235996d9175ce8b110c6f17fb682b9ea5cf2502..15ae3076d79ea2ac780afe8cb7a1e150740bd62d 100644 (file)
 static char *master_path;              /* config file name */
 static VSTREAM *master_fp;             /* config file pointer */
 static int master_line;                        /* config file line number */
+static int master_line_first;          /* config file line number */
 static ARGV *master_disable;           /* disabled service patterns */
 
 static char master_blanks[] = " \t\r\n";/* field delimiters */
 
-static NORETURN fatal_invalid_field(char *, char *);
-static NORETURN fatal_with_context(char *,...);
-
 /* fset_master_ent - specify configuration file pathname */
 
 void    fset_master_ent(char *path)
@@ -167,9 +165,21 @@ void    end_master_ent()
     master_disable = 0;
 }
 
+/* master_conf_context - plot the target range */
+
+static const char *master_conf_context(void)
+{
+    static VSTRING *context_buf = 0;
+
+    if (context_buf == 0)
+       context_buf = vstring_alloc(100);
+    vstring_sprintf(context_buf, "%s: line %d", master_path, master_line_first);
+    return (vstring_str(context_buf));
+}
+
 /* fatal_with_context - print fatal error with file/line context */
 
-static NORETURN fatal_with_context(char *format,...)
+static NORETURN PRINTFLIKE(1, 2) fatal_with_context(char *format,...)
 {
     const char *myname = "fatal_with_context";
     VSTRING *vp = vstring_alloc(100);
@@ -181,7 +191,7 @@ static NORETURN fatal_with_context(char *format,...)
     va_start(ap, format);
     vstring_vsprintf(vp, format, ap);
     va_end(ap);
-    msg_fatal("%s: line %d: %s", master_path, master_line, vstring_str(vp));
+    msg_fatal("%s: %s", master_conf_context(), vstring_str(vp));
 }
 
 /* fatal_invalid_field - report invalid field value */
@@ -203,8 +213,8 @@ static char *get_str_ent(char **bufp, char *name, char *def_val)
        if (def_val == 0)
            fatal_with_context("field \"%s\" has no default value", name);
        if (warn_compat_break_chroot && strcmp(name, "chroot") == 0)
-           msg_info("%s: line %d: using backwards-compatible default setting "
-                    "%s=%s", master_path, master_line, name, def_val);
+           msg_info("%s: using backwards-compatible default setting "
+                    "%s=%s", master_conf_context(), name, def_val);
        return (def_val);
     } else {
        return (value);
@@ -288,7 +298,7 @@ MASTER_SERV *get_master_ent()
      * Skip blank lines and comment lines.
      */
     for (;;) {
-       if (readlline(buf, master_fp, &master_line) == 0) {
+       if (readllines(buf, master_fp, &master_line, &master_line_first) == 0) {
            vstring_free(buf);
            vstring_free(junk);
            return (0);
@@ -340,17 +350,14 @@ MASTER_SERV *get_master_ent()
        serv->type = MASTER_SERV_TYPE_INET;
        atmp = mystrdup(name);
        if ((parse_err = host_port(atmp, &host, "", &port, (char *) 0)) != 0)
-           msg_fatal("%s: line %d: %s in \"%s\"",
-                     VSTREAM_PATH(master_fp), master_line,
-                     parse_err, name);
+           fatal_with_context("%s in \"%s\"", parse_err, name);
        if (*host) {
            serv->flags |= MASTER_FLAG_INETHOST;/* host:port */
            MASTER_INET_ADDRLIST(serv) = (INET_ADDR_LIST *)
                mymalloc(sizeof(*MASTER_INET_ADDRLIST(serv)));
            inet_addr_list_init(MASTER_INET_ADDRLIST(serv));
            if (inet_addr_host(MASTER_INET_ADDRLIST(serv), host) == 0)
-               msg_fatal("%s: line %d: bad hostname or network address: %s",
-                         VSTREAM_PATH(master_fp), master_line, name);
+               fatal_with_context("bad hostname or network address: %s", name);
            inet_addr_list_uniq(MASTER_INET_ADDRLIST(serv));
            serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
        } else {
@@ -454,8 +461,7 @@ MASTER_SERV *get_master_ent()
      * sockets is frozen anyway once we build the command-line vector below.
      */
     if (serv->listen_fd_count == 0) {
-       msg_fatal("%s: line %d: no valid IP address found: %s",
-                 VSTREAM_PATH(master_fp), master_line, name);
+       fatal_with_context("no valid IP address found: %s", name);
     }
     serv->listen_fd = (int *) mymalloc(sizeof(int) * serv->listen_fd_count);
     for (n = 0; n < serv->listen_fd_count; n++)
@@ -557,8 +563,7 @@ MASTER_SERV *get_master_ent()
                 (char *) 0);
     while ((cp = mystrtokq(&bufp, master_blanks, "{}")) != 0) {
        if (*cp == '{' && (err = extpar(&cp, "{}", EXTPAR_FLAG_STRIP)) != 0)
-           msg_fatal("%s: line %d: %s",
-                     VSTREAM_PATH(master_fp), master_line, err);
+           fatal_with_context("%s", err);
        argv_add(serv->args, cp, (char *) 0);
     }
     argv_terminate(serv->args);
index 430c156417d989e1744cd5d1b14812d9fd57b8a7..b5b4bf6e9a6ea1895387163228c389445d8430c5 100644 (file)
@@ -263,6 +263,7 @@ static void postalias(char *map_type, char *path_name, int postalias_flags,
     VSTRING *line_buffer;
     MKMAP  *mkmap;
     int     lineno;
+    int     last_line;
     VSTRING *key_buffer;
     VSTRING *value_buffer;
     TOK822 *tok_list;
@@ -334,8 +335,8 @@ static void postalias(char *map_type, char *path_name, int postalias_flags,
        /*
         * Add records to the database.
         */
-       lineno = 0;
-       while (readlline(line_buffer, source_fp, &lineno)) {
+       last_line = 0;
+       while (readllines(line_buffer, source_fp, &last_line, &lineno)) {
 
            /*
             * Tokenize the input, so that we do the right thing when a
index 481c35730db205bbd92e19bca86a95841c0ea6d9..a745df20cb675a8f8abe8adcd47671738fc7c7ca 100644 (file)
@@ -395,7 +395,8 @@ void    pcf_read_master(int fail_on_open_error)
     VSTREAM *fp;
     const char *err;
     int     entry_count = 0;
-    int     line_count = 0;
+    int     line_count;
+    int     last_line = 0;
 
     /*
      * Sanity check.
@@ -425,7 +426,7 @@ void    pcf_read_master(int fail_on_open_error)
        msg_warn("open %s: %m", path);
     } else {
        buf = vstring_alloc(100);
-       while (readlline(buf, fp, &line_count) != 0) {
+       while (readllines(buf, fp, &last_line, &line_count) != 0) {
            pcf_master_table = (PCF_MASTER_ENT *) myrealloc((char *) pcf_master_table,
                             (entry_count + 2) * sizeof(*pcf_master_table));
            if ((err = pcf_parse_master_entry(pcf_master_table + entry_count,
index e10ac166976467a1993e02631cc1e18c8ee4d7d4..85301cc7f6dd67f0918bc13d1406d2f3d3a509ea 100644 (file)
@@ -332,6 +332,7 @@ static void postmap(char *map_type, char *path_name, int postmap_flags,
     VSTRING *line_buffer;
     MKMAP  *mkmap;
     int     lineno;
+    int     last_line;
     char   *key;
     char   *value;
     struct stat st;
@@ -397,8 +398,8 @@ static void postmap(char *map_type, char *path_name, int postmap_flags,
        /*
         * Add records to the database.
         */
-       lineno = 0;
-       while (readlline(line_buffer, source_fp, &lineno)) {
+       last_line = 0;
+       while (readllines(line_buffer, source_fp, &last_line, &lineno)) {
 
            /*
             * Split on the first whitespace character, then trim leading and
index c0c22b6053d61d4ed4575dc90939a45ce88752d7..f02acf590e512f7db5bcdb3876ea44971ce27fc9 100644 (file)
@@ -453,7 +453,7 @@ typedef struct {                    /* server response */
 
 /* command - send an SMTP command */
 
-static void command(STATE *state, int verbose, char *fmt,...)
+static void PRINTFLIKE(3, 4) command(STATE *state, int verbose, char *fmt,...)
 {
     VSTREAM *stream = state->stream;
     VSTRING *buf;
index d282122be4b8ceb7d3be55b327f7b5b3b282c2cd..55627c6d260b8073152e8152b476c7309e0abf03 100644 (file)
@@ -3114,13 +3114,6 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
        rec_fputs(state->cleanup, REC_TYPE_MESG, "");
     }
 
-    /*
-     * PREPEND message headers.
-     */
-    if (state->prepend)
-       for (cpp = state->prepend->argv; *cpp; cpp++)
-           out_fprintf(out_stream, REC_TYPE_NORM, "%s", *cpp);
-
     /*
      * Suppress our own Received: header in the unlikely case that we are an
      * intermediate proxy.
@@ -3210,6 +3203,14 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
                    "\t(envelope-from %s)", STR(state->buffer));
 #endif
     }
+
+    /*
+     * PREPEND message headers.
+     */
+    if (state->prepend)
+       for (cpp = state->prepend->argv; *cpp; cpp++)
+           out_fprintf(out_stream, REC_TYPE_NORM, "%s", *cpp);
+
     smtpd_chat_reply(state, "354 End data with <CR><LF>.<CR><LF>");
     state->where = SMTPD_AFTER_DATA;
 
index f20e673c59117089bcf9e9d0d558293f94cd3f7c..552c61abe99b6b535b90c62b29ca619049016df2 100644 (file)
@@ -233,7 +233,7 @@ static VSTREAM *smtpd_proxy_replay_stream;
   */
 static void smtpd_proxy_fake_server_reply(SMTPD_STATE *, int);
 static int smtpd_proxy_rdwr_error(SMTPD_STATE *, int);
-static int smtpd_proxy_cmd(SMTPD_STATE *, int, const char *,...);
+static int PRINTFLIKE(3, 4) smtpd_proxy_cmd(SMTPD_STATE *, int, const char *,...);
 static int smtpd_proxy_rec_put(VSTREAM *, int, const char *, ssize_t);
 
  /*
@@ -652,7 +652,7 @@ static int smtpd_proxy_replay_send(SMTPD_STATE *state)
 
 /* smtpd_proxy_save_cmd - save SMTP command + expected response to replay log */
 
-static int smtpd_proxy_save_cmd(SMTPD_STATE *state, int expect, const char *fmt,...)
+static int PRINTFLIKE(3, 4) smtpd_proxy_save_cmd(SMTPD_STATE *state, int expect, const char *fmt,...)
 {
     va_list ap;
 
index 769b16b3c3d529de1e9049d86452a7e8bf4e1cab..fefd0ad4e02fd0c0a1d31c23a8fe1d5d324e527c 100644 (file)
@@ -476,7 +476,7 @@ void    dict_load_fp(const char *dict_name, VSTREAM *fp)
     char   *member;
     char   *val;
     const char *old;
-    int     old_lineno;
+    int     last_line;
     int     lineno;
     const char *err;
     struct stat st;
@@ -487,16 +487,15 @@ void    dict_load_fp(const char *dict_name, VSTREAM *fp)
      */
     DICT_FIND_FOR_UPDATE(dict, dict_name);
     buf = vstring_alloc(100);
-    old_lineno = lineno = 0;
+    last_line = 0;
 
     if (fstat(vstream_fileno(fp), &st) < 0)
        msg_fatal("fstat %s: %m", VSTREAM_PATH(fp));
-    for ( /* void */ ; readlline(buf, fp, &lineno); old_lineno = lineno) {
+    while (readllines(buf, fp, &last_line, &lineno)) {
        if ((err = split_nameval(STR(buf), &member, &val)) != 0)
-           msg_fatal("%s, line %s: %s: \"%s\"",
+           msg_fatal("%s, line %d: %s: \"%s\"",
                      VSTREAM_PATH(fp),
-                     format_line_number((VSTRING *) 0,
-                                        old_lineno + 1, lineno),
+                     lineno,
                      err, STR(buf));
        if (msg_verbose > 1)
            msg_info("%s: %s = %s", myname, member, val);
index 76577fcb392adc0bd4f2414cec4fdfd9ae461589..0ee9c4cc2fc389e0ce848e9b34260aa056dc2a76 100644 (file)
@@ -171,7 +171,8 @@ DICT   *dict_cidr_open(const char *mapname, int open_flags, int dict_flags)
     VSTRING *why = 0;
     DICT_CIDR_ENTRY *rule;
     DICT_CIDR_ENTRY *last_rule = 0;
-    int     lineno = 0;
+    int     last_line = 0;
+    int     lineno;
 
     /*
      * Let the optimizer worry about eliminating redundant code.
@@ -223,7 +224,7 @@ DICT   *dict_cidr_open(const char *mapname, int open_flags, int dict_flags)
     dict_cidr->dict.owner.uid = st.st_uid;
     dict_cidr->dict.owner.status = (st.st_uid != 0);
 
-    while (readlline(line_buffer, map_fp, &lineno)) {
+    while (readllines(line_buffer, map_fp, &last_line, &lineno)) {
        rule = dict_cidr_parse_rule(vstring_str(line_buffer), why);
        if (rule == 0) {
            msg_warn("cidr map %s, line %d: %s: skipping this rule",
index 3f183386848b278ca8f149e2607f36d70c83affd..23ac2cd6f332a741a3dabc11b6496a63a8e06a28 100644 (file)
@@ -812,7 +812,8 @@ DICT   *dict_pcre_open(const char *mapname, int open_flags, int dict_flags)
     VSTRING *line_buffer = 0;
     DICT_PCRE_RULE *last_rule = 0;
     DICT_PCRE_RULE *rule;
-    int     lineno = 0;
+    int     last_line = 0;
+    int     lineno;
     int     nesting = 0;
     char   *p;
 
@@ -870,7 +871,7 @@ DICT   *dict_pcre_open(const char *mapname, int open_flags, int dict_flags)
     /*
      * Parse the pcre table.
      */
-    while (readlline(line_buffer, map_fp, &lineno)) {
+    while (readllines(line_buffer, map_fp, &last_line, &lineno)) {
        p = vstring_str(line_buffer);
        trimblanks(p, 0)[0] = 0;                /* Trim space at end */
        if (*p == 0)
index d6415788272cad88b1b5c1071c39bada55791a70..c32925122e8f80ce041ffef9d1b49f93ac9a1bf4 100644 (file)
@@ -743,7 +743,8 @@ DICT   *dict_regexp_open(const char *mapname, int open_flags, int dict_flags)
     VSTRING *line_buffer = 0;
     DICT_REGEXP_RULE *rule;
     DICT_REGEXP_RULE *last_rule = 0;
-    int     lineno = 0;
+    int     lineno;
+    int     last_line = 0;
     size_t  max_sub = 0;
     int     nesting = 0;
     char   *p;
@@ -797,7 +798,7 @@ DICT   *dict_regexp_open(const char *mapname, int open_flags, int dict_flags)
     /*
      * Parse the regexp table.
      */
-    while (readlline(line_buffer, map_fp, &lineno)) {
+    while (readllines(line_buffer, map_fp, &last_line, &lineno)) {
        p = vstring_str(line_buffer);
        trimblanks(p, 0)[0] = 0;
        if (*p == 0)
index bd4af6ce6ccf3c099fceabf2030a69b43e880cc4..1bee77d30b1ac3cd02cd24346ac9ffb6427b0924 100644 (file)
@@ -151,6 +151,7 @@ DICT   *dict_thash_open(const char *path, int open_flags, int dict_flags)
     time_t  after;
     VSTRING *line_buffer = 0;
     int     lineno;
+    int     last_line;
     char   *key;
     char   *value;
     HTABLE *table;
@@ -189,9 +190,9 @@ DICT   *dict_thash_open(const char *path, int open_flags, int dict_flags)
        }
        if (line_buffer == 0)
            line_buffer = vstring_alloc(100);
-       lineno = 0;
+       last_line = 0;
        table = htable_create(13);
-       while (readlline(line_buffer, fp, &lineno)) {
+       while (readllines(line_buffer, fp, &last_line, &lineno)) {
 
            /*
             * Split on the first whitespace character, then trim leading and
index 95bb29bb761cf780a506444c7b4c872bcd9cc217..015877a2f28c220b2ad41b8ac3423daa0ba92ac8 100644 (file)
@@ -6,12 +6,18 @@
 /* SYNOPSIS
 /*     #include <readlline.h>
 /*
+/*     VSTRING *readllines(buf, fp, lineno, first_line)
+/*     VSTRING *buf;
+/*     VSTREAM *fp;
+/*     int     *lineno;
+/*     int     *first_line;
+/*
 /*     VSTRING *readlline(buf, fp, lineno)
 /*     VSTRING *buf;
 /*     VSTREAM *fp;
 /*     int     *lineno;
 /* DESCRIPTION
-/*     readlline() reads one logical line from the named stream.
+/*     readllines() reads one logical line from the named stream.
 /* .IP "blank lines and comments"
 /*     Empty lines and whitespace-only lines are ignored, as
 /*     are lines whose first non-whitespace character is a `#'.
@@ -22,6 +28,8 @@
 /*     The result value is the input buffer argument or a null pointer
 /*     when no input is found.
 /*
+/*     readlline() is a backwards-compatibility wrapper.
+/*
 /*     Arguments:
 /* .IP buf
 /*     A variable-length buffer for input. The result is null terminated.
 /*     Handle to an open stream.
 /* .IP lineno
 /*     A null pointer, or a pointer to an integer that is incremented
-/*     after reading a newline character.
-/* .RE
+/*     after reading a physical line.
+/* .IP first_line
+/*     A null pointer, or a pointer to an integer that will contain
+/*     the line number of the first non-blank, non-comment line
+/*     in the result logical line.
 /* DIAGNOSTICS
 /*     Warning: a continuation line that does not continue preceding text.
 /*     The invalid input is ignored, to avoid complicating caller code.
@@ -66,9 +77,9 @@
 #define LEN(x) VSTRING_LEN(x)
 #define END(x) vstring_end(x)
 
-/* readlline - read one logical line */
+/* readllines - read one logical line */
 
-VSTRING *readlline(VSTRING *buf, VSTREAM *fp, int *lineno)
+VSTRING *readllines(VSTRING *buf, VSTREAM *fp, int *lineno, int *first_line)
 {
     int     ch;
     int     next;
@@ -86,13 +97,15 @@ VSTRING *readlline(VSTRING *buf, VSTREAM *fp, int *lineno)
        start = LEN(buf);
        while ((ch = VSTREAM_GETC(fp)) != VSTREAM_EOF && ch != '\n')
            VSTRING_ADDCH(buf, ch);
-       if (ch == '\n' && lineno != 0)
+       if (lineno != 0 && (ch == '\n' || LEN(buf) > start))
            *lineno += 1;
        /* Ignore comment line, all whitespace line, or empty line. */
        for (cp = STR(buf) + start; cp < END(buf) && ISSPACE(*cp); cp++)
             /* void */ ;
        if (cp == END(buf) || *cp == '#')
            vstring_truncate(buf, start);
+       else if (start == 0 && lineno != 0 && first_line != 0)
+           *first_line = *lineno;
        /* Terminate at EOF or at the beginning of the next logical line. */
        if (ch == VSTREAM_EOF)
            break;
@@ -115,7 +128,7 @@ VSTRING *readlline(VSTRING *buf, VSTREAM *fp, int *lineno)
        msg_warn("%s: logical line must not start with whitespace: \"%.30s%s\"",
                 VSTREAM_PATH(fp), STR(buf),
                 LEN(buf) > 30 ? "..." : "");
-       return (readlline(buf, fp, lineno));
+       return (readllines(buf, fp, lineno, first_line));
     }
 
     /*
index 8a8bd548711fdf7654e12b0c6ce738a206317895..d63cf7d21899c37be435d9924196674bcd8a268c 100644 (file)
@@ -20,7 +20,9 @@
  /*
   * External interface.
   */
-extern VSTRING *readlline(VSTRING *, VSTREAM *, int *);
+extern VSTRING *readllines(VSTRING *, VSTREAM *, int *, int *);
+
+#define readlline(bp, fp, lp) readllines((bp), (fp), (lp), (int *) 0)
 
 /* LICENSE
 /* .ad