[exim-cvs] cvs commit: exim/exim-doc/doc-txt ChangeLog exim…

Top Page
Delete this message
Reply to this message
Author: Philip Hazel
Date:  
To: exim-cvs
Subject: [exim-cvs] cvs commit: exim/exim-doc/doc-txt ChangeLog exim/exim-src/src smtp_in.c exim/exim-test README exim/exim-test/confs 0556 exim/exim-test/log 0556 exim/exim-test/rejectlog 0556 exim/exim-te
ph10 2007/02/20 15:58:02 GMT

  Modified files:
    exim-doc/doc-txt     ChangeLog 
    exim-src/src         smtp_in.c 
    exim-test            README 
  Added files:
    exim-test/confs      0556 
    exim-test/log        0556 
    exim-test/rejectlog  0556 
    exim-test/scripts/0000-Basic 0556 
    exim-test/stdout     0556 
  Log:
  Add extra sync checks after ACLs that might delay.


  Revision  Changes    Path
  1.484     +8 -0      exim/exim-doc/doc-txt/ChangeLog
  1.55      +90 -32    exim/exim-src/src/smtp_in.c
  1.8       +7 -4      exim/exim-test/README
  1.1       +39 -0     exim/exim-test/confs/0556 (new)
  1.1       +5 -0      exim/exim-test/log/0556 (new)
  1.1       +3 -0      exim/exim-test/rejectlog/0556 (new)
  1.1       +55 -0     exim/exim-test/scripts/0000-Basic/0556 (new)
  1.1       +59 -0     exim/exim-test/stdout/0556 (new)


  Index: ChangeLog
  ===================================================================
  RCS file: /home/cvs/exim/exim-doc/doc-txt/ChangeLog,v
  retrieving revision 1.483
  retrieving revision 1.484
  diff -u -r1.483 -r1.484
  --- ChangeLog    20 Feb 2007 11:37:16 -0000    1.483
  +++ ChangeLog    20 Feb 2007 15:58:02 -0000    1.484
  @@ -1,4 +1,4 @@
  -$Cambridge: exim/exim-doc/doc-txt/ChangeLog,v 1.483 2007/02/20 11:37:16 ph10 Exp $
  +$Cambridge: exim/exim-doc/doc-txt/ChangeLog,v 1.484 2007/02/20 15:58:02 ph10 Exp $


   Change log file for Exim from version 4.21
   -------------------------------------------
  @@ -122,6 +122,14 @@
         in the case of a MAIL command with additional options following the
         address, for example: MAIL FROM:<foo@bar> SIZE=1234. The option settings
         were accidentally chopped off.
  +
  +PH/29 SMTP synchronization checks are implemented when a command is read -
  +      there is a check that no more input is waiting when there shouldn't be
  +      any. However, for some commands, a delay in an ACL can mean that it is
  +      some time before the response is written. In this time, more input might
  +      arrive, invalidly. So now there are extra checks after an ACL has run for
  +      HELO/EHLO and after the predata ACL, and likewise for MAIL and RCPT when
  +      pipelining has not been advertised.



