Fix bug in previous patch: following data is permitted after '.' so it
authorPhilip Hazel <ph10@hermes.cam.ac.uk>
Mon, 16 Apr 2007 10:31:58 +0000 (10:31 +0000)
committerPhilip Hazel <ph10@hermes.cam.ac.uk>
Mon, 16 Apr 2007 10:31:58 +0000 (10:31 +0000)
must not be diagnosed as an error. The check for vanished socket can
only be applied when there is no data pending.

15 files changed:
doc/doc-txt/ChangeLog
src/src/receive.c
test/log/0559
test/log/2029
test/log/2150
test/scripts/0000-Basic/0300
test/scripts/0000-Basic/0301
test/scripts/0000-Basic/0559
test/scripts/2000-GnuTLS/2029
test/scripts/2100-OpenSSL/2150
test/stdout/0300
test/stdout/0301
test/stdout/0559
test/stdout/2029
test/stdout/2150

index 4a8d41d6657c8427580dfa9c08c449d4098540d0..db68bdae1957f2b531ad3b7963e0484c549ab195 100644 (file)
@@ -1,4 +1,4 @@
-$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.502 2007/04/13 15:13:47 ph10 Exp $
+$Cambridge: exim/doc/doc-txt/ChangeLog,v 1.503 2007/04/16 10:31:58 ph10 Exp $
 
 Change log file for Exim from version 4.21
 -------------------------------------------
 
 Change log file for Exim from version 4.21
 -------------------------------------------
@@ -203,14 +203,16 @@ SC/03 Eximstats - V1.58 Fix to get <> and blackhole to show in edomain tables.
 PH/43 Yet another patch from the Sieve maintainer.
 
 PH/44 I found a way to check for a TCP/IP connection going away before sending
 PH/43 Yet another patch from the Sieve maintainer.
 
 PH/44 I found a way to check for a TCP/IP connection going away before sending
