Cutthrough: handle request when a callout-hold is active. Bug 2604
authorJeremy Harris <jgh146exb@wizmail.org>
Mon, 22 Jun 2020 16:27:18 +0000 (17:27 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Mon, 22 Jun 2020 17:13:19 +0000 (18:13 +0100)
(cherry picked from commit 99bfcf2b678e7bd8125a7eb44409e46549bfc111)

doc/doc-txt/ChangeLog
src/src/acl.c
src/src/verify.c
test/confs/5409 [new file with mode: 0644]
test/log/5409 [new file with mode: 0644]
test/scripts/5400-cutthrough/5409 [new file with mode: 0644]
test/stdout/5409 [new file with mode: 0644]

index 1173b3651dc11dc003ac6860a16236d7e62e1b26..de11b4f097b396298961d27eea23ae195715864d 100644 (file)
@@ -45,6 +45,10 @@ JH/10 Bug 2603: Fix coding of string copying to only evaluate arguments once.
       argument as an expression having side-effects, incorrect operation
       resulted.  Use an inlineable function.
 
+JH/11 Bug 2604: Fix request to cutthrough-deliver when a connection is already
+      held open for a verify callout.  Previously this wan not accounted for
+      and a corrupt onward SMTP conversation resulted.
+
 
 
 Exim version 4.94
index 11d1fd028ff2c42526a0a808e18de01c68472238..62cb6856179e7868c85014e93e35bd3ebbd160f0 100644 (file)
@@ -3264,37 +3264,41 @@ for (; cb; cb = cb->next)
            the case where both sides handle prdr and this-node prdr acl
            is "accept" */
            ignored = US"PRDR active";
+         else if (f.deliver_freeze)
+           ignored = US"frozen";
+         else if (f.queue_only_policy)
+           ignored = US"queue-only";
+         else if (fake_response == FAIL)
+           ignored = US"fakereject";
+         else if (rcpt_count != 1)
+           ignored = US"nonfirst rcpt";
+         else if (cutthrough.delivery)
+           ignored = US"repeated";
+         else if (cutthrough.callout_hold_only)
+           {
+           DEBUG(D_acl)
+             debug_printf_indent(" cutthrough request upgrades callout hold\n");
+           cutthrough.callout_hold_only = FALSE;
+           cutthrough.delivery = TRUE; /* control accepted */
+           }
          else
            {
-           if (f.deliver_freeze)
-             ignored = US"frozen";
-           else if (f.queue_only_policy)
-             ignored = US"queue-only";
-           else if (fake_response == FAIL)
-             ignored = US"fakereject";
-           else
+           cutthrough.delivery = TRUE; /* control accepted */
+           while (*p == '/')
              {
-             if (rcpt_count == 1)
+             const uschar * pp = p+1;
+             if (Ustrncmp(pp, "defer=", 6) == 0)
                {
-               cutthrough.delivery = TRUE;     /* control accepted */
-               while (*p == '/')
-                 {
-                 const uschar * pp = p+1;
-                 if (Ustrncmp(pp, "defer=", 6) == 0)
-                   {
-                   pp += 6;
-                   if (Ustrncmp(pp, "pass", 4) == 0) cutthrough.defer_pass = TRUE;
-                   /* else if (Ustrncmp(pp, "spool") == 0) ;   default */
-                   }
-                 else
-                   while (*pp && *pp != '/') pp++;
-                 p = pp;
-                 }
+               pp += 6;
+               if (Ustrncmp(pp, "pass", 4) == 0) cutthrough.defer_pass = TRUE;
+               /* else if (Ustrncmp(pp, "spool") == 0) ;       default */
                }
              else
-               ignored = US"nonfirst rcpt";
+               while (*pp && *pp != '/') pp++;
+             p = pp;
              }
            }
+
          DEBUG(D_acl) if (ignored)
            debug_printf(" cutthrough request ignored on %s item\n", ignored);
          }
index fba1f6e9e0a96d80c447a9201bddc00ad563cc38..5f4181de91af5576aa8dce73c137d0eefbfc4ee9 100644 (file)
@@ -875,12 +875,12 @@ tls_retry_connection:
                    case PENDING_OK:  done = TRUE;
                                      new_address_record.result = ccache_accept;
                                      break;
