]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.9-20240104
authorWietse Venema <wietse@porcupine.org>
Thu, 4 Jan 2024 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <ietf-dane@dukhovni.org>
Fri, 5 Jan 2024 04:58:53 +0000 (23:58 -0500)
21 files changed:
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/html/postconf.5.html
postfix/html/smtpd.8.html
postfix/man/man5/postconf.5
postfix/man/man8/smtpd.8
postfix/mantools/dehtml
postfix/mantools/postlink
postfix/proto/postconf.proto
postfix/proto/stop
postfix/proto/stop.double-history
postfix/proto/stop.double-install-proto-text
postfix/proto/stop.double-proto-html
postfix/proto/stop.spell-history
postfix/src/global/cleanup_user.h
postfix/src/global/mail_params.h
postfix/src/global/mail_version.h
postfix/src/global/smtp_stream.c
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd_check.c
postfix/src/smtpd/smtpd_check.h

index b16cdc2eda23199a354a7ca716d66651fa5929cf..d6e357af423a8a140354e1696ca450ff4ffcb8e9 100644 (file)
@@ -27644,11 +27644,31 @@ Apologies for any names omitted.
        mantools/postlink, proto/postconf.proto, global/mail_params.h,
        global/smtp_stream.c, global/smtp_stream.h, smtpd/smtpd.c.
 
-20231226
+20240104
 
-       Cleanup: a nicer implementation of smtpd_forbid_bare_newline
-       that does not hang up the the middle of a BDAT or DATA
-       command, and that optionally includes the offending command
-       sequence in a postmaster 'protocol' notification. Files:
-       smtpd/smtpd.c, global/stp_stream.[hc], global/cleanup_user.h,
-       global/cleanup_strerror.c.
+       Cleanup: when the Postfix SMTP server rejects bare <LF>,
+       log the helo, mail and rcpt information if available. Files:
+       smtpd/smtpd.c, smtpd/smtpd_check.c.
+
+       Cleanup: when the Postfix SMTP server rejects bare <LF>,
+       keep reading message content after an unexpected <LF>.<LF>
+       or <LF>.<CR><LF>, before responding. This increases the
+       likelihood that the client will actually see the Postfix
+       response and remove the attack from their mail queue. Files:
+       smtpd/smtpd.c, global/smtp_stream.[hc], global/cleanup_user.h.
+
+       Cleanup: added smtpd_forbid_bare_newline settings "reject"
+       and "normalize". The default setting "normalize" (and "yes")
+       will accept bare newlines from local or remote SMTP clients,
+       but if any DATA content line ends in <CR><LF>, require the
+       standard End-of-DATA form <CR><LF>.<CR><LF> and skip plus
+       log non-standard End-of-DATA forms. This may fail to receive
+       email from legitimate clients that send a mix of lines
+       ending in <LF> and <CR><LF>. If such clients exist, they
+       need to be excluded with smtpd_forbid_bare_newline_exclusions.
+       Files: proto/postconf.proto, global/mail_params.h,
+       smtpd/smtpd.c.
+
+       Tooling: mantools/dehtml was breaking words in code examples,
+       causing false spellchecker errors. File: mantools/dehtml,
+       proto/stop.double-proto-html.
index 70d611ee3385b5f7a8270c95fcd3a7a64427c670..d5b101140ae000f9a5da30ea0a2e2dd155e744eb 100644 (file)
@@ -26,6 +26,56 @@ now also distributed with the more recent Eclipse Public License
 license of their choice. Those who are more comfortable with the
 IPL can continue with that license.
 
+Major changes with snapshot 20240102
+====================================
+
+This updates Postfix fixes for SMTP smuggling attacks, For background,
+see https://www.postfix.org/smtp-smuggling.html
+
+This release improves configuration (see below) and logging (it now
+includes helo, mail, and rcpt information if available).
+
+- The new setting "smtpd_forbid_bare_newline = normalize" allows
+  bare newlines from local and remote SMTP clients that send bare
+  newlines consistently, and maintains more compatibility with
+  infrastructure tools such as probers and surveys.
+
+- The new setting "smtpd_forbid_bare_newline = reject" rejects a
+  command or message that contains a bare newline. To disconnect
+  the client, specify "smtpd_forbid_bare_newline_reject_code = 521".
+
+- The old setting "yes" has become an alias for "normalize".
+
+- The old setting "no" has not changed, and allows SMTP smuggling.
+
+The recommended Postfix 3.9 settings (i.e. the defaults) are now:
+
+    # Allow bare newlines from local and remote SMTP clients. If any DATA
+    # content line ends in <CR><LF>, require the standard End-of-DATA form
+    # <CR><LF>.<CR><LF> and skip non-standard End-of-DATA forms with
+    # logging that looks like:
+    #
+    #    skipping unexpected <LF>.<LF> in DATA from...
+    #    skipping unexpected <LF>.<CR><LF> in DATA from...
+    #
+    # This may fail to receive email from legitimate clients that send a
+    # mix of lines ending in <LF> and <CR><LF>. If such clients exist,
+    # they need to be excluded with smtpd_forbid_bare_newline_exclusions.
+    #
+    smtpd_forbid_bare_newline = normalize
+    smtpd_forbid_bare_newline_exclusions = $mynetworks
+
+Alternative settings:
+
+    # Reject bare newlines from remote SMTP clients, but allow them from
+    # local non-standard clients such as netcat, fax machines, or load
+    # balancer health checks.
+    #
+    smtpd_forbid_bare_newline = reject
+    smtpd_forbid_bare_newline_exclusions = $mynetworks
+
+This will be back ported to Postfix 3.8.5, 3.7.10, 3.6.14, and 3.5.24.
+
 Incompatible changes with snapshot 20231221
 ===========================================
 
index c6b76a48cfa9dd3fdfadefbebb365dae2f53e95c..449e10ba33ecfe1e2ac83a0136f8e904fe97518b 100644 (file)
@@ -15922,31 +15922,86 @@ This feature is available in Postfix 2.0 and later.
 </DD>
 
 <DT><b><a name="smtpd_forbid_bare_newline">smtpd_forbid_bare_newline</a>
-(default: Postfix &ge; 3.9: yes)</b></DT><DD>
+(default: Postfix &ge; 3.9: normalize)</b></DT><DD>
 
-<p> Reply with "Error: bare &lt;LF&gt; received" and disconnect
-when a remote SMTP client sends a line ending in &lt;LF&gt;, violating
-the <a href="https://tools.ietf.org/html/rfc5321">RFC 5321</a> requirement that lines must end in &lt;CR&gt;&lt;LF&gt;.
-This feature is enabled by default with Postfix &ge; 3.9. Use
-<a href="postconf.5.html#smtpd_forbid_bare_newline_exclusions">smtpd_forbid_bare_newline_exclusions</a> to exclude non-standard clients
-such as netcat. Specify "<a href="postconf.5.html#smtpd_forbid_bare_newline">smtpd_forbid_bare_newline</a> = no" to disable
-(not recommended for an Internet-connected MTA). </p>
+<p> Disconnect, reject, or normalize commands and email message
+content when a remote SMTP client sends lines ending in &lt;LF&gt;.
+Such line endings are commonly allowed with UNIX-based SMTP servers,
+but they violate the <a href="https://tools.ietf.org/html/rfc5321">RFC 5321</a> requirement that lines must end in
+&lt;CR&gt;&lt;LF&gt;. <.p>
 
-<p> Example: </p>
+<p> Specify one of the following values (case does not matter): </p>
+
+<dl compact>
 
+<dt> <b>normalize</b> </dt> <dd> Maintain compatibility with legacy
+SMTP clients that send lines ending in the non-standard &lt;LF&gt;,
+and treat those line endings as if the client sent the standard
+&lt;CR&gt;&lt;LF&gt;. However, if an SMTP client sends any DATA
+content line ending in the standard &lt;CR&gt;&lt;LF&gt;, support
+only the standard End-of-DATA form
+&lt;CR&gt;&lt;LF&gt;.&lt;CR&gt;&lt;LF&gt;, and skip non-standard
+End-of-DATA forms after logging them as:
 <blockquote>
 <pre>
