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