I have prepared patch that allows again queries to dnsmasq without rd
bit set. It allows queries to locally defined names even without rd bit,
but stil refuses queries to cached remote records.

I think this is important issue, could it be reviewed?

On 4/12/19 11:29 AM, Petr Mensik wrote:
> Hi,
> 
> I was checking latest dnsmasq reponses to non-recursive queries. It
> seems strange, it does not work as it should. Originally, I was checking
> NXDOMAIN issue, reported on Fedora bug #1647464.
> 
> But this issue seems important, it makes difficult to use dnsmasq with
> bigger resolvers like bind or unbound. It does skip even local defined
> hosts, which I think should be responded always even without recursion
> bit set.
> 
> This was tested first on released dnsmasq 2.80 in Fedora rawhide, then
> on git compilation with version v2.80-53-g343b7b4. Both seems to be
> incorrect.
> 
> # grep -w qeos-1 /etc/hosts
> 172.16.36.1    qeos-1
> 
> # dig @127.0.0.1 +norec qeos-1
> 
> ; <<>> DiG 9.11.5-P4-RedHat-9.11.5-13.P4.fc31 <<>> @127.0.0.1 +norec qeos-1
> ; (1 server found)
> ;; global options: +cmd
> ;; Got answer:
> ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50085
> ;; flags: qr ra; QUERY: 1, ANSWER: 0, AUTHORITY: 13, ADDITIONAL: 27
> 
> ;; OPT PSEUDOSECTION:
> ; EDNS: version: 0, flags:; udp: 4096
> ;; QUESTION SECTION:
> ;qeos-1.                              IN      A
> 
> ;; AUTHORITY SECTION:
> .                     498600  IN      NS      b.root-servers.net.
> .                     498600  IN      NS      m.root-servers.net.
> .                     498600  IN      NS      e.root-servers.net.
> .                     498600  IN      NS      f.root-servers.net.
> .                     498600  IN      NS      k.root-servers.net.
> .                     498600  IN      NS      l.root-servers.net.
> .                     498600  IN      NS      c.root-servers.net.
> .                     498600  IN      NS      d.root-servers.net.
> .                     498600  IN      NS      i.root-servers.net.
> .                     498600  IN      NS      g.root-servers.net.
> .                     498600  IN      NS      a.root-servers.net.
> .                     498600  IN      NS      h.root-servers.net.
> .                     498600  IN      NS      j.root-servers.net.
> 
> ;; ADDITIONAL SECTION:
> e.root-servers.net.   153695  IN      A       192.203.230.10
> e.root-servers.net.   153695  IN      AAAA    2001:500:a8::e
> h.root-servers.net.   153695  IN      A       198.97.190.53
> h.root-servers.net.   153695  IN      AAAA    2001:500:1::53
> l.root-servers.net.   585734  IN      A       199.7.83.42
> l.root-servers.net.   153695  IN      AAAA    2001:500:9f::42
> i.root-servers.net.   585699  IN      A       192.36.148.17
> i.root-servers.net.   153695  IN      AAAA    2001:7fe::53
> a.root-servers.net.   597264  IN      A       198.41.0.4
> a.root-servers.net.   597264  IN      AAAA    2001:503:ba3e::2:30
> d.root-servers.net.   153695  IN      A       199.7.91.13
> d.root-servers.net.   153695  IN      AAAA    2001:500:2d::d
> c.root-servers.net.   153695  IN      A       192.33.4.12
> c.root-servers.net.   153695  IN      AAAA    2001:500:2::c
> b.root-servers.net.   585695  IN      A       199.9.14.201
> b.root-servers.net.   153695  IN      AAAA    2001:500:200::b
> j.root-servers.net.   153695  IN      A       192.58.128.30
> j.root-servers.net.   153695  IN      AAAA    2001:503:c27::2:30
> k.root-servers.net.   586670  IN      A       193.0.14.129
> k.root-servers.net.   153695  IN      AAAA    2001:7fd::1
> g.root-servers.net.   153695  IN      A       192.112.36.4
> g.root-servers.net.   153695  IN      AAAA    2001:500:12::d0d
> m.root-servers.net.   153695  IN      A       202.12.27.33
> m.root-servers.net.   153695  IN      AAAA    2001:dc3::35
> f.root-servers.net.   153695  IN      A       192.5.5.241
> f.root-servers.net.   153695  IN      AAAA    2001:500:2f::f
> 
> # dig @127.0.0.1 +rec qeos-1
> ; <<>> DiG 9.11.5-P4-RedHat-9.11.5-13.P4.fc31 <<>> @127.0.0.1 +rec qeos-1
> ; (1 server found)
> ;; global options: +cmd
> ;; Got answer:
> ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50355
> ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
> 
> ;; OPT PSEUDOSECTION:
> ; EDNS: version: 0, flags:; udp: 4096
> ;; QUESTION SECTION:
> ;qeos-1.                              IN      A
> 
> ;; ANSWER SECTION:
> qeos-1.                       0       IN      A       172.16.36.1
> 
> ;; Query time: 0 msec
> ;; SERVER: 127.0.0.1#53(127.0.0.1)
> ;; WHEN: Pá dub 12 05:23:57 EDT 2019
> ;; MSG SIZE  rcvd: 51
> 
> 1. https://bugzilla.redhat.com/show_bug.cgi?id=1647464
> 

