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