[exim-cvs] Deal explicitly with attempt to callout via null …

Top Page
Delete this message
Reply to this message
Author: Exim Git Commits Mailing List
Date:  
To: exim-cvs
Subject: [exim-cvs] Deal explicitly with attempt to callout via null transport; fixes crash.
Gitweb: http://git.exim.org/exim.git/commitdiff/193e3acd2723abeaaad8575fec3c058df674fc5d
Commit:     193e3acd2723abeaaad8575fec3c058df674fc5d
Parent:     cb9d95aeae369ae85cd13473cda0bb3ae415fcb9
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Sun May 6 17:12:31 2012 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Mon Jun 4 14:57:02 2012 +0100


    Deal explicitly with attempt to callout via null transport; fixes crash.
---
 src/src/verify.c             |  983 +++++++++++++++++++++---------------------
 test/confs/0538              |    7 +
 test/log/0527                |    4 +-
 test/rejectlog/0527          |    4 +-
 test/scripts/0000-Basic/0527 |   11 -
 test/scripts/0000-Basic/0538 |    4 +-
 test/stderr/0443             |    5 +-
 test/stderr/0473             |    2 +-
 test/stdout/0473             |   18 +-
 test/stdout/0527             |   20 +-
 test/stdout/0538             |    4 +-
 11 files changed, 524 insertions(+), 538 deletions(-)


diff --git a/src/src/verify.c b/src/src/verify.c
index 964bdf7..39ef337 100644
--- a/src/src/verify.c
+++ b/src/src/verify.c
@@ -154,7 +154,6 @@ do_callout(address_item *addr, host_item *host_list, transport_feedback *tf,
int callout, int callout_overall, int callout_connect, int options,
uschar *se_mailfrom, uschar *pm_mailfrom)
{
-smtp_transport_options_block *ob = (smtp_transport_options_block *)(addr->transport->options_block);
BOOL is_recipient = (options & vopt_is_recipient) != 0;
BOOL callout_no_cache = (options & vopt_callout_no_cache) != 0;
BOOL callout_random = (options & vopt_callout_random) != 0;
@@ -370,596 +369,606 @@ if (dbm_file != NULL)
dbm_file = NULL;
}

-/* The information wasn't available in the cache, so we have to do a real
-callout and save the result in the cache for next time, unless no_cache is set,
-or unless we have a previously cached negative random result. If we are to test
-with a random local part, ensure that such a local part is available. If not,
-log the fact, but carry on without randomming. */
-
-if (callout_random && callout_random_local_part != NULL)
+if (!addr->transport)
   {
-  random_local_part = expand_string(callout_random_local_part);
-  if (random_local_part == NULL)
-    log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand "
-      "callout_random_local_part: %s", expand_string_message);
+  HDEBUG(D_verify) debug_printf("cannot callout via null transport\n");
   }
+else
+  {
+  smtp_transport_options_block *ob =
+    (smtp_transport_options_block *)(addr->transport->options_block);


-/* Default the connect and overall callout timeouts if not set, and record the
-time we are starting so that we can enforce it. */
+ /* The information wasn't available in the cache, so we have to do a real
+ callout and save the result in the cache for next time, unless no_cache is set,
+ or unless we have a previously cached negative random result. If we are to test
+ with a random local part, ensure that such a local part is available. If not,
+ log the fact, but carry on without randomming. */

-if (callout_overall < 0) callout_overall = 4 * callout;
-if (callout_connect < 0) callout_connect = callout;
-callout_start_time = time(NULL);
+  if (callout_random && callout_random_local_part != NULL)
+    {
+    random_local_part = expand_string(callout_random_local_part);
+    if (random_local_part == NULL)
+      log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand "
+        "callout_random_local_part: %s", expand_string_message);
+    }


-/* Before doing a real callout, if this is an SMTP connection, flush the SMTP
-output because a callout might take some time. When PIPELINING is active and
-there are many recipients, the total time for doing lots of callouts can add up
-and cause the client to time out. So in this case we forgo the PIPELINING
-optimization. */
+ /* Default the connect and overall callout timeouts if not set, and record the
+ time we are starting so that we can enforce it. */

-if (smtp_out != NULL && !disable_callout_flush) mac_smtp_fflush();
+ if (callout_overall < 0) callout_overall = 4 * callout;
+ if (callout_connect < 0) callout_connect = callout;
+ callout_start_time = time(NULL);

-/* Precompile some regex that are used to recognize parameters in response
-to an EHLO command, if they aren't already compiled. */
-#ifdef SUPPORT_TLS
-if (regex_STARTTLS == NULL) regex_STARTTLS =
- regex_must_compile(US"\\n250[\\s\\-]STARTTLS(\\s|\\n|$)", FALSE, TRUE);
-#endif
+ /* Before doing a real callout, if this is an SMTP connection, flush the SMTP
+ output because a callout might take some time. When PIPELINING is active and
+ there are many recipients, the total time for doing lots of callouts can add up
+ and cause the client to time out. So in this case we forgo the PIPELINING
+ optimization. */

-/* Now make connections to the hosts and do real callouts. The list of hosts
-is passed in as an argument. */
+ if (smtp_out != NULL && !disable_callout_flush) mac_smtp_fflush();

