*************************************************/
/* Copyright (c) University of Cambridge 1995 - 2018 */
-/* Copyright (c) The Exim Maintainers 2020 */
+/* Copyright (c) The Exim Maintainers 2020 - 2021 */
/* See the file NOTICE for conditions of use and distribution. */
/* Functions for interfacing with the DNS. */
{
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
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;
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;
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;
}
{
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;
}
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,
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;
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;
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++)
{
/* Extract the numerical SRV fields (p is incremented) */
GETSHORT(priority, p);
- GETSHORT(weight, p);
+ GETSHORT(dummy_weight, p);
GETSHORT(port, p);
/* Check the CSA version number */
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;
}
{
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;
}