summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2020-08-23 15:32:48 +0100
committerJeremy Harris <jgh146exb@wizmail.org>2020-08-23 17:05:52 +0100
commit99350dede64ad634300ddf15d0d97a81fd75d330 (patch)
tree4b30b80983ba93658a0832f3ad1d30263e4da88d /src
parentd6ffd8ef9ebcb2dc913c75ee255459e8ff4fb4da (diff)
DANE: Fix 2-rcpt message, diff domins case. Bug 2265
Diffstat (limited to 'src')
-rw-r--r--src/src/debug.c1
-rw-r--r--src/src/deliver.c3
-rw-r--r--src/src/macros.h1
-rw-r--r--src/src/transports/smtp.c71
-rw-r--r--src/src/verify.c2
5 files changed, 67 insertions, 11 deletions
diff --git a/src/src/debug.c b/src/src/debug.c
index 90c48dde4..fee0b7a81 100644
--- a/src/src/debug.c
+++ b/src/src/debug.c
@@ -31,6 +31,7 @@ const uschar * rc_names[] = { /* Mostly for debug output */
[CANCELLED] = US"CANCELLED",
[FAIL_SEND] = US"FAIL_SEND",
[FAIL_DROP] = US"FAIL_DROP",
+ [DANE] = US"DANE",
};
const uschar * dns_rc_names[] = {
diff --git a/src/src/deliver.c b/src/src/deliver.c
index dd922c728..a47440695 100644
--- a/src/src/deliver.c
+++ b/src/src/deliver.c
@@ -460,6 +460,9 @@ TRUE if the lists refer to the same hosts in the same order, except that
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
diff --git a/src/src/macros.h b/src/src/macros.h
index 5c3fa06f6..8e2050e22 100644
--- a/src/src/macros.h
+++ b/src/src/macros.h
@@ -305,6 +305,7 @@ Use rc_names[] for debug strings. */
#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 */
diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
index d1deffa6f..447f76a9b 100644
--- a/src/src/transports/smtp.c
+++ b/src/src/transports/smtp.c
@@ -2017,11 +2017,12 @@ if (!continue_hostname)
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);
@@ -3442,6 +3443,7 @@ BOOL pass_message = FALSE;
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;
*message_defer = FALSE;
@@ -3457,13 +3459,36 @@ sx->conn_args.tblock = tblock;
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
@@ -4213,7 +4238,7 @@ if (sx->completed_addr && sx->ok && sx->send_quit)
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;
@@ -4249,7 +4274,7 @@ if (sx->completed_addr && sx->ok && sx->send_quit)
'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
{
@@ -4269,7 +4294,7 @@ if (sx->completed_addr && sx->ok && sx->send_quit)
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. */
@@ -4309,7 +4334,7 @@ propagate it from the initial
sx->cctx.sock = -1;
continue_transport = NULL;
continue_hostname = NULL;
- return yield;
+ goto TIDYUP;
}
log_write(0, LOG_PANIC_DIE, "fork failed");
}
@@ -4384,9 +4409,35 @@ if (sx->send_quit)
(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;
}
diff --git a/src/src/verify.c b/src/src/verify.c
index efc05fcf1..a50ac8b7b 100644
--- a/src/src/verify.c
+++ b/src/src/verify.c
@@ -654,7 +654,7 @@ coding means skipping this whole loop and doing the append separately. */
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;