Bug 1278 - Incomplete wildcard proof
Incomplete wildcard proof
Status: RESOLVED FIXED
Product: unbound
Classification: Unclassified
Component: server
1.6.2
x86_64 Linux
: P5 normal
Assigned To: unbound team
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2017-06-12 11:58 CEST by Vladimír Čunát
Modified: 2017-06-12 12:14 CEST (History)
2 users (show)

See Also:


Attachments
Example: captured packets for detskeoci.cz, with unbound running on 5335 port (2.44 KB, application/gzip)
2017-06-12 11:58 CEST, Vladimír Čunát
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Vladimír Čunát 2017-06-12 11:58:03 CEST
Created attachment 406 [details]
Example: captured packets for detskeoci.cz, with unbound running on 5335 port

When running this couple of queries:
$ kdig +dnssec +cd www.detskeoci.cz A
$ kdig +dnssec +cd www.detskeoci.cz AAAA

I'm getting an insufficient proof in the second answer.  In particular it's missing this record `mail.detskeoci.cz. NSEC detskeoci.cz.` that proves that www is missing and thus it's OK to use the wildcard.  Consequently, this breaks validation when forwarding to unbound (from knot-resolver).

I inspected the packets and I can see no problem in the answers from the authoritative servers; see the attachment.


The insufficient output, for simplicity:

;; ->>HEADER<<- opcode: QUERY; status: NOERROR; id: 53317
;; Flags: qr rd ra cd; QUERY: 1; ANSWER: 2; AUTHORITY: 4; ADDITIONAL: 1

;; EDNS PSEUDOSECTION:
;; Version: 0; flags: do; UDP size: 4096 B; ext-rcode: Unused

;; QUESTION SECTION:
;; www.detskeoci.cz.            IN      AAAA

;; ANSWER SECTION:
www.detskeoci.cz.       1799    IN      CNAME   detskeoci.cz.
www.detskeoci.cz.       1799    IN      RRSIG   CNAME 5 2 1800 20170621220302 20170522220302 42408 detskeoci.cz. i8Znj282sIVEdzo2mvgqIWBnJidtCrgM7Vqtre3lNhZc9RYaTFxYKC9XJJPaVYpJwNlqB6VJCrFDJCqpbhJVUzVZdJnIMfrOiysioYUtI04uDbCah+efKgdAESB1ZfuB5BFbyC3thBTvN4/R4F6aiPLPplgO/qvK5LEYEIPcx2A=

;; AUTHORITY SECTION:
detskeoci.cz.           3600    IN      SOA     ns.forpsi.net. admin.forpsi.com. 2017052301 3600 1800 2592000 3600
detskeoci.cz.           3600    IN      RRSIG   SOA 5 2 3600 20170621220302 20170522220302 42408 detskeoci.cz. BzdzZXoKb4bhXC3HaG3bcu3+tjJrHjMCwGBg5Cjp149rXQ1MnAxmmhCaR+MQySB6pgOcaVo236iyOy0SW74ZBTzK7wT2MASrmJ9U6uTH8y+LZuuQwvrSFKa0d0m1J+sjNOm08B5kzdcxXuXFRXoZ/nfctVbpn4LGojEhaKcXGuY=
detskeoci.cz.           3600    IN      NSEC    *.detskeoci.cz. A NS SOA MX TXT RRSIG NSEC DNSKEY
detskeoci.cz.           3600    IN      RRSIG   NSEC 5 2 3600 20170621220302 20170522220302 42408 detskeoci.cz. iIRcKYx9cfvtMAUDc0ujkw9GOAPHF4mvt5Z3QFQavuuPLxV2d2DBHt7EPMiC13AASwppomW4nbmx1k4M9nlGD/3PP7xfsA1A+sXzqd+YrKMmUnFPHS39oKGzxPRoHVJexlLbVJq8gcl+nvCDiF2oANcQ7SwXi0wpskLnVz82LJY=

;; Received 677 B
;; Time 2017-06-12 10:59:16 CEST
;; From ::1@5335(UDP) in 5.0 ms
Comment 1 Vladimír Čunát 2017-06-12 12:04:07 CEST
To reproduce this, it seems important to run that A query beforehand and AAAA query soon after that (before TTLs expire).
Comment 2 Wouter Wijngaards 2017-06-12 12:14:01 CEST
Hi Vladimír,

Thank you for the detailed bug report.  The issue was the wildcard cname for unbound's cache.  I have fixed this to provide the wildcard information for such CNAMEs.  The patch is below, but also contributed in to the code repository.

Best regards, Wouter


Index: services/cache/dns.c
===================================================================
--- services/cache/dns.c	(revision 4217)
+++ services/cache/dns.c	(working copy)
@@ -41,6 +41,7 @@
 #include "config.h"
 #include "iterator/iter_delegpt.h"
 #include "validator/val_nsec.h"
+#include "validator/val_utils.h"
 #include "services/cache/dns.h"
 #include "services/cache/rrset.h"
 #include "util/data/msgreply.h"
@@ -755,10 +756,16 @@
 	if( qtype != LDNS_RR_TYPE_DS &&
 	   (rrset=rrset_cache_lookup(env->rrset_cache, qname, qnamelen, 
 		LDNS_RR_TYPE_CNAME, qclass, 0, now, 0))) {
-		struct dns_msg* msg = rrset_msg(rrset, region, now, &k);
-		if(msg) {
-			lock_rw_unlock(&rrset->entry.lock);
-			return msg;
+		uint8_t* wc = NULL;
+		/* if the rrset is not a wildcard expansion, with wcname */
+		/* because, if we return that CNAME rrset on its own, it is
+		 * missing the NSEC or NSEC3 proof */
+		if(!(val_rrset_wildcard(rrset, &wc) && wc != NULL)) {
+			struct dns_msg* msg = rrset_msg(rrset, region, now, &k);
+			if(msg) {
+				lock_rw_unlock(&rrset->entry.lock);
+				return msg;
+			}
 		}
 		lock_rw_unlock(&rrset->entry.lock);
 	}