Bug 347 - wrong nsec3 returned for DS-no-data for empty-non-terminals
wrong nsec3 returned for DS-no-data for empty-non-terminals
Status: RESOLVED REMIND
Product: NSD
Classification: Unclassified
Component: NSD Code
3.2.x
All Linux
: P5 major
Assigned To: NSD team
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2011-01-04 18:39 CET by Jeff Warrington
Modified: 2011-01-06 10:08 CET (History)
1 user (show)

See Also:


Attachments
a signed zone file and nsd.conf file that demonstrate the problem (3.55 KB, application/x-gzip)
2011-01-04 18:39 CET, Jeff Warrington
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Jeff Warrington 2011-01-04 18:39:27 CET
Created attachment 155 [details]
a signed zone file and nsd.conf file that demonstrate the problem

Requesting a QNAME that is an empty-non-terminal and looking for QTYPE of DS returns the parent's NSEC3 instead of the one that matches the QNAME.  This also seems to affect children of empty-non-terminals.

In the attached zone querying for "ns.foo.example. ds" returns an nsec3 owner of "1rab9ojs6d7sl7ndfr940fa0i3l8gg7v.example." instead of the expected "p07mnffp3l15cm8ssgbfhn7nlp2edqhg.example."

I'm curious to know if the following patch is a valid solution or if it introduces other problems.

diff --git a/nsec3.c b/nsec3.c
index b285e9a..3c64ea4 100644
--- a/nsec3.c
+++ b/nsec3.c
@@ -485,7 +485,7 @@ nsec3_add_ds_proof(struct query *query, struct answer *answer,
                        domain->nsec3_ds_parent_cover);
        } else {
                /* prove closest provable encloser */
-               domain_type* par = domain->parent;
+               domain_type* par = domain;
                domain_type* prev_par = 0;
                while(par && !par->nsec3_is_exact)
                {
Comment 1 Matthijs Mekking 2011-01-06 10:08:03 CET
Hi Jeff, 

Thanks for the report. We have fixed it in trunk and will do a release very soon.

Your proposed fix however does not work in all cases. When searching for the closest provable encloser (par), the assumption is made that the next closer (prev_par) has no exact matching NSEC3 record. But if you start searching with the delegation name and the closest provable encloser is only one up, the next closer does have an exact match, which results in an assertion error.

To conclude, the fix misses a check whether the answer is a response or a referral. In the case of a referral, nsd works correctly. In the case of a response, nsd should check if the current domain has a NSEC3 that exactly matches.

The fix looks like this:

--- trunk/nsec3.c	2011-01-05 12:52:07 UTC (rev 3098)
+++ trunk/nsec3.c	2011-01-05 16:12:01 UTC (rev 3099)
@@ -475,7 +475,7 @@
 
 static void
 nsec3_add_ds_proof(struct query *query, struct answer *answer,
-	struct domain *domain)
+	struct domain *domain, int delegpt)
 {
 	/* assert we are above the zone cut */
 	assert(domain != query->zone->apex);
@@ -528,7 +531,7 @@
 			return;
 		}
 		/* query->zone must be the parent zone */
-		nsec3_add_ds_proof(query, answer, original);
+		nsec3_add_ds_proof(query, answer, original, 0);
 	}
 	/* the nodata is result from a wildcard match */
 	else if (original==original->wildcard_child_closest_match
@@ -554,7 +557,7 @@
 {
 	if(!query->zone->nsec3_soa_rr)
 		return;
-	nsec3_add_ds_proof(query, answer, query->delegation_domain);
+	nsec3_add_ds_proof(query, answer, query->delegation_domain, 1);
 }
 
and 

--- trunk/nsec3.c	2011-01-05 16:12:01 UTC (rev 3099)
+++ trunk/nsec3.c	2011-01-05 17:55:57 UTC (rev 3100)
@@ -483,13 +483,14 @@
 		/* use NSEC3 record from above the zone cut. */
 		nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
 			domain->nsec3_ds_parent_cover);
+	} else if (!delegpt && domain->nsec3_is_exact) {
+		nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
+			domain->nsec3_cover);
 	} else {
 		/* prove closest provable encloser */

I am still working on some tests.