-# Disconnect remote SMTP clients that send bare newlines, but allow
-# local clients with non-standard SMTP implementations such as netcat,
-# fax machines, or load balancer health checks.
+skipping unexpected &lt;LF&gt;.&lt;LF&gt; in DATA from...
+skipping unexpected &lt;LF&gt;.&lt;CR&gt;&lt;LF&gt; in DATA from...
+</pre>
+</blockquote>
+This may fail to receive email from legitimate SMTP clients that
+send DATA content with a mix of line endings. Such clients need
+to be excluded with <a href="postconf.5.html#smtpd_forbid_bare_newline_exclusions">smtpd_forbid_bare_newline_exclusions</a>. </dd>
+
+<dt> <b>yes</b> </dt> <dd> Alias for "normalize". </dd>
+
+<dt> <b>reject</b> </dt> <dd> When an SMTP client sends a command
+or message content line ending in &lt;LF&gt;, log a "bare &lt;LF&gt;
+received" error, and reject the command or message content with
+<a href="postconf.5.html#smtpd_forbid_bare_newline_reject_code">smtpd_forbid_bare_newline_reject_code</a>. This will fail to receive
+email from legitimate SMTP clients that send command or message
+content with lines ending in &lt;LF&gt;. Such clients need to be
+excluded with <a href="postconf.5.html#smtpd_forbid_bare_newline_exclusions">smtpd_forbid_bare_newline_exclusions</a>.  </dd>
+
+<dt> <b>no</b> </dt> <dd> Treat all lines ending in &lt;LF&gt;
+as if the client sent &lt;CR&gt;&lt;LF&gt;. This option is fully
+backwards compatible, but is not recommended for an Internet-facing
+SMTP server, because it is vulnerable to <a
+href="https://www.postfix.org/smtp-smuggling.html"> SMTP smuggling</a>.
+</dd>
+
+</dl>
+
+<p> Examples: </p>
+
+<blockquote>
+<pre>
+# Allow bare newlines from local and remote SMTP clients. If any
+# DATA content line ends in &lt;CR&gt;&lt;LF&gt;, require the standard End-of-DATA
+# form &lt;CR&gt;&lt;LF&gt;.&lt;CR&gt;&lt;LF&gt; and skip plus log non-standard forms.
+# This may fail to receive email from legitimate clients that send a
+# mix of lines ending in &lt;LF&gt; and &lt;CR&gt;&lt;LF&gt;. If such clients exist,
+# they need to be excluded with <a href="postconf.5.html#smtpd_forbid_bare_newline_exclusions">smtpd_forbid_bare_newline_exclusions</a>.
 #
-<a href="postconf.5.html#smtpd_forbid_bare_newline">smtpd_forbid_bare_newline</a> = yes
+<a href="postconf.5.html#smtpd_forbid_bare_newline">smtpd_forbid_bare_newline</a> = normalize
 <a href="postconf.5.html#smtpd_forbid_bare_newline_exclusions">smtpd_forbid_bare_newline_exclusions</a> = $<a href="postconf.5.html#mynetworks">mynetworks</a>
 </pre>
 </blockquote>
 
-<p> This feature is available in Postfix &ge; 3.9, 3.8.4, 3.7.9,
-3.6.13, and 3.5.23. </p>
+<blockquote>
+<pre>
+# Reject bare newlines from remote SMTP clients, but allow them from
+# local non-standard clients such as netcat, fax machines, or load
+# balancer health checks.
+#
+<a href="postconf.5.html#smtpd_forbid_bare_newline">smtpd_forbid_bare_newline</a> = reject
+<a href="postconf.5.html#smtpd_forbid_bare_newline_exclusions">smtpd_forbid_bare_newline_exclusions</a> = $<a href="postconf.5.html#mynetworks">mynetworks</a>
+</pre>
+</blockquote>
+
+<p> This feature with settings 'yes' and 'no' is available in Postfix
+&ge; 3.9, 3.8.4, 3.7.9, 3.6.13, and 3.5.23. The settings 'reject'
+and 'normalize' are available with Postfix &ge; 3.9, 3.8.5, 3.7.10,
+3.6.14, and 3.5.24. </p>
 
 
 </DD>
@@ -15958,23 +16013,25 @@ such as netcat. Specify "<a href="postconf.5.html#smtpd_forbid_bare_newline">smt
 enforcement. It uses the same syntax and parent-domain matching
 behavior as <a href="postconf.5.html#mynetworks">mynetworks</a>. </p>
 
-<p> Example: </p>
-
-<blockquote>
-<pre>
-# Disconnect remote SMTP clients that send bare newlines, but allow
-# local clients with non-standard SMTP implementations such as netcat,
-# fax machines, or load balancer health checks.
-#
-<a href="postconf.5.html#smtpd_forbid_bare_newline">smtpd_forbid_bare_newline</a> = yes
-<a href="postconf.5.html#smtpd_forbid_bare_newline_exclusions">smtpd_forbid_bare_newline_exclusions</a> = $<a href="postconf.5.html#mynetworks">mynetworks</a>
-</pre>
-</blockquote>
-
 <p> This feature is available in Postfix &ge; 3.9, 3.8.4, 3.7.9,
 3.6.13, and 3.5.23. </p>
 
 
+</DD>
+
+<DT><b><a name="smtpd_forbid_bare_newline_reject_code">smtpd_forbid_bare_newline_reject_code</a>
+(default: 550)</b></DT><DD>
+
+<p>
+The numerical Postfix SMTP server response code when a request
+is rejected by the <b><a href="postconf.5.html#smtpd_forbid_bare_newline">smtpd_forbid_bare_newline</a></b> feature.
+Specify a 5XX status code (521 to disconnect).
+</p>
+
+<p> This feature is available in Postfix &ge; 3.9, 3.8.5, 3.7.10,
+3.6.14, and 3.5.24. </p>
+
+
 </DD>
 
 <DT><b><a name="smtpd_forbid_unauth_pipelining">smtpd_forbid_unauth_pipelining</a>
index 26ea40b95855be52d892e30996a077b2126dd0d6..c48c494c3a3ee4dfed5fb7037321a120eca03b4d 100644 (file)
@@ -997,15 +997,20 @@ SMTPD(8)                                                              SMTPD(8)
 
        Available in Postfix 3.9, 3.8.4, 3.7.9, 3.6.13, 3.5.23 and later:
 
-       <b><a href="postconf.5.html#smtpd_forbid_bare_newline">smtpd_forbid_bare_newline</a> (Postfix</b> &gt;<b>= 3.9: yes)</b>
-              Reply  with  "Error:  bare  &lt;LF&gt; received" and disconnect when a
-              remote SMTP client sends a line ending in  &lt;LF&gt;,  violating  the
-              <a href="https://tools.ietf.org/html/rfc5321">RFC 5321</a> requirement that lines must end in &lt;CR&gt;&lt;LF&gt;.
+       <b><a href="postconf.5.html#smtpd_forbid_bare_newline">smtpd_forbid_bare_newline</a> (Postfix</b> &gt;<b>= 3.9: normalize)</b>
+              Disconnect, reject, or normalize commands and email message con-
+              tent when a remote SMTP client sends lines ending in &lt;LF&gt;.
 
        <b><a href="postconf.5.html#smtpd_forbid_bare_newline_exclusions">smtpd_forbid_bare_newline_exclusions</a> ($<a href="postconf.5.html#mynetworks">mynetworks</a>)</b>
-              Exclude  the  specified  clients  from <a href="postconf.5.html#smtpd_forbid_bare_newline">smtpd_forbid_bare_newline</a>
+              Exclude the  specified  clients  from  <a href="postconf.5.html#smtpd_forbid_bare_newline">smtpd_forbid_bare_newline</a>
               enforcement.
 
