From 59eaad2b1af0dc58545dff6a7211948782811e1a Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Wed, 24 Feb 2016 18:19:04 +0000 Subject: [PATCH] Cutthrough: fix operation under -bhc to not actually deliver. Bug 1800 --- doc/doc-txt/ChangeLog | 4 + src/src/acl.c | 6 +- test/README | 4 +- test/confs/5402 | 70 ++++++ test/runtest | 5 +- test/scripts/5400-cutthrough/5402 | 42 ++++ test/src/server.c | 8 +- test/stderr/5402 | 365 ++++++++---------------------- test/stdout/5402 | 43 +++- 9 files changed, 260 insertions(+), 287 deletions(-) create mode 100644 test/confs/5402 create mode 100644 test/scripts/5400-cutthrough/5402 diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index a3911ac18..eab7419be 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -179,6 +179,10 @@ JH/43 Tidy coding issues detected by gcc --fsanitize=undefined. Some remain; either intentional arithmetic overflow during PRNG, or testing config- induced overflows. +JH/44 Bug 1800: The combination of a -bhc commandline option and cutthrough + delivery resulted in actual delivery. Cancel cutthrough before DATA + stage. + Exim version 4.86 diff --git a/src/src/acl.c b/src/src/acl.c index 684b93bbb..d508a29e7 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -4509,12 +4509,14 @@ case ACL_WHERE_RCPT: #ifndef DISABLE_PRDR case ACL_WHERE_PRDR: #endif - if (rc == OK && cutthrough.delivery && rcpt_count > cutthrough.nrcpt) + if (host_checking_callout) /* -bhc mode */ + cancel_cutthrough_connection("host-checking mode"); + else if (rc == OK && cutthrough.delivery && rcpt_count > cutthrough.nrcpt) open_cutthrough_connection(addr); break; case ACL_WHERE_PREDATA: - if( rc == OK ) + if (rc == OK) cutthrough_predata(); else cancel_cutthrough_connection("predata acl not ok"); diff --git a/test/README b/test/README index bcf03498d..5d9bed72d 100644 --- a/test/README +++ b/test/README @@ -928,7 +928,9 @@ input, details of which are given below. A number of options are implemented: -d causes the server to output debugging information -t sets a timeout (default 5) for when the server is - awaiting an incoming connection + awaiting an incoming connection. If negative, the + absolute value is used and a timeout results in a + nonfailure exit code -noipv4 causes the server not to set up an IPv4 socket diff --git a/test/confs/5402 b/test/confs/5402 new file mode 100644 index 000000000..e480b64b5 --- /dev/null +++ b/test/confs/5402 @@ -0,0 +1,70 @@ +# Exim test configuration 5400 + +exim_path = EXIM_PATH +keep_environment = +host_lookup_order = bydns +primary_hostname = myhost.test.ex +spool_directory = DIR/spool +log_file_path = DIR/spool/log/%slog +gecos_pattern = "" +gecos_name = CALLER_NAME +tls_advertise_hosts = + +log_selector = +received_recipients + +# ----- Main settings ----- + +domainlist local_domains = test.ex : *.test.ex + +acl_smtp_rcpt = ar + + +# ----- ACLs ----- + +begin acl + +ar: + warn control = cutthrough_delivery + logwrite = rcpt for $local_part@$domain + warn condition = ${if eq {verify}{$local_part}} + verify = recipient/callout=use_sender + accept + +# ----- Routers ----- + +begin routers + +dns: + driver = dnslookup + domains = localhost.test.ex : localhost4.test.ex : thishost.test.ex + self = send + transport = smtp + +all: + driver = manualroute + domains = ! +local_domains + route_list = special.com HOSTIPV4 ; * 127.0.0.1 + self = send + transport = ${if eq {special_tpt}{$local_part} {smtp2}{smtp}} + headers_remove = X-hdr-rtr + headers_add = X-hdr-rtr-new: $h_X-hdr-rtr:+++ + no_more + + +# ----- Transports ----- + +begin transports + +smtp: + driver = smtp + interface = HOSTIPV4 + port = PORT_S + headers_add = ${if def:h_X-hdr-rtr {X-hdr-tpt-new: new} {}} + +smtp2: + driver = smtp + interface = HOSTIPV4 + port = PORT_S + + +# End diff --git a/test/runtest b/test/runtest index 18ed0915d..96f5c11e9 100755 --- a/test/runtest +++ b/test/runtest @@ -3733,8 +3733,9 @@ foreach $test (@test_list) my($subtest_startline) = $lineno; - # Now run the command. The function returns 0 if exim was run and waited - # for, 1 if any other command was run and waited for, and 2 if a command + # Now run the command. The function returns 0 for an inline command, + # 1 if a non-exim command was run and waited for, 2 if an exim + # command was run and waited for, and 3 if a command # was run and not waited for (usually a daemon or server startup). my($commandname) = ""; diff --git a/test/scripts/5400-cutthrough/5402 b/test/scripts/5400-cutthrough/5402 new file mode 100644 index 000000000..3e6f3189e --- /dev/null +++ b/test/scripts/5400-cutthrough/5402 @@ -0,0 +1,42 @@ +# cutthrough_delivery and -bhc +need_ipv4 +munge loopback +no_msglog_check +# +# Despite config for cutthrough should not make onward conn +server -t -2 PORT_S +**** +exim -bhc 1.2.3.4 +EHLO myhost.test.ex +MAIL FROM: +RCPT TO: +DATA + +. +QUIT +**** +# +# Onward conn made for r-verify but cleared before DATA +server PORT_S +220 server ready +EHLO +250 OK +MAIL +250 OK +RCPT +250 OK +QUIT +220 OK +*eof +**** +exim -bhc 1.2.3.4 +EHLO myhost.test.ex +MAIL FROM: +RCPT TO: +DATA + +. +QUIT +**** +# +# End diff --git a/test/src/server.c b/test/src/server.c index 5c6080238..3aecf76f0 100644 --- a/test/src/server.c +++ b/test/src/server.c @@ -65,13 +65,14 @@ typedef struct line { /************************************************* * SIGALRM handler - crash out * *************************************************/ +int tmo_noerror = 0; static void sigalrm_handler(int sig) { sig = sig; /* Keep picky compilers happy */ printf("\nServer timed out\n"); -exit(99); +exit(tmo_noerror ? 0 : 99); } @@ -215,7 +216,10 @@ if (argc > 1 && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h"))) while (na < argc && argv[na][0] == '-') { if (strcmp(argv[na], "-d") == 0) debug = 1; - else if (strcmp(argv[na], "-t") == 0) timeout = atoi(argv[++na]); + else if (strcmp(argv[na], "-t") == 0) + { + if (tmo_noerror = ((timeout = atoi(argv[++na])) < 0)) timeout = -timeout; + } else if (strcmp(argv[na], "-i") == 0) initial_pause = atoi(argv[++na]); else if (strcmp(argv[na], "-noipv4") == 0) use_ipv4 = 0; else if (strcmp(argv[na], "-noipv6") == 0) use_ipv6 = 0; diff --git a/test/stderr/5402 b/test/stderr/5402 index 7babe3546..49d3574fe 100644 --- a/test/stderr/5402 +++ b/test/stderr/5402 @@ -1,274 +1,91 @@ -Exim version x.yz .... -configuration file is TESTSUITE/test-config -admin user - in hosts_connection_nolog? no (option unset) -LOG: smtp_connection MAIN - SMTP connection from CALLER -expanding: $smtp_active_hostname ESMTP Exim $version_number $tod_full - result: myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 - in pipelining_advertise_hosts? yes (matched "*") - in tls_advertise_hosts? yes (matched "*") -expanding: SERVER - result: SERVER -expanding: server - result: server -condition: eq {SERVER}{server} - result: false -expanding: queue - result: queue -skipping: result is not used -expanding: cutthrough - result: cutthrough -expanding: ${if eq {SERVER}{server}{queue}{cutthrough}} - result: cutthrough -using ACL "cutthrough" -processing "accept" -check control = cutthrough_delivery -check verify = recipient -domain.com in "test.ex : *.test.ex"? no (end of list) -domain.com in "! +local_domains"? yes (end of list) -expanding: $local_part - result: userx -domain.com in "*"? yes (matched "*") ------------ end verify ------------ -accept: condition test succeeded in ACL "cutthrough" ------------ start cutthrough setup ------------ -domain.com in "test.ex : *.test.ex"? no (end of list) -domain.com in "! +local_domains"? yes (end of list) -expanding: $local_part - result: userx -domain.com in "*"? yes (matched "*") -Connecting to 127.0.0.1 [127.0.0.1]:1225 from ip4.ip4.ip4.ip4 ... connected -expanding: $primary_hostname - result: myhost.test.ex - SMTP<< 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 -127.0.0.1 in hosts_avoid_esmtp? no (option unset) - SMTP>> EHLO myhost.test.ex - SMTP<< 250-myhost.test.ex Hello the.local.host.name [ip4.ip4.ip4.ip4] - 250-SIZE 52428800 - 250-8BITMIME - 250-PIPELINING - 250-STARTTLS - 250 HELP -expanding: $address_data - result: userx -expanding: usery - result: usery -condition: eq {$address_data}{usery} - result: false -expanding: * - result: * -skipping: result is not used -expanding: : - result: : -expanding: ${if eq {$address_data}{usery}{*}{:}} - result: : -127.0.0.1 in hosts_avoid_tls? no (end of list) - SMTP>> STARTTLS - SMTP<< 220 TLS go ahead - SMTP>> EHLO myhost.test.ex - SMTP<< 250-myhost.test.ex Hello the.local.host.name [ip4.ip4.ip4.ip4] - 250-SIZE 52428800 - 250-8BITMIME - 250-PIPELINING - 250 HELP - SMTP>> MAIL FROM: - SMTP<< 250 OK - SMTP>> RCPT TO: - SMTP<< 250 Accepted ------------ end cutthrough setup ------------ -processing "accept" -accept: condition test succeeded in inline ACL - SMTP>> DATA - SMTP<< 354 Enter message, ending with "." on a line by itself -expanding: ${tod_full} - result: Tue, 2 Mar 1999 09:44:33 +0000 -condition: def:sender_rcvhost - result: false -expanding: from $sender_rcvhost - - result: from - -skipping: result is not used -condition: def:sender_ident - result: true -expanding: $sender_ident - result: CALLER -expanding: from ${quote_local_part:$sender_ident} - result: from CALLER -condition: def:sender_helo_name - result: true -expanding: (helo=$sender_helo_name) - - result: (helo=myhost.test.ex) - -expanding: ${if def:sender_ident {from ${quote_local_part:$sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name) - }} - result: from CALLER (helo=myhost.test.ex) - -condition: def:received_protocol - result: true -expanding: with $received_protocol - result: with local-esmtp -condition: def:sender_address - result: true -expanding: (envelope-from <$sender_address>) - - result: (envelope-from ) - -condition: def:received_for - result: true -expanding: - for $received_for - result: - for userx@domain.com -PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< -expanding: ${tod_full} - result: Tue, 2 Mar 1999 09:44:33 +0000 - SMTP>> . - SMTP<< 250 OK id=10HmaX-0005vi-00 -LOG: MAIN - >> userx@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] X=TLSv1:AES256-SHA:256 C="250 OK id=10HmaX-0005vi-00" - SMTP>> QUIT ------------ cutthrough shutdown (delivered) ------------ -LOG: MAIN - <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss -LOG: MAIN - Completed -LOG: smtp_connection MAIN - SMTP connection from CALLER closed by QUIT ->>>>>>>>>>>>>>>> Exim pid=pppp terminating with rc=0 >>>>>>>>>>>>>>>> -Exim version x.yz .... -configuration file is TESTSUITE/test-config -admin user - in hosts_connection_nolog? no (option unset) -LOG: smtp_connection MAIN - SMTP connection from CALLER -expanding: $smtp_active_hostname ESMTP Exim $version_number $tod_full - result: myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 - in pipelining_advertise_hosts? yes (matched "*") - in tls_advertise_hosts? yes (matched "*") -expanding: SERVER - result: SERVER -expanding: server - result: server -condition: eq {SERVER}{server} - result: false -expanding: queue - result: queue -skipping: result is not used -expanding: cutthrough - result: cutthrough -expanding: ${if eq {SERVER}{server}{queue}{cutthrough}} - result: cutthrough -using ACL "cutthrough" -processing "accept" -check control = cutthrough_delivery -check verify = recipient -domain.com in "test.ex : *.test.ex"? no (end of list) -domain.com in "! +local_domains"? yes (end of list) -expanding: $local_part - result: usery -domain.com in "*"? yes (matched "*") ------------ end verify ------------ -accept: condition test succeeded in ACL "cutthrough" ------------ start cutthrough setup ------------ -domain.com in "test.ex : *.test.ex"? no (end of list) -domain.com in "! +local_domains"? yes (end of list) -expanding: $local_part - result: usery -domain.com in "*"? yes (matched "*") -Connecting to 127.0.0.1 [127.0.0.1]:1225 from ip4.ip4.ip4.ip4 ... connected -expanding: $primary_hostname - result: myhost.test.ex - SMTP<< 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 -127.0.0.1 in hosts_avoid_esmtp? no (option unset) - SMTP>> EHLO myhost.test.ex - SMTP<< 250-myhost.test.ex Hello the.local.host.name [ip4.ip4.ip4.ip4] - 250-SIZE 52428800 - 250-8BITMIME - 250-PIPELINING - 250-STARTTLS - 250 HELP -expanding: $address_data - result: usery -expanding: usery - result: usery -condition: eq {$address_data}{usery} - result: true -expanding: * - result: * -expanding: : - result: : -skipping: result is not used -expanding: ${if eq {$address_data}{usery}{*}{:}} - result: * -127.0.0.1 in hosts_avoid_tls? yes (matched "*") - SMTP>> MAIL FROM: - SMTP<< 250 OK - SMTP>> RCPT TO: - SMTP<< 250 Accepted ------------ end cutthrough setup ------------ -processing "accept" -accept: condition test succeeded in inline ACL - SMTP>> DATA - SMTP<< 354 Enter message, ending with "." on a line by itself -expanding: ${tod_full} - result: Tue, 2 Mar 1999 09:44:33 +0000 -condition: def:sender_rcvhost - result: false -expanding: from $sender_rcvhost - - result: from - -skipping: result is not used -condition: def:sender_ident - result: true -expanding: $sender_ident - result: CALLER -expanding: from ${quote_local_part:$sender_ident} - result: from CALLER -condition: def:sender_helo_name - result: true -expanding: (helo=$sender_helo_name) - - result: (helo=myhost.test.ex) - -expanding: ${if def:sender_ident {from ${quote_local_part:$sender_ident} }}${if def:sender_helo_name {(helo=$sender_helo_name) - }} - result: from CALLER (helo=myhost.test.ex) - -condition: def:received_protocol - result: true -expanding: with $received_protocol - result: with local-esmtp -condition: def:sender_address - result: true -expanding: (envelope-from <$sender_address>) - - result: (envelope-from ) - -condition: def:received_for - result: true -expanding: - for $received_for - result: - for usery@domain.com -PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< -expanding: ${tod_full} - result: Tue, 2 Mar 1999 09:44:33 +0000 - SMTP>> . - SMTP<< 250 OK id=10HmaZ-0005vi-00 -LOG: MAIN - >> usery@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK id=10HmaZ-0005vi-00" - SMTP>> QUIT ------------ cutthrough shutdown (delivered) ------------ -LOG: MAIN - <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss -LOG: MAIN - Completed -LOG: smtp_connection MAIN - SMTP connection from CALLER closed by QUIT ->>>>>>>>>>>>>>>> Exim pid=pppp terminating with rc=0 >>>>>>>>>>>>>>>> - -******** SERVER ******** +>>> host in hosts_connection_nolog? no (option unset) +>>> host in host_lookup? no (option unset) +>>> host in host_reject_connection? no (option unset) +>>> host in sender_unqualified_hosts? no (option unset) +>>> host in recipient_unqualified_hosts? no (option unset) +>>> host in helo_verify_hosts? no (option unset) +>>> host in helo_try_verify_hosts? no (option unset) +>>> host in helo_accept_junk_hosts? no (option unset) +>>> myhost.test.ex in helo_lookup_domains? yes (matched "@") +>>> looking up host name for 1.2.3.4 +LOG: no host name found for IP address 1.2.3.4 +>>> host in dsn_advertise_hosts? no (option unset) +>>> host in pipelining_advertise_hosts? yes (matched "*") +>>> using ACL "ar" +>>> processing "warn" +>>> check control = cutthrough_delivery +>>> check logwrite = rcpt for $local_part@$domain +>>> = rcpt for plain@domain.com +LOG: rcpt for plain@domain.com +>>> warn: condition test succeeded in ACL "ar" +>>> processing "warn" +>>> check condition = ${if eq {verify}{$local_part}} +>>> = +>>> warn: condition test failed in ACL "ar" +>>> processing "accept" +>>> accept: condition test succeeded in ACL "ar" +>>> end of ACL "ar": ACCEPT +LOG: 10HmaX-0005vi-00 <= CALLER@myhost.test.ex H=(myhost.test.ex) [1.2.3.4] P=esmtp S=sss for plain@domain.com +>>> host in hosts_connection_nolog? no (option unset) +>>> host in host_lookup? no (option unset) +>>> host in host_reject_connection? no (option unset) +>>> host in sender_unqualified_hosts? no (option unset) +>>> host in recipient_unqualified_hosts? no (option unset) +>>> host in helo_verify_hosts? no (option unset) +>>> host in helo_try_verify_hosts? no (option unset) +>>> host in helo_accept_junk_hosts? no (option unset) +>>> myhost.test.ex in helo_lookup_domains? yes (matched "@") +>>> looking up host name for 1.2.3.4 +LOG: no host name found for IP address 1.2.3.4 +>>> host in dsn_advertise_hosts? no (option unset) +>>> host in pipelining_advertise_hosts? yes (matched "*") +>>> using ACL "ar" +>>> processing "warn" +>>> check control = cutthrough_delivery +>>> check logwrite = rcpt for $local_part@$domain +>>> = rcpt for verify@domain.com +LOG: rcpt for verify@domain.com +>>> warn: condition test succeeded in ACL "ar" +>>> processing "warn" +>>> check condition = ${if eq {verify}{$local_part}} +>>> = true +>>> check verify = recipient/callout=use_sender +>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +>>> routing verify@domain.com +>>> domain.com in "localhost.test.ex : localhost4.test.ex : thishost.test.ex"? no (end of list) +>>> domain.com in "test.ex : *.test.ex"? no (end of list) +>>> domain.com in "! +local_domains"? yes (end of list) +>>> calling all router +>>> domain.com in "special.com"? no (end of list) +>>> domain.com in "*"? yes (matched "*") +>>> local host found for non-MX address +>>> fully qualified name = 127.0.0.1 +MUNGED: ::1 will be omitted in what follows +>>> get[host|ipnode]byname[2] looked up these IP addresses: +>>> name=127.0.0.1 address=127.0.0.1 +>>> routed by all router +>>> Attempting full verification using callout +>>> callout cache: no domain record found for domain.com +>>> callout cache: no address record found for verify@domain.com/ +>>> interface=ip4.ip4.ip4.ip4 port=1224 +>>> Connecting to 127.0.0.1 [127.0.0.1]:1224 from ip4.ip4.ip4.ip4 ... connected +>>> SMTP<< 220 server ready +>>> 127.0.0.1 in hosts_avoid_esmtp? no (option unset) +>>> SMTP>> EHLO myhost.test.ex +>>> SMTP<< 250 OK +>>> 127.0.0.1 in hosts_require_auth? no (option unset) +>>> SMTP>> MAIL FROM: +>>> SMTP<< 250 OK +>>> SMTP>> RCPT TO: +>>> SMTP<< 250 OK +>>> wrote callout cache domain record: +>>> result=1 postmaster=0 random=0 +>>> wrote positive callout cache address record +>>> ----------- end verify ------------ +>>> warn: condition test succeeded in ACL "ar" +>>> processing "accept" +>>> accept: condition test succeeded in ACL "ar" +>>> end of ACL "ar": ACCEPT +>>> SMTP>> QUIT +>>> ----------- cutthrough shutdown (host-checking mode) ------------ +LOG: 10HmaY-0005vi-00 <= CALLER@myhost.test.ex H=(myhost.test.ex) [1.2.3.4] P=esmtp S=sss for verify@domain.com diff --git a/test/stdout/5402 b/test/stdout/5402 index 252c82917..c0548bae7 100644 --- a/test/stdout/5402 +++ b/test/stdout/5402 @@ -1,24 +1,55 @@ + +**** SMTP testing session as if from host 1.2.3.4 +**** but without any ident (RFC 1413) callback. +**** This is not for real! + 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 -250-myhost.test.ex Hello CALLER at myhost.test.ex +250-myhost.test.ex Hello myhost.test.ex [1.2.3.4] 250-SIZE 52428800 250-8BITMIME 250-PIPELINING -250-STARTTLS 250 HELP 250 OK 250 Accepted 354 Enter message, ending with "." on a line by itself -250 OK id=10HmaY-0005vi-00 +250 OK id=10HmaX-0005vi-00 + +**** SMTP testing: that is not a real message id! + 221 myhost.test.ex closing connection + +**** SMTP testing session as if from host 1.2.3.4 +**** but without any ident (RFC 1413) callback. +**** This is not for real! + 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000 -250-myhost.test.ex Hello CALLER at myhost.test.ex +250-myhost.test.ex Hello myhost.test.ex [1.2.3.4] 250-SIZE 52428800 250-8BITMIME 250-PIPELINING -250-STARTTLS 250 HELP 250 OK 250 Accepted 354 Enter message, ending with "." on a line by itself -250 OK id=10HmbA-0005vi-00 +250 OK id=10HmaY-0005vi-00 + +**** SMTP testing: that is not a real message id! + 221 myhost.test.ex closing connection + +******** SERVER ******** +Listening on port 1224 ... +Server timed out +Listening on port 1224 ... +Connection request from [ip4.ip4.ip4.ip4] +220 server ready +EHLO myhost.test.ex +250 OK +MAIL FROM: +250 OK +RCPT TO: +250 OK +QUIT +220 OK +Expected EOF read from client +End of script -- 2.30.2