]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.5-20190615
authorWietse Venema <wietse@porcupine.org>
Sat, 15 Jun 2019 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Tue, 18 Jun 2019 01:40:39 +0000 (21:40 -0400)
40 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/WISHLIST
postfix/conf/main.cf
postfix/html/lmtp.8.html
postfix/html/postconf.5.html
postfix/html/smtp.8.html
postfix/html/smtpd.8.html
postfix/html/tlsproxy.8.html
postfix/man/man5/postconf.5
postfix/man/man8/smtp.8
postfix/man/man8/smtpd.8
postfix/man/man8/tlsproxy.8
postfix/mantools/postlink
postfix/proto/postconf.proto
postfix/src/global/Makefile.in
postfix/src/global/deliver_request.h
postfix/src/global/mail_params.h
postfix/src/global/mail_version.h
postfix/src/global/reject_deliver_request.c [new file with mode: 0644]
postfix/src/smtp/Makefile.in
postfix/src/smtp/smtp.c
postfix/src/smtp/smtp.h
postfix/src/smtp/smtp_misc.c [new file with mode: 0644]
postfix/src/smtp/smtp_proto.c
postfix/src/smtp/smtp_rcpt.c
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd_check.c
postfix/src/tls/Makefile.in
postfix/src/tls/tls_misc.c
postfix/src/tls/tls_session.c
postfix/src/tlsproxy/tlsproxy.c
postfix/src/util/Makefile.in
postfix/src/util/byte_mask.c [new file with mode: 0644]
postfix/src/util/byte_mask.h [new file with mode: 0644]
postfix/src/util/byte_mask.in [new file with mode: 0644]
postfix/src/util/byte_mask.ref0 [new file with mode: 0644]
postfix/src/util/byte_mask.ref1 [new file with mode: 0644]
postfix/src/util/byte_mask.ref2 [new file with mode: 0644]

index 53b78a05a4b51cf72e9b2d7f48625d897dad53cf..9131c1f7c7a65ce7d01fe0faf634d34387d378c6 100644 (file)
@@ -34,6 +34,7 @@
 -TBOUNCE_TEMPLATES
 -TBOUNCE_TIME_DIVISOR
 -TBOUNCE_TIME_PARAMETER
+-TBYTE_MASK
 -TCFG_PARSER
 -TCIDR_MATCH
 -TCLEANUP_REGION
 -TSMTPD_TOKEN
 -TSMTPD_XFORWARD_ATTR
 -TSMTP_ADDR
+-TSMTP_CLI_ATTR
 -TSMTP_CMD
 -TSMTP_ITERATOR
 -TSMTP_RESP
index 90995d74acd49e60844a607b29f1780fcea699ee..9cfd7fc089cf4450e47046b5ad9c52d0b0b2772b 100644 (file)
@@ -24286,3 +24286,31 @@ Apologies for any names omitted.
        "check_ccert_access { inline:{a=b} { search_order=c,d } }".
        Fixed by adding another level of recursion. File:
        postconf/postconf_dbms.c.
+
+20190525
+
+       Infrastructure: reject_deliver_request() to reject an entire
+       delivery request and bounce or defer all its recipients.
+       File: global/reject_deliver_request.c.
+
+20190609
+
+       Infrastructure: byte_mask() to convert "flags=mumble" into
+       a byte mask. This is similar to name_mask(). Files:
+       util/byte_mask.[hc] and tests.
+
+20190615
+
+       Feature: SMTP/LMTP client support for 'D', 'O', 'R', 'X'
+       flags similar to the pipe(8) daemon, to produce Delivered-To,
+       X-Original-To, and Return-Path headers, and to indicate
+       final delivery. Files: smtp/smtp.c, smtp/smtp.h, smtp/smtp_misc.c,
+       smtp/smtp_proto.c, smtp/smtp_rcpt.c.
+
+       Cleanup: don't wait for the TLS peer to respond after sending
+       a TLS 'close' notification. This should be safe with TLSv1.2
+       and later. Specify "tls_fast_shutdown_enable = no" to enable
+       historical behavior where Postfix waits, and then sends a
+       second TLS 'close' notification before closing the TCP
+       connection. Files: global/mail_params.h, tls/tls_session.c,
+       and documentation.
index 8dded9175a0732155bf1395e5feaecb5f1047786..8a7ebaf40b47e5e577db72e95ef42ce53bf34a56 100644 (file)
@@ -25,6 +25,31 @@ more recent Eclipse Public License 2.0. Recipients can choose to take
 the software under the license of their choice. Those who are more
 comfortable with the IPL can continue with that license.
 
+Incompatibility with snapshot 20190615
+====================================
+
+The Postfix TLS library by default no longer waits after sending a
+TLS 'close' notification. This should be safe with TLSv1.2 and
+later. Specify "tls_fast_shutdown_enable = no" to enable historical
+Postfix behavior.
+
+Major changes with snapshot 20190615
+====================================
+
+After sending a TLS 'close' notification, the Postfix library by
+default no longer waits for the TLS peer to respond. According to
+RFC 2246 (TLSv1.2) section 7.2.1, "It is not required for the
+initiator of the close to wait for the responding close_notify alert
+before closing the read side of the connection."
+
+The SMTP+LMTP delivery agent can now prepend Delivered-To, X-Original-To
+and Return-Path headers, just like the pipe(8) delivery agent. This
+uses the same "flags=DOR" command-line flags in master.cf. See the
+smtp(8) manpage for details.
+
+This obsoletes the "lmtp_assume_final = yes" setting, and replaces
+it with "flags=...X...", for consistency with pipe(8).
+
 Major changes with snapshot 20190517
 ====================================
 
@@ -54,8 +79,9 @@ exact same result:
                 search_order = cert_fingerprint, pubkey_fingerprint } }
         ...
 
-The check_ccert_access search order also supports the subject and
-issuer properties. Support is planned for rfc822name and smtputf8mailbox.
+The check_ccert_access search order also supports the subject_cn and
+issuer_cn properties. Support is planned for rfc822name and
+smtputf8mailbox.
 
 Incompatibility with snapshot 20190427
 ======================================
index 35ab5c7145373bed9eb58aa1879be7ac9a22eaee..ce9c9bea354e2abf689e78bc49a049f05f8e4654 100644 (file)
@@ -1,5 +1,13 @@
 Wish list:
 
+       transport policy protocol (clone of check_policy).
+
+       See also postscreen even-driven client for policy delegation
+       below.
+
+       Replace ad-hoc code for pipe(8) flags handling, with
+       infrastructure that was built for smtp(8).
+
        Things to do before the stable release:
 
        Spell-check, double-word check, HTML validator check,
index 7af8bdeea627e7f8f54de571969364d2d71a63d8..9247ef7be94091a9438293858d34172989701a61 100644 (file)
@@ -249,7 +249,7 @@ unknown_local_recipient_reject_code = 550
 #
 # By default (mynetworks_style = subnet), Postfix "trusts" SMTP
 # clients in the same IP subnetworks as the local machine.
-# On Linux, this does works correctly only with interfaces specified
+# On Linux, this works correctly only with interfaces specified
 # with the "ifconfig" command.
 # 
 # Specify "mynetworks_style = class" when Postfix should "trust" SMTP
index e02d8980709f9a026668c8b2fca6998b96c4b8cf..175b103944ad0bea80f46bc0c20a5a94bdc41ad0 100644 (file)
@@ -10,7 +10,7 @@ SMTP(8)                                                                SMTP(8)
        smtp - Postfix SMTP+LMTP client
 
 <b>SYNOPSIS</b>
-       <b>smtp</b> [generic Postfix daemon options]
+       <b>smtp</b> [generic Postfix daemon options] [flags=DORX]
 
 <b>DESCRIPTION</b>
        The Postfix SMTP+LMTP client implements the SMTP and LMTP mail delivery
@@ -84,10 +84,58 @@ SMTP(8)                                                                SMTP(8)
               will   be   used.    An   IPv6  address  must  be  formatted  as
               [<b>ipv6</b>:<i>address</i>].
 
+<b>SINGLE-RECIPIENT DELIVERY</b>
+       By default, the Postfix SMTP+LMTP  client  delivers  mail  to  multiple
+       recipients  per delivery request. This is undesirable when prepending a
+       <b>Delivered-to:</b> or <b>X-Original-To:</b> message header. To prevent Postfix from
+       sending multiple recipients per delivery request, specify
+
+           <b><a href="postconf.5.html#transport_destination_recipient_limit"><i>transport</i>_destination_recipient_limit</a> = 1</b>
+
+       in  the  Postfix <a href="postconf.5.html"><b>main.cf</b></a> file, where <i>transport</i> is the name in the first
+       column of the Postfix  <a href="master.5.html"><b>master.cf</b></a>  entry  for  the  pipe-based  delivery
+       transport.
+
+<b>COMMAND ATTRIBUTE SYNTAX</b>
+       <b>flags=DORX</b> (optional)
+              Optional message processing flags.
+
+              <b>D</b>      Prepend  a  "<b>Delivered-To:</b> <i>recipient</i>" message header with
+                     the envelope recipient address. Note: for this  to  work,
+                     the  <b><a href="postconf.5.html#transport_destination_recipient_limit"><i>transport</i>_destination_recipient_limit</a></b> must be 1 (see
+                     SINGLE-RECIPIENT DELIVERY above for details).
+
+                     The <b>D</b> flag also enforces loop  detection:  if  a  message
+                     already  contains  a  <b>Delivered-To:</b>  header with the same
+                     recipient address, then the message is returned as  unde-
+                     liverable. The address comparison is case insensitive.
+
+                     This feature is available as of Postfix 3.5.
+
+              <b>O</b>      Prepend an "<b>X-Original-To:</b> <i>recipient</i>" message header with
+                     the recipient address as given to Postfix. Note: for this
+                     to  work,  the <b><a href="postconf.5.html#transport_destination_recipient_limit"><i>transport</i>_destination_recipient_limit</a></b> must
+                     be 1 (see SINGLE-RECIPIENT DELIVERY above for details).
+
+                     This feature is available as of Postfix 3.5.
+
+              <b>R</b>      Prepend a "<b>Return-Path:</b> &lt;<i>sender</i>&gt;" message header with the
+                     envelope sender address.
+
+                     This feature is available as of Postfix 3.5.
+
+              <b>X</b>      Indicates  that  the delivery is final. This flag affects
+                     the status reported in  "success"  DSN  (delivery  status
+                     notification)  messages,  and  changes  it from "relayed"
+                     into "delivered".
+
+                     This feature is available as of Postfix 3.5.
+
 <b>SECURITY</b>
-       The SMTP+LMTP client is moderately security-sensitive. It talks to SMTP
-       or LMTP servers and to DNS servers on the network. The SMTP+LMTP client
-       can be run chrooted at fixed low privilege.
+       The SMTP+LMTP client is moderately security-sensitive. It
+       talks to SMTP or LMTP servers and to DNS servers on the
+       network. The SMTP+LMTP client can be run chrooted at fixed
+       low privilege.
 
 <b>STANDARDS</b>
        <a href="http://tools.ietf.org/html/rfc821">RFC 821</a> (SMTP protocol)
@@ -120,13 +168,11 @@ SMTP(8)                                                                SMTP(8)
        ter is notified of bounces, protocol problems, and of other trouble.
 
 <b>BUGS</b>
-       SMTP  and LMTP connection caching does not work with TLS. The necessary
-       support for TLS object passivation and  re-activation  does  not  exist
-       without closing the session, which defeats the purpose.
+       SMTP  and  LMTP  connection  reuse for TLS (without closing the SMTP or
+       LMTP connection) is not supported before Postfix 3.4.
 
-       SMTP  and  LMTP  connection  caching  assumes that SASL credentials are
-       valid for all destinations that map onto the same IP  address  and  TCP
-       port.
+       SMTP and LMTP connection reuse assumes that SASL credentials are  valid
+       for all destinations that map onto the same IP address and TCP port.
 
 <b>CONFIGURATION PARAMETERS</b>
        Before  Postfix version 2.3, the LMTP client is a separate program that
@@ -595,6 +641,13 @@ SMTP(8)                                                                SMTP(8)
               Optional  name  to  send  to  the  remote SMTP server in the TLS
               Server Name Indication (SNI) extension.
 
