From 29ae3083981ea82f535f77ea54bbd538f1224a9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= Date: Fri, 12 Apr 2019 15:29:00 +0200 Subject: [PATCH] Restore ability to answer non-recursive requests Instead, check only local configured entries are answered without rdbit set. All cached replies are still denied, but locally configured names are available with both recursion and without it. Fixes commit 4139298d287eb5c57f4aa53c459cb02fc5be2495 unintended behaviour. --- src/rfc1035.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/rfc1035.c b/src/rfc1035.c index 6054f3b..f1edc45 100644 --- a/src/rfc1035.c +++ b/src/rfc1035.c @@ -1301,7 +1301,11 @@ static unsigned long crec_ttl(struct crec *crecp, time_t now) else return daemon->max_ttl; } - + +static int cache_validated(const struct crec *crecp) +{ + return (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)); +} /* return zero if we can't answer from cache, or packet size if we can */ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, @@ -1320,12 +1324,12 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, int nxdomain = 0, notimp = 0, auth = 1, trunc = 0, sec_data = 1; struct mx_srv_record *rec; size_t len; + int rd_bit = (header->hb3 & HB3_RD); /* never answer queries with RD unset, to avoid cache snooping. */ - if (!(header->hb3 & HB3_RD) || - ntohs(header->ancount) != 0 || + if (ntohs(header->ancount) != 0 || ntohs(header->nscount) != 0 || - ntohs(header->qdcount) == 0 || + ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY ) return 0; @@ -1372,9 +1376,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, /* If the client asked for DNSSEC don't use cached data. */ if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || - !do_bit || - (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))) - + (rd_bit && (!do_bit || cache_validated(crecp)))) { if (crecp->flags & F_CONFIG || qtype == T_CNAME) ans = 1; @@ -1543,9 +1545,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, /* Don't use cache when DNSSEC data required, unless we know that the zone is unsigned, which implies that we're doing validation. */ - if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || - !do_bit || - (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))) + if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || + (rd_bit && (!do_bit || cache_validated(crecp)) )) { do { @@ -1726,8 +1727,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, /* If the client asked for DNSSEC don't use cached data. */ if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || - !do_bit || - (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))) + (rd_bit && (!do_bit || cache_validated(crecp)) )) do { /* don't answer wildcard queries with data not from /etc/hosts @@ -1808,7 +1808,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, } } - if (!found && (option_bool(OPT_SELFMX) || option_bool(OPT_LOCALMX)) && + if (!found && (option_bool(OPT_SELFMX) || option_bool(OPT_LOCALMX)) && cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP | F_NO_RR)) { ans = 1; @@ -1870,7 +1870,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, if (!found) { if ((crecp = cache_find_by_name(NULL, name, now, F_SRV | (dryrun ? F_NO_RR : 0))) && - (!do_bit || (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))) + rd_bit && (!do_bit || (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))) { if (!(crecp->flags & F_DNSSECOK)) sec_data = 0;