From ae9d18bce985de6ff806c167059ffdd554278882 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Mon, 8 Jun 2015 21:48:50 +0100 Subject: [PATCH] Truncate delay when peer closes connection. Bug 348 This is now possible on Linux, at least. --- src/src/acl.c | 40 +++++++++++++++++++-------- test/confs/0609 | 47 ++++++++++++++++++++++++++++++++ test/log/0552 | 2 +- test/log/0609 | 7 +++++ test/runtest | 3 +++ test/scripts/0000-Basic/0552 | 1 + test/scripts/0000-Basic/0609 | 29 ++++++++++++++++++++ test/stderr/0609 | 52 ++++++++++++++++++++++++++++++++++++ test/stdout/0609 | 21 +++++++++++++++ 9 files changed, 190 insertions(+), 12 deletions(-) create mode 100644 test/confs/0609 create mode 100644 test/log/0609 create mode 100644 test/scripts/0000-Basic/0609 create mode 100644 test/stderr/0609 create mode 100644 test/stdout/0609 diff --git a/src/src/acl.c b/src/src/acl.c index e79c87f83..dae310117 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -3480,6 +3480,34 @@ for (; cb != NULL; cb = cb->next) debug_printf("delay skipped in -bh checking mode\n"); } + /* NOTE 1: Remember that we may be + dealing with stdin/stdout here, in addition to TCP/IP connections. + Also, delays may be specified for non-SMTP input, where smtp_out and + smtp_in will be NULL. Whatever is done must work in all cases. + + NOTE 2: The added feature of flushing the output before a delay must + apply only to SMTP input. Hence the test for smtp_out being non-NULL. + */ + + else + { + if (smtp_out != NULL && !disable_delay_flush) + mac_smtp_fflush(); + +#if !defined(NO_POLL_H) && defined (_GNU_SOURCE) + { + struct pollfd p; + nfds_t n = 0; + if (smtp_out) + { + p.fd = fileno(smtp_out); + p.events = POLLRDHUP; + n = 1; + } + if (poll(&p, n, delay*1000) > 0) + HDEBUG(D_acl) debug_printf("delay cancelled by peer close\n"); + } +#else /* It appears to be impossible to detect that a TCP/IP connection has gone away without reading from it. This means that we cannot shorten the delay below if the client goes away, because we cannot discover @@ -3489,20 +3517,10 @@ for (; cb != NULL; cb = cb->next) Exim process is not held up unnecessarily. However, it seems that we can't. The poll() function does not do the right thing, and in any case it is not always available. - - NOTE 1: If ever this state of affairs changes, remember that we may be - dealing with stdin/stdout here, in addition to TCP/IP connections. - Also, delays may be specified for non-SMTP input, where smtp_out and - smtp_in will be NULL. Whatever is done must work in all cases. - - NOTE 2: The added feature of flushing the output before a delay must - apply only to SMTP input. Hence the test for smtp_out being non-NULL. */ - else - { - if (smtp_out != NULL && !disable_delay_flush) mac_smtp_fflush(); while (delay > 0) delay = sleep(delay); +#endif } } } diff --git a/test/confs/0609 b/test/confs/0609 new file mode 100644 index 000000000..d6ac511fd --- /dev/null +++ b/test/confs/0609 @@ -0,0 +1,47 @@ +# Exim test configuration 0609 +# Long ACL delays + +SERVER= + +exim_path = EXIM_PATH +host_lookup_order = bydns +primary_hostname = myhost.test.ex +spool_directory = DIR/spool +log_file_path = DIR/spool/log/SERVER%slog +gecos_pattern = "" +gecos_name = CALLER_NAME + +# ----- Main settings ----- + +disable_ipv6 = true + +acl_smtp_rcpt = delay4_accept +log_selector = +smtp_connection +#hosts_connection_nolog = : 127.0.0.1 + + +# ----- ACLs ----- + +begin acl + +delay4_accept: + accept delay = 4s + +# ----- Routers ----- + +begin routers + +accept: + driver = accept + transport = appendfile + +# ----- Transports ----- + +begin transports + +appendfile: + driver = appendfile + file = DIR/test-mail/$local_part + user = CALLER + +# End diff --git a/test/log/0552 b/test/log/0552 index 8148c5aeb..d070f9c8c 100644 --- a/test/log/0552 +++ b/test/log/0552 @@ -14,6 +14,6 @@ ******** SERVER ******** 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 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port 1225 1999-03-02 09:44:33 SMTP connection from localhost (myhost.test.ex) [127.0.0.1] lost while reading message data (header) +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 <= CALLER@myhost.test.ex H=localhost (myhost.test.ex) [127.0.0.1] P=esmtp S=sss id=E10HmaX-0005vi-00@myhost.test.ex diff --git a/test/log/0609 b/test/log/0609 new file mode 100644 index 000000000..a19051aa1 --- /dev/null +++ b/test/log/0609 @@ -0,0 +1,7 @@ + +******** SERVER ******** +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 connection from [127.0.0.1] (TCP/IP connection count = 1) +1999-03-02 09:44:33 SMTP connection from [127.0.0.1] closed by QUIT +1999-03-02 09:44:33 SMTP connection from [127.0.0.1] (TCP/IP connection count = 1) +1999-03-02 09:44:33 unexpected disconnection while reading SMTP command from [127.0.0.1] diff --git a/test/runtest b/test/runtest index 616ded37c..df6132b98 100755 --- a/test/runtest +++ b/test/runtest @@ -1378,6 +1378,9 @@ $munges = 'tls_anycipher' => { 'mainlog' => 's/ X=TLS\S+ / X=TLS_proto_and_cipher /' }, + 'debug_pid' => + { 'stderr' => 's/\d{1,5}/ppppp/g' }, + }; diff --git a/test/scripts/0000-Basic/0552 b/test/scripts/0000-Basic/0552 index 1958dbe64..a0621ca32 100644 --- a/test/scripts/0000-Basic/0552 +++ b/test/scripts/0000-Basic/0552 @@ -11,6 +11,7 @@ exim -DSERVER=server -DDDF=control=no_delay_flush -bd -oX PORT_D exim -qf **** killdaemon +sleep 1 # This daemon should flush before delaying exim -DSERVER=server -bd -oX PORT_D **** diff --git a/test/scripts/0000-Basic/0609 b/test/scripts/0000-Basic/0609 new file mode 100644 index 000000000..84ab89ded --- /dev/null +++ b/test/scripts/0000-Basic/0609 @@ -0,0 +1,29 @@ +# Long ACL delay, truncated +munge debug_pid +need_ipv4 +# +# We want the debug note of a truncated delay +exim -d-all+acl -DSERVER=server -odq -bd -oX PORT_D +**** +# +# Server delays 4s before accepting RCPT +client 127.0.0.1 PORT_D +??? 220 +mail from: +??? 250 +rcpt to: +??? 250 +quit +??? 221 +**** +# +# Server delays 4s before accepting RCPT +# but client closes connection +client 127.0.0.1 PORT_D +??? 220 +mail from: +??? 250 +rcpt to: +**** +killdaemon +no_msglog_check diff --git a/test/stderr/0609 b/test/stderr/0609 new file mode 100644 index 000000000..99a047537 --- /dev/null +++ b/test/stderr/0609 @@ -0,0 +1,52 @@ + +******** SERVER ******** +Exim version x.yz .... +configuration file is TESTSUITE/test-config +admin user +ppppp daemon_smtp_port overridden by -oX: +ppppp <: ppppp +ppppp listening on all interfaces (IPvppppp) port ppppp +ppppp pid written to TESTSUITE/spool/exim-daemon.pid +ppppp LOG: MAIN +ppppp exim x.yz daemon started: pid=ppppp, no queue runs, listening for SMTP on port ppppp (IPvppppp) +ppppp daemon running with uid=ppppp gid=ppppp euid=ppppp egid=ppppp +ppppp Listening... +ppppp Connection request from ppppp.ppppp.ppppp.ppppp port ppppp +ppppp LOG: smtp_connection MAIN +ppppp SMTP connection from [ppppp.ppppp.ppppp.ppppp] (TCP/IP connection count = ppppp) +ppppp ppppp SMTP accept process running +ppppp Listening... +ppppp Process ppppp is handling incoming connection from [ppppp.ppppp.ppppp.ppppp] +ppppp Process ppppp is ready for new message +ppppp using ACL "delayppppp_accept" +ppppp processing "accept" +ppppp check delay = ppppps +ppppp delay modifier requests ppppp-second delay +ppppp accept: condition test succeeded in ACL "delayppppp_accept" +ppppp end of ACL "delayppppp_accept": ACCEPT +ppppp LOG: smtp_connection MAIN +ppppp SMTP connection from [ppppp.ppppp.ppppp.ppppp] closed by QUIT +ppppp child ppppp ended: status=pppppxppppp +ppppp normal exit, ppppp +ppppp ppppp SMTP accept processes now running +ppppp Listening... +ppppp Connection request from ppppp.ppppp.ppppp.ppppp port ppppp +ppppp LOG: smtp_connection MAIN +ppppp SMTP connection from [ppppp.ppppp.ppppp.ppppp] (TCP/IP connection count = ppppp) +ppppp ppppp SMTP accept process running +ppppp Listening... +ppppp Process ppppp is handling incoming connection from [ppppp.ppppp.ppppp.ppppp] +ppppp Process ppppp is ready for new message +ppppp using ACL "delayppppp_accept" +ppppp processing "accept" +ppppp check delay = ppppps +ppppp delay modifier requests ppppp-second delay +ppppp delay cancelled by peer close +ppppp accept: condition test succeeded in ACL "delayppppp_accept" +ppppp end of ACL "delayppppp_accept": ACCEPT +ppppp LOG: lost_incoming_connection MAIN +ppppp unexpected disconnection while reading SMTP command from [ppppp.ppppp.ppppp.ppppp] +ppppp child ppppp ended: status=pppppxppppp +ppppp normal exit, ppppp +ppppp ppppp SMTP accept processes now running +ppppp Listening... diff --git a/test/stdout/0609 b/test/stdout/0609 new file mode 100644 index 000000000..8ebf9a24f --- /dev/null +++ b/test/stdout/0609 @@ -0,0 +1,21 @@ +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 +>>> mail from: +??? 250 +<<< 250 OK +>>> rcpt to: +??? 250 +<<< 250 Accepted +>>> quit +??? 221 +<<< 221 myhost.test.ex closing connection +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 +>>> mail from: +??? 250 +<<< 250 OK +>>> rcpt to: +End of script -- 2.25.1