From cf2b569e3a2f8956b7045191e96bc5edfd366c78 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Sun, 10 Aug 2014 11:49:49 +0100 Subject: [PATCH] On a host lookup name->MX->A->ip sequence, require both stages to be dnssec before declaring the lookup was secure. --- src/src/host.c | 51 ++++++++++++++++++++++++++++--------------- src/src/tls-openssl.c | 1 + test/confs/5850 | 8 ++++--- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/src/src/host.c b/src/src/host.c index 00524f416..2eef0ba70 100644 --- a/src/src/host.c +++ b/src/src/host.c @@ -2207,7 +2207,7 @@ Returns: HOST_FIND_FAILED couldn't find A record static int set_address_from_dns(host_item *host, host_item **lastptr, uschar *ignore_target_hosts, BOOL allow_ip, uschar **fully_qualified_name, - BOOL dnssec_requested, BOOL dnssec_require) + BOOL dnssec_request, BOOL dnssec_require) { dns_record *rr; host_item *thishostlast = NULL; /* Indicates not yet filled in anything */ @@ -2268,7 +2268,7 @@ for (; i >= 0; i--) dns_scan dnss; int rc = dns_lookup(&dnsa, host->name, type, fully_qualified_name); - lookup_dnssec_authenticated = !dnssec_requested ? NULL + lookup_dnssec_authenticated = !dnssec_request ? NULL : dns_is_secure(&dnsa) ? US"yes" : US"no"; /* We want to return HOST_FIND_AGAIN if one of the A, A6, or AAAA lookups @@ -2292,11 +2292,31 @@ for (; i >= 0; i--) if (rc != DNS_NOMATCH && rc != DNS_NODATA) v6_find_again = TRUE; continue; } - if (dnssec_require && !dns_is_secure(&dnsa)) + + if (dnssec_request) { - log_write(L_host_lookup_failed, LOG_MAIN, "dnssec fail on %s for %.256s", + if (dns_is_secure(&dnsa)) + { + DEBUG(D_host_lookup) debug_printf("%s A DNSSEC\n", host->name); + if (host->dnssec == DS_UNK) /* set in host_find_bydns() */ + host->dnssec = DS_YES; + } + else + { + if (dnssec_require) + { + log_write(L_host_lookup_failed, LOG_MAIN, + "dnssec fail on %s for %.256s", i>1 ? "A6" : i>0 ? "AAAA" : "A", host->name); - continue; + continue; + } + if (host->dnssec == DS_YES) /* set in host_find_bydns() */ + { + DEBUG(D_host_lookup) debug_printf("%s A cancel DNSSEC\n", host->name); + host->dnssec = DS_NO; + lookup_dnssec_authenticated = US"no"; + } + } } /* Lookup succeeded: fill in the given host item with the first non-ignored @@ -2562,9 +2582,14 @@ if (rc != DNS_SUCCEED && (whichrrs & HOST_FIND_BY_MX) != 0) if (dnssec_request) { if (dns_is_secure(&dnsa)) - { dnssec = DS_YES; lookup_dnssec_authenticated = US"yes"; } + { + DEBUG(D_host_lookup) debug_printf("%s MX DNSSEC\n", host->name); + dnssec = DS_YES; lookup_dnssec_authenticated = US"yes"; + } else - { dnssec = DS_NO; lookup_dnssec_authenticated = US"no"; } + { + dnssec = DS_NO; lookup_dnssec_authenticated = US"no"; + } } switch (rc) @@ -2578,7 +2603,7 @@ if (rc != DNS_SUCCEED && (whichrrs & HOST_FIND_BY_MX) != 0) log_write(L_host_lookup_failed, LOG_MAIN, "dnssec fail on MX for %.256s", host->name); rc = DNS_FAIL; - /*FALLTRHOUGH*/ + /*FALLTHROUGH*/ case DNS_FAIL: case DNS_AGAIN: @@ -2609,19 +2634,11 @@ if (rc != DNS_SUCCEED) last = host; /* End of local chainlet */ host->mx = MX_NONE; host->port = PORT_NONE; - dnssec = DS_UNK; + host->dnssec = DS_UNK; lookup_dnssec_authenticated = NULL; rc = set_address_from_dns(host, &last, ignore_target_hosts, FALSE, fully_qualified_name, dnssec_request, dnssec_require); - if (dnssec_request) - { - if (dns_is_secure(&dnsa)) - { dnssec = DS_YES; lookup_dnssec_authenticated = US"yes"; } - else - { dnssec = DS_NO; lookup_dnssec_authenticated = US"no"; } - } - /* If one or more address records have been found, check that none of them are local. Since we know the host items all have their IP addresses inserted, host_scan_for_local_hosts() can only return HOST_FOUND or diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index 0bd23ac63..eb74605da 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -1664,6 +1664,7 @@ if (host->dnssec == DS_YES) else if (dane_required) { /* Hmm - what lookup, precisely? */ + /*XXX a shame we only find this after making tcp & smtp connection */ log_write(0, LOG_MAIN, "DANE error: previous lookup not DNSSEC"); return FAIL; } diff --git a/test/confs/5850 b/test/confs/5850 index 53cb78ae1..0b132e29e 100644 --- a/test/confs/5850 +++ b/test/confs/5850 @@ -37,9 +37,11 @@ tls_privatekey = ${if eq {SERVER}{server}{DIR/aux-fixed/cert1}fail} begin routers client: - driver = accept + driver = dnslookup condition = ${if eq {SERVER}{server}{no}{yes}} - retry_use_local_part +# retry_use_local_part + dnssec_request_domains = * + self = send transport = send_to_server server: @@ -54,7 +56,7 @@ begin transports send_to_server: driver = smtp allow_localhost - hosts = 127.0.0.1 +# hosts = 127.0.0.1 port = PORT_D # tls_certificate = DIR/aux-fixed/cert2 # tls_privatekey = DIR/aux-fixed/cert2 -- 2.30.2