From 5bbea085d0feed21ed0001ae3798659ddee17756 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Sat, 18 Jan 2025 22:40:30 +0000 Subject: [PATCH] Fix subtle bug in arbitrary-RR caching. If the client asks for DNSSEC RRs via the do bit, and we have an answer cached, we can only return the cached answer if the RR was not validated. This is because we don't the extra info (RRSIGS, NSECs) for a complete validated answer. In that case we have to forward again. This bug was that the "is the cache entry validated" test was in an outer loop rather than an inner one. A cache hit on a different RRtype that wasn't validated would satify the condition to use the cache, even if the cache entry for the required RRtype didn't. The only time when there can be a mix of validated and non validated cache entries for the same domain is when most are not validated, but one is a negative cache for a DS record. This bug took a long time to find. --- src/rfc1035.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/rfc1035.c b/src/rfc1035.c index 8a23e61..b62a342 100644 --- a/src/rfc1035.c +++ b/src/rfc1035.c @@ -1561,8 +1561,6 @@ static unsigned long crec_ttl(struct crec *crecp, time_t now) static int cache_validated(const struct crec *crecp) { - /* return 0; */ - return (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)); } @@ -2159,19 +2157,19 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen, if (!ans) { - if ((crecp = cache_find_by_name(NULL, name, now, F_RR | F_NXDOMAIN)) && - rd_bit && (!do_bit || cache_validated(crecp))) + if ((crecp = cache_find_by_name(NULL, name, now, F_RR | F_NXDOMAIN)) && rd_bit) do { int flags = crecp->flags; unsigned short rrtype; - + if (flags & F_KEYTAG) rrtype = crecp->addr.rrblock.rrtype; else rrtype = crecp->addr.rrdata.rrtype; - if ((flags & F_NXDOMAIN) || rrtype == qtype) + if (((flags & F_NXDOMAIN) || rrtype == qtype) && + (!do_bit || cache_validated(crecp))) { char *rrdata = NULL; unsigned short rrlen = 0;