SPDX: Mass-update to GPL-2.0-or-later
[exim.git] / src / src / dns.c
index b567c3e71813b87fdfdf5667e8c8a32a2f73f8b2..4e01d8661271948ad1b75b2378d7eb9554a28598 100644 (file)
@@ -2,9 +2,10 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
+/* Copyright (c) The Exim Maintainers 2020 - 2022 */
 /* Copyright (c) University of Cambridge 1995 - 2018 */
-/* Copyright (c) The Exim Maintainers 2020 */
 /* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
 
 /* Functions for interfacing with the DNS. */
 
@@ -258,7 +259,7 @@ else
   {
   int v6[4];
 
-  g = string_get_tainted(32, is_tainted(string));
+  g = string_get_tainted(32, string);
   (void)host_aton(string, v6);
 
   /* The original specification for IPv6 reverse lookup was to invert each
@@ -334,7 +335,6 @@ char * trace = NULL;
 #ifdef rr_trace
 # define TRACE DEBUG(D_dns)
 #else
-trace = trace;
 # define TRACE if (FALSE)
 #endif
 
@@ -516,7 +516,7 @@ if (  !h->aa
    || !(trusted = expand_string(dns_trust_aa))
    || !*trusted
    || !(auth_name = dns_extract_auth_name(dnsa))
-   || OK != match_isinlist(auth_name, &trusted, 0, NULL, NULL,
+   || OK != match_isinlist(auth_name, &trusted, 0, &domainlist_anchor, NULL,
                            MCL_DOMAIN, TRUE, NULL)
    )
   return FALSE;
@@ -638,7 +638,7 @@ if ((previous = tree_search(tree_dns_fails, node_name)))
   e = previous->data.ptr;
 else
   {
-  e = store_get_perm(DNS_FAILNODE_SIZE, is_tainted(name));
+  e = store_get_perm(DNS_FAILNODE_SIZE, name);
   new = (void *)(e+1);
   dns_fail_tag(new->name, name, type);
   new->data.ptr = e;
@@ -672,13 +672,10 @@ e = previous->data.ptr;
 val = e->data.val;
 rc = e->expiry && e->expiry <= time(NULL) ? -1 : val;
 
-DEBUG(D_dns) debug_printf("DNS lookup of %.255s-%s: %scached value %s%s\n",
+DEBUG(D_dns) debug_printf("DNS lookup of %.255s (%s): %scached value %s%s\n",
   name, dns_text_type(type),
   rc == -1 ? "" : "using ",
-    val == DNS_NOMATCH ? "DNS_NOMATCH" :
-    val == DNS_NODATA ? "DNS_NODATA" :
-    val == DNS_AGAIN ? "DNS_AGAIN" :
-    val == DNS_FAIL ? "DNS_FAIL" : "??",
+  dns_rc_names[val],
   rc == -1 ? " past valid time" : "");
 
 return rc;
@@ -695,9 +692,11 @@ packet length has been lost inside libresolv, so we have to guess a
 replacement value. (The only way to fix this properly would be to
 re-implement res_search() and res_query() so that they don't muddle their
 success and packet length return values.) For added safety we only reset
-the packet length if the packet header looks plausible. */
+the packet length if the packet header looks plausible.
 
-static void
+Return TRUE iff it seemed ok */
+
+static BOOL
 fake_dnsa_len_for_fail(dns_answer * dnsa, int type)
 {
 const HEADER * h = (const HEADER *)dnsa->answer;
@@ -714,7 +713,11 @@ if (  h->qr == 1                           /* a response */
   DEBUG(D_dns) debug_printf("faking res_search(%s) response length as %d\n",
     dns_text_type(type), (int)sizeof(dnsa->answer));
   dnsa->answerlen = sizeof(dnsa->answer);
+  return TRUE;
   }
+DEBUG(D_dns) debug_printf("DNS: couldn't fake dnsa len\n");
+/* Maybe we should just do a second lookup for an SOA? */
+return FALSE;
 }
 
 
@@ -728,37 +731,37 @@ dns_expire_from_soa(dns_answer * dnsa, int type)
 {
 dns_scan dnss;
 
-fake_dnsa_len_for_fail(dnsa, type);
+if (fake_dnsa_len_for_fail(dnsa, type))
+  for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_AUTHORITY);
+       rr; rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)
+      ) if (rr->type == T_SOA)
+    {
+    const uschar * p = rr->data;
+    uschar discard_buf[256];
+    int len;
+    unsigned long ttl;
+
+    /* Skip the mname & rname strings */
+
+    if ((len = dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen,
+       p, (DN_EXPAND_ARG4_TYPE)discard_buf, 256)) < 0)
+      break;
+    p += len;
+    if ((len = dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen,
+       p, (DN_EXPAND_ARG4_TYPE)discard_buf, 256)) < 0)
+      break;
+    p += len;
+
+    /* Skip the SOA serial, refresh, retry & expire.  Grab the TTL */
+
+    if (p > dnsa->answer + dnsa->answerlen - 5 * INT32SZ)
+      break;
+    p += 4 * INT32SZ;
+    GETLONG(ttl, p);
+
+    return time(NULL) + ttl;
+    }
 