-                   case FAIL:      done = TRUE;
+                   case FAIL:        done = TRUE;
                                      yield = FAIL;
                                      *failure_ptr = US"recipient";
                                      new_address_record.result = ccache_reject;
                                      break;
-                   default:        break;
+                   default:          break;
                    }
                  break;
 
diff --git a/test/confs/5409 b/test/confs/5409
new file mode 100644 (file)
index 0000000..be1415e
--- /dev/null
@@ -0,0 +1,46 @@
+# Exim test configuration 5409
+
+.include DIR/aux-var/std_conf_prefix
+
+primary_hostname = myhost.test.ex
+
+# ----- Main settings -----
+
+domainlist local_domains = test.ex : *.test.ex
+
+acl_smtp_rcpt = acl_rcpt
+
+# ----- ACLs -------
+
+begin acl
+
+acl_rcpt:
+    accept     verify = recipient/callout=use_sender,hold,no_cache
+               control = cutthrough_delivery
+
+
+# ----- Routers -----
+
+begin routers
+
+all:
+  driver = manualroute
+  domains = ! +local_domains
+  route_list = * 127.0.0.1
+  self = send
+  transport = smtp
+  no_more
+
+
+# ----- Transports -----
+
+begin transports
+
+smtp:
+  driver = smtp
+  interface = HOSTIPV4
+  port = PORT_S
+  hosts_try_fastopen = :
+
+
+# End
diff --git a/test/log/5409 b/test/log/5409
new file mode 100644 (file)
index 0000000..37ad467
--- /dev/null
@@ -0,0 +1,3 @@
+1999-03-02 09:44:33 10HmaX-0005vi-00 >> userx@domain.com R=all T=smtp H=127.0.0.1 [127.0.0.1] C="250 OK"
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local-esmtp S=sss
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
diff --git a/test/scripts/5400-cutthrough/5409 b/test/scripts/5400-cutthrough/5409
new file mode 100644 (file)
index 0000000..c9d63d1
--- /dev/null
@@ -0,0 +1,29 @@
+# cutthrough_delivery preceded by recipient-verify/hold
+need_ipv4
+#
+server PORT_S
+220 ESMTP
+EHLO
+250 OK
+MAIL FROM:
+250 Sender OK
+RCPT TO:
+250 Recipient OK
+DATA
+354 Send data
+.
+250 OK
+QUIT
+250 OK
+****
+exim -bs -odf
+EHLO myhost.test.ex
+MAIL FROM:<CALLER@myhost.test.ex>
+RCPT TO:<userx@domain.com>
+DATA
+Subject: test
+
+body
+.
+QUIT
+****
diff --git a/test/stdout/5409 b/test/stdout/5409
new file mode 100644 (file)
index 0000000..a582bb8
--- /dev/null
@@ -0,0 +1,40 @@
+220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
+250-myhost.test.ex Hello CALLER at myhost.test.ex\r
+250-SIZE 52428800\r
+250-8BITMIME\r
+250-PIPELINING\r
+250 HELP\r
+250 OK\r
+250 Accepted\r
+354 Enter message, ending with "." on a line by itself\r
+250 OK id=10HmaX-0005vi-00\r
+221 myhost.test.ex closing connection\r
+
+******** SERVER ********
+Listening on port 1224 ... 
+Connection request from [ip4.ip4.ip4.ip4]
+220 ESMTP
+EHLO myhost.test.ex
+250 OK
+MAIL FROM:<CALLER@myhost.test.ex>
+250 Sender OK
+RCPT TO:<userx@domain.com>
+250 Recipient OK
+DATA
+354 Send data
+Received: from CALLER (helo=myhost.test.ex)
+       by myhost.test.ex with local-esmtp (Exim x.yz)
+       (envelope-from <CALLER@myhost.test.ex>)
+       id 10HmaX-0005vi-00
+       for userx@domain.com; Tue, 2 Mar 1999 09:44:33 +0000
+Subject: test
+Message-Id: <E10HmaX-0005vi-00@myhost.test.ex>
+From: CALLER_NAME <CALLER@myhost.test.ex>
+Date: Tue, 2 Mar 1999 09:44:33 +0000
+
+body
+.
+250 OK
+QUIT
+250 OK
+End of script