+       Available in Postfix 3.9, 3.8.5, 3.7.10, 3.6.14, 3.5.24 and later:
+
+       <b><a href="postconf.5.html#smtpd_forbid_bare_newline_reject_code">smtpd_forbid_bare_newline_reject_code</a> (550)</b>
+              The  numerical  Postfix SMTP server response code when a request
+              is rejected by the <b><a href="postconf.5.html#smtpd_forbid_bare_newline">smtpd_forbid_bare_newline</a></b> feature.
+
 <b>TARPIT CONTROLS</b>
        When a remote SMTP client makes errors, the  Postfix  SMTP  server  can
        insert  delays  before  responding. This can help to slow down run-away
index e1280475fced172c2e95efc3b1e2f3d4a515cdb0..6d7d45177f74d9b9b3d1287b5a2fde81ea2bc366 100644 (file)
@@ -11003,58 +11003,111 @@ The smtpd_expansion_filter value is not subject to Postfix configuration
 parameter $name expansion.
 .PP
 This feature is available in Postfix 2.0 and later.
-.SH smtpd_forbid_bare_newline (default: Postfix >= 3.9: yes)
-Reply with "Error: bare <LF> received" and disconnect
-when a remote SMTP client sends a line ending in <LF>, violating
-the RFC 5321 requirement that lines must end in <CR><LF>.
-This feature is enabled by default with Postfix >= 3.9. Use
-smtpd_forbid_bare_newline_exclusions to exclude non\-standard clients
-such as netcat. Specify "smtpd_forbid_bare_newline = no" to disable
-(not recommended for an Internet\-connected MTA).
+.SH smtpd_forbid_bare_newline (default: Postfix >= 3.9: normalize)
+Disconnect, reject, or normalize commands and email message
+content when a remote SMTP client sends lines ending in <LF>.
+Such line endings are commonly allowed with UNIX\-based SMTP servers,
+but they violate the RFC 5321 requirement that lines must end in
+<CR><LF>. <.p>
+.PP
+Specify one of the following values (case does not matter):
+.IP "\fBnormalize\fR"
+Maintain compatibility with legacy
+SMTP clients that send lines ending in the non\-standard <LF>,
+and treat those line endings as if the client sent the standard
+<CR><LF>. However, if an SMTP client sends any DATA
+content line ending in the standard <CR><LF>, support
+only the standard End\-of\-DATA form
+<CR><LF>.<CR><LF>, and skip non\-standard
+End\-of\-DATA forms after logging them as:
+.sp
+.in +4
+.nf
+.na
+.ft C
+skipping unexpected <LF>.<LF> in DATA from...
+skipping unexpected <LF>.<CR><LF> in DATA from...
+.fi
+.ad
+.ft R
+.in -4
+This may fail to receive email from legitimate SMTP clients that
+send DATA content with a mix of line endings. Such clients need
+to be excluded with smtpd_forbid_bare_newline_exclusions.
+.br
+.IP "\fByes\fR"
+Alias for "normalize".
+.br
+.IP "\fBreject\fR"
+When an SMTP client sends a command
+or message content line ending in <LF>, log a "bare <LF>
+received" error, and reject the command or message content with
+smtpd_forbid_bare_newline_reject_code. This will fail to receive
+email from legitimate SMTP clients that send command or message
+content with lines ending in <LF>. Such clients need to be
+excluded with smtpd_forbid_bare_newline_exclusions.
+.br
+.IP "\fBno\fR"
+Treat all lines ending in <LF>
+as if the client sent <CR><LF>. This option is fully
+backwards compatible, but is not recommended for an Internet\-facing
+SMTP server, because it is vulnerable to  SMTP smuggling.
+.br
+.br
 .PP
-Example:
+Examples:
 .sp
 .in +4
 .nf
 .na
 .ft C
-# Disconnect remote SMTP clients that send bare newlines, but allow
-# local clients with non\-standard SMTP implementations such as netcat,
-# fax machines, or load balancer health checks.
+# Allow bare newlines from local and remote SMTP clients. If any
+# DATA content line ends in <CR><LF>, require the standard End\-of\-DATA
+# form <CR><LF>.<CR><LF> and skip plus log non\-standard forms.
+# This may fail to receive email from legitimate clients that send a
+# mix of lines ending in <LF> and <CR><LF>. If such clients exist,
+# they need to be excluded with smtpd_forbid_bare_newline_exclusions.
 #
-smtpd_forbid_bare_newline = yes
+smtpd_forbid_bare_newline = normalize
 smtpd_forbid_bare_newline_exclusions = $mynetworks
 .fi
 .ad
 .ft R
 .in -4
-.PP
-This feature is available in Postfix >= 3.9, 3.8.4, 3.7.9,
-3.6.13, and 3.5.23.
-.SH smtpd_forbid_bare_newline_exclusions (default: $mynetworks)
-Exclude the specified clients from smtpd_forbid_bare_newline
-enforcement. It uses the same syntax and parent\-domain matching
-behavior as mynetworks.
-.PP
-Example:
 .sp
 .in +4
 .nf
 .na
 .ft C
-# Disconnect remote SMTP clients that send bare newlines, but allow
-# local clients with non\-standard SMTP implementations such as netcat,
-# fax machines, or load balancer health checks.
+# Reject bare newlines from remote SMTP clients, but allow them from
+# local non\-standard clients such as netcat, fax machines, or load
+# balancer health checks.
 #
-smtpd_forbid_bare_newline = yes
+smtpd_forbid_bare_newline = reject
 smtpd_forbid_bare_newline_exclusions = $mynetworks
 .fi
 .ad
 .ft R
 .in -4
 .PP
+This feature with settings 'yes' and 'no' is available in Postfix
+>= 3.9, 3.8.4, 3.7.9, 3.6.13, and 3.5.23. The settings 'reject'
+and 'normalize' are available with Postfix >= 3.9, 3.8.5, 3.7.10,
+3.6.14, and 3.5.24.
+.SH smtpd_forbid_bare_newline_exclusions (default: $mynetworks)
+Exclude the specified clients from smtpd_forbid_bare_newline
+enforcement. It uses the same syntax and parent\-domain matching
+behavior as mynetworks.
+.PP
 This feature is available in Postfix >= 3.9, 3.8.4, 3.7.9,
 3.6.13, and 3.5.23.
+.SH smtpd_forbid_bare_newline_reject_code (default: 550)
+The numerical Postfix SMTP server response code when a request
+is rejected by the \fBsmtpd_forbid_bare_newline\fR feature.
+Specify a 5XX status code (521 to disconnect).
+.PP
+This feature is available in Postfix >= 3.9, 3.8.5, 3.7.10,
+3.6.14, and 3.5.24.
 .SH smtpd_forbid_unauth_pipelining (default: Postfix >= 3.9: yes)
 Disconnect remote SMTP clients that violate RFC 2920 (or 5321)
 command pipelining constraints. The server replies with "554 5.5.0
index 17b19695d1d44d0ef763cbdd8608c2812ab221b8..25b1f48a4b85e49a883a712a464c99be6f2e206d 100644 (file)
@@ -870,13 +870,18 @@ Disconnect remote SMTP clients that violate RFC 2920 (or 5321)
 command pipelining constraints.
 .PP
 Available in Postfix 3.9, 3.8.4, 3.7.9, 3.6.13, 3.5.23 and later:
-.IP "\fBsmtpd_forbid_bare_newline (Postfix >= 3.9: yes)\fR"
-Reply with "Error: bare <LF> received" and disconnect
-when a remote SMTP client sends a line ending in <LF>, violating
-the RFC 5321 requirement that lines must end in <CR><LF>.
+.IP "\fBsmtpd_forbid_bare_newline (Postfix >= 3.9: normalize)\fR"
+Disconnect, reject, or normalize commands and email message
+content when a remote SMTP client sends lines ending in <LF>.
 .IP "\fBsmtpd_forbid_bare_newline_exclusions ($mynetworks)\fR"
 Exclude the specified clients from smtpd_forbid_bare_newline
 enforcement.
+.PP
+Available in Postfix 3.9, 3.8.5, 3.7.10, 3.6.14, 3.5.24 and
+later:
+.IP "\fBsmtpd_forbid_bare_newline_reject_code (550)\fR"
+The numerical Postfix SMTP server response code when a request
+is rejected by the \fBsmtpd_forbid_bare_newline\fR feature.
 .SH "TARPIT CONTROLS"
 .na
 .nf