-for (host = host_list; host != NULL && !done; host = host->next)
-  {
-  smtp_inblock inblock;
-  smtp_outblock outblock;
-  int host_af;
-  int port = 25;
-  BOOL send_quit = TRUE;
-  uschar *active_hostname = smtp_active_hostname;
-  BOOL lmtp;
-  BOOL smtps;
-  BOOL esmtp;
-  BOOL suppress_tls = FALSE;
-  uschar *interface = NULL;  /* Outgoing interface to use; NULL => any */
-  uschar inbuffer[4096];
-  uschar outbuffer[1024];
-  uschar responsebuffer[4096];
-
-  clearflag(addr, af_verify_pmfail);  /* postmaster callout flag */
-  clearflag(addr, af_verify_nsfail);  /* null sender callout flag */
-
-  /* Skip this host if we don't have an IP address for it. */
-
-  if (host->address == NULL)
-    {
-    DEBUG(D_verify) debug_printf("no IP address for host name %s: skipping\n",
-      host->name);
-    continue;
-    }
+  /* Precompile some regex that are used to recognize parameters in response
+  to an EHLO command, if they aren't already compiled. */
+  #ifdef SUPPORT_TLS
+  if (regex_STARTTLS == NULL) regex_STARTTLS =
+    regex_must_compile(US"\\n250[\\s\\-]STARTTLS(\\s|\\n|$)", FALSE, TRUE);
+  #endif


- /* Check the overall callout timeout */
+ /* Now make connections to the hosts and do real callouts. The list of hosts
+ is passed in as an argument. */

-  if (time(NULL) - callout_start_time >= callout_overall)
+  for (host = host_list; host != NULL && !done; host = host->next)
     {
-    HDEBUG(D_verify) debug_printf("overall timeout for callout exceeded\n");
-    break;
-    }
+    smtp_inblock inblock;
+    smtp_outblock outblock;
+    int host_af;
+    int port = 25;
+    BOOL send_quit = TRUE;
+    uschar *active_hostname = smtp_active_hostname;
+    BOOL lmtp;
+    BOOL smtps;
+    BOOL esmtp;
+    BOOL suppress_tls = FALSE;
+    uschar *interface = NULL;  /* Outgoing interface to use; NULL => any */
+    uschar inbuffer[4096];
+    uschar outbuffer[1024];
+    uschar responsebuffer[4096];
+
+    clearflag(addr, af_verify_pmfail);  /* postmaster callout flag */
+    clearflag(addr, af_verify_nsfail);  /* null sender callout flag */
+
+    /* Skip this host if we don't have an IP address for it. */
+
+    if (host->address == NULL)
+      {
+      DEBUG(D_verify) debug_printf("no IP address for host name %s: skipping\n",
+        host->name);
+      continue;
+      }


-  /* Set IPv4 or IPv6 */
+    /* Check the overall callout timeout */


-  host_af = (Ustrchr(host->address, ':') == NULL)? AF_INET:AF_INET6;
+    if (time(NULL) - callout_start_time >= callout_overall)
+      {
+      HDEBUG(D_verify) debug_printf("overall timeout for callout exceeded\n");
+      break;
+      }


-  /* Expand and interpret the interface and port strings. The latter will not
-  be used if there is a host-specific port (e.g. from a manualroute router).
-  This has to be delayed till now, because they may expand differently for
-  different hosts. If there's a failure, log it, but carry on with the
-  defaults. */
+    /* Set IPv4 or IPv6 */


-  deliver_host = host->name;
-  deliver_host_address = host->address;
-  deliver_domain = addr->domain;
+    host_af = (Ustrchr(host->address, ':') == NULL)? AF_INET:AF_INET6;


-  if (!smtp_get_interface(tf->interface, host_af, addr, NULL, &interface,
-          US"callout") ||
-      !smtp_get_port(tf->port, addr, &port, US"callout"))
-    log_write(0, LOG_MAIN|LOG_PANIC, "<%s>: %s", addr->address,
-      addr->message);
+    /* Expand and interpret the interface and port strings. The latter will not
+    be used if there is a host-specific port (e.g. from a manualroute router).
+    This has to be delayed till now, because they may expand differently for
+    different hosts. If there's a failure, log it, but carry on with the
+    defaults. */


-  /* Set HELO string according to the protocol */
-  lmtp= Ustrcmp(tf->protocol, "lmtp") == 0;
-  smtps= Ustrcmp(tf->protocol, "smtps") == 0;
+    deliver_host = host->name;
+    deliver_host_address = host->address;
+    deliver_domain = addr->domain;


+    if (!smtp_get_interface(tf->interface, host_af, addr, NULL, &interface,
+            US"callout") ||
+        !smtp_get_port(tf->port, addr, &port, US"callout"))
+      log_write(0, LOG_MAIN|LOG_PANIC, "<%s>: %s", addr->address,
+        addr->message);


-  HDEBUG(D_verify) debug_printf("interface=%s port=%d\n", interface, port);
+    /* Set HELO string according to the protocol */
+    lmtp= Ustrcmp(tf->protocol, "lmtp") == 0;
+    smtps= Ustrcmp(tf->protocol, "smtps") == 0;


- /* Set up the buffer for reading SMTP response packets. */

-  inblock.buffer = inbuffer;
-  inblock.buffersize = sizeof(inbuffer);
-  inblock.ptr = inbuffer;
-  inblock.ptrend = inbuffer;
+    HDEBUG(D_verify) debug_printf("interface=%s port=%d\n", interface, port);


-  /* Set up the buffer for holding SMTP commands while pipelining */
+    /* Set up the buffer for reading SMTP response packets. */


-  outblock.buffer = outbuffer;
-  outblock.buffersize = sizeof(outbuffer);
-  outblock.ptr = outbuffer;
-  outblock.cmd_count = 0;
-  outblock.authenticating = FALSE;
+    inblock.buffer = inbuffer;
+    inblock.buffersize = sizeof(inbuffer);
+    inblock.ptr = inbuffer;
+    inblock.ptrend = inbuffer;


-  /* Reset the parameters of a TLS session */
-  tls_out.cipher = tls_out.peerdn = NULL;
+    /* Set up the buffer for holding SMTP commands while pipelining */


-  /* 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. */
+    outblock.buffer = outbuffer;
+    outblock.buffersize = sizeof(outbuffer);
+    outblock.ptr = outbuffer;
+    outblock.cmd_count = 0;
+    outblock.authenticating = FALSE;


-  tls_retry_connection:
+    /* Reset the parameters of a TLS session */
+    tls_out.cipher = tls_out.peerdn = NULL;


-  inblock.sock = outblock.sock =
-    smtp_connect(host, host_af, port, interface, callout_connect, TRUE, NULL);
-  /* reconsider DSCP here */
-  if (inblock.sock < 0)
-    {
-    addr->message = string_sprintf("could not connect to %s [%s]: %s",
-        host->name, host->address, strerror(errno));
-    deliver_host = deliver_host_address = NULL;
-    deliver_domain = save_deliver_domain;
-    continue;
-    }
+    /* 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. */


-  /* Expand the helo_data string to find the host name to use. */
+    tls_retry_connection:


-  if (tf->helo_data != NULL)
-    {
-    uschar *s = expand_string(tf->helo_data);
-    if (s == NULL)
-      log_write(0, LOG_MAIN|LOG_PANIC, "<%s>: failed to expand transport's "
-        "helo_data value for callout: %s", addr->address,
-        expand_string_message);
-    else active_hostname = s;
-    }
+    inblock.sock = outblock.sock =
+      smtp_connect(host, host_af, port, interface, callout_connect, TRUE);
+    /* reconsider DSCP here */
+    if (inblock.sock < 0)
+      {
+      addr->message = string_sprintf("could not connect to %s [%s]: %s",
+          host->name, host->address, strerror(errno));
+      deliver_host = deliver_host_address = NULL;
+      deliver_domain = save_deliver_domain;
+      continue;
+      }


-  deliver_host = deliver_host_address = NULL;
-  deliver_domain = save_deliver_domain;
+    /* Expand the helo_data string to find the host name to use. */


-  /* Wait for initial response, and send HELO. The smtp_write_command()
-  function leaves its command in big_buffer. This is used in error responses.
-  Initialize it in case the connection is rejected. */
+    if (tf->helo_data != NULL)
+      {
+      uschar *s = expand_string(tf->helo_data);
+      if (s == NULL)
+        log_write(0, LOG_MAIN|LOG_PANIC, "<%s>: failed to expand transport's "
+          "helo_data value for callout: %s", addr->address,
+          expand_string_message);
+      else active_hostname = s;
+      }


-  Ustrcpy(big_buffer, "initial connection");
+    deliver_host = deliver_host_address = NULL;
+    deliver_domain = save_deliver_domain;


-  /* Unless ssl-on-connect, wait for the initial greeting */
-  smtps_redo_greeting:
+    /* Wait for initial response, and send HELO. The smtp_write_command()
+    function leaves its command in big_buffer. This is used in error responses.
+    Initialize it in case the connection is rejected. */


-  #ifdef SUPPORT_TLS
-  if (!smtps || (smtps && tls_out.active >= 0))
-  #endif
-    if (!(done= smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer), '2', callout)))
-      goto RESPONSE_FAILED;
-  
-  /* Not worth checking greeting line for ESMTP support */
-  if (!(esmtp = verify_check_this_host(&(ob->hosts_avoid_esmtp), NULL,
-    host->name, host->address, NULL) != OK))
-    DEBUG(D_transport)
-      debug_printf("not sending EHLO (host matches hosts_avoid_esmtp)\n");
+    Ustrcpy(big_buffer, "initial connection");


