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 enabled by default with Postfix ≥ 3.9 but may +not work with non-standard clients such as netcat. Specify +"smtpd_forbid_bare_newline = no" to disable (not recommended for +an Internet-connected MTA).
+ +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: 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 but may +not work with non-standard clients such as netcat. Specify +"smtpd_forbid_bare_newline = no" to disable (not recommended for +an Internet-connected MTA).
+ +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/proto/stop b/postfix/proto/stop
index 66dd2dab1..375597d29 100644
--- a/postfix/proto/stop
+++ b/postfix/proto/stop
@@ -1588,3 +1588,4 @@ sni
Amawalk
resychronization
ENVID
+netcat
diff --git a/postfix/proto/stop.double-history b/postfix/proto/stop.double-history
index 68d5bd80f..b75d9c7dc 100644
--- a/postfix/proto/stop.double-history
+++ b/postfix/proto/stop.double-history
@@ -81,3 +81,4 @@ proto proto aliases proto virtual proto ADDRESS_REWRITING_README html
client process name File proxymap proxymap c
available Files local command c local local c
ID if available File pipe pipe c
+ global smtp_stream h smtpd smtpd c
diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h
index 11d58a6e7..244f05f51 100644
--- a/postfix/src/global/mail_params.h
+++ b/postfix/src/global/mail_params.h
@@ -4302,6 +4302,12 @@ extern char *var_smtp_dns_re_filter;
#define DEF_SMTPD_DNS_RE_FILTER ""
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
+
/*
* Share TLS sessions through tlsproxy(8).
*/
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index 3f684bfb1..2bfce0ea5 100644
--- a/postfix/src/global/mail_version.h
+++ b/postfix/src/global/mail_version.h
@@ -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 "20231213"
+#define MAIL_RELEASE_DATE "20231219"
#define MAIL_VERSION_NUMBER "3.9"
#ifdef SNAPSHOT
diff --git a/postfix/src/global/smtp_stream.c b/postfix/src/global/smtp_stream.c
index 595a159f0..b7209009d 100644
--- a/postfix/src/global/smtp_stream.c
+++ b/postfix/src/global/smtp_stream.c
@@ -52,6 +52,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;
@@ -131,11 +133,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 deadline or data-rate support.
+/*
+/* smtp_forbid_bare_lf controls whether smtp_get_noexcept()
+/* will reject input with a bare newline byte.
/* DIAGNOSTICS
/* .fi
/* .ad
@@ -214,6 +221,7 @@
* the buffer. Such system calls would really hurt when receiving or sending
* body content one line at a time.
*/
+int smtp_forbid_bare_lf;
/* smtp_timeout_reset - reset per-stream error flags */
@@ -418,6 +426,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 75700fed3..4bcd6b59b 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