X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fsrc%2Fhost.c;h=a31c09b659f15bee1740e210d49dd004634db492;hb=2130e492c2cda886d74abbb77df4493f151e0a44;hp=a00d048f675b6d3a8e62a0ea4104d110df668b86;hpb=f3ebb786e451da973560f1c9d8cdb151d25108b5;p=user%2Fhenk%2Fcode%2Fexim.git diff --git a/src/src/host.c b/src/src/host.c index a00d048f6..a31c09b65 100644 --- a/src/src/host.c +++ b/src/src/host.c @@ -3,6 +3,7 @@ *************************************************/ /* Copyright (c) University of Cambridge 1995 - 2018 */ +/* Copyright (c) The Exim Maintainers 2020 */ /* See the file NOTICE for conditions of use and distribution. */ /* Functions for finding hosts, either by gethostbyname(), gethostbyaddr(), or @@ -138,7 +139,7 @@ if (!slow_lookup_log) time_msec = get_time_in_ms(); retval = dns_lookup(dnsa, name, type, fully_qualified_name); if ((time_msec = get_time_in_ms() - time_msec) > slow_lookup_log) - log_long_lookup(US"name", name, time_msec); + log_long_lookup(dns_text_type(type), name, time_msec); return retval; } @@ -177,24 +178,23 @@ const uschar *lname = name; uschar *adds; uschar **alist; struct hostent *yield; -dns_answer dnsa; +dns_answer * dnsa = store_get_dns_answer(); dns_scan dnss; DEBUG(D_host_lookup) debug_printf("using host_fake_gethostbyname for %s (%s)\n", name, - (af == AF_INET)? "IPv4" : "IPv6"); + af == AF_INET ? "IPv4" : "IPv6"); /* Handle unqualified "localhost" */ if (Ustrcmp(name, "localhost") == 0) - lname = (af == AF_INET)? US"127.0.0.1" : US"::1"; + lname = af == AF_INET ? US"127.0.0.1" : US"::1"; /* Handle a literal IP address */ if ((ipa = string_is_ip_address(lname, NULL)) != 0) - { - if ((ipa == 4 && af == AF_INET) || - (ipa == 6 && af == AF_INET6)) + if ( ipa == 4 && af == AF_INET + || ipa == 6 && af == AF_INET6) { int x[4]; yield = store_get(sizeof(struct hostent), FALSE); @@ -224,14 +224,13 @@ if ((ipa = string_is_ip_address(lname, NULL)) != 0) *error_num = HOST_NOT_FOUND; return NULL; } - } /* Handle a host name */ else { - int type = (af == AF_INET)? T_A:T_AAAA; - int rc = dns_lookup_timerwrap(&dnsa, lname, type, NULL); + int type = af == AF_INET ? T_A:T_AAAA; + int rc = dns_lookup_timerwrap(dnsa, lname, type, NULL); int count = 0; lookup_dnssec_authenticated = NULL; @@ -246,9 +245,9 @@ else case DNS_FAIL: *error_num = NO_RECOVERY; return NULL; } - for (dns_record * rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); + for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr; - rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT)) if (rr->type == type) + rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)) if (rr->type == type) count++; yield = store_get(sizeof(struct hostent), FALSE); @@ -261,13 +260,13 @@ else yield->h_length = alen; yield->h_addr_list = CSS alist; - for (dns_record * rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); + for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr; - rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT)) if (rr->type == type) + rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)) if (rr->type == type) { int x[4]; dns_address *da; - if (!(da = dns_address_from_rr(&dnsa, rr))) break; + if (!(da = dns_address_from_rr(dnsa, rr))) break; *alist++ = adds; for (int n = host_aton(da->address, x), i = 0; i < n; i++) { @@ -729,6 +728,7 @@ host_build_ifacelist(const uschar *list, uschar *name) int sep = 0; uschar *s; ip_address_item * yield = NULL, * last = NULL, * next; +BOOL taint = is_tainted(list); while ((s = string_nextinlist(&list, &sep, NULL, 0))) { @@ -747,7 +747,7 @@ while ((s = string_nextinlist(&list, &sep, NULL, 0))) address above. The field in the ip_address_item is large enough to hold an IPv6 address. */ - next = store_get(sizeof(ip_address_item), FALSE); + next = store_get(sizeof(ip_address_item), taint); next->next = NULL; Ustrcpy(next->address, s); next->port = port; @@ -945,13 +945,15 @@ else /* If there is no buffer, put the string into some new store. */ -if (buffer == NULL) return string_copy(yield); +if (!buffer) buffer = store_get(46, FALSE); /* Callers of this function with a non-NULL buffer must ensure that it is large enough to hold an IPv6 address, namely, at least 46 bytes. That's what -makes this use of strcpy() OK. */ +makes this use of strcpy() OK. +If the library returned apparently an apparently tainted string, clean it; +we trust IP addresses. */ -Ustrcpy(buffer, yield); +string_format_nt(buffer, 46, "%s", yield); return buffer; } @@ -1230,14 +1232,11 @@ BOOL host_is_tls_on_connect_port(int port) { int sep = 0; -uschar buffer[32]; -const uschar *list = tls_in.on_connect_ports; -uschar *s; -uschar *end; +const uschar * list = tls_in.on_connect_ports; if (tls_in.on_connect) return TRUE; -while ((s = string_nextinlist(&list, &sep, buffer, sizeof(buffer)))) +for (uschar * s, * end; s = string_nextinlist(&list, &sep, NULL, 0); ) if (Ustrtol(s, &end, 10) == port) return TRUE; @@ -1501,9 +1500,7 @@ Returns: OK, DEFER, FAIL static int host_name_lookup_byaddr(void) { -int len; -uschar *s, *t; -struct hostent *hosts; +struct hostent * hosts; struct in_addr addr; unsigned long time_msec = 0; /* init to quieten dumb static analysis */ @@ -1546,7 +1543,7 @@ hosts = gethostbyaddr(CS(&addr), sizeof(addr), AF_INET); if ( slow_lookup_log && (time_msec = get_time_in_ms() - time_msec) > slow_lookup_log ) - log_long_lookup(US"name", sender_host_address, time_msec); + log_long_lookup(US"gethostbyaddr", sender_host_address, time_msec); /* Failed to look up the host. */ @@ -1646,10 +1643,9 @@ int old_pool, rc; int sep = 0; uschar *save_hostname; uschar **aliases; -uschar buffer[256]; uschar *ordername; const uschar *list = host_lookup_order; -dns_answer dnsa; +dns_answer * dnsa = store_get_dns_answer(); dns_scan dnss; sender_host_dnssec = host_lookup_deferred = host_lookup_failed = FALSE; @@ -1672,13 +1668,14 @@ if (f.running_in_test_harness && /* Do lookups directly in the DNS or via gethostbyaddr() (or equivalent), in the order specified by the host_lookup_order option. */ -while ((ordername = string_nextinlist(&list, &sep, buffer, sizeof(buffer)))) +while ((ordername = string_nextinlist(&list, &sep, NULL, 0))) { if (strcmpic(ordername, US"bydns") == 0) { + uschar * name = dns_build_reverse(sender_host_address); + dns_init(FALSE, FALSE, FALSE); /* dnssec ctrl by dns_dnssec_ok glbl */ - dns_build_reverse(sender_host_address, buffer); - rc = dns_lookup_timerwrap(&dnsa, buffer, T_PTR, NULL); + rc = dns_lookup_timerwrap(dnsa, name, T_PTR, NULL); /* The first record we come across is used for the name; others are considered to be aliases. We have to scan twice, in order to find out the @@ -1693,16 +1690,16 @@ while ((ordername = string_nextinlist(&list, &sep, buffer, sizeof(buffer)))) int count = 0; int old_pool = store_pool; - sender_host_dnssec = dns_is_secure(&dnsa); + sender_host_dnssec = dns_is_secure(dnsa); DEBUG(D_dns) debug_printf("Reverse DNS security status: %s\n", sender_host_dnssec ? "DNSSEC verified (AD)" : "unverified"); store_pool = POOL_PERM; /* Save names in permanent storage */ - for (dns_record * rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); + for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr; - rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT)) if (rr->type == T_PTR) + rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)) if (rr->type == T_PTR) count++; /* Get store for the list of aliases. For compatibility with @@ -1712,16 +1709,16 @@ while ((ordername = string_nextinlist(&list, &sep, buffer, sizeof(buffer)))) /* Re-scan and extract the names */ - for (dns_record * rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); + for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr; - rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT)) if (rr->type == T_PTR) + rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)) if (rr->type == T_PTR) { uschar * s = store_get(ssize, TRUE); /* names are tainted */ /* If an overlong response was received, the data will have been truncated and dn_expand may fail. */ - if (dn_expand(dnsa.answer, dnsa.answer + dnsa.answerlen, + if (dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen, US (rr->data), (DN_EXPAND_ARG4_TYPE)(s), ssize) < 0) { log_write(0, LOG_MAIN, "host name alias list truncated for %s", @@ -1946,8 +1943,13 @@ host_find_byname(host_item *host, const uschar *ignore_target_hosts, int flags, int yield, times; host_item *last = NULL; BOOL temp_error = FALSE; -#if HAVE_IPV6 int af; + +#ifndef DISABLE_TLS +/* Copy the host name at this point to the value which is used for +TLS certificate name checking, before anything modifies it. */ + +host->certname = host->name; #endif /* Make sure DNS options are set as required. This appears to be necessary in @@ -1967,10 +1969,10 @@ lookups here (except when testing standalone). */ #ifdef STAND_ALONE if (disable_ipv6) #else - if (disable_ipv6 || - (dns_ipv4_lookup != NULL && - match_isinlist(host->name, CUSS &dns_ipv4_lookup, 0, NULL, NULL, - MCL_DOMAIN, TRUE, NULL) == OK)) + if ( disable_ipv6 + || dns_ipv4_lookup + && match_isinlist(host->name, CUSS &dns_ipv4_lookup, 0, NULL, NULL, + MCL_DOMAIN, TRUE, NULL) == OK) #endif { af = AF_INET; times = 1; } @@ -1980,7 +1982,7 @@ lookups here (except when testing standalone). */ /* No IPv6 support */ #else /* HAVE_IPV6 */ - times = 1; + af = AF_INET; times = 1; #endif /* HAVE_IPV6 */ /* Initialize the flag that gets set for DNS syntax check errors, so that the @@ -2022,7 +2024,7 @@ for (int i = 1; i <= times; #else /* not HAVE_IPV6 */ if (f.running_in_test_harness) - hostdata = host_fake_gethostbyname(host->name, AF_INET, &error_num); + hostdata = host_fake_gethostbyname(host->name, af, &error_num); else { hostdata = gethostbyname(CS host->name); @@ -2032,47 +2034,46 @@ for (int i = 1; i <= times; if ( slow_lookup_log && (time_msec = get_time_in_ms() - time_msec) > slow_lookup_log) - log_long_lookup(US"name", host->name, time_msec); + log_long_lookup(US"gethostbyname", host->name, time_msec); - if (hostdata == NULL) + if (!hostdata) { - uschar *error; + uschar * error; switch (error_num) { - case HOST_NOT_FOUND: error = US"HOST_NOT_FOUND"; break; - case TRY_AGAIN: error = US"TRY_AGAIN"; break; - case NO_RECOVERY: error = US"NO_RECOVERY"; break; - case NO_DATA: error = US"NO_DATA"; break; - #if NO_DATA != NO_ADDRESS - case NO_ADDRESS: error = US"NO_ADDRESS"; break; - #endif + case HOST_NOT_FOUND: error = US"HOST_NOT_FOUND"; break; + case TRY_AGAIN: error = US"TRY_AGAIN"; temp_error = TRUE; break; + case NO_RECOVERY: error = US"NO_RECOVERY"; temp_error = TRUE; break; + case NO_DATA: error = US"NO_DATA"; break; + #if NO_DATA != NO_ADDRESS + case NO_ADDRESS: error = US"NO_ADDRESS"; break; + #endif default: error = US"?"; break; } - DEBUG(D_host_lookup) debug_printf("%s returned %d (%s)\n", - #if HAVE_IPV6 - #if HAVE_GETIPNODEBYNAME - (af == AF_INET6)? "getipnodebyname(af=inet6)" : "getipnodebyname(af=inet)", - #else - (af == AF_INET6)? "gethostbyname2(af=inet6)" : "gethostbyname2(af=inet)", - #endif - #else - "gethostbyname", - #endif - error_num, error); + DEBUG(D_host_lookup) debug_printf("%s(af=%s) returned %d (%s)\n", + f.running_in_test_harness ? "host_fake_gethostbyname" : +#if HAVE_IPV6 +# if HAVE_GETIPNODEBYNAME + "getipnodebyname", +# else + "gethostbyname2", +# endif +#else + "gethostbyname", +#endif + af == AF_INET ? "inet" : "inet6", error_num, error); - if (error_num == TRY_AGAIN || error_num == NO_RECOVERY) temp_error = TRUE; continue; } - if ((hostdata->h_addr_list)[0] == NULL) continue; + if (!(hostdata->h_addr_list)[0]) continue; /* Replace the name with the fully qualified one if necessary, and fill in the fully_qualified_name pointer. */ - if (hostdata->h_name[0] != 0 && - Ustrcmp(host->name, hostdata->h_name) != 0) + if (hostdata->h_name[0] && Ustrcmp(host->name, hostdata->h_name) != 0) host->name = string_copy_dnsdomain(US hostdata->h_name); - if (fully_qualified_name != NULL) *fully_qualified_name = host->name; + if (fully_qualified_name) *fully_qualified_name = host->name; /* Get the list of addresses. IPv4 and IPv6 addresses can be distinguished by their different lengths. Scan the list, ignoring any that are to be @@ -2086,9 +2087,9 @@ for (int i = 1; i <= times; host_ntoa(ipv4_addr? AF_INET:AF_INET6, *addrlist, NULL, NULL); #ifndef STAND_ALONE - if (ignore_target_hosts != NULL && - verify_check_this_host(&ignore_target_hosts, NULL, host->name, - text_address, NULL) == OK) + if ( ignore_target_hosts + && verify_check_this_host(&ignore_target_hosts, NULL, host->name, + text_address, NULL) == OK) { DEBUG(D_host_lookup) debug_printf("ignored host %s [%s]\n", host->name, text_address); @@ -2096,10 +2097,10 @@ for (int i = 1; i <= times; } #endif - /* If this is the first address, last == NULL and we put the data in the + /* If this is the first address, last is NULL and we put the data in the original block. */ - if (last == NULL) + if (!last) { host->address = text_address; host->port = PORT_NONE; @@ -2116,6 +2117,9 @@ for (int i = 1; i <= times; { host_item *next = store_get(sizeof(host_item), FALSE); next->name = host->name; +#ifndef DISABLE_TLS + next->certname = host->certname; +#endif next->mx = host->mx; next->address = text_address; next->port = PORT_NONE; @@ -2134,12 +2138,12 @@ for (int i = 1; i <= times; NULL. If temp_error is set, at least one of the lookups gave a temporary error, so we pass that back. */ -if (host->address == NULL) +if (!host->address) { uschar *msg = #ifndef STAND_ALONE - (message_id[0] == 0 && smtp_in != NULL)? - string_sprintf("no IP address found for host %s (during %s)", host->name, + !message_id[0] && smtp_in + ? string_sprintf("no IP address found for host %s (during %s)", host->name, smtp_get_connection_info()) : #endif string_sprintf("no IP address found for host %s", host->name); @@ -2259,6 +2263,13 @@ BOOL v6_find_again = FALSE; BOOL dnssec_fail = FALSE; int i; +#ifndef DISABLE_TLS +/* Copy the host name at this point to the value which is used for +TLS certificate name checking, before any CNAME-following modifies it. */ + +host->certname = host->name; +#endif + /* If allow_ip is set, a name which is an IP address returns that value as its address. This is used for MX records when allow_mx_to_ip is set, for those sites that feel they have to flaunt the RFC rules. */ @@ -2307,17 +2318,17 @@ for (; i >= 0; i--) int type = types[i]; int randoffset = i == (whichrrs & HOST_FIND_IPV4_FIRST ? 1 : 0) ? 500 : 0; /* Ensures v6/4 sort order */ - dns_answer dnsa; + dns_answer * dnsa = store_get_dns_answer(); dns_scan dnss; - int rc = dns_lookup_timerwrap(&dnsa, host->name, type, fully_qualified_name); + int rc = dns_lookup_timerwrap(dnsa, host->name, type, fully_qualified_name); lookup_dnssec_authenticated = !dnssec_request ? NULL - : dns_is_secure(&dnsa) ? US"yes" : US"no"; + : dns_is_secure(dnsa) ? US"yes" : US"no"; DEBUG(D_dns) if ( (dnssec_request || dnssec_require) - && !dns_is_secure(&dnsa) - && dns_is_aa(&dnsa) + && !dns_is_secure(dnsa) + && dns_is_aa(dnsa) ) debug_printf("DNS lookup of %.256s (A/AAAA) requested AD, but got AA\n", host->name); @@ -2345,7 +2356,7 @@ for (; i >= 0; i--) if (dnssec_request) { - if (dns_is_secure(&dnsa)) + 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() */ @@ -2376,11 +2387,11 @@ for (; i >= 0; i--) fully_qualified_name = NULL; - for (dns_record * rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); + for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr; - rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT)) if (rr->type == type) + rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)) if (rr->type == type) { - dns_address * da = dns_address_from_rr(&dnsa, rr); + dns_address * da = dns_address_from_rr(dnsa, rr); DEBUG(D_host_lookup) if (!da) debug_printf("no addresses extracted from A6 RR for %s\n", @@ -2542,7 +2553,7 @@ host_item *h, *last; int rc = DNS_FAIL; int ind_type = 0; int yield; -dns_answer dnsa; +dns_answer * dnsa = store_get_dns_answer(); dns_scan dnss; BOOL dnssec_require = dnssec_d && match_isinlist(host->name, CUSS &dnssec_d->require, @@ -2584,18 +2595,18 @@ if (whichrrs & HOST_FIND_BY_SRV) dnssec = DS_UNK; lookup_dnssec_authenticated = NULL; - rc = dns_lookup_timerwrap(&dnsa, temp_fully_qualified_name, ind_type, + rc = dns_lookup_timerwrap(dnsa, temp_fully_qualified_name, ind_type, CUSS &temp_fully_qualified_name); DEBUG(D_dns) if ((dnssec_request || dnssec_require) - && !dns_is_secure(&dnsa) - && dns_is_aa(&dnsa)) + && !dns_is_secure(dnsa) + && dns_is_aa(dnsa)) debug_printf("DNS lookup of %.256s (SRV) requested AD, but got AA\n", host->name); if (dnssec_request) { - if (dns_is_secure(&dnsa)) + if (dns_is_secure(dnsa)) { dnssec = DS_YES; lookup_dnssec_authenticated = US"yes"; } else { dnssec = DS_NO; lookup_dnssec_authenticated = US"no"; } @@ -2607,7 +2618,7 @@ if (whichrrs & HOST_FIND_BY_SRV) /* On DNS failures, we give the "try again" error unless the domain is listed as one for which we continue. */ - if (rc == DNS_SUCCEED && dnssec_require && !dns_is_secure(&dnsa)) + if (rc == DNS_SUCCEED && dnssec_require && !dns_is_secure(dnsa)) { log_write(L_host_lookup_failed, LOG_MAIN, "dnssec fail on SRV for %.256s", host->name); @@ -2637,18 +2648,18 @@ if (rc != DNS_SUCCEED && whichrrs & HOST_FIND_BY_MX) ind_type = T_MX; dnssec = DS_UNK; lookup_dnssec_authenticated = NULL; - rc = dns_lookup_timerwrap(&dnsa, host->name, ind_type, fully_qualified_name); + rc = dns_lookup_timerwrap(dnsa, host->name, ind_type, fully_qualified_name); DEBUG(D_dns) if ( (dnssec_request || dnssec_require) - && !dns_is_secure(&dnsa) - && dns_is_aa(&dnsa)) + && !dns_is_secure(dnsa) + && dns_is_aa(dnsa)) debug_printf("DNS lookup of %.256s (MX) requested AD, but got AA\n", host->name); if (dnssec_request) - if (dns_is_secure(&dnsa)) + if (dns_is_secure(dnsa)) { - DEBUG(D_host_lookup) debug_printf("%s MX DNSSEC\n", host->name); + DEBUG(D_host_lookup) debug_printf("%s (MX resp) DNSSEC\n", host->name); dnssec = DS_YES; lookup_dnssec_authenticated = US"yes"; } else @@ -2662,7 +2673,7 @@ if (rc != DNS_SUCCEED && whichrrs & HOST_FIND_BY_MX) yield = HOST_FIND_FAILED; goto out; case DNS_SUCCEED: - if (!dnssec_require || dns_is_secure(&dnsa)) + if (!dnssec_require || dns_is_secure(dnsa)) break; DEBUG(D_host_lookup) debug_printf("dnssec fail on MX for %.256s", host->name); @@ -2756,9 +2767,9 @@ host which is not the primary hostname. */ last = NULL; /* Indicates that not even the first item is filled yet */ -for (dns_record * rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); +for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr; - rr = dns_next_rr(&dnsa, &dnss, RESET_NEXT)) if (rr->type == ind_type) + rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)) if (rr->type == ind_type) { int precedence, weight; int port = PORT_NONE; @@ -2783,7 +2794,7 @@ for (dns_record * rr = dns_next_rr(&dnsa, &dnss, RESET_ANSWERS); /* Get the name of the host pointed to. */ - (void)dn_expand(dnsa.answer, dnsa.answer + dnsa.answerlen, s, + (void)dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen, s, (DN_EXPAND_ARG4_TYPE)data, sizeof(data)); /* Check that we haven't already got this host on the chain; if we have, @@ -3154,6 +3165,79 @@ dns_init(FALSE, FALSE, FALSE); /* clear the dnssec bit for getaddrbyname */ return yield; } + + + +#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 + FAIL_FORCED No TLSA record; DANE not usable + FAIL Do not use this connection +*/ + +int +tlsa_lookup(const host_item * host, dns_answer * dnsa, BOOL dane_required) +{ +uschar buffer[300]; +const uschar * fullname = buffer; +int rc; +BOOL sec; + +/* TLSA lookup string */ +(void)sprintf(CS buffer, "_%d._tcp.%.256s", host->port, host->name); + +rc = dns_lookup_timerwrap(dnsa, buffer, T_TLSA, &fullname); +sec = dns_is_secure(dnsa); +DEBUG(D_transport) + debug_printf("TLSA lookup ret %s %sDNSSEC\n", dns_rc_names[rc], sec ? "" : "not "); + +switch (rc) + { + case DNS_AGAIN: + return DEFER; /* just defer this TLS'd conn */ + + case DNS_SUCCEED: + if (sec) + { + DEBUG(D_transport) + { + dns_scan dnss; + for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_ANSWERS); rr; + rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)) + if (rr->type == T_TLSA && rr->size > 3) + { + uint16_t payload_length = rr->size - 3; + uschar s[MAX_TLSA_EXPANDED_SIZE], * sp = s, * p = US rr->data; + + sp += sprintf(CS sp, "%d ", *p++); /* usage */ + sp += sprintf(CS sp, "%d ", *p++); /* selector */ + sp += sprintf(CS sp, "%d ", *p++); /* matchtype */ + while (payload_length-- > 0 && sp-s < (MAX_TLSA_EXPANDED_SIZE - 4)) + sp += sprintf(CS sp, "%02x", *p++); + + debug_printf(" %s\n", s); + } + } + return OK; + } + log_write(0, LOG_MAIN, + "DANE error: TLSA lookup for %s not DNSSEC", host->name); + /*FALLTRHOUGH*/ + + case DNS_NODATA: /* no TLSA RR for this lookup */ + case DNS_NOMATCH: /* no records at all for this lookup */ + return dane_required ? FAIL : FAIL_FORCED; + + default: + case DNS_FAIL: + return dane_required ? FAIL : DEFER; + } +} +#endif /*SUPPORT_DANE*/ + + + /************************************************* ************************************************** * Stand-alone test program *