X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/d4095f83496094d7d8649cc412536f69d1cfcb6a..a85c067ba6c6940512cf57ec213277a370d87e70:/src/src/dnsbl.c diff --git a/src/src/dnsbl.c b/src/src/dnsbl.c index d3afd5cf8..af80f6be1 100644 --- a/src/src/dnsbl.c +++ b/src/src/dnsbl.c @@ -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-only */ /* Functions concerned with dnsbls */ @@ -74,7 +75,7 @@ tree_node *t; dnsbl_cache_block *cb; int old_pool = store_pool; uschar * query; -int qlen; +int qlen, yield; /* Construct the specific query domainname */ @@ -83,7 +84,8 @@ if ((qlen = Ustrlen(query)) >= 256) { 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. */ @@ -114,9 +116,9 @@ else 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); } @@ -247,7 +249,15 @@ if (cb->rc == DNS_SUCCEED) 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 */ @@ -297,7 +307,35 @@ if (cb->rc == DNS_SUCCEED) 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; } } @@ -308,8 +346,11 @@ if (cb->rc == DNS_SUCCEED) 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. */ @@ -325,7 +366,7 @@ if (cb->rc == DNS_SUCCEED) 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; } @@ -333,7 +374,8 @@ if (cb->rc == DNS_SUCCEED) dnslist_value = addlist; dnslist_text = cb->text; - return OK; + yield = OK; + goto out; } /* There was a problem with the DNS lookup */ @@ -345,7 +387,8 @@ if (cb->rc != DNS_NOMATCH && cb->rc != DNS_NODATA) 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 */ @@ -357,7 +400,12 @@ HDEBUG(D_dnsbl) keydomain, domain); } -return FAIL; +yield = FAIL; + +out: + +store_free_dns_answer(dnsa); +return yield; }