From f172a89c065d732898181b0b3f8e7abdae533d06 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Tue, 9 Jul 2024 10:44:57 +0800 Subject: [PATCH] Reject "dot, LF" as ending data phase. Bug 3063 --- src/receive.c | 15 +++++++++++---- src/smtp_in.c | 13 ++++++++----- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/receive.c b/src/receive.c index 0a27c79..8639fa9 100644 --- a/src/receive.c +++ b/src/receive.c @@ -1948,8 +1948,10 @@ for (;;) if (ch == '\n') { - if (first_line_ended_crlf == TRUE_UNSET) first_line_ended_crlf = FALSE; - else if (first_line_ended_crlf) receive_ungetc(' '); + if (first_line_ended_crlf == TRUE_UNSET) + first_line_ended_crlf = FALSE; + else if (first_line_ended_crlf) + receive_ungetc(' '); goto EOL; } @@ -1965,7 +1967,11 @@ for (;;) if (f.dot_ends && ptr == 0 && ch == '.') { ch = (receive_getc)(GETC_BUFFER_UNLIMITED); - if (ch == '\r') + if (ch == '\n' && first_line_ended_crlf == TRUE /* and not TRUE_UNSET */ ) + /* dot, LF but we are in CRLF mode. Attack? */ + ch = ' '; /* replace the LF with a space */ + + else if (ch == '\r') { ch = (receive_getc)(GETC_BUFFER_UNLIMITED); if (ch != '\n') @@ -2001,7 +2007,8 @@ for (;;) ch = (receive_getc)(GETC_BUFFER_UNLIMITED); if (ch == '\n') { - if (first_line_ended_crlf == TRUE_UNSET) first_line_ended_crlf = TRUE; + if (first_line_ended_crlf == TRUE_UNSET) + first_line_ended_crlf = TRUE; goto EOL; } diff --git a/src/smtp_in.c b/src/smtp_in.c index edb0adf..3119bad 100644 --- a/src/smtp_in.c +++ b/src/smtp_in.c @@ -5432,15 +5432,18 @@ while (done <= 0) } if (chunking_state > CHUNKING_OFFERED) - rc = OK; /* No predata ACL or go-ahead output for BDAT */ + rc = OK; /* There is no predata ACL or go-ahead output for BDAT */ else { - /* If there is an ACL, re-check the synchronization afterwards, since the - ACL may have delayed. To handle cutthrough delivery enforce a dummy call - to get the DATA command sent. */ + /* If there is a predata-ACL, re-check the synchronization afterwards, + since the ACL may have delayed. To handle cutthrough delivery enforce a + dummy call to get the DATA command sent. */ if (!acl_smtp_predata && cutthrough.cctx.sock < 0) - rc = OK; + { + if (!check_sync()) goto SYNC_FAILURE; + rc = OK; + } else { uschar * acl = acl_smtp_predata ? acl_smtp_predata : US"accept"; -- 2.27.0