index 69f66b7b1f6923d103b64eb85315187262820267..9a3be6f3f53e884265a5be252494b40ff7363135 100755 (executable)
@@ -3,7 +3,7 @@
 for i
 do
     case $i in
-    /*) lynx -dump file://localhost$i;;
-     *) lynx -dump file://localhost`pwd`/$i;;
+    /*) lynx -width=256 -dump file://localhost$i;;
+     *) lynx -width=256 -dump file://localhost`pwd`/$i;;
     esac
 done | grep -v 'file://localhost/'
index d49217e864b2e3db723602265e7d82960113a7aa..85f6b68c4d05cb2c4ea58f646d40c4616281d5fd 100755 (executable)
@@ -562,6 +562,7 @@ while (<>) {
     s;\bsmtpd_expansion_filter\b;<a href="postconf.5.html#smtpd_expansion_filter">$&</a>;g;
     s;\bsmtpd_for[-</bB>]*\n*[ <bB>]*bidden_commands\b;<a href="postconf.5.html#smtpd_forbidden_commands">$&</a>;g;
     s;\bsmtpd_for[-</bB>]*\n*[ <bB>]*bid_bare_newline\b;<a href="postconf.5.html#smtpd_forbid_bare_newline">$&</a>;g;
+    s;\bsmtpd_for[-</bB>]*\n*[ <bB>]*bid_bare_newline_reject_code\b;<a href="postconf.5.html#smtpd_forbid_bare_newline_reject_code">$&</a>;g;
     s;\bsmtpd_for[-</bB>]*\n*[ <bB>]*bid_bare_newline_exclusions\b;<a href="postconf.5.html#smtpd_forbid_bare_newline_exclusions">$&</a>;g;
     s;\bsmtpd_for[-</bB>]*\n*[ <bB>]*bid_unauth_pipelining\b;<a href="postconf.5.html#smtpd_forbid_unauth_pipelining">$&</a>;g;
     s;\bsmtpd_hard_error_limit\b;<a href="postconf.5.html#smtpd_hard_error_limit">$&</a>;g;
index 537e02af40739fc23daa0b30d57e7ea50ba9581b..f0b835099ab1d9926eb98790e89329aa540ddada 100644 (file)
@@ -11240,6 +11240,17 @@ is rejected by the <b>reject_plaintext_session</b> restriction.
 
 <p> This feature is available in Postfix 2.3 and later. </p>
 
+%PARAM smtpd_forbid_bare_newline_reject_code 550
+
+<p>
+The numerical Postfix SMTP server response code when a request
+is rejected by the <b>smtpd_forbid_bare_newline</b> feature.
+Specify a 5XX status code (521 to disconnect).
+</p>
+
+<p> This feature is available in Postfix &ge; 3.9, 3.8.5, 3.7.10,
+3.6.14, and 3.5.24. </p>
+
 %PARAM resolve_numeric_domain no
 
 <p> Resolve "user@ipaddress" as "user@[ipaddress]", instead of
@@ -19055,51 +19066,93 @@ MinProtocol = TLSv1
 <p> This feature is available in Postfix &ge; 3.9, 3.8.1, 3.7.6,
 3.6.10, and 3.5.20. </p>
 
-%PARAM smtpd_forbid_bare_newline Postfix &ge; 3.9: yes
+%PARAM smtpd_forbid_bare_newline Postfix &ge; 3.9: normalize
 
-<p> Reply with "Error: bare &lt;LF&gt; received" and disconnect
-when a remote SMTP client sends a line ending in &lt;LF&gt;, violating
-the RFC 5321 requirement that lines must end in &lt;CR&gt;&lt;LF&gt;.
-This feature is enabled by default with Postfix &ge; 3.9. Use
-smtpd_forbid_bare_newline_exclusions to exclude non-standard clients
-such as netcat. Specify "smtpd_forbid_bare_newline = no" to disable
-(not recommended for an Internet-connected MTA). </p>
+<p> Disconnect, reject, or normalize commands and email message
+content when a remote SMTP client sends lines ending in &lt;LF&gt;.
+Such line endings are commonly allowed with UNIX-based SMTP servers,
+but they violate the RFC 5321 requirement that lines must end in
+&lt;CR&gt;&lt;LF&gt;. <.p>
 
-<p> Example: </p>
+<p> Specify one of the following values (case does not matter): </p>
+
+<dl compact>
 
+<dt> <b>normalize</b> </dt> <dd> Maintain compatibility with legacy
+SMTP clients that send lines ending in the non-standard &lt;LF&gt;,
+and treat those line endings as if the client sent the standard
+&lt;CR&gt;&lt;LF&gt;. However, if an SMTP client sends any DATA
+content line ending in the standard &lt;CR&gt;&lt;LF&gt;, support
+only the standard End-of-DATA form
+&lt;CR&gt;&lt;LF&gt;.&lt;CR&gt;&lt;LF&gt;, and skip non-standard
+End-of-DATA forms after logging them as:
 <blockquote>
 <pre>
-# Disconnect remote SMTP clients that send bare newlines, but allow
-# local clients with non-standard SMTP implementations such as netcat,
-# fax machines, or load balancer health checks.
-#
-smtpd_forbid_bare_newline = yes
-smtpd_forbid_bare_newline_exclusions = $mynetworks
+skipping unexpected &lt;LF&gt;.&lt;LF&gt; in DATA from...
+skipping unexpected &lt;LF&gt;.&lt;CR&gt;&lt;LF&gt; in DATA from...
 </pre>
 </blockquote>
+This may fail to receive email from legitimate SMTP clients that
+send DATA content with a mix of line endings. Such clients need
+to be excluded with smtpd_forbid_bare_newline_exclusions. </dd>
+
+<dt> <b>yes</b> </dt> <dd> Alias for "normalize". </dd>
+
+<dt> <b>reject</b> </dt> <dd> When an SMTP client sends a command
+or message content line ending in &lt;LF&gt;, log a "bare &lt;LF&gt;
+received" error, and reject the command or message content with
+smtpd_forbid_bare_newline_reject_code. This will fail to receive
+email from legitimate SMTP clients that send command or message
+content with lines ending in &lt;LF&gt;. Such clients need to be
+excluded with smtpd_forbid_bare_newline_exclusions.  </dd>
+
+<dt> <b>no</b> </dt> <dd> Treat all lines ending in &lt;LF&gt;
+as if the client sent &lt;CR&gt;&lt;LF&gt;. This option is fully
+backwards compatible, but is not recommended for an Internet-facing
+SMTP server, because it is vulnerable to <a
+href="https://www.postfix.org/smtp-smuggling.html"> SMTP smuggling</a>.
+</dd>
 
-<p> This feature is available in Postfix &ge; 3.9, 3.8.4, 3.7.9,
-3.6.13, and 3.5.23. </p>
-
-%PARAM smtpd_forbid_bare_newline_exclusions $mynetworks
+</dl>
 
-<p> Exclude the specified clients from smtpd_forbid_bare_newline
-enforcement. It uses the same syntax and parent-domain matching 
-behavior as mynetworks. </p>
+<p> Examples: </p>
 
-<p> Example: </p>
+<blockquote>
+<pre>
+# Allow bare newlines from local and remote SMTP clients. If any
+# DATA content line ends in &lt;CR&gt;&lt;LF&gt;, require the standard End-of-DATA
+# form &lt;CR&gt;&lt;LF&gt;.&lt;CR&gt;&lt;LF&gt; and skip plus log non-standard forms.
+# This may fail to receive email from legitimate clients that send a
+# mix of lines ending in &lt;LF&gt; and &lt;CR&gt;&lt;LF&gt;. If such clients exist,
+# they need to be excluded with smtpd_forbid_bare_newline_exclusions.
+#
+smtpd_forbid_bare_newline = normalize
+smtpd_forbid_bare_newline_exclusions = $mynetworks
+</pre>
+</blockquote>
 
 <blockquote>
 <pre>
-# Disconnect remote SMTP clients that send bare newlines, but allow
-# local clients with non-standard SMTP implementations such as netcat,
-# fax machines, or load balancer health checks.
+# Reject bare newlines from remote SMTP clients, but allow them from
+# local non-standard clients such as netcat, fax machines, or load
+# balancer health checks.
 #
-smtpd_forbid_bare_newline = yes
+smtpd_forbid_bare_newline = reject
 smtpd_forbid_bare_newline_exclusions = $mynetworks
 </pre>
 </blockquote>
 
+<p> This feature with settings 'yes' and 'no' is available in Postfix
+&ge; 3.9, 3.8.4, 3.7.9, 3.6.13, and 3.5.23. The settings 'reject'
+and 'normalize' are available with Postfix &ge; 3.9, 3.8.5, 3.7.10,
+3.6.14, and 3.5.24. </p>
+
+%PARAM smtpd_forbid_bare_newline_exclusions $mynetworks
+
+<p> Exclude the specified clients from smtpd_forbid_bare_newline
+enforcement. It uses the same syntax and parent-domain matching 
+behavior as mynetworks. </p>
+
 <p> This feature is available in Postfix &ge; 3.9, 3.8.4, 3.7.9,
 3.6.13, and 3.5.23. </p>
 
index 375597d29527efde1127353cde4d97559e717f24..13a4b3d63a91c6a696a2d49b836a9ada6d87ba3f 100644 (file)
@@ -1589,3 +1589,4 @@ Amawalk
 resychronization
 ENVID
 netcat
+probers
index b75d9c7dcfb7cc4c7b806bc93435901f179b70bd..7b32c1fda8009182b52e26c704c64aa61b60aedd 100644 (file)
@@ -82,3 +82,9 @@ proto  proto aliases proto virtual proto ADDRESS_REWRITING_README html
  available Files local command c local local c 
  ID if available File pipe pipe c 
  global smtp_stream h smtpd smtpd c 
+ global smtp_stream c global smtp_stream h smtpd smtpd c 
+ log the helo mail and rcpt information Files smtpd smtpd c 
+ LF LF or LF CR LF before responding This increases
+ smtpd smtpd c global smtp_stream hc global cleanup_user h 
+ smtpd smtpd c smtpd smtpd_check c 
+ keep reading message content after an unexpected LF LF 
index 338286eb8ee003a0151eae4184bb6ccfdd13f983..edccb249808bf2031a10a04a5b112779cc65324a 100644 (file)
@@ -39,3 +39,4 @@ root  root you
  shlib_directory shlib_directory 
  user foo domain user domain domain 
 virtual  virtual alias domain anything right hand content does not matter 
+ skipping unexpected LF LF in DATA from 
index 3d69cd0a63da6bce59a139310503da913628c410..78f8eed9da98816412952cac61f9e00458de6da8 100644 (file)
@@ -252,3 +252,96 @@ postfix_ssl_settings  postfix_ssl_settings
 baseline_postfix_settings  baseline_postfix_settings 
  The and match and literally Without the the
  The matches literally Without the the would
+ The example is simplified for educational purposes In reality my patterns list multiple domain names as domain domain 
+ The matches literally Without the the would match any character 
+ The and match and literally Without the the and would be grouping operators 
+ The matches literally Without the the would match any character 
+ pipeline all commands following EHLO for example MAIL RCPT BDAT BDAT MAIL RCPT BDAT without ever having to wait for a server response This means that with BDAT the Postfix SMTP server cannot distinguish between a well behaved client and a
+ NOTE Postfix 3 6 also introduces support for the level level and other operators to compare compatibility levels With the standard operators etc compatibility level 3 10 would be smaller than 3 9 which is undesirable 
+ Otherwise the benefits of SMTP connection caching are minor it eliminates the latency of the TCP handshake SYN SYN ACK ACK plus the latency of the SMTP initial handshake 220 greeting EHLO command EHLO response With TLS encrypted
+ Otherwise the benefits of SMTP connection caching are minor it eliminates the latency of the TCP handshake SYN SYN ACK ACK plus the latency of the SMTP initial handshake 220 greeting EHLO command EHLO response With TLS encrypted
+ 3 Reject the mail by sending a suitable status code back to Postfix Postfix will send the mail back to the sender address 
+ Line 8 NEVER NEVER NEVER use the t command line option here It will mis deliver mail like sending messages from a mailing list back to the mailing list 
+ Line 8 NEVER NEVER NEVER use the t command line option here It will mis deliver mail like sending messages from a mailing list back to the mailing list 
+Documentation  Documentation is available as README files start with the file README_FILES AAAREADME as HTML web pages point your browser to html index html and as UNIX style manual pages 
+ Parameters whose defaults can be specified in this way are listed below See the postconf 5 manpage for a description command nroff man man man5 postconf 5 less 
+ Parameters whose defaults can be specified in this way are listed below See the postconf 5 manpage for a description command nroff man man man5 postconf 5 less 
+mynetworks mynetworks 127 0 0 0 8 168 100 189 0 28 1 128 fe80 10 2001 240 587 64
+Postfix  Postfix can use an LDAP directory as a source for any of its lookups aliases 5 virtual 5 canonical 5 etc This allows you to keep information for your mail service in a replicated network database with fine grained access controls By not
+ If you re using the libraries from the UM distribution http www umich edu dirsvcs ldap ldap html or OpenLDAP http www openldap org something like this in the top level of your Postfix source tree should work 
+query_filter mailacceptinggeneralid s maildrop maildrop maildrop 
+query_filter mailacceptinggeneralid s maildrop maildrop maildrop 
+query_filter mailacceptinggeneralid s maildrop maildrop maildrop owner cn root dc your dc com 
+query_filter mailacceptinggeneralid s maildrop maildrop maildrop owner cn root dc your dc com 
+ As of Postfix version 2 0 the Postfix SMTP server rejects mail for unknown recipients in local domains domains that match mydestination or the IP addresses in inet_interfaces or proxy_interfaces with User unknown in local recipient table 
+ Postfix emulates a limited number of Sendmail macros as shown in the table Some macro values depend on whether a recipient is rejected rejected recipients are available on request by the Milter application Different macros are available at
+ Postfix has TWO sets of mail filters filters that are used for SMTP mail only specified with the smtpd_milters parameter and filters for non SMTP mail specified with the non_smtpd_milters parameter The non SMTP filters are primarily for
+ etc usr usr bin var var spool and so on This is especially an issue if you executed postfix install see above as an unprivileged user 
+ etc usr usr bin var var spool and so on This is especially an issue if you executed postfix install see above as an unprivileged user 
+ parametername stress something stress something or parametername stress something something Other parameters always evaluate as if the stress value is the empty string 
+ parametername stress something stress something or parametername stress something something Other parameters always evaluate as if the stress value is the empty string 
+ more CPU faster disks and more network bandwidth can deal with larger deferred queues but as a rule of thumb the deferred queue scales to somewhere between 100 000 and 1 000 000 messages with good performance unlikely above that limit 
+ 31 sasldb Accounts are stored stored in a Cyrus SASL Berkeley DB database
+ assigned to the delivery slots might look like this 12131415 Hmm fine for sneaking in the single recipient mail but how do we sneak in the mail with more than one recipient Say if we have one four recipient mail followed by two two recipient
+ we see the hundred recipient job can accumulate ten free delivery slots and then we could preempt it and sneak in the ten recipient mail Wait wait wait Could we Aren t we overinflating the original one thousand recipient mail 
+ The truth is that it turns out that it is not really necessary to wait until the jobs counter accumulates all the delivery slots in advance Say we have ten recipient mail followed by two two recipient mails If the preemption happened when enough
+ Disallowing RFC 822 address syntax example MAIL FROM the dude dude example com 
+ 3 Reject the mail by sending a suitable SMTP status code back to Postfix Postfix passes the status back to the remote SMTP client This way Postfix does not have to send a bounce message 
+ Lines 14 18 Define the list of valid addresses in the the backed up domain tld domain This prevents your mail queue from filling up with undeliverable MAILER DAEMON messages If you can t maintain a list of valid recipients then you must
+ The syntax of name value value name value and name value is explained at the beginning of the postconf 5 manual page 
+ Use 521 SMTP reply codes Postfix 2 6 and later or 421 Postfix 2 3 2 5 to hang up on clients that that match botnet related RBLs see next bullet or that match selected non RBL restrictions such as SMTP access maps The Postfix SMTP
+ the next hop destination can have the Postfix specific form name name port name or name port 
+ dt b a name no_unknown_recipient_checks no_unknown_recipient_checks a b dt 
+ dt b a name check_ccert_access check_ccert_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name check_client_access check_client_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name check_client_a_access check_client_a_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name check_client_mx_access check_client_mx_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name check_client_ns_access check_client_ns_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name check_reverse_client_hostname_access check_reverse_client_hostname_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name check_reverse_client_hostname_a_access check_reverse_client_hostname_a_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name check_reverse_client_hostname_mx_access check_reverse_client_hostname_mx_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name check_reverse_client_hostname_ns_access check_reverse_client_hostname_ns_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name check_sasl_access check_sasl_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name permit_sasl_authenticated permit_sasl_authenticated a b dt 
+ dt b a name permit_tls_all_clientcerts permit_tls_all_clientcerts a b dt 
+ dt b a name reject_rbl_client reject_rbl_client i rbl_domain d d d d i a b dt 
+ dt b a name permit_dnswl_client permit_dnswl_client i dnswl_domain d d d d i a b dt 
+ dt b a name reject_rhsbl_client reject_rhsbl_client i rbl_domain d d d d i a b dt 
+ dt b a name permit_rhswl_client permit_rhswl_client i rhswl_domain d d d d i a b dt 
+ dt b a name reject_rhsbl_reverse_client reject_rhsbl_reverse_client i rbl_domain d d d d i a b dt 
+ dt b a name reject_unknown_client_hostname reject_unknown_client_hostname a b with Postfix lt 2 3 reject_unknown_client dt 
+ dt b a name reject_unknown_reverse_client_hostname reject_unknown_reverse_client_hostname a b dt 
+ dt b a name reject_unknown_forward_client_hostname reject_unknown_forward_client_hostname a b dt 
+ dt b a name check_policy_service check_policy_service i servername i a b dt 
+ dt b a name reject_multi_recipient_bounce reject_multi_recipient_bounce a b dt 
+ dt b a name check_etrn_access check_etrn_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name check_helo_access check_helo_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name check_helo_a_access check_helo_a_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name check_helo_mx_access check_helo_mx_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name check_helo_ns_access check_helo_ns_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name reject_invalid_helo_hostname reject_invalid_helo_hostname a b with Postfix lt 2 3 reject_invalid_hostname dt 
+ dt b a name reject_non_fqdn_helo_hostname reject_non_fqdn_helo_hostname a b with Postfix lt 2 3 reject_non_fqdn_hostname dt 
+ dt b a name reject_rhsbl_helo reject_rhsbl_helo i rbl_domain d d d d i a b dt 
+ dt b a name reject_unknown_helo_hostname reject_unknown_helo_hostname a b with Postfix lt 2 3 reject_unknown_hostname dt 
+ dt b a name check_recipient_access check_recipient_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name check_recipient_a_access check_recipient_a_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name check_recipient_mx_access check_recipient_mx_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name check_recipient_ns_access check_recipient_ns_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name reject_non_fqdn_recipient reject_non_fqdn_recipient a b dt 
+ dt b a name reject_rhsbl_recipient reject_rhsbl_recipient i rbl_domain d d d d i a b dt 
+ dt b a name reject_unauth_destination reject_unauth_destination a b dt 
+ dt b a name reject_unknown_recipient_domain reject_unknown_recipient_domain a b dt 
+ dt b a name reject_unlisted_recipient reject_unlisted_recipient a b with Postfix version 2 0 check_recipient_maps dt 
+ dt b a name reject_unverified_recipient reject_unverified_recipient a b dt 
+ dt b a name check_sender_access check_sender_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name check_sender_a_access check_sender_a_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name check_sender_mx_access check_sender_mx_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name check_sender_ns_access check_sender_ns_access a i a href DATABASE_README html type table a i b dt 
+ dt b a name reject_authenticated_sender_login_mismatch reject_authenticated_sender_login_mismatch a b dt 
+ dt b a name reject_known_sender_login_mismatch reject_known_sender_login_mismatch a b dt 
+ dt b a name reject_rhsbl_sender reject_rhsbl_sender i rbl_domain d d d d i a b dt 
+ dt b a name reject_sender_login_mismatch reject_sender_login_mismatch a b dt 
+ dt b a name reject_unauthenticated_sender_login_mismatch reject_unauthenticated_sender_login_mismatch a b dt 
+ dt b a name reject_unknown_sender_domain reject_unknown_sender_domain a b dt 
+ dt b a name check_address_map check_address_map a i a href DATABASE_README html type table a i b dt 
+ PARAM postscreen_dnsbl_max_ttl postscreen_dnsbl_ttl postscreen_dnsbl_ttl 1 h
index 8a46857979aa849006bbbfc45e1128e8caf973a7..912bffcecf9c193b1a8216976dcd9b2155a2d8e7 100644 (file)
@@ -66,3 +66,4 @@ spammy
 Birta
 Levente
 MariaDB
+dehtml
index 9bc0b9db414bd659abc2a56921d623e635ea2cbe..74815bed3a9726f237f401b6f894fa93c9570d2d 100644 (file)
@@ -68,7 +68,7 @@
   * Non-cleanup errors that live in the same bitmask space, to centralize
   * error handling.
   */