-  tls_redo_helo:
+    /* Unless ssl-on-connect, wait for the initial greeting */
+    smtps_redo_greeting:


-  #ifdef SUPPORT_TLS
-  if (smtps  &&  tls_out.active < 0)    /* ssl-on-connect, first pass */
-    {
-    tls_offered = TRUE;
-    ob->tls_tempfail_tryclear = FALSE;
-    }
-    else                /* all other cases */
-  #endif
+    #ifdef SUPPORT_TLS
+    if (!smtps || (smtps && tls_out.active >= 0))
+    #endif
+      if (!(done= smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer), '2', callout)))
+        goto RESPONSE_FAILED;
+    
+    /* Not worth checking greeting line for ESMTP support */
+    if (!(esmtp = verify_check_this_host(&(ob->hosts_avoid_esmtp), NULL,
+      host->name, host->address, NULL) != OK))
+      DEBUG(D_transport)
+        debug_printf("not sending EHLO (host matches hosts_avoid_esmtp)\n");


-    { esmtp_retry:
+    tls_redo_helo:


-    if (!(done= smtp_write_command(&outblock, FALSE, "%s %s\r\n",
-      !esmtp? "HELO" : lmtp? "LHLO" : "EHLO", active_hostname) >= 0))
-      goto SEND_FAILED;
-    if (!smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer), '2', callout))
+    #ifdef SUPPORT_TLS
+    if (smtps  &&  tls_out.active < 0)    /* ssl-on-connect, first pass */
       {
-      if (errno != 0 || responsebuffer[0] == 0 || lmtp || !esmtp || tls_out.active >= 0)
-    {
-    done= FALSE;
-        goto RESPONSE_FAILED;
-    }
-      #ifdef SUPPORT_TLS
-      tls_offered = FALSE;
-      #endif
-      esmtp = FALSE;
-      goto esmtp_retry;            /* fallback to HELO */
+      tls_offered = TRUE;
+      ob->tls_tempfail_tryclear = FALSE;
       }
-
-    /* Set tls_offered if the response to EHLO specifies support for STARTTLS. */
-    #ifdef SUPPORT_TLS
-    tls_offered = esmtp && !suppress_tls &&  tls_out.active < 0  &&
-      pcre_exec(regex_STARTTLS, NULL, CS responsebuffer, Ustrlen(responsebuffer), 0,
-        PCRE_EOPT, NULL, 0) >= 0;
+      else                /* all other cases */
     #endif
-    }


-  /* If TLS is available on this connection attempt to
-  start up a TLS session, unless the host is in hosts_avoid_tls. If successful,
-  send another EHLO - the server may give a different answer in secure mode. We
-  use a separate buffer for reading the response to STARTTLS so that if it is
-  negative, the original EHLO data is available for subsequent analysis, should
-  the client not be required to use TLS. If the response is bad, copy the buffer
-  for error analysis. */
+      { esmtp_retry:


-  #ifdef SUPPORT_TLS
-  if (tls_offered &&
-      verify_check_this_host(&(ob->hosts_avoid_tls), NULL, host->name,
-      host->address, NULL) != OK)
-    {
-    uschar buffer2[4096];
-    if (  !smtps
-       && !(done= smtp_write_command(&outblock, FALSE, "STARTTLS\r\n") >= 0))
-      goto SEND_FAILED;
-
-    /* If there is an I/O error, transmission of this message is deferred. If
-    there is a temporary rejection of STARRTLS and tls_tempfail_tryclear is
-    false, we also defer. However, if there is a temporary rejection of STARTTLS
-    and tls_tempfail_tryclear is true, or if there is an outright rejection of
-    STARTTLS, we carry on. This means we will try to send the message in clear,
-    unless the host is in hosts_require_tls (tested below). */
-
-    if (!smtps && !smtp_read_response(&inblock, buffer2, sizeof(buffer2), '2',
-            ob->command_timeout))
-      {
-      if (errno != 0 || buffer2[0] == 0 ||
-          (buffer2[0] == '4' && !ob->tls_tempfail_tryclear))
-    {
-    Ustrncpy(responsebuffer, buffer2, sizeof(responsebuffer));
-    done= FALSE;
-    goto RESPONSE_FAILED;
-    }
+      if (!(done= smtp_write_command(&outblock, FALSE, "%s %s\r\n",
+        !esmtp? "HELO" : lmtp? "LHLO" : "EHLO", active_hostname) >= 0))
+        goto SEND_FAILED;
+      if (!smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer), '2', callout))
+        {
+        if (errno != 0 || responsebuffer[0] == 0 || lmtp || !esmtp || tls_out.active >= 0)
+      {
+      done= FALSE;
+          goto RESPONSE_FAILED;
+      }
+        #ifdef SUPPORT_TLS
+        tls_offered = FALSE;
+        #endif
+        esmtp = FALSE;
+        goto esmtp_retry;            /* fallback to HELO */
+        }
+
+      /* Set tls_offered if the response to EHLO specifies support for STARTTLS. */
+      #ifdef SUPPORT_TLS
+      tls_offered = esmtp && !suppress_tls &&  tls_out.active < 0  &&
+        pcre_exec(regex_STARTTLS, NULL, CS responsebuffer, Ustrlen(responsebuffer), 0,
+          PCRE_EOPT, NULL, 0) >= 0;
+      #endif
       }