-      the response to the final '.' that terminates a message. At this time,
-      there should not be any pending input - the client should be waiting for
-      the response. Therefore, a select() can be used: if it shows that the
-      input is "ready", there is either input waiting, or the socket has been
-      closed. Both cases are errors. (It's a bit more complicated than this
-      because of buffering, but that's the essence of it.) Previously, Exim
+      the response to the final '.' that terminates a message, but only in the
+      case where the client has not sent further data following the '.'
+      (unfortunately, this is allowed). However, in many cases there won't be
+      any further data because there won't be any more messages to send. A call
+      to select() can be used: if it shows that the input is "ready", there is
+      either input waiting, or the socket has been closed. An attempt to read
+      the next input character can distinguish the two cases. Previously, Exim
       would have sent an OK response which the client would never have see.
       would have sent an OK response which the client would never have see.
-      This could lead to message repetition. This fix should cure that.
+      This could lead to message repetition. This fix should cure that, at
+      least in a lot of common cases.
 
 
 Exim version 4.66
 
 
 Exim version 4.66
index 98a728b2fcbe49422aaff04c70b5663ea210ff9a..e4c82d2fa7e7087e31fdaf6e822f7e78f3f24f1f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/receive.c,v 1.36 2007/04/13 15:13:47 ph10 Exp $ */
+/* $Cambridge: exim/src/src/receive.c,v 1.37 2007/04/16 10:31:58 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -3436,21 +3436,26 @@ to cause a call to receive_bomb_out() if the log cannot be opened. */
 
 receive_call_bombout = TRUE;
 
 
 receive_call_bombout = TRUE;
 
-/* Before sending an SMTP response in a TCP/IP session, we check to see if
-there is unconsumed input (which there shouldn't be) or if the connection has
-gone away. This can be done because the end of a message is always a
-synchronization point. If the connection is still present, but there is no
-pending input, the result of a select() call will be zero. If, however, the
-connection has gone away, or if there is pending input, the result of select()
-will be non-zero. The two cases can be distinguished by trying to read the next
-input character. Of course, since TCP/IP is asynchronous, there is always a
-chance that the connection will vanish between the time of this test and the
-sending of the response, but the chance of this happening should be small.
+/* Before sending an SMTP response in a TCP/IP session, we check to see if the
+connection has gone away. This can only be done if there is no unconsumed input
+waiting in the local input buffer. We can test for this by calling
+receive_smtp_buffered(). RFC 2920 (pipelining) explicitly allows for additional
+input to be sent following the final dot, so the presence of following input is
+not an error.
 
 
-We also check for input that has already been received and is in the local
-input buffer (plain SMTP or TLS) by calling receive_smtp_buffered(). */
+If the connection is still present, but there is no unread input for the
+socket, the result of a select() call will be zero. If, however, the connection
+has gone away, or if there is pending input, the result of select() will be
+non-zero. The two cases can be distinguished by trying to read the next input
+character. If we succeed, we can unread it so that it remains in the local
+buffer for handling later. If not, the connection has been lost.
 
 
-if (smtp_input && sender_host_address != NULL && !sender_host_notsocket)
+Of course, since TCP/IP is asynchronous, there is always a chance that the
+connection will vanish between the time of this test and the sending of the
+response, but the chance of this happening should be small. */
+
+if (smtp_input && sender_host_address != NULL && !sender_host_notsocket &&
+    !receive_smtp_buffered())
   {
   struct timeval tv;
   fd_set select_check;
   {
   struct timeval tv;
   fd_set select_check;
@@ -3459,47 +3464,39 @@ if (smtp_input && sender_host_address != NULL && !sender_host_notsocket)
   tv.tv_sec = 0;
   tv.tv_usec = 0;
 
   tv.tv_sec = 0;
   tv.tv_usec = 0;
 
-  if (select(fileno(smtp_in) + 1, &select_check, NULL, NULL, &tv) != 0 ||
-      receive_smtp_buffered())
+  if (select(fileno(smtp_in) + 1, &select_check, NULL, NULL, &tv) != 0)
     {
     {
-    uschar *msg;
-    if ((RECEIVE_GETC)() == EOF)
-      {
-      msg = US"SMTP connection lost after final dot";
-      smtp_reply = US"";   /* No attempt to send a response */
-      }
-    else
+    int c = (RECEIVE_GETC)();
+    if (c != EOF) (RECEIVE_UNGETC)(c); else
       {
       {
-      msg = US"Synchronization error (data after final dot)";
-      smtp_reply = US"550 Synchronization error (data after final dot)";
-      }
-
-    /* Overwrite the log line workspace */
+      uschar *msg = US"SMTP connection lost after final dot";
+      smtp_reply = US"";    /* No attempt to send a response */
+      smtp_yield = FALSE;   /* Nothing more on this connection */
 
 
-    sptr = 0;
-    s = string_cat(s, &size, &sptr, msg, Ustrlen(msg));
-    s = add_host_info_for_log(s, &size, &sptr);
-    s[sptr] = 0;
-    log_write(0, LOG_MAIN, "%s", s);
+      /* Re-use the log line workspace */
 
 
-    /* We now have to delete the files for this aborted message. */
+      sptr = 0;
+      s = string_cat(s, &size, &sptr, msg, Ustrlen(msg));
+      s = add_host_info_for_log(s, &size, &sptr);
+      s[sptr] = 0;
+      log_write(0, LOG_MAIN, "%s", s);
 
 
-    sprintf(CS spool_name, "%s/input/%s/%s-D", spool_directory, message_subdir,
-      message_id);
-    Uunlink(spool_name);
+      /* Delete the files for this aborted message. */
 
 
-    sprintf(CS spool_name, "%s/input/%s/%s-H", spool_directory, message_subdir,
-      message_id);
-    Uunlink(spool_name);
+      sprintf(CS spool_name, "%s/input/%s/%s-D", spool_directory,
+        message_subdir, message_id);
+      Uunlink(spool_name);
 
 
-    sprintf(CS spool_name, "%s/msglog/%s/%s", spool_directory, message_subdir,
-      message_id);
-    Uunlink(spool_name);
+      sprintf(CS spool_name, "%s/input/%s/%s-H", spool_directory,
+        message_subdir, message_id);
+      Uunlink(spool_name);
 
 
-    /* Do not accept any more messages on this connection. */
+      sprintf(CS spool_name, "%s/msglog/%s/%s", spool_directory,
+        message_subdir, message_id);
+      Uunlink(spool_name);
 
 
-    smtp_yield = FALSE;
-    goto TIDYUP;
+      goto TIDYUP;
+      }
     }
   }
 
     }
   }
 
index 077691e9563d225ba5f3ec041c27cbf344cba008..fcae1cf93a9baf8633b687af889731229b42d726 100644 (file)
@@ -1,4 +1,2 @@
 1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
 1999-03-02 09:44:33 10HmaX-0005vi-00 SMTP connection lost after final dot H=(abcd) [127.0.0.1] P=esmtp
 1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
 1999-03-02 09:44:33 10HmaX-0005vi-00 SMTP connection lost after final dot H=(abcd) [127.0.0.1] P=esmtp
-1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
-1999-03-02 09:44:33 10HmaY-0005vi-00 Synchronization error (data after final dot) H=(abcd) [127.0.0.1] P=esmtp
index 737b6977b4d6d9dcb868fdece1582aab336a59e3..0e16a7b246948783cc69fae44d783ffdde1ab792 100644 (file)
@@ -1,5 +1,3 @@
 1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
 1999-03-02 09:44:33 10HmaX-0005vi-00 TLS recv error on connection from [127.0.0.1]: A TLS packet with unexpected length was received.
 1999-03-02 09:44:33 10HmaX-0005vi-00 SMTP connection lost after final dot H=[127.0.0.1] P=smtps
 1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
 1999-03-02 09:44:33 10HmaX-0005vi-00 TLS recv error on connection from [127.0.0.1]: A TLS packet with unexpected length was received.
 1999-03-02 09:44:33 10HmaX-0005vi-00 SMTP connection lost after final dot H=[127.0.0.1] P=smtps
-1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
-1999-03-02 09:44:33 10HmaY-0005vi-00 Synchronization error (data after final dot) H=[127.0.0.1] P=smtps
index 41ada44352cffcd93a5da2729257d17b71e5e862..01c430781175525e4e84af385866ed663fef7025 100644 (file)
@@ -1,4 +1,2 @@
 1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
 1999-03-02 09:44:33 10HmaX-0005vi-00 SMTP connection lost after final dot H=[127.0.0.1] P=smtps
 1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
 1999-03-02 09:44:33 10HmaX-0005vi-00 SMTP connection lost after final dot H=[127.0.0.1] P=smtps
-1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225
-1999-03-02 09:44:33 10HmaY-0005vi-00 Synchronization error (data after final dot) H=[127.0.0.1] P=smtps
index de3be10956feaa17b0e8045a57cbfc76d394a060..053aec80422fa57eda26c634b1db7a1b94558456 100644 (file)
@@ -23,9 +23,8 @@ rset\r\nmail from:<userx@test.ex>\r\nrcpt to:<userx@test.ex>\r\ndata
 ??? 250
 ??? 354
 the message
 ??? 250
 ??? 354
 the message
-.
+.\r\nmail from:<userx@test.ex>
 +++ 1
 +++ 1
-mail from:<userx@test.ex>
 rcpt to:<userx@test.ex>\r\ndata\r\nthe message\r\nsecond line
 ??? 250
 ??? 250
 rcpt to:<userx@test.ex>\r\ndata\r\nthe message\r\nsecond line
 ??? 250
 ??? 250
index f84244f05dbd16480a60da130f6e2bdd9b0cd785..4add8f42ceb1de393f2243985c8c22a7a72a37dc 100644 (file)
@@ -26,9 +26,8 @@ mail from:<userx@test.ex>\r\nrcpt to:<userx@test.ex>\r\ndata
 ??? 250
 ??? 354
 the message
 ??? 250
 ??? 354
 the message
-.
+.\r\nmail from:<userx@test.ex>\r\nrcpt to:<userx@test.ex>\r\ndata\r\nthe message
 ??? 250
 ??? 250
-mail from:<userx@test.ex>\r\nrcpt to:<userx@test.ex>\r\ndata\r\nthe message
 ??? 250
 ??? 250
 ??? 354
 ??? 250
 ??? 250
 ??? 354
index 01d7d99afcf27e0ccd62692f97382e176b7970b3..3729f25aba20df99bdfb250978c9c2685fa3fd5e 100644 (file)
@@ -20,25 +20,3 @@ This is a test message.
 ****
 sleep 1
 killdaemon
 ****
 sleep 1
 killdaemon
-#
-# Also check for next input sent too soon
-#
-exim -DSERVER=server -bd -oX PORT_D
-****
-client -t5 127.0.0.1 PORT_D
-??? 220
-ehlo abcd
-??? 250-
-??? 250-
-??? 250-
-??? 250
-mail from:<userx@test.ex>\r\nrcpt to:<userx@test.ex>\r\ndata
-??? 250
-??? 250
-??? 354
-This is a test message.
-.\r\nrset
-??? 550
-****
-sleep 1
-killdaemon
index e371e68d7e07d019fa32e83ac0161f909d85af2d..c2b35497b75b0aa111da63795c7ed2a6b8a5a576 100644 (file)
@@ -28,30 +28,3 @@ This is a test message.
 ****
 sleep 1
 killdaemon
 ****
 sleep 1
 killdaemon
-#
-# Also check for next input sent too soon
-#
-exim -DSERVER=server -bd -oX PORT_D
-****
-client-gnutls 127.0.0.1 PORT_D
-??? 220
-ehlo abcd
-??? 250-
-??? 250-
-??? 250-
-??? 250-
-??? 250
-starttls
-??? 220
-mail from:<userx@test.ex>
-??? 250
-rcpt to:<userx@test.ex>
-??? 250
-data
-??? 354
-This is a test message.
-.\r\nrset
-+++ 1
-****
-sleep 1
-killdaemon
index cfc6a20d75b3b7f657c4625eefcb07ef65a85a83..91cd38276b9d1405371a2026aef3a371198fc185 100644 (file)
@@ -26,30 +26,3 @@ This is a test message.
 ****
 sleep 1
 killdaemon
 ****
 sleep 1
 killdaemon
-#
-# Also check for next input sent too soon
-#
-exim -DSERVER=server -bd -oX PORT_D
-****
-client-gnutls 127.0.0.1 PORT_D
-??? 220
-ehlo abcd
-??? 250-
-??? 250-
-??? 250-
-??? 250-
-??? 250
-starttls
-??? 220
-mail from:<userx@test.ex>
-??? 250
-rcpt to:<userx@test.ex>
-??? 250
-data
-??? 354
-This is a test message.
-.\r\nrset
-+++ 1
-****
-sleep 1
-killdaemon
index 8dd5a3cc17efc5c5acc5ce138759b4ea9227fec8..a41df39d36e623f972fed426223e733855b12e7c 100644 (file)
@@ -27,9 +27,8 @@ Connecting to 127.0.0.1 port 1225 ... connected
 ??? 354
 <<< 354 Enter message, ending with "." on a line by itself
 >>> the message
 ??? 354
 <<< 354 Enter message, ending with "." on a line by itself
 >>> the message
->>> .
+>>> .\r\nmail from:<userx@test.ex>
 +++ 1
 +++ 1
->>> mail from:<userx@test.ex>
 >>> rcpt to:<userx@test.ex>\r\ndata\r\nthe message\r\nsecond line
 ??? 250
 <<< 250 OK id=10HmaX-0005vi-00
 >>> rcpt to:<userx@test.ex>\r\ndata\r\nthe message\r\nsecond line
 ??? 250
 <<< 250 OK id=10HmaX-0005vi-00
index 964f0c17b50c8bc7e90355131bbae2d1e1277250..198962d06fa4f088ebdb744090205faff79137d4 100644 (file)
@@ -36,10 +36,9 @@ Connecting to 127.0.0.1 port 1225 ... connected
 ??? 354
 <<< 354 Enter message, ending with "." on a line by itself
 >>> the message
 ??? 354
 <<< 354 Enter message, ending with "." on a line by itself
 >>> the message
->>> .
+>>> .\r\nmail from:<userx@test.ex>\r\nrcpt to:<userx@test.ex>\r\ndata\r\nthe message
 ??? 250
 <<< 250 OK id=10HmaX-0005vi-00
 ??? 250
 <<< 250 OK id=10HmaX-0005vi-00
->>> mail from:<userx@test.ex>\r\nrcpt to:<userx@test.ex>\r\ndata\r\nthe message
 ??? 250
 <<< 250 OK
 ??? 250
 ??? 250
 <<< 250 OK
 ??? 250
index eee1b2e4361e0efd027e5f7a10404741a08df4b3..71f5c45414b806e3960d611a0cb80ae5915552fe 100644 (file)
@@ -21,27 +21,3 @@ Connecting to 127.0.0.1 port 1225 ... connected
 >>> .
 +++ 1
 End of script
 >>> .
 +++ 1
 End of script
-Connecting to 127.0.0.1 port 1225 ... connected
-??? 220
-<<< 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
->>> ehlo abcd
-??? 250-
-<<< 250-myhost.test.ex Hello abcd [127.0.0.1]
-??? 250-
-<<< 250-SIZE 52428800
-??? 250-
-<<< 250-PIPELINING
-??? 250
-<<< 250 HELP
->>> mail from:<userx@test.ex>\r\nrcpt to:<userx@test.ex>\r\ndata
-??? 250
-<<< 250 OK
-??? 250
-<<< 250 Accepted
-??? 354
-<<< 354 Enter message, ending with "." on a line by itself
->>> This is a test message.
->>> .\r\nrset
-??? 550
-<<< 550 Synchronization error (data after final dot)
-End of script
index dd1bdaef8287f5cce1982beb6083478a0108c94b..1efa5cd7c87dcf7e10e5f7dd0d92a8cc37636fd7 100644 (file)
@@ -30,35 +30,3 @@ Succeeded in starting TLS
 >>> .
 +++ 1
 End of script
 >>> .
 +++ 1
 End of script
-Connecting to 127.0.0.1 port 1225 ... connected
-??? 220
-<<< 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
->>> ehlo abcd
-??? 250-
-<<< 250-myhost.test.ex Hello abcd [127.0.0.1]
-??? 250-
-<<< 250-SIZE 52428800
-??? 250-
-<<< 250-PIPELINING
-??? 250-
-<<< 250-STARTTLS
-??? 250
-<<< 250 HELP
->>> starttls
-??? 220
-<<< 220 TLS go ahead
-Attempting to start TLS
-Succeeded in starting TLS
->>> mail from:<userx@test.ex>
-??? 250
-<<< 250 OK
->>> rcpt to:<userx@test.ex>
-??? 250
-<<< 250 Accepted
->>> data
-??? 354
-<<< 354 Enter message, ending with "." on a line by itself
->>> This is a test message.
->>> .\r\nrset
-+++ 1
-End of script
index dd1bdaef8287f5cce1982beb6083478a0108c94b..1efa5cd7c87dcf7e10e5f7dd0d92a8cc37636fd7 100644 (file)
@@ -30,35 +30,3 @@ Succeeded in starting TLS
 >>> .
 +++ 1
 End of script
 >>> .
 +++ 1
 End of script
-Connecting to 127.0.0.1 port 1225 ... connected
-??? 220
-<<< 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
->>> ehlo abcd
-??? 250-
-<<< 250-myhost.test.ex Hello abcd [127.0.0.1]
-??? 250-
-<<< 250-SIZE 52428800
-??? 250-
-<<< 250-PIPELINING
-??? 250-
-<<< 250-STARTTLS
-??? 250
-<<< 250 HELP
->>> starttls
-??? 220
-<<< 220 TLS go ahead
-Attempting to start TLS
-Succeeded in starting TLS
->>> mail from:<userx@test.ex>
-??? 250
-<<< 250 OK
->>> rcpt to:<userx@test.ex>
-??? 250
-<<< 250 Accepted
->>> data
-??? 354
-<<< 354 Enter message, ending with "." on a line by itself
->>> This is a test message.
->>> .\r\nrset
-+++ 1
-End of script