-#define CLEANUP_STAT_BARE_LF   (1<<16) /* Bare <LF> received */
+#define CLEANUP_STAT_BARE_LF   (1<<16) /* Bare <LF> received */
 
  /*
   * These are set when we can't bounce even if we were asked to.
index 338dc667df54a31b2173a7a3c760411cb9e4977d..d21e5bfe04fe8f308fa0c619f4dfd66d776893f9 100644 (file)
@@ -4306,11 +4306,14 @@ extern char *var_smtpd_dns_re_filter;
   * Backwards compatibility.
   */
 #define VAR_SMTPD_FORBID_BARE_LF       "smtpd_forbid_bare_newline"
-#define DEF_SMTPD_FORBID_BARE_LF       1
+#define DEF_SMTPD_FORBID_BARE_LF       "normalize"
 
 #define VAR_SMTPD_FORBID_BARE_LF_EXCL  "smtpd_forbid_bare_newline_exclusions"
 #define DEF_SMTPD_FORBID_BARE_LF_EXCL  "$" VAR_MYNETWORKS
 
+#define VAR_SMTPD_FORBID_BARE_LF_CODE  "smtpd_forbid_bare_newline_reject_code"
+#define DEF_SMTPD_FORBID_BARE_LF_CODE  550
+
  /*
   * Share TLS sessions through tlsproxy(8).
   */