-     /* STARTTLS accepted or ssl-on-connect: try to negotiate a TLS session. */
-    else
+    /* If TLS is available on this connection attempt to
+    start up a TLS session, unless the host is in hosts_avoid_tls. If successful,
+    send another EHLO - the server may give a different answer in secure mode. We
+    use a separate buffer for reading the response to STARTTLS so that if it is
+    negative, the original EHLO data is available for subsequent analysis, should
+    the client not be required to use TLS. If the response is bad, copy the buffer
+    for error analysis. */
+
+    #ifdef SUPPORT_TLS
+    if (tls_offered &&
+        verify_check_this_host(&(ob->hosts_avoid_tls), NULL, host->name,
+        host->address, NULL) != OK)
       {
-      int rc = tls_client_start(inblock.sock, host, addr,
-     NULL,                    /* No DH param */
-     ob->tls_certificate, ob->tls_privatekey,
-     ob->tls_sni,
-     ob->tls_verify_certificates, ob->tls_crl,
-     ob->tls_require_ciphers,
-     ob->gnutls_require_mac, ob->gnutls_require_kx, ob->gnutls_require_proto,
-     callout);
-
-      /* TLS negotiation failed; give an error.  Try in clear on a new connection,
-         if the options permit it for this host. */
-      if (rc != OK)
+      uschar buffer2[4096];
+      if (  !smtps
+         && !(done= smtp_write_command(&outblock, FALSE, "STARTTLS\r\n") >= 0))
+        goto SEND_FAILED;
+
+      /* If there is an I/O error, transmission of this message is deferred. If
+      there is a temporary rejection of STARRTLS and tls_tempfail_tryclear is
+      false, we also defer. However, if there is a temporary rejection of STARTTLS
+      and tls_tempfail_tryclear is true, or if there is an outright rejection of
+      STARTTLS, we carry on. This means we will try to send the message in clear,
+      unless the host is in hosts_require_tls (tested below). */
+
+      if (!smtps && !smtp_read_response(&inblock, buffer2, sizeof(buffer2), '2',
+              ob->command_timeout))
         {
-    if (rc == DEFER && ob->tls_tempfail_tryclear && !smtps &&
-       verify_check_this_host(&(ob->hosts_require_tls), NULL, host->name,
-         host->address, NULL) != OK)
-      {
-          (void)close(inblock.sock);
-      log_write(0, LOG_MAIN, "TLS session failure: delivering unencrypted "
-        "to %s [%s] (not in hosts_require_tls)", host->name, host->address);
-      suppress_tls = TRUE;
-      goto tls_retry_connection;
-      }
-    /*save_errno = ERRNO_TLSFAILURE;*/
-    /*message = US"failure while setting up TLS session";*/
-    send_quit = FALSE;
-    done= FALSE;
-    goto TLS_FAILED;
-    }
-
-      /* TLS session is set up.  Copy info for logging. */
-      addr->cipher = tls_out.cipher;
-      addr->peerdn = tls_out.peerdn;
-
-      /* For SMTPS we need to wait for the initial OK response, then do HELO. */
-      if (smtps)
-     goto smtps_redo_greeting;
-
-      /* For STARTTLS we need to redo EHLO */
-      goto tls_redo_helo;
-      }
-    }
+        if (errno != 0 || buffer2[0] == 0 ||
+            (buffer2[0] == '4' && !ob->tls_tempfail_tryclear))
+      {
+      Ustrncpy(responsebuffer, buffer2, sizeof(responsebuffer));
+      done= FALSE;
+      goto RESPONSE_FAILED;
+      }
+        }


-  /* If the host is required to use a secure channel, ensure that we have one. */
-  if (tls_out.active < 0)
-    if (verify_check_this_host(&(ob->hosts_require_tls), NULL, host->name,
-        host->address, NULL) == OK)
-      {
-      /*save_errno = ERRNO_TLSREQUIRED;*/
-      log_write(0, LOG_MAIN, "a TLS session is required for %s [%s], but %s",
-        host->name, host->address,
-    tls_offered? "an attempt to start TLS failed" : "the server did not offer TLS support");
-      done= FALSE;
-      goto TLS_FAILED;
+       /* STARTTLS accepted or ssl-on-connect: try to negotiate a TLS session. */
+      else
+        {
+        int rc = tls_client_start(inblock.sock, host, addr,
+       NULL,                    /* No DH param */
+       ob->tls_certificate, ob->tls_privatekey,
+       ob->tls_sni,
+       ob->tls_verify_certificates, ob->tls_crl,
+       ob->tls_require_ciphers,
+       ob->gnutls_require_mac, ob->gnutls_require_kx, ob->gnutls_require_proto,
+       callout);
+
+        /* TLS negotiation failed; give an error.  Try in clear on a new connection,
+           if the options permit it for this host. */
+        if (rc != OK)
+          {
+      if (rc == DEFER && ob->tls_tempfail_tryclear && !smtps &&
+         verify_check_this_host(&(ob->hosts_require_tls), NULL, host->name,
+           host->address, NULL) != OK)
+        {
+            (void)close(inblock.sock);
+        log_write(0, LOG_MAIN, "TLS session failure: delivering unencrypted "
+          "to %s [%s] (not in hosts_require_tls)", host->name, host->address);
+        suppress_tls = TRUE;
+        goto tls_retry_connection;
+        }
+      /*save_errno = ERRNO_TLSFAILURE;*/
+      /*message = US"failure while setting up TLS session";*/
+      send_quit = FALSE;
+      done= FALSE;
+      goto TLS_FAILED;
+      }
+
+        /* TLS session is set up.  Copy info for logging. */
+        addr->cipher = tls_out.cipher;
+        addr->peerdn = tls_out.peerdn;
+
+        /* For SMTPS we need to wait for the initial OK response, then do HELO. */
+        if (smtps)
+       goto smtps_redo_greeting;
+
+        /* For STARTTLS we need to redo EHLO */
+        goto tls_redo_helo;
+        }
       }


-  #endif /*SUPPORT_TLS*/
+    /* If the host is required to use a secure channel, ensure that we have one. */
+    if (tls_out.active < 0)
+      if (verify_check_this_host(&(ob->hosts_require_tls), NULL, host->name,
+          host->address, NULL) == OK)
+        {
+        /*save_errno = ERRNO_TLSREQUIRED;*/
+        log_write(0, LOG_MAIN, "a TLS session is required for %s [%s], but %s",
+          host->name, host->address,
+      tls_offered? "an attempt to start TLS failed" : "the server did not offer TLS support");
+        done= FALSE;
+        goto TLS_FAILED;
+        }


-  done = TRUE; /* so far so good; have response to HELO */
+    #endif /*SUPPORT_TLS*/


-  /*XXX the EHLO response would be analyzed here for IGNOREQUOTA, SIZE, PIPELINING, AUTH */
-  /* If we haven't authenticated, but are required to, give up. */
+    done = TRUE; /* so far so good; have response to HELO */


-  /*XXX "filter command specified for this transport" ??? */
-  /* for now, transport_filter by cutthrough-delivery is not supported */
-  /* Need proper integration with the proper transport mechanism. */
+    /*XXX the EHLO response would be analyzed here for IGNOREQUOTA, SIZE, PIPELINING, AUTH */
+    /* If we haven't authenticated, but are required to, give up. */


+    /*XXX "filter command specified for this transport" ??? */
+    /* for now, transport_filter by cutthrough-delivery is not supported */
+    /* Need proper integration with the proper transport mechanism. */


- SEND_FAILED:
- RESPONSE_FAILED:
- TLS_FAILED:
- ;
- /* Clear down of the TLS, SMTP and TCP layers on error is handled below. */