Exim version 4.66

  Index: smtp_in.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/smtp_in.c,v
  retrieving revision 1.54
  retrieving revision 1.55
  diff -u -r1.54 -r1.55
  --- smtp_in.c    20 Feb 2007 11:37:16 -0000    1.54
  +++ smtp_in.c    20 Feb 2007 15:58:02 -0000    1.55
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/smtp_in.c,v 1.54 2007/02/20 11:37:16 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/smtp_in.c,v 1.55 2007/02/20 15:58:02 ph10 Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -469,6 +469,7 @@




  +
   /*************************************************
   *           Read one command line                *
   *************************************************/
  @@ -604,6 +605,60 @@



   /*************************************************
  +*          Recheck synchronization               *
  +*************************************************/
  +
  +/* Synchronization checks can never be perfect because a packet may be on its
  +way but not arrived when the check is done. Such checks can in any case only be
  +done when TLS is not in use. Normally, the checks happen when commands are
  +read: Exim ensures that there is no more input in the input buffer. In normal
  +cases, the response to the command will be fast, and there is no further check.
  +
  +However, for some commands an ACL is run, and that can include delays. In those
  +cases, it is useful to do another check on the input just before sending the
  +response. This also applies at the start of a connection. This function does
  +that check by means of the select() function, as long as the facility is not
  +disabled or inappropriate. A failure of select() is ignored.
  +
  +When there is unwanted input, we read it so that it appears in the log of the
  +error.
  +
  +Arguments: none
  +Returns:   TRUE if all is well; FALSE if there is input pending
  +*/
  +
  +static BOOL
  +check_sync(void)
  +{
  +int fd, rc;
  +fd_set fds;
  +struct timeval tzero;
  +
  +if (!smtp_enforce_sync || sender_host_address == NULL ||
  +    sender_host_notsocket || tls_active >= 0)
  +  return TRUE;
  +
  +fd = fileno(smtp_in);
  +FD_ZERO(&fds);
  +FD_SET(fd, &fds);
  +tzero.tv_sec = 0;
  +tzero.tv_usec = 0;
  +rc = select(fd + 1, (SELECT_ARG2_TYPE *)&fds, NULL, NULL, &tzero);
  +
  +if (rc <= 0) return TRUE;     /* Not ready to read */
  +rc = smtp_getc();
  +if (rc < 0) return TRUE;      /* End of file or error */
  +
  +smtp_ungetc(rc);
  +rc = smtp_inend - smtp_inptr;
  +if (rc > 150) rc = 150;
  +smtp_inptr[rc] = 0;
  +return FALSE;
  +}
  +
  +
  +
  +/*************************************************
   *          Forced closedown of call              *
   *************************************************/


@@ -1760,30 +1815,14 @@
/* Before we write the banner, check that there is no input pending, unless
this synchronisation check is disabled. */

  -if (smtp_enforce_sync && sender_host_address != NULL && !sender_host_notsocket)
  +if (!check_sync())
     {
  -  fd_set fds;
  -  struct timeval tzero;
  -  tzero.tv_sec = 0;
  -  tzero.tv_usec = 0;
  -  FD_ZERO(&fds);
  -  FD_SET(fileno(smtp_in), &fds);
  -  if (select(fileno(smtp_in) + 1, (SELECT_ARG2_TYPE *)&fds, NULL, NULL,
  -      &tzero) > 0)
  -    {
  -    int rc = read(fileno(smtp_in), smtp_inbuffer, in_buffer_size);
  -    if (rc > 0)
  -      {
  -      if (rc > 150) rc = 150;
  -      smtp_inbuffer[rc] = 0;
  -      log_write(0, LOG_MAIN|LOG_REJECT, "SMTP protocol "
  -        "synchronization error (input sent without waiting for greeting): "
  -        "rejected connection from %s input=\"%s\"", host_and_ident(TRUE),
  -        string_printing(smtp_inbuffer));
  -      smtp_printf("554 SMTP synchronization error\r\n");
  -      return FALSE;
  -      }
  -    }
  +  log_write(0, LOG_MAIN|LOG_REJECT, "SMTP protocol "
  +    "synchronization error (input sent without waiting for greeting): "
  +    "rejected connection from %s input=\"%s\"", host_and_ident(TRUE),
  +    string_printing(smtp_inptr));
  +  smtp_printf("554 SMTP synchronization error\r\n");
  +  return FALSE;
     }


   /* Now output the banner */
  @@ -2731,7 +2770,8 @@
       spf_init(sender_helo_name, sender_host_address);
   #endif


  -    /* Apply an ACL check if one is defined */
  +    /* Apply an ACL check if one is defined; afterwards, recheck
  +    synchronization in case the client started sending in a delay. */


       if (acl_smtp_helo != NULL)
         {
  @@ -2743,6 +2783,7 @@
           host_build_sender_fullhost();  /* Rebuild */
           break;
           }
  +      else if (!check_sync()) goto SYNC_FAILURE;
         }


       /* Generate an OK reply. The default string includes the ident if present,
  @@ -3236,10 +3277,16 @@
           }
         }


  -    /* Apply an ACL check if one is defined, before responding */
  -
  -    rc = (acl_smtp_mail == NULL)? OK :
  -      acl_check(ACL_WHERE_MAIL, NULL, acl_smtp_mail, &user_msg, &log_msg);
  +    /* Apply an ACL check if one is defined, before responding. Afterwards,
  +    when pipelining is not advertised, do another sync check in case the ACL
  +    delayed and the client started sending in the meantime. */
  +
  +    if (acl_smtp_mail == NULL) rc = OK; else
  +      {
  +      rc = acl_check(ACL_WHERE_MAIL, NULL, acl_smtp_mail, &user_msg, &log_msg);
  +      if (rc == OK && !pipelining_advertised && !check_sync())
  +        goto SYNC_FAILURE;
  +      }


       if (rc == OK || rc == DISCARD)
         {
  @@ -3395,10 +3442,17 @@
         }


       /* If the MAIL ACL discarded all the recipients, we bypass ACL checking
  -    for them. Otherwise, check the access control list for this recipient. */
  +    for them. Otherwise, check the access control list for this recipient. As
  +    there may be a delay in this, re-check for a synchronization error
  +    afterwards, unless pipelining was advertised. */


  -    rc = recipients_discarded? DISCARD :
  -      acl_check(ACL_WHERE_RCPT, recipient, acl_smtp_rcpt, &user_msg, &log_msg);
  +    if (recipients_discarded) rc = DISCARD; else
  +      {
  +      rc = acl_check(ACL_WHERE_RCPT, recipient, acl_smtp_rcpt, &user_msg,
  +        &log_msg);
  +      if (rc == OK && !pipelining_advertised && !check_sync())
  +        goto SYNC_FAILURE;
  +      }


       /* The ACL was happy */


  @@ -3472,12 +3526,16 @@
         break;
         }


  +    /* If there is an ACL, re-check the synchronization afterwards, since the
  +    ACL may have delayed. */
  +
       if (acl_smtp_predata == NULL) rc = OK; else
         {
         enable_dollar_recipients = TRUE;
         rc = acl_check(ACL_WHERE_PREDATA, NULL, acl_smtp_predata, &user_msg,
           &log_msg);
         enable_dollar_recipients = FALSE;
  +      if (rc == OK && !check_sync()) goto SYNC_FAILURE;
         }


       if (rc == OK)
  @@ -3493,7 +3551,6 @@


       else
         done = smtp_handle_acl_fail(ACL_WHERE_PREDATA, rc, user_msg, log_msg);
  -
       break;