index 013508eacca8b0414da5e1bf50e993fed48e3ace..b2f0c79994c93a2496ac4843b6c2db81cff80958 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      "20231226"
+#define MAIL_RELEASE_DATE      "20240104"
 #define MAIL_VERSION_NUMBER    "3.9"
 
 #ifdef SNAPSHOT
index dccf279a711b2b1ef3e671de71ebfc03692cbb41..b22d245a1ecd76145e9e3446897f043ce36a96dd 100644 (file)
 /*     smtp_vprintf() is the machine underneath smtp_printf().
 /*
 /*     smtp_get_noexcept() implements the subset of smtp_get()
-/*     without timeouts and without making long jumps. Instead
+/*     without timeouts and without making long jumps. Instead,
 /*     query the stream status with vstream_feof() etc.
-/*     This function will set smtp_forbid_bare_lf when flagging
+/*     This function will set smtp_seen_bare_lf when flagging
 /*     input with a bare newline byte.
 /*
 /*     smtp_timeout_setup() is a backwards-compatibility interface
@@ -433,7 +433,7 @@ int     smtp_get_noexcept(VSTRING *vp, VSTREAM *stream, ssize_t bound, int flags
        vstring_truncate(vp, VSTRING_LEN(vp) - 1);
        if (smtp_forbid_bare_lf
            && (VSTRING_LEN(vp) == 0 || vstring_end(vp)[-1] != '\r'))
-           smtp_seen_bare_lf = 1;
+           smtp_seen_bare_lf = smtp_forbid_bare_lf;
        while (VSTRING_LEN(vp) > 0 && vstring_end(vp)[-1] == '\r')
            vstring_truncate(vp, VSTRING_LEN(vp) - 1);
        VSTRING_TERMINATE(vp);
index f3ab0305dc998d68760226ede966d2dbf76280f7..1fe3b003cfc57981ab8543236556810e2a634156 100644 (file)
 /*     command pipelining constraints.
 /* .PP
 /*     Available in Postfix 3.9, 3.8.4, 3.7.9, 3.6.13, 3.5.23 and later:
-/* .IP "\fBsmtpd_forbid_bare_newline (Postfix >= 3.9: yes)\fR"
-/*     Reply with "Error: bare <LF> received" and disconnect
-/*     when a remote SMTP client sends a line ending in <LF>, violating
-/*     the RFC 5321 requirement that lines must end in <CR><LF>.
+/* .IP "\fBsmtpd_forbid_bare_newline (Postfix >= 3.9: normalize)\fR"
+/*     Disconnect, reject, or normalize commands and email message
+/*     content when a remote SMTP client sends lines ending in <LF>.
 /* .IP "\fBsmtpd_forbid_bare_newline_exclusions ($mynetworks)\fR"
 /*     Exclude the specified clients from smtpd_forbid_bare_newline
 /*     enforcement.
+/* .PP
+/*     Available in Postfix 3.9, 3.8.5, 3.7.10, 3.6.14, 3.5.24 and
+/*     later:
+/* .IP "\fBsmtpd_forbid_bare_newline_reject_code (550)\fR"
+/*     The numerical Postfix SMTP server response code when a request
+/*     is rejected by the \fBsmtpd_forbid_bare_newline\fR feature.
 /* TARPIT CONTROLS
 /* .ad
 /* .fi
@@ -1542,8 +1547,10 @@ bool    var_relay_before_rcpt_checks;
 bool    var_smtpd_req_deadline;
 int     var_smtpd_min_data_rate;
 char   *var_hfrom_format;
-bool    var_smtpd_forbid_bare_lf;
+char   *var_smtpd_forbid_bare_lf;
 char   *var_smtpd_forbid_bare_lf_excl;
+int     var_smtpd_forbid_bare_lf_code;
+static int bare_lf_mask;
 static NAMADR_LIST *bare_lf_excl;
 
  /*
@@ -1643,6 +1650,23 @@ static DICT *smtpd_cmd_filter;
   */
 int     smtpd_hfrom_format;
 
