This should be documented with the feature. If the documentation does not
explicitly state that the feature is infeasible in the other TLS
implementation, then patches are welcome.
+.new
+.next
+The output from "exim -bV" will show which (if any) support was included
+in the build.
+Also, the macro "_HAVE_OPENSSL" or "_HAVE_GNUTLS" will be defined.
+.wen
.endlist
[UNEXPECTED] = US"UNEXPECTED",
[CANCELLED] = US"CANCELLED",
[FAIL_SEND] = US"FAIL_SEND",
- [FAIL_DROP] = US"FAIL_DROP"
+ [FAIL_DROP] = US"FAIL_DROP",
+ [DANE] = US"DANE",
+};
+
+const uschar * dns_rc_names[] = {
+ [DNS_SUCCEED] = US"DNS_SUCCEED",
+ [DNS_NOMATCH] = US"DNS_NOMATCH",
+ [DNS_NODATA] = US"DNS_NODATA",
+ [DNS_AGAIN] = US"DNS_AGAIN",
+ [DNS_FAIL] = US"DNS_FAIL",
};
This enables Exim to use a single SMTP transaction for sending to two entirely
different domains that happen to end up pointing at the same hosts.
+We do not try to batch up different A-record host names that refer to the
+same IP.
+
Arguments:
one points to the first host list
two points to the second host list
#define CANCELLED 13 /* Authentication cancelled */
#define FAIL_SEND 14 /* send() failed in authenticator */
#define FAIL_DROP 15 /* Fail and drop connection (used in ACL) */
+#define DANE 16 /* Deferred for domain mismatch (used in transport) */
/* Returns from the deliver_message() function */
switch (rc = tlsa_lookup(sx->conn_args.host, &sx->conn_args.tlsa_dnsa, sx->dane_required))
{
case OK: sx->conn_args.dane = TRUE;
- ob->tls_tempfail_tryclear = FALSE;
- ob->tls_sni = sx->addrlist->domain;
+ ob->tls_tempfail_tryclear = FALSE; /* force TLS */
+ ob->tls_sni = sx->first_addr->domain; /* force SNI */
break;
case FAIL_FORCED: break;
- default: set_errno_nohost(sx->addrlist, ERRNO_DNSDEFER,
+ default:
+ set_errno_nohost(sx->addrlist, ERRNO_DNSDEFER,
string_sprintf("DANE error: tlsa lookup %s",
rc_to_string(rc)),
rc, FALSE, &sx->delivery_start);
uschar *message = NULL;
uschar new_message_id[MESSAGE_ID_LENGTH + 1];
smtp_context * sx = store_get(sizeof(*sx), TRUE); /* tainted, for the data buffers */
+BOOL dane_held;
suppress_tls = suppress_tls; /* stop compiler warning when no TLS support */
*message_defer = FALSE;
gettimeofday(&sx->delivery_start, NULL);
sx->sync_addr = sx->first_addr = addrlist;
-/* Get the channel set up ready for a message (MAIL FROM being the next
-SMTP command to send */
+DANE_DOMAINS:
+dane_held = FALSE;
+
+/* Get the channel set up ready for a message, MAIL FROM being the next
+SMTP command to send. */
if ((rc = smtp_setup_conn(sx, suppress_tls)) != OK)
{
timesince(&addrlist->delivery_time, &sx->delivery_start);
- return rc;
+ yield = rc;
+ goto TIDYUP;
+ }
+
+/*XXX*/
+/* If the connection used DANE, ignore for now any addresses with incompatible
+domains. The SNI has to be the domain. Arrange a whole new TCP conn later,
+just in case only TLS isn't enough. */
+
+if (sx->conn_args.dane)
+ {
+ const uschar * dane_domain = sx->first_addr->domain;
+
+ for (address_item * a = sx->first_addr->next; a; a = a->next)
+ if ( a->transport_return == PENDING_DEFER
+ && Ustrcmp(dane_domain, a->domain) != 0)
+ {
+ DEBUG(D_transport) debug_printf("DANE: holding %s for later\n", a->domain);
+ dane_held = TRUE;
+ a->transport_return = DANE;
+ }
}
/* If there is a filter command specified for this transport, we can now
if (sx->first_addr != NULL) /* More addresses still to be sent */
- { /* in this run of the transport */
+ { /* on this connection */
continue_sequence++; /* Causes * in logging */
pipelining_active = sx->pipelining_used; /* was cleared at DATA */
goto SEND_MESSAGE;
'2', ob->command_timeout);
if (sx->ok && f.continue_more)
- return yield; /* More addresses for another run */
+ goto TIDYUP; /* More addresses for another run */
}
else
{
else
#endif
if (f.continue_more)
- return yield; /* More addresses for another run */
+ goto TIDYUP; /* More addresses for another run */
/* If the socket is successfully passed, we mustn't send QUIT (or
indeed anything!) from here. */
sx->cctx.sock = -1;
continue_transport = NULL;
continue_hostname = NULL;
- return yield;
+ goto TIDYUP;
}
log_write(0, LOG_PANIC_DIE, "fork failed");
}
(void) event_raise(tblock->event_action, US"tcp:close", NULL);
#endif
+/*XXX*/
+if (dane_held)
+ {
+ sx->first_addr = NULL;
+ for (address_item * a = sx->addrlist->next; a; a = a->next)
+ if (a->transport_return == DANE)
+ {
+ a->transport_return = PENDING_DEFER;
+ if (!sx->first_addr)
+ {
+ /* Remember the new start-point in the addrlist, for smtp_setup_conn()
+ to get the domain string for SNI */
+
+ sx->first_addr = a;
+ DEBUG(D_transport) debug_printf("DANE: go-around for %s\n", a->domain);
+ }
+ }
+ goto DANE_DOMAINS;
+ }
+
continue_transport = NULL;
continue_hostname = NULL;
return yield;
+
+TIDYUP:
+if (dane_held) for (address_item * a = sx->addrlist->next; a; a = a->next)
+ if (a->transport_return == DANE)
+ a->transport_return = PENDING_DEFER;
+return yield;
}
if (!sx) sx = store_get(sizeof(*sx), TRUE); /* tainted buffers */
memset(sx, 0, sizeof(*sx));
- sx->addrlist = addr;
+ sx->addrlist = sx->first_addr = addr;
sx->conn_args.host = host;
sx->conn_args.host_af = host_af,
sx->port = port;
--- /dev/null
+# Exim test configuration 5801
+# DANE common
+
+SERVER=
+CONTROL= *
+
+.include DIR/aux-var/tls_conf_prefix
+
+primary_hostname = myhost.test.ex
+
+# ----- Main settings -----
+
+.ifndef OPT
+acl_smtp_rcpt = accept
+.else
+acl_smtp_rcpt = accept verify = recipient/callout
+.endif
+
+log_selector = +received_recipients +tls_certificate_verified +tls_sni
+
+queue_run_in_order
+
+tls_advertise_hosts = *
+.ifdef _HAVE_GNUTLS
+# needed to force generation
+tls_dhparam = historic
+.endif
+
+# Set certificate only if server
+CDIR1 = DIR/aux-fixed/exim-ca/example.net/server1.example.net
+CDIR2 = DIR/aux-fixed/exim-ca/example.com/server1.example.com
+
+
+tls_certificate = ${if eq {SERVER}{server} \
+ {${if or {{eq {DETAILS}{ta}} {eq {DETAILS}{ca}} {eq {DETAILS}{ee}}} \
+ {CDIR2/fullchain.pem}\
+ {CDIR1/fullchain.pem}}}\
+ fail}
+
+tls_privatekey = ${if eq {SERVER}{server} \
+ {${if or {{eq {DETAILS}{ta}} {eq {DETAILS}{ca}} {eq {DETAILS}{ee}}} \
+ {CDIR2/server1.example.com.unlocked.key}\
+ {CDIR1/server1.example.net.unlocked.key}}}\
+ fail}
+
+# ----- Routers -----
+
+begin routers
+
+client:
+ driver = dnslookup
+ condition = ${if eq {SERVER}{}}
+ dnssec_request_domains = *
+ self = send
+ transport = send_to_server
+ errors_to = ""
+
+server:
+ driver = redirect
+ data = :blackhole:
+
+
+# ----- Transports -----
+
+begin transports
+
+send_to_server:
+ driver = smtp
+ allow_localhost
+ port = PORT_D
+ hosts_try_fastopen = :
+
+ hosts_try_dane = CONTROL
+ hosts_require_dane = HOSTIPV4
+ tls_verify_cert_hostnames = ${if eq {OPT}{no_certname} {}{*}}
+ tls_try_verify_hosts = thishost.test.ex
+ tls_verify_certificates = ${if eq {DETAILS}{ca} {CDIR2/ca_chain.pem} {}}
+
+
+
+# ----- Retry -----
+
+
+begin retry
+
+* * F,5d,10s
+
+
+# End
; | awk '{print $2}'
;
DNSSEC mxdane512ee MX 1 dane512ee
+DNSSEC mxdane512ee1 MX 1 dane512ee
DNSSEC dane512ee A HOSTIPV4
DNSSEC _1225._tcp.dane512ee TLSA 3 1 2 c0c2fc12e9fe1abf0ae7b1f2ad2798a4689668db8cf7f7b771a43bf8a4f1d9741ef103bad470b1201157150fbd6182054b0170e90ce66b944a82a0a9c81281af
--- /dev/null
+1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@myhost.test.ex U=CALLER P=local S=sss for t00@mxdane512ee.test.ex t01@mxdane512ee1.test.ex
+1999-03-02 09:44:33 10HmaX-0005vi-00 => t00@mxdane512ee.test.ex R=client T=send_to_server H=dane512ee.test.ex [ip4.ip4.ip4.ip4] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=dane C="250 OK id=10HmaY-0005vi-00"
+1999-03-02 09:44:33 10HmaX-0005vi-00 => t01@mxdane512ee1.test.ex R=client T=send_to_server H=dane512ee.test.ex [ip4.ip4.ip4.ip4] X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=dane C="250 OK id=10HmaZ-0005vi-00"
+1999-03-02 09:44:33 10HmaX-0005vi-00 Completed
+
+******** SERVER ********
+1999-03-02 09:44:33 exim x.yz daemon started: pid=pppp, no queue runs, listening for SMTP on port PORT_D
+1999-03-02 09:44:33 10HmaY-0005vi-00 <= <> H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no SNI=mxdane512ee.test.ex S=sss id=E10HmaX-0005vi-00@myhost.test.ex for t00@mxdane512ee.test.ex
+1999-03-02 09:44:33 10HmaY-0005vi-00 => :blackhole: <t00@mxdane512ee.test.ex> R=server
+1999-03-02 09:44:33 10HmaY-0005vi-00 Completed
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= <> H=the.local.host.name (myhost.test.ex) [ip4.ip4.ip4.ip4] P=esmtps X=TLS1.x:ke-RSA-AES256-SHAnnn:xxx CV=no SNI=mxdane512ee1.test.ex S=sss id=E10HmaX-0005vi-00@myhost.test.ex for t01@mxdane512ee1.test.ex
+1999-03-02 09:44:33 10HmaZ-0005vi-00 => :blackhole: <t01@mxdane512ee1.test.ex> R=server
+1999-03-02 09:44:33 10HmaZ-0005vi-00 Completed
--- /dev/null
+# DANE client: conflicting domain
+#
+exim -DSERVER=server -DDETAILS=ee -bd -oX PORT_D
+****
+#
+#
+# A single message with 2 receipients, different domains though same MX host
+exim -odf t00@mxdane512ee.test.ex t01@mxdane512ee1.test.ex
+****
+#
+killdaemon
+no_msglog_check