+    SEND_FAILED:
+    RESPONSE_FAILED:
+    TLS_FAILED:
+    ;
+    /* Clear down of the TLS, SMTP and TCP layers on error is handled below.  */


- /* Failure to accept HELO is cached; this blocks the whole domain for all
- senders. I/O errors and defer responses are not cached. */

-  if (!done)
-    {
-    *failure_ptr = US"mail";     /* At or before MAIL */
-    if (errno == 0 && responsebuffer[0] == '5')
+    /* Failure to accept HELO is cached; this blocks the whole domain for all
+    senders. I/O errors and defer responses are not cached. */
+
+    if (!done)
       {
-      setflag(addr, af_verify_nsfail);
-      new_domain_record.result = ccache_reject;
+      *failure_ptr = US"mail";     /* At or before MAIL */
+      if (errno == 0 && responsebuffer[0] == '5')
+        {
+        setflag(addr, af_verify_nsfail);
+        new_domain_record.result = ccache_reject;
+        }
       }
-    }


-  /* Send the MAIL command */
+    /* Send the MAIL command */


-  else done =
-    smtp_write_command(&outblock, FALSE, "MAIL FROM:<%s>\r\n",
-      from_address) >= 0 &&
-    smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer),
-      '2', callout);
+    else done =
+      smtp_write_command(&outblock, FALSE, "MAIL FROM:<%s>\r\n",
+        from_address) >= 0 &&
+      smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer),
+        '2', callout);


-  /* If the host does not accept MAIL FROM:<>, arrange to cache this
-  information, but again, don't record anything for an I/O error or a defer. Do
-  not cache rejections of MAIL when a non-empty sender has been used, because
-  that blocks the whole domain for all senders. */
+    /* If the host does not accept MAIL FROM:<>, arrange to cache this
+    information, but again, don't record anything for an I/O error or a defer. Do
+    not cache rejections of MAIL when a non-empty sender has been used, because
+    that blocks the whole domain for all senders. */


-  if (!done)
-    {
-    *failure_ptr = US"mail";     /* At or before MAIL */
-    if (errno == 0 && responsebuffer[0] == '5')
+    if (!done)
       {
-      setflag(addr, af_verify_nsfail);
-      if (from_address[0] == 0)
-        new_domain_record.result = ccache_reject_mfnull;
+      *failure_ptr = US"mail";     /* At or before MAIL */
+      if (errno == 0 && responsebuffer[0] == '5')
+        {
+        setflag(addr, af_verify_nsfail);
+        if (from_address[0] == 0)
+          new_domain_record.result = ccache_reject_mfnull;
+        }
       }
-    }


-  /* Otherwise, proceed to check a "random" address (if required), then the
-  given address, and the postmaster address (if required). Between each check,
-  issue RSET, because some servers accept only one recipient after MAIL
-  FROM:<>.
+    /* Otherwise, proceed to check a "random" address (if required), then the
+    given address, and the postmaster address (if required). Between each check,
+    issue RSET, because some servers accept only one recipient after MAIL
+    FROM:<>.


-  Before doing this, set the result in the domain cache record to "accept",
-  unless its previous value was ccache_reject_mfnull. In that case, the domain
-  rejects MAIL FROM:<> and we want to continue to remember that. When that is
-  the case, we have got here only in the case of a recipient verification with
-  a non-null sender. */
+    Before doing this, set the result in the domain cache record to "accept",
+    unless its previous value was ccache_reject_mfnull. In that case, the domain
+    rejects MAIL FROM:<> and we want to continue to remember that. When that is
+    the case, we have got here only in the case of a recipient verification with
+    a non-null sender. */


-  else
-    {
-    new_domain_record.result =
-      (old_domain_cache_result == ccache_reject_mfnull)?
-        ccache_reject_mfnull: ccache_accept;
+    else
+      {
+      new_domain_record.result =
+        (old_domain_cache_result == ccache_reject_mfnull)?
+          ccache_reject_mfnull: ccache_accept;


-    /* Do the random local part check first */
+      /* Do the random local part check first */


-    if (random_local_part != NULL)
-      {
-      uschar randombuffer[1024];
-      BOOL random_ok =
-        smtp_write_command(&outblock, FALSE,
-          "RCPT TO:<%.1000s@%.1000s>\r\n", random_local_part,
-          addr->domain) >= 0 &&
-        smtp_read_response(&inblock, randombuffer,
-          sizeof(randombuffer), '2', callout);
+      if (random_local_part != NULL)
+        {
+        uschar randombuffer[1024];
+        BOOL random_ok =
+          smtp_write_command(&outblock, FALSE,
+            "RCPT TO:<%.1000s@%.1000s>\r\n", random_local_part,
+            addr->domain) >= 0 &&
+          smtp_read_response(&inblock, randombuffer,
+            sizeof(randombuffer), '2', callout);


-      /* Remember when we last did a random test */
+        /* Remember when we last did a random test */


-      new_domain_record.random_stamp = time(NULL);
+        new_domain_record.random_stamp = time(NULL);


-      /* If accepted, we aren't going to do any further tests below. */
+        /* If accepted, we aren't going to do any further tests below. */


-      if (random_ok)
-        {
-        new_domain_record.random_result = ccache_accept;
-        }
+        if (random_ok)
+          {
+          new_domain_record.random_result = ccache_accept;
+          }


-      /* 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. */
+        /* 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. */


-      else if (errno == 0)
+        else if (errno == 0)
+          {
+          if (randombuffer[0] == '5')
+            new_domain_record.random_result = ccache_reject;
+
+          done =
+            smtp_write_command(&outblock, FALSE, "RSET\r\n") >= 0 &&
+            smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer),
+              '2', callout) &&
+
+            smtp_write_command(&outblock, FALSE, "MAIL FROM:<%s>\r\n",
+              from_address) >= 0 &&
+            smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer),
+              '2', callout);
+          }
+        else done = FALSE;    /* Some timeout/connection problem */
+        }                     /* Random check */
+
+      /* 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. */
+
+      if (new_domain_record.random_result != ccache_accept && done)
         {
-        if (randombuffer[0] == '5')
-          new_domain_record.random_result = ccache_reject;
+        /* Get the rcpt_include_affixes flag from the transport if there is one,
+        but assume FALSE if there is not. */


         done =
-          smtp_write_command(&outblock, FALSE, "RSET\r\n") >= 0 &&
-          smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer),
-            '2', callout) &&
-
-          smtp_write_command(&outblock, FALSE, "MAIL FROM:<%s>\r\n",
-            from_address) >= 0 &&
+          smtp_write_command(&outblock, FALSE, "RCPT TO:<%.1000s>\r\n",
+            transport_rcpt_address(addr,
+              (addr->transport == NULL)? FALSE :
+               addr->transport->rcpt_include_affixes)) >= 0 &&
           smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer),
             '2', callout);
-        }
-      else done = FALSE;    /* Some timeout/connection problem */
-      }                     /* Random check */