-- 
Petr Menšík
Software Engineer
Red Hat, http://www.redhat.com/
email: pemen...@redhat.com  PGP: 65C6C973
From e3aa12144191713f06d341d08ab1f541e0bb6927 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemen...@redhat.com>
Date: Fri, 12 Apr 2019 15:29:00 +0200
Subject: [PATCH] Restore ability to answer non-recursive requests

Instead, check only local configured entries are answered without
rdbit set. All cached replies are still denied, but locally configured
names are available with both recursion and without it.

Fixes commit 4139298d287eb5c57f4aa53c459cb02fc5be2495 unintended
behaviour.
---
 src/rfc1035.c | 28 +++++++++++++++-------------
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/src/rfc1035.c b/src/rfc1035.c
index 79270ef..961e77a 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -1291,7 +1291,11 @@ static unsigned long crec_ttl(struct crec *crecp, time_t now)
   else
     return daemon->max_ttl;
 }
-  
+
+static int cache_validated(const struct crec *crecp)
+{
+  return (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK));
+}
 
 /* return zero if we can't answer from cache, or packet size if we can */
 size_t answer_request(struct dns_header *header, char *limit, size_t qlen,  
@@ -1310,12 +1314,12 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
   int nxdomain = 0, notimp = 0, auth = 1, trunc = 0, sec_data = 1;
   struct mx_srv_record *rec;
   size_t len;
+  int rd_bit = (header->hb3 & HB3_RD);
 
   /* never answer queries with RD unset, to avoid cache snooping. */
-  if (!(header->hb3 & HB3_RD) ||
-      ntohs(header->ancount) != 0 ||
+  if (ntohs(header->ancount) != 0 ||
       ntohs(header->nscount) != 0 ||
-      ntohs(header->qdcount) == 0 || 
+      ntohs(header->qdcount) == 0 ||
       OPCODE(header) != QUERY )
     return 0;
 
@@ -1501,9 +1505,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
 		  /* Don't use cache when DNSSEC data required, unless we know that
 		     the zone is unsigned, which implies that we're doing
 		     validation. */
-		  if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || 
-		      !do_bit || 
-		      (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))
+		  if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
+		      (rd_bit && (!do_bit || cache_validated(crecp)) ))
 		    {
 		      do 
 			{ 
@@ -1686,8 +1689,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
 
 		  /* If the client asked for DNSSEC  don't use cached data. */
 		  if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
-		      !do_bit ||
-		      (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))
+		      (rd_bit && (!do_bit || cache_validated(crecp)) ))
 		    do
 		      { 
 			/* don't answer wildcard queries with data not from /etc/hosts
@@ -1770,8 +1772,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
 	  if (qtype == T_CNAME || qtype == T_ANY)
 	    {
 	      if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME | (dryrun ? F_NO_RR : 0))) &&
-		  (qtype == T_CNAME || (crecp->flags & F_CONFIG)) &&
-		  ((crecp->flags & F_CONFIG) || !do_bit || (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))))
+		  ((qtype == T_CNAME && rd_bit) || (crecp->flags & F_CONFIG)) &&
+		  ((crecp->flags & F_CONFIG) || (!do_bit || cache_validated(crecp))))
 		{
 		  if (!(crecp->flags & F_DNSSECOK))
 		    sec_data = 0;
@@ -1810,7 +1812,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
 		      }
 		  }
 	      
-	      if (!found && (option_bool(OPT_SELFMX) || option_bool(OPT_LOCALMX)) && 
+	      if (!found && (option_bool(OPT_SELFMX) || option_bool(OPT_LOCALMX)) &&
 		  cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP | F_NO_RR))
 		{ 
 		  ans = 1;
@@ -1873,7 +1875,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
 		{
 		cname_srv_restart:
 		  if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME | F_SRV | (dryrun ? F_NO_RR : 0))) &&
-		      (!do_bit || (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))))
+		      rd_bit && (!do_bit || cache_validated(crecp)) )
 		    {
 		      if (!(crecp->flags & F_DNSSECOK))
 			sec_data = 0;
-- 
2.20.1

_______________________________________________
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss

Reply via email to