* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2012 */
+/* Copyright (c) University of Cambridge 1995 - 2014 */
/* See the file NOTICE for conditions of use and distribution. */
#include "../exim.h"
(void *)offsetof(smtp_transport_options_block, tls_sni) },
{ "tls_tempfail_tryclear", opt_bool,
(void *)offsetof(smtp_transport_options_block, tls_tempfail_tryclear) },
+ { "tls_try_verify_hosts", opt_stringptr,
+ (void *)offsetof(smtp_transport_options_block, tls_try_verify_hosts) },
{ "tls_verify_certificates", opt_stringptr,
- (void *)offsetof(smtp_transport_options_block, tls_verify_certificates) }
+ (void *)offsetof(smtp_transport_options_block, tls_verify_certificates) },
+ { "tls_verify_hosts", opt_stringptr,
+ (void *)offsetof(smtp_transport_options_block, tls_verify_hosts) }
+#endif
+#ifdef EXPERIMENTAL_TPDA
+ ,{ "tpda_host_defer_action", opt_stringptr,
+ (void *)offsetof(smtp_transport_options_block, tpda_host_defer_action) },
#endif
};
NULL, /* tls_verify_certificates */
EXIM_CLIENT_DH_DEFAULT_MIN_BITS,
/* tls_dh_min_bits */
- TRUE /* tls_tempfail_tryclear */
+ TRUE, /* tls_tempfail_tryclear */
+ NULL, /* tls_verify_hosts */
+ NULL /* tls_try_verify_hosts */
#endif
#ifndef DISABLE_DKIM
,NULL, /* dkim_canon */
NULL, /* dkim_sign_headers */
NULL /* dkim_strict */
#endif
+#ifdef EXPERIMENTAL_TPDA
+ ,NULL /* tpda_host_defer_action */
+#endif
};
+#ifdef EXPERIMENTAL_TPDA
+/*************************************************
+* Post-defer action *
+*************************************************/
+
+/* This expands an arbitrary per-transport string.
+ It might, for example, be used to write to the database log.
+
+Arguments:
+ ob transport options block
+ addr the address item containing error information
+ host the current host
+
+Returns: nothing
+*/
+
+static void
+tpda_deferred(smtp_transport_options_block *ob, address_item *addr, host_item *host)
+{
+uschar *action = ob->tpda_host_defer_action;
+if (!action)
+ return;
+
+tpda_delivery_ip = string_copy(host->address);
+tpda_delivery_port = (host->port == PORT_NONE)? 25 : host->port;
+tpda_delivery_fqdn = string_copy(host->name);
+tpda_delivery_local_part = string_copy(addr->local_part);
+tpda_delivery_domain = string_copy(addr->domain);
+tpda_defer_errno = addr->basic_errno;
+
+tpda_defer_errstr = addr->message
+ ? addr->basic_errno > 0
+ ? string_sprintf("%s: %s", addr->message, strerror(addr->basic_errno))
+ : string_copy(addr->message)
+ : addr->basic_errno > 0
+ ? string_copy(strerror(addr->basic_errno))
+ : NULL;
+
+DEBUG(D_transport)
+ debug_printf(" TPDA(host defer): tpda_host_defer_action=|%s| tpda_delivery_IP=%s\n",
+ action, tpda_delivery_ip);
+
+router_name = addr->router->name;
+transport_name = addr->transport->name;
+if (!expand_string(action) && *expand_string_message)
+ log_write(0, LOG_MAIN|LOG_PANIC, "failed to expand tpda_defer_action in %s: %s\n",
+ transport_name, expand_string_message);
+router_name = transport_name = NULL;
+}
+#endif
+
+
+
/*************************************************
* Synchronize SMTP responses *
*************************************************/
FALSE);
return DEFER;
}
-
+
return OK;
}
/* Reset the parameters of a TLS session. */
-tls_in.bits = 0;
-tls_in.cipher = NULL; /* for back-compatible behaviour */
-tls_in.peerdn = NULL;
-#if defined(SUPPORT_TLS) && !defined(USE_GNUTLS)
-tls_in.sni = NULL;
-#endif
-
tls_out.bits = 0;
tls_out.cipher = NULL; /* the one we may use for this transport */
tls_out.peerdn = NULL;
tls_out.sni = NULL;
#endif
+/* Flip the legacy TLS-related variables over to the outbound set in case
+they're used in the context of the transport. Don't bother resetting
+afterward as we're in a subprocess. */
+
+tls_modify_variables(&tls_out);
+
#ifndef SUPPORT_TLS
if (smtps)
{
ob->hosts_require_ocsp,
#endif
ob->tls_dh_min_bits,
- ob->command_timeout);
+ ob->command_timeout,
+ ob->tls_verify_hosts,
+ ob->tls_try_verify_hosts);
/* TLS negotiation failed; give an error. From outside, this function may
be called again to try in clear on a new connection, if the options permit
/* Set up confirmation if needed - applies only to SMTP */
- if ((log_extra_selector & LX_smtp_confirmation) != 0 && !lmtp)
+ if (
+ #ifndef EXPERIMENTAL_TPDA
+ (log_extra_selector & LX_smtp_confirmation) != 0 &&
+ #endif
+ !lmtp
+ )
{
uschar *s = string_printing(buffer);
conf = (s == buffer)? (uschar *)string_copy(s) : s;
the transport name. See lots of comments in deliver.c about the reasons
for the complications when homonyms are involved. Just carry on after
write error, as it may prove possible to update the spool file later. */
-
+
if (testflag(addr, af_homonym))
sprintf(CS buffer, "%.500s/%s\n", addr->unique + 3, tblock->name);
else
sprintf(CS buffer, "%.500s\n", addr->unique);
-
+
DEBUG(D_deliver) debug_printf("journalling %s", buffer);
len = Ustrlen(CS buffer);
if (write(journal_fd, buffer, len) != len)
sprintf(CS buffer, "%.500s/%s\n", addr->unique + 3, tblock->name);
else
sprintf(CS buffer, "%.500s\n", addr->unique);
-
+
DEBUG(D_deliver) debug_printf("journalling(PRDR) %s", buffer);
len = Ustrlen(CS buffer);
if (write(journal_fd, buffer, len) != len)
rc = host_find_byname(host, NULL, flags, &canonical_name, TRUE);
else
rc = host_find_bydns(host, NULL, flags, NULL, NULL, NULL,
+ NULL, NULL, /*XXX todo: smtp tpt hosts_require_dnssec */
&canonical_name, NULL);
/* Update the host (and any additional blocks, resulting from
first_addr->basic_errno != ERRNO_TLSFAILURE)
write_logs(first_addr, host);
+ #ifdef EXPERIMENTAL_TPDA
+ if (rc == DEFER)
+ tpda_deferred(ob, first_addr, host);
+ #endif
+
/* If STARTTLS was accepted, but there was a failure in setting up the
TLS session (usually a certificate screwup), and the host is not in
hosts_require_tls, and tls_tempfail_tryclear is true, try again, with
expanded_hosts != NULL, &message_defer, TRUE);
if (rc == DEFER && first_addr->basic_errno != ERRNO_AUTHFAIL)
write_logs(first_addr, host);
+ #ifdef EXPERIMENTAL_TPDA
+ if (rc == DEFER)
+ tpda_deferred(ob, first_addr, host);
+ #endif
}
#endif
}