From f75140fe8504f1fa69e98facbf8258b67af7ebff Mon Sep 17 00:00:00 2001
From: Wietse Venema
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 disbled 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).
+ +See +https://www.postfix.org/smtp-smuggling.html for details. + +
Example:
+ +++ ++# 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 ++
This feature is available in Postfix ≥ 3.9, 3.8.4, 3.7.9, +3.6.13, and 3.5.23.
+ + +Exclude the specified clients from smtpd_forbid_bare_newline +enforcement. It uses the same syntax and parent-domain matching +behavior as mynetworks.
+ +Example:
+ +++ ++# 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 ++
This feature is available in Postfix ≥ 3.9, 3.8.4, 3.7.9, +3.6.13, and 3.5.23.
+ +This feature is available in Postfix ≥ 3.9, 3.8.1, 3.7.6, 3.6.10, and 3.5.20.
+%PARAM smtpd_forbid_bare_newline Postfix < 3.9: no + +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 disbled 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).
+ +See +https://www.postfix.org/smtp-smuggling.html for details. + +
Example:
+ +++ ++# 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 ++
This feature is available in Postfix ≥ 3.9, 3.8.4, 3.7.9, +3.6.13, and 3.5.23.
+ +%PARAM smtpd_forbid_bare_newline_exclusions $mynetworks + +Exclude the specified clients from smtpd_forbid_bare_newline +enforcement. It uses the same syntax and parent-domain matching +behavior as mynetworks.
+ +Example:
+ +++ ++# 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 ++
This feature is available in Postfix ≥ 3.9, 3.8.4, 3.7.9, +3.6.13, and 3.5.23.
+ %PARAM smtpd_forbid_unauth_pipelining Postfix ≥ 3.9: yes Disconnect remote SMTP clients that violate RFC 2920 (or 5321)
diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h
index ccf0b259b..87973bd41 100644
--- a/postfix/src/global/mail_params.h
+++ b/postfix/src/global/mail_params.h
@@ -4142,7 +4142,16 @@ extern char *var_smtp_dns_re_filter;
extern char *var_smtpd_dns_re_filter;
/*
- * Share TLS sessions through tlproxy(8).
+ * Backwards compatibility.
+ */
+#define VAR_SMTPD_FORBID_BARE_LF "smtpd_forbid_bare_newline"
+#define DEF_SMTPD_FORBID_BARE_LF 0
+
+#define VAR_SMTPD_FORBID_BARE_LF_EXCL "smtpd_forbid_bare_newline_exclusions"
+#define DEF_SMTPD_FORBID_BARE_LF_EXCL "$" VAR_MYNETWORKS
+
+ /*
+ * Share TLS sessions through tlsproxy(8).
*/
#define VAR_SMTP_TLS_CONN_REUSE "smtp_tls_connection_reuse"
#define DEF_SMTP_TLS_CONN_REUSE 0
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index e7aaad923..6332387b7 100644
--- a/postfix/src/global/mail_version.h
+++ b/postfix/src/global/mail_version.h
@@ -20,8 +20,8 @@
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20231101"
-#define MAIL_VERSION_NUMBER "3.5.22"
+#define MAIL_RELEASE_DATE "20231222"
+#define MAIL_VERSION_NUMBER "3.5.23"
#ifdef SNAPSHOT
#define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE
diff --git a/postfix/src/global/smtp_stream.c b/postfix/src/global/smtp_stream.c
index a42cdcfd2..cb611d1b2 100644
--- a/postfix/src/global/smtp_stream.c
+++ b/postfix/src/global/smtp_stream.c
@@ -50,6 +50,8 @@
/* VSTREAM *stream;
/* char *format;
/* va_list ap;
+/*
+/* int smtp_forbid_bare_lf;
/* AUXILIARY API
/* int smtp_get_noexcept(vp, stream, maxlen, flags)
/* VSTRING *vp;
@@ -124,11 +126,16 @@
/* 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 long jumps for timeout or EOF errors. Instead,
/* query the stream status with vstream_feof() etc.
+/* This function will make a VSTREAM long jump (error code
+/* SMTP_ERR_LF) when rejecting input with a bare newline byte.
/*
/* smtp_timeout_setup() is a backwards-compatibility interface
/* for programs that don't require per-record deadline support.
+/*
+/* smtp_forbid_bare_lf controls whether smtp_get_noexcept()
+/* will reject input with a bare newline byte.
/* DIAGNOSTICS
/* .fi
/* .ad
@@ -201,6 +208,8 @@
#include "smtp_stream.h"
+int smtp_forbid_bare_lf;
+
/* smtp_timeout_reset - reset per-stream error flags, restart deadline timer */
static void smtp_timeout_reset(VSTREAM *stream)
@@ -404,6 +413,9 @@ int smtp_get_noexcept(VSTRING *vp, VSTREAM *stream, ssize_t bound, int flags
*/
case '\n':
vstring_truncate(vp, VSTRING_LEN(vp) - 1);
+ if (smtp_forbid_bare_lf
+ && (VSTRING_LEN(vp) == 0 || vstring_end(vp)[-1] != '\r'))
+ vstream_longjmp(stream, SMTP_ERR_LF);
while (VSTRING_LEN(vp) > 0 && vstring_end(vp)[-1] == '\r')
vstring_truncate(vp, VSTRING_LEN(vp) - 1);
VSTRING_TERMINATE(vp);
diff --git a/postfix/src/global/smtp_stream.h b/postfix/src/global/smtp_stream.h
index ec824b3c3..da1c68af8 100644
--- a/postfix/src/global/smtp_stream.h
+++ b/postfix/src/global/smtp_stream.h
@@ -32,6 +32,7 @@
#define SMTP_ERR_QUIET 3 /* silent cleanup (application) */
#define SMTP_ERR_NONE 4 /* non-error case */
#define SMTP_ERR_DATA 5 /* application data error */
+#define SMTP_ERR_LF 6 /* bare