@@ -3942,6 +3999,7 @@


       case BADSYN_CMD:
  +    SYNC_FAILURE:
       if (smtp_inend >= smtp_inbuffer + in_buffer_size)
         smtp_inend = smtp_inbuffer + in_buffer_size - 1;
       c = smtp_inend - smtp_inptr;


  Index: README
  ===================================================================
  RCS file: /home/cvs/exim/exim-test/README,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- README    31 Jan 2007 16:52:12 -0000    1.7
  +++ README    20 Feb 2007 15:58:02 -0000    1.8
  @@ -1,4 +1,4 @@
  -$Cambridge: exim/exim-test/README,v 1.7 2007/01/31 16:52:12 ph10 Exp $
  +$Cambridge: exim/exim-test/README,v 1.8 2007/02/20 15:58:02 ph10 Exp $


EXPORTABLE EXIM TEST SUITE
--------------------------
@@ -6,7 +6,7 @@
This document last updated for:

Test Suite Version: 4.67
-Date: 31 January 2007
+Date: 20 February 2007


BACKGROUND
@@ -765,9 +765,12 @@

This command runs the auxiliary "client" program that simulates an SMTP client.
It is controlled by a script read from its standard input, details of which are
-given below. The only option is -t, which must be followed by a number, to
-specify the command timeout in seconds. The program connects to the given IP
-address and port, using the specified interface, if one is given.
+given below. There are two options. One is -t, which must be followed directly
+by a number, to specify the command timeout in seconds (e.g. -t5). The default
+timeout is 1 second. The other option is -tls-on-connect, which causes the
+client to try to start up a TLS session as soon as it has connected, without
+using the STARTTLS command. The client program connects to the given IP address
+and port, using the specified interface, if one is given.


     client-ssl [<options>] <ip address> <port> [<outgoing interface>] \


Index: 0556
====================================================================
# Exim test configuration 0556

ACL_MAIL=accept
ACL_RCPT=accept
ACL_PREDATA=accept
PAH=127.0.0.1

