8e0267
From 10642f9fb350e118d88e995b8dfa2badc7be1c30 Mon Sep 17 00:00:00 2001
8e0267
From: Petr Mensik <pemensik@redhat.com>
8e0267
Date: Wed, 11 Dec 2019 13:41:57 +0100
8e0267
Subject: [PATCH] Restore ability to answer non-recursive requests
8e0267
8e0267
Instead, check only local configured entries are answered without
8e0267
rdbit set. All cached replies are still denied, but locally configured
8e0267
names are available with both recursion and without it.
8e0267
---
8e0267
 src/rfc1035.c | 27 ++++++++++++++-------------
8e0267
 1 file changed, 14 insertions(+), 13 deletions(-)
8e0267
8e0267
diff --git a/src/rfc1035.c b/src/rfc1035.c
8e0267
index 6b3bb27..6a7c154 100644
8e0267
--- a/src/rfc1035.c
8e0267
+++ b/src/rfc1035.c
8e0267
@@ -1262,7 +1262,11 @@ static unsigned long crec_ttl(struct crec *crecp, time_t now)
8e0267
   else
8e0267
     return daemon->max_ttl;
8e0267
 }
8e0267
-  
8e0267
+
8e0267
+static int cache_validated(const struct crec *crecp)
8e0267
+{
8e0267
+  return (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK));
8e0267
+}
8e0267
 
8e0267
 /* return zero if we can't answer from cache, or packet size if we can */
8e0267
 size_t answer_request(struct dns_header *header, char *limit, size_t qlen,  
8e0267
@@ -1281,6 +1285,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
8e0267
   int nxdomain = 0, auth = 1, trunc = 0, sec_data = 1;
8e0267
   struct mx_srv_record *rec;
8e0267
   size_t len;
8e0267
+  int rd_bit;
8e0267
   // Make sure we do not underflow here too.
8e0267
   if (qlen > (limit - ((char *)header))) return 0;
8e0267
 
8e0267
@@ -1290,10 +1295,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
8e0267
       OPCODE(header) != QUERY )
8e0267
     return 0;
8e0267
 
8e0267
-  /* always servfail queries with RD unset, to avoid cache snooping. */
8e0267
-  if (!(header->hb3 & HB3_RD))
8e0267
-    return setup_reply(header, qlen, NULL, F_SERVFAIL, 0);
8e0267
-  
8e0267
+  rd_bit = (header->hb3 & HB3_RD);
8e0267
+
8e0267
   /* Don't return AD set if checking disabled. */
8e0267
   if (header->hb4 & HB4_CD)
8e0267
     sec_data = 0;
8e0267
@@ -1458,9 +1461,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
8e0267
 		  /* Don't use cache when DNSSEC data required, unless we know that
8e0267
 		     the zone is unsigned, which implies that we're doing
8e0267
 		     validation. */
8e0267
-		  if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || 
8e0267
-		      !do_bit || 
8e0267
-		      (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))
8e0267
+		  if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
8e0267
+		      (rd_bit && (!do_bit || cache_validated(crecp)) ))
8e0267
 		    {
8e0267
 		      do 
8e0267
 			{ 
8e0267
@@ -1657,8 +1659,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
8e0267
 
8e0267
 		  /* If the client asked for DNSSEC  don't use cached data. */
8e0267
 		  if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
8e0267
-		      !do_bit ||
8e0267
-		      (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))
8e0267
+		      (rd_bit && (!do_bit || cache_validated(crecp)) ))
8e0267
 		    do
8e0267
 		      { 
8e0267
 			/* don't answer wildcard queries with data not from /etc/hosts
8e0267
@@ -1741,8 +1742,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
8e0267
 	  if (qtype == T_CNAME || qtype == T_ANY)
8e0267
 	    {
8e0267
 	      if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME | (dryrun ? F_NO_RR : 0))) &&
8e0267
-		  (qtype == T_CNAME || (crecp->flags & F_CONFIG)) &&
8e0267
-		  ((crecp->flags & F_CONFIG) || !do_bit || (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))))
8e0267
+		  ((qtype == T_CNAME && rd_bit) || (crecp->flags & F_CONFIG)) &&
8e0267
+		  ((crecp->flags & F_CONFIG) || (!do_bit || cache_validated(crecp))))
8e0267
 		{
8e0267
 		  if (!(crecp->flags & F_DNSSECOK))
8e0267
 		    sec_data = 0;
8e0267
@@ -1780,7 +1781,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
8e0267
 		    }
8e0267
 		  }
8e0267
 	      
8e0267
-	      if (!found && (option_bool(OPT_SELFMX) || option_bool(OPT_LOCALMX)) && 
8e0267
+	      if (!found && (option_bool(OPT_SELFMX) || option_bool(OPT_LOCALMX)) &&
8e0267
 		  cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP | F_NO_RR))
8e0267
 		{ 
8e0267
 		  ans = 1;
8e0267
-- 
8e0267
2.21.0
8e0267