* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2017 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */
#include "../exim.h"
(void *)offsetof(smtp_transport_options_block, address_retry_include_sender) },
{ "allow_localhost", opt_bool,
(void *)offsetof(smtp_transport_options_block, allow_localhost) },
+#ifdef EXPERIMENTAL_ARC
+ { "arc_sign", opt_stringptr,
+ (void *)offsetof(smtp_transport_options_block, arc_sign) },
+#endif
{ "authenticated_sender", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, authenticated_sender) },
{ "authenticated_sender_force", opt_bool,
{ "hosts_require_auth", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, hosts_require_auth) },
#ifdef SUPPORT_TLS
-# ifdef EXPERIMENTAL_DANE
+# ifdef SUPPORT_DANE
{ "hosts_require_dane", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, hosts_require_dane) },
# endif
(void *)offsetof(smtp_transport_options_block, hosts_try_auth) },
{ "hosts_try_chunking", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, hosts_try_chunking) },
-#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_DANE)
+#if defined(SUPPORT_TLS) && defined(SUPPORT_DANE)
{ "hosts_try_dane", opt_stringptr,
(void *)offsetof(smtp_transport_options_block, hosts_try_dane) },
#endif
.fallback_hosts = NULL,
.hostlist = NULL,
.fallback_hostlist = NULL,
- .authenticated_sender = NULL,
.helo_data = US"$primary_hostname",
.interface = NULL,
.port = NULL,
.hosts_try_auth = NULL,
.hosts_require_auth = NULL,
.hosts_try_chunking = US"*",
-#ifdef EXPERIMENTAL_DANE
+#ifdef SUPPORT_DANE
.hosts_try_dane = NULL,
.hosts_require_dane = NULL,
#endif
.dkim_sign_headers = NULL,
.dkim_strict = NULL,
.dkim_hash = US"sha256",
- .dot_stuffed = FALSE},
+ .dot_stuffed = FALSE,
+ .force_bodyhash = FALSE,
+# ifdef EXPERIMENTAL_ARC
+ .arc_signspec = NULL,
+# endif
+ },
+# ifdef EXPERIMENTAL_ARC
+ .arc_sign = NULL,
+# endif
#endif
};
-#ifdef EXPERIMENTAL_DANE
+#ifdef SUPPORT_DANE
/* Lookup TLSA record for host/port.
Return: OK success with dnssec; DANE mode
DEFER Do not use this host now, may retry later
int
smtp_setup_conn(smtp_context * sx, BOOL suppress_tls)
{
-#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_DANE)
+#if defined(SUPPORT_TLS) && defined(SUPPORT_DANE)
dns_answer tlsa_dnsa;
#endif
BOOL pass_message = FALSE;
sx->utf8_needed = FALSE;
#endif
sx->dsn_all_lasthop = TRUE;
-#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_DANE)
+#if defined(SUPPORT_TLS) && defined(SUPPORT_DANE)
sx->dane = FALSE;
sx->dane_required = verify_check_given_host(&sx->ob->hosts_require_dane, sx->host) == OK;
#endif
smtp_port_for_connect(sx->host, sx->port);
-#if defined(SUPPORT_TLS) && defined(EXPERIMENTAL_DANE)
+#if defined(SUPPORT_TLS) && defined(SUPPORT_DANE)
/* Do TLSA lookup for DANE */
{
tls_out.dane_verified = FALSE;
string_sprintf("DANE error: tlsa lookup %s",
rc == DEFER ? "DEFER" : "FAIL"),
rc, FALSE);
+ (void) event_raise(sx->tblock->event_action,
+ US"dane:fail", sx->dane_required
+ ? US"dane-required" : US"dnssec-invalid");
return rc;
}
}
set_errno_nohost(sx->addrlist, ERRNO_DNSDEFER,
string_sprintf("DANE error: %s lookup not DNSSEC", sx->host->name),
FAIL, FALSE);
+ (void) event_raise(sx->tblock->event_action,
+ US"dane:fail", US"dane-required");
return FAIL;
}
}
address_item * addr;
uschar * errstr;
int rc = tls_client_start(sx->inblock.sock, sx->host, sx->addrlist, sx->tblock,
-# ifdef EXPERIMENTAL_DANE
+# ifdef SUPPORT_DANE
sx->dane ? &tlsa_dnsa : NULL,
# endif
&errstr);
if (rc != OK)
{
-# ifdef EXPERIMENTAL_DANE
- if (sx->dane) log_write(0, LOG_MAIN,
+# ifdef SUPPORT_DANE
+ if (sx->dane)
+ {
+ log_write(0, LOG_MAIN,
"DANE attempt failed; TLS connection to %s [%s]: %s",
sx->host->name, sx->host->address, errstr);
+ (void) event_raise(sx->tblock->event_action,
+ US"dane:fail", US"validation-failure"); /* could do with better detail */
+ }
# endif
errno = ERRNO_TLSFAILURE;
have one. */
else if ( sx->smtps
-# ifdef EXPERIMENTAL_DANE
+# ifdef SUPPORT_DANE
|| sx->dane
# endif
|| verify_check_given_host(&sx->ob->hosts_require_tls, sx->host) == OK
message = string_sprintf("a TLS session is required, but %s",
smtp_peer_options & OPTION_TLS
? "an attempt to start TLS failed" : "the server did not offer TLS support");
+# ifdef SUPPORT_DANE
+ if (sx->dane)
+ (void) event_raise(sx->tblock->event_action, US"dane:fail",
+ smtp_peer_options & OPTION_TLS
+ ? US"validation-failure" /* could do with better detail */
+ : US"starttls-not-supported");
+# endif
goto TLS_FAILED;
}
#endif /*SUPPORT_TLS*/
(void)smtp_write_command(&sx->outblock, SCMD_FLUSH, "QUIT\r\n");
#ifdef SUPPORT_TLS
-tls_close(FALSE, TRUE);
+tls_close(FALSE, TLS_SHUTDOWN_NOWAIT);
#endif
/* Close the socket, and return the appropriate value, first setting
if ((rc = read(pfd[0], buf, bsize)) <= 0)
{
fd_bits = 0;
- tls_close(FALSE, TRUE);
+ tls_close(FALSE, TLS_SHUTDOWN_NOWAIT);
}
else
{
transport_count = 0;
#ifndef DISABLE_DKIM
+ dkim_exim_sign_init();
+# ifdef EXPERIMENTAL_ARC
+ {
+ uschar * s = sx.ob->arc_sign;
+ if (s)
+ {
+ if (!(sx.ob->dkim.arc_signspec = expand_string(s)))
+ {
+ message = US"failed to expand arc_sign";
+ sx.ok = FALSE;
+ goto SEND_FAILED;
+ }
+ /* Ask dkim code to hash the body for ARC */
+ (void) arc_ams_setup_sign_bodyhash();
+ sx.ob->dkim.force_bodyhash = TRUE;
+ }
+ }
+# endif
sx.ok = dkim_transport_write_message(&tctx, &sx.ob->dkim, CUSS &message);
#else
sx.ok = transport_write_message(&tctx, 0);
#ifndef DISABLE_PRDR
if (sx.prdr_active)
{
+ const uschar * overall_message;
+
/* PRDR - get the final, overall response. For any non-success
upgrade all the address statuses. */
+
sx.ok = smtp_read_response(&sx.inblock, sx.buffer, sizeof(sx.buffer), '2',
sx.ob->final_timeout);
if (!sx.ok)
goto RESPONSE_FAILED;
}
- /* Update the journal, or setup retry. */
+ /* Append the overall response to the individual PRDR response for logging
+ and update the journal, or setup retry. */
+
+ overall_message = string_printing(sx.buffer);
+ for (addr = addrlist; addr != sx.first_addr; addr = addr->next)
+ if (addr->transport_return == OK)
+ addr->message = string_sprintf("%s\\n%s", addr->message, overall_message);
+
for (addr = addrlist; addr != sx.first_addr; addr = addr->next)
if (addr->transport_return == OK)
{
a new EHLO. If we don't get a good response, we don't attempt to pass
the socket on. */
- tls_close(FALSE, TRUE);
+ tls_close(FALSE, TLS_SHUTDOWN_WAIT);
smtp_peer_options = smtp_peer_options_wrap;
sx.ok = !sx.smtps
&& smtp_write_command(&sx.outblock, SCMD_FLUSH,
close(pfd[0]);
/* tidy the inter-proc to disconn the proxy proc */
waitpid(pid, NULL, 0);
- tls_close(FALSE, FALSE);
+ tls_close(FALSE, TLS_NO_SHUTDOWN);
(void)close(sx.inblock.sock);
continue_transport = NULL;
continue_hostname = NULL;
END_OFF:
#ifdef SUPPORT_TLS
-tls_close(FALSE, TRUE);
+tls_close(FALSE, TLS_SHUTDOWN_NOWAIT);
#endif
/* Close the socket, and return the appropriate value, first setting
if (tls_out.active == fd)
{
(void) tls_write(FALSE, US"QUIT\r\n", 6, FALSE);
- tls_close(FALSE, TRUE);
+ tls_close(FALSE, TLS_SHUTDOWN_NOWAIT);
}
else
#else