Re: [Exim] bare linefeeds in SMTP

Top Page
Delete this message
Reply to this message
Author: Kjetil Torgrim Homme
Date:  
To: exim-users
Old-Topics: Re: [Exim] bare linefeeds in SMTP
Subject: Re: [Exim] bare linefeeds in SMTP
--
On Fri, 2003-12-19 at 19:11, Kjetil Torgrim Homme wrote:
> On Fri, 2003-12-19 at 10:52, Philip Hazel wrote:
> > Possibly. I need to think about this. "If first line of DATA is
> > terminated by CRLF, then fixup bare LF in header lines" might indeed be
> > the best heuristic.
>
> I'll have a look at it.


my apologies for taking so long for something so small, please consider
the enclosed patch for the next release of Exim.

notice:

* the heuristic is applied regardless of the source of the message.

* if strict mode has been entered, "LF . LF" will not terminate DATA;
however, "CR LF . LF" will.  I don't think adding the code to be
pedantically correct is worthwhile, it's certainly not a common
occurence to terminate DATA within headers, and that dot should have
been dot stuffed by an RFC compliant sender.
--
Kjetil T.
--
--- exim-4.30/src/receive.c.~1~    Mon Dec  1 11:15:41 2003
+++ exim-4.30/src/receive.c    Thu Feb 19 06:32:11 2004
@@ -956,6 +956,7 @@
 BOOL had_zero = FALSE;
 BOOL smtp_yield = TRUE;
 BOOL yield = FALSE;
+enum { CRLF_UNKNOWN, CRLF_STRICT, CRLF_LENIENT } crlf_mode = CRLF_UNKNOWN;


BOOL resents_exist = FALSE;
uschar *resent_prefix = US"";
@@ -1142,8 +1143,23 @@
other MTAs accept this. We are therefore forced into this "liberalisation"
too. */

-  if (ch == EOF || ch == '\n') goto EOL;
-
+  if (ch == EOF) goto EOL;
+  if (ch == '\n')
+    switch (crlf_mode)
+      {
+      case CRLF_UNKNOWN:
+      crlf_mode = CRLF_LENIENT;
+      /* Fall through */
+      case CRLF_LENIENT:
+      goto EOL;
+      case CRLF_STRICT:
+      /* The very first line of the DATA input was properly CR LF
+      terminated, so assume that the complete message has proper CR LF
+      endings.  In such messages, bare linefeeds must be escaped. */
+      next->text[ptr++] = '\n';
+      message_size++;
+      ch = ' ';
+      }


   /* This is not the end of the line. If this is SMTP input and this is
   the first character in the line and it is a "." character, ignore it.
@@ -1185,12 +1201,18 @@
       }
     }


- /* If CR is immediately followed by LF, end the line, ignoring the CR. */
+ /* If CR is immediately followed by LF, end the line, ignoring the CR.
+ If this is the first line, enter strict mode, requiring every line to
+ be terminated by CR LF. */

   if (ch == '\r')
     {
     ch = (receive_getc)();
-    if (ch == '\n') goto EOL;
+    if (ch == '\n')
+      {
+      if (crlf_mode == CRLF_UNKNOWN) crlf_mode = CRLF_STRICT;
+      goto EOL;
+      }


     /* Otherwise, put back the character after CR, and turn the bare CR
     into LF SP. */
--