BOOL esmtp;
BOOL suppress_tls = FALSE;
uschar *interface = NULL; /* Outgoing interface to use; NULL => any */
+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_DANE)
+ BOOL dane = FALSE;
+ dns_answer tlsa_dnsa;
+#endif
uschar inbuffer[4096];
uschar outbuffer[1024];
uschar responsebuffer[4096];
deliver_host_address = host->address;
deliver_host_port = host->port;
deliver_domain = addr->domain;
+ transport_name = addr->transport->name;
if (!smtp_get_interface(tf->interface, host_af, addr, NULL, &interface,
US"callout") ||
HDEBUG(D_verify) debug_printf("interface=%s port=%d\n", interface, port);
+#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_DANE)
+ {
+ BOOL dane_required;
+ int rc;
+
+ tls_out.dane_verified = FALSE;
+ tls_out.tlsa_usage = 0;
+
+ dane_required =
+ verify_check_given_host(&ob->hosts_require_dane, host) == OK;
+
+ if (host->dnssec == DS_YES)
+ {
+ if( dane_required
+ || verify_check_given_host(&ob->hosts_try_dane, host) == OK
+ )
+ if ((rc = tlsa_lookup(host, &tlsa_dnsa, dane_required, &dane)) != OK)
+ return rc;
+ }
+ else if (dane_required)
+ {
+ log_write(0, LOG_MAIN, "DANE error: %s lookup not DNSSEC", host->name);
+ return FAIL;
+ }
+
+ if (dane)
+ ob->tls_tempfail_tryclear = FALSE;
+ }
+#endif /*DANE*/
+
/* Set up the buffer for reading SMTP response packets. */
inblock.buffer = inbuffer;
inblock.sock = outblock.sock =
smtp_connect(host, host_af, port, interface, callout_connect, TRUE, NULL
-#ifdef EXPERIMENTAL_TPDA
- /*XXX tpda action? NULL for now. */
+#ifdef EXPERIMENTAL_EVENT
+ /*XXX event action? NULL for now. */
, NULL
#endif
);
{
addr->message = string_sprintf("could not connect to %s [%s]: %s",
host->name, host->address, strerror(errno));
+ transport_name = NULL;
deliver_host = deliver_host_address = NULL;
deliver_domain = save_deliver_domain;
continue;
if (!(done= smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer), '2', callout)))
goto RESPONSE_FAILED;
-#ifdef EXPERIMENTAL_TPDA
- if (tpda_raise_event(addr->transport->tpda_event_action,
- US"smtp:connect", responsebuffer) == DEFER)
+#ifdef EXPERIMENTAL_EVENT
+ lookup_dnssec_authenticated = host->dnssec==DS_YES ? US"yes"
+ : host->dnssec==DS_NO ? US"no" : NULL;
+ if (event_raise(addr->transport->event_action,
+ US"smtp:connect", responsebuffer))
{
+ lookup_dnssec_authenticated = NULL;
/* Logging? Debug? */
goto RESPONSE_FAILED;
}
+ lookup_dnssec_authenticated = NULL;
#endif
}
/* 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))
+ if (!(esmtp = verify_check_given_host(&(ob->hosts_avoid_esmtp), host) != OK))
DEBUG(D_transport)
debug_printf("not sending EHLO (host matches hosts_avoid_esmtp)\n");
for error analysis. */
#ifdef SUPPORT_TLS
- if (tls_offered &&
- verify_check_this_host(&(ob->hosts_avoid_tls), NULL, host->name,
- host->address, NULL) != OK &&
- verify_check_this_host(&(ob->hosts_verify_avoid_tls), NULL, host->name,
- host->address, NULL) != OK
+ if ( tls_offered
+ && verify_check_given_host(&ob->hosts_avoid_tls, host) != OK
+ && verify_check_given_host(&ob->hosts_verify_avoid_tls, host) != OK
)
{
uschar buffer2[4096];
int rc;
ob->command_timeout = callout;
- rc = tls_client_start(inblock.sock, host, addr, addr->transport);
+ rc = tls_client_start(inblock.sock, host, addr, addr->transport
+#ifdef EXPERIMENTAL_DANE
+ , dane ? &tlsa_dnsa : NULL
+#endif
+ );
ob->command_timeout = oldtimeout;
/* 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
-#ifdef EXPERIMENTAL_DANE
- && verify_check_this_host(&(ob->hosts_require_dane), NULL,
- host->name, host->address, NULL) != OK
-#endif
+ && verify_check_given_host(&ob->hosts_require_tls, host) != OK
)
{
- (void)close(inblock.sock);
+ (void)close(inblock.sock);
+#ifdef EXPERIMENTAL_EVENT
+ (void) event_raise(addr->transport->event_action,
+ US"tcp:close", NULL);
+#endif
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;
/* 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
+ if (
#ifdef EXPERIMENTAL_DANE
- || verify_check_this_host(&(ob->hosts_require_dane), NULL, host->name,
- host->address, NULL) == OK
+ dane ||
#endif
+ verify_check_given_host(&ob->hosts_require_tls, host) == OK
)
{
/*save_errno = ERRNO_TLSREQUIRED;*/
- log_write(0, LOG_MAIN, "a TLS session is required for %s [%s], but %s",
+ log_write(0, LOG_MAIN,
+ "H=%s [%s]: a TLS session is required for this host, but %s",
host->name, host->address,
- tls_offered? "an attempt to start TLS failed" : "the server did not offer TLS support");
+ tls_offered ? "an attempt to start TLS failed"
+ : "the server did not offer TLS support");
done= FALSE;
goto TLS_FAILED;
}
/* If accepted, we aren't going to do any further tests below. */
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
cutthrough_addr = *addr; /* Save the address_item for later logging */
cutthrough_addr.next = NULL;
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;
+ *(cutthrough_addr.host_used) = *host;
if (addr->parent)
*(cutthrough_addr.parent = store_get(sizeof(address_item)))= *addr->parent;
ctblock.buffer = ctbuffer;
tls_close(FALSE, TRUE);
#endif
(void)close(inblock.sock);
-#ifdef EXPERIMENTAL_TPDA
- (void) tpda_raise_event(addr->transport->tpda_event_action,
+#ifdef EXPERIMENTAL_EVENT
+ (void) event_raise(addr->transport->event_action,
US"tcp:close", NULL);
#endif
}
#ifdef SUPPORT_TLS
deliver_set_expansions(addr);
#endif
+ verify_mode = is_recipient ? US"R" : US"S";
rc = do_callout(addr, host_list, &tf, callout, callout_overall,
callout_connect, options, se_mailfrom, pm_mailfrom);
+ verify_mode = NULL;
}
}
else
+/*************************************************
+* Check the given host item matches a list *
+*************************************************/
+int
+verify_check_given_host(uschar **listptr, host_item *host)
+{
+return verify_check_this_host(listptr, NULL, host->name, host->address, NULL);
+}
+
/*************************************************
* Check the remote host matches a list *
*************************************************/