-for (dns_record * rr = dns_next_rr(dnsa, &dnss, RESET_AUTHORITY);
-     rr; rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)
-    ) if (rr->type == T_SOA)
-  {
-  const uschar * p = rr->data;
-  uschar discard_buf[256];
-  int len;
-  unsigned long ttl;
-
-  /* Skip the mname & rname strings */
-
-  if ((len = dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen,
-      p, (DN_EXPAND_ARG4_TYPE)discard_buf, 256)) < 0)
-    break;
-  p += len;
-  if ((len = dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen,
-      p, (DN_EXPAND_ARG4_TYPE)discard_buf, 256)) < 0)
-    break;
-  p += len;
-
-  /* Skip the SOA serial, refresh, retry & expire.  Grab the TTL */
-
-  if (p > dnsa->answer + dnsa->answerlen - 5 * INT32SZ)
-    break;
-  p += 4 * INT32SZ;
-  GETLONG(ttl, p);
-
-  return time(NULL) + ttl;
-  }
 DEBUG(D_dns) debug_printf("DNS: no SOA record found for neg-TTL\n");
 return 0;
 }
@@ -848,11 +851,8 @@ more.) */
 
 if (check_dns_names_pattern[0] != 0 && type != T_PTR && type != T_TXT)
   {
-  int ovector[3*(EXPAND_MAXN+1)];
-
   dns_pattern_init();
-  if (pcre_exec(regex_check_dns_names, NULL, CCS name, Ustrlen(name),
-      0, PCRE_EOPT, ovector, nelem(ovector)) < 0)
+  if (!regex_match(regex_check_dns_names, name, -1, NULL))
     {
     DEBUG(D_dns)
       debug_printf("DNS name syntax check failed: %s (%s)\n", name,
@@ -908,8 +908,8 @@ if (dnsa->answerlen < 0) switch (h_errno)
 #ifndef STAND_ALONE
     save_domain = deliver_domain;
     deliver_domain = string_copy(name);  /* set $domain */
-    rc = match_isinlist(name, (const uschar **)&dns_again_means_nonexist, 0, NULL, NULL,
-      MCL_DOMAIN, TRUE, NULL);
+    rc = match_isinlist(name, CUSS &dns_again_means_nonexist, 0,
+      &domainlist_anchor, NULL, MCL_DOMAIN, TRUE, NULL);
     deliver_domain = save_domain;
     if (rc != OK)
       {
@@ -1066,7 +1066,7 @@ for (int i = 0; i <= dns_cname_loops; i++)
     return DNS_FAIL;
 
   /* DNS data comes from the outside, hence tainted */
-  data = store_get(256, TRUE);
+  data = store_get(256, GET_TAINTED);
   if (dn_expand(dnsa->answer, dnsa->answer + dnsa->answerlen,
       cname_rr.data, (DN_EXPAND_ARG4_TYPE)data, 256) < 0)
     return DNS_FAIL;
@@ -1149,7 +1149,7 @@ switch (type)
   case T_CSA:
     {
     uschar *srvname, *namesuff, *tld;
-    int priority, weight, port;
+    int priority, dummy_weight, port;
     int limit, rc, i;
     BOOL ipv6;
     dns_record *rr;
@@ -1203,18 +1203,7 @@ switch (type)
     If the TLD and the 2LD exist but the explicit CSA record lookup failed, then
     the AUTHORITY SOA will be the 2LD's or a subdomain thereof. */
 
-    if (rc == DNS_NOMATCH)
-      {
-      fake_dnsa_len_for_fail(dnsa, T_CSA);
-
-      for (rr = dns_next_rr(dnsa, &dnss, RESET_AUTHORITY);
-          rr; rr = dns_next_rr(dnsa, &dnss, RESET_NEXT)
-         )
-       if (rr->type != T_SOA) continue;
-       else if (strcmpic(rr->name, US"") == 0 ||
-                strcmpic(rr->name, tld) == 0) return DNS_NOMATCH;
-       else break;
-      }
+    if (rc == DNS_NOMATCH) return DNS_NOMATCH;
 
     for (i = 0; i < limit; i++)
       {
@@ -1249,7 +1238,7 @@ switch (type)
 
        /* Extract the numerical SRV fields (p is incremented) */
        GETSHORT(priority, p);
-       GETSHORT(weight, p);    weight = weight; /* compiler quietening */
+       GETSHORT(dummy_weight, p);
        GETSHORT(port, p);
 
        /* Check the CSA version number */
@@ -1305,7 +1294,7 @@ if (rr->type == T_A)
   if (p + 4 <= dnsa_lim)
     {
     /* the IP is not regarded as tainted */
-    yield = store_get(sizeof(dns_address) + 20, FALSE);
+    yield = store_get(sizeof(dns_address) + 20, GET_UNTAINTED);
     (void)sprintf(CS yield->address, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
     yield->next = NULL;
     }
@@ -1319,7 +1308,7 @@ else
     {
     struct in6_addr in6;
     for (int i = 0; i < 16; i++) in6.s6_addr[i] = rr->data[i];
-    yield = store_get(sizeof(dns_address) + 50, FALSE);
+    yield = store_get(sizeof(dns_address) + 50, GET_UNTAINTED);
     inet_ntop(AF_INET6, &in6, CS yield->address, 50);
     yield->next = NULL;
     }
@@ -1336,7 +1325,7 @@ dns_pattern_init(void)
 {
 if (check_dns_names_pattern[0] != 0 && !regex_check_dns_names)
   regex_check_dns_names =
-    regex_must_compile(check_dns_names_pattern, FALSE, TRUE);
+    regex_must_compile(check_dns_names_pattern, MCS_NOFLAGS, TRUE);
 }
 
 /* vi: aw ai sw=2