-    /* 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. */
-
-    if (new_domain_record.random_result != ccache_accept && done)
-      {
-      /* Get the rcpt_include_affixes flag from the transport if there is one,
-      but assume FALSE if there is not. */
-
-      done =
-        smtp_write_command(&outblock, FALSE, "RCPT TO:<%.1000s>\r\n",
-          transport_rcpt_address(addr,
-            (addr->transport == NULL)? FALSE :
-             addr->transport->rcpt_include_affixes)) >= 0 &&
-        smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer),
-          '2', callout);
-
-      if (done)
-        new_address_record.result = ccache_accept;
-      else if (errno == 0 && responsebuffer[0] == '5')
-        {
-        *failure_ptr = US"recipient";
-        new_address_record.result = ccache_reject;
-        }
+        if (done)
+          new_address_record.result = ccache_accept;
+        else if (errno == 0 && responsebuffer[0] == '5')
+          {
+          *failure_ptr = US"recipient";
+          new_address_record.result = ccache_reject;
+          }


-      /* Do postmaster check if requested; if a full check is required, we
-      check for RCPT TO:<postmaster> (no domain) in accordance with RFC 821. */
+        /* Do postmaster check if requested; if a full check is required, we
+        check for RCPT TO:<postmaster> (no domain) in accordance with RFC 821. */


-      if (done && pm_mailfrom != NULL)
-        {
-        /*XXX not suitable for cutthrough - sequencing problems */
-    cutthrough_delivery= FALSE;
-    HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of postmaster verify\n");
+        if (done && pm_mailfrom != NULL)
+          {
+          /*XXX not suitable for cutthrough - sequencing problems */
+      cutthrough_delivery= FALSE;
+      HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of postmaster verify\n");


-        done =
-          smtp_write_command(&outblock, FALSE, "RSET\r\n") >= 0 &&
-          smtp_read_response(&inblock, responsebuffer,
-            sizeof(responsebuffer), '2', callout) &&
+          done =
+            smtp_write_command(&outblock, FALSE, "RSET\r\n") >= 0 &&
+            smtp_read_response(&inblock, responsebuffer,
+              sizeof(responsebuffer), '2', callout) &&


-          smtp_write_command(&outblock, FALSE,
-            "MAIL FROM:<%s>\r\n", pm_mailfrom) >= 0 &&
-          smtp_read_response(&inblock, responsebuffer,
-            sizeof(responsebuffer), '2', callout) &&
+            smtp_write_command(&outblock, FALSE,
+              "MAIL FROM:<%s>\r\n", pm_mailfrom) >= 0 &&
+            smtp_read_response(&inblock, responsebuffer,
+              sizeof(responsebuffer), '2', callout) &&


-          /* First try using the current domain */
+            /* First try using the current domain */


-          ((
-          smtp_write_command(&outblock, FALSE,
-            "RCPT TO:<postmaster@%.1000s>\r\n", addr->domain) >= 0 &&
-          smtp_read_response(&inblock, responsebuffer,
-            sizeof(responsebuffer), '2', callout)
-          )
+            ((
+            smtp_write_command(&outblock, FALSE,
+              "RCPT TO:<postmaster@%.1000s>\r\n", addr->domain) >= 0 &&
+            smtp_read_response(&inblock, responsebuffer,
+              sizeof(responsebuffer), '2', callout)
+            )


-          ||
+            ||


-          /* If that doesn't work, and a full check is requested,
-          try without the domain. */
+            /* If that doesn't work, and a full check is requested,
+            try without the domain. */


-          (
-          (options & vopt_callout_fullpm) != 0 &&
-          smtp_write_command(&outblock, FALSE,
-            "RCPT TO:<postmaster>\r\n") >= 0 &&
-          smtp_read_response(&inblock, responsebuffer,
-            sizeof(responsebuffer), '2', callout)
-          ));
+            (
+            (options & vopt_callout_fullpm) != 0 &&
+            smtp_write_command(&outblock, FALSE,
+              "RCPT TO:<postmaster>\r\n") >= 0 &&
+            smtp_read_response(&inblock, responsebuffer,
+              sizeof(responsebuffer), '2', callout)
+            ));


-        /* Sort out the cache record */
+          /* Sort out the cache record */


-        new_domain_record.postmaster_stamp = time(NULL);
+          new_domain_record.postmaster_stamp = time(NULL);


-        if (done)
-          new_domain_record.postmaster_result = ccache_accept;
-        else if (errno == 0 && responsebuffer[0] == '5')
-          {
-          *failure_ptr = US"postmaster";
-          setflag(addr, af_verify_pmfail);
-          new_domain_record.postmaster_result = ccache_reject;
+          if (done)
+            new_domain_record.postmaster_result = ccache_accept;
+          else if (errno == 0 && responsebuffer[0] == '5')
+            {
+            *failure_ptr = US"postmaster";
+            setflag(addr, af_verify_pmfail);
+            new_domain_record.postmaster_result = ccache_reject;
+            }
           }
-        }
-      }           /* Random not accepted */
-    }             /* MAIL FROM: accepted */
+        }           /* Random not accepted */
+      }             /* MAIL FROM: accepted */


-  /* For any failure of the main check, other than a negative response, we just
-  close the connection and carry on. We can identify a negative response by the
-  fact that errno is zero. For I/O errors it will be non-zero
+    /* For any failure of the main check, other than a negative response, we just
+    close the connection and carry on. We can identify a negative response by the
+    fact that errno is zero. For I/O errors it will be non-zero


-  Set up different error texts for logging and for sending back to the caller
-  as an SMTP response. Log in all cases, using a one-line format. For sender
-  callouts, give a full response to the caller, but for recipient callouts,
-  don't give the IP address because this may be an internal host whose identity
-  is not to be widely broadcast. */
+    Set up different error texts for logging and for sending back to the caller
+    as an SMTP response. Log in all cases, using a one-line format. For sender
+    callouts, give a full response to the caller, but for recipient callouts,
+    don't give the IP address because this may be an internal host whose identity
+    is not to be widely broadcast. */


