Verify callout/random: repoen connection if error after random rcpt attempt. Bug 495
authorJeremy Harris <jgh146exb@wizmail.org>
Sun, 15 Feb 2015 20:38:26 +0000 (20:38 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Sun, 15 Feb 2015 21:05:03 +0000 (21:05 +0000)
src/src/verify.c
test/scripts/0000-Basic/0473
test/stdout/0473

index ec75ce5ce3b3fec2d090c722a4ce38ea6dfd5872..c1fb17767659a6be24de8c68d5578758bf953c9f 100644 (file)
@@ -388,12 +388,9 @@ else
   log the fact, but carry on without randomming. */
 
   if (callout_random && callout_random_local_part != NULL)
-    {
-    random_local_part = expand_string(callout_random_local_part);
-    if (random_local_part == NULL)
+    if (!(random_local_part = expand_string(callout_random_local_part)))
       log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand "
         "callout_random_local_part: %s", expand_string_message);
-    }
 
   /* Default the connect and overall callout timeouts if not set, and record the
   time we are starting so that we can enforce it. */
@@ -635,14 +632,14 @@ can do it there for the non-rcpt-verify case.  For this we keep an addresscount.
     outblock.cmd_count = 0;
     outblock.authenticating = FALSE;
 
-    /* Reset the parameters of a TLS session */
-    tls_out.cipher = tls_out.peerdn = tls_out.peercert = NULL;
-
     /* Connect to the host; on failure, just loop for the next one, but we
     set the error for the last one. Use the callout_connect timeout. */
 
     tls_retry_connection:
 
+    /* Reset the parameters of a TLS session */
+    tls_out.cipher = tls_out.peerdn = tls_out.peercert = NULL;
+
     inblock.sock = outblock.sock =
       smtp_connect(host, host_af, port, interface, callout_connect, TRUE, NULL
 #ifdef EXPERIMENTAL_EVENT
@@ -1009,10 +1006,15 @@ can do it there for the non-rcpt-verify case.  For this we keep an addresscount.
 
         /* Otherwise, cache a real negative response, and get back to the right
         state to send RCPT. Unless there's some problem such as a dropped
-        connection, we expect to succeed, because the commands succeeded above. */
+        connection, we expect to succeed, because the commands succeeded above.
+       However, some servers drop the connection after responding to  an
+       invalid recipient, so on (any) error we drop and remake the connection.
+       */
 
         else if (errno == 0)
           {
+         /* This would be ok for 1st rcpt a cutthrough, but no way to
+         handle a subsequent.  So refuse to support any */
          cancel_cutthrough_connection("random-recipient");
 
           if (randombuffer[0] == '5')
@@ -1027,6 +1029,22 @@ can do it there for the non-rcpt-verify case.  For this we keep an addresscount.
               from_address) >= 0 &&
             smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer),
               '2', callout);
+
+         if (!done)
+           {
+           HDEBUG(D_acl|D_v)
+             debug_printf("problem after random/rset/mfrom; reopen conn\n");
+           random_local_part = NULL;
+#ifdef SUPPORT_TLS
+           tls_close(FALSE, TRUE);
+#endif
+           (void)close(inblock.sock);
+#ifdef EXPERIMENTAL_EVENT
+           (void) event_raise(addr->transport->event_action,
+                             US"tcp:close", NULL);
+#endif
+           goto tls_retry_connection;
+           }
           }
         else done = FALSE;    /* Some timeout/connection problem */
         }                     /* Random check */
@@ -1060,8 +1078,9 @@ can do it there for the non-rcpt-verify case.  For this we keep an addresscount.
 
         if (done && pm_mailfrom != NULL)
           {
-          /*XXX not suitable for cutthrough - we cannot afford to do an RSET
-         and lose the original mail-from */
+          /* Could possibly shift before main verify, just above, and be ok
+         for cutthrough.  But no way to handle a subsequent rcpt, so just
+         refuse any */
        cancel_cutthrough_connection("postmaster verify");
        HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of postmaster verify\n");
 
index 3d17e5ed019868c5e18866cf7c43bb2f46d674b4..df613c4b7ca53378be2f7e95b8de370fc5524a94 100644 (file)
@@ -150,6 +150,34 @@ rcpt to: r11@two.test.ex
 quit
 ****
 dump callout
+#
+# callout target dumps after random-reject
+server PORT_S 2
+220 Server ready
+EHLO
+250 OK
+MAIL FROM
+250 OK
+RCPT TO
+550 Bad receipient, dropping conn
+>*eof
+220 Server ready
+EHLO
+250 OK
+MAIL FROM
+250 OK
+RCPT TO
+250 OK
+QUIT
+250 OK
+****
+exim -DUSE_SENDER=,random -bs
+ehlo xxxx
+mail from: x12@three.test.ex
+rcpt to: r12@three.test.ex
+quit
+****
+dump callout
 server PORT_S
 220 Server ready
 EHLO
index 9fff9a601a3d87030714d920c0d9cb96e89974a0..59ed36d6a602e2ff2c66f73b696b08c1d12e18ff 100644 (file)
 250-PIPELINING\r
 250 HELP\r
 250 OK\r
+250 Accepted\r
+221 the.local.host.name closing connection\r
++++++++++++++++++++++++++++
+07-Mar-2000 12:21:52 r12@three.test.ex callout=accept
+07-Mar-2000 12:21:52 r1@test.ex callout=accept
+07-Mar-2000 12:21:52 r1@test.ex/<postmaster@the.local.host.name> callout=accept
+07-Mar-2000 12:21:52 r1@test.ex/<s1@test.ex> callout=accept
+07-Mar-2000 12:21:52 r1@test.ex/<s2@test.ex> callout=accept
+07-Mar-2000 12:21:52 r9@test.ex/<x9@test.ex> callout=reject
+07-Mar-2000 12:21:52 test.ex callout=accept postmaster=unknown random=unknown
+07-Mar-2000 12:21:52 three.test.ex callout=accept postmaster=unknown random=reject (07-Mar-2000 12:21:52)
+07-Mar-2000 12:21:52 two.test.ex callout=accept postmaster=unknown random=accept (07-Mar-2000 12:21:52)
+07-Mar-2000 12:21:52 x9@test.ex callout=reject
+220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
+250-the.local.host.name Hello CALLER at xxxx\r
+250-SIZE 52428800\r
+250-8BITMIME\r
+250-PIPELINING\r
+250 HELP\r
+250 OK\r
 451 Could not complete recipient verify callout\r
 221 the.local.host.name closing connection\r
 220 the.local.host.name ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000\r
@@ -221,6 +241,28 @@ EHLO the.local.host.name
 250 OK
 MAIL FROM:<>
 250 OK
+RCPT TO:<the.local.host.name--testing@three.test.ex>
+550 Bad receipient, dropping conn
+>*eof
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Server ready
+EHLO the.local.host.name
+250 OK
+MAIL FROM:<>
+250 OK
+RCPT TO:<r12@three.test.ex>
+250 OK
+QUIT
+250 OK
+End of script
+Listening on port 1224 ... 
+Connection request from [127.0.0.1]
+220 Server ready
+EHLO the.local.host.name
+250 OK
+MAIL FROM:<>
+250 OK
 RCPT TO:<r11@two.test.ex>
 *sleep 2
 End of script