]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Fix auth nsec3 code (#1280)
authorYorgos Thessalonikefs <yorgos@nlnetlabs.nl>
Mon, 12 May 2025 12:26:47 +0000 (14:26 +0200)
committerGitHub <noreply@github.com>
Mon, 12 May 2025 12:26:47 +0000 (14:26 +0200)
- Fix NSEC3 code to not break on broken auth zones that include unsigned
  out of zone (above apex) data. Could lead to hang while trying to
  prove a wildcard answer.
  Reported by Dmitrii Kuvaiskii from Amazon Web Services.

- Tests for NSEC3 auth zones with out of zone data.

services/authzone.c
testcode/unitdname.c
testdata/auth_nsec3_ent_with_out_of_zone_data.rpl [new file with mode: 0644]
testdata/auth_nsec3_wild_with_out_of_zone_data.rpl [new file with mode: 0644]
util/data/dname.c
util/data/dname.h

index 3c3dc9ad05d9fab4c829343cf7f2aee890ebd40d..7d1df032e2d23f4f139c3bf0b2a180f63a5c9622 100644 (file)
@@ -2413,14 +2413,12 @@ az_find_wildcard(struct auth_zone* z, struct query_info* qinfo,
        if(!dname_subdomain_c(nm, z->name))
                return NULL; /* out of zone */
        while((node=az_find_wildcard_domain(z, nm, nmlen))==NULL) {
-               /* see if we can go up to find the wildcard */
                if(nmlen == z->namelen)
                        return NULL; /* top of zone reached */
                if(ce && nmlen == ce->namelen)
                        return NULL; /* ce reached */
-               if(dname_is_root(nm))
-                       return NULL; /* cannot go up */
-               dname_remove_label(&nm, &nmlen);
+               if(!dname_remove_label_limit_len(&nm, &nmlen, z->namelen))
+                       return NULL; /* can't go up */
        }
        return node;
 }
@@ -2442,9 +2440,8 @@ az_find_candidate_ce(struct auth_zone* z, struct query_info* qinfo,
        n = az_find_name(z, nm, nmlen);
        /* delete labels and go up on name */
        while(!n) {
-               if(dname_is_root(nm))
-                       return NULL; /* cannot go up */
-               dname_remove_label(&nm, &nmlen);
+               if(!dname_remove_label_limit_len(&nm, &nmlen, z->namelen))
+                       return NULL; /* can't go up */
                n = az_find_name(z, nm, nmlen);
        }
        return n;
@@ -2456,8 +2453,7 @@ az_domain_go_up(struct auth_zone* z, struct auth_data* n)
 {
        uint8_t* nm = n->name;
        size_t nmlen = n->namelen;
-       while(!dname_is_root(nm)) {
-               dname_remove_label(&nm, &nmlen);
+       while(dname_remove_label_limit_len(&nm, &nmlen, z->namelen)) {
                if((n=az_find_name(z, nm, nmlen)) != NULL)
                        return n;
        }
@@ -2788,9 +2784,9 @@ az_find_nsec_cover(struct auth_zone* z, struct auth_data** node)
        /* but there could be glue, and if this is node, then it has no NSEC.
         * Go up to find nonglue (previous) NSEC-holding nodes */
        while((rrset=az_domain_rrset(*node, LDNS_RR_TYPE_NSEC)) == NULL) {
-               if(dname_is_root(nm)) return NULL;
                if(nmlen == z->namelen) return NULL;
-               dname_remove_label(&nm, &nmlen);
+               if(!dname_remove_label_limit_len(&nm, &nmlen, z->namelen))
+                       return NULL; /* can't go up */
                /* adjust *node for the nsec rrset to find in */
                *node = az_find_name(z, nm, nmlen);
        }
@@ -3018,12 +3014,9 @@ az_nsec3_find_ce(struct auth_zone* z, uint8_t** cenm, size_t* cenmlen,
        struct auth_data* node;
        while((node = az_nsec3_find_exact(z, *cenm, *cenmlen,
                algo, iter, salt, saltlen)) == NULL) {
-               if(*cenmlen == z->namelen) {
-                       /* next step up would take us out of the zone. fail */
-                       return NULL;
-               }
+               if(!dname_remove_label_limit_len(cenm, cenmlen, z->namelen))
+                       return NULL; /* can't go up */
                *no_exact_ce = 1;
-               dname_remove_label(cenm, cenmlen);
        }
        return node;
 }
@@ -3340,7 +3333,8 @@ az_generate_wildcard_answer(struct auth_zone* z, struct query_info* qinfo,
        } else if(ce) {
                uint8_t* wildup = wildcard->name;
                size_t wilduplen= wildcard->namelen;
-               dname_remove_label(&wildup, &wilduplen);
+               if(!dname_remove_label_limit_len(&wildup, &wilduplen, z->namelen))
+                       return 0; /* can't go up */
                if(!az_add_nsec3_proof(z, region, msg, wildup,
                        wilduplen, msg->qinfo.qname,
                        msg->qinfo.qname_len, 0, insert_ce, 1, 0))
index 08a2dbad774d4acfa4fda4075aa11b2374ede266..32a9a5fdca15b9227006c18a34fb3096c49bc64c 100644 (file)
@@ -476,6 +476,23 @@ dname_test_removelabel(void)
        unit_assert( l == 1 );
 }
 
+/** test dname_remove_label_limit_len */
+static void
+dname_test_removelabellimitlen(void)
+{
+       uint8_t* orig = (uint8_t*)"\007example\003com\000";
+       uint8_t* n = orig;
+       size_t l = 13;
+       size_t lenlimit = 5; /* com.*/
+       unit_show_func("util/data/dname.c", "dname_remove_label_limit_len");
+       unit_assert(dname_remove_label_limit_len(&n, &l, lenlimit) == 1);
+       unit_assert( n == orig+8 );
+       unit_assert( l == 5 );
+       unit_assert(dname_remove_label_limit_len(&n, &l, lenlimit) == 0);
+       unit_assert( n == orig+8 );
+       unit_assert( l == 5 );
+}
+
 /** test dname_signame_label_count */
 static void
 dname_test_sigcount(void)
@@ -1024,6 +1041,7 @@ void dname_test(void)
        dname_test_subdomain();
        dname_test_isroot();
        dname_test_removelabel();
+       dname_test_removelabellimitlen();
        dname_test_sigcount();
        dname_test_iswild();
        dname_test_canoncmp();
diff --git a/testdata/auth_nsec3_ent_with_out_of_zone_data.rpl b/testdata/auth_nsec3_ent_with_out_of_zone_data.rpl
new file mode 100644 (file)
index 0000000..3381515
--- /dev/null
@@ -0,0 +1,228 @@
+; config options
+server:
+       target-fetch-policy: "0 0 0 0 0"
+
+auth-zone:
+       name: "unbound-auth-test.nlnetlabs.nl."
+       ## zonefile (or none).
+       ## zonefile: "example.com.zone"
+       ## master by IP address or hostname
+       ## can list multiple masters, each on one line.
+       ## master:
+       ## url for http fetch
+       ## url:
+       ## queries from downstream clients get authoritative answers.
+       ## for-downstream: yes
+       for-downstream: yes
+       ## queries are used to fetch authoritative answers from this zone,
+       ## instead of unbound itself sending queries there.
+       ## for-upstream: yes
+       for-upstream: yes
+       ## on failures with for-upstream, fallback to sending queries to
+       ## the authority servers
+       ## fallback-enabled: no
+
+       ## this line generates zonefile: \n"/tmp/xxx.example.com"\n
+       zonefile:
+TEMPFILE_NAME unbound-auth-test.nlnetlabs.nl
+       ## this is the inline file /tmp/xxx.unbound-auth-test.nlnetlabs.nl
+       ## the tempfiles are deleted when the testrun is over.
+TEMPFILE_CONTENTS unbound-auth-test.nlnetlabs.nl
+;; Zone: unbound-auth-test.nlnetlabs.nl.
+;
+unbound-auth-test.nlnetlabs.nl.        3600    IN      SOA     ns.nlnetlabs.nl. ralph.nlnetlabs.nl. 1554201247 14400 3600 604800 3600
+unbound-auth-test.nlnetlabs.nl.        3600    IN      RRSIG   SOA 13 3 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. NLFcC2oet+HC+1dhT4D/2JJFIcMiRtTM81KwvT7u8ybF3iDE4bnyrILvQk8DsizpYKwk+D3J3tMC3TV5+//qFw==
+;; Out of zone record that shouldn't break NSEC3 proofs.
+;; There was a bug that would keep removing labels and use this out of zone
+;; record.
+nlnetlabs.nl. 3600 IN NS ns.nlnetlabs.nl.
+;
+unbound-auth-test.nlnetlabs.nl.        3600    IN      NS      ns.nlnetlabs.nl.
+unbound-auth-test.nlnetlabs.nl.        3600    IN      RRSIG   NS 13 3 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. Gm0UF77ljiInG4/HZ6Tkzx7z9N45WwwmbBt9KxeN3z1BkdBLiy10Du71ZBFLP71b+USs1rv5SJQ0hteZFbl8sg==
+unbound-auth-test.nlnetlabs.nl.        3600    IN      DNSKEY  256 3 13 S3Da9HqpFj0pEbI8WXOdkvN3vgZ6qxNSz4XyKkmWWAG28kq5T+/lWp36DUDvnMI9wJNuixzUHtgZ6oZoAaVrPg== ;{id = 15486 (zsk), size = 256b}
+unbound-auth-test.nlnetlabs.nl.        3600    IN      RRSIG   DNSKEY 13 3 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. 1cLFaDb6kP8KnRJujW1ieHUdS5Tgdv59TCZ+FloCRJMJBwQAow6UKAIY7HHlTb8IHTajyUrjlxX/dN8S/5VwuA==
+unbound-auth-test.nlnetlabs.nl.        3600    IN      NSEC3PARAM      1 0 1 -
+unbound-auth-test.nlnetlabs.nl.        3600    IN      RRSIG   NSEC3PARAM 13 3 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. GWgtJArNpfJ4ifoinUBUVRTlkk0CMemdozhMKY13dk3EQMP0jb4g49PcTAgEP2dBUs9efttQVQQpmFPyTGfN1w==
+tvdhfml24jp7cott1qijj9812qu9ibh3.unbound-auth-test.nlnetlabs.nl.       3600    IN      NSEC3   1 0 1 -  41pcah2j3fr8k99gj5pveh4igrjfc871 NS SOA RRSIG DNSKEY NSEC3PARAM  ;{ flags: -, from: unbound-auth-test.nlnetlabs.nl. to: b.b.unbound-auth-test.nlnetlabs.nl.}
+tvdhfml24jp7cott1qijj9812qu9ibh3.unbound-auth-test.nlnetlabs.nl.       3600    IN      RRSIG   NSEC3 13 4 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. DzwQTaZj4j29eHXEKllIFcq4yNWA7VMqkh8+gCrBO+GEek9+hGxL6ANsU0Hv6glyBmPDeYUZcy4xy0EEj1R4hQ==
+;
+;; Empty nonterminal: b.unbound-auth-test.nlnetlabs.nl.
+apejmh1fqds9gir0nnsf4d5gtno10tg1.unbound-auth-test.nlnetlabs.nl.       3600    IN      NSEC3   1 0 1 -  dbs0aj50410urbvt3ghfr644n7h06gs5 ;{ flags: -, from: b.unbound-auth-test.nlnetlabs.nl. to: c.b.unbound-auth-test.nlnetlabs.nl.}
+apejmh1fqds9gir0nnsf4d5gtno10tg1.unbound-auth-test.nlnetlabs.nl.       3600    IN      RRSIG   NSEC3 13 4 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. m9B0W8xDZF6ml/m8OujrZZBiF1O0wAeKciK/5FMT/hCjHR0hMrbXBPg/ZntpVJD/Pko2HcBvWKu87U721yTHyQ==
+;
+;; Empty nonterminal: a.b.unbound-auth-test.nlnetlabs.nl.
+toqivctpt4pdcp5g19neqt19fvtgbgeu.unbound-auth-test.nlnetlabs.nl.       3600    IN      NSEC3   1 0 1 -  tvdhfml24jp7cott1qijj9812qu9ibh3 ;{ flags: -, from: a.b.unbound-auth-test.nlnetlabs.nl. to: unbound-auth-test.nlnetlabs.nl.}
+toqivctpt4pdcp5g19neqt19fvtgbgeu.unbound-auth-test.nlnetlabs.nl.       3600    IN      RRSIG   NSEC3 13 4 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. Jr1oPPs+DGBVV13n4gG4AGVFsleItluLbtCIyQDcYZEA+e5JMkrLzfW3rXqXaUSUauR4iEu5FmTfs4GTsumdUw==
+;
+*.a.b.unbound-auth-test.nlnetlabs.nl.  3600    IN      TXT     "*.a.b"
+*.a.b.unbound-auth-test.nlnetlabs.nl.  3600    IN      RRSIG   TXT 13 5 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. NrMUaNzZp88lXit/HLL/iDBHspDSfoM//K+/0VwUYRZjmVJQQHCHtHBGgR4NgrLi3ffvCAWq2LNGxDm+YMSl3g==
+jrtu61ssgd18lfjglqrbbs5b2vmbh6cl.unbound-auth-test.nlnetlabs.nl.       3600    IN      NSEC3   1 0 1 -  k8r2bchsbehs5dbu5d6ivjfnmjb3jc8s TXT RRSIG  ;{ flags: -, from: *.a.b.unbound-auth-test.nlnetlabs.nl. to: *.c.b.unbound-auth-test.nlnetlabs.nl.}
+jrtu61ssgd18lfjglqrbbs5b2vmbh6cl.unbound-auth-test.nlnetlabs.nl.       3600    IN      RRSIG   NSEC3 13 4 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. kLIhE9+iz1OybJwXbtRJZst+Mk5u4OAtpZGWSwJUfqD6dXAk+h6msKAR18jpPeL7cCjXjIAKIv3x4oYRkl+uKw==
+;
+;; Empty nonterminal: b.b.unbound-auth-test.nlnetlabs.nl.
+41pcah2j3fr8k99gj5pveh4igrjfc871.unbound-auth-test.nlnetlabs.nl.       3600    IN      NSEC3   1 0 1 -  apejmh1fqds9gir0nnsf4d5gtno10tg1 ;{ flags: -, from: b.b.unbound-auth-test.nlnetlabs.nl. to: b.unbound-auth-test.nlnetlabs.nl.}
+41pcah2j3fr8k99gj5pveh4igrjfc871.unbound-auth-test.nlnetlabs.nl.       3600    IN      RRSIG   NSEC3 13 4 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. XlIjnuF313w0GXn6vymrAcsyuxZSaN6IShFjxQ5T2HUFePHBNvtRkL+TtMQZNlR8nTR3+MWcON0cOZIGjVCCjg==
+;
+*.b.b.unbound-auth-test.nlnetlabs.nl.  3600    IN      TXT     "*.b.b"
+*.b.b.unbound-auth-test.nlnetlabs.nl.  3600    IN      RRSIG   TXT 13 5 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. FkS3ceWpoHyOKaa8OtywIl148Bwo0vkzBd263vqYe0puhuRa6IvNEk5ERdwfWt9eNEq+6IlizPT/dYxA2fXYXA==
+ft7dasbom0copm9e2ak9k151dj08kjfs.unbound-auth-test.nlnetlabs.nl.       3600    IN      NSEC3   1 0 1 -  jrtu61ssgd18lfjglqrbbs5b2vmbh6cl TXT RRSIG  ;{ flags: -, from: *.b.b.unbound-auth-test.nlnetlabs.nl. to: *.a.b.unbound-auth-test.nlnetlabs.nl.}
+ft7dasbom0copm9e2ak9k151dj08kjfs.unbound-auth-test.nlnetlabs.nl.       3600    IN      RRSIG   NSEC3 13 4 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. 5QhLGohTRLQSGC8vstzDjqcwfrbOnLUG2OelSjvsZFy1smsWUxJBCQXQdx1+JX7xamZHlZESQtS+cELuZUqpvA==
+;
+;; Empty nonterminal: c.b.unbound-auth-test.nlnetlabs.nl.
+dbs0aj50410urbvt3ghfr644n7h06gs5.unbound-auth-test.nlnetlabs.nl.       3600    IN      NSEC3   1 0 1 -  ft7dasbom0copm9e2ak9k151dj08kjfs ;{ flags: -, from: c.b.unbound-auth-test.nlnetlabs.nl. to: *.b.b.unbound-auth-test.nlnetlabs.nl.}
+dbs0aj50410urbvt3ghfr644n7h06gs5.unbound-auth-test.nlnetlabs.nl.       3600    IN      RRSIG   NSEC3 13 4 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. hjk1foJWW68JK3O1Ktf0ZogoXVrMDw3mHVBBYTrpaBKX1gWR5icmJiOCYZWYx3z88PUnGkfH+kx4oDUjioqN+Q==
+;
+*.c.b.unbound-auth-test.nlnetlabs.nl.  3600    IN      TXT     "*.c.b"
+*.c.b.unbound-auth-test.nlnetlabs.nl.  3600    IN      RRSIG   TXT 13 5 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. b7rFR5tlx5Y5SQqNdYBtfD6DrkNx9h79GCmnZfWrUzRz+A256k2v08IPRJDK+WxEHuYHjfNnVWxjRr9M1OW2Iw==
+k8r2bchsbehs5dbu5d6ivjfnmjb3jc8s.unbound-auth-test.nlnetlabs.nl.       3600    IN      NSEC3   1 0 1 -  toqivctpt4pdcp5g19neqt19fvtgbgeu TXT RRSIG  ;{ flags: -, from: *.c.b.unbound-auth-test.nlnetlabs.nl. to: a.b.unbound-auth-test.nlnetlabs.nl.}
+k8r2bchsbehs5dbu5d6ivjfnmjb3jc8s.unbound-auth-test.nlnetlabs.nl.       3600    IN      RRSIG   NSEC3 13 4 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. 34BS1ajedCNdfXgUfxTyiAK1ichfFLshhJ3TnfplrUps0UsZaQLEG+EIlP4wTBtro2c6V8YCSmOuxuce4gYoDw==
+;
+TEMPFILE_END
+
+stub-zone:
+       name: "."
+       stub-addr: 193.0.14.129         # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test authority zone with NSEC3 empty nonterminal
+; with exact match NSEC3 in existence (eg. not a CE-proof)
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+       ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS        K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET.    IN      A       193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com.   IN NS   a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net.    IN      A       192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+       ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com.   IN NS   a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net.    IN      A       192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+       ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net.                IN      A       1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A   1.2.3.44
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+www.example.net. IN A  1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com.   IN NS   ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A  10.20.30.40
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+a.b.unbound-auth-test.nlnetlabs.nl. IN TXT
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD RA DO NOERROR
+SECTION QUESTION
+a.b.unbound-auth-test.nlnetlabs.nl. IN TXT
+SECTION ANSWER
+SECTION AUTHORITY
+unbound-auth-test.nlnetlabs.nl.        3600 IN SOA     ns.nlnetlabs.nl. ralph.nlnetlabs.nl. 1554201247 14400 3600 604800 3600
+unbound-auth-test.nlnetlabs.nl.        3600 IN RRSIG   SOA 13 3 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. NLFcC2oet+HC+1dhT4D/2JJFIcMiRtTM81KwvT7u8ybF3iDE4bnyrILv Qk8DsizpYKwk+D3J3tMC3TV5+//qFw==
+toqivctpt4pdcp5g19neqt19fvtgbgeu.unbound-auth-test.nlnetlabs.nl. 3600 IN NSEC3 1 0 1 - TVDHFML24JP7COTT1QIJJ9812QU9IBH3
+toqivctpt4pdcp5g19neqt19fvtgbgeu.unbound-auth-test.nlnetlabs.nl. 3600 IN RRSIG NSEC3 13 4 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. Jr1oPPs+DGBVV13n4gG4AGVFsleItluLbtCIyQDcYZEA+e5JMkrLzfW3 rXqXaUSUauR4iEu5FmTfs4GTsumdUw==
+ENTRY_END
+
+SCENARIO_END
diff --git a/testdata/auth_nsec3_wild_with_out_of_zone_data.rpl b/testdata/auth_nsec3_wild_with_out_of_zone_data.rpl
new file mode 100644 (file)
index 0000000..8c5a008
--- /dev/null
@@ -0,0 +1,234 @@
+; config options
+server:
+       target-fetch-policy: "0 0 0 0 0"
+
+auth-zone:
+       name: "test-ns-signed.dev.internet.nl."
+       ## zonefile (or none).
+       ## zonefile: "example.com.zone"
+       ## master by IP address or hostname
+       ## can list multiple masters, each on one line.
+       ## master:
+       ## url for http fetch
+       ## url:
+       ## queries from downstream clients get authoritative answers.
+       ## for-downstream: yes
+       for-downstream: yes
+       ## queries are used to fetch authoritative answers from this zone,
+       ## instead of unbound itself sending queries there.
+       ## for-upstream: yes
+       for-upstream: yes
+       ## on failures with for-upstream, fallback to sending queries to
+       ## the authority servers
+       ## fallback-enabled: no
+
+       ## this line generates zonefile: \n"/tmp/xxx.example.com"\n
+       zonefile:
+TEMPFILE_NAME test-ns-signed.dev.internet.nl
+       ## this is the inline file /tmp/xxx.test-ns-signed.dev.internet.nl
+       ## the tempfiles are deleted when the testrun is over.
+TEMPFILE_CONTENTS test-ns-signed.dev.internet.nl
+test-ns-signed.dev.internet.nl.        3600    IN      SOA     ns.nlnetlabs.nl. ralph.nlnetlabs.nl. 4 14400 3600 604800 3600
+test-ns-signed.dev.internet.nl.        3600    IN      RRSIG   SOA 8 4 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. ybb0Hc7NC+QOFEEv4cX2+Umlk+miiOAHmeP2Uwvg6lqfxkk+3g7yWBEKMinXjLKz0odWZ6fki6M/3yBPQX8SV0OCRY5gYvAHAjbxAIHozIM+5iwOkRQhNF1DRgQ3BLjL93f6T5e5Z4y1812iOpu4GYswXW/UTOZACXz2UiaCPAg=
+;; Out of zone record that shouldn't break NSEC3 proofs.
+;; There was a bug that would keep removing labels and use this out of zone
+;; record.
+dev.internet.nl. 3600 IN NS ns.test-ns-signed.dev.internet.nl.
+test-ns-signed.dev.internet.nl.        3600    IN      NS      ns.test-ns-signed.dev.internet.nl.
+test-ns-signed.dev.internet.nl.        3600    IN      RRSIG   NS 8 4 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. KqiwTF3hKm1ZHGbgx6MVzZYHlS1p7+Xrikx4izMHFbWiD6ki6lrJBJsnH9j/hH1cwHxjXslOeJh0hdBdbn8la0meZPsebOyUbEjoLPzRLzKNLDBuA4BUJnRGQJy21CX7XooXAMAmR8YFipO8CojI9EogU2m2o9YkfbpacFWQoTk=
+test-ns-signed.dev.internet.nl.        3600    IN      DNSKEY  256 3 8 AwEAAc6c8tpMXBSOFLu/9n4aUUDK43wN4B7A2UDqZi0IOkyptxWCFghleyZeeN5uq6p9MoUt8lS73mFmIYC0ux5zBO3uVaJQ9u+00qRAEVg/RgBwa58y2f/zNtFV/f7mBSPcPTiEjUh0bwHSiTvUn/8JkrvjyAcbQMO0YOsRof5q6tzl ;{id = 32784 (zsk), size = 1024b}
+test-ns-signed.dev.internet.nl.        3600    IN      DNSKEY  257 3 8 AwEAAdC0hBJP1U8lbZ6JFXn0ouK6VipiraN7I8oog62SuEd/fqAupys7A/Ih6WK/UoJorjlnccEL8euNMaS4kNogvoBrFx8ciIWKcbot5mtwc4WDr3cnR+HIZNCUFVkIxsMqE7HCD0yn0zhkB60shED+ZHs8zpyU+cjnsOSizxOnIY+F ;{id = 54502 (ksk), size = 1024b}
+test-ns-signed.dev.internet.nl.        3600    IN      RRSIG   DNSKEY 8 4 3600 20190205132351 20190108132351 54502 test-ns-signed.dev.internet.nl. X3qN+plfjf45FA4pr/tcUqUCR9ajDqwtNe4TS19WOJogVL/Gf/N5/ToOCrs3s+a7VrJl58WvSJquDM8xAS8f4oJggKgHFhopce8tMTGRxkRvJo4y+tt3vCveh/zjHLAnbOaBGA4CJ/IPhRqzHzcX/SjSv0EACWd6XpQIWogRv6c=
+test-ns-signed.dev.internet.nl.        3600    IN      NSEC3PARAM      1 0 1 -
+test-ns-signed.dev.internet.nl.        3600    IN      RRSIG   NSEC3PARAM 8 4 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. A/1xUGO46uIz+9vjPGfWVD99akwU9bd/UlnVG9LPfoTzG7TMWSoZ4ksg8k8ub8K1TrkDmQokNHSW0Gt6qwoRh17c+p1h/SFlDVL83wgTc4NqG43OQjgGU9RV035XU+VESlO3lavifhlu8rHWBJTlhiXcMGq6H+zvoz4sx9p5GNM=
+93stp7o7i5n9gb83uu7vv6h8qltk14ig.test-ns-signed.dev.internet.nl.       3600    IN      NSEC3   1 0 1 -  fee0c2kfhi6bnljce6vehaenqq3pbupu NS SOA RRSIG DNSKEY NSEC3PARAM
+93stp7o7i5n9gb83uu7vv6h8qltk14ig.test-ns-signed.dev.internet.nl.       3600    IN      RRSIG   NSEC3 8 5 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. YoTRDQ7sSvERcY1WwAH4oRRR7DmaAwA8/H70jdMeSU4wsnM/VM03kDcc2sgq5edmHiZoTWnq7nEb/1Y7Ro0YrqTUQdYFZvXi6UjZQrKI9nqAGnhdXZWlZJHmYpn2+2Emd+bYHkwvKaPnfnnKjUoGVBH8Hly0HBYKPUF1/viquB0=
+kl94uofq16t2vlq0bmampf6e4o9k5hbi.test-ns-signed.dev.internet.nl.       3600    IN      NSEC3   1 0 1 -  7ag3p2pfrvq09dpn63cvga8ub1rnrrg1
+kl94uofq16t2vlq0bmampf6e4o9k5hbi.test-ns-signed.dev.internet.nl.       3600    IN      RRSIG   NSEC3 8 5 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. NI5zJ/k1kPVZ1abms5OoME/wazb77Ltduyk6ZevAnt4tKydZYwSsjEd0Ixknw9xnakCABn5rAYEXctARN0KCwCkNHR7TYlTAJT14hlDYjbad2u2HT9L1kzAnfj3BeLZl/LRADeMbTtzrkTSF3Dnezurb94fMnUnKt2hPfQfj560=
+fee0c2kfhi6bnljce6vehaenqq3pbupu.test-ns-signed.dev.internet.nl.       3600    IN      NSEC3   1 0 1 -  i6pi4e3o98e7vtkpjfhqn7g77d3mjcnv
+fee0c2kfhi6bnljce6vehaenqq3pbupu.test-ns-signed.dev.internet.nl.       3600    IN      RRSIG   NSEC3 8 5 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. WIb3ISP1nlafbyWoWa4z7sG5IS+V86PyvEMHdD/64hgsFkrCu483XK7VNnBz28SL/631JXA1R19O+UxeWhTUyctp8QSt6cEZcMPY8b7yG97rNFNvhSw75rSXXt+JwgIYHPHQV5oqPtVmEpQM5SfJd+hs+Nn1bJcWB3UaESNNAMQ=
+*.a.b.test-ns-signed.dev.internet.nl.  3600    IN      TXT     "a"
+*.a.b.test-ns-signed.dev.internet.nl.  3600    IN      RRSIG   TXT 8 6 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. eNcJkQXdTO1z21od0sXbgqtABhhr/9tNC/Zx8zYbhXkfj7rufN71yk9xqgu6TG0MeJV26ISrqIGRVFJFmTRvO1LLxoKkEPhqe+08nqRztxXZajCV+dDeFoGIDcXJg6tAxB+MJznkKDtZPpIWvyt1WwdYfcMrGtE9AmR3K1/P/xE=
+7ag3p2pfrvq09dpn63cvga8ub1rnrrg1.test-ns-signed.dev.internet.nl.       3600    IN      NSEC3   1 0 1 -  93stp7o7i5n9gb83uu7vv6h8qltk14ig TXT RRSIG
+7ag3p2pfrvq09dpn63cvga8ub1rnrrg1.test-ns-signed.dev.internet.nl.       3600    IN      RRSIG   NSEC3 8 5 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. gtxoiTa3FRUqoRLvkWSxmWQ+DfijVd26gpKH3+GmGIcNB/sr/Cf8kERRwVVHvgzYIcvdJcys5b2LUXnZJwcdAlx7efZPWgNZzWxJrw6ES25LCWJOrp31isWn9FlAZGIbnpyEXxD2apBSmtyPnKbTgU6lHHS9jrsYHu4G8Zouv3k=
+ns.test-ns-signed.dev.internet.nl.     3600    IN      A       185.49.141.11
+ns.test-ns-signed.dev.internet.nl.     3600    IN      RRSIG   A 8 5 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. F9sXEVAmlRn+/84WbuvegiCwstNxMDMQLl0Obv2CTPpee4U6psbmXrlzczjjjkE6aLjsIHYdcXCzEWTrmukT+V9jzaGPRJvxNvC0ASWyzggAoh0Z++Hl4cVa9587o6I9ODayehFI9Pgdem+RVdb4zlWuzi9FmKXgeTlgWN54tPg=
+ns.test-ns-signed.dev.internet.nl.     3600    IN      AAAA    2a04:b900:0:100::11
+ns.test-ns-signed.dev.internet.nl.     3600    IN      RRSIG   AAAA 8 5 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. F1XRrx/QgfzJ1RS7d0m23QoIPx1G8WL1SrlTOm7pk5vWTL07w7HEw2TETblkjnitJGKfN9ebsIum/cDPUZc3UqLkguP2UCWpePnlllTJuwmG0Z+wyINIR4xF4PQlqttvzThBkD2JKWb/o0W8dQyXTj+jJ1vCZ0NjjA2N4+iJIQE=
+i6pi4e3o98e7vtkpjfhqn7g77d3mjcnv.test-ns-signed.dev.internet.nl.       3600    IN      NSEC3   1 0 1 -  kl94uofq16t2vlq0bmampf6e4o9k5hbi A AAAA RRSIG
+i6pi4e3o98e7vtkpjfhqn7g77d3mjcnv.test-ns-signed.dev.internet.nl.       3600    IN      RRSIG   NSEC3 8 5 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. xLysIqn3r3rdHE3GvwVjZwUyuFClhkhgrQdwyc66RuHKE3MfSuhVr9cHTCJzhipF5TwQTbUpLOr74r99bzdiIY8Xkgjy2M0nc76v1ObSGJdPPjGTevbhDOnavUURwOR/q0NqqO2iPrgFjOVMZ+8uwRJtCty2iAVZfVG+qDzs8hU=
+TEMPFILE_END
+
+stub-zone:
+       name: "."
+       stub-addr: 193.0.14.129         # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test authority zone with NSEC3 wildcard
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+       ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS        K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET.    IN      A       193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com.   IN NS   a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net.    IN      A       192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+       ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com.   IN NS   a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net.    IN      A       192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+       ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net.                IN      A       1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A   1.2.3.44
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+www.example.net. IN A  1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com.   IN NS   ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A  10.20.30.40
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+something.a.b.test-ns-signed.dev.internet.nl. IN TXT
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD RA DO NOERROR
+SECTION QUESTION
+something.a.b.test-ns-signed.dev.internet.nl. IN TXT
+SECTION ANSWER
+something.a.b.test-ns-signed.dev.internet.nl. IN TXT "a"
+something.a.b.test-ns-signed.dev.internet.nl.  3600    IN      RRSIG   TXT 8 6 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. eNcJkQXdTO1z21od0sXbgqtABhhr/9tNC/Zx8zYbhXkfj7rufN71yk9xqgu6TG0MeJV26ISrqIGRVFJFmTRvO1LLxoKkEPhqe+08nqRztxXZajCV+dDeFoGIDcXJg6tAxB+MJznkKDtZPpIWvyt1WwdYfcMrGtE9AmR3K1/P/xE=
+SECTION AUTHORITY
+i6pi4e3o98e7vtkpjfhqn7g77d3mjcnv.test-ns-signed.dev.internet.nl. 3600 IN NSEC3 1 0 1 - KL94UOFQ16T2VLQ0BMAMPF6E4O9K5HBI  A AAAA RRSIG
+i6pi4e3o98e7vtkpjfhqn7g77d3mjcnv.test-ns-signed.dev.internet.nl.       3600    IN      RRSIG   NSEC3 8 5 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. xLysIqn3r3rdHE3GvwVjZwUyuFClhkhgrQdwyc66RuHKE3MfSuhVr9cHTCJzhipF5TwQTbUpLOr74r99bzdiIY8Xkgjy2M0nc76v1ObSGJdPPjGTevbhDOnavUURwOR/q0NqqO2iPrgFjOVMZ+8uwRJtCty2iAVZfVG+qDzs8hU=
+ENTRY_END
+
+; Check that the reply for a wildcard nodata answer contains the NSEC3s.
+; qname denial NSEC3, closest encloser NSEC3, and type bitmap NSEC3.
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+something.a.b.test-ns-signed.dev.internet.nl. IN AAAA
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD RA DO NOERROR
+SECTION QUESTION
+something.a.b.test-ns-signed.dev.internet.nl. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+test-ns-signed.dev.internet.nl.        3600    IN      SOA     ns.nlnetlabs.nl. ralph.nlnetlabs.nl. 4 14400 3600 604800 3600
+test-ns-signed.dev.internet.nl.        3600    IN      RRSIG   SOA 8 4 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. ybb0Hc7NC+QOFEEv4cX2+Umlk+miiOAHmeP2Uwvg6lqfxkk+3g7yWBEKMinXjLKz0odWZ6fki6M/3yBPQX8SV0OCRY5gYvAHAjbxAIHozIM+5iwOkRQhNF1DRgQ3BLjL93f6T5e5Z4y1812iOpu4GYswXW/UTOZACXz2UiaCPAg= ;{id = 32784}
+7ag3p2pfrvq09dpn63cvga8ub1rnrrg1.test-ns-signed.dev.internet.nl.       3600    IN      NSEC3   1 0 1 - 93stp7o7i5n9gb83uu7vv6h8qltk14ig TXT RRSIG
+7ag3p2pfrvq09dpn63cvga8ub1rnrrg1.test-ns-signed.dev.internet.nl.       3600    IN      RRSIG   NSEC3 8 5 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. gtxoiTa3FRUqoRLvkWSxmWQ+DfijVd26gpKH3+GmGIcNB/sr/Cf8kERRwVVHvgzYIcvdJcys5b2LUXnZJwcdAlx7efZPWgNZzWxJrw6ES25LCWJOrp31isWn9FlAZGIbnpyEXxD2apBSmtyPnKbTgU6lHHS9jrsYHu4G8Zouv3k= ;{id = 32784}
+fee0c2kfhi6bnljce6vehaenqq3pbupu.test-ns-signed.dev.internet.nl.       3600    IN      NSEC3   1 0 1 - i6pi4e3o98e7vtkpjfhqn7g77d3mjcnv
+fee0c2kfhi6bnljce6vehaenqq3pbupu.test-ns-signed.dev.internet.nl.       3600    IN      RRSIG   NSEC3 8 5 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. WIb3ISP1nlafbyWoWa4z7sG5IS+V86PyvEMHdD/64hgsFkrCu483XK7VNnBz28SL/631JXA1R19O+UxeWhTUyctp8QSt6cEZcMPY8b7yG97rNFNvhSw75rSXXt+JwgIYHPHQV5oqPtVmEpQM5SfJd+hs+Nn1bJcWB3UaESNNAMQ= ;{id = 32784}
+i6pi4e3o98e7vtkpjfhqn7g77d3mjcnv.test-ns-signed.dev.internet.nl.       3600    IN      NSEC3   1 0 1 - kl94uofq16t2vlq0bmampf6e4o9k5hbi A AAAA RRSIG
+i6pi4e3o98e7vtkpjfhqn7g77d3mjcnv.test-ns-signed.dev.internet.nl.       3600    IN      RRSIG   NSEC3 8 5 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. xLysIqn3r3rdHE3GvwVjZwUyuFClhkhgrQdwyc66RuHKE3MfSuhVr9cHTCJzhipF5TwQTbUpLOr74r99bzdiIY8Xkgjy2M0nc76v1ObSGJdPPjGTevbhDOnavUURwOR/q0NqqO2iPrgFjOVMZ+8uwRJtCty2iAVZfVG+qDzs8hU= ;{id = 32784}
+ENTRY_END
+
+SCENARIO_END
index f08760e2f9fc581461945362e7a7d1ea77471b53..2fe7b171df001dd3eec2d0bd5a59db05e803be96 100644 (file)
@@ -728,7 +728,7 @@ dname_is_root(uint8_t* dname)
        return (len == 0);
 }
 
-void 
+void
 dname_remove_label(uint8_t** dname, size_t* len)
 {
        size_t lablen;
@@ -742,7 +742,23 @@ dname_remove_label(uint8_t** dname, size_t* len)
        *dname += lablen+1;
 }
 
-void 
+int
+dname_remove_label_limit_len(uint8_t** dname, size_t* len, size_t lenlimit)
+{
+       size_t lablen;
+       log_assert(dname && *dname && len);
+       lablen = (*dname)[0];
+       log_assert(!LABEL_IS_PTR(lablen));
+       log_assert(*len > lablen);
+       if(lablen == 0)
+               return 0; /* do not modify root label */
+       if(*len - (lablen + 1) < lenlimit) return 0;
+       *len -= lablen+1;
+       *dname += lablen+1;
+       return 1;
+}
+
+void
 dname_remove_labels(uint8_t** dname, size_t* len, int n)
 {
        int i;
index 6e4cf7ea3be7639360416630b129f0281509adef..e4a0313ac6b2cb959420924b8cd1e6bd447289c2 100644 (file)
@@ -262,10 +262,23 @@ int dname_is_root(uint8_t* dname);
  * Snip off first label from a dname, returning the parent zone.
  * @param dname: from what to strip off. uncompressed wireformat.
  * @param len: length, adjusted to become less.
- * return stripped off, or "." if input was ".".
+ * return dname stripped off, or "." if input was ".".
  */
 void dname_remove_label(uint8_t** dname, size_t* len);
 
+/**
+ * Same as dname_remove_label but fails if removal would surpass lenlimit.
+ * If no failure,
+ * snip off first label from a dname, returning the parent zone.
+ * @param dname: from what to strip off. uncompressed wireformat.
+ * @param len: length, adjusted to become less.
+ * @param lenlimit: length limit that we can't surpass (usually the zone apex).
+ * return
+ *     o 1,  and dname stripped off, or "." if input was ".", else
+ *     o 0, if going up would surpass lenlimit.
+ */
+int dname_remove_label_limit_len(uint8_t** dname, size_t* len, size_t lenlimit);
+
 /**
  * Snip off first N labels from a dname, returning the parent zone.
  * @param dname: from what to strip off. uncompressed wireformat.