-  if (!done)
-    {
-    if (errno == ETIMEDOUT)
+    if (!done)
       {
-      HDEBUG(D_verify) debug_printf("SMTP timeout\n");
-      send_quit = FALSE;
-      }
-    else if (errno == 0)
-      {
-      if (*responsebuffer == 0) Ustrcpy(responsebuffer, US"connection dropped");
+      if (errno == ETIMEDOUT)
+        {
+        HDEBUG(D_verify) debug_printf("SMTP timeout\n");
+        send_quit = FALSE;
+        }
+      else if (errno == 0)
+        {
+        if (*responsebuffer == 0) Ustrcpy(responsebuffer, US"connection dropped");


-      addr->message =
-        string_sprintf("response to \"%s\" from %s [%s] was: %s",
-          big_buffer, host->name, host->address,
-          string_printing(responsebuffer));
+        addr->message =
+          string_sprintf("response to \"%s\" from %s [%s] was: %s",
+            big_buffer, host->name, host->address,
+            string_printing(responsebuffer));


-      addr->user_message = is_recipient?
-        string_sprintf("Callout verification failed:\n%s", responsebuffer)
-        :
-        string_sprintf("Called:   %s\nSent:     %s\nResponse: %s",
-          host->address, big_buffer, responsebuffer);
+        addr->user_message = is_recipient?
+          string_sprintf("Callout verification failed:\n%s", responsebuffer)
+          :
+          string_sprintf("Called:   %s\nSent:     %s\nResponse: %s",
+            host->address, big_buffer, responsebuffer);


-      /* Hard rejection ends the process */
+        /* Hard rejection ends the process */


-      if (responsebuffer[0] == '5')   /* Address rejected */
-        {
-        yield = FAIL;
-        done = TRUE;
+        if (responsebuffer[0] == '5')   /* Address rejected */
+          {
+          yield = FAIL;
+          done = TRUE;
+          }
         }
       }
-    }


-  /* End the SMTP conversation and close the connection. */
-
-  /* Cutthrough - on a successfull connect and recipient-verify with use-sender
-  and we have no cutthrough conn so far
-  here is where we want to leave the conn open */
-  if (  cutthrough_delivery
-     && done
-     && yield == OK
-     && (options & (vopt_callout_recipsender|vopt_callout_recippmaster)) == vopt_callout_recipsender
-     && !random_local_part
-     && !pm_mailfrom
-     && cutthrough_fd < 0
-     )
-    {
-    cutthrough_fd= outblock.sock;    /* We assume no buffer in use in the outblock */
-    cutthrough_addr = *addr;        /* Save the address_item for later logging */
-    cutthrough_addr.host_used = store_get(sizeof(host_item));
-    cutthrough_addr.host_used->name =    host->name;
-    cutthrough_addr.host_used->address = host->address;
-    cutthrough_addr.host_used->port =    port;
-    if (addr->parent)
-      *(cutthrough_addr.parent = store_get(sizeof(address_item)))= *addr->parent;
-    ctblock.buffer = ctbuffer;
-    ctblock.buffersize = sizeof(ctbuffer);
-    ctblock.ptr = ctbuffer;
-    /* ctblock.cmd_count = 0; ctblock.authenticating = FALSE; */
-    ctblock.sock = cutthrough_fd;
-    }
-  else
-    {
-    if (options & vopt_callout_recipsender)
-      cancel_cutthrough_connection();    /* Ensure no cutthrough on multiple address verifies */
-    if (send_quit) (void)smtp_write_command(&outblock, FALSE, "QUIT\r\n");
+    /* End the SMTP conversation and close the connection. */
+
+    /* Cutthrough - on a successfull connect and recipient-verify with use-sender
+    and we have no cutthrough conn so far
+    here is where we want to leave the conn open */
+    if (  cutthrough_delivery
+       && done
+       && yield == OK
+       && (options & (vopt_callout_recipsender|vopt_callout_recippmaster)) == vopt_callout_recipsender
+       && !random_local_part
+       && !pm_mailfrom
+       && cutthrough_fd < 0
+       )
+      {
+      cutthrough_fd= outblock.sock;    /* We assume no buffer in use in the outblock */
+      cutthrough_addr = *addr;        /* Save the address_item for later logging */
+      cutthrough_addr.host_used = store_get(sizeof(host_item));
+      cutthrough_addr.host_used->name =    host->name;
+      cutthrough_addr.host_used->address = host->address;
+      cutthrough_addr.host_used->port =    port;
+      if (addr->parent)
+        *(cutthrough_addr.parent = store_get(sizeof(address_item)))= *addr->parent;
+      ctblock.buffer = ctbuffer;
+      ctblock.buffersize = sizeof(ctbuffer);
+      ctblock.ptr = ctbuffer;
+      /* ctblock.cmd_count = 0; ctblock.authenticating = FALSE; */
+      ctblock.sock = cutthrough_fd;
+      }
+    else
+      {
+      if (options & vopt_callout_recipsender)
+        cancel_cutthrough_connection();    /* Ensure no cutthrough on multiple address verifies */
+      if (send_quit) (void)smtp_write_command(&outblock, FALSE, "QUIT\r\n");


-    #ifdef SUPPORT_TLS
-    tls_close(FALSE, TRUE);
-    #endif
-    (void)close(inblock.sock);
-    }
+      #ifdef SUPPORT_TLS
+      tls_close(FALSE, TRUE);
+      #endif
+      (void)close(inblock.sock);
+      }


-  }    /* Loop through all hosts, while !done */
+    }    /* Loop through all hosts, while !done */
+  }