+       Available in Postfix version 3.5 and later:
+
+       <b><a href="postconf.5.html#tls_fast_shutdown_enable">tls_fast_shutdown_enable</a> (yes)</b>
+              After sending a TLS 'close' notification, do not  wait  for  the
+              TLS  peer to respond, and do not send a second TLS 'close' noti-
+              fication.
+
 <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 33840234a20259272b8690be6b883a6e878ce2d3..7d5c900ccf3ba6221c7f51a81039b299bbec8d24 100644 (file)
@@ -14200,11 +14200,12 @@ Postfix version 2.5).  This feature is available with Postfix version
 order (Postfix 3.5 and later). The default search order as described
 above corresponds with: </dd>
 
-<dd> <a href="postconf.5.html#check_ccert_access">check_ccert_access</a> { <a href="DATABASE_README.html">type:table</a> { search_order = cert_fingerprint,
+<dd> <a href="postconf.5.html#check_ccert_access">check_ccert_access</a> { <a href="DATABASE_README.html">type:table</a>, { search_order = cert_fingerprint,
 pubkey_fingerprint } } </dd>
 
-<dd> Other valid search_order elements are "subject" (the certificate
-subject DN) and "issuer" (the certificate issuer DN). </dd>
+<dd> The commas are optional. Other valid search_order elements are
+"subject_cn" (the certificate subject CN) and "issuer_cn" (the
+certificate issuer CN). </dd>
 
 <dt><b><a name="check_client_access">check_client_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
 
@@ -18542,6 +18543,21 @@ encouraged to not change this setting.  </p>
 <p> This feature is available in Postfix 2.3 and later. </p>
 
 
+</DD>
+
+<DT><b><a name="tls_fast_shutdown_enable">tls_fast_shutdown_enable</a>
+(default: yes)</b></DT><DD>
+
+<p> After sending a TLS 'close' notification, do not wait for the
+TLS peer to respond, and do not send a second TLS 'close' notification.
+According to <a href="http://tools.ietf.org/html/rfc2246">RFC 2246</a> (TLSv1.2) section 7.2.1, "It is not required
+for the initiator of the close to wait for the responding close_notify
+alert before closing the read side of the connection." </p>
+
+<p> Specify "<a href="postconf.5.html#tls_fast_shutdown_enable">tls_fast_shutdown_enable</a> = no" to enable historical
+Postfix behavior.  </p>
+
+
 </DD>
 
 <DT><b><a name="tls_high_cipherlist">tls_high_cipherlist</a>
index e02d8980709f9a026668c8b2fca6998b96c4b8cf..175b103944ad0bea80f46bc0c20a5a94bdc41ad0 100644 (file)
@@ -10,7 +10,7 @@ SMTP(8)                                                                SMTP(8)
        smtp - Postfix SMTP+LMTP client
 
 <b>SYNOPSIS</b>
-       <b>smtp</b> [generic Postfix daemon options]
+       <b>smtp</b> [generic Postfix daemon options] [flags=DORX]
 
 <b>DESCRIPTION</b>
        The Postfix SMTP+LMTP client implements the SMTP and LMTP mail delivery
@@ -84,10 +84,58 @@ SMTP(8)                                                                SMTP(8)
               will   be   used.    An   IPv6  address  must  be  formatted  as
               [<b>ipv6</b>:<i>address</i>].
 
+<b>SINGLE-RECIPIENT DELIVERY</b>
+       By default, the Postfix SMTP+LMTP  client  delivers  mail  to  multiple
+       recipients  per delivery request. This is undesirable when prepending a
+       <b>Delivered-to:</b> or <b>X-Original-To:</b> message header. To prevent Postfix from
+       sending multiple recipients per delivery request, specify
+
+           <b><a href="postconf.5.html#transport_destination_recipient_limit"><i>transport</i>_destination_recipient_limit</a> = 1</b>
+
+       in  the  Postfix <a href="postconf.5.html"><b>main.cf</b></a> file, where <i>transport</i> is the name in the first
+       column of the Postfix  <a href="master.5.html"><b>master.cf</b></a>  entry  for  the  pipe-based  delivery
+       transport.
+
+<b>COMMAND ATTRIBUTE SYNTAX</b>
+       <b>flags=DORX</b> (optional)
+              Optional message processing flags.
+
+              <b>D</b>      Prepend  a  "<b>Delivered-To:</b> <i>recipient</i>" message header with
+                     the envelope recipient address. Note: for this  to  work,
+                     the  <b><a href="postconf.5.html#transport_destination_recipient_limit"><i>transport</i>_destination_recipient_limit</a></b> must be 1 (see
+                     SINGLE-RECIPIENT DELIVERY above for details).
+
+                     The <b>D</b> flag also enforces loop  detection:  if  a  message
+                     already  contains  a  <b>Delivered-To:</b>  header with the same
+                     recipient address, then the message is returned as  unde-
+                     liverable. The address comparison is case insensitive.
+
+                     This feature is available as of Postfix 3.5.
+
+              <b>O</b>      Prepend an "<b>X-Original-To:</b> <i>recipient</i>" message header with
+                     the recipient address as given to Postfix. Note: for this
+                     to  work,  the <b><a href="postconf.5.html#transport_destination_recipient_limit"><i>transport</i>_destination_recipient_limit</a></b> must
+                     be 1 (see SINGLE-RECIPIENT DELIVERY above for details).
+
+                     This feature is available as of Postfix 3.5.
+
+              <b>R</b>      Prepend a "<b>Return-Path:</b> &lt;<i>sender</i>&gt;" message header with the
+                     envelope sender address.
+
+                     This feature is available as of Postfix 3.5.
+
+              <b>X</b>      Indicates  that  the delivery is final. This flag affects
+                     the status reported in  "success"  DSN  (delivery  status
+                     notification)  messages,  and  changes  it from "relayed"
+                     into "delivered".
+
+                     This feature is available as of Postfix 3.5.
+
 <b>SECURITY</b>
-       The SMTP+LMTP client is moderately security-sensitive. It talks to SMTP
-       or LMTP servers and to DNS servers on the network. The SMTP+LMTP client
-       can be run chrooted at fixed low privilege.
+       The SMTP+LMTP client is moderately security-sensitive. It
+       talks to SMTP or LMTP servers and to DNS servers on the
+       network. The SMTP+LMTP client can be run chrooted at fixed
+       low privilege.
 
 <b>STANDARDS</b>
        <a href="http://tools.ietf.org/html/rfc821">RFC 821</a> (SMTP protocol)
@@ -120,13 +168,11 @@ SMTP(8)                                                                SMTP(8)
        ter is notified of bounces, protocol problems, and of other trouble.
 
 <b>BUGS</b>
-       SMTP  and LMTP connection caching does not work with TLS. The necessary
-       support for TLS object passivation and  re-activation  does  not  exist
-       without closing the session, which defeats the purpose.
+       SMTP  and  LMTP  connection  reuse for TLS (without closing the SMTP or
+       LMTP connection) is not supported before Postfix 3.4.
 
-       SMTP  and  LMTP  connection  caching  assumes that SASL credentials are
-       valid for all destinations that map onto the same IP  address  and  TCP
-       port.
+       SMTP and LMTP connection reuse assumes that SASL credentials are  valid
+       for all destinations that map onto the same IP address and TCP port.
 
 <b>CONFIGURATION PARAMETERS</b>
        Before  Postfix version 2.3, the LMTP client is a separate program that
@@ -595,6 +641,13 @@ SMTP(8)                                                                SMTP(8)
               Optional  name  to  send  to  the  remote SMTP server in the TLS
               Server Name Indication (SNI) extension.
 
+       Available in Postfix version 3.5 and later:
+
+       <b><a href="postconf.5.html#tls_fast_shutdown_enable">tls_fast_shutdown_enable</a> (yes)</b>
+              After sending a TLS 'close' notification, do not  wait  for  the
+              TLS  peer to respond, and do not send a second TLS 'close' noti-
+              fication.
+
 <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 191fe63b6805a14b177df1f511cb9ea0a07510e6..43e98f02a3e86662ad63d5347b94e8ba2ab9fe28 100644 (file)
@@ -589,6 +589,13 @@ SMTPD(8)                                                              SMTPD(8)
               clients via the TLS Server Name Indication  (SNI)  extension  to
               the appropriate keys and certificate chains.
 
+       Available in Postfix version 3.5 and later:
+
+       <b><a href="postconf.5.html#tls_fast_shutdown_enable">tls_fast_shutdown_enable</a> (yes)</b>
+              After  sending  a  TLS 'close' notification, do not wait for the
+              TLS peer to respond, and do not send a second TLS 'close'  noti-
+              fication.
+
 <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 25016ce577d42271538afb93a056f882ecc4ab0a..49fee4bd7e518956d7ce0fbe85e436ffc6052a83 100644 (file)
@@ -144,6 +144,13 @@ TLSPROXY(8)                                                        TLSPROXY(8)
               clients via the TLS Server Name Indication  (SNI)  extension  to
               the appropriate keys and certificate chains.
 
+       Available in Postfix version 3.5 and later:
+
+       <b><a href="postconf.5.html#tls_fast_shutdown_enable">tls_fast_shutdown_enable</a> (yes)</b>
+              After  sending  a  TLS 'close' notification, do not wait for the
+              TLS peer to respond, and do not send a second TLS 'close'  noti-
+              fication.
+
 <b>STARTTLS SERVER CONTROLS</b>
        These  settings are clones of Postfix SMTP server settings.  They allow
        <a href="tlsproxy.8.html"><b>tlsproxy</b>(8)</a> to load the same certificate and private key information as
index 4093ad0b66154168e9602014a076a059fd468c76..a32ec971f6556125e024e633a3745b0cf396adc4 100644 (file)
@@ -12942,6 +12942,15 @@ the default cipherlist for the SMTP server. You are strongly
 encouraged to not change this setting.
 .PP
 This feature is available in Postfix 2.3 and later.
+.SH tls_fast_shutdown_enable (default: yes)
+After sending a TLS 'close' notification, do not wait for the
+TLS peer to respond, and do not send a second TLS 'close' notification.
+According to RFC 2246 (TLSv1.2) section 7.2.1, "It is not required
+for the initiator of the close to wait for the responding close_notify
+alert before closing the read side of the connection."
+.PP
+Specify "tls_fast_shutdown_enable = no" to enable historical
+Postfix behavior.
 .SH tls_high_cipherlist (default: see "postconf \-d" output)
 The OpenSSL cipherlist for "high" grade ciphers. This defines
 the meaning of the "high" setting in smtpd_tls_ciphers,
index ca81ebc48d64a77501eb37881b13acb4a8698f1b..2edbe5f0ee235d85284f7ad7d0d540ae8fffe7a9 100644 (file)
@@ -8,7 +8,7 @@ Postfix SMTP+LMTP client
 .SH "SYNOPSIS"
 .na
 .nf
-\fBsmtp\fR [generic Postfix daemon options]
+\fBsmtp\fR [generic Postfix daemon options] [flags=DORX]
 .SH DESCRIPTION
 .ad
 .fi
@@ -80,12 +80,68 @@ remote host. If no port is specified, connect to the port defined as
 If no such service is found, the \fBlmtp_tcp_port\fR configuration
 parameter (default value of 24) will be used.
 An IPv6 address must be formatted as [\fBipv6\fR:\fIaddress\fR].
-.PP
-.SH "SECURITY"
+.SH "SINGLE-RECIPIENT DELIVERY"
 .na
 .nf
 .ad
 .fi
+By default, the Postfix SMTP+LMTP client delivers mail to
+multiple recipients per delivery request. This is undesirable
+when prepending a \fBDelivered\-to:\fR or \fBX\-Original\-To:\fR
+message header. To prevent Postfix from sending multiple
+recipients per delivery request, specify
+.sp
+.nf
+    \fItransport\fB_destination_recipient_limit = 1\fR
+.fi
+
+in the Postfix \fBmain.cf\fR file, where \fItransport\fR
+is the name in the first column of the Postfix \fBmaster.cf\fR
+entry for the pipe\-based delivery transport.
+.SH "COMMAND ATTRIBUTE SYNTAX"
+.na
+.nf
+.ad
+.fi
+.IP "\fBflags=DORX\fR (optional)"
+Optional message processing flags.
+.RS
+.IP \fBD\fR
+Prepend a "\fBDelivered\-To: \fIrecipient\fR" message header
+with the envelope recipient address. Note: for this to work,
+the \fItransport\fB_destination_recipient_limit\fR must be
+1 (see SINGLE\-RECIPIENT DELIVERY above for details).
+.sp
+The \fBD\fR flag also enforces loop detection: if a message
+already contains a \fBDelivered\-To:\fR header with the same
+recipient address, then the message is returned as
+undeliverable. The address comparison is case insensitive.
+.sp
+This feature is available as of Postfix 3.5.
+.IP \fBO\fR
+Prepend an "\fBX\-Original\-To: \fIrecipient\fR" message
+header with the recipient address as given to Postfix. Note:
+for this to work, the
+\fItransport\fB_destination_recipient_limit\fR must be 1
+(see SINGLE\-RECIPIENT DELIVERY above for details).
+.sp
+This feature is available as of Postfix 3.5.
+.IP \fBR\fR
+Prepend a "\fBReturn\-Path: <\fIsender\fB>\fR" message header
+with the envelope sender address.
+.sp
+This feature is available as of Postfix 3.5.
+.IP \fBX\fR
+Indicates that the delivery is final. This flag affects
+the status reported in "success" DSN (delivery status
+notification) messages, and changes it from "relayed" into
+"delivered".
+.sp
+This feature is available as of Postfix 3.5.
+.RE
+.SH "SECURITY"
+.na
+.nf
 The SMTP+LMTP client is moderately security\-sensitive. It
 talks to SMTP or LMTP servers and to DNS servers on the
 network. The SMTP+LMTP client can be run chrooted at fixed
@@ -526,6 +582,11 @@ directly followed by a corresponding certificate chain.
 .IP "\fBsmtp_tls_servername (empty)\fR"
 Optional name to send to the remote SMTP server in the TLS Server
 Name Indication (SNI) extension.
+.PP
+Available in Postfix version 3.5 and later:
+.IP "\fBtls_fast_shutdown_enable (yes)\fR"
+After sending a TLS 'close' notification, do not wait for the
+TLS peer to respond, and do not send a second TLS 'close' notification.
 .SH "OBSOLETE STARTTLS CONTROLS"
 .na
 .nf
index 1ea172fdfc24e44d668b1733ded1356b26fd6832..e03a4b056163cb23b05bfde4ece89affd9a8f4b9 100644 (file)
@@ -527,6 +527,11 @@ directly followed by a corresponding certificate chain.
 Optional lookup tables that map names received from remote SMTP
 clients via the TLS Server Name Indication (SNI) extension to the
 appropriate keys and certificate chains.
+.PP
+Available in Postfix version 3.5 and later:
+.IP "\fBtls_fast_shutdown_enable (yes)\fR"
+After sending a TLS 'close' notification, do not wait for the
+TLS peer to respond, and do not send a second TLS 'close' notification.
 .SH "OBSOLETE STARTTLS CONTROLS"
 .na
 .nf
index 71a3e4e8da0f7702a8c9565a058b397765262dfe..fd46a1c56e93e34b9e62f8959ef934a9abd7bd80 100644 (file)
@@ -145,6 +145,11 @@ Available in Postfix version 3.4 and later:
 Optional lookup tables that map names received from remote SMTP
 clients via the TLS Server Name Indication (SNI) extension to the
 appropriate keys and certificate chains.
+.PP
+Available in Postfix version 3.5 and later:
+.IP "\fBtls_fast_shutdown_enable (yes)\fR"
+After sending a TLS 'close' notification, do not wait for the
+TLS peer to respond, and do not send a second TLS 'close' notification.
 .SH "STARTTLS SERVER CONTROLS"
 .na
 .nf
index e2749fe9bac33ac5c23c17862bc27a665687d370..4d5817d2a18dbfd86dc37aa9d08d28b0c3cec594 100755 (executable)
@@ -765,6 +765,7 @@ while (<>) {
     s;\btls_ssl_options\b;<a href="postconf.5.html#tls_ssl_options">$&</a>;g;
     s;\btls_dane_digest_agility\b;<a href="postconf.5.html#tls_dane_digest_agility">$&</a>;g;
     s;\btls_dane_trust_anchor_digest_enable\b;<a href="postconf.5.html#tls_dane_trust_anchor_digest_enable">$&</a>;g;
+    s;\btls_fast_shutdown_enable\b;<a href="postconf.5.html#tls_fast_shutdown_enable">$&</a>;g;
 
     s;\bfrozen_delivered_to\b;<a href="postconf.5.html#frozen_delivered_to">$&</a>;g;
     s;\breset_owner_alias\b;<a href="postconf.5.html#reset_owner_alias">$&</a>;g;
index 24291cc4d64ac8aff32b2ab46065e630b5d8821c..df44d0c797ec80c38809533cd0469b81c62a3364 100644 (file)
@@ -5115,11 +5115,12 @@ Postfix version 2.5).  This feature is available with Postfix version
 order (Postfix 3.5 and later). The default search order as described
 above corresponds with: </dd>
 
-<dd> check_ccert_access { type:table { search_order = cert_fingerprint,
+<dd> check_ccert_access { type:table, { search_order = cert_fingerprint,
 pubkey_fingerprint } } </dd>
 
-<dd> Other valid search_order elements are "subject" (the certificate
-subject DN) and "issuer" (the certificate issuer DN). </dd>
+<dd> The commas are optional. Other valid search_order elements are
+"subject_cn" (the certificate subject CN) and "issuer_cn" (the
+certificate issuer CN). </dd>
 
 <dt><b><a name="check_client_access">check_client_access</a> <i><a href="DATABASE_README.html">type:table</a></i></b></dt>
 
@@ -17621,3 +17622,14 @@ default suffix, YYYYMMDD-HHMMSS, allows logs to be rotated frequently.
 </p>
 
 <p> This feature is available in Postfix 3.4 and later. </p>
+
+%PARAM tls_fast_shutdown_enable yes
+
+<p> After sending a TLS 'close' notification, do not wait for the
+TLS peer to respond, and do not send a second TLS 'close' notification.
+According to RFC 2246 (TLSv1.2) section 7.2.1, "It is not required
+for the initiator of the close to wait for the responding close_notify
+alert before closing the read side of the connection." </p>
+
+<p> Specify "tls_fast_shutdown_enable = no" to enable historical
+Postfix behavior.  </p>
index 8dc1f696e5ff0866030d6a4de3ac364ab67a0396..6577d287f80cb5dd72de3801e68453e196329ed5 100644 (file)
@@ -35,7 +35,7 @@ SRCS  = abounce.c anvil_clnt.c been_here.c bounce.c bounce_log.c \
        mkmap_fail.c haproxy_srvr.c dsn_filter.c dynamicmaps.c uxtext.c \
        smtputf8.c mail_conf_over.c mail_parm_split.c midna_adomain.c \
        mail_addr_form.c quote_flags.c maillog_client.c \
-       normalize_mailhost_addr.c map_search.c
+       normalize_mailhost_addr.c map_search.c reject_deliver_request.c
 OBJS   = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
        canon_addr.o cfg_parser.o cleanup_strerror.o cleanup_strflags.o \
        clnt_stream.o conv_time.o db_common.o debug_peer.o debug_process.o \
@@ -72,7 +72,7 @@ OBJS  = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
        mkmap_fail.o haproxy_srvr.o dsn_filter.o dynamicmaps.o uxtext.o \
        smtputf8.o attr_override.o mail_parm_split.o midna_adomain.o \
        $(NON_PLUGIN_MAP_OBJ) mail_addr_form.o quote_flags.o maillog_client.o \
-       normalize_mailhost_addr.o map_search.o
+       normalize_mailhost_addr.o map_search.o reject_deliver_request.o
 # MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf.
 # When hard-linking these maps, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ),
 # otherwise it sets the PLUGIN_* macros.
@@ -2462,6 +2462,25 @@ record.o: off_cvt.h
 record.o: rec_type.h
 record.o: record.c
 record.o: record.h
+reject_deliver_request.o: ../../include/attr.h
+reject_deliver_request.o: ../../include/check_arg.h
+reject_deliver_request.o: ../../include/htable.h
+reject_deliver_request.o: ../../include/msg.h
+reject_deliver_request.o: ../../include/mymalloc.h
+reject_deliver_request.o: ../../include/nvtable.h
+reject_deliver_request.o: ../../include/sys_defs.h
+reject_deliver_request.o: ../../include/vbuf.h
+reject_deliver_request.o: ../../include/vstream.h
+reject_deliver_request.o: ../../include/vstring.h
+reject_deliver_request.o: bounce.h
+reject_deliver_request.o: defer.h
+reject_deliver_request.o: deliver_completed.h
+reject_deliver_request.o: deliver_request.h
+reject_deliver_request.o: dsn.h
+reject_deliver_request.o: dsn_buf.h
+reject_deliver_request.o: msg_stats.h
+reject_deliver_request.o: recipient_list.h
+reject_deliver_request.o: reject_deliver_request.c
 remove.o: ../../include/check_arg.h
 remove.o: ../../include/sys_defs.h
 remove.o: ../../include/vbuf.h
index 0dd25734eabbc889346f3aeac75faea07f490719..a00bcf7a2fa68e1852a4744624c070bc7e6f5aa2 100644 (file)
 /* DESCRIPTION
 /* .nf
 
+ /*
+  * System library.
+  */
+#include <sys_defs.h>
+#include <stdarg.h>
+
  /*
   * Utility library.
   */
@@ -128,6 +134,9 @@ typedef struct VSTREAM _deliver_vstream_;
 extern DELIVER_REQUEST *deliver_request_read(_deliver_vstream_ *);
 extern int deliver_request_done(_deliver_vstream_ *, DELIVER_REQUEST *, int);
 
+extern int PRINTFLIKE(4, 5) reject_deliver_request(const char *,
+                        DELIVER_REQUEST *, const char *, const char *,...);
+
 /* LICENSE
 /* .ad
 /* .fi
index 638daa15d39e19f99f1c9e9611d73cc1b8bb835f..258c5dcad3a72fc9aaf61058dcde6209372a4031 100644 (file)
@@ -3330,6 +3330,13 @@ extern char *var_tls_server_sni_maps;
 #define DEF_TLS_DANE_DIGESTS   "sha512 sha256"
 extern char *var_tls_dane_digests;
 
+ /*
+  * Backwards compatibility for Postfix 3.5 and later.
+  */
+#define VAR_TLS_FAST_SHUTDOWN  "tls_fast_shutdown"
+#define DEF_TLS_FAST_SHUTDOWN  1
+extern bool var_tls_fast_shutdown;
+
  /*
   * Sendmail-style mail filter support.
   */
index 713ba8ec81678f31071839a4cd9c6363c66f4213..adfb936e0f5b788f10ce03d2124f798618ae4fa0 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      "20190518"
+#define MAIL_RELEASE_DATE      "20190615"
 #define MAIL_VERSION_NUMBER    "3.5"
 
 #ifdef SNAPSHOT
diff --git a/postfix/src/global/reject_deliver_request.c b/postfix/src/global/reject_deliver_request.c
new file mode 100644 (file)
index 0000000..1b1b2a5
--- /dev/null
@@ -0,0 +1,105 @@
+/*++
+/* NAME
+/*     reject_deliver_request 3
+/* SUMMARY
+/*     reject an entire delivery request
+/* SYNOPSIS
+/*     #include <reject_deliver_request.h>
+/*
+/*     int     reject_deliver_request(
+/*     const char *service,
+/*     DELIVER_REQUEST *request,
+/*     const char *code,
+/*     const char *format, ...);
+/* DESCRIPTION
+/*     reject_deliver_request() rejects an entire delivery request
+/*     and bounces or defers all its recipients. The result value
+/*     is the request's delivery status.
+/*
+/*     Arguments:
+/* .IP service
+/*     The service name from master.cf.
+/* .IP request
+/*     The delivery request that is being rejected.
+/* .IP code
+/*     Enhanced status code, must be in 4.X.X or 5.X.X. form.
+/*     All recipients in the request are bounced or deferred
+/*     depending on the status code value.
+/* .IP "format, ..."
+/*     Format string and optional arguments.
+/* DIAGNOSTICS
+/*     Panic: interface violation. Fatal: out of memory.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
+/*--*/
+
+ /*
+  * System library.
+  */
+#include <sys_defs.h>
+#include <string.h>
+
+ /*
+  * Utility library.
+  */
+#include <msg.h>
+
+ /*
+  * Global library.
+  */
+#include <bounce.h>
+#include <defer.h>
+#include <deliver_completed.h>
+#include <deliver_request.h>
+#include <recipient_list.h>
+
+/* reject_deliver_request - reject an entire delivery request */
+
+int     reject_deliver_request(const char *service, DELIVER_REQUEST *request,
+                                      const char *code,
+                                      const char *format,...)
+{
+    const char myname[] = "reject_deliver_request";
+    va_list ap;
+    RECIPIENT *rcpt;
+    DSN_BUF *why;
+    int     status;
+    int     result = 0;
+    int     n;
+
+    /*
+     * Format something that we can pass to bounce_append() or
+     * defer_append().
+     */
+    va_start(ap, format);
+    why = vdsb_simple(dsb_create(), code, format, ap);
+    va_end(ap);
+    (void) DSN_FROM_DSN_BUF(why);
+    if (strchr("45", vstring_str(why->status)[0]) == 0)
+       msg_panic("%s: bad enhanced status code %s", myname, code);
+
+    /*
+     * Blindly bounce or defer all recipients.
+     */
+    for (n = 0; n < request->rcpt_list.len; n++) {
+       rcpt = request->rcpt_list.info + n;
+       status = (vstring_str(why->status)[0] != '4' ?
+                 bounce_append : defer_append)
+           (DEL_REQ_TRACE_FLAGS(request->flags),
+            request->queue_id,
+            &request->msg_stats, rcpt,
+            service, &why->dsn);
+       if (status == 0)
+           deliver_completed(request->fp, rcpt->offset);
+       result |= status;
+    }
+    dsb_free(why);
+    return (result);
+}
index 7d455649699ff5f65d1be592e25524522874dda0..140192f89ae181b4e46016d2093500c845dfc54d 100644 (file)
@@ -2,11 +2,11 @@ SHELL = /bin/sh
 SRCS   = smtp.c smtp_connect.c smtp_proto.c smtp_chat.c smtp_session.c \
        smtp_addr.c smtp_trouble.c smtp_state.c smtp_rcpt.c smtp_tls_policy.c \
        smtp_sasl_proto.c smtp_sasl_glue.c smtp_reuse.c smtp_map11.c \
-       smtp_sasl_auth_cache.c smtp_key.c
+       smtp_sasl_auth_cache.c smtp_key.c smtp_misc.c
 OBJS   = smtp.o smtp_connect.o smtp_proto.o smtp_chat.o smtp_session.o \
        smtp_addr.o smtp_trouble.o smtp_state.o smtp_rcpt.o smtp_tls_policy.o \
        smtp_sasl_proto.o smtp_sasl_glue.o smtp_reuse.o smtp_map11.o \
-       smtp_sasl_auth_cache.o smtp_key.o
+       smtp_sasl_auth_cache.o smtp_key.o smtp_misc.o
 HDRS   = smtp.h smtp_sasl.h smtp_addr.h smtp_reuse.h smtp_sasl_auth_cache.h
 TESTSRC        = 
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
@@ -89,6 +89,7 @@ depend: $(MAKES)
 lmtp_params.o: lmtp_params.c
 smtp.o: ../../include/argv.h
 smtp.o: ../../include/attr.h
+smtp.o: ../../include/byte_mask.h
 smtp.o: ../../include/check_arg.h
 smtp.o: ../../include/debug_peer.h
 smtp.o: ../../include/deliver_request.h
@@ -358,6 +359,46 @@ smtp_map11.o: ../../include/vstream.h
 smtp_map11.o: ../../include/vstring.h
 smtp_map11.o: smtp.h
 smtp_map11.o: smtp_map11.c
+smtp_misc.o: ../../include/argv.h
+smtp_misc.o: ../../include/attr.h
+smtp_misc.o: ../../include/check_arg.h
+smtp_misc.o: ../../include/deliver_request.h
+smtp_misc.o: ../../include/dict.h
+smtp_misc.o: ../../include/dns.h
+smtp_misc.o: ../../include/dsn.h
+smtp_misc.o: ../../include/dsn_buf.h
+smtp_misc.o: ../../include/ext_prop.h
+smtp_misc.o: ../../include/header_body_checks.h
+smtp_misc.o: ../../include/header_opts.h
+smtp_misc.o: ../../include/htable.h
+smtp_misc.o: ../../include/mail_params.h
+smtp_misc.o: ../../include/maps.h
+smtp_misc.o: ../../include/match_list.h
+smtp_misc.o: ../../include/mime_state.h
+smtp_misc.o: ../../include/msg_stats.h
+smtp_misc.o: ../../include/myaddrinfo.h
+smtp_misc.o: ../../include/myflock.h
+smtp_misc.o: ../../include/mymalloc.h
+smtp_misc.o: ../../include/name_code.h
+smtp_misc.o: ../../include/name_mask.h
+smtp_misc.o: ../../include/nvtable.h
+smtp_misc.o: ../../include/quote_821_local.h
+smtp_misc.o: ../../include/quote_822_local.h
+smtp_misc.o: ../../include/quote_flags.h
+smtp_misc.o: ../../include/recipient_list.h
+smtp_misc.o: ../../include/resolve_clnt.h
+smtp_misc.o: ../../include/scache.h
+smtp_misc.o: ../../include/sock_addr.h
+smtp_misc.o: ../../include/string_list.h
+smtp_misc.o: ../../include/sys_defs.h
+smtp_misc.o: ../../include/tls.h
+smtp_misc.o: ../../include/tls_proxy.h
+smtp_misc.o: ../../include/tok822.h
+smtp_misc.o: ../../include/vbuf.h
+smtp_misc.o: ../../include/vstream.h
+smtp_misc.o: ../../include/vstring.h
+smtp_misc.o: smtp.h
+smtp_misc.o: smtp_misc.c
 smtp_params.o: smtp_params.c
 smtp_proto.o: ../../include/argv.h
 smtp_proto.o: ../../include/attr.h
@@ -397,7 +438,6 @@ smtp_proto.o: ../../include/name_code.h
 smtp_proto.o: ../../include/name_mask.h
 smtp_proto.o: ../../include/nvtable.h
 smtp_proto.o: ../../include/off_cvt.h
-smtp_proto.o: ../../include/quote_821_local.h
 smtp_proto.o: ../../include/quote_822_local.h
 smtp_proto.o: ../../include/quote_flags.h
 smtp_proto.o: ../../include/rec_type.h
index 4e50699f84ddb6f89c613a3e002a0f984b005a2e..2d57578750b6eac16feb485a6c53939ef123b3dd 100644 (file)
@@ -4,7 +4,7 @@
 /* SUMMARY
 /*     Postfix SMTP+LMTP client
 /* SYNOPSIS
-/*     \fBsmtp\fR [generic Postfix daemon options]
+/*     \fBsmtp\fR [generic Postfix daemon options] [flags=DORX]
 /* DESCRIPTION
 /*     The Postfix SMTP+LMTP client implements the SMTP and LMTP mail
 /*     delivery protocols. It processes message delivery requests from
 /*     If no such service is found, the \fBlmtp_tcp_port\fR configuration
 /*     parameter (default value of 24) will be used.
 /*     An IPv6 address must be formatted as [\fBipv6\fR:\fIaddress\fR].
-/* .PP
-/* SECURITY
+/* SINGLE-RECIPIENT DELIVERY
+/* .ad
+/* .fi
+/*     By default, the Postfix SMTP+LMTP client delivers mail to
+/*     multiple recipients per delivery request. This is undesirable
+/*     when prepending a \fBDelivered-to:\fR or \fBX-Original-To:\fR
+/*     message header. To prevent Postfix from sending multiple
+/*     recipients per delivery request, specify
+/* .sp
+/* .nf
+/*         \fItransport\fB_destination_recipient_limit = 1\fR
+/* .fi
+/*
+/*     in the Postfix \fBmain.cf\fR file, where \fItransport\fR
+/*     is the name in the first column of the Postfix \fBmaster.cf\fR
+/*     entry for the pipe-based delivery transport.
+/* COMMAND ATTRIBUTE SYNTAX
 /* .ad
 /* .fi
+/* .IP "\fBflags=DORX\fR (optional)"
+/*     Optional message processing flags.
+/* .RS
+/* .IP \fBD\fR
+/*     Prepend a "\fBDelivered-To: \fIrecipient\fR" message header
+/*     with the envelope recipient address. Note: for this to work,
+/*     the \fItransport\fB_destination_recipient_limit\fR must be
+/*     1 (see SINGLE-RECIPIENT DELIVERY above for details).
+/* .sp
+/*     The \fBD\fR flag also enforces loop detection: if a message
+/*     already contains a \fBDelivered-To:\fR header with the same
+/*     recipient address, then the message is returned as
+/*     undeliverable. The address comparison is case insensitive.
+/* .sp
+/*     This feature is available as of Postfix 3.5.
+/* .IP \fBO\fR
+/*     Prepend an "\fBX-Original-To: \fIrecipient\fR" message
+/*     header with the recipient address as given to Postfix. Note:
+/*     for this to work, the
+/*     \fItransport\fB_destination_recipient_limit\fR must be 1
+/*     (see SINGLE-RECIPIENT DELIVERY above for details).
+/* .sp
+/*     This feature is available as of Postfix 3.5.
+/* .IP \fBR\fR
+/*     Prepend a "\fBReturn-Path: <\fIsender\fB>\fR" message header
+/*     with the envelope sender address.
+/* .sp
+/*     This feature is available as of Postfix 3.5.
+/* .IP \fBX\fR
+/*     Indicates that the delivery is final. This flag affects
+/*     the status reported in "success" DSN (delivery status
+/*     notification) messages, and changes it from "relayed" into
+/*     "delivered".
+/* .sp
+/*     This feature is available as of Postfix 3.5.
+/* .RE
+/* SECURITY
 /*     The SMTP+LMTP client is moderately security-sensitive. It
 /*     talks to SMTP or LMTP servers and to DNS servers on the
 /*     network. The SMTP+LMTP client can be run chrooted at fixed
 /*     the postmaster is notified of bounces, protocol problems, and of
 /*     other trouble.
 /* BUGS
-/*     SMTP and LMTP connection caching does not work with TLS. The necessary
-/*     support for TLS object passivation and re-activation does not
-/*     exist without closing the session, which defeats the purpose.
+/*     SMTP and LMTP connection reuse for TLS (without closing the
+/*     SMTP or LMTP connection) is not supported before Postfix 3.4.
 /*
-/*     SMTP and LMTP connection caching assumes that SASL credentials
+/*     SMTP and LMTP connection reuse assumes that SASL credentials
 /*     are valid for all destinations that map onto the same IP
 /*     address and TCP port.
 /* CONFIGURATION PARAMETERS
 /* .IP "\fBsmtp_tls_servername (empty)\fR"
 /*     Optional name to send to the remote SMTP server in the TLS Server
 /*     Name Indication (SNI) extension.
+/* .PP
+/*     Available in Postfix version 3.5 and later:
+/* .IP "\fBtls_fast_shutdown_enable (yes)\fR"
+/*     After sending a TLS 'close' notification, do not wait for the
+/*     TLS peer to respond, and do not send a second TLS 'close' notification.
 /* OBSOLETE STARTTLS CONTROLS
 /* .ad
 /* .fi
 #include <mymalloc.h>
 #include <name_mask.h>
 #include <name_code.h>
+#include <byte_mask.h>
 
 /* Global library. */
 
 #include <deliver_request.h>
+#include <delivered_hdr.h>
 #include <mail_proto.h>
 #include <mail_params.h>
 #include <mail_version.h>
@@ -1000,6 +1058,7 @@ unsigned smtp_dns_res_opt;
 MAPS   *smtp_pix_bug_maps;
 HBC_CHECKS *smtp_header_checks;                /* limited header checks */
 HBC_CHECKS *smtp_body_checks;          /* limited body checks */
+SMTP_CLI_ATTR smtp_cli_attr;           /* parsed command-line */
 
 #ifdef USE_TLS
 
@@ -1016,6 +1075,59 @@ int     smtp_tls_insecure_mx_policy;
   */
 static int smtp_addr_pref;
 
+/* get_cli_attr - get command-line attributes */
+
+static void get_cli_attr(SMTP_CLI_ATTR *attr, char **argv)
+{
+    const char myname[] = "get_cli_attr";
+    const char *last_flags = "flags="; /* i.e. empty */
+    static const BYTE_MASK flags_map[] = {
+       'D', SMTP_CLI_FLAG_DELIVERED_TO,
+       'O', SMTP_CLI_FLAG_ORIG_RCPT,
+       'R', SMTP_CLI_FLAG_RETURN_PATH,
+       'X', SMTP_CLI_FLAG_FINAL_DELIVERY,
+       0,
+    };
+
+    /*
+     * Initialize.
+     */
+    attr->flags = 0;
+
+    /*
+     * Iterate over the command-line attribute list. Errors are fatal.
+     */
+    for ( /* void */ ; *argv != 0; argv++) {
+
+       /*
+        * flags=stuff. Errors are fatal.
+        */
+       if (strncasecmp("flags=", *argv, sizeof("flags=") - 1) == 0) {
+           last_flags = *argv;
+           if (msg_verbose)
+               msg_info("%s: %s", myname, last_flags);
+           attr->flags = byte_mask(*argv, flags_map,
+                                   *argv + sizeof("flags=") - 1);
+       }
+
+       /*
+        * Bad.
+        */
+       else
+           msg_fatal("unknown attribute name: %s", *argv);
+    }
+
+    /*
+     * Backwards compatibility, redundancy, and obsolescence.
+     */
+    if (!smtp_mode && var_lmtp_assume_final
+       && (attr->flags & SMTP_CLI_FLAG_FINAL_DELIVERY) == 0) {
+       attr->flags |= SMTP_CLI_FLAG_FINAL_DELIVERY;
+       msg_warn("%s is obsolete; instead, specify \"%sX\" in %s",
+                VAR_LMTP_ASSUME_FINAL, last_flags, MASTER_CONF_FILE);
+    }
+}
+
 /* deliver_message - deliver message with extreme prejudice */
 
 static int deliver_message(const char *service, DELIVER_REQUEST *request)
@@ -1036,6 +1148,55 @@ static int deliver_message(const char *service, DELIVER_REQUEST *request)
     if (request->rcpt_list.len <= 0)
        msg_fatal("recipient count: %d", request->rcpt_list.len);
 
+    /*
+     * D flag checks.
+     */
+    if (smtp_cli_attr.flags & SMTP_CLI_FLAG_DELIVERED_TO) {
+
+       /*
+        * The D flag cannot be specified for multi-recipient deliveries.
+        */
+       if (request->rcpt_list.len > 1) {
+           msg_warn("flag `D' requires %s_destination_recipient_limit = 1",
+                    service);
+           return (reject_deliver_request(service, request, "4.3.5",
+                                       "mail system configuration error"));
+       }
+
+       /*
+        * The recipient cannot appear in a Delivered-To: header.
+        */
+       else {
+           DELIVERED_HDR_INFO *delivered_info = delivered_hdr_init(
+                         request->fp, request->data_offset, FOLD_ADDR_ALL);
+           VSTRING *generic_rcpt = vstring_alloc(100);
+           int     have_delivered_loop;
+
+           smtp_rewrite_generic_internal(generic_rcpt,
+                                         request->rcpt_list.info->address);
+           have_delivered_loop = delivered_hdr_find(
+                                        delivered_info, STR(generic_rcpt));
+           vstring_free(generic_rcpt);
+           delivered_hdr_free(delivered_info);
+           if (have_delivered_loop) {
+               return (reject_deliver_request(service, request, "5.4.6",
+                                              "mail forwarding loop for %s",
+                                        request->rcpt_list.info->address));
+           }
+       }
+    }
+
+    /*
+     * The O flag cannot be specified for multi-recipient deliveries.
+     */
+    if ((smtp_cli_attr.flags & SMTP_CLI_FLAG_ORIG_RCPT)
+       && request->rcpt_list.len > 1) {
+       msg_warn("flag `O' requires %s_destination_recipient_limit = 1",
+                service);
+       return (reject_deliver_request(service, request, "4.3.5",
+                                      "mail system configuration error"));
+    }
+
     /*
      * Initialize. Bundle all information about the delivery request, so that
      * we can produce understandable diagnostics when something goes wrong
@@ -1066,17 +1227,12 @@ static int deliver_message(const char *service, DELIVER_REQUEST *request)
 
 /* smtp_service - perform service for client */
 
-static void smtp_service(VSTREAM *client_stream, char *service, char **argv)
+static void smtp_service(VSTREAM *client_stream, char *service,
+                                char **unused_argv)
 {
     DELIVER_REQUEST *request;
     int     status;
 
-    /*
-     * Sanity check. This service takes no command-line arguments.
-     */
-    if (argv[0])
-       msg_fatal("unexpected command-line argument: %s", argv[0]);
-
     /*
      * This routine runs whenever a client connects to the UNIX-domain socket
      * dedicated to remote SMTP delivery service. What we see below is a
@@ -1093,7 +1249,7 @@ static void smtp_service(VSTREAM *client_stream, char *service, char **argv)
 
 /* post_init - post-jail initialization */
 
-static void post_init(char *unused_name, char **unused_argv)
+static void post_init(char *unused_name, char **argv)
 {
     static const NAME_MASK lookup_masks[] = {
        SMTP_HOST_LOOKUP_DNS, SMTP_HOST_FLAG_DNS,
@@ -1180,6 +1336,12 @@ static void post_init(char *unused_name, char **unused_argv)
      * Address verification.
      */
     smtp_vrfy_init();
+
+    /*
+     * Look up service command-line attributes; these do not change during
+     * the process lifetime.
+     */
+    get_cli_attr(&smtp_cli_attr, argv);
 }
 
 /* pre_init - pre-jail initialization */
@@ -1396,6 +1558,7 @@ int     main(int argc, char **argv)
     else if (strcmp(sane_procname, "lmtp") == 0)
        smtp_mode = 0;
     else
+       /* TODO: logging is not initialized. */
        msg_fatal("unexpected process name \"%s\" - "
                  "specify \"smtp\" or \"lmtp\"", var_procname);
 
index ed3e6a526a24ba77f87e42d369e0cc86608e592a..281cfe42fa56f17d91f293f6ee2a455b8aac3b3b 100644 (file)
@@ -700,6 +700,31 @@ extern int smtp_mode;
 #define VAR_LMTP_SMTP(x) (smtp_mode ? VAR_SMTP_##x : VAR_LMTP_##x)
 #define LMTP_SMTP_SUFFIX(x) (smtp_mode ? x##_SMTP : x##_LMTP)
 
+ /*
+  * Parsed command-line attributes. These do not change during the process
+  * lifetime.
+  */
+typedef struct {
+    int     flags;                     /* from flags=, see below */
+} SMTP_CLI_ATTR;
+
+#define SMTP_CLI_FLAG_DELIVERED_TO     (1<<0)  /* prepend Delivered-To: */
+#define SMTP_CLI_FLAG_ORIG_RCPT                (1<<1)  /* prepend X-Original-To: */
+#define SMTP_CLI_FLAG_RETURN_PATH      (1<<2)  /* prepend Return-Path: */
+#define SMTP_CLI_FLAG_FINAL_DELIVERY   (1<<3)  /* final, not relay */
+
+#define SMTP_CLI_MASK_ADD_HEADERS      (SMTP_CLI_FLAG_DELIVERED_TO | \
+       SMTP_CLI_FLAG_ORIG_RCPT | SMTP_CLI_FLAG_RETURN_PATH)
+
+extern SMTP_CLI_ATTR smtp_cli_attr;
+
+ /*
+  * smtp_misc.c.
+  */
+extern void smtp_rewrite_generic_internal(VSTRING *, const char *);
+extern void smtp_quote_822_address_flags(VSTRING *, const char *, int);
+extern void smtp_quote_821_address(VSTRING *, const char *);
+
 /* LICENSE
 /* .ad
 /* .fi
diff --git a/postfix/src/smtp/smtp_misc.c b/postfix/src/smtp/smtp_misc.c
new file mode 100644 (file)
index 0000000..53b76fd
--- /dev/null
@@ -0,0 +1,100 @@
+/*++
+/* NAME
+/*     smtp_misc 3
+/* SUMMARY
+/*     SMTP client address rewriting
+/* SYNOPSIS
+/*     #include <smtp_addr.h>
+/*
+/*     void    smtp_rewrite_generic_internal(
+/*     VSTRING *dst,
+/*     const char *src);
+/*
+/*     void    smtp_quote_822_address_flags(
+/*     VSTRING *dst,
+/*     const char *src,
+/*     int flags);
+/*
+/*     void    smtp_quote_821_address(
+/*     VSTRING *dst,
+/*     const char *src);
+/* DESCRIPTION
+/*     smtp_rewrite_generic_internal() rewrites a non-empty address
+/*     if generic mapping is enabled, otherwise copies it literally.
+/*
+/*     smtp_quote_822_address_flags() is a wrapper around
+/*     quote_822_local_flags(), except for the empty address which
+/*     is copied literally.
+/*
+/*     smtp_quote_821_address() is a wrapper around quote_821_local(),
+/*     except for the empty address or with "smtp_quote_rfc821_envelope
+/*     = no"; in those cases the addres is copied literally.
+/* DIAGNOSTICS
+/*     Fatal: out of memory.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
+/*--*/
+
+ /*
+  * System library.
+  */
+#include <sys_defs.h>
+
+ /*
+  * Utility library.
+  */
+#include <vstring.h>
+
+ /*
+  * Global library.
+  */
+#include <ext_prop.h>
+#include <mail_params.h>
+#include <quote_821_local.h>
+#include <quote_822_local.h>
+
+ /*
+  * Application-specific.
+  */
+#include <smtp.h>
+
+/* smtp_rewrite_generic_internal - generic non-empty address rewriting */
+
+void    smtp_rewrite_generic_internal(VSTRING *dst, const char *src)
+{
+    vstring_strcpy(dst, src);
+    if (*src && smtp_generic_maps)
+       smtp_map11_internal(dst, smtp_generic_maps,
+                           smtp_ext_prop_mask & EXT_PROP_GENERIC);
+}
+
+/* smtp_quote_822_address_flags - quote non-empty header address */
+
+void    smtp_quote_822_address_flags(VSTRING *dst, const char *src, int flags)
+{
+    if (*src) {
+       quote_822_local_flags(dst, src, flags);
+    } else if (flags & QUOTE_FLAG_APPEND) {
+       vstring_strcat(dst, src);
+    } else {
+       vstring_strcpy(dst, src);
+    }
+}
+
+/* smtp_quote_821_address - quote non-empty envelope address */
+
+void    smtp_quote_821_address(VSTRING *dst, const char *src)
+{
+    if (*src && var_smtp_quote_821_env) {
+       quote_821_local(dst, src);
+    } else {
+       vstring_strcpy(dst, src);
+    }
+}
index a43a326af347247e56e92ea44b1a9cca45127bd9..a968ff2957264e399d62812bc9ff6b55823951e4 100644 (file)
 #include <rec_type.h>
 #include <off_cvt.h>
 #include <mark_corrupt.h>
-#include <quote_821_local.h>
 #include <quote_822_local.h>
 #include <mail_proto.h>
 #include <mime_state.h>
@@ -1388,6 +1387,64 @@ static void smtp_mime_fail(SMTP_STATE *state, int mime_errs)
                   "%s", detail->text);
 }
 
+/* smtp_out_raw_or_mime - output buffer, raw output or MIME-aware */
+
+static int smtp_out_raw_or_mime(SMTP_STATE *state, VSTRING *buf)
+{
+    SMTP_SESSION *session = state->session;
+    int     mime_errs;
+
+    if (session->mime_state == 0) {
+       smtp_text_out((void *) state, REC_TYPE_NORM, vstring_str(buf),
+                     VSTRING_LEN(buf), (off_t) 0);
+    } else {
+       mime_errs =
+           mime_state_update(session->mime_state, REC_TYPE_NORM,
+                             vstring_str(buf), VSTRING_LEN(buf));
+       if (mime_errs) {
+           smtp_mime_fail(state, mime_errs);
+           return (-1);
+       }
+    }
+    return (0);
+}
+
+/* smtp_out_add_header - format address header, uses session->scratch* */
+
+static int smtp_out_add_header(SMTP_STATE *state, const char *label,
+                                      const char *lt, const char *addr,
+                                      const char *gt)
+{
+    SMTP_SESSION *session = state->session;
+
+    smtp_rewrite_generic_internal(session->scratch2, addr);
+    vstring_sprintf(session->scratch, "%s: %s", label, lt);
+    smtp_quote_822_address_flags(session->scratch,
+                                vstring_str(session->scratch2),
+                                QUOTE_FLAG_DEFAULT | QUOTE_FLAG_APPEND);
+    vstring_strcat(session->scratch, gt);
+    return (smtp_out_raw_or_mime(state, session->scratch));
+}
+
+/* smtp_out_add_headers - output additional headers, uses session->scratch* */
+
+static int smtp_out_add_headers(SMTP_STATE *state)
+{
+    if (smtp_cli_attr.flags & SMTP_CLI_FLAG_DELIVERED_TO)
+       if (smtp_out_add_header(state, "Delivered-To", "",
+                          state->request->rcpt_list.info->address, "") < 0)
+           return (-1);
+    if (smtp_cli_attr.flags & SMTP_CLI_FLAG_ORIG_RCPT)
+       if (smtp_out_add_header(state, "X-Original-To", "",
+                        state->request->rcpt_list.info->orig_addr, "") < 0)
+           return (-1);
+    if (smtp_cli_attr.flags & SMTP_CLI_FLAG_RETURN_PATH)
+       if (smtp_out_add_header(state, "Return-Path", "<",
+                               state->request->sender, ">") < 0)
+           return (-1);
+    return (0);
+}
+
 /* smtp_loop - exercise the SMTP protocol engine */
 
 static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state,
@@ -1416,24 +1473,6 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state,
     SMTP_RESP fake;
     int     fail_status;
 
-    /*
-     * Macros for readability.
-     */
-#define REWRITE_ADDRESS(dst, src) do { \
-       vstring_strcpy(dst, src); \
-       if (*(src) && smtp_generic_maps) \
-           smtp_map11_internal(dst, smtp_generic_maps, \
-               smtp_ext_prop_mask & EXT_PROP_GENERIC); \
-    } while (0)
-
-#define QUOTE_ADDRESS(dst, src) do { \
-       if (*(src) && var_smtp_quote_821_env) { \
-           quote_821_local(dst, src); \
-       } else { \
-           vstring_strcpy(dst, src); \
-       } \
-    } while (0)
-
     /* Caution: changes to RETURN() also affect code outside the main loop. */
 
 #define RETURN(x) do { \
@@ -1608,8 +1647,9 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state,
        case SMTP_STATE_MAIL:
            request->msg_stats.reuse_count = session->reuse_count;
            GETTIMEOFDAY(&request->msg_stats.conn_setup_done);
-           REWRITE_ADDRESS(session->scratch2, request->sender);
-           QUOTE_ADDRESS(session->scratch, vstring_str(session->scratch2));
+           smtp_rewrite_generic_internal(session->scratch2, request->sender);
+           smtp_quote_821_address(session->scratch,
+                                  vstring_str(session->scratch2));
            vstring_sprintf(next_command, "MAIL FROM:<%s>",
                            vstring_str(session->scratch));
            /* XXX Don't announce SIZE if we're going to MIME downgrade. */
@@ -1697,8 +1737,9 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state,
             */
        case SMTP_STATE_RCPT:
            rcpt = request->rcpt_list.info + send_rcpt;
-           REWRITE_ADDRESS(session->scratch2, rcpt->address);
-           QUOTE_ADDRESS(session->scratch, vstring_str(session->scratch2));
+           smtp_rewrite_generic_internal(session->scratch2, rcpt->address);
+           smtp_quote_821_address(session->scratch,
+                                  vstring_str(session->scratch2));
            vstring_sprintf(next_command, "RCPT TO:<%s>",
                            vstring_str(session->scratch));
            if (session->features & SMTP_FEATURE_DSN) {
@@ -2259,24 +2300,15 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state,
                                                           (void *) state);
                state->space_left = var_smtp_line_limit;
 
+               if ((smtp_cli_attr.flags & SMTP_CLI_MASK_ADD_HEADERS) != 0
+                   && smtp_out_add_headers(state) < 0)
+                   RETURN(0);
+
                while ((rec_type = rec_get(state->src, session->scratch, 0)) > 0) {
                    if (rec_type != REC_TYPE_NORM && rec_type != REC_TYPE_CONT)
                        break;
-                   if (session->mime_state == 0) {
-                       smtp_text_out((void *) state, rec_type,
-                                     vstring_str(session->scratch),
-                                     VSTRING_LEN(session->scratch),
-                                     (off_t) 0);
-                   } else {
-                       mime_errs =
-                           mime_state_update(session->mime_state, rec_type,
-                                             vstring_str(session->scratch),
-                                             VSTRING_LEN(session->scratch));
-                       if (mime_errs) {
-                           smtp_mime_fail(state, mime_errs);
-                           RETURN(0);
-                       }
-                   }
+                   if (smtp_out_raw_or_mime(state, session->scratch) < 0)
+                       RETURN(0);
                    prev_type = rec_type;
                }
 
index 673f0b4efb55c1edeeae5bd8f939de6f64491f06..3d00a7cb86e5b6e67c6f055440d69de801343b05 100644 (file)
@@ -160,7 +160,7 @@ void    smtp_rcpt_done(SMTP_STATE *state, SMTP_RESP *resp, RECIPIENT *rcpt)
      */
     if ((session->features & SMTP_FEATURE_DSN) == 0
        && !smtp_mode
-       && var_lmtp_assume_final != 0)
+       && (smtp_cli_attr.flags & SMTP_CLI_FLAG_FINAL_DELIVERY) != 0)
        dsn_action = "delivered";
 
     /*
index 3eaf905c8b57553ca48254a2269ec17dea3812cd..2a74d21e77adadf0cd4615f82ccbe195cec1ce8e 100644 (file)
 /*     Optional lookup tables that map names received from remote SMTP
 /*     clients via the TLS Server Name Indication (SNI) extension to the
 /*     appropriate keys and certificate chains.
+/* .PP
+/*     Available in Postfix version 3.5 and later:
+/* .IP "\fBtls_fast_shutdown_enable (yes)\fR"
+/*     After sending a TLS 'close' notification, do not wait for the
+/*     TLS peer to respond, and do not send a second TLS 'close' notification.
 /* OBSOLETE STARTTLS CONTROLS
 /* .ad
 /* .fi
index 401b1d8bc0192fd970673a1fc2794abaf2b035a3..90860065e92e645783ca263947ed1fc697d6d8cc 100644 (file)
@@ -521,8 +521,8 @@ static ATTR_OVER_STR str_table[] = {
   */
 #define SMTPD_ACL_SEARCH_NAME_CERT_FPRINT      "cert_fingerprint"
 #define SMTPD_ACL_SEARCH_NAME_PKEY_FPRINT      "pubkey_fingerprint"
