Blame SOURCES/dnsmasq-2.80-dnssec.patch

85f98a
From a997ca0da044719a0ce8a232d14da8b30022592b Mon Sep 17 00:00:00 2001
85f98a
From: Simon Kelley <simon@thekelleys.org.uk>
85f98a
Date: Fri, 29 Jun 2018 14:39:41 +0100
85f98a
Subject: [PATCH] Fix sometimes missing DNSSEC RRs when DNSSEC validation not
85f98a
 enabled.
85f98a
85f98a
Dnsmasq does pass on the do-bit, and return DNSSEC RRs, irrespective
85f98a
of of having DNSSEC validation compiled in or enabled.
85f98a
85f98a
The thing to understand here is that the cache does not store all the
85f98a
DNSSEC RRs, and dnsmasq doesn't have the (very complex) logic required
85f98a
to determine the set of DNSSEC RRs required in an answer. Therefore if
85f98a
the client wants the DNSSEC RRs, the query can not be answered from
85f98a
the cache. When DNSSEC validation is enabled, any query with the
85f98a
do-bit set is never answered from the cache, unless the domain is
85f98a
known not to be signed: the query is always forwarded. This ensures
85f98a
that the DNSEC RRs are included.
85f98a
85f98a
The same thing should be true when DNSSEC validation is not enabled,
85f98a
but there's a bug in the logic.
85f98a
85f98a
line 1666 of src/rfc1035.c looks like this
85f98a
85f98a
 if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !do_bit || !(crecp->flags & F_DNSSECOK))
85f98a
85f98a
{ ...answer from cache ... }
85f98a
85f98a
So local stuff (hosts, DHCP, ) get answered. If the do_bit is not set
85f98a
then the query is answered, and if the domain is known not to be
85f98a
signed, the query is answered.
85f98a
85f98a
Unfortunately, if DNSSEC validation is not turned on then the
85f98a
F_DNSSECOK bit is not valid, and it's always zero, so the question
85f98a
always gets answered from the cache, even when the do-bit is set.
85f98a
85f98a
This code should look like that at line 1468, dealing with PTR queries
85f98a
85f98a
  if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
85f98a
      !do_bit ||
85f98a
      (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))
85f98a
85f98a
where the F_DNSSECOK bit is only used when validation is enabled.
85f98a
---
85f98a
 src/rfc1035.c | 6 ++++--
85f98a
 1 file changed, 4 insertions(+), 2 deletions(-)
85f98a
85f98a
diff --git a/src/rfc1035.c b/src/rfc1035.c
85f98a
index ebb1f36..580f5ef 100644
85f98a
--- a/src/rfc1035.c
85f98a
+++ b/src/rfc1035.c
85f98a
@@ -1663,7 +1663,9 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
85f98a
 		    }
85f98a
 
85f98a
 		  /* If the client asked for DNSSEC  don't use cached data. */
85f98a
-		  if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !do_bit || !(crecp->flags & F_DNSSECOK))
85f98a
+		  if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
85f98a
+		      !do_bit ||
85f98a
+		      (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))
85f98a
 		    do
85f98a
 		      { 
85f98a
 			/* don't answer wildcard queries with data not from /etc/hosts
85f98a
@@ -1747,7 +1749,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
85f98a
 	    {
85f98a
 	      if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME | (dryrun ? F_NO_RR : 0))) &&
85f98a
 		  (qtype == T_CNAME || (crecp->flags & F_CONFIG)) &&
85f98a
-		  ((crecp->flags & F_CONFIG) || !do_bit || !(crecp->flags & F_DNSSECOK)))
85f98a
+		  ((crecp->flags & F_CONFIG) || !do_bit || (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))))
85f98a
 		{
85f98a
 		  if (!(crecp->flags & F_DNSSECOK))
85f98a
 		    sec_data = 0;
85f98a
-- 
85f98a
2.14.4
85f98a