diff options
author | Philip Hazel <ph10@hermes.cam.ac.uk> | 2007-04-13 15:13:47 +0000 |
---|---|---|
committer | Philip Hazel <ph10@hermes.cam.ac.uk> | 2007-04-13 15:13:47 +0000 |
commit | 58eb016e585187a87ade7602b2aecb2208605320 (patch) | |
tree | c0021c9485b5b1b0c0b72591ffb5b827efcb1e3d /src | |
parent | 0a4e3112aeb6531661cb8d49379db4f84ff5841b (diff) |
Check for lost connection or unexpected input at end of message.
Diffstat (limited to 'src')
-rw-r--r-- | src/src/functions.h | 4 | ||||
-rw-r--r-- | src/src/globals.c | 3 | ||||
-rw-r--r-- | src/src/globals.h | 3 | ||||
-rw-r--r-- | src/src/receive.c | 122 | ||||
-rw-r--r-- | src/src/smtp_in.c | 20 | ||||
-rw-r--r-- | src/src/tls-gnu.c | 4 | ||||
-rw-r--r-- | src/src/tls-openssl.c | 4 | ||||
-rw-r--r-- | src/src/tls.c | 20 |
8 files changed, 148 insertions, 32 deletions
diff --git a/src/src/functions.h b/src/src/functions.h index 55a2e22d3..d6262d1a7 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/functions.h,v 1.36 2007/02/07 11:24:56 ph10 Exp $ */ +/* $Cambridge: exim/src/src/functions.h,v 1.37 2007/04/13 15:13:47 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -32,6 +32,7 @@ extern int tls_ferror(void); extern int tls_getc(void); extern int tls_read(uschar *, size_t); extern int tls_server_start(uschar *, uschar *, uschar *, uschar *); +extern BOOL tls_smtp_buffered(void); extern int tls_ungetc(int); extern int tls_write(const uschar *, size_t); #endif @@ -261,6 +262,7 @@ extern void sha1_start(sha1 *); extern int sieve_interpret(uschar *, int, uschar *, uschar *, uschar *, address_item **, uschar **); extern void sigalrm_handler(int); +extern BOOL smtp_buffered(void); extern void smtp_closedown(uschar *); extern int smtp_connect(host_item *, int, int, uschar *, int, BOOL); extern int smtp_feof(void); diff --git a/src/src/globals.c b/src/src/globals.c index 5f4ed83fd..83c37b09e 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/globals.c,v 1.71 2007/02/06 12:19:27 ph10 Exp $ */ +/* $Cambridge: exim/src/src/globals.c,v 1.72 2007/04/13 15:13:47 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -136,6 +136,7 @@ int (*receive_getc)(void) = stdin_getc; int (*receive_ungetc)(int) = stdin_ungetc; int (*receive_feof)(void) = stdin_feof; int (*receive_ferror)(void) = stdin_ferror; +BOOL (*receive_smtp_buffered)(void) = NULL; /* Only used for SMTP */ #endif diff --git a/src/src/globals.h b/src/src/globals.h index 48b4e0ecc..8dbb41379 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/globals.h,v 1.51 2007/02/06 12:19:27 ph10 Exp $ */ +/* $Cambridge: exim/src/src/globals.h,v 1.52 2007/04/13 15:13:47 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -96,6 +96,7 @@ extern int (*receive_getc)(void); extern int (*receive_ungetc)(int); extern int (*receive_feof)(void); extern int (*receive_ferror)(void); +extern BOOL (*receive_smtp_buffered)(void); /* For clearing, saving, restoring address expansion variables. We have to have diff --git a/src/src/receive.c b/src/src/receive.c index f6d294e6d..98a728b2f 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/receive.c,v 1.35 2007/04/12 09:03:19 ph10 Exp $ */ +/* $Cambridge: exim/src/src/receive.c,v 1.36 2007/04/13 15:13:47 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -3081,7 +3081,7 @@ if (local_scan_data != NULL) if (rc == LOCAL_SCAN_ACCEPT_FREEZE) { - if (!deliver_freeze) /* ACL might have already frozen */ + if (!deliver_freeze) /* ACL might have already frozen */ { deliver_freeze = TRUE; deliver_frozen_at = time(NULL); @@ -3380,22 +3380,6 @@ not put the zero in. */ s[sptr] = 0; -/* While writing to the log, set a flag to cause a call to receive_bomb_out() -if the log cannot be opened. */ - -receive_call_bombout = TRUE; -log_write(0, LOG_MAIN | - (((log_extra_selector & LX_received_recipients) != 0)? LOG_RECIPIENTS : 0) | - (((log_extra_selector & LX_received_sender) != 0)? LOG_SENDER : 0), - "%s", s); -receive_call_bombout = FALSE; - -/* Log any control actions taken by an ACL or local_scan(). */ - -if (deliver_freeze) log_write(0, LOG_MAIN, "frozen by %s", frozen_by); -if (queue_only_policy) log_write(L_delay_delivery, LOG_MAIN, - "no immediate delivery: queued by %s", queued_by); - /* Create a message log file if message logs are being used and this message is not blackholed. Write the reception stuff to it. We used to leave message log creation until the first delivery, but this has proved confusing for somep @@ -3446,6 +3430,94 @@ if (message_logs && blackholed_by == NULL) } } +/* Everything has now been done for a successful message except logging its +arrival, and outputting an SMTP response. While writing to the log, set a flag +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. + +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 (smtp_input && sender_host_address != NULL && !sender_host_notsocket) + { + struct timeval tv; + fd_set select_check; + FD_ZERO(&select_check); + FD_SET(fileno(smtp_in), &select_check); + tv.tv_sec = 0; + tv.tv_usec = 0; + + if (select(fileno(smtp_in) + 1, &select_check, NULL, NULL, &tv) != 0 || + receive_smtp_buffered()) + { + uschar *msg; + if ((RECEIVE_GETC)() == EOF) + { + msg = US"SMTP connection lost after final dot"; + smtp_reply = US""; /* No attempt to send a response */ + } + else + { + msg = US"Synchronization error (data after final dot)"; + smtp_reply = US"550 Synchronization error (data after final dot)"; + } + + /* Overwrite the log line workspace */ + + 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); + + /* We now have to delete the files for this aborted message. */ + + sprintf(CS spool_name, "%s/input/%s/%s-D", 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); + + sprintf(CS spool_name, "%s/msglog/%s/%s", spool_directory, message_subdir, + message_id); + Uunlink(spool_name); + + /* Do not accept any more messages on this connection. */ + + smtp_yield = FALSE; + goto TIDYUP; + } + } + +/* The connection has not gone away; we really are going to take responsibility +for this message. */ + +log_write(0, LOG_MAIN | + (((log_extra_selector & LX_received_recipients) != 0)? LOG_RECIPIENTS : 0) | + (((log_extra_selector & LX_received_sender) != 0)? LOG_SENDER : 0), + "%s", s); +receive_call_bombout = FALSE; + +/* Log any control actions taken by an ACL or local_scan(). */ + +if (deliver_freeze) log_write(0, LOG_MAIN, "frozen by %s", frozen_by); +if (queue_only_policy) log_write(L_delay_delivery, LOG_MAIN, + "no immediate delivery: queued by %s", queued_by); + store_reset(s); /* The store for the main log message can be reused */ /* If the message is frozen, and freeze_tell is set, do the telling. */ @@ -3460,9 +3532,9 @@ if (deliver_freeze && freeze_tell != NULL && freeze_tell[0] != 0) /* Either a message has been successfully received and written to the two spool files, or an error in writing the spool has occurred for an SMTP message, or -an SMTP message has been rejected because of a bad sender. (For a non-SMTP -message we will have already given up because there's no point in carrying on!) -In either event, we must now close (and thereby unlock) the data file. In the +an SMTP message has been rejected for policy reasons. (For a non-SMTP message +we will have already given up because there's no point in carrying on!) In +either event, we must now close (and thereby unlock) the data file. In the successful case, this leaves the message on the spool, ready for delivery. In the error case, the spool file will be deleted. Then tidy up store, interact with an SMTP call if necessary, and return. @@ -3491,9 +3563,9 @@ if (smtp_input) yield = smtp_yield; /* Handle interactive SMTP callers. After several kinds of error, smtp_reply - is set to the response. However, after an ACL error or local_scan() error, - the response has already been sent, and smtp_reply is an empty string to - indicate this. */ + is set to the response that should be sent. When it is NULL, we generate + default responses. After an ACL error or local_scan() error, the response has + already been sent, and smtp_reply is an empty string to indicate this. */ if (!smtp_batched_input) { @@ -3522,7 +3594,7 @@ if (smtp_input) "\n**** SMTP testing: that is not a real message id!\n\n"); } - /* smtp_reply was previously set */ + /* smtp_reply is set non-empty */ else if (smtp_reply[0] != 0) { diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c index bdac07be7..dc96a9aa1 100644 --- a/src/src/smtp_in.c +++ b/src/src/smtp_in.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/smtp_in.c,v 1.56 2007/03/21 15:10:39 ph10 Exp $ */ +/* $Cambridge: exim/src/src/smtp_in.c,v 1.57 2007/04/13 15:13:47 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -333,6 +333,23 @@ return smtp_had_error; +/************************************************* +* Test for characters in the SMTP buffer * +*************************************************/ + +/* Used at the end of a message + +Arguments: none +Returns: TRUE/FALSE +*/ + +BOOL +smtp_buffered(void) +{ +return smtp_inptr < smtp_inend; +} + + /************************************************* * Write formatted string to SMTP channel * @@ -1378,6 +1395,7 @@ receive_getc = smtp_getc; receive_ungetc = smtp_ungetc; receive_feof = smtp_feof; receive_ferror = smtp_ferror; +receive_smtp_buffered = smtp_buffered; smtp_inptr = smtp_inend = smtp_inbuffer; smtp_had_eof = smtp_had_error = 0; diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index ee57659fa..e66c2e448 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/tls-gnu.c,v 1.18 2007/01/18 15:35:42 ph10 Exp $ */ +/* $Cambridge: exim/src/src/tls-gnu.c,v 1.19 2007/04/13 15:13:47 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -976,6 +976,7 @@ receive_getc = tls_getc; receive_ungetc = tls_ungetc; receive_feof = tls_feof; receive_ferror = tls_ferror; +receive_smtp_buffered = tls_smtp_buffered; tls_active = fileno(smtp_out); @@ -1174,6 +1175,7 @@ if (ssl_xfer_buffer_lwm >= ssl_xfer_buffer_hwm) receive_ungetc = smtp_ungetc; receive_feof = smtp_feof; receive_ferror = smtp_ferror; + receive_smtp_buffered = smtp_buffered; gnutls_deinit(tls_session); tls_session = NULL; diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index 85f4e15fe..a9b67dcdd 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/tls-openssl.c,v 1.11 2007/03/13 09:50:22 ph10 Exp $ */ +/* $Cambridge: exim/src/src/tls-openssl.c,v 1.12 2007/04/13 15:13:47 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -733,6 +733,7 @@ receive_getc = tls_getc; receive_ungetc = tls_ungetc; receive_feof = tls_feof; receive_ferror = tls_ferror; +receive_smtp_buffered = tls_smtp_buffered; tls_active = fileno(smtp_out); return OK; @@ -886,6 +887,7 @@ if (ssl_xfer_buffer_lwm >= ssl_xfer_buffer_hwm) receive_ungetc = smtp_ungetc; receive_feof = smtp_feof; receive_ferror = smtp_ferror; + receive_smtp_buffered = smtp_buffered; SSL_free(ssl); ssl = NULL; diff --git a/src/src/tls.c b/src/src/tls.c index e76a97020..f1583f231 100644 --- a/src/src/tls.c +++ b/src/src/tls.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/tls.c,v 1.4 2007/01/08 10:50:18 ph10 Exp $ */ +/* $Cambridge: exim/src/src/tls.c,v 1.5 2007/04/13 15:13:47 ph10 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -147,6 +147,24 @@ tls_ferror(void) return ssl_xfer_error; } + +/************************************************* +* TLS version of smtp_buffered * +*************************************************/ + +/* Tests for unused chars in the TLS input buffer. + +Arguments: none +Returns: TRUE/FALSE +*/ + +BOOL +tls_smtp_buffered(void) +{ +return ssl_xfer_buffer_lwm < ssl_xfer_buffer_hwm; +} + + #endif /* SUPPORT_TLS */ /* End of tls.c */ |