+ /*
+  * Bare newline handling.
+  */
+#define BARE_LF_FLAG_NORMALIZE (1<<0)  /* Best effort */
+#define BARE_LF_FLAG_REJECT    (1<<1)  /* Purist */
+
+#define IS_BARE_LF_NORMALIZE(m)        ((m) & BARE_LF_FLAG_NORMALIZE)
+#define IS_BARE_LF_REJECT(m)   ((m) & BARE_LF_FLAG_REJECT)
+
+static const NAME_CODE bare_lf_masks[] = {
+    "normalize", BARE_LF_FLAG_NORMALIZE,
+    "yes", BARE_LF_FLAG_NORMALIZE,
+    "reject", BARE_LF_FLAG_REJECT,
+    "no", 0,
+    0, -1,                             /* error */
+};
+
 #ifdef USE_SASL_AUTH
 
  /*
@@ -3598,6 +3622,8 @@ static void receive_data_message(SMTPD_STATE *state,
     int     curr_rec_type;
     int     prev_rec_type;
     int     first = 1;
+    int     prev_seen_bare_lf = 0;
+    int     expect_crlf_dot = 0;
 
     /*
      * If deadlines are enabled, increase the time budget as message content
@@ -3618,13 +3644,15 @@ static void receive_data_message(SMTPD_STATE *state,
      * XXX Deal with UNIX-style From_ lines at the start of message content
      * because sendmail permits it.
      */
