X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/7156b1ef48de59429a3d81d966ef151edc1c01ad..44649fdb169979af3c5a08b10889d1ecee48a469:/src/src/dns.c diff --git a/src/src/dns.c b/src/src/dns.c index 9d4da4ae1..6efb88d58 100644 --- a/src/src/dns.c +++ b/src/src/dns.c @@ -1,10 +1,8 @@ -/* $Cambridge: exim/src/src/dns.c,v 1.20 2009/11/11 10:08:01 nm4 Exp $ */ - /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2007 */ +/* Copyright (c) University of Cambridge 1995 - 2014 */ /* See the file NOTICE for conditions of use and distribution. */ /* Functions for interfacing with the DNS. */ @@ -161,25 +159,85 @@ the first time we have been here, and set the resolver options. Arguments: qualify_single TRUE to set the RES_DEFNAMES option search_parents TRUE to set the RES_DNSRCH option + use_dnssec TRUE to set the RES_USE_DNSSEC option Returns: nothing */ void -dns_init(BOOL qualify_single, BOOL search_parents) +dns_init(BOOL qualify_single, BOOL search_parents, BOOL use_dnssec) { -if ((_res.options & RES_INIT) == 0) +res_state resp = os_get_dns_resolver_res(); + +if ((resp->options & RES_INIT) == 0) { - DEBUG(D_resolver) _res.options |= RES_DEBUG; /* For Cygwin */ + DEBUG(D_resolver) resp->options |= RES_DEBUG; /* For Cygwin */ + os_put_dns_resolver_res(resp); res_init(); - DEBUG(D_resolver) _res.options |= RES_DEBUG; + DEBUG(D_resolver) resp->options |= RES_DEBUG; + os_put_dns_resolver_res(resp); } -_res.options &= ~(RES_DNSRCH | RES_DEFNAMES); -_res.options |= (qualify_single? RES_DEFNAMES : 0) | +resp->options &= ~(RES_DNSRCH | RES_DEFNAMES); +resp->options |= (qualify_single? RES_DEFNAMES : 0) | (search_parents? RES_DNSRCH : 0); -if (dns_retrans > 0) _res.retrans = dns_retrans; -if (dns_retry > 0) _res.retry = dns_retry; +if (dns_retrans > 0) resp->retrans = dns_retrans; +if (dns_retry > 0) resp->retry = dns_retry; + +#ifdef RES_USE_EDNS0 +if (dns_use_edns0 >= 0) + { + if (dns_use_edns0) + resp->options |= RES_USE_EDNS0; + else + resp->options &= ~RES_USE_EDNS0; + DEBUG(D_resolver) + debug_printf("Coerced resolver EDNS0 support %s.\n", + dns_use_edns0 ? "on" : "off"); + } +#else +if (dns_use_edns0 >= 0) + DEBUG(D_resolver) + debug_printf("Unable to %sset EDNS0 without resolver support.\n", + dns_use_edns0 ? "" : "un"); +#endif + +#ifndef DISABLE_DNSSEC +# ifdef RES_USE_DNSSEC +# ifndef RES_USE_EDNS0 +# error Have RES_USE_DNSSEC but not RES_USE_EDNS0? Something hinky ... +# endif +if (use_dnssec) + resp->options |= RES_USE_DNSSEC; +if (dns_dnssec_ok >= 0) + { + if (dns_use_edns0 == 0 && dns_dnssec_ok != 0) + { + DEBUG(D_resolver) + debug_printf("CONFLICT: dns_use_edns0 forced false, dns_dnssec_ok forced true, ignoring latter!\n"); + } + else + { + if (dns_dnssec_ok) + resp->options |= RES_USE_DNSSEC; + else + resp->options &= ~RES_USE_DNSSEC; + DEBUG(D_resolver) debug_printf("Coerced resolver DNSSEC support %s.\n", + dns_dnssec_ok ? "on" : "off"); + } + } +# else +if (dns_dnssec_ok >= 0) + DEBUG(D_resolver) + debug_printf("Unable to %sset DNSSEC without resolver support.\n", + dns_dnssec_ok ? "" : "un"); +if (use_dnssec) + DEBUG(D_resolver) + debug_printf("Unable to set DNSSEC without resolver support.\n"); +# endif +#endif /* DISABLE_DNSSEC */ + +os_put_dns_resolver_res(resp); } @@ -372,6 +430,34 @@ return &(dnss->srr); +/************************************************* +* Return whether AD bit set in DNS result * +*************************************************/ + +/* We do not perform DNSSEC work ourselves; if the administrator has installed +a verifying resolver which sets AD as appropriate, though, we'll use that. +(AD = Authentic Data) + +Argument: pointer to dns answer block +Returns: bool indicating presence of AD bit +*/ + +BOOL +dns_is_secure(dns_answer *dnsa) +{ +#ifdef DISABLE_DNSSEC +DEBUG(D_dns) + debug_printf("DNSSEC support disabled at build-time; dns_is_secure() false\n"); +return FALSE; +#else +HEADER *h = (HEADER *)dnsa->answer; +return h->ad ? TRUE : FALSE; +#endif +} + + + + /************************************************* * Turn DNS type into text * *************************************************/ @@ -393,11 +479,13 @@ switch(t) case T_AAAA: return US"AAAA"; case T_A6: return US"A6"; case T_TXT: return US"TXT"; + case T_SPF: return US"SPF"; case T_PTR: return US"PTR"; case T_SOA: return US"SOA"; case T_SRV: return US"SRV"; case T_NS: return US"NS"; case T_CNAME: return US"CNAME"; + case T_TLSA: return US"TLSA"; default: return US"?"; } } @@ -424,9 +512,10 @@ Returns: the return code static int dns_return(uschar *name, int type, int rc) { +res_state resp = os_get_dns_resolver_res(); tree_node *node = store_get_perm(sizeof(tree_node) + 290); sprintf(CS node->name, "%.255s-%s-%lx", name, dns_text_type(type), - _res.options); + resp->options); node->data.val = rc; (void)tree_insertnode(&tree_dns_fails, node); return rc; @@ -466,6 +555,7 @@ dns_basic_lookup(dns_answer *dnsa, uschar *name, int type) int rc = -1; uschar *save; #endif +res_state resp = os_get_dns_resolver_res(); tree_node *previous; uschar node_name[290]; @@ -476,7 +566,7 @@ have many addresses in the same domain. We rely on the resolver and name server caching for successful lookups. */ sprintf(CS node_name, "%.255s-%s-%lx", name, dns_text_type(type), - _res.options); + resp->options); previous = tree_search(tree_dns_fails, node_name); if (previous != NULL) { @@ -1165,4 +1255,6 @@ else return yield; } +/* vi: aw ai sw=2 +*/ /* End of dns.c */