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