X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/d4095f83496094d7d8649cc412536f69d1cfcb6a..92583637b25b6bde926f9ca6be7b085e5ac8b1e6:/src/src/dnsbl.c diff --git a/src/src/dnsbl.c b/src/src/dnsbl.c index d3afd5cf8..ad36e8ecb 100644 --- a/src/src/dnsbl.c +++ b/src/src/dnsbl.c @@ -74,7 +74,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 +83,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. */ @@ -247,7 +248,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 +306,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 +345,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 +365,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, TRUE); store_pool = old_pool; break; } @@ -333,7 +373,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 +386,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 +399,12 @@ HDEBUG(D_dnsbl) keydomain, domain); } -return FAIL; +yield = FAIL; + +out: + +store_free_dns_answer(dnsa); +return yield; }