exim_path = EXIM_PATH
host_lookup_order = bydns
primary_hostname = myhost.test.ex
rfc1413_query_timeout = 0s
spool_directory = DIR/spool
log_file_path = DIR/spool/log/%slog
gecos_pattern = ""
gecos_name = CALLER_NAME

# ----- Main settings -----

acl_smtp_predata = ACL_PREDATA
acl_smtp_mail = ACL_MAIL
acl_smtp_rcpt = ACL_RCPT
pipelining_advertise_hosts = PAH

queue_only

# ----- ACL -----

begin ACL

  check_predata:
    accept     delay = 2s


  check_mail:
    accept     delay = 2s


  check_rcpt:
    accept     delay = 2s


# End

Index: 0556
====================================================================
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 SMTP protocol synchronization error (next input sent too soon: pipelining was advertised): rejected "data" H=(abcd) [127.0.0.1] next input="Start: sent early ...\r\n"
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 SMTP protocol synchronization error (next input sent too soon: pipelining was not advertised): rejected "mail from:<userx@???>" H=(abcd) [127.0.0.1] next input="rcpt to:<userx@???>\r\n"
1999-03-02 09:44:33 SMTP protocol synchronization error (next input sent too soon: pipelining was not advertised): rejected "rcpt to:<userx@???>" H=(abcd) [127.0.0.1] next input="data\r\n"

Index: 0556
====================================================================
1999-03-02 09:44:33 SMTP protocol synchronization error (next input sent too soon: pipelining was advertised): rejected "data" H=(abcd) [127.0.0.1] next input="Start: sent early ...\r\n"
1999-03-02 09:44:33 SMTP protocol synchronization error (next input sent too soon: pipelining was not advertised): rejected "mail from:<userx@???>" H=(abcd) [127.0.0.1] next input="rcpt to:<userx@???>\r\n"
1999-03-02 09:44:33 SMTP protocol synchronization error (next input sent too soon: pipelining was not advertised): rejected "rcpt to:<userx@???>" H=(abcd) [127.0.0.1] next input="data\r\n"

  Index: 0556
  ====================================================================
  # SMTP synchronization checks before sending responses
  need_ipv4
  #
  exim -DSERVER=server -DACL_PREDATA=check_predata -bd -oX PORT_D
  ****
  # The pause (+++ 1) in the middle of this is so that there is no pending
  # input when DATA is received, but we start sending the data itself too
  # early (the server will be waiting 2 seconds in the predata ACL).
  #
  client 127.0.0.1 PORT_D
  ??? 220
  ehlo abcd
  ??? 250-
  ??? 250-
  ??? 250-
  ??? 250
  rset\r\nmail from:<userx@???>\r\nrcpt to:<userx@???>\r\ndata
  +++ 1
  Start: sent early ...
  ??? 250
  ??? 250
  ??? 250
  ??? 554
  ****
  sleep 1
  killdaemon
  # This time turn off pipelining to check MAIL and RCPT
  exim -DSERVER=server -DACL_MAIL=check_mail -DACL_RCPT=check_rcpt -DPAH= \
       -bd -oX PORT_D
  ****
  client -t5 127.0.0.1 PORT_D
  ??? 220
  ehlo abcd
  ??? 250-
  ??? 250-
  ??? 250
  mail from:<userx@???>
  +++ 1
  rcpt to:<userx@???>
  ??? 554
  ****
  client -t5 127.0.0.1 PORT_D
  ??? 220
  ehlo abcd
  ??? 250-
  ??? 250-
  ??? 250
  mail from:<userx@???>
  ??? 250
  rcpt to:<userx@???>
  +++ 1
  data
  ??? 554
  ****
  killdaemon      


Index: 0556
====================================================================
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
>>> rset\r\nmail from:<userx@???>\r\nrcpt to:<userx@???>\r\ndata

+++ 1
>>> Start: sent early ...

??? 250
<<< 250 Reset OK
??? 250
<<< 250 OK
??? 250
<<< 250 Accepted
??? 554
<<< 554 SMTP synchronization error
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 HELP
>>> mail from:<userx@???>

+++ 1
>>> rcpt to:<userx@???>

??? 554
<<< 554 SMTP synchronization error
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 HELP
>>> mail from:<userx@???>

??? 250
<<< 250 OK
>>> rcpt to:<userx@???>

+++ 1
>>> data

??? 554
<<< 554 SMTP synchronization error
End of script