val_nsec.c revision 292206
167754Smsmith/*
267754Smsmith * validator/val_nsec.c - validator NSEC denial of existence functions.
367754Smsmith *
467754Smsmith * Copyright (c) 2007, NLnet Labs. All rights reserved.
567754Smsmith *
667754Smsmith * This software is open source.
7217365Sjkim *
8298714Sjkim * Redistribution and use in source and binary forms, with or without
970243Smsmith * modification, are permitted provided that the following conditions
1067754Smsmith * are met:
11217365Sjkim *
12217365Sjkim * Redistributions of source code must retain the above copyright notice,
13217365Sjkim * this list of conditions and the following disclaimer.
14217365Sjkim *
15217365Sjkim * Redistributions in binary form must reproduce the above copyright notice,
16217365Sjkim * this list of conditions and the following disclaimer in the documentation
17217365Sjkim * and/or other materials provided with the distribution.
18217365Sjkim *
19217365Sjkim * Neither the name of the NLNET LABS nor the names of its contributors may
20217365Sjkim * be used to endorse or promote products derived from this software without
21217365Sjkim * specific prior written permission.
22217365Sjkim *
23217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2567754Smsmith * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27217365Sjkim * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28217365Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2967754Smsmith * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30217365Sjkim * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31217365Sjkim * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32217365Sjkim * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33217365Sjkim * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34217365Sjkim */
35217365Sjkim
36217365Sjkim/**
37217365Sjkim * \file
38217365Sjkim *
39217365Sjkim * This file contains helper functions for the validator module.
40217365Sjkim * The functions help with NSEC checking, the different NSEC proofs
41217365Sjkim * for denial of existence, and proofs for presence of types.
42217365Sjkim */
4367754Smsmith#include "config.h"
44193341Sjkim#include "validator/val_nsec.h"
45193341Sjkim#include "validator/val_utils.h"
46193341Sjkim#include "util/data/msgreply.h"
47193341Sjkim#include "util/data/dname.h"
48193341Sjkim#include "util/net_help.h"
49193341Sjkim#include "util/module.h"
50193341Sjkim#include "services/cache/rrset.h"
5167754Smsmith
5277424Smsmith/** get ttl of rrset */
5391116Smsmithstatic uint32_t
5467754Smsmithrrset_get_ttl(struct ub_packed_rrset_key* k)
55167802Sjkim{
56167802Sjkim	struct packed_rrset_data* d = (struct packed_rrset_data*)k->entry.data;
57151937Sjkim	return d->ttl;
58151937Sjkim}
59151937Sjkim
60151937Sjkimint
61151937Sjkimnsecbitmap_has_type_rdata(uint8_t* bitmap, size_t len, uint16_t type)
6267754Smsmith{
63151937Sjkim	/* Check type present in NSEC typemap with bitmap arg */
64100966Siwasaki	/* bitmasks for determining type-lowerbits presence */
65151937Sjkim	uint8_t masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
6667754Smsmith	uint8_t type_window = type>>8;
6799146Siwasaki	uint8_t type_low = type&0xff;
6867754Smsmith	uint8_t win, winlen;
6999146Siwasaki	/* read each of the type bitmap windows and see if the searched
7099146Siwasaki	 * type is amongst it */
7167754Smsmith	while(len > 0) {
7267754Smsmith		if(len < 3) /* bad window, at least window# winlen bitmap */
7367754Smsmith			return 0;
7467754Smsmith		win = *bitmap++;
7567754Smsmith		winlen = *bitmap++;
7667754Smsmith		len -= 2;
7767754Smsmith		if(len < winlen || winlen < 1 || winlen > 32)
78151937Sjkim			return 0;	/* bad window length */
7967754Smsmith		if(win == type_window) {
80151937Sjkim			/* search window bitmap for the correct byte */
8199146Siwasaki			/* mybyte is 0 if we need the first byte */
8267754Smsmith			size_t mybyte = type_low>>3;
8367754Smsmith			if(winlen <= mybyte)
8467754Smsmith				return 0; /* window too short */
8567754Smsmith			return (int)(bitmap[mybyte] & masks[type_low&0x7]);
8667754Smsmith		} else {
8767754Smsmith			/* not the window we are looking for */
88209746Sjkim			bitmap += winlen;
8967754Smsmith			len -= winlen;
9067754Smsmith		}
91167802Sjkim	}
9267754Smsmith	/* end of bitmap reached, no type found */
9367754Smsmith	return 0;
94104470Siwasaki}
9599679Siwasaki
9667754Smsmithint
9767754Smsmithnsec_has_type(struct ub_packed_rrset_key* nsec, uint16_t type)
98167802Sjkim{
9987031Smsmith	struct packed_rrset_data* d = (struct packed_rrset_data*)nsec->
10067754Smsmith		entry.data;
10167754Smsmith	size_t len;
10299679Siwasaki	if(!d || d->count == 0 || d->rr_len[0] < 2+1)
10367754Smsmith		return 0;
104151937Sjkim	len = dname_valid(d->rr_data[0]+2, d->rr_len[0]-2);
105298714Sjkim	if(!len)
106298714Sjkim		return 0;
107298714Sjkim	return nsecbitmap_has_type_rdata(d->rr_data[0]+2+len,
108298714Sjkim		d->rr_len[0]-2-len, type);
10967754Smsmith}
11067754Smsmith
111167802Sjkim/**
112167802Sjkim * Get next owner name from nsec record
113167802Sjkim * @param nsec: the nsec RRset.
114167802Sjkim *	If there are multiple RRs, then this will only return one of them.
115167802Sjkim * @param nm: the next name is returned.
116167802Sjkim * @param ln: length of nm is returned.
117167802Sjkim * @return false on a bad NSEC RR (too short, malformed dname).
118167802Sjkim */
119167802Sjkimstatic int
120167802Sjkimnsec_get_next(struct ub_packed_rrset_key* nsec, uint8_t** nm, size_t* ln)
121167802Sjkim{
122167802Sjkim	struct packed_rrset_data* d = (struct packed_rrset_data*)nsec->
123167802Sjkim		entry.data;
124167802Sjkim	if(!d || d->count == 0 || d->rr_len[0] < 2+1) {
125167802Sjkim		*nm = 0;
126167802Sjkim		*ln = 0;
127167802Sjkim		return 0;
128167802Sjkim	}
129167802Sjkim	*nm = d->rr_data[0]+2;
130167802Sjkim	*ln = dname_valid(*nm, d->rr_len[0]-2);
131167802Sjkim	if(!*ln) {
132167802Sjkim		*nm = 0;
133167802Sjkim		*ln = 0;
134167802Sjkim		return 0;
135167802Sjkim	}
136167802Sjkim	return 1;
137167802Sjkim}
138104470Siwasaki
13967754Smsmith/**
14067754Smsmith * For an NSEC that matches the DS queried for, check absence of DS type.
141193267Sjkim *
142193267Sjkim * @param nsec: NSEC for proof, must be trusted.
143193267Sjkim * @param qinfo: what is queried for.
144193267Sjkim * @return if secure the nsec proves that no DS is present, or
145193267Sjkim *	insecure if it proves it is not a delegation point.
146193267Sjkim *	or bogus if something was wrong.
147193267Sjkim */
148193267Sjkimstatic enum sec_status
149193267Sjkimval_nsec_proves_no_ds(struct ub_packed_rrset_key* nsec,
150193267Sjkim	struct query_info* qinfo)
151193267Sjkim{
152193267Sjkim	log_assert(qinfo->qtype == LDNS_RR_TYPE_DS);
153193267Sjkim	log_assert(ntohs(nsec->rk.type) == LDNS_RR_TYPE_NSEC);
154193267Sjkim
155193267Sjkim	if(nsec_has_type(nsec, LDNS_RR_TYPE_SOA) && qinfo->qname_len != 1) {
156193267Sjkim		/* SOA present means that this is the NSEC from the child,
157193267Sjkim		 * not the parent (so it is the wrong one). */
158193267Sjkim		return sec_status_bogus;
159193267Sjkim	}
160193267Sjkim	if(nsec_has_type(nsec, LDNS_RR_TYPE_DS)) {
161193267Sjkim		/* DS present means that there should have been a positive
162193267Sjkim		 * response to the DS query, so there is something wrong. */
163193267Sjkim		return sec_status_bogus;
164298714Sjkim	}
165298714Sjkim
166193267Sjkim	if(!nsec_has_type(nsec, LDNS_RR_TYPE_NS)) {
167193267Sjkim		/* If there is no NS at this point at all, then this
168193267Sjkim		 * doesn't prove anything one way or the other. */
169193267Sjkim		return sec_status_insecure;
170193267Sjkim	}
171209746Sjkim	/* Otherwise, this proves no DS. */
172209746Sjkim	return sec_status_secure;
173209746Sjkim}
174209746Sjkim
175209746Sjkim/** check security status from cache or verify rrset, returns true if secure */
176209746Sjkimstatic int
177209746Sjkimnsec_verify_rrset(struct module_env* env, struct val_env* ve,
178193267Sjkim	struct ub_packed_rrset_key* nsec, struct key_entry_key* kkey,
179209746Sjkim	char** reason)
180209746Sjkim{
181209746Sjkim	struct packed_rrset_data* d = (struct packed_rrset_data*)
182209746Sjkim		nsec->entry.data;
183209746Sjkim	if(d->security == sec_status_secure)
184209746Sjkim		return 1;
185209746Sjkim	rrset_check_sec_status(env->rrset_cache, nsec, *env->now);
186193267Sjkim	if(d->security == sec_status_secure)
187193267Sjkim		return 1;
188193267Sjkim	d->security = val_verify_rrset_entry(env, ve, nsec, kkey, reason);
189193267Sjkim	if(d->security == sec_status_secure) {
190193267Sjkim		rrset_update_sec_status(env->rrset_cache, nsec, *env->now);
191193267Sjkim		return 1;
192193267Sjkim	}
193193267Sjkim	return 0;
194193267Sjkim}
195193267Sjkim
196193267Sjkimenum sec_status
197193267Sjkimval_nsec_prove_nodata_dsreply(struct module_env* env, struct val_env* ve,
198193267Sjkim	struct query_info* qinfo, struct reply_info* rep,
199193267Sjkim	struct key_entry_key* kkey, time_t* proof_ttl, char** reason)
200193267Sjkim{
201193267Sjkim	struct ub_packed_rrset_key* nsec = reply_find_rrset_section_ns(
202193267Sjkim		rep, qinfo->qname, qinfo->qname_len, LDNS_RR_TYPE_NSEC,
203193267Sjkim		qinfo->qclass);
204193267Sjkim	enum sec_status sec;
205193267Sjkim	size_t i;
206193267Sjkim	uint8_t* wc = NULL, *ce = NULL;
207193267Sjkim	int valid_nsec = 0;
208193267Sjkim	struct ub_packed_rrset_key* wc_nsec = NULL;
209193267Sjkim
210193267Sjkim	/* If we have a NSEC at the same name, it must prove one
211193267Sjkim	 * of two things
212193267Sjkim	 * --
213193267Sjkim	 * 1) this is a delegation point and there is no DS
214193267Sjkim	 * 2) this is not a delegation point */
215193267Sjkim	if(nsec) {
216193267Sjkim		if(!nsec_verify_rrset(env, ve, nsec, kkey, reason)) {
217193267Sjkim			verbose(VERB_ALGO, "NSEC RRset for the "
218193267Sjkim				"referral did not verify.");
219193267Sjkim			return sec_status_bogus;
22067754Smsmith		}
22167754Smsmith		sec = val_nsec_proves_no_ds(nsec, qinfo);
222167802Sjkim		if(sec == sec_status_bogus) {
22367754Smsmith			/* something was wrong. */
224151937Sjkim			*reason = "NSEC does not prove absence of DS";
225298714Sjkim			return sec;
22667754Smsmith		} else if(sec == sec_status_insecure) {
22767754Smsmith			/* this wasn't a delegation point. */
22867754Smsmith			return sec;
22967754Smsmith		} else if(sec == sec_status_secure) {
23067754Smsmith			/* this proved no DS. */
231298714Sjkim			*proof_ttl = ub_packed_rrset_ttl(nsec);
232298714Sjkim			return sec;
23367754Smsmith		}
23467754Smsmith		/* if unchecked, fall through to next proof */
23577424Smsmith	}
23667754Smsmith
23767754Smsmith	/* Otherwise, there is no NSEC at qname. This could be an ENT.
23867754Smsmith	 * (ENT=empty non terminal). If not, this is broken. */
239193267Sjkim
24067754Smsmith	/* verify NSEC rrsets in auth section */
241193267Sjkim	for(i=rep->an_numrrsets; i < rep->an_numrrsets+rep->ns_numrrsets;
24267754Smsmith		i++) {
24367754Smsmith		if(rep->rrsets[i]->rk.type != htons(LDNS_RR_TYPE_NSEC))
24467754Smsmith			continue;
245151937Sjkim		if(!nsec_verify_rrset(env, ve, rep->rrsets[i], kkey, reason)) {
24667754Smsmith			verbose(VERB_ALGO, "NSEC for empty non-terminal "
24799146Siwasaki				"did not verify.");
24867754Smsmith			return sec_status_bogus;
24999679Siwasaki		}
25099679Siwasaki		if(nsec_proves_nodata(rep->rrsets[i], qinfo, &wc)) {
25199679Siwasaki			verbose(VERB_ALGO, "NSEC for empty non-terminal "
25267754Smsmith				"proved no DS.");
25367754Smsmith			*proof_ttl = rrset_get_ttl(rep->rrsets[i]);
25467754Smsmith			if(wc && dname_is_wild(rep->rrsets[i]->rk.dname))
25567754Smsmith				wc_nsec = rep->rrsets[i];
25667754Smsmith			valid_nsec = 1;
25767754Smsmith		}
25867754Smsmith		if(val_nsec_proves_name_error(rep->rrsets[i], qinfo->qname)) {
259151937Sjkim			ce = nsec_closest_encloser(qinfo->qname,
26067754Smsmith				rep->rrsets[i]);
26167754Smsmith		}
26299146Siwasaki	}
26367754Smsmith	if(wc && !ce)
26467754Smsmith		valid_nsec = 0;
26599146Siwasaki	else if(wc && ce) {
26667754Smsmith		/* ce and wc must match */
26767754Smsmith		if(query_dname_compare(wc, ce) != 0)
26867754Smsmith			valid_nsec = 0;
26967754Smsmith		else if(!wc_nsec)
27099679Siwasaki			valid_nsec = 0;
27199146Siwasaki	}
27267754Smsmith	if(valid_nsec) {
27367754Smsmith		if(wc) {
274167802Sjkim			/* check if this is a delegation */
27567754Smsmith			*reason = "NSEC for wildcard does not prove absence of DS";
27667754Smsmith			return val_nsec_proves_no_ds(wc_nsec, qinfo);
277167802Sjkim		}
278167802Sjkim		/* valid nsec proves empty nonterminal */
279167802Sjkim		return sec_status_insecure;
280167802Sjkim	}
281167802Sjkim
28299146Siwasaki	/* NSEC proof did not conclusively point to DS or no DS */
283167802Sjkim	return sec_status_unchecked;
28467754Smsmith}
28599146Siwasaki
28667754Smsmithint nsec_proves_nodata(struct ub_packed_rrset_key* nsec,
28799146Siwasaki	struct query_info* qinfo, uint8_t** wc)
28899146Siwasaki{
28999146Siwasaki	log_assert(wc);
29099146Siwasaki	if(query_dname_compare(nsec->rk.dname, qinfo->qname) != 0) {
29199146Siwasaki		uint8_t* nm;
29299146Siwasaki		size_t ln;
29399146Siwasaki
29467754Smsmith		/* empty-non-terminal checking.
29567754Smsmith		 * Done before wildcard, because this is an exact match,
29699146Siwasaki		 * and would prevent a wildcard from matching. */
297241973Sjkim
29899146Siwasaki		/* If the nsec is proving that qname is an ENT, the nsec owner
29967754Smsmith		 * will be less than qname, and the next name will be a child
30099679Siwasaki		 * domain of the qname. */
30167754Smsmith		if(!nsec_get_next(nsec, &nm, &ln))
30299679Siwasaki			return 0; /* bad nsec */
30399146Siwasaki		if(dname_strict_subdomain_c(nm, qinfo->qname) &&
30467754Smsmith			dname_canonical_compare(nsec->rk.dname,
30599679Siwasaki				qinfo->qname) < 0) {
30699146Siwasaki			return 1; /* proves ENT */
307167802Sjkim		}
308204773Sjkim
30999679Siwasaki		/* wildcard checking. */
31099146Siwasaki
31199146Siwasaki		/* If this is a wildcard NSEC, make sure that a) it was
31299146Siwasaki		 * possible to have generated qname from the wildcard and
31399146Siwasaki		 * b) the type map does not contain qtype. Note that this
31499146Siwasaki		 * does NOT prove that this wildcard was the applicable
315117521Snjl		 * wildcard. */
31667754Smsmith		if(dname_is_wild(nsec->rk.dname)) {
31767754Smsmith			/* the purported closest encloser. */
31867754Smsmith			uint8_t* ce = nsec->rk.dname;
31999146Siwasaki			size_t ce_len = nsec->rk.dname_len;
320102550Siwasaki			dname_remove_label(&ce, &ce_len);
32199146Siwasaki
32267754Smsmith			/* The qname must be a strict subdomain of the
32399146Siwasaki			 * closest encloser, for the wildcard to apply
32499146Siwasaki			 */
32567754Smsmith			if(dname_strict_subdomain_c(qinfo->qname, ce)) {
32699146Siwasaki				/* here we have a matching NSEC for the qname,
32799146Siwasaki				 * perform matching NSEC checks */
32867754Smsmith				if(nsec_has_type(nsec, LDNS_RR_TYPE_CNAME)) {
32999146Siwasaki				   /* should have gotten the wildcard CNAME */
33067754Smsmith					return 0;
33199146Siwasaki				}
33299146Siwasaki				if(nsec_has_type(nsec, LDNS_RR_TYPE_NS) &&
33399146Siwasaki				   !nsec_has_type(nsec, LDNS_RR_TYPE_SOA)) {
334117521Snjl				   /* wrong parentside (wildcard) NSEC used */
335117521Snjl					return 0;
33667754Smsmith				}
337114237Snjl				if(nsec_has_type(nsec, qinfo->qtype)) {
33899146Siwasaki					return 0;
339298714Sjkim				}
340298714Sjkim				*wc = ce;
341114237Snjl				return 1;
342114237Snjl			}
343114237Snjl		} else {
344114237Snjl			/* See if the next owner name covers a wildcard
345114237Snjl			 * empty non-terminal. */
34699146Siwasaki			while (dname_strict_subdomain_c(nm, nsec->rk.dname)) {
347114237Snjl				/* wildcard does not apply if qname below
34899146Siwasaki				 * the name that exists under the '*' */
349114237Snjl				if (dname_subdomain_c(qinfo->qname, nm))
350114237Snjl					break;
351284583Sjkim				/* but if it is a wildcard and qname is below
352298714Sjkim				 * it, then the wildcard applies. The wildcard
353114237Snjl				 * is an empty nonterminal. nodata proven. */
35499146Siwasaki				if (dname_is_wild(nm)) {
35599146Siwasaki					size_t ce_len = ln;
35699146Siwasaki					uint8_t* ce = nm;
357167802Sjkim					dname_remove_label(&ce, &ce_len);
35899146Siwasaki					if(dname_strict_subdomain_c(qinfo->qname, ce)) {
35967754Smsmith						*wc = ce;
36067754Smsmith						return 1;
36167754Smsmith					}
362151937Sjkim				}
36367754Smsmith				dname_remove_label(&nm, &ln);
36499146Siwasaki			}
36567754Smsmith		}
36699679Siwasaki
36799679Siwasaki		/* Otherwise, this NSEC does not prove ENT and is not a
368167802Sjkim		 * wildcard, so it does not prove NODATA. */
369167802Sjkim		return 0;
37067754Smsmith	}
37167754Smsmith
37267754Smsmith	/* If the qtype exists, then we should have gotten it. */
37367754Smsmith	if(nsec_has_type(nsec, qinfo->qtype)) {
37499146Siwasaki		return 0;
37599146Siwasaki	}
37667754Smsmith
377167802Sjkim	/* if the name is a CNAME node, then we should have gotten the CNAME*/
378167802Sjkim	if(nsec_has_type(nsec, LDNS_RR_TYPE_CNAME)) {
379167802Sjkim		return 0;
380167802Sjkim	}
381167802Sjkim
382167802Sjkim	/* If an NS set exists at this name, and NOT a SOA (so this is a
383167802Sjkim	 * zone cut, not a zone apex), then we should have gotten a
384167802Sjkim	 * referral (or we just got the wrong NSEC).
385167802Sjkim	 * The reverse of this check is used when qtype is DS, since that
386167802Sjkim	 * must use the NSEC from above the zone cut. */
387167802Sjkim	if(qinfo->qtype != LDNS_RR_TYPE_DS &&
388167802Sjkim		nsec_has_type(nsec, LDNS_RR_TYPE_NS) &&
389151937Sjkim		!nsec_has_type(nsec, LDNS_RR_TYPE_SOA)) {
39067754Smsmith		return 0;
39167754Smsmith	} else if(qinfo->qtype == LDNS_RR_TYPE_DS &&
39299146Siwasaki		nsec_has_type(nsec, LDNS_RR_TYPE_SOA) &&
39367754Smsmith		!dname_is_root(qinfo->qname)) {
39467754Smsmith		return 0;
395167802Sjkim	}
39667754Smsmith
39767754Smsmith	return 1;
39899146Siwasaki}
39999146Siwasaki
40099146Siwasakiint
40199146Siwasakival_nsec_proves_name_error(struct ub_packed_rrset_key* nsec, uint8_t* qname)
402193267Sjkim{
403167802Sjkim	uint8_t* owner = nsec->rk.dname;
404167802Sjkim	uint8_t* next;
40567754Smsmith	size_t nlen;
40667754Smsmith	if(!nsec_get_next(nsec, &next, &nlen))
407167802Sjkim		return 0;
40899146Siwasaki
40999146Siwasaki	/* If NSEC owner == qname, then this NSEC proves that qname exists. */
41099146Siwasaki	if(query_dname_compare(qname, owner) == 0) {
41199146Siwasaki		return 0;
41299679Siwasaki	}
413167802Sjkim
41499679Siwasaki	/* If NSEC is a parent of qname, we need to check the type map
41567754Smsmith	 * If the parent name has a DNAME or is a delegation point, then
41699679Siwasaki	 * this NSEC is being misused. */
41799146Siwasaki	if(dname_subdomain_c(qname, owner) &&
41882367Smsmith		(nsec_has_type(nsec, LDNS_RR_TYPE_DNAME) ||
419167802Sjkim		(nsec_has_type(nsec, LDNS_RR_TYPE_NS)
420167802Sjkim			&& !nsec_has_type(nsec, LDNS_RR_TYPE_SOA))
421167802Sjkim		)) {
422167802Sjkim		return 0;
42399146Siwasaki	}
424167802Sjkim
42599146Siwasaki	if(query_dname_compare(owner, next) == 0) {
42699146Siwasaki		/* this nsec is the only nsec */
42799146Siwasaki		/* zone.name NSEC zone.name, disproves everything else */
42899146Siwasaki		/* but only for subdomains of that zone */
42999146Siwasaki		if(dname_strict_subdomain_c(qname, next))
43099146Siwasaki			return 1;
43199146Siwasaki	}
43267754Smsmith	else if(dname_canonical_compare(owner, next) > 0) {
43399679Siwasaki		/* this is the last nsec, ....(bigger) NSEC zonename(smaller) */
43499146Siwasaki		/* the names after the last (owner) name do not exist
43582367Smsmith		 * there are no names before the zone name in the zone
43699146Siwasaki		 * but the qname must be a subdomain of the zone name(next). */
437167802Sjkim		if(dname_canonical_compare(owner, qname) < 0 &&
438167802Sjkim			dname_strict_subdomain_c(qname, next))
439167802Sjkim			return 1;
44099146Siwasaki	} else {
441167802Sjkim		/* regular NSEC, (smaller) NSEC (larger) */
442167802Sjkim		if(dname_canonical_compare(owner, qname) < 0 &&
44399146Siwasaki		   dname_canonical_compare(qname, next) < 0) {
44499146Siwasaki			return 1;
44599146Siwasaki		}
44699146Siwasaki	}
44799146Siwasaki	return 0;
44899146Siwasaki}
44999146Siwasaki
450167802Sjkimint val_nsec_proves_insecuredelegation(struct ub_packed_rrset_key* nsec,
451167802Sjkim	struct query_info* qinfo)
45299146Siwasaki{
453167802Sjkim	if(nsec_has_type(nsec, LDNS_RR_TYPE_NS) &&
454167802Sjkim		!nsec_has_type(nsec, LDNS_RR_TYPE_DS) &&
455167802Sjkim		!nsec_has_type(nsec, LDNS_RR_TYPE_SOA)) {
456167802Sjkim		/* see if nsec signals an insecure delegation */
45799146Siwasaki		if(qinfo->qtype == LDNS_RR_TYPE_DS) {
45899679Siwasaki			/* if type is DS and qname is equal to nsec, then it
45999679Siwasaki			 * is an exact match nsec, result not insecure */
460167802Sjkim			if(dname_strict_subdomain_c(qinfo->qname,
46199146Siwasaki				nsec->rk.dname))
46299679Siwasaki				return 1;
46399146Siwasaki		} else {
464193267Sjkim			if(dname_subdomain_c(qinfo->qname, nsec->rk.dname))
465193267Sjkim				return 1;
466193267Sjkim		}
467193267Sjkim	}
468193267Sjkim	return 0;
469193267Sjkim}
470193267Sjkim
471298714Sjkimuint8_t*
472298714Sjkimnsec_closest_encloser(uint8_t* qname, struct ub_packed_rrset_key* nsec)
473193267Sjkim{
474193267Sjkim	uint8_t* next;
475193267Sjkim	size_t nlen;
476193267Sjkim	uint8_t* common1, *common2;
47799146Siwasaki	if(!nsec_get_next(nsec, &next, &nlen))
478193267Sjkim		return NULL;
479193267Sjkim	/* longest common with owner or next name */
480193267Sjkim	common1 = dname_get_shared_topdomain(nsec->rk.dname, qname);
48199146Siwasaki	common2 = dname_get_shared_topdomain(next, qname);
48299146Siwasaki	if(dname_count_labels(common1) > dname_count_labels(common2))
48399146Siwasaki		return common1;
484298714Sjkim	return common2;
485298714Sjkim}
48699146Siwasaki
48799146Siwasakiint val_nsec_proves_positive_wildcard(struct ub_packed_rrset_key* nsec,
488167802Sjkim	struct query_info* qinf, uint8_t* wc)
489167802Sjkim{
490167802Sjkim	uint8_t* ce;
491167802Sjkim	/*  1) prove that qname doesn't exist and
492167802Sjkim	 *  2) that the correct wildcard was used
493167802Sjkim	 *  nsec has been verified already. */
494167802Sjkim	if(!val_nsec_proves_name_error(nsec, qinf->qname))
495167802Sjkim		return 0;
496167802Sjkim	/* check wildcard name */
497167802Sjkim	ce = nsec_closest_encloser(qinf->qname, nsec);
498167802Sjkim	if(!ce)
499167802Sjkim		return 0;
500167802Sjkim	if(query_dname_compare(wc, ce) != 0) {
501167802Sjkim		return 0;
502167802Sjkim	}
503167802Sjkim	return 1;
50499679Siwasaki}
50599146Siwasaki
50699146Siwasakiint
507193267Sjkimval_nsec_proves_no_wc(struct ub_packed_rrset_key* nsec, uint8_t* qname,
508193267Sjkim	size_t qnamelen)
509193267Sjkim{
510167802Sjkim	/* Determine if a NSEC record proves the non-existence of a
511193267Sjkim	 * wildcard that could have produced qname. */
512193267Sjkim	int labs;
513197104Sjkim	int i;
514193267Sjkim	uint8_t* ce = nsec_closest_encloser(qname, nsec);
515193267Sjkim	uint8_t* strip;
516193267Sjkim	size_t striplen;
517199337Sjkim	uint8_t buf[LDNS_MAX_DOMAINLEN+3];
518197104Sjkim	if(!ce)
519197104Sjkim		return 0;
520197104Sjkim	/* we can subtract the closest encloser count - since that is the
521193267Sjkim	 * largest shared topdomain with owner and next NSEC name,
522193267Sjkim	 * because the NSEC is no proof for names shorter than the owner
523193267Sjkim	 * and next names. */
524197104Sjkim	labs = dname_count_labels(qname) - dname_count_labels(ce);
525197104Sjkim
526197104Sjkim	for(i=labs; i>0; i--) {
527197104Sjkim		/* i is number of labels to strip off qname, prepend * wild */
528197104Sjkim		strip = qname;
529197104Sjkim		striplen = qnamelen;
530197104Sjkim		dname_remove_labels(&strip, &striplen, i);
531197104Sjkim		if(striplen > LDNS_MAX_DOMAINLEN-2)
532197104Sjkim			continue; /* too long to prepend wildcard */
533197104Sjkim		buf[0] = 1;
534197104Sjkim		buf[1] = (uint8_t)'*';
535193267Sjkim		memmove(buf+2, strip, striplen);
536193267Sjkim		if(val_nsec_proves_name_error(nsec, buf)) {
537193267Sjkim			return 1;
538193267Sjkim		}
539193267Sjkim	}
540193267Sjkim	return 0;
541298714Sjkim}
542298714Sjkim
543298714Sjkim/**
544193267Sjkim * Find shared topdomain that exists
545193267Sjkim */
546193267Sjkimstatic void
547193267Sjkimdlv_topdomain(struct ub_packed_rrset_key* nsec, uint8_t* qname,
548193267Sjkim	uint8_t** nm, size_t* nm_len)
549193267Sjkim{
550193267Sjkim	/* make sure reply is part of nm */
551193267Sjkim	/* take shared topdomain with left of NSEC. */
552167802Sjkim
553298714Sjkim	/* because, if empty nonterminal, then right is subdomain of qname.
554298714Sjkim	 * and any shared topdomain would be empty nonterminals.
555193267Sjkim	 *
556167802Sjkim	 * If nxdomain, then the right is bigger, and could have an
557167802Sjkim	 * interesting shared topdomain, but if it does have one, it is
55899146Siwasaki	 * an empty nonterminal. An empty nonterminal shared with the left
559167802Sjkim	 * one. */
56099146Siwasaki	int n;
56167754Smsmith	uint8_t* common = dname_get_shared_topdomain(qname, nsec->rk.dname);
56267754Smsmith	n = dname_count_labels(*nm) - dname_count_labels(common);
56367754Smsmith	dname_remove_labels(nm, nm_len, n);
564151937Sjkim}
56567754Smsmith
56667754Smsmithint val_nsec_check_dlv(struct query_info* qinfo,
56767754Smsmith        struct reply_info* rep, uint8_t** nm, size_t* nm_len)
56899679Siwasaki{
56999679Siwasaki	uint8_t* next;
57099679Siwasaki	size_t i, nlen;
57167754Smsmith	int c;
57267754Smsmith	/* we should now have a NOERROR/NODATA or NXDOMAIN message */
57367754Smsmith	if(rep->an_numrrsets != 0) {
57499679Siwasaki		return 0;
57567754Smsmith	}
576151937Sjkim	/* is this NOERROR ? */
57767754Smsmith	if(FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NOERROR) {
57867754Smsmith		/* it can be a plain NSEC match - go up one more level. */
57967754Smsmith		/* or its an empty nonterminal - go up to nonempty level */
58067754Smsmith		for(i=0; i<rep->ns_numrrsets; i++) {
58167754Smsmith			if(htons(rep->rrsets[i]->rk.type)!=LDNS_RR_TYPE_NSEC ||
58267754Smsmith				!nsec_get_next(rep->rrsets[i], &next, &nlen))
58367754Smsmith				continue;
58467754Smsmith			c = dname_canonical_compare(
58567754Smsmith				rep->rrsets[i]->rk.dname, qinfo->qname);
58667754Smsmith			if(c == 0) {
58767754Smsmith				/* plain match */
588167802Sjkim				if(nsec_has_type(rep->rrsets[i],
58967754Smsmith					LDNS_RR_TYPE_DLV))
59067754Smsmith					return 0;
59185756Smsmith				dname_remove_label(nm, nm_len);
59285756Smsmith				return 1;
593241973Sjkim			} else if(c < 0 &&
59485756Smsmith				dname_strict_subdomain_c(next, qinfo->qname)) {
59585756Smsmith				/* ENT */
59687031Smsmith				dlv_topdomain(rep->rrsets[i], qinfo->qname,
59785756Smsmith					nm, nm_len);
59885756Smsmith				return 1;
59985756Smsmith			}
60085756Smsmith		}
60199679Siwasaki		return 0;
60267754Smsmith	}
60367754Smsmith
60467754Smsmith	/* is this NXDOMAIN ? */
60567754Smsmith	if(FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NXDOMAIN) {
60667754Smsmith		/* find the qname denial NSEC record. It can tell us
60767754Smsmith		 * a closest encloser name; or that we not need bother */
60867754Smsmith		for(i=0; i<rep->ns_numrrsets; i++) {
60967754Smsmith			if(htons(rep->rrsets[i]->rk.type) != LDNS_RR_TYPE_NSEC)
610298714Sjkim				continue;
611298714Sjkim			if(val_nsec_proves_name_error(rep->rrsets[i],
61267754Smsmith				qinfo->qname)) {
61367754Smsmith				log_nametypeclass(VERB_ALGO, "topdomain on",
61467754Smsmith					rep->rrsets[i]->rk.dname,
61567754Smsmith					ntohs(rep->rrsets[i]->rk.type), 0);
61667754Smsmith				dlv_topdomain(rep->rrsets[i], qinfo->qname,
617114237Snjl					nm, nm_len);
61867754Smsmith				return 1;
619193267Sjkim			}
62067754Smsmith		}
62199146Siwasaki		return 0;
62267754Smsmith	}
62391116Smsmith	return 0;
62467754Smsmith}
62585756Smsmith