Add gnutls_enable_pkcs11 option.
[exim.git] / src / src / dns.c
index f5e8ab7384ab306ad7acea13a495a416f7ec1e15..95db526867029321275e247fbd986037247ef594 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2012 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 /* Functions for interfacing with the DNS. */
@@ -166,26 +166,30 @@ Returns:            nothing
 void
 dns_init(BOOL qualify_single, BOOL search_parents)
 {
-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)
-    _res.options |= RES_USE_EDNS0;
+    resp->options |= RES_USE_EDNS0;
   else
-    _res.options &= ~RES_USE_EDNS0;
+    resp->options &= ~RES_USE_EDNS0;
   DEBUG(D_resolver)
     debug_printf("Coerced resolver EDNS0 support %s.\n",
         dns_use_edns0 ? "on" : "off");
@@ -196,6 +200,38 @@ if (dns_use_edns0 >= 0)
     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 (dns_use_dnssec >= 0)
+  {
+  if (dns_use_edns0 == 0 && dns_use_dnssec != 0)
+    {
+    DEBUG(D_resolver)
+      debug_printf("CONFLICT: dns_use_edns0 forced false, dns_use_dnssec forced true!\n");
+    }
+  else
+    {
+    if (dns_use_dnssec)
+      resp->options |= RES_USE_DNSSEC;
+    else
+      resp->options &= ~RES_USE_DNSSEC;
+    DEBUG(D_resolver) debug_printf("Coerced resolver DNSSEC support %s.\n",
+        dns_use_dnssec ? "on" : "off");
+    }
+  }
+# else
+if (dns_use_dnssec >= 0)
+  DEBUG(D_resolver)
+    debug_printf("Unable to %sset DNSSEC without resolver support.\n",
+        dns_use_dnssec ? "" : "un");
+# endif
+#endif /* DISABLE_DNSSEC */
+
+os_put_dns_resolver_res(resp);
 }
 
 
@@ -388,6 +424,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             *
 *************************************************/
@@ -409,6 +473,7 @@ 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";
@@ -440,9 +505,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;
@@ -482,6 +548,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];
@@ -492,7 +559,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)
   {