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