/* If we get here with done == TRUE, a successful callout happened, and yield
will be set OK or FAIL according to the response to the RCPT command.
diff --git a/test/confs/0538 b/test/confs/0538
index 7f89ccc..5865e31 100644
--- a/test/confs/0538
+++ b/test/confs/0538
@@ -38,6 +38,13 @@ r1:
route_list = * "<= 127.0.0.1:PORT_S"
self = send
verify_only
+ transport = t1
+
+
+begin transports
+
+t1:
+ driver = smtp


# End
diff --git a/test/log/0527 b/test/log/0527
index 3da4433..702dbb7 100644
--- a/test/log/0527
+++ b/test/log/0527
@@ -1,2 +1,2 @@
-1999-03-02 09:44:33 U=CALLER sender verify fail for <unknown@???>: response to "RCPT TO:<unknown@???>" from 127.0.0.1 [127.0.0.1] was: 550 unrouteable address
-1999-03-02 09:44:33 U=CALLER F=<unknown@???> rejected RCPT <unknown@???>: Sender verify failed
+1999-03-02 09:44:33 U=CALLER sender verify defer for <unknown@???>: Could not complete sender verify callout
+1999-03-02 09:44:33 U=CALLER F=<unknown@???> temporarily rejected RCPT <unknown@???>: Could not complete sender verify callout
diff --git a/test/rejectlog/0527 b/test/rejectlog/0527
index 3da4433..702dbb7 100644
--- a/test/rejectlog/0527
+++ b/test/rejectlog/0527
@@ -1,2 +1,2 @@
-1999-03-02 09:44:33 U=CALLER sender verify fail for <unknown@???>: response to "RCPT TO:<unknown@???>" from 127.0.0.1 [127.0.0.1] was: 550 unrouteable address
-1999-03-02 09:44:33 U=CALLER F=<unknown@???> rejected RCPT <unknown@???>: Sender verify failed
+1999-03-02 09:44:33 U=CALLER sender verify defer for <unknown@???>: Could not complete sender verify callout
+1999-03-02 09:44:33 U=CALLER F=<unknown@???> temporarily rejected RCPT <unknown@???>: Could not complete sender verify callout
diff --git a/test/scripts/0000-Basic/0527 b/test/scripts/0000-Basic/0527
index e65032b..9c880d6 100644
--- a/test/scripts/0000-Basic/0527
+++ b/test/scripts/0000-Basic/0527
@@ -1,17 +1,6 @@
# callout with no transport
need_ipv4
#
-server PORT_S
-220 Welcome
-HELO
-250 Hi
-MAIL FROM
-250 OK
-RCPT TO
-550 unrouteable address
-QUIT
-221 Bye
-****
exim -bs
mail from:<unknown@???>
rcpt to:<unknown@???>
diff --git a/test/scripts/0000-Basic/0538 b/test/scripts/0000-Basic/0538
index c464f3b..ccabcfb 100644
--- a/test/scripts/0000-Basic/0538
+++ b/test/scripts/0000-Basic/0538
@@ -4,7 +4,7 @@ need_ipv4
# Do a sender address verify that rejects MAIL FROM:<>
server PORT_S
220 Welcome
-HELO
+EHLO
250 Hi
MAIL FROM
550 I'm misconfigured
@@ -18,7 +18,7 @@ quit
# Now do a recipient verify for the same domain, with use_sender
server PORT_S
220 Welcome
-HELO
+EHLO
250 Hi
MAIL FROM
250 OK
diff --git a/test/stderr/0443 b/test/stderr/0443
index 6cf1dcf..99dc1c6 100644
--- a/test/stderr/0443
+++ b/test/stderr/0443
@@ -16,9 +16,8 @@
>>> Attempting full verification using callout
>>> callout cache: no domain record found
>>> callout cache: no address record found

->>> interface=NULL port=25
->>> Connecting to ten-1.test.ex [V4NET.0.0.1]:25 ... failed: Network Error
+>>> cannot callout via null transport
>>> ----------- end verify ------------
>>> accept: condition test deferred in ACL "rcpt"

-LOG: H=[V4NET.0.0.1] sender verify defer for <x@???>: could not connect to ten-1.test.ex [V4NET.0.0.1]: Network Error
+LOG: H=[V4NET.0.0.1] sender verify defer for <x@???>: Could not complete sender verify callout
 LOG: H=[V4NET.0.0.1] F=<x@???> temporarily rejected RCPT x@y: Could not complete sender verify callout
diff --git a/test/stderr/0473 b/test/stderr/0473
index a29575e..090335d 100644
--- a/test/stderr/0473
+++ b/test/stderr/0473
@@ -14,7 +14,7 @@ callout cache: no address record found
 interface=NULL port=1224
 Connecting to 127.0.0.1 [127.0.0.1]:1224 ... connected
   SMTP<< 220 Server ready
-  SMTP>> HELO the.local.host.name
+  SMTP>> EHLO the.local.host.name
   SMTP<< 250 OK
   SMTP>> MAIL FROM:<>
   SMTP<< 250 OK
diff --git a/test/stdout/0473 b/test/stdout/0473
index 00112d3..9fff9a6 100644
--- a/test/stdout/0473
+++ b/test/stdout/0473
@@ -123,7 +123,7 @@
 Listening on port 1224 ... 
 Connection request from [127.0.0.1]
 220 Server ready
-HELO the.local.host.name
+EHLO the.local.host.name
 250 OK
 MAIL FROM:<s1@???>
 250 OK
@@ -135,7 +135,7 @@ Expected EOF read from client
 Listening on port 1224 ... 
 Connection request from [127.0.0.1]
 220 Server ready
-HELO the.local.host.name
+EHLO the.local.host.name
 250 OK
 MAIL FROM:<s2@???>
 250 OK
@@ -147,7 +147,7 @@ Expected EOF read from client
 Listening on port 1224 ... 
 Connection request from [127.0.0.1]
 220 Server ready
-HELO the.local.host.name
+EHLO the.local.host.name
 250 OK
 MAIL FROM:<s3@???>
 550 NOTOK
@@ -157,7 +157,7 @@ End of script
 Listening on port 1224 ... 
 Connection request from [127.0.0.1]
 220 Server ready
-HELO the.local.host.name
+EHLO the.local.host.name
 250 OK
 MAIL FROM:<>
 250 OK
@@ -169,7 +169,7 @@ End of script
 Listening on port 1224 ... 
 Connection request from [127.0.0.1]
 220 Server ready
-HELO the.local.host.name
+EHLO the.local.host.name
 250 OK
 MAIL FROM:<postmaster@???>
 250 OK
@@ -181,7 +181,7 @@ End of script
 Listening on port 1224 ... 
 Connection request from [127.0.0.1]
 220 server ready
-HELO the.local.host.name
+EHLO the.local.host.name
 250 OK
 MAIL FROM:<x9@???>
 250 OK
@@ -193,7 +193,7 @@ End of script
 Listening on port 1224 ... 
 Connection request from [127.0.0.1]
 220 server ready
-HELO the.local.host.name
+EHLO the.local.host.name
 250 OK
 MAIL FROM:<>
 250 OK
@@ -205,7 +205,7 @@ End of script
 Listening on port 1224 ... 
 Connection request from [127.0.0.1]
 220 Server ready
-HELO the.local.host.name
+EHLO the.local.host.name
 250 OK
 MAIL FROM:<postmaster@???>
 250 OK
@@ -217,7 +217,7 @@ End of script
 Listening on port 1224 ... 
 Connection request from [127.0.0.1]
 220 Server ready
-HELO the.local.host.name
+EHLO the.local.host.name
 250 OK
 MAIL FROM:<>
 250 OK
diff --git a/test/stdout/0527 b/test/stdout/0527
index 180c02a..98cca17 100644
--- a/test/stdout/0527
+++ b/test/stdout/0527
@@ -1,22 +1,4 @@
 220 myhost.test.ex ESMTP Exim x.yz Tue, 2 Mar 1999 09:44:33 +0000
 250 OK
-550-Verification failed for <unknown@???>
-550-Called:   127.0.0.1
-550-Sent:     RCPT TO:<unknown@???>
-550-Response: 550 unrouteable address
-550 Sender verify failed
+451 Could not complete sender verify callout
 221 myhost.test.ex closing connection
-
-******** SERVER ********
-Listening on port 1224 ... 
-Connection request from [127.0.0.1]
-220 Welcome
-HELO myhost.test.ex
-250 Hi
-MAIL FROM:<>
-250 OK
-RCPT TO:<unknown@???>
-550 unrouteable address
-QUIT
-221 Bye
-End of script
diff --git a/test/stdout/0538 b/test/stdout/0538
index c7bd592..7a19058 100644
--- a/test/stdout/0538
+++ b/test/stdout/0538
@@ -29,7 +29,7 @@
 Listening on port 1224 ... 
 Connection request from [127.0.0.1]
 220 Welcome
-HELO myhost.test.ex
+EHLO myhost.test.ex
 250 Hi
 MAIL FROM:<>
 550 I'm misconfigured
@@ -39,7 +39,7 @@ End of script
 Listening on port 1224 ... 
 Connection request from [127.0.0.1]
 220 Welcome
-HELO myhost.test.ex
+EHLO myhost.test.ex
 250 Hi
 MAIL FROM:<userx@???>
 250 OK