diff options
author | Philip Hazel <ph10@hermes.cam.ac.uk> | 2007-04-16 10:31:58 +0000 |
---|---|---|
committer | Philip Hazel <ph10@hermes.cam.ac.uk> | 2007-04-16 10:31:58 +0000 |
commit | 563b63fa3e09d67239f51483e5dcec5c91251522 (patch) | |
tree | 39c50ba6ecad3e86c0b1a5676ad1d935e9beda73 /src | |
parent | 58eb016e585187a87ade7602b2aecb2208605320 (diff) |
Fix bug in previous patch: following data is permitted after '.' so it
must not be diagnosed as an error. The check for vanished socket can
only be applied when there is no data pending.
Diffstat (limited to 'src')
-rw-r--r-- | src/src/receive.c | 89 |
1 files changed, 43 insertions, 46 deletions
diff --git a/src/src/receive.c b/src/src/receive.c index 98a728b2f..e4c82d2fa 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -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 * @@ -3436,21 +3436,26 @@ to cause a call to receive_bomb_out() if the log cannot be opened. */ 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; @@ -3459,47 +3464,39 @@ if (smtp_input && sender_host_address != NULL && !sender_host_notsocket) 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; + } } } |