if (smtp_out != NULL && !disable_callout_flush) mac_smtp_fflush();
- /* 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
-
/* Now make connections to the hosts and do real callouts. The list of hosts
is passed in as an argument. */
tls_retry_connection:
inblock.sock = outblock.sock =
- smtp_connect(host, host_af, port, interface, callout_connect, TRUE);
+ smtp_connect(host, host_af, port, interface, callout_connect, TRUE, NULL);
/* reconsider DSCP here */
if (inblock.sock < 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;
- }
+ if (errno != 0 || responsebuffer[0] == 0 || lmtp || !esmtp || tls_out.active >= 0)
+ {
+ done= FALSE;
+ goto RESPONSE_FAILED;
+ }
#ifdef SUPPORT_TLS
tls_offered = FALSE;
#endif
/* 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;
+ if (esmtp && !suppress_tls && tls_out.active < 0)
+ {
+ if (regex_STARTTLS == NULL) regex_STARTTLS =
+ regex_must_compile(US"\\n250[\\s\\-]STARTTLS(\\s|\\n|$)", FALSE, TRUE);
+
+ tls_offered = pcre_exec(regex_STARTTLS, NULL, CS responsebuffer,
+ Ustrlen(responsebuffer), 0, PCRE_EOPT, NULL, 0) >= 0;
+ }
+ else
+ tls_offered = FALSE;
#endif
}
#ifdef SUPPORT_TLS
if (tls_offered &&
verify_check_this_host(&(ob->hosts_avoid_tls), NULL, host->name,
- host->address, NULL) != OK)
+ host->address, NULL) != OK &&
+ verify_check_this_host(&(ob->hosts_verify_avoid_tls), NULL, host->name,
+ host->address, NULL) != OK
+ )
{
uschar buffer2[4096];
if ( !smtps
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,
+ ob->tls_require_ciphers, ob->tls_dh_min_bits,
callout);
/* TLS negotiation failed; give an error. Try in clear on a new connection,
}
else
{
+ /* Ensure no cutthrough on multiple address verifies */
if (options & vopt_callout_recipsender)
- cancel_cutthrough_connection(); /* Ensure no cutthrough on multiple address verifies */
+ cancel_cutthrough_connection("multiple verify calls");
if (send_quit) (void)smtp_write_command(&outblock, FALSE, "QUIT\r\n");
#ifdef SUPPORT_TLS
{
if (cutthrough_fd < 0) return TRUE;
if (_cutthrough_puts(cp, n)) return TRUE;
-cancel_cutthrough_connection();
+cancel_cutthrough_connection("transmit failed");
return FALSE;
}
cutthrough_flush_send( void )
{
if (_cutthrough_flush_send()) return TRUE;
-cancel_cutthrough_connection();
+cancel_cutthrough_connection("transmit failed");
return FALSE;
}
inblock.sock = cutthrough_fd;
/* this relies on (inblock.sock == tls_out.active) */
if(!smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer), expect, CUTTHROUGH_DATA_TIMEOUT))
- cancel_cutthrough_connection();
+ cancel_cutthrough_connection("target timeout on read");
if(copy != NULL)
{
static void
-close_cutthrough_connection( void )
+close_cutthrough_connection( const char * why )
{
if(cutthrough_fd >= 0)
{
#endif
(void)close(cutthrough_fd);
cutthrough_fd= -1;
- HDEBUG(D_acl) debug_printf("----------- cutthrough shutdown ------------\n");
+ HDEBUG(D_acl) debug_printf("----------- cutthrough shutdown (%s) ------------\n", why);
}
ctblock.ptr = ctbuffer;
}
void
-cancel_cutthrough_connection( void )
+cancel_cutthrough_connection( const char * why )
{
-close_cutthrough_connection();
+close_cutthrough_connection(why);
cutthrough_delivery= FALSE;
}
{
case '2':
delivery_log(LOG_MAIN, &cutthrough_addr, (int)'>', NULL);
- close_cutthrough_connection();
+ close_cutthrough_connection("delivered");
break;
case '4':
if (address[0] == 0) return OK;
+/* Flip the legacy TLS-related variables over to the outbound set in case
+they're used in the context of a transport used by verification. Reset them
+at exit from this routine. */
+
+modify_variable(US"tls_bits", &tls_out.bits);
+modify_variable(US"tls_certificate_verified", &tls_out.certificate_verified);
+modify_variable(US"tls_cipher", &tls_out.cipher);
+modify_variable(US"tls_peerdn", &tls_out.peerdn);
+#if defined(SUPPORT_TLS) && !defined(USE_GNUTLS)
+modify_variable(US"tls_sni", &tls_out.sni);
+#endif
+
/* Save a copy of the sender address for re-instating if we change it to <>
while verifying a sender address (a nice bit of self-reference there). */
}
else
{
+#ifdef SUPPORT_TLS
+ deliver_set_expansions(addr);
+#endif
rc = do_callout(addr, host_list, &tf, callout, callout_overall,
callout_connect, options, se_mailfrom, pm_mailfrom);
}
}
respond_printf(f, "%s\n", cr);
}
- cancel_cutthrough_connection();
+ cancel_cutthrough_connection("routing hard fail");
- if (!full_info) return copy_error(vaddr, addr, FAIL);
- else yield = FAIL;
+ if (!full_info)
+ {
+ yield = copy_error(vaddr, addr, FAIL);
+ goto out;
+ }
+ else yield = FAIL;
}
/* Soft failure */
}
respond_printf(f, "%s\n", cr);
}
- cancel_cutthrough_connection();
+ cancel_cutthrough_connection("routing soft fail");
- if (!full_info) return copy_error(vaddr, addr, DEFER);
- else if (yield == OK) yield = DEFER;
+ if (!full_info)
+ {
+ yield = copy_error(vaddr, addr, DEFER);
+ goto out;
+ }
+ else if (yield == OK) yield = DEFER;
}
/* If we are handling EXPN, we do not want to continue to route beyond
if (addr_new == NULL) ok_prefix = US"250 ";
respond_printf(f, "%s<%s>\r\n", ok_prefix, addr2->address);
}
- return OK;
+ yield = OK;
+ goto out;
}
/* Successful routing other than EXPN. */
of $address_data to be that of the child */
vaddr->p.address_data = addr->p.address_data;
- return OK;
+ yield = OK;
+ goto out;
}
}
} /* Loop for generated addresses */
if (allok && addr_local == NULL && addr_remote == NULL)
{
fprintf(f, "mail to %s is discarded\n", address);
- return yield;
+ goto out;
}
for (addr_list = addr_local, i = 0; i < 2; addr_list = addr_remote, i++)
}
}
-/* Will be DEFER or FAIL if any one address has, only for full_info (which is
+/* Yield will be DEFER or FAIL if any one address has, only for full_info (which is
the -bv or -bt case). */
+out:
+
+modify_variable(US"tls_bits", &tls_in.bits);
+modify_variable(US"tls_certificate_verified", &tls_in.certificate_verified);
+modify_variable(US"tls_cipher", &tls_in.cipher);
+modify_variable(US"tls_peerdn", &tls_in.peerdn);
+#if defined(SUPPORT_TLS) && !defined(USE_GNUTLS)
+modify_variable(US"tls_sni", &tls_in.sni);
+#endif
+
return yield;
}