-#define SMTPD_ACL_SEARCH_NAME_CERT_ISSUER      "issuer"
-#define SMTPD_ACL_SEARCH_NAME_CERT_SUBJECT     "subject"
+#define SMTPD_ACL_SEARCH_NAME_CERT_ISSUER_CN   "issuer_cn"
+#define SMTPD_ACL_SEARCH_NAME_CERT_SUBJECT_CN  "subject_cn"
 
  /*
   * Search order tokens must be distinct, and 1..126 inclusive, so that they
@@ -531,8 +531,8 @@ static ATTR_OVER_STR str_table[] = {
   */
 #define SMTPD_ACL_SEARCH_CODE_CERT_FPRINT      1
 #define SMTPD_ACL_SEARCH_CODE_PKEY_FPRINT      2
-#define SMTPD_ACL_SEARCH_CODE_CERT_ISSUER      3
-#define SMTPD_ACL_SEARCH_CODE_CERT_SUBJECT     4
+#define SMTPD_ACL_SEARCH_CODE_CERT_ISSUER_CN   3
+#define SMTPD_ACL_SEARCH_CODE_CERT_SUBJECT_CN  4
 
  /*
   * Mapping from search-list names and to search-list codes.
@@ -540,8 +540,8 @@ static ATTR_OVER_STR str_table[] = {
 static const NAME_CODE search_actions[] = {
     SMTPD_ACL_SEARCH_NAME_CERT_FPRINT, SMTPD_ACL_SEARCH_CODE_CERT_FPRINT,
     SMTPD_ACL_SEARCH_NAME_PKEY_FPRINT, SMTPD_ACL_SEARCH_CODE_PKEY_FPRINT,
-    SMTPD_ACL_SEARCH_NAME_CERT_ISSUER, SMTPD_ACL_SEARCH_CODE_CERT_ISSUER,
-    SMTPD_ACL_SEARCH_NAME_CERT_SUBJECT, SMTPD_ACL_SEARCH_CODE_CERT_SUBJECT,
+    SMTPD_ACL_SEARCH_NAME_CERT_ISSUER_CN, SMTPD_ACL_SEARCH_CODE_CERT_ISSUER_CN,
+    SMTPD_ACL_SEARCH_NAME_CERT_SUBJECT_CN, SMTPD_ACL_SEARCH_CODE_CERT_SUBJECT_CN,
     0, MAP_SEARCH_CODE_UNKNOWN,
 };
 
@@ -3168,8 +3168,8 @@ static int check_ccert_access(SMTPD_STATE *state, const char *acl_spec,
     if ((search_order = acl->search_order) == 0)
        search_order = default_search;
     if (msg_verbose)
-       msg_info("%s: search_order length=%d",
-                myname, strlen(search_order));
+       msg_info("%s: search_order length=%ld",
+                myname, (long) strlen(search_order));
 
     /*
      * When directly checking the fingerprint, it is OK if the issuing CA is
@@ -3188,10 +3188,10 @@ static int check_ccert_access(SMTPD_STATE *state, const char *acl_spec,
            case SMTPD_ACL_SEARCH_CODE_PKEY_FPRINT:
                match_this = state->tls_context->peer_pkey_fprint;
                break;
-           case SMTPD_ACL_SEARCH_CODE_CERT_ISSUER:
+           case SMTPD_ACL_SEARCH_CODE_CERT_ISSUER_CN:
                match_this = state->tls_context->issuer_CN;
                break;
-           case SMTPD_ACL_SEARCH_CODE_CERT_SUBJECT:
+           case SMTPD_ACL_SEARCH_CODE_CERT_SUBJECT_CN:
                match_this = state->tls_context->peer_CN;
                break;
            default:
index dabd6403cb672fcd3f4e125210254f3f83d01558..fec7d4542eccb8e6a8b20f8be45871aef624f7c3 100644 (file)
@@ -572,6 +572,7 @@ tls_server.o: tls_server.c
 tls_session.o: ../../include/argv.h
 tls_session.o: ../../include/check_arg.h
 tls_session.o: ../../include/dns.h
+tls_session.o: ../../include/mail_params.h
 tls_session.o: ../../include/msg.h
 tls_session.o: ../../include/myaddrinfo.h
 tls_session.o: ../../include/mymalloc.h
index a28623af5e282ca4fde3209f74927bb4ec643eaa..a6f572403e0ebd21693d789728be8aac9cc18e54 100644 (file)
@@ -289,6 +289,7 @@ char   *var_tls_mgr_service;
 char   *var_tls_tkt_cipher;
 char   *var_openssl_path;
 char   *var_tls_server_sni_maps;
+bool    var_tls_fast_shutdown;
 
 static MAPS *tls_server_sni_maps;
 
@@ -625,6 +626,7 @@ void    tls_param_init(void)
        VAR_TLS_BC_PKEY_FPRINT, DEF_TLS_BC_PKEY_FPRINT, &var_tls_bc_pkey_fprint,
        VAR_TLS_PREEMPT_CLIST, DEF_TLS_PREEMPT_CLIST, &var_tls_preempt_clist,
        VAR_TLS_MULTI_WILDCARD, DEF_TLS_MULTI_WILDCARD, &var_tls_multi_wildcard,
+       VAR_TLS_FAST_SHUTDOWN, DEF_TLS_FAST_SHUTDOWN, &var_tls_fast_shutdown,
        0,
     };
     static int init_done;
index 112b89df07f48b16731d85c4c7480aae51eca7a6..3f6027fc4ef85a81ae66a02da00b007fb9f7f373 100644 (file)
 #include <msg.h>
 #include <mymalloc.h>
 
+/* Global library. */
+
+#include <mail_params.h>
+
 /* TLS library. */
 
 #define TLS_INTERNAL
