On callout avoid SIZE every time but noncacheable rcpt main-verify. Bug 2151
[exim.git] / src / src / verify.c
index 3dd2d3a39c9c850ee6bf196f6ec0194c8495bdce..31c061535274197b3044cec3770f2b179705d5e1 100644 (file)
@@ -682,7 +682,9 @@ tls_retry_connection:
     SMTP command to send.  If we tried TLS but it failed, try again without
     if permitted */
 
-    if (  (yield = smtp_setup_conn(&sx, FALSE)) == DEFER
+    yield = smtp_setup_conn(&sx, FALSE);
+#ifdef SUPPORT_TLS
+    if (  yield == DEFER
        && addr->basic_errno == ERRNO_TLSFAILURE
        && ob->tls_tempfail_tryclear
        && verify_check_given_host(&ob->hosts_require_tls, host) != OK
@@ -694,6 +696,7 @@ tls_retry_connection:
       addr->transport_return = PENDING_DEFER;
       yield = smtp_setup_conn(&sx, TRUE);
       }
+#endif
     if (yield != OK)
       {
       errno = addr->basic_errno;
@@ -776,16 +779,26 @@ tls_retry_connection:
       postmaster-verify.
       The sync_responses() would need to be taught about it and we'd
       need another return code filtering out to here.
+
+      Avoid using a SIZE option on the MAIL for all randon-rcpt checks.
       */
 
+      sx.avoid_option = OPTION_SIZE;
+
+      /* Remember when we last did a random test */
+      new_domain_record.random_stamp = time(NULL);
+
       if (smtp_write_mail_and_rcpt_cmds(&sx, &yield) == 0)
        switch(addr->transport_return)
          {
          case PENDING_OK:
            new_domain_record.random_result = ccache_accept;
-           break;
-         case FAIL:
+           yield = OK;         /* Only usable result we can return */
+           done = TRUE;
+           goto no_conn;
+         case FAIL:            /* the preferred result */
            new_domain_record.random_result = ccache_reject;
+           sx.avoid_option = 0;
 
            /* Between each check, issue RSET, because some servers accept only
            one recipient after MAIL FROM:<>.
@@ -798,25 +811,27 @@ tls_retry_connection:
              break;
 
            HDEBUG(D_acl|D_v)
-             debug_printf("problem after random/rset/mfrom; reopen conn\n");
+             debug_printf_indent("problem after random/rset/mfrom; reopen conn\n");
            random_local_part = NULL;
 #ifdef SUPPORT_TLS
            tls_close(FALSE, TRUE);
 #endif
-           HDEBUG(D_transport|D_acl|D_v) debug_printf("  SMTP(close)>>\n");
+           HDEBUG(D_transport|D_acl|D_v) debug_printf_indent("  SMTP(close)>>\n");
            (void)close(sx.inblock.sock);
            sx.inblock.sock = sx.outblock.sock = -1;
 #ifndef DISABLE_EVENT
            (void) event_raise(addr->transport->event_action,
                              US"tcp:close", NULL);
 #endif
+           addr->address = main_address;
+           addr->transport_return = PENDING_DEFER;
+           sx.first_addr = sx.sync_addr = addr;
+           sx.ok = FALSE;
+           sx.send_rset = TRUE;
+           sx.completed_addr = FALSE;
            goto tls_retry_connection;
          }
 
-      /* Remember when we last did a random test */
-
-      new_domain_record.random_stamp = time(NULL);
-
       /* Re-setup for main verify, or for the error message when failing */
       addr->address = main_address;
       addr->transport_return = PENDING_DEFER;
@@ -828,12 +843,14 @@ tls_retry_connection:
     else
       done = TRUE;
 
-    /* Main verify. If the host is accepting all local parts, as determined
-    by the "random" check, we don't need to waste time doing any further
-    checking. */
+    /* Main verify.  For rcpt-verify use SIZE if we know it and we're not cacheing;
+    for sndr-verify never use it. */
 
     if (done)
       {
+      if (!(options & vopt_is_recipient  &&  options & vopt_callout_no_cache))
+       sx.avoid_option = OPTION_SIZE;
+
       done = FALSE;
       switch(smtp_write_mail_and_rcpt_cmds(&sx, &yield))
        {
@@ -842,12 +859,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;
 
@@ -881,7 +898,7 @@ tls_retry_connection:
       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");
+      HDEBUG(D_acl|D_v) debug_printf_indent("Cutthrough cancelled by presence of postmaster verify\n");
 
       done = smtp_write_command(&sx.outblock, FALSE, "RSET\r\n") >= 0
           && smtp_read_response(&sx.inblock, sx.buffer,
@@ -900,6 +917,7 @@ tls_retry_connection:
        sx.ok = FALSE;
        sx.send_rset = TRUE;
        sx.completed_addr = FALSE;
+       sx.avoid_option = OPTION_SIZE;
 
        if(  smtp_write_mail_and_rcpt_cmds(&sx, &yield) == 0
          && addr->transport_return == PENDING_OK
@@ -1009,7 +1027,7 @@ no_conn:
        && !sx.lmtp
        )
       {
-      HDEBUG(D_acl|D_v) debug_printf("holding verify callout open for cutthrough delivery\n");
+      HDEBUG(D_acl|D_v) debug_printf_indent("holding verify callout open for cutthrough delivery\n");
 
       cutthrough.fd = sx.outblock.sock;        /* We assume no buffer in use in the outblock */
       cutthrough.nrcpt = 1;
@@ -1046,7 +1064,7 @@ no_conn:
 #ifdef SUPPORT_TLS
        tls_close(FALSE, TRUE);
 #endif
-       HDEBUG(D_transport|D_acl|D_v) debug_printf("  SMTP(close)>>\n");
+       HDEBUG(D_transport|D_acl|D_v) debug_printf_indent("  SMTP(close)>>\n");
        (void)close(sx.inblock.sock);
        sx.inblock.sock = sx.outblock.sock = -1;
 #ifndef DISABLE_EVENT
@@ -1123,7 +1141,7 @@ int rc;
 get rewritten. */
 
 addr2 = *addr;
-HDEBUG(D_acl) debug_printf("----------- %s cutthrough setup ------------\n",
+HDEBUG(D_acl) debug_printf_indent("----------- %s cutthrough setup ------------\n",
   rcpt_count > 1 ? "more" : "start");
 rc = verify_address(&addr2, NULL,
        vopt_is_recipient | vopt_callout_recipsender | vopt_callout_no_cache,
@@ -1131,7 +1149,7 @@ rc = verify_address(&addr2, NULL,
        NULL, NULL, NULL);
 addr->message = addr2.message;
 addr->user_message = addr2.user_message;
-HDEBUG(D_acl) debug_printf("----------- end cutthrough setup ------------\n");
+HDEBUG(D_acl) debug_printf_indent("----------- end cutthrough setup ------------\n");
 return rc;
 }
 
@@ -1156,7 +1174,7 @@ if(
   return TRUE;
 }
 
-HDEBUG(D_transport|D_acl) debug_printf("cutthrough_send failed: %s\n", strerror(errno));
+HDEBUG(D_transport|D_acl) debug_printf_indent("cutthrough_send failed: %s\n", strerror(errno));
 return FALSE;
 }
 
@@ -1254,7 +1272,7 @@ cutthrough_predata(void)
 if(cutthrough.fd < 0)
   return FALSE;
 
-HDEBUG(D_transport|D_acl|D_v) debug_printf("  SMTP>> DATA\n");
+HDEBUG(D_transport|D_acl|D_v) debug_printf_indent("  SMTP>> DATA\n");
 cutthrough_puts(US"DATA\r\n", 6);
 cutthrough_flush_send();
 
@@ -1292,7 +1310,7 @@ if(cutthrough.fd < 0)
 /* We share a routine with the mainline transport to handle header add/remove/rewrites,
    but having a separate buffered-output function (for now)
 */
-HDEBUG(D_acl) debug_printf("----------- start cutthrough headers send -----------\n");
+HDEBUG(D_acl) debug_printf_indent("----------- start cutthrough headers send -----------\n");
 
 tctx.tblock = cutthrough.addr.transport;
 tctx.addr = &cutthrough.addr;
@@ -1303,7 +1321,7 @@ tctx.options = topt_use_crlf;
 if (!transport_headers_send(cutthrough.fd, &tctx, &cutthrough_write_chunk))
   return FALSE;
 
-HDEBUG(D_acl) debug_printf("----------- done cutthrough headers send ------------\n");
+HDEBUG(D_acl) debug_printf_indent("----------- done cutthrough headers send ------------\n");
 return TRUE;
 }
 
@@ -1318,7 +1336,7 @@ if(cutthrough.fd >= 0)
      conn before the final dot.
   */
   ctblock.ptr = ctbuffer;
-  HDEBUG(D_transport|D_acl|D_v) debug_printf("  SMTP>> QUIT\n");
+  HDEBUG(D_transport|D_acl|D_v) debug_printf_indent("  SMTP>> QUIT\n");
   _cutthrough_puts(US"QUIT\r\n", 6);   /* avoid recursion */
   _cutthrough_flush_send();
 
@@ -1328,10 +1346,10 @@ if(cutthrough.fd >= 0)
   #ifdef SUPPORT_TLS
   tls_close(FALSE, TRUE);
   #endif
-  HDEBUG(D_transport|D_acl|D_v) debug_printf("  SMTP(close)>>\n");
+  HDEBUG(D_transport|D_acl|D_v) debug_printf_indent("  SMTP(close)>>\n");
   (void)close(cutthrough.fd);
   cutthrough.fd = -1;
-  HDEBUG(D_acl) debug_printf("----------- cutthrough shutdown (%s) ------------\n", why);
+  HDEBUG(D_acl) debug_printf_indent("----------- cutthrough shutdown (%s) ------------\n", why);
   }
 ctblock.ptr = ctbuffer;
 }
@@ -1356,7 +1374,7 @@ cutthrough_finaldot(void)
 {
 uschar res;
 address_item * addr;
-HDEBUG(D_transport|D_acl|D_v) debug_printf("  SMTP>> .\n");
+HDEBUG(D_transport|D_acl|D_v) debug_printf_indent("  SMTP>> .\n");
 
 /* Assume data finshed with new-line */
 if(  !cutthrough_puts(US".", 1)