*/
static struct hostent *
-host_fake_gethostbyname(uschar *name, int af, int *error_num)
+host_fake_gethostbyname(const uschar *name, int af, int *error_num)
{
#if HAVE_IPV6
int alen = (af == AF_INET)? sizeof(struct in_addr):sizeof(struct in6_addr);
#endif
int ipa;
-uschar *lname = name;
+const uschar *lname = name;
uschar *adds;
uschar **alist;
struct hostent *yield;
int rc = dns_lookup(&dnsa, lname, type, NULL);
int count = 0;
+ lookup_dnssec_authenticated = NULL;
+
switch(rc)
{
case DNS_SUCCEED: break;
*/
void
-host_build_hostlist(host_item **anchor, uschar *list, BOOL randomize)
+host_build_hostlist(host_item **anchor, const uschar *list, BOOL randomize)
{
int sep = 0;
int fake_mx = MX_NONE; /* This value is actually -1 */
uschar *name;
-uschar buffer[1024];
if (list == NULL) return;
if (randomize) fake_mx--; /* Start at -2 for randomizing */
*anchor = NULL;
-while ((name = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
+while ((name = string_nextinlist(&list, &sep, NULL, 0)) != NULL)
{
host_item *h;
}
h = store_get(sizeof(host_item));
- h->name = string_copy(name);
+ h->name = name;
h->address = NULL;
h->port = PORT_NONE;
h->mx = fake_mx;
int
host_item_get_port(host_item *h)
{
-uschar *p;
+const uschar *p;
int port, x;
int len = Ustrlen(h->name);
*/
ip_address_item *
-host_build_ifacelist(uschar *list, uschar *name)
+host_build_ifacelist(const uschar *list, uschar *name)
{
int sep = 0;
uschar *s;
if (local_interface_data == NULL)
{
void *reset_item = store_get(0);
- ip_address_item *dlist = host_build_ifacelist(local_interfaces,
+ ip_address_item *dlist = host_build_ifacelist(CUS local_interfaces,
US"local_interfaces");
- ip_address_item *xlist = host_build_ifacelist(extra_local_interfaces,
+ ip_address_item *xlist = host_build_ifacelist(CUS extra_local_interfaces,
US"extra_local_interfaces");
ip_address_item *ipa;
*/
int
-host_aton(uschar *address, int *bin)
+host_aton(const uschar *address, int *bin)
{
int x[4];
int v4offset = 0;
if (Ustrchr(address, ':') != NULL)
{
- uschar *p = address;
- uschar *component[8];
+ const uschar *p = address;
+ const uschar *component[8];
BOOL ipv4_ends = FALSE;
int ci = 0;
int nulloffset = 0;
{
int sep = 0;
uschar buffer[32];
-uschar *list = tls_in.on_connect_ports;
+const uschar *list = tls_in.on_connect_ports;
uschar *s;
+uschar *end;
if (tls_in.on_connect) return TRUE;
-while ((s = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
- {
- uschar *end;
- int lport = Ustrtol(s, &end, 10);
- if (*end != 0) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "tls_on_connect_ports "
- "contains \"%s\", which is not a port number: exim abandoned", s);
- if (lport == port) return TRUE;
- }
+while ((s = string_nextinlist(&list, &sep, buffer, sizeof(buffer))))
+ if (Ustrtol(s, &end, 10) == port)
+ return TRUE;
return FALSE;
}
*/
BOOL
-host_is_in_net(uschar *host, uschar *net, int maskoffset)
+host_is_in_net(const uschar *host, const uschar *net, int maskoffset)
{
int i;
int address[4];
if (hosts_treat_as_local != NULL)
{
int rc;
- uschar *save = deliver_domain;
+ const uschar *save = deliver_domain;
deliver_domain = h->name; /* set $domain */
- rc = match_isinlist(string_copylc(h->name), &hosts_treat_as_local, 0,
+ rc = match_isinlist(string_copylc(h->name), CUSS &hosts_treat_as_local, 0,
&domainlist_anchor, NULL, MCL_DOMAIN, TRUE, NULL);
deliver_domain = save;
if (rc == OK) goto FOUND_LOCAL;
uschar **aliases;
uschar buffer[256];
uschar *ordername;
-uschar *list = host_lookup_order;
+const uschar *list = host_lookup_order;
dns_record *rr;
dns_answer dnsa;
dns_scan dnss;
{
if (strcmpic(ordername, US"bydns") == 0)
{
- dns_init(FALSE, FALSE, FALSE); /*XXX dnssec? */
+ dns_init(FALSE, FALSE, FALSE); /* dnssec ctrl by dns_dnssec_ok glbl */
dns_build_reverse(sender_host_address, buffer);
rc = dns_lookup(&dnsa, buffer, T_PTR, NULL);
HDEBUG(D_host_lookup)
{
uschar **aliases = sender_host_aliases;
- debug_printf("IP address lookup yielded %s\n", sender_host_name);
- while (*aliases != NULL) debug_printf(" alias %s\n", *aliases++);
+ debug_printf("IP address lookup yielded \"%s\"\n", sender_host_name);
+ while (*aliases != NULL) debug_printf(" alias \"%s\"\n", *aliases++);
}
/* We need to verify that a forward lookup on the name we found does indeed
*/
int
-host_find_byname(host_item *host, uschar *ignore_target_hosts, int flags,
- uschar **fully_qualified_name, BOOL local_host_check)
+host_find_byname(host_item *host, const uschar *ignore_target_hosts, int flags,
+ const uschar **fully_qualified_name, BOOL local_host_check)
{
int i, yield, times;
uschar **addrlist;
if (running_in_test_harness)
{
- uschar *endname = host->name + Ustrlen(host->name);
+ const uschar *endname = host->name + Ustrlen(host->name);
if (Ustrcmp(endname - 14, "test.again.dns") == 0) goto RETURN_AGAIN;
}
#else
if (disable_ipv6 ||
(dns_ipv4_lookup != NULL &&
- match_isinlist(host->name, &dns_ipv4_lookup, 0, NULL, NULL, MCL_DOMAIN,
- TRUE, NULL) == OK))
+ match_isinlist(host->name, CUSS &dns_ipv4_lookup, 0, NULL, NULL,
+ MCL_DOMAIN, TRUE, NULL) == OK))
#endif
{ af = AF_INET; times = 1; }
host->port = PORT_NONE;
host->status = hstatus_unknown;
host->why = hwhy_unknown;
+ host->dnssec = DS_UNK;
last = host;
}
next->port = PORT_NONE;
next->status = hstatus_unknown;
next->why = hwhy_unknown;
+ next->dnssec = DS_UNK;
next->last_try = 0;
next->next = last->next;
last->next = next;
HDEBUG(D_host_lookup)
{
- host_item *h;
+ const host_item *h;
if (fully_qualified_name != NULL)
debug_printf("fully qualified name = %s\n", *fully_qualified_name);
debug_printf("%s looked up these IP addresses:\n",
{
#ifndef STAND_ALONE
int rc;
- uschar *save = deliver_domain;
+ const uschar *save = deliver_domain;
deliver_domain = host->name; /* set $domain */
- rc = match_isinlist(host->name, &dns_again_means_nonexist, 0, NULL, NULL,
+ rc = match_isinlist(host->name, CUSS &dns_again_means_nonexist, 0, NULL, NULL,
MCL_DOMAIN, TRUE, NULL);
deliver_domain = save;
if (rc == OK)
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_require)
+ const uschar *ignore_target_hosts, BOOL allow_ip,
+ const uschar **fully_qualified_name,
+ BOOL dnssec_request, BOOL dnssec_require)
{
dns_record *rr;
host_item *thishostlast = NULL; /* Indicates not yet filled in anything */
#if HAVE_IPV6
#ifndef STAND_ALONE
if (disable_ipv6 || (dns_ipv4_lookup != NULL &&
- match_isinlist(host->name, &dns_ipv4_lookup, 0, NULL, NULL, MCL_DOMAIN,
- TRUE, NULL) == OK))
+ match_isinlist(host->name, CUSS &dns_ipv4_lookup, 0, NULL, NULL,
+ MCL_DOMAIN, TRUE, NULL) == OK))
i = 0; /* look up A records only */
else
#endif /* STAND_ALONE */
dns_scan dnss;
int rc = dns_lookup(&dnsa, host->name, type, fully_qualified_name);
+ 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
fails or times out, but not if another one succeeds. (In the early
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
*/
int
-host_find_bydns(host_item *host, uschar *ignore_target_hosts, int whichrrs,
+host_find_bydns(host_item *host, const uschar *ignore_target_hosts, int whichrrs,
uschar *srv_service, uschar *srv_fail_domains, uschar *mx_fail_domains,
uschar *dnssec_request_domains, uschar *dnssec_require_domains,
- uschar **fully_qualified_name, BOOL *removed)
+ const uschar **fully_qualified_name, BOOL *removed)
{
host_item *h, *last;
dns_record *rr;
int yield;
dns_answer dnsa;
dns_scan dnss;
-BOOL dnssec_request = match_isinlist(host->name, &dnssec_request_domains,
+BOOL dnssec_require = match_isinlist(host->name, CUSS &dnssec_require_domains,
0, NULL, NULL, MCL_DOMAIN, TRUE, NULL) == OK;
-BOOL dnssec_require = match_isinlist(host->name, &dnssec_require_domains,
+BOOL dnssec_request = dnssec_require
+ || match_isinlist(host->name, CUSS &dnssec_request_domains,
0, NULL, NULL, MCL_DOMAIN, TRUE, NULL) == OK;
+dnssec_status_t dnssec;
/* Set the default fully qualified name to the incoming name, initialize the
resolver if necessary, set up the relevant options, and initialize the flag
if (fully_qualified_name != NULL) *fully_qualified_name = host->name;
dns_init((whichrrs & HOST_FIND_QUALIFY_SINGLE) != 0,
(whichrrs & HOST_FIND_SEARCH_PARENTS) != 0,
- dnssec_request || dnssec_require
+ dnssec_request
);
host_find_failed_syntax = FALSE;
the input name, pass back the new original domain, without the prepended
magic. */
- rc = dns_lookup(&dnsa, buffer, ind_type, &temp_fully_qualified_name);
+ dnssec = DS_UNK;
+ lookup_dnssec_authenticated = NULL;
+ rc = dns_lookup(&dnsa, buffer, ind_type, CUSS &temp_fully_qualified_name);
+
+ 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 (temp_fully_qualified_name != buffer && fully_qualified_name != NULL)
*fully_qualified_name = temp_fully_qualified_name + prefix_length;
if (rc == DNS_FAIL || rc == DNS_AGAIN)
{
#ifndef STAND_ALONE
- if (match_isinlist(host->name, &srv_fail_domains, 0, NULL, NULL, MCL_DOMAIN,
- TRUE, NULL) != OK)
+ if (match_isinlist(host->name, CUSS &srv_fail_domains, 0, NULL, NULL,
+ MCL_DOMAIN, TRUE, NULL) != OK)
#endif
{ yield = HOST_FIND_AGAIN; goto out; }
DEBUG(D_host_lookup) debug_printf("DNS_%s treated as DNS_NODATA "
if (rc != DNS_SUCCEED && (whichrrs & HOST_FIND_BY_MX) != 0)
{
ind_type = T_MX;
+ dnssec = DS_UNK;
+ lookup_dnssec_authenticated = NULL;
rc = dns_lookup(&dnsa, host->name, ind_type, fully_qualified_name);
+
+ if (dnssec_request)
+ {
+ if (dns_is_secure(&dnsa))
+ {
+ 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";
+ }
+ }
+
switch (rc)
{
case DNS_NOMATCH:
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:
#ifndef STAND_ALONE
- if (match_isinlist(host->name, &mx_fail_domains, 0, NULL, NULL, MCL_DOMAIN,
- TRUE, NULL) != OK)
+ if (match_isinlist(host->name, CUSS &mx_fail_domains, 0, NULL, NULL,
+ MCL_DOMAIN, TRUE, NULL) != OK)
#endif
{ yield = HOST_FIND_AGAIN; goto out; }
DEBUG(D_host_lookup) debug_printf("DNS_%s treated as DNS_NODATA "
last = host; /* End of local chainlet */
host->mx = MX_NONE;
host->port = PORT_NONE;
+ host->dnssec = DS_UNK;
+ lookup_dnssec_authenticated = NULL;
rc = set_address_from_dns(host, &last, ignore_target_hosts, FALSE,
- fully_qualified_name, dnssec_require);
+ fully_qualified_name, dnssec_request, dnssec_require);
/* 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
the same precedence to sort randomly. */
if (ind_type == T_MX)
- {
weight = random_number(500);
- }
/* SRV records are specified with a port and a weight. The weight is used
in a special algorithm. However, to start with, we just use it to order the
host->sort_key = precedence * 1000 + weight;
host->status = hstatus_unknown;
host->why = hwhy_unknown;
+ host->dnssec = dnssec;
last = host;
}
next->sort_key = sort_key;
next->status = hstatus_unknown;
next->why = hwhy_unknown;
+ next->dnssec = dnssec;
next->last_try = 0;
/* Handle the case when we have to insert before the first item. */
{
if (h->address != NULL) continue; /* Inserted by a multihomed host */
rc = set_address_from_dns(h, &last, ignore_target_hosts, allow_mx_to_ip,
- NULL, dnssec_require);
+ NULL, dnssec_request, dnssec_require);
if (rc != HOST_FOUND)
{
h->status = hstatus_unusable;
yield);
for (h = host; h != last->next; h = h->next)
{
- debug_printf(" %s %s MX=%d ", h->name,
- (h->address == NULL)? US"<null>" : h->address, h->mx);
+ debug_printf(" %s %s MX=%d %s", h->name,
+ !h->address ? US"<null>" : h->address, h->mx,
+ h->dnssec == DS_YES ? US"DNSSEC " : US"");
if (h->port != PORT_NONE) debug_printf("port=%d ", h->port);
if (h->status >= hstatus_unusable) debug_printf("*");
debug_printf("\n");