* 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 concerned with dnsbls */
dnsbl_cache_block *cb;
int old_pool = store_pool;
uschar * query;
-int qlen;
+int qlen, yield;
/* Construct the specific query domainname */
{
log_write(0, LOG_MAIN|LOG_PANIC, "dnslist query is too long "
"(ignored): %s...", query);
- return FAIL;
+ yield = FAIL;
+ goto out;
}
/* Look for this query in the cache. */
else
{ /* Set up a tree entry to cache the lookup */
- t = store_get(sizeof(tree_node) + qlen + 1 + 1, is_tainted(query));
+ t = store_get(sizeof(tree_node) + qlen + 1 + 1, query);
Ustrcpy(t->name, query);
- t->data.ptr = cb = store_get(sizeof(dnsbl_cache_block), FALSE);
+ t->data.ptr = cb = store_get(sizeof(dnsbl_cache_block), GET_UNTAINTED);
(void)tree_insertnode(&dnsbl_cache, t);
}
ignore IPv6 addresses. The default mask is 0, which always matches.
We change this only for IPv4 addresses in the list. */
- if (host_aton(da->address, address) == 1) mask = address[0];
+ if (host_aton(da->address, address) == 1)
+ if ((address[0] & 0xff000000) != 0x7f000000) /* 127.0.0.0/8 */
+ log_write(0, LOG_MAIN,
+ "DNS list lookup for %s at %s returned %s;"
+ " not in 127.0/8 and discarded",
+ keydomain, domain, da->address);
+
+ else
+ mask = address[0];
/* Scan the returned addresses, skipping any that are IPv6 */
match_type & MT_ALL ? "=" : "",
bitmask ? '&' : '=', iplist);
}
- return FAIL;
+ yield = FAIL;
+ goto out;
+ }
+ }
+
+ /* No address list check; discard any illegal returns and give up if
+ none remain. */
+
+ else
+ {
+ BOOL ok = FALSE;
+ for (da = cb->rhs; da; da = da->next)
+ {
+ int address[4];
+
+ if ( host_aton(da->address, address) == 1 /* ipv4 */
+ && (address[0] & 0xff000000) == 0x7f000000 /* 127.0.0.0/8 */
+ )
+ ok = TRUE;
+ else
+ log_write(0, LOG_MAIN,
+ "DNS list lookup for %s at %s returned %s;"
+ " not in 127.0/8 and discarded",
+ keydomain, domain, da->address);
+ }
+ if (!ok)
+ {
+ yield = FAIL;
+ goto out;
}
}
there is indeed an A record at the alternate domain. */
if (domain_txt != domain)
- return one_check_dnsbl(domain_txt, domain_txt, keydomain, prepend, NULL,
+ {
+ yield = one_check_dnsbl(domain_txt, domain_txt, keydomain, prepend, NULL,
FALSE, match_type, defer_return);
+ goto out;
+ }
/* If there is no alternate domain, look up a TXT record in the main domain
if it has not previously been cached. */
int len = (rr->data)[0];
if (len > 511) len = 127;
store_pool = POOL_PERM;
- cb->text = string_sprintf("%.*s", len, CUS (rr->data+1));
+ cb->text = string_copyn_taint(CUS (rr->data+1), len, GET_TAINTED);
store_pool = old_pool;
break;
}
dnslist_value = addlist;
dnslist_text = cb->text;
- return OK;
+ yield = OK;
+ goto out;
}
/* There was a problem with the DNS lookup */
defer_return == OK ? US"assumed in list" :
defer_return == FAIL ? US"assumed not in list" :
US"returned DEFER");
- return defer_return;
+ yield = defer_return;
+ goto out;
}
/* No entry was found in the DNS; continue for next domain */
keydomain, domain);
}
-return FAIL;
+yield = FAIL;
+
+out:
+
+store_free_dns_answer(dnsa);
+return yield;
}