-    for (prev_rec_type = 0; /* void */ ; prev_rec_type = curr_rec_type) {
+    for (prev_rec_type = 0; /* void */ ; prev_rec_type = curr_rec_type,
+        expect_crlf_dot = (expect_crlf_dot || smtp_seen_bare_lf == 0),
+        prev_seen_bare_lf = smtp_seen_bare_lf) {
        if (smtp_get(state->buffer, state->client, var_line_limit,
                     SMTP_GET_FLAG_NONE) == '\n')
            curr_rec_type = REC_TYPE_NORM;
        else
            curr_rec_type = REC_TYPE_CONT;
-       if (smtp_seen_bare_lf)
+       if (IS_BARE_LF_REJECT(smtp_seen_bare_lf))
            state->err |= CLEANUP_STAT_BARE_LF;
        start = vstring_str(state->buffer);
        len = VSTRING_LEN(state->buffer);
@@ -3638,9 +3666,18 @@ static void receive_data_message(SMTPD_STATE *state,
            if (len > 0 && IS_SPACE_TAB(start[0]))
                out_record(out_stream, REC_TYPE_NORM, "", 0);
        }
-       if (prev_rec_type != REC_TYPE_CONT && *start == '.'
-           && (proxy == 0 ? (++start, --len) == 0 : len == 1))
-           break;
+       if (prev_rec_type != REC_TYPE_CONT && *start == '.') {
+           if (len == 1 && prev_seen_bare_lf && expect_crlf_dot) {
+               if (IS_BARE_LF_NORMALIZE(prev_seen_bare_lf))
+                   msg_info("%s: skipping unexpected <LF>.%s in DATA from %s",
+                            state->queue_id ? state->queue_id : "NOQUEUE",
+                            smtp_seen_bare_lf ? "<LF>" : "<CR><LF>",
+                            state->namaddr);
+               continue;
+           }
+           if (proxy == 0 ? (++start, --len) == 0 : len == 1)
+               break;
+       }
        if (state->err == CLEANUP_STAT_OK) {
            if (ENFORCING_SIZE_LIMIT(var_message_limit)
                && var_message_limit - state->act_size < len + 2) {
@@ -3794,11 +3831,10 @@ static int common_post_message_handling(SMTPD_STATE *state)
            smtpd_chat_reply(state,
                             "250 2.0.0 Ok: queued as %s", state->queue_id);
     } else if ((state->err & CLEANUP_STAT_BARE_LF) != 0) {
-       /* Disconnect immediately. */
        state->error_mask |= MAIL_ERROR_PROTOCOL;
-       msg_info("disconnect: bare <LF> received from %s", state->namaddr);
-       smtpd_chat_reply(state, "521 5.5.2 %s Error: bare <LF> received",
-                        var_myhostname);
+       log_whatsup(state, "reject", "bare <LF> received");
+       smtpd_chat_reply(state, "%d 5.5.2 %s Error: bare <LF> received",
+                        var_smtpd_forbid_bare_lf_code, var_myhostname);
     } else if (why && IS_SMTP_REJECT(STR(why))) {
        state->error_mask |= MAIL_ERROR_POLICY;
        smtpd_chat_reply(state, "%s", STR(why));
@@ -4123,7 +4159,7 @@ static int bdat_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
                /* Skip the out_record() and VSTRING_RESET() calls below. */
                break;
            }
-           if (smtp_seen_bare_lf)
+           if (IS_BARE_LF_REJECT(smtp_seen_bare_lf))
                state->err |= CLEANUP_STAT_BARE_LF;
            start = vstring_str(state->bdat_get_buffer);
            len = VSTRING_LEN(state->bdat_get_buffer);
@@ -4776,9 +4812,9 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
      */
     xclient_allowed =
        namadr_list_match(xclient_hosts, state->name, state->addr);
-    smtp_forbid_bare_lf = SMTPD_STAND_ALONE((state)) == 0
-       && var_smtpd_forbid_bare_lf
-       && !namadr_list_match(bare_lf_excl, state->name, state->addr);
+    smtp_forbid_bare_lf = (SMTPD_STAND_ALONE((state)) == 0 && bare_lf_mask
+           && !namadr_list_match(bare_lf_excl, state->name, state->addr)) ?
+       bare_lf_mask : 0;
     /* NOT: tls_reset() */
     if (got_helo == 0)
        helo_reset(state);
@@ -5820,13 +5856,11 @@ static void smtpd_proto(SMTPD_STATE *state)
            }
            watchdog_pat();
            smtpd_chat_query(state);
-           if (smtp_seen_bare_lf) {
-               msg_info("disconnect: bare <LF> received from %s",
-                        state->namaddr);
+           if (IS_BARE_LF_REJECT(smtp_seen_bare_lf)) {
+               log_whatsup(state, "reject", "bare <LF> received");
                state->error_mask |= MAIL_ERROR_PROTOCOL;
-               smtpd_chat_reply(state,
-                                "521 5.5.2 %s Error: bare <LF> received",
-                                var_myhostname);
+               smtpd_chat_reply(state, "%d 5.5.2 %s Error: bare <LF> received",
+                            var_smtpd_forbid_bare_lf_code, var_myhostname);
                break;
            }
            /* Safety: protect internal interfaces against malformed UTF-8. */
@@ -6180,9 +6214,9 @@ static void smtpd_service(VSTREAM *stream, char *service, char **argv)
     /*
      * Enforce strict SMTP line endings, with compatibility exclusions.
      */
-    smtp_forbid_bare_lf = SMTPD_STAND_ALONE((&state)) == 0
-       && var_smtpd_forbid_bare_lf
-       && !namadr_list_match(bare_lf_excl, state.name, state.addr);
+    smtp_forbid_bare_lf = (SMTPD_STAND_ALONE((&state)) == 0 && bare_lf_mask
+             && !namadr_list_match(bare_lf_excl, state.name, state.addr)) ?
+       bare_lf_mask : 0;
 
     /*
      * See if we need to turn on verbose logging for this client.
@@ -6249,6 +6283,10 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
                                    MATCH_FLAG_RETURN
                                    | match_parent_style(VAR_MYNETWORKS),
                                    var_smtpd_forbid_bare_lf_excl);
+    if ((bare_lf_mask = name_code(bare_lf_masks, NAME_CODE_FLAG_NONE,
+                                 var_smtpd_forbid_bare_lf)) < 0)
+       msg_fatal("bad parameter value: '%s = %s'",
+                 VAR_SMTPD_FORBID_BARE_LF, var_smtpd_forbid_bare_lf);
 
     /*
      * Open maps before dropping privileges so we can read passwords etc.
@@ -6548,6 +6586,7 @@ int     main(int argc, char **argv)
        VAR_VIRT_MAILBOX_CODE, DEF_VIRT_MAILBOX_CODE, &var_virt_mailbox_code, 0, 0,
        VAR_RELAY_RCPT_CODE, DEF_RELAY_RCPT_CODE, &var_relay_rcpt_code, 0, 0,
        VAR_PLAINTEXT_CODE, DEF_PLAINTEXT_CODE, &var_plaintext_code, 0, 0,
+       VAR_SMTPD_FORBID_BARE_LF_CODE, DEF_SMTPD_FORBID_BARE_LF_CODE, &var_smtpd_forbid_bare_lf_code, 500, 599,
        VAR_SMTPD_CRATE_LIMIT, DEF_SMTPD_CRATE_LIMIT, &var_smtpd_crate_limit, 0, 0,
        VAR_SMTPD_CCONN_LIMIT, DEF_SMTPD_CCONN_LIMIT, &var_smtpd_cconn_limit, 0, 0,
        VAR_SMTPD_CMAIL_LIMIT, DEF_SMTPD_CMAIL_LIMIT, &var_smtpd_cmail_limit, 0, 0,
@@ -6615,7 +6654,6 @@ int     main(int argc, char **argv)
        VAR_SMTPD_DELAY_OPEN, DEF_SMTPD_DELAY_OPEN, &var_smtpd_delay_open,
        VAR_SMTPD_CLIENT_PORT_LOG, DEF_SMTPD_CLIENT_PORT_LOG, &var_smtpd_client_port_log,
        VAR_SMTPD_FORBID_UNAUTH_PIPE, DEF_SMTPD_FORBID_UNAUTH_PIPE, &var_smtpd_forbid_unauth_pipe,
-       VAR_SMTPD_FORBID_BARE_LF, DEF_SMTPD_FORBID_BARE_LF, &var_smtpd_forbid_bare_lf,
        0,
     };
     static const CONFIG_NBOOL_TABLE nbool_table[] = {
@@ -6733,6 +6771,7 @@ int     main(int argc, char **argv)
        VAR_SMTPD_REJ_FTR_MAPS, DEF_SMTPD_REJ_FTR_MAPS, &var_smtpd_rej_ftr_maps, 0, 0,
        VAR_HFROM_FORMAT, DEF_HFROM_FORMAT, &var_hfrom_format, 1, 0,
        VAR_SMTPD_FORBID_BARE_LF_EXCL, DEF_SMTPD_FORBID_BARE_LF_EXCL, &var_smtpd_forbid_bare_lf_excl, 0, 0,
+       VAR_SMTPD_FORBID_BARE_LF, DEF_SMTPD_FORBID_BARE_LF, &var_smtpd_forbid_bare_lf, 1, 0,
        0,
     };
     static const CONFIG_RAW_TABLE raw_table[] = {
index 560cd0b2e084a68475e3daf964157edc06037e98..975fcbe79b4b3ad290cf699f862486d25f0f0cef 100644 (file)
 /*
 /*     char    *smtpd_check_queue(state)
 /*     SMTPD_STATE *state;
+/* AUXILIARY FUNCTIONS
+/*     void    log_whatsup(state, action, text)
+/*     SMTPD_STATE *state;
+/*     const char *action;
+/*     const char *text;
 /* DESCRIPTION
 /*     This module implements additional checks on SMTP client requests.
 /*     A client request is validated in the context of the session state.
 /*     The recipient address given with the RCPT TO or VRFY command.
 /* .IP size
 /*     The message size given with the MAIL FROM command (zero if unknown).
+/* .PP
+/*     log_whatsup() logs "<queueid>: <action>: <protocol state>
+/*     from: <client-name[client-addr]>: <text>" plus the protocol
+/*     (SMTP or ESMTP), and if available, EHLO, MAIL FROM, or RCPT
+/*     TO.
 /* BUGS
 /*     Policies like these should not be hard-coded in C, but should
 /*     be user-programmable instead.
@@ -988,8 +998,8 @@ void    smtpd_check_init(void)
 
 /* log_whatsup - log as much context as we have */
 
-static void log_whatsup(SMTPD_STATE *state, const char *whatsup,
-                               const char *text)
+void    log_whatsup(SMTPD_STATE *state, const char *whatsup,
+                           const char *text)
 {
     VSTRING *buf = vstring_alloc(100);
 
@@ -5853,7 +5863,7 @@ char   *var_smtpd_dns_re_filter;
 bool    var_smtpd_tls_ask_ccert;
 int     var_smtpd_cipv4_prefix;
 int     var_smtpd_cipv6_prefix;
-bool   var_smtpd_tls_enable_rpk;
+bool    var_smtpd_tls_enable_rpk;
 
 #define int_table test_int_table
 
index ce24498e21a1c5d54672ff2792839dbf6233a942..bf0fe001ac178d91f7d0bb6498ecccb3c5f1d1a8 100644 (file)
@@ -25,6 +25,7 @@ extern char *smtpd_check_etrn(SMTPD_STATE *, char *);
 extern char *smtpd_check_data(SMTPD_STATE *);
 extern char *smtpd_check_eod(SMTPD_STATE *);
 extern char *smtpd_check_policy(SMTPD_STATE *, char *);
+extern void log_whatsup(SMTPD_STATE *, const char *, const char *);
 
 /* LICENSE
 /* .ad