Hey Simon,

I tried your recent extended DNS errors (EDE) addition. I tested the
following well-know DNSSEC testing domains:

- dnssec-failed.org: "BOGUS (EDE: DNSKEY missing)"
- rhybar.cz: "BOGUS (EDE: DNSSEC signature expired)"
- sigfail.verteiltesysteme.net: "BOGUS"

Interestingly, sigfail.verteiltesysteme.net did not show any additional
information added to the BOGUS result. The validation failed here
because none of the DNSKEY records validate the A RRset.

My patch extends the EDE facility you implemented to allow for
additional errors not standardized in RFC 8914. This may be handy in
other places of the DNSSEC validation process, too. I could imagine
extending this further by, e.g., "bad packet" or "upstream SERVFAIL"
errors.

Before: 
> query[A] sigfail.verteiltesysteme.net from 127.0.0.1
> forwarded sigfail.verteiltesysteme.net to 127.0.0.1
> validation result is BOGUS

New:
> query[A] sigfail.verteiltesysteme.net from 127.0.0.1
> forwarded sigfail.verteiltesysteme.net to 127.0.0.1
> validation result is BOGUS (EDE: no matching key found)

This dnsmasq-internal EDE is not sent to clients. It may be debated if
this is intended. Following RFC 8914, Sec. 4.1, they can be included as
EXTRA-TEXT for EDE code 0. This is not included in this patch but could
be easily added in a follow-up.

Best,
Dominik
From c7b5dc9c5dc16c9ea9aa6e76d4f49c842645e3e1 Mon Sep 17 00:00:00 2001
From: Dominik DL6ER <dl...@dl6er.de>
Date: Sun, 27 Jun 2021 13:05:47 +0200
Subject: [PATCH] Add extended DNS error message in case no varifying key was
 found (result is BOGUS)

Signed-off-by: Dominik DL6ER <dl...@dl6er.de>
---
 src/cache.c        | 9 +++++----
 src/dns-protocol.h | 4 +++-
 src/dnsmasq.h      | 1 +
 src/dnssec.c       | 7 +++++--
 src/forward.c      | 6 +++---
 5 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/src/cache.c b/src/cache.c
index a4acad6..e09afb1 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -1890,6 +1890,7 @@ static char *edestr(int ede)
     case EDE_NO_AUTH:                     return "no reachable authority";
     case EDE_NETERR:                      return "network error";
     case EDE_INVALID_DATA:                return "invalid data";
+    case EDE_NO_MATCH:                    return "no matching key found";
     default:                              return "unknown";
     }
 }
@@ -1922,10 +1923,10 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg)
 	  else
 	    sprintf(daemon->addrbuff, "%u", rcode);
 
-	  if (addr->log.ede != -1)
+	  if (addr->log.ede != EDE_UNSET)
 	    {
 	      extra = daemon->addrbuff;
-	      sprintf(extra, " (EDE:%s)", edestr(addr->log.ede));
+	      sprintf(extra, " (EDE: %s)", edestr(addr->log.ede));
 	    }
 	}
       else
@@ -1973,10 +1974,10 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg)
     source = "reply";
   else if (flags & F_SECSTAT)
     {
-      if (addr && addr->log.ede != -1)
+      if (addr && addr->log.ede != EDE_UNSET)
 	{
 	  extra = daemon->addrbuff;
-	  sprintf(extra, " (EDE:%s)", edestr(addr->log.ede));
+	  sprintf(extra, " (EDE: %s)", edestr(addr->log.ede));
 	}
       source = "validation";
       dest = arg;
diff --git a/src/dns-protocol.h b/src/dns-protocol.h
index 01d5f8f..fff526c 100644
--- a/src/dns-protocol.h
+++ b/src/dns-protocol.h
@@ -85,7 +85,9 @@
 #define EDNS0_OPTION_NOMCPEID       65074 /* Nominum temporary assignment */
 #define EDNS0_OPTION_UMBRELLA       20292 /* Cisco Umbrella temporary assignment */
 
-/* RFC-8914 extended errors */
+/* RFC-8914 extended errors, negative values are our definitions */
+#define EDE_NO_MATCH       -2
+#define EDE_UNSET          -1
 #define EDE_OTHER           0  /* Other */
 #define EDE_USUPDNSKEY      1  /* Unsupported DNSKEY algo */
 #define EDE_USUPDS          2  /* Unsupported DS Digest */
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 939e41e..d20ffcb 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -707,6 +707,7 @@ struct hostsfile {
 #define DNSSEC_FAIL_NONSEC      0x0040 /* No NSEC */
 #define DNSSEC_FAIL_NODSSUP     0x0080 /* no supported DS algo. */
 #define DNSSEC_FAIL_NOKEY       0x0100 /* no DNSKEY */
+#define DNSSEC_FAIL_NOMATCH     0x2000 /* no matching key */
 
 #define STAT_ISEQUAL(a, b)  (((a) & 0xffff0000) == (b))
 
diff --git a/src/dnssec.c b/src/dnssec.c
index 3152d83..3e1c205 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -744,7 +744,8 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
 	}
     }
 
-  return STAT_BOGUS | failflags;
+  /* If we reach this point, no verifying key was found */
+  return STAT_BOGUS | failflags | DNSSEC_FAIL_NOMATCH;
 }
  
 
@@ -2192,7 +2193,9 @@ int errflags_to_ede(int status)
     return EDE_DNSSEC_IND;
   else if (status & DNSSEC_FAIL_NOSIG)
     return EDE_NO_RRSIG;
+  else if(status & DNSSEC_FAIL_NOMATCH)
+	return -2; // no matching key
   else
-    return -1;
+    return -1; // no EDE available
 }
 #endif /* HAVE_DNSSEC */
diff --git a/src/forward.c b/src/forward.c
index 7647b13..5d0bad9 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -537,7 +537,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
 	{
 	  u16 swap = htons((u16)ede);
 
-	  if (ede != -1)
+	  if (ede > EDE_UNSET)
 	    plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 0);
 	  else
 	    plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
@@ -734,7 +734,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
     }
 #endif
 
-  if (pheader && ede != -1)
+  if (pheader && ede > EDE_UNSET)
     {
       u16 swap = htons((u16)ede);
       n = add_pseudoheader(header, n, limit, daemon->edns_pktsz, EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 1);
@@ -2136,7 +2136,7 @@ unsigned char *tcp_request(int confd, time_t now,
 	    {
 	      u16 swap = htons((u16)ede);
 
-	       if (ede != -1)
+	       if (ede > EDE_UNSET)
 		 m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536, daemon->edns_pktsz, EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 0);
 	       else
 		 m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
-- 
2.25.1

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

Reply via email to