@@ -95,6 +99,18 @@ void    tls_session_stop(TLS_APPL_STATE *unused_ctx, VSTREAM *stream, int timeou
        msg_panic("%s: stream has no active TLS context", myname);
 
     /*
+     * According to RFC 2246 (TLS 1.0), there is no requirement to wait for
+     * the peer's close-notify. If the application protocol provides
+     * sufficient session termination signaling, then there's no need to
+     * duplicate that at the TLS close-notify layer.
+     * 
+     * https://tools.ietf.org/html/rfc2246#section-7.2.1
+     * https://tools.ietf.org/html/rfc4346#section-7.2.1
+     * https://tools.ietf.org/html/rfc5246#section-7.2.1
+     * 
+     * Specify 'tls_fast_shutdown = no' to enable the historical behavior
+     * described below.
+     * 
      * Perform SSL_shutdown() twice, as the first attempt will send out the
      * shutdown alert but it will not wait for the peer's shutdown alert.
      * Therefore, when we are the first party to send the alert, we must call
@@ -104,7 +120,7 @@ void    tls_session_stop(TLS_APPL_STATE *unused_ctx, VSTREAM *stream, int timeou
      */
     if (!failure) {
        retval = tls_bio_shutdown(vstream_fileno(stream), timeout, TLScontext);
-       if (retval == 0)
+       if (!var_tls_fast_shutdown && retval == 0)
            tls_bio_shutdown(vstream_fileno(stream), timeout, TLScontext);
     }
     tls_free_context(TLScontext);
index 7339da6b9618832822cb2e55d23c6d53c18532fb..a9aa29dd00e7a66f0852dfdf9feb83e66ed7cb0c 100644 (file)
 /*     Optional lookup tables that map names received from remote SMTP
 /*     clients via the TLS Server Name Indication (SNI) extension to the
 /*     appropriate keys and certificate chains.
+/* .PP
+/*     Available in Postfix version 3.5 and later:
+/* .IP "\fBtls_fast_shutdown_enable (yes)\fR"
+/*     After sending a TLS 'close' notification, do not wait for the
+/*     TLS peer to respond, and do not send a second TLS 'close' notification.
 /* STARTTLS SERVER CONTROLS
 /* .ad
 /* .fi
index 381bb6e1310fa027de9d665f012c27027a04cd8b..6c23678ab4fede21731d92e071e3059f10fff938 100644 (file)
@@ -41,7 +41,8 @@ SRCS  = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \
        valid_utf8_hostname.c midna_domain.c argv_splitq.c balpar.c dict_union.c \
        extpar.c dict_inline.c casefold.c dict_utf8.c strcasecmp_utf8.c \
        split_qnameval.c argv_attr_print.c argv_attr_scan.c dict_file.c \
-       msg_logger.c logwriter.c unix_dgram_connect.c unix_dgram_listen.c
+       msg_logger.c logwriter.c unix_dgram_connect.c unix_dgram_listen.c \
+       byte_mask.c
 OBJS   = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
        attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
        attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
@@ -84,7 +85,8 @@ OBJS  = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
        valid_utf8_hostname.o midna_domain.o argv_splitq.o balpar.o dict_union.o \
        extpar.o dict_inline.o casefold.o dict_utf8.o strcasecmp_utf8.o \
        split_qnameval.o argv_attr_print.o argv_attr_scan.o dict_file.o \
-       msg_logger.o logwriter.o unix_dgram_connect.o unix_dgram_listen.o
+       msg_logger.o logwriter.o unix_dgram_connect.o unix_dgram_listen.o \
+       byte_mask.o
 # MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf.
 # When hard-linking these, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ),
 # otherwise it sets the PLUGIN_* macros.
@@ -114,7 +116,7 @@ HDRS        = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
        dict_fail.h warn_stat.h dict_sockmap.h line_number.h timecmp.h \
        slmdb.h compat_va_copy.h dict_pipe.h dict_random.h \
        valid_utf8_hostname.h midna_domain.h dict_union.h dict_inline.h \
-       check_arg.h argv_attr.h msg_logger.h logwriter.h
+       check_arg.h argv_attr.h msg_logger.h logwriter.h byte_mask.h
 TESTSRC        = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
        stream_test.c dup2_pass_on_exec.c
 DEFS   = -I. -D$(SYSTYPE)
@@ -134,7 +136,7 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
        myaddrinfo myaddrinfo4 inet_proto sane_basename format_tv \
        valid_utf8_string ip_match base32_code msg_rate_delay netstring \
        vstream timecmp dict_cache midna_domain casefold strcasecmp_utf8 \
-       vbuf_print split_qnameval vstream msg_logger
+       vbuf_print split_qnameval vstream msg_logger byte_mask
 PLUGIN_MAP_SO = $(LIB_PREFIX)pcre$(LIB_SUFFIX)
 
 LIB_DIR        = ../../lib
@@ -351,6 +353,11 @@ name_mask: $(LIB)
        $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
        mv junk $@.o
 
+byte_mask: $(LIB)
+       mv $@.o junk
+       $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
+       mv junk $@.o
+
 rand_sleep: $(LIB)
        mv $@.o junk
        $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
@@ -552,7 +559,7 @@ tests: all valid_hostname_test mac_expand_test dict_test unescape_test \
        miss_endif_pcre_test miss_endif_regexp_test split_qnameval_test \
        vstring_test vstream_test dict_pcre_file_test dict_regexp_file_test \
        dict_cidr_file_test dict_static_file_test dict_random_test \
-       dict_random_file_test dict_inline_file_test
+       dict_random_file_test dict_inline_file_test byte_mask_tests
 
 root_tests:
 
@@ -734,7 +741,7 @@ name_mask_tests: name_mask_test0 name_mask_test1 name_mask_test2 \
        name_mask_test7 name_mask_test8 name_mask_test9
 
 name_mask_test0: name_mask name_mask.in name_mask.ref0
-       $(SHLIB_ENV) ${VALGRIND} ./name_mask IGNORE IGNORE < name_mask.in > name_mask.tmp 2>&0
+       $(SHLIB_ENV) ${VALGRIND} ./name_mask IGNORE IGNORE < name_mask.in > name_mask.tmp 2>&1
        diff name_mask.ref0 name_mask.tmp
        rm -f name_mask.tmp
 
@@ -783,6 +790,29 @@ name_mask_test9: name_mask name_mask.in name_mask.ref9
        diff name_mask.ref9 name_mask.tmp
        rm -f name_mask.tmp
 
+byte_mask_tests: byte_mask_test0 byte_mask_test1 byte_mask_test2
+
+byte_mask_test0: byte_mask byte_mask.in byte_mask.ref0
+       while read line; do \
+           echo "$$line" | $(SHLIB_ENV) ${VALGRIND} ./byte_mask IGNORE IGNORE; \
+       done < byte_mask.in > byte_mask.tmp 2>&1
+       diff byte_mask.ref0 byte_mask.tmp
+       rm -f byte_mask.tmp
+
+byte_mask_test1: byte_mask byte_mask.in byte_mask.ref1
+       while read line; do \
+           echo "$$line" | $(SHLIB_ENV) ${VALGRIND} ./byte_mask WARN WARN; \
+       done < byte_mask.in > byte_mask.tmp 2>&1
+       diff byte_mask.ref1 byte_mask.tmp
+       rm -f byte_mask.tmp
+
+byte_mask_test2: byte_mask byte_mask.in byte_mask.ref2
+       -while read line; do \
+           echo "$$line" | $(SHLIB_ENV) ${VALGRIND} ./byte_mask FATAL FATAL; \
+       done < byte_mask.in > byte_mask.tmp 2>&1
+       diff byte_mask.ref2 byte_mask.tmp
+       rm -f byte_mask.tmp
+
 base32_code_test: base32_code
        $(SHLIB_ENV) ${VALGRIND} ./base32_code
 
@@ -1143,6 +1173,15 @@ binhash.o: binhash.h
 binhash.o: msg.h
 binhash.o: mymalloc.h
 binhash.o: sys_defs.h
+byte_mask.o: byte_mask.c
+byte_mask.o: byte_mask.h
+byte_mask.o: check_arg.h
+byte_mask.o: msg.h
+byte_mask.o: mymalloc.h
+byte_mask.o: stringops.h
+byte_mask.o: sys_defs.h
+byte_mask.o: vbuf.h
+byte_mask.o: vstring.h
 casefold.o: casefold.c
 casefold.o: check_arg.h
 casefold.o: msg.h
@@ -1910,8 +1949,6 @@ load_file.o: vbuf.h
 load_file.o: vstream.h
 load_file.o: warn_stat.h
 load_lib.o: load_lib.c
-load_lib.o: load_lib.h
-load_lib.o: msg.h
 load_lib.o: sys_defs.h
 logwriter.o: check_arg.h
 logwriter.o: iostuff.h
diff --git a/postfix/src/util/byte_mask.c b/postfix/src/util/byte_mask.c
new file mode 100644 (file)
index 0000000..37cfd7e
--- /dev/null
@@ -0,0 +1,299 @@
+/*++
+/* NAME
+/*     byte_mask 3
+/* SUMMARY
+/*     map byte sequence to bit mask
+/* SYNOPSIS
+/*     #include <byte_mask.h>
+/*
+/*     int     byte_mask(
+/*     const char *context,
+/*     const BYTE_MASK *table,
+/*     const char *bytes);
+/*
+/*     const char *str_byte_mask(
+/*     const char *context,
+/*     const BYTE_MASK *table,
+/*     int     mask);
+/*
+/*     int     byte_mask_opt(
+/*     const char *context;
+/*     const BYTE_MASK *table,
+/*     const char *bytes,
+/*     int     flags);
+/*
+/*     const char *str_byte_mask_opt(
+/*     VSTRING *buf,
+/*     const char *context,
+/*     const BYTE_MASK *table,
+/*     int     mask,
+/*     int     flags);
+/* DESCRIPTION
+/*     byte_mask() takes a null-terminated \fItable\fR with (byte
+/*     value, single-bit mask) pairs and computes the bit-wise OR
+/*     of the masks that correspond to the byte values pointed to
+/*     by the \fIbytes\fR argument.
+/*
+/*     str_byte_mask() translates a bit mask into its equivalent
+/*     bytes. The result is written to a static buffer that is
+/*     overwritten upon each call.
+/*
+/*     byte_mask_opt() and str_name_mask_opt() are extended versions
+/*     with additional fine control.
+/*
+/*     Arguments:
+/* .IP buf
+/*     Null pointer or pointer to buffer storage.
+/* .IP context
+/*     What kind of byte values and bit masks are being manipulated,
+/*     reported in error messages. Typically, this would be the
+/*     name of a user-configurable parameter or command-line
+/*     attribute.
+/* .IP table
+/*     Table with (byte value, single-bit mask) pairs.
+/* .IP bytes
+/*     A null-terminated string that is to be converted into a bit
+/*     mask.
+/* .IP mask
+/*     A bit mask that is to be converted into null-terminated
+/*     string.
+/* .IP flags
+/*     Bit-wise OR of one or more of the following. Where features
+/*     would have conflicting results (e.g., FATAL versus IGNORE),
+/*     the feature that takes precedence is described first.
+/*
+/*     When converting from string to mask, at least one of the
+/*     following must be specified: BYTE_MASK_FATAL, BYTE_MASK_RETURN,
+/*     BYTE_MASK_WARN or BYTE_MASK_IGNORE.
+/*
+/*     When converting from mask to string, at least one of the
+/*     following must be specified: BYTE_MASK_FATAL, BYTE_MASK_RETURN,
+/*     BYTE_MASK_WARN or BYTE_MASK_IGNORE.
+/* .RS
+/* .IP BYTE_MASK_FATAL
+/*     Require that all values in \fIbytes\fR exist in \fItable\fR,
+/*     and require that all bits listed in \fImask\fR exist in
+/*     \fItable\fR. Terminate with a fatal run-time error if this
+/*     condition is not met. This feature is enabled by default
+/*     when calling byte_mask() or str_name_mask().
+/* .IP BYTE_MASK_RETURN
+/*     Require that all values in \fIbytes\fR exist in \fItable\fR,
+/*     and require that all bits listed in \fImask\fR exist in
+/*     \fItable\fR. Log a warning, and return 0 (byte_mask()) or
+/*     a null pointer (str_byte_mask()) if this condition is not
+/*     met. This feature is not enabled by default when calling
+/*     byte_mask() or str_name_mask().
+/* .IP BYTE_MASK_WARN
+/*     Require that all values in \fIbytes\fR exist in \fItable\fR,
+/*     and require that all bits listed in \fImask\fR exist in
+/*     \fItable\fR. Log a warning if this condition is not met,
+/*     continue processing, and return all valid bits or bytes.
+/*     This feature is not enabled by default when calling byte_mask()
+/*     or str_byte_mask().
+/* .IP BYTE_MASK_IGNORE
+/*     Silently ignore values in \fIbytes\fR that don't exist in
+/*     \fItable\fR, and silently ignore bits listed in \fImask\fR
+/*     that don't exist in \fItable\fR. This feature is not enabled
+/*     by default when calling byte_mask() or str_byte_mask().
+/* .IP BYTE_MASK_ANY_CASE
+/*     Enable case-insensitive matching. This feature is not
+/*     enabled by default when calling byte_mask(); it has no
+/*     effect with str_byte_mask().
+/* .RE
+/*     The value BYTE_MASK_NONE explicitly requests no features,
+/*     and BYTE_MASK_DEFAULT enables the default options.
+/* DIAGNOSTICS
+/*     Fatal: the \fIbytes\fR argument specifies a name not found in
+/*     \fItable\fR, or the \fImask\fR specifies a bit not found in
+/*     \fItable\fR.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* HISTORY
+/*     This code is a clone of Postfix name_mask(3).
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <stringops.h>
+#include <byte_mask.h>
+#include <vstring.h>
+
+#define STR(x) vstring_str(x)
+
+/* byte_mask_opt - compute mask corresponding to byte string */
+
+int     byte_mask_opt(const char *context, const BYTE_MASK *table,
+                             const char *bytes, int flags)
+{
+    const char myname[] = "byte_mask";
+    const char *bp;
+    int     result = 0;
+    const BYTE_MASK *np;
+
+    if ((flags & BYTE_MASK_REQUIRED) == 0)
+       msg_panic("%s: missing BYTE_MASK_FATAL/RETURN/WARN/IGNORE flag",
+                 myname);
+
+    /*
+     * Iterate over bytes string, and look up each byte in the table. If the
+     * byte is found, merge its mask with the result.
+     */
+    for (bp = bytes; *bp; bp++) {
+       int     byte_val = *(const unsigned char *) bp;
+
+       for (np = table; /* void */ ; np++) {
+           if (np->byte_val == 0) {
+               if (flags & BYTE_MASK_FATAL) {
+                   msg_fatal("unknown %s value \"%c\" in \"%s\"",
+                             context, byte_val, bytes);
+               } else if (flags & BYTE_MASK_RETURN) {
+                   msg_warn("unknown %s value \"%c\" in \"%s\"",
+                            context, byte_val, bytes);
+                   return (0);
+               } else if (flags & BYTE_MASK_WARN) {
+                   msg_warn("unknown %s value \"%c\" in \"%s\"",
+                            context, byte_val, bytes);
+               }
+               break;
+           }
+           if ((flags & BYTE_MASK_ANY_CASE) ?
+               (TOLOWER(byte_val) == TOLOWER(np->byte_val)) :
+               (byte_val == np->byte_val)) {
+               if (msg_verbose)
+                   msg_info("%s: %c", myname, byte_val);
+               result |= np->mask;
+               break;
+           }
+       }
+    }
+    return (result);
+}
+
+/* str_byte_mask_opt - mask to string */
+
+const char *str_byte_mask_opt(VSTRING *buf, const char *context,
+                                     const BYTE_MASK *table,
+                                     int mask, int flags)
+{
+    const char myname[] = "byte_mask";
+    const BYTE_MASK *np;
+    static VSTRING *my_buf = 0;
+
+    if ((flags & STR_BYTE_MASK_REQUIRED) == 0)
+       msg_panic("%s: missing BYTE_MASK_FATAL/RETURN/WARN/IGNORE flag",
+                 myname);
+
+    if (buf == 0) {
+       if (my_buf == 0)
+           my_buf = vstring_alloc(1);
+       buf = my_buf;
+    }
+    VSTRING_RESET(buf);
+
+    for (np = table; mask != 0; np++) {
+       if (np->byte_val == 0) {
+           if (flags & BYTE_MASK_FATAL) {
+               msg_fatal("%s: unknown %s bit in mask: 0x%x",
+                         myname, context, mask);
+           } else if (flags & BYTE_MASK_RETURN) {
+               msg_warn("%s: unknown %s bit in mask: 0x%x",
+                        myname, context, mask);
+               return (0);
+           } else if (flags & BYTE_MASK_WARN) {
+               msg_warn("%s: unknown %s bit in mask: 0x%x",
+                        myname, context, mask);
+           }
+           break;
+       }
+       if (mask & np->mask) {
+           mask &= ~np->mask;
+           vstring_sprintf_append(buf, "%c", np->byte_val);
+       }
+    }
+    VSTRING_TERMINATE(buf);
+
+    return (STR(buf));
+}
+
+#ifdef TEST
+
+ /*
+  * Stand-alone test program.
+  */
+#include <stdlib.h>
+#include <vstream.h>
+#include <vstring_vstream.h>
+#include <name_mask.h>
+
+int     main(int argc, char **argv)
+{
+    static const BYTE_MASK demo_table[] = {
+       '0', 1 << 0,
+       '1', 1 << 1,
+       '2', 1 << 2,
+       '3', 1 << 3,
+       0, 0,
+    };
+    static const NAME_MASK feature_table[] = {
+       "DEFAULT", BYTE_MASK_DEFAULT,
+       "FATAL", BYTE_MASK_FATAL,
+       "ANY_CASE", BYTE_MASK_ANY_CASE,
+       "RETURN", BYTE_MASK_RETURN,
+       "WARN", BYTE_MASK_WARN,
+       "IGNORE", BYTE_MASK_IGNORE,
+       0,
+    };
+    int     in_feature_mask;
+    int     out_feature_mask;
+    int     demo_mask;
+    const char *demo_str;
+    VSTRING *out_buf = vstring_alloc(1);
+    VSTRING *in_buf = vstring_alloc(1);
+
+    if (argc != 3)
+       msg_fatal("usage: %s in-feature-mask out-feature-mask", argv[0]);
+    in_feature_mask = name_mask(argv[1], feature_table, argv[1]);
+    out_feature_mask = name_mask(argv[2], feature_table, argv[2]);
+    while (vstring_get_nonl(in_buf, VSTREAM_IN) != VSTREAM_EOF) {
+       demo_mask = byte_mask_opt("name", demo_table,
+                                 STR(in_buf), in_feature_mask);
+       demo_str = str_byte_mask_opt(out_buf, "mask", demo_table,
+                                    demo_mask, out_feature_mask);
+       vstream_printf("%s -> 0x%x -> %s\n",
+                      STR(in_buf), demo_mask,
+                      demo_str ? demo_str : "(null)");
+       demo_mask <<=1;
+       demo_str = str_byte_mask_opt(out_buf, "mask", demo_table,
+                                    demo_mask, out_feature_mask);
+       vstream_printf("0x%x -> %s\n",
+                      demo_mask, demo_str ? demo_str : "(null)");
+       vstream_fflush(VSTREAM_OUT);
+    }
+    vstring_free(in_buf);
+    vstring_free(out_buf);
+    exit(0);
+}
+
+#endif
diff --git a/postfix/src/util/byte_mask.h b/postfix/src/util/byte_mask.h
new file mode 100644 (file)
index 0000000..6cdea1d
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef _BYTE_MASK_H_INCLUDED_
+#define _BYTE_MASK_H_INCLUDED_
+
+/*++
+/* NAME
+/*     byte_mask 3h
+/* SUMMARY
+/*     map names to bit mask
+/* SYNOPSIS
+/*     #include <byte_mask.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * Utility library.
+  */
+#include <vstring.h>
+
+ /*
+  * External interface.
+  */
+typedef struct {
+    int     byte_val;
+    int     mask;
+} BYTE_MASK;
+
+#define BYTE_MASK_FATAL                (1<<0)
+#define BYTE_MASK_ANY_CASE     (1<<1)
+#define BYTE_MASK_RETURN       (1<<2)
+#define BYTE_MASK_WARN         (1<<6)
+#define BYTE_MASK_IGNORE       (1<<7)
+
+#define BYTE_MASK_REQUIRED \
+    (BYTE_MASK_FATAL | BYTE_MASK_RETURN | BYTE_MASK_WARN | BYTE_MASK_IGNORE)
+#define STR_BYTE_MASK_REQUIRED (BYTE_MASK_REQUIRED)
+
+#define BYTE_MASK_NONE         0
+#define BYTE_MASK_DEFAULT      (BYTE_MASK_FATAL)
+
+#define byte_mask(tag, table, str) \
+       byte_mask_opt((tag), (table), (str), BYTE_MASK_DEFAULT)
+#define str_byte_mask(tag, table, mask) \
+       str_byte_mask_opt(((VSTRING *) 0), (tag), (table), (mask), BYTE_MASK_DEFAULT)
+
+extern int byte_mask_opt(const char *, const BYTE_MASK *, const char *, int);
+extern const char *str_byte_mask_opt(VSTRING *, const char *, const BYTE_MASK *, int, int);
+
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
+/*     Google, Inc.
+/*     111 8th Avenue
+/*     New York, NY 10011, USA
+/*--*/
+
+#endif
diff --git a/postfix/src/util/byte_mask.in b/postfix/src/util/byte_mask.in
new file mode 100644 (file)
index 0000000..6d89c5a
--- /dev/null
@@ -0,0 +1,7 @@
+0123
+0
+1
+2
+3
+1234
+abcd
diff --git a/postfix/src/util/byte_mask.ref0 b/postfix/src/util/byte_mask.ref0
new file mode 100644 (file)
index 0000000..a6ab11b
--- /dev/null
@@ -0,0 +1,14 @@
+0123 -> 0xf -> 0123
+0x1e -> 123
+0 -> 0x1 -> 0
+0x2 -> 1
+1 -> 0x2 -> 1
+0x4 -> 2
+2 -> 0x4 -> 2
+0x8 -> 3
+3 -> 0x8 -> 3
+0x10 -> 
+1234 -> 0xe -> 123
+0x1c -> 23
+abcd -> 0x0 -> 
+0x0 -> 
diff --git a/postfix/src/util/byte_mask.ref1 b/postfix/src/util/byte_mask.ref1
new file mode 100644 (file)
index 0000000..92e3f4f
--- /dev/null
@@ -0,0 +1,22 @@
+unknown: warning: byte_mask: unknown mask bit in mask: 0x10
+0123 -> 0xf -> 0123
+0x1e -> 123
+0 -> 0x1 -> 0
+0x2 -> 1
+1 -> 0x2 -> 1
+0x4 -> 2
+2 -> 0x4 -> 2
+0x8 -> 3
+unknown: warning: byte_mask: unknown mask bit in mask: 0x10
+3 -> 0x8 -> 3
+0x10 -> 
+unknown: warning: unknown name value "4" in "1234"
+unknown: warning: byte_mask: unknown mask bit in mask: 0x10
+1234 -> 0xe -> 123
+0x1c -> 23
+unknown: warning: unknown name value "a" in "abcd"
+unknown: warning: unknown name value "b" in "abcd"
+unknown: warning: unknown name value "c" in "abcd"
+unknown: warning: unknown name value "d" in "abcd"
+abcd -> 0x0 -> 
+0x0 -> 
diff --git a/postfix/src/util/byte_mask.ref2 b/postfix/src/util/byte_mask.ref2
new file mode 100644 (file)
index 0000000..631ec53
--- /dev/null
@@ -0,0 +1,10 @@
+unknown: fatal: byte_mask: unknown mask bit in mask: 0x10
+0 -> 0x1 -> 0
+0x2 -> 1
+1 -> 0x2 -> 1
+0x4 -> 2
+2 -> 0x4 -> 2
+0x8 -> 3
+unknown: fatal: byte_mask: unknown mask bit in mask: 0x10
+unknown: fatal: unknown name value "4" in "1234"
+unknown: fatal: unknown name value "a" in "abcd"