1 /*
2  * nsec3.c -- nsec3 handling.
3  *
4  * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
5  *
6  * See LICENSE for the license.
7  *
8  */
9 #include "config.h"
10 #ifdef NSEC3
11 #include <stdio.h>
12 #include <stdlib.h>
13 
14 #include "nsec3.h"
15 #include "iterated_hash.h"
16 #include "namedb.h"
17 #include "nsd.h"
18 #include "answer.h"
19 #include "udbzone.h"
20 #include "options.h"
21 
22 #define NSEC3_RDATA_BITMAP 5
23 
24 /* compare nsec3 hashes in nsec3 tree */
25 static int
cmp_hash_tree(const void * x,const void * y)26 cmp_hash_tree(const void* x, const void* y)
27 {
28 	const domain_type* a = (const domain_type*)x;
29 	const domain_type* b = (const domain_type*)y;
30 	if(!a->nsec3) return (b->nsec3?-1:0);
31 	if(!b->nsec3) return 1;
32 	if(!a->nsec3->hash_wc) return (b->nsec3->hash_wc?-1:0);
33 	if(!b->nsec3->hash_wc) return 1;
34 	return memcmp(a->nsec3->hash_wc->hash.hash,
35 		b->nsec3->hash_wc->hash.hash, NSEC3_HASH_LEN);
36 }
37 
38 /* compare nsec3 hashes in nsec3 wc tree */
39 static int
cmp_wchash_tree(const void * x,const void * y)40 cmp_wchash_tree(const void* x, const void* y)
41 {
42 	const domain_type* a = (const domain_type*)x;
43 	const domain_type* b = (const domain_type*)y;
44 	if(!a->nsec3) return (b->nsec3?-1:0);
45 	if(!b->nsec3) return 1;
46 	if(!a->nsec3->hash_wc) return (b->nsec3->hash_wc?-1:0);
47 	if(!b->nsec3->hash_wc) return 1;
48 	return memcmp(a->nsec3->hash_wc->wc.hash,
49 		b->nsec3->hash_wc->wc.hash, NSEC3_HASH_LEN);
50 }
51 
52 /* compare nsec3 hashes in nsec3 ds tree */
53 static int
cmp_dshash_tree(const void * x,const void * y)54 cmp_dshash_tree(const void* x, const void* y)
55 {
56 	const domain_type* a = (const domain_type*)x;
57 	const domain_type* b = (const domain_type*)y;
58 	if(!a->nsec3) return (b->nsec3?-1:0);
59 	if(!b->nsec3) return 1;
60 	if(!a->nsec3->ds_parent_hash) return (b->nsec3->ds_parent_hash?-1:0);
61 	if(!b->nsec3->ds_parent_hash) return 1;
62 	return memcmp(a->nsec3->ds_parent_hash->hash,
63 		b->nsec3->ds_parent_hash->hash, NSEC3_HASH_LEN);
64 }
65 
66 /* compare base32-encoded nsec3 hashes in nsec3 rr tree, they are
67  * stored in the domain name of the node */
68 static int
cmp_nsec3_tree(const void * x,const void * y)69 cmp_nsec3_tree(const void* x, const void* y)
70 {
71 	const domain_type* a = (const domain_type*)x;
72 	const domain_type* b = (const domain_type*)y;
73 	/* labelcount + 32long label */
74 	assert(dname_name(domain_dname_const(a))[0] == 32);
75 	assert(dname_name(domain_dname_const(b))[0] == 32);
76 	return memcmp(dname_name(domain_dname_const(a)), dname_name(domain_dname_const(b)), 33);
77 }
78 
nsec3_zone_trees_create(struct region * region,zone_type * zone)79 void nsec3_zone_trees_create(struct region* region, zone_type* zone)
80 {
81 	if(!zone->nsec3tree)
82 		zone->nsec3tree = rbtree_create(region, cmp_nsec3_tree);
83 	if(!zone->hashtree)
84 		zone->hashtree = rbtree_create(region, cmp_hash_tree);
85 	if(!zone->wchashtree)
86 		zone->wchashtree = rbtree_create(region, cmp_wchash_tree);
87 	if(!zone->dshashtree)
88 		zone->dshashtree = rbtree_create(region, cmp_dshash_tree);
89 }
90 
91 static void
detect_nsec3_params(rr_type * nsec3_apex,const unsigned char ** salt,int * salt_len,int * iter)92 detect_nsec3_params(rr_type* nsec3_apex,
93 	const unsigned char** salt, int* salt_len, int* iter)
94 {
95 	assert(salt && salt_len && iter);
96 	assert(nsec3_apex);
97 	*salt_len = rdata_atom_data(nsec3_apex->rdatas[3])[0];
98 	*salt = (unsigned char*)(rdata_atom_data(nsec3_apex->rdatas[3])+1);
99 	*iter = read_uint16(rdata_atom_data(nsec3_apex->rdatas[2]));
100 }
101 
102 const dname_type *
nsec3_b32_create(region_type * region,zone_type * zone,unsigned char * hash)103 nsec3_b32_create(region_type* region, zone_type* zone, unsigned char* hash)
104 {
105 	const dname_type* dname;
106 	char b32[SHA_DIGEST_LENGTH*2+1];
107 	b32_ntop(hash, SHA_DIGEST_LENGTH, b32, sizeof(b32));
108 	dname=dname_parse(region, b32);
109 	dname=dname_concatenate(region, dname, domain_dname(zone->apex));
110 	return dname;
111 }
112 
113 void
nsec3_hash_and_store(zone_type * zone,const dname_type * dname,uint8_t * store)114 nsec3_hash_and_store(zone_type* zone, const dname_type* dname, uint8_t* store)
115 {
116 	const unsigned char* nsec3_salt = NULL;
117 	int nsec3_saltlength = 0;
118 	int nsec3_iterations = 0;
119 
120 	detect_nsec3_params(zone->nsec3_param, &nsec3_salt,
121 		&nsec3_saltlength, &nsec3_iterations);
122 	assert(nsec3_iterations >= 0 && nsec3_iterations <= 65536);
123 	iterated_hash((unsigned char*)store, nsec3_salt, nsec3_saltlength,
124 		dname_name(dname), dname->name_size, nsec3_iterations);
125 }
126 
127 #define STORE_HASH(x,y) memmove(domain->nsec3->x,y,NSEC3_HASH_LEN); domain->nsec3->have_##x =1;
128 
129 /** find hash or create it and store it */
130 static void
nsec3_lookup_hash_and_wc(region_type * region,zone_type * zone,const dname_type * dname,domain_type * domain,region_type * tmpregion)131 nsec3_lookup_hash_and_wc(region_type* region, zone_type* zone,
132 	const dname_type* dname, domain_type* domain, region_type* tmpregion)
133 {
134 	const dname_type* wcard;
135 	if(domain->nsec3->hash_wc) {
136 		return;
137 	}
138 	/* lookup failed; disk failure or so */
139 	domain->nsec3->hash_wc = (nsec3_hash_wc_node_type *)
140 		region_alloc(region, sizeof(nsec3_hash_wc_node_type));
141 	domain->nsec3->hash_wc->hash.node.key = NULL;
142 	domain->nsec3->hash_wc->wc.node.key = NULL;
143 	nsec3_hash_and_store(zone, dname, domain->nsec3->hash_wc->hash.hash);
144 	wcard = dname_parse(tmpregion, "*");
145 	wcard = dname_concatenate(tmpregion, wcard, dname);
146 	nsec3_hash_and_store(zone, wcard, domain->nsec3->hash_wc->wc.hash);
147 }
148 
149 static void
nsec3_lookup_hash_ds(region_type * region,zone_type * zone,const dname_type * dname,domain_type * domain)150 nsec3_lookup_hash_ds(region_type* region, zone_type* zone,
151 	const dname_type* dname, domain_type* domain)
152 {
153 	if(domain->nsec3->ds_parent_hash) {
154 		return;
155 	}
156 	/* lookup failed; disk failure or so */
157 	domain->nsec3->ds_parent_hash = (nsec3_hash_node_type *)
158 		region_alloc(region, sizeof(nsec3_hash_node_type));
159 	domain->nsec3->ds_parent_hash->node.key = NULL;
160 	nsec3_hash_and_store(zone, dname, domain->nsec3->ds_parent_hash->hash);
161 }
162 
163 static int
nsec3_has_soa(rr_type * rr)164 nsec3_has_soa(rr_type* rr)
165 {
166 	if(rdata_atom_size(rr->rdatas[NSEC3_RDATA_BITMAP]) >= 3 && /* has types in bitmap */
167 		rdata_atom_data(rr->rdatas[NSEC3_RDATA_BITMAP])[0] == 0 && /* first window = 0, */
168 		/* [1]: bitmap length must be >= 1 */
169 		/* [2]: bit[6] = SOA, thus mask first bitmap octet with 0x02 */
170 		rdata_atom_data(rr->rdatas[NSEC3_RDATA_BITMAP])[2]&0x02) { /* SOA bit set */
171 		return 1;
172 	}
173 	return 0;
174 }
175 
176 static rr_type*
check_apex_soa(namedb_type * namedb,zone_type * zone,int nolog)177 check_apex_soa(namedb_type* namedb, zone_type *zone, int nolog)
178 {
179 	uint8_t h[NSEC3_HASH_LEN];
180 	domain_type* domain;
181 	const dname_type* hashed_apex, *dname = domain_dname(zone->apex);
182 	unsigned j;
183 	rrset_type* nsec3_rrset;
184 	region_type* tmpregion;
185 
186 	nsec3_hash_and_store(zone, dname, h);
187 	tmpregion = region_create(xalloc, free);
188 	hashed_apex = nsec3_b32_create(tmpregion, zone, h);
189 	domain = domain_table_find(namedb->domains, hashed_apex);
190 	if(!domain) {
191 		if(!nolog) {
192 			log_msg(LOG_ERR, "%s NSEC3PARAM entry has no hash(apex).",
193 				domain_to_string(zone->apex));
194 			log_msg(LOG_ERR, "hash(apex)= %s",
195 				dname_to_string(hashed_apex, NULL));
196 		}
197 		region_destroy(tmpregion);
198 		return NULL;
199 	}
200 	nsec3_rrset = domain_find_rrset(domain, zone, TYPE_NSEC3);
201 	if(!nsec3_rrset) {
202 		if(!nolog) {
203 			log_msg(LOG_ERR, "%s NSEC3PARAM entry: hash(apex) has no NSEC3 RRset.",
204 				domain_to_string(zone->apex));
205 			log_msg(LOG_ERR, "hash(apex)= %s",
206 				dname_to_string(hashed_apex, NULL));
207 		}
208 		region_destroy(tmpregion);
209 		return NULL;
210 	}
211 	for(j=0; j<nsec3_rrset->rr_count; j++) {
212 		if(nsec3_has_soa(&nsec3_rrset->rrs[j])) {
213 			region_destroy(tmpregion);
214 			return &nsec3_rrset->rrs[j];
215 		}
216 	}
217 	if(!nolog) {
218 		log_msg(LOG_ERR, "%s NSEC3PARAM entry: hash(apex) NSEC3 has no SOA flag.",
219 			domain_to_string(zone->apex));
220 		log_msg(LOG_ERR, "hash(apex)= %s",
221 			dname_to_string(hashed_apex, NULL));
222 	}
223 	region_destroy(tmpregion);
224 	return NULL;
225 }
226 
227 static void
nsec3param_to_str(struct rr * rr,char * str,size_t buflen)228 nsec3param_to_str(struct rr* rr, char* str, size_t buflen)
229 {
230 	rdata_atom_type* rd = rr->rdatas;
231 	size_t len;
232 	len = snprintf(str, buflen, "%u %u %u ",
233 		(unsigned)rdata_atom_data(rd[0])[0],
234 		(unsigned)rdata_atom_data(rd[1])[0],
235 		(unsigned)read_uint16(rdata_atom_data(rd[2])));
236 	if(rdata_atom_data(rd[3])[0] == 0) {
237 		if(buflen > len + 2)
238 			str[len++] = '-';
239 	} else {
240 		len += hex_ntop(rdata_atom_data(rd[3])+1,
241 			rdata_atom_data(rd[3])[0], str+len, buflen-len-1);
242 	}
243 	if(buflen > len + 1)
244 		str[len] = 0;
245 }
246 
247 static struct rr*
db_find_nsec3param(struct namedb * db,struct zone * z,struct rr * avoid_rr,int checkchain)248 db_find_nsec3param(struct namedb* db, struct zone* z, struct rr* avoid_rr,
249 	int checkchain)
250 {
251 	unsigned i;
252 	rrset_type* rrset = domain_find_rrset(z->apex, z, TYPE_NSEC3PARAM);
253 	if(!rrset) /* no NSEC3PARAM in mem */
254 		return NULL;
255 	/* find first nsec3param we can support (SHA1, no flags) */
256 	for(i=0; i<rrset->rr_count; i++) {
257 		rdata_atom_type* rd = rrset->rrs[i].rdatas;
258 		/* do not use the RR that is going to be deleted (in IXFR) */
259 		if(&rrset->rrs[i] == avoid_rr) continue;
260 		if(rrset->rrs[i].rdata_count < 4) continue;
261 		if(rdata_atom_data(rd[0])[0] == NSEC3_SHA1_HASH &&
262 			rdata_atom_data(rd[1])[0] == 0) {
263 			if(checkchain) {
264 				z->nsec3_param = &rrset->rrs[i];
265 				if(!check_apex_soa(db, z, 1)) {
266 					char str[MAX_RDLENGTH*2+16];
267 					nsec3param_to_str(z->nsec3_param,
268 						str, sizeof(str));
269 					VERBOSITY(1, (LOG_WARNING, "zone %s NSEC3PARAM %s has broken chain, ignoring", domain_to_string(z->apex), str));
270 					continue; /* don't use broken chain */
271 				}
272 			}
273 			if(2 <= verbosity) {
274 				char str[MAX_RDLENGTH*2+16];
275 				nsec3param_to_str(&rrset->rrs[i], str,
276 					sizeof(str));
277 				VERBOSITY(2, (LOG_INFO, "rehash of zone %s with parameters %s",
278 					domain_to_string(z->apex), str));
279 			}
280 			return &rrset->rrs[i];
281 		}
282 	}
283 	return NULL;
284 }
285 
286 static struct rr*
udb_zone_find_nsec3param(struct namedb * db,udb_base * udb,udb_ptr * uz,struct zone * z,int checkchain)287 udb_zone_find_nsec3param(struct namedb* db, udb_base* udb, udb_ptr* uz,
288 	struct zone* z, int checkchain)
289 {
290 	udb_ptr urr;
291 	unsigned i;
292 	rrset_type* rrset = domain_find_rrset(z->apex, z, TYPE_NSEC3PARAM);
293 	if(!rrset) /* no NSEC3PARAM in mem */
294 		return NULL;
295 	udb_ptr_new(&urr, udb, &ZONE(uz)->nsec3param);
296 	if(!urr.data || RR(&urr)->len < 5) {
297 		/* no NSEC3PARAM in udb */
298 		udb_ptr_unlink(&urr, udb);
299 		return NULL;
300 	}
301 	/* find matching NSEC3PARAM RR in memory */
302 	for(i=0; i<rrset->rr_count; i++) {
303 		/* if this RR matches the udb RR then we are done */
304 		rdata_atom_type* rd = rrset->rrs[i].rdatas;
305 		if(rrset->rrs[i].rdata_count < 4) continue;
306 		if(RR(&urr)->wire[0] == rdata_atom_data(rd[0])[0] && /*alg*/
307 		   RR(&urr)->wire[1] == rdata_atom_data(rd[1])[0] && /*flg*/
308 		   RR(&urr)->wire[2] == rdata_atom_data(rd[2])[0] && /*iter*/
309 		   RR(&urr)->wire[3] == rdata_atom_data(rd[2])[1] &&
310 		   RR(&urr)->wire[4] == rdata_atom_data(rd[3])[0] && /*slen*/
311 		   RR(&urr)->len >= 5 + RR(&urr)->wire[4] &&
312 		   memcmp(RR(&urr)->wire+5, rdata_atom_data(rd[3])+1,
313 			rdata_atom_data(rd[3])[0]) == 0) {
314 			udb_ptr_unlink(&urr, udb);
315 			if(checkchain) {
316 				z->nsec3_param = &rrset->rrs[i];
317 				if(!check_apex_soa(db, z, 1))
318 					return db_find_nsec3param(db, z,
319 						NULL, checkchain);
320 			}
321 			return &rrset->rrs[i];
322 		}
323 	}
324 	udb_ptr_unlink(&urr, udb);
325 	return NULL;
326 }
327 
328 void
nsec3_find_zone_param(struct namedb * db,struct zone * zone,udb_ptr * z,struct rr * avoid_rr,int checkchain)329 nsec3_find_zone_param(struct namedb* db, struct zone* zone, udb_ptr* z,
330 	struct rr* avoid_rr, int checkchain)
331 {
332 	/* get nsec3param RR from udb */
333 	if(db->udb)
334 		zone->nsec3_param = udb_zone_find_nsec3param(db, db->udb,
335 			z, zone, checkchain);
336 	/* no db, get from memory, avoid using the rr that is going to be
337 	 * deleted, avoid_rr */
338 	else	zone->nsec3_param = db_find_nsec3param(db, zone, avoid_rr,
339 			checkchain);
340 }
341 
342 /* check params ok for one RR */
343 static int
nsec3_rdata_params_ok(rdata_atom_type * prd,rdata_atom_type * rd)344 nsec3_rdata_params_ok(rdata_atom_type* prd, rdata_atom_type* rd)
345 {
346 	return (rdata_atom_data(rd[0])[0] ==
347 		rdata_atom_data(prd[0])[0] && /* hash algo */
348 	   rdata_atom_data(rd[2])[0] ==
349 		rdata_atom_data(prd[2])[0] && /* iterations 0 */
350 	   rdata_atom_data(rd[2])[1] ==
351 		rdata_atom_data(prd[2])[1] && /* iterations 1 */
352 	   rdata_atom_data(rd[3])[0] ==
353 		rdata_atom_data(prd[3])[0] && /* salt length */
354 	   memcmp(rdata_atom_data(rd[3])+1,
355 		rdata_atom_data(prd[3])+1, rdata_atom_data(rd[3])[0])
356 		== 0 );
357 }
358 
359 int
nsec3_rr_uses_params(rr_type * rr,zone_type * zone)360 nsec3_rr_uses_params(rr_type* rr, zone_type* zone)
361 {
362 	if(!rr || rr->rdata_count < 4)
363 		return 0;
364 	return nsec3_rdata_params_ok(zone->nsec3_param->rdatas, rr->rdatas);
365 }
366 
367 int
nsec3_in_chain_count(domain_type * domain,zone_type * zone)368 nsec3_in_chain_count(domain_type* domain, zone_type* zone)
369 {
370 	rrset_type* rrset = domain_find_rrset(domain, zone, TYPE_NSEC3);
371 	unsigned i;
372 	int count = 0;
373 	if(!rrset || !zone->nsec3_param)
374 		return 0; /* no NSEC3s, none in the chain */
375 	for(i=0; i<rrset->rr_count; i++) {
376 		if(nsec3_rr_uses_params(&rrset->rrs[i], zone))
377 			count++;
378 	}
379 	return count;
380 }
381 
382 struct domain*
nsec3_chain_find_prev(struct zone * zone,struct domain * domain)383 nsec3_chain_find_prev(struct zone* zone, struct domain* domain)
384 {
385 	if(domain->nsec3 && domain->nsec3->nsec3_node.key) {
386 		/* see if there is a prev */
387 		rbnode_type* r = rbtree_previous(&domain->nsec3->nsec3_node);
388 		if(r != RBTREE_NULL) {
389 			/* found a previous, which is not the root-node in
390 			 * the prehash tree (and thus points to the tree) */
391 			return (domain_type*)r->key;
392 		}
393 	}
394 	if(zone->nsec3_last && zone->nsec3_last != domain)
395 		return zone->nsec3_last;
396 	return NULL;
397 }
398 
399 
400 /** clear hash tree. Called from nsec3_clear_precompile() only. */
401 static void
hash_tree_clear(rbtree_type * tree)402 hash_tree_clear(rbtree_type* tree)
403 {
404 	if(!tree) return;
405 
406 	/* Previously (before commit 4ca61188b3f7a0e077476875810d18a5d439871f
407 	 * and/or svn commit 4776) prehashes and corresponding rbtree nodes
408 	 * were part of struct nsec3_domain_data. Clearing the hash_tree would
409 	 * then mean setting the key value of the nodes to NULL to indicate
410 	 * absence of the prehash.
411 	 * But since prehash structs are separatly allocated, this is no longer
412 	 * necessary as currently the prehash structs are simply recycled and
413 	 * NULLed.
414 	 *
415 	 * rbnode_type* n;
416 	 * for(n=rbtree_first(tree); n!=RBTREE_NULL; n=rbtree_next(n)) {
417 	 *	n->key = NULL;
418 	 * }
419 	 */
420 	tree->count = 0;
421 	tree->root = RBTREE_NULL;
422 }
423 
424 void
nsec3_clear_precompile(struct namedb * db,zone_type * zone)425 nsec3_clear_precompile(struct namedb* db, zone_type* zone)
426 {
427 	domain_type* walk;
428 	/* clear prehash items (there must not be items for other zones) */
429 	prehash_clear(db->domains);
430 	/* clear trees */
431 	hash_tree_clear(zone->nsec3tree);
432 	hash_tree_clear(zone->hashtree);
433 	hash_tree_clear(zone->wchashtree);
434 	hash_tree_clear(zone->dshashtree);
435 	/* wipe hashes */
436 
437 	/* wipe precompile */
438 	walk = zone->apex;
439 	while(walk && domain_is_subdomain(walk, zone->apex)) {
440 		if(walk->nsec3) {
441 			if(nsec3_condition_hash(walk, zone)) {
442 				walk->nsec3->nsec3_node.key = NULL;
443 				walk->nsec3->nsec3_cover = NULL;
444 				walk->nsec3->nsec3_wcard_child_cover = NULL;
445 				walk->nsec3->nsec3_is_exact = 0;
446 				if (walk->nsec3->hash_wc) {
447 					region_recycle(db->domains->region,
448 						walk->nsec3->hash_wc,
449 						sizeof(nsec3_hash_wc_node_type));
450 					walk->nsec3->hash_wc = NULL;
451 				}
452 			}
453 			if(nsec3_condition_dshash(walk, zone)) {
454 				walk->nsec3->nsec3_ds_parent_cover = NULL;
455 				walk->nsec3->nsec3_ds_parent_is_exact = 0;
456 				if (walk->nsec3->ds_parent_hash) {
457 					region_recycle(db->domains->region,
458 						walk->nsec3->ds_parent_hash,
459 						sizeof(nsec3_hash_node_type));
460 					walk->nsec3->ds_parent_hash = NULL;
461 				}
462 			}
463 		}
464 		walk = domain_next(walk);
465 	}
466 	zone->nsec3_last = NULL;
467 }
468 
469 /* see if domain name is part of (existing names in) the nsec3 zone */
470 int
nsec3_domain_part_of_zone(domain_type * d,zone_type * z)471 nsec3_domain_part_of_zone(domain_type* d, zone_type* z)
472 {
473 	while(d) {
474 		if(d->is_apex)
475 			return (z->apex == d); /* zonecut, if right zone*/
476 		d = d->parent;
477 	}
478 	return 0;
479 }
480 
481 /* condition when a domain is precompiled */
482 int
nsec3_condition_hash(domain_type * d,zone_type * z)483 nsec3_condition_hash(domain_type* d, zone_type* z)
484 {
485 	return d->is_existing && !domain_has_only_NSEC3(d, z) &&
486 		nsec3_domain_part_of_zone(d, z) && !domain_is_glue(d, z);
487 }
488 
489 /* condition when a domain is ds precompiled */
490 int
nsec3_condition_dshash(domain_type * d,zone_type * z)491 nsec3_condition_dshash(domain_type* d, zone_type* z)
492 {
493 	return d->is_existing && !domain_has_only_NSEC3(d, z) &&
494 		(domain_find_rrset(d, z, TYPE_DS) ||
495 		domain_find_rrset(d, z, TYPE_NS)) && d != z->apex
496 		&& nsec3_domain_part_of_zone(d->parent, z);
497 }
498 
499 zone_type*
nsec3_tree_zone(namedb_type * db,domain_type * d)500 nsec3_tree_zone(namedb_type* db, domain_type* d)
501 {
502 	/* see nsec3_domain_part_of_zone; domains part of zone that has
503 	 * apex above them */
504 	/* this does not use the rrset->zone pointer because there may be
505 	 * no rrsets left at apex (no SOA), e.g. during IXFR */
506 	while(d) {
507 		if(d->is_apex) {
508 			/* we can try a SOA if its present (faster than tree)*/
509 			/* DNSKEY and NSEC3PARAM are also good indicators */
510 			rrset_type *rrset;
511 			for (rrset = d->rrsets; rrset; rrset = rrset->next)
512 				if (rrset_rrtype(rrset) == TYPE_SOA ||
513 					rrset_rrtype(rrset) == TYPE_DNSKEY ||
514 					rrset_rrtype(rrset) == TYPE_NSEC3PARAM)
515 					return rrset->zone;
516 			return namedb_find_zone(db, domain_dname(d));
517 		}
518 		d = d->parent;
519 	}
520 	return NULL;
521 }
522 
523 zone_type*
nsec3_tree_dszone(namedb_type * db,domain_type * d)524 nsec3_tree_dszone(namedb_type* db, domain_type* d)
525 {
526 	/* the DStree does not contain nodes with d==z->apex */
527 	if(d->is_apex)
528 		d = d->parent;
529 	return nsec3_tree_zone(db, d);
530 }
531 
532 int
nsec3_find_cover(zone_type * zone,uint8_t * hash,size_t hashlen,domain_type ** result)533 nsec3_find_cover(zone_type* zone, uint8_t* hash, size_t hashlen,
534 	domain_type** result)
535 {
536 	rbnode_type* r = NULL;
537 	int exact;
538 	domain_type d;
539 	uint8_t n[48];
540 
541 	/* nsec3tree is sorted by b32 encoded domain name of the NSEC3 */
542 	b32_ntop(hash, hashlen, (char*)(n+5), sizeof(n)-5);
543 #ifdef USE_RADIX_TREE
544 	d.dname = (dname_type*)n;
545 #else
546 	d.node.key = n;
547 #endif
548 	n[0] = 34; /* name_size */
549 	n[1] = 2; /* label_count */
550 	n[2] = 0; /* label_offset[0] */
551 	n[3] = 0; /* label_offset[1] */
552 	n[4] = 32; /* label-size[0] */
553 
554 	assert(result);
555 	assert(zone->nsec3_param && zone->nsec3tree);
556 
557 	exact = rbtree_find_less_equal(zone->nsec3tree, &d, &r);
558 	if(r) {
559 		*result = (domain_type*)r->key;
560 	} else {
561 		*result = zone->nsec3_last;
562 	}
563 	return exact;
564 }
565 
566 void
nsec3_precompile_domain(struct namedb * db,struct domain * domain,struct zone * zone,region_type * tmpregion)567 nsec3_precompile_domain(struct namedb* db, struct domain* domain,
568 	struct zone* zone, region_type* tmpregion)
569 {
570 	domain_type* result = 0;
571 	int exact;
572 	allocate_domain_nsec3(db->domains, domain);
573 
574 	/* hash it */
575 	nsec3_lookup_hash_and_wc(db->region,
576 		zone, domain_dname(domain), domain, tmpregion);
577 
578 	/* add into tree */
579 	zone_add_domain_in_hash_tree(db->region, &zone->hashtree,
580 		cmp_hash_tree, domain, &domain->nsec3->hash_wc->hash.node);
581 	zone_add_domain_in_hash_tree(db->region, &zone->wchashtree,
582 		cmp_wchash_tree, domain, &domain->nsec3->hash_wc->wc.node);
583 
584 	/* lookup in tree cover ptr (or exact) */
585 	exact = nsec3_find_cover(zone, domain->nsec3->hash_wc->hash.hash,
586 		sizeof(domain->nsec3->hash_wc->hash.hash), &result);
587 	domain->nsec3->nsec3_cover = result;
588 	if(exact)
589 		domain->nsec3->nsec3_is_exact = 1;
590 	else	domain->nsec3->nsec3_is_exact = 0;
591 
592 	/* find cover for *.domain for wildcard denial */
593 	(void)nsec3_find_cover(zone, domain->nsec3->hash_wc->wc.hash,
594 		sizeof(domain->nsec3->hash_wc->wc.hash), &result);
595 	domain->nsec3->nsec3_wcard_child_cover = result;
596 }
597 
598 void
nsec3_precompile_domain_ds(struct namedb * db,struct domain * domain,struct zone * zone)599 nsec3_precompile_domain_ds(struct namedb* db, struct domain* domain,
600 	struct zone* zone)
601 {
602 	domain_type* result = 0;
603 	int exact;
604 	allocate_domain_nsec3(db->domains, domain);
605 
606 	/* hash it : it could have different hash parameters then the
607 	   other hash for this domain name */
608 	nsec3_lookup_hash_ds(db->region, zone, domain_dname(domain), domain);
609 	/* lookup in tree cover ptr (or exact) */
610 	exact = nsec3_find_cover(zone, domain->nsec3->ds_parent_hash->hash,
611 		sizeof(domain->nsec3->ds_parent_hash->hash), &result);
612 	if(exact)
613 		domain->nsec3->nsec3_ds_parent_is_exact = 1;
614 	else 	domain->nsec3->nsec3_ds_parent_is_exact = 0;
615 	domain->nsec3->nsec3_ds_parent_cover = result;
616 	/* add into tree */
617 	zone_add_domain_in_hash_tree(db->region, &zone->dshashtree,
618 		cmp_dshash_tree, domain, &domain->nsec3->ds_parent_hash->node);
619 }
620 
621 static void
parse_nsec3_name(const dname_type * dname,uint8_t * hash,size_t buflen)622 parse_nsec3_name(const dname_type* dname, uint8_t* hash, size_t buflen)
623 {
624 	/* first label must be the match, */
625 	size_t lablen = (buflen-1) * 8 / 5;
626 	const uint8_t* wire = dname_name(dname);
627 	assert(lablen == 32 && buflen == NSEC3_HASH_LEN+1);
628 	/* labels of length 32 for SHA1, and must have space+1 for convert */
629 	if(wire[0] != lablen) {
630 		/* not NSEC3 */
631 		memset(hash, 0, buflen);
632 		return;
633 	}
634 	(void)b32_pton((char*)wire+1, hash, buflen);
635 }
636 
637 void
nsec3_precompile_nsec3rr(namedb_type * db,struct domain * domain,struct zone * zone)638 nsec3_precompile_nsec3rr(namedb_type* db, struct domain* domain,
639 	struct zone* zone)
640 {
641 	allocate_domain_nsec3(db->domains, domain);
642 	/* add into nsec3tree */
643 	zone_add_domain_in_hash_tree(db->region, &zone->nsec3tree,
644 		cmp_nsec3_tree, domain, &domain->nsec3->nsec3_node);
645 	/* fixup the last in the zone */
646 	if(rbtree_last(zone->nsec3tree)->key == domain) {
647 		zone->nsec3_last = domain;
648 	}
649 }
650 
651 void
nsec3_precompile_newparam(namedb_type * db,zone_type * zone)652 nsec3_precompile_newparam(namedb_type* db, zone_type* zone)
653 {
654 	region_type* tmpregion = region_create(xalloc, free);
655 	domain_type* walk;
656 	time_t s = time(NULL);
657 	unsigned long n = 0, c = 0;
658 
659 	/* add nsec3s of chain to nsec3tree */
660 	for(walk=zone->apex; walk && domain_is_subdomain(walk, zone->apex);
661 		walk = domain_next(walk)) {
662 		n++;
663 		if(nsec3_in_chain_count(walk, zone) != 0) {
664 			nsec3_precompile_nsec3rr(db, walk, zone);
665 		}
666 	}
667 	/* hash and precompile zone */
668 	for(walk=zone->apex; walk && domain_is_subdomain(walk, zone->apex);
669 		walk = domain_next(walk)) {
670 		if(nsec3_condition_hash(walk, zone)) {
671 			nsec3_precompile_domain(db, walk, zone, tmpregion);
672 			region_free_all(tmpregion);
673 		}
674 		if(nsec3_condition_dshash(walk, zone))
675 			nsec3_precompile_domain_ds(db, walk, zone);
676 		if(++c % ZONEC_PCT_COUNT == 0 && time(NULL) > s + ZONEC_PCT_TIME) {
677 			s = time(NULL);
678 			VERBOSITY(1, (LOG_INFO, "nsec3 %s %d %%",
679 				zone->opts->name,
680 				(int)(c*((unsigned long)100)/n)));
681 		}
682 	}
683 	region_destroy(tmpregion);
684 }
685 
686 void
prehash_zone_complete(struct namedb * db,struct zone * zone)687 prehash_zone_complete(struct namedb* db, struct zone* zone)
688 {
689 	udb_ptr udbz;
690 
691 	/* robust clear it */
692 	nsec3_clear_precompile(db, zone);
693 	/* find zone settings */
694 
695 	assert(db && zone);
696 	udbz.data = 0;
697 	if(db->udb) {
698 		if(!udb_zone_search(db->udb, &udbz, dname_name(domain_dname(
699 			zone->apex)), domain_dname(zone->apex)->name_size)) {
700 			udb_ptr_init(&udbz, db->udb); /* zero the ptr */
701 		}
702 	}
703 	nsec3_find_zone_param(db, zone, &udbz, NULL, 1);
704 	if(!zone->nsec3_param || !check_apex_soa(db, zone, 0)) {
705 		zone->nsec3_param = NULL;
706 		zone->nsec3_last = NULL;
707 		if(udbz.data)
708 			udb_ptr_unlink(&udbz, db->udb);
709 		return;
710 	}
711 	if(udbz.data)
712 		udb_ptr_unlink(&udbz, db->udb);
713 	nsec3_precompile_newparam(db, zone);
714 }
715 
716 static void
init_lookup_key_hash_tree(domain_type * d,uint8_t * hash)717 init_lookup_key_hash_tree(domain_type* d, uint8_t* hash)
718 { memcpy(d->nsec3->hash_wc->hash.hash, hash, NSEC3_HASH_LEN); }
719 
720 static void
init_lookup_key_wc_tree(domain_type * d,uint8_t * hash)721 init_lookup_key_wc_tree(domain_type* d, uint8_t* hash)
722 { memcpy(d->nsec3->hash_wc->wc.hash, hash, NSEC3_HASH_LEN); }
723 
724 static void
init_lookup_key_ds_tree(domain_type * d,uint8_t * hash)725 init_lookup_key_ds_tree(domain_type* d, uint8_t* hash)
726 { memcpy(d->nsec3->ds_parent_hash->hash, hash, NSEC3_HASH_LEN); }
727 
728 /* find first in the tree and true if the first to process it */
729 static int
process_first(rbtree_type * tree,uint8_t * hash,rbnode_type ** p,void (* init)(domain_type *,uint8_t *))730 process_first(rbtree_type* tree, uint8_t* hash, rbnode_type** p,
731 	void (*init)(domain_type*, uint8_t*))
732 {
733 	domain_type d;
734 	struct nsec3_domain_data n;
735 	nsec3_hash_wc_node_type hash_wc;
736 	nsec3_hash_node_type ds_parent_hash;
737 
738 	if(!tree) {
739 		*p = RBTREE_NULL;
740 		return 0;
741 	}
742 	hash_wc.hash.node.key = NULL;
743 	hash_wc.wc.node.key = NULL;
744 	n.hash_wc = &hash_wc;
745 	ds_parent_hash.node.key = NULL;
746 	n.ds_parent_hash = &ds_parent_hash;
747 	d.nsec3 = &n;
748 	init(&d, hash);
749 	if(rbtree_find_less_equal(tree, &d, p)) {
750 		/* found an exact match */
751 		return 1;
752 	}
753 	if(!*p) /* before first, go from first */
754 		*p = rbtree_first(tree);
755 	/* the inexact, smaller, match we found, does not itself need to
756 	 * be edited */
757 	else
758 		*p = rbtree_next(*p); /* if this becomes NULL, nothing to do */
759 	return 0;
760 }
761 
762 /* set end pointer if possible */
763 static void
process_end(rbtree_type * tree,uint8_t * hash,rbnode_type ** p,void (* init)(domain_type *,uint8_t *))764 process_end(rbtree_type* tree, uint8_t* hash, rbnode_type** p,
765 	void (*init)(domain_type*, uint8_t*))
766 {
767 	domain_type d;
768 	struct nsec3_domain_data n;
769 	nsec3_hash_wc_node_type hash_wc;
770 	nsec3_hash_node_type ds_parent_hash;
771 
772 	if(!tree) {
773 		*p = RBTREE_NULL;
774 		return;
775 	}
776 	hash_wc.hash.node.key = NULL;
777 	hash_wc.wc.node.key = NULL;
778 	n.hash_wc = &hash_wc;
779 	ds_parent_hash.node.key = NULL;
780 	n.ds_parent_hash = &ds_parent_hash;
781 	d.nsec3 = &n;
782 	init(&d, hash);
783 	if(rbtree_find_less_equal(tree, &d, p)) {
784 		/* an exact match, fine, because this one does not get
785 		 * processed */
786 		return;
787 	}
788 	/* inexact element, but if NULL, until first element in tree */
789 	if(!*p) {
790 		*p = rbtree_first(tree);
791 		return;
792 	}
793 	/* inexact match, use next element, if possible, the smaller
794 	 * element is part of the range */
795 	*p = rbtree_next(*p);
796 	/* if next returns null, we go until the end of the tree */
797 }
798 
799 /* prehash domains in hash range start to end */
800 static void
process_range(zone_type * zone,domain_type * start,domain_type * end,domain_type * nsec3)801 process_range(zone_type* zone, domain_type* start,
802 	domain_type* end, domain_type* nsec3)
803 {
804 	/* start NULL means from first in tree */
805 	/* end NULL means to last in tree */
806 	rbnode_type *p = RBTREE_NULL, *pwc = RBTREE_NULL, *pds = RBTREE_NULL;
807 	rbnode_type *p_end = RBTREE_NULL, *pwc_end = RBTREE_NULL, *pds_end = RBTREE_NULL;
808 	/* because the nodes are on the prehashlist, the domain->nsec3 is
809 	 * already allocated, and we need not allocate it here */
810 	/* set start */
811 	if(start) {
812 		uint8_t hash[NSEC3_HASH_LEN+1];
813 		parse_nsec3_name(domain_dname(start), hash, sizeof(hash));
814 		/* if exact match on first, set is_exact */
815 		if(process_first(zone->hashtree, hash, &p, init_lookup_key_hash_tree)) {
816 			((domain_type*)(p->key))->nsec3->nsec3_cover = nsec3;
817 			((domain_type*)(p->key))->nsec3->nsec3_is_exact = 1;
818 			p = rbtree_next(p);
819 		}
820 		(void)process_first(zone->wchashtree, hash, &pwc, init_lookup_key_wc_tree);
821 		if(process_first(zone->dshashtree, hash, &pds, init_lookup_key_ds_tree)){
822 			((domain_type*)(pds->key))->nsec3->
823 				nsec3_ds_parent_cover = nsec3;
824 			((domain_type*)(pds->key))->nsec3->
825 				nsec3_ds_parent_is_exact = 1;
826 			pds = rbtree_next(pds);
827 		}
828 	} else {
829 		if(zone->hashtree)
830 			p = rbtree_first(zone->hashtree);
831 		if(zone->wchashtree)
832 			pwc = rbtree_first(zone->wchashtree);
833 		if(zone->dshashtree)
834 			pds = rbtree_first(zone->dshashtree);
835 	}
836 	/* set end */
837 	if(end) {
838 		uint8_t hash[NSEC3_HASH_LEN+1];
839 		parse_nsec3_name(domain_dname(end), hash, sizeof(hash));
840 		process_end(zone->hashtree, hash, &p_end, init_lookup_key_hash_tree);
841 		process_end(zone->wchashtree, hash, &pwc_end, init_lookup_key_wc_tree);
842 		process_end(zone->dshashtree, hash, &pds_end, init_lookup_key_ds_tree);
843 	}
844 
845 	/* precompile */
846 	while(p != RBTREE_NULL && p != p_end) {
847 		((domain_type*)(p->key))->nsec3->nsec3_cover = nsec3;
848 		((domain_type*)(p->key))->nsec3->nsec3_is_exact = 0;
849 		p = rbtree_next(p);
850 	}
851 	while(pwc != RBTREE_NULL && pwc != pwc_end) {
852 		((domain_type*)(pwc->key))->nsec3->
853 			nsec3_wcard_child_cover = nsec3;
854 		pwc = rbtree_next(pwc);
855 	}
856 	while(pds != RBTREE_NULL && pds != pds_end) {
857 		((domain_type*)(pds->key))->nsec3->
858 			nsec3_ds_parent_cover = nsec3;
859 		((domain_type*)(pds->key))->nsec3->
860 			nsec3_ds_parent_is_exact = 0;
861 		pds = rbtree_next(pds);
862 	}
863 }
864 
865 /* prehash a domain from the prehash list */
866 static void
process_prehash_domain(domain_type * domain,zone_type * zone)867 process_prehash_domain(domain_type* domain, zone_type* zone)
868 {
869 	/* in the hashtree, wchashtree, dshashtree walk through to next NSEC3
870 	 * and set precompile pointers to point to this domain (or is_exact),
871 	 * the first domain can be is_exact. If it is the last NSEC3, also
872 	 * process the initial part (before the first) */
873 	rbnode_type* nx;
874 
875 	/* this domain is part of the prehash list and therefore the
876 	 * domain->nsec3 is allocated and need not be allocated here */
877 	assert(domain->nsec3 && domain->nsec3->nsec3_node.key);
878 	nx = rbtree_next(&domain->nsec3->nsec3_node);
879 	if(nx != RBTREE_NULL) {
880 		/* process until next nsec3 */
881 		domain_type* end = (domain_type*)nx->key;
882 		process_range(zone, domain, end, domain);
883 	} else {
884 		/* first is root, but then comes the first nsec3 */
885 		domain_type* first = (domain_type*)(rbtree_first(
886 			zone->nsec3tree)->key);
887 		/* last in zone */
888 		process_range(zone, domain, NULL, domain);
889 		/* also process before first in zone */
890 		process_range(zone, NULL, first, domain);
891 	}
892 }
893 
prehash_zone(struct namedb * db,struct zone * zone)894 void prehash_zone(struct namedb* db, struct zone* zone)
895 {
896 	domain_type* d;
897 	if(!zone->nsec3_param) {
898 		prehash_clear(db->domains);
899 		return;
900 	}
901 	if(!check_apex_soa(db, zone, 1)) {
902 		/* the zone fails apex soa check, prehash complete may
903 		 * detect other valid chains */
904 		prehash_clear(db->domains);
905 		prehash_zone_complete(db, zone);
906 		return;
907 	}
908 	/* process prehash list */
909 	for(d = db->domains->prehash_list; d; d = d->nsec3->prehash_next) {
910 		process_prehash_domain(d, zone);
911 	}
912 	/* clear prehash list */
913 	prehash_clear(db->domains);
914 
915 	if(!check_apex_soa(db, zone, 0)) {
916 		zone->nsec3_param = NULL;
917 		zone->nsec3_last = NULL;
918 	}
919 }
920 
921 /* add the NSEC3 rrset to the query answer at the given domain */
922 static void
nsec3_add_rrset(struct query * query,struct answer * answer,rr_section_type section,struct domain * domain)923 nsec3_add_rrset(struct query* query, struct answer* answer,
924 	rr_section_type section, struct domain* domain)
925 {
926 	if(domain) {
927 		rrset_type* rrset = domain_find_rrset(domain, query->zone, TYPE_NSEC3);
928 		if(rrset)
929 			answer_add_rrset(answer, section, domain, rrset);
930 	}
931 }
932 
933 /* this routine does hashing at query-time. slow. */
934 static void
nsec3_add_nonexist_proof(struct query * query,struct answer * answer,struct domain * encloser,const dname_type * qname)935 nsec3_add_nonexist_proof(struct query* query, struct answer* answer,
936         struct domain* encloser, const dname_type* qname)
937 {
938 	uint8_t hash[NSEC3_HASH_LEN];
939 	const dname_type* to_prove;
940 	domain_type* cover=0;
941 	assert(encloser);
942 	/* if query=a.b.c.d encloser=c.d. then proof needed for b.c.d. */
943 	/* if query=a.b.c.d encloser=*.c.d. then proof needed for b.c.d. */
944 	to_prove = dname_partial_copy(query->region, qname,
945 		dname_label_match_count(qname, domain_dname(encloser))+1);
946 	/* generate proof that one label below closest encloser does not exist */
947 	nsec3_hash_and_store(query->zone, to_prove, hash);
948 	if(nsec3_find_cover(query->zone, hash, sizeof(hash), &cover))
949 	{
950 		/* exact match, hash collision */
951 		domain_type* walk;
952 		char hashbuf[512];
953 		char reversebuf[512];
954 		(void)b32_ntop(hash, sizeof(hash), hashbuf, sizeof(hashbuf));
955 		snprintf(reversebuf, sizeof(reversebuf), "(no name in the zone hashes to this nsec3 record)");
956 		walk = query->zone->apex;
957 		while(walk) {
958 			if(walk->nsec3 && walk->nsec3->nsec3_cover == cover) {
959 				snprintf(reversebuf, sizeof(reversebuf),
960 					"%s %s", domain_to_string(walk),
961 					walk->nsec3->nsec3_is_exact?"exact":"no_exact_hash_match");
962 				if(walk->nsec3->nsec3_is_exact)
963 					break;
964 			}
965 			if(walk->nsec3 && walk->nsec3->nsec3_ds_parent_cover == cover) {
966 				snprintf(reversebuf, sizeof(reversebuf),
967 					"%s %s", domain_to_string(walk),
968 					walk->nsec3->nsec3_ds_parent_is_exact?"exact":"no_exact_hash_match");
969 				if(walk->nsec3->nsec3_ds_parent_is_exact)
970 					break;
971 			}
972 			walk = domain_next(walk);
973 		}
974 
975 
976 		/* the hashed name of the query corresponds to an existing name. */
977 		VERBOSITY(3, (LOG_ERR, "nsec3 hash collision for name=%s hash=%s reverse=%s",
978 			dname_to_string(to_prove, NULL), hashbuf, reversebuf));
979 		RCODE_SET(query->packet, RCODE_SERVFAIL);
980 		/* RFC 8914 - Extended DNS Errors
981 		 * 4.21. Extended DNS Error Code 0 - Other */
982 		ASSIGN_EDE_CODE_AND_STRING_LITERAL(query->edns.ede,
983 			EDE_OTHER, "NSEC3 hash collision");
984 		return;
985 	}
986 	else
987 	{
988 		/* cover proves the qname does not exist */
989 		nsec3_add_rrset(query, answer, AUTHORITY_SECTION, cover);
990 	}
991 }
992 
993 static void
nsec3_add_closest_encloser_proof(struct query * query,struct answer * answer,struct domain * closest_encloser,const dname_type * qname)994 nsec3_add_closest_encloser_proof(
995 	struct query* query, struct answer* answer,
996 	struct domain* closest_encloser, const dname_type* qname)
997 {
998 	if(!closest_encloser)
999 		return;
1000 	/* prove that below closest encloser nothing exists */
1001 	nsec3_add_nonexist_proof(query, answer, closest_encloser, qname);
1002 	/* proof that closest encloser exists */
1003 	if(closest_encloser->nsec3 && closest_encloser->nsec3->nsec3_is_exact)
1004 		nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
1005 			closest_encloser->nsec3->nsec3_cover);
1006 }
1007 
1008 void
nsec3_answer_wildcard(struct query * query,struct answer * answer,struct domain * wildcard,const dname_type * qname)1009 nsec3_answer_wildcard(struct query *query, struct answer *answer,
1010         struct domain *wildcard, const dname_type* qname)
1011 {
1012 	if(!wildcard)
1013 		return;
1014 	if(!query->zone->nsec3_param)
1015 		return;
1016 	nsec3_add_nonexist_proof(query, answer, wildcard, qname);
1017 }
1018 
1019 static void
nsec3_add_ds_proof(struct query * query,struct answer * answer,struct domain * domain,int delegpt)1020 nsec3_add_ds_proof(struct query *query, struct answer *answer,
1021 	struct domain *domain, int delegpt)
1022 {
1023 	/* assert we are above the zone cut */
1024 	assert(domain != query->zone->apex);
1025 	if(domain->nsec3 && domain->nsec3->nsec3_ds_parent_is_exact) {
1026 		/* use NSEC3 record from above the zone cut. */
1027 		nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
1028 			domain->nsec3->nsec3_ds_parent_cover);
1029 	} else if (!delegpt && domain->nsec3 && domain->nsec3->nsec3_is_exact
1030 		&& nsec3_domain_part_of_zone(domain->nsec3->nsec3_cover,
1031 		query->zone)) {
1032 		nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
1033 			domain->nsec3->nsec3_cover);
1034 	} else {
1035 		/* prove closest provable encloser */
1036 		domain_type* par = domain->parent;
1037 		domain_type* prev_par = 0;
1038 
1039 		while(par && (!par->nsec3 || !par->nsec3->nsec3_is_exact))
1040 		{
1041 			prev_par = par;
1042 			par = par->parent;
1043 		}
1044 		assert(par); /* parent zone apex must be provable, thus this ends */
1045 		if(!par->nsec3) return;
1046 		nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
1047 			par->nsec3->nsec3_cover);
1048 		/* we took several steps to go to the provable parent, so
1049 		   the one below it has no exact nsec3, disprove it.
1050 		   disprove is easy, it has a prehashed cover ptr. */
1051 		if(prev_par && prev_par->nsec3) {
1052 			assert(prev_par != domain &&
1053 				!prev_par->nsec3->nsec3_is_exact);
1054 			nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
1055 				prev_par->nsec3->nsec3_cover);
1056 		} else {
1057 			/* the exact case was handled earlier, so this is
1058 			 * with a closest-encloser proof, if in the part
1059 			 * before the else the closest encloser proof is done,
1060 			 * then we do not need to add a DS here because
1061 			 * the optout proof is already complete. If not,
1062 			 * we add the nsec3 here to complete the closest
1063 			 * encloser proof with a next closer */
1064 			/* add optout range from parent zone */
1065 			/* note: no check of optout bit, resolver checks it */
1066 			if(domain->nsec3) {
1067 				nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
1068 					domain->nsec3->nsec3_ds_parent_cover);
1069 			}
1070 		}
1071 	}
1072 }
1073 
1074 void
nsec3_answer_nodata(struct query * query,struct answer * answer,struct domain * original)1075 nsec3_answer_nodata(struct query* query, struct answer* answer,
1076 	struct domain* original)
1077 {
1078 	if(!query->zone->nsec3_param)
1079 		return;
1080 	/* nodata when asking for secure delegation */
1081 	if(query->qtype == TYPE_DS)
1082 	{
1083 		if(original == query->zone->apex) {
1084 			/* DS at zone apex, but server not authoritative for parent zone */
1085 			/* so answer at the child zone level */
1086 			if(original->nsec3 && original->nsec3->nsec3_is_exact)
1087 				nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
1088 					original->nsec3->nsec3_cover);
1089 			return;
1090 		}
1091 		/* query->zone must be the parent zone */
1092 		nsec3_add_ds_proof(query, answer, original, 0);
1093 		/* if the DS is from a wildcard match */
1094 		if (original==original->wildcard_child_closest_match
1095 			&& label_is_wildcard(dname_name(domain_dname(original)))) {
1096 			/* denial for wildcard is already there */
1097 			/* add parent proof to have a closest encloser proof for wildcard parent */
1098 			/* in other words: nsec3 matching closest encloser */
1099 			if(original->parent && original->parent->nsec3 &&
1100 				original->parent->nsec3->nsec3_is_exact)
1101 				nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
1102 					original->parent->nsec3->nsec3_cover);
1103 		}
1104 	}
1105 	/* the nodata is result from a wildcard match */
1106 	else if (original==original->wildcard_child_closest_match
1107 		&& label_is_wildcard(dname_name(domain_dname(original)))) {
1108 		/* denial for wildcard is already there */
1109 
1110 		/* add parent proof to have a closest encloser proof for wildcard parent */
1111 		/* in other words: nsec3 matching closest encloser */
1112 		if(original->parent && original->parent->nsec3 &&
1113 			original->parent->nsec3->nsec3_is_exact)
1114 			nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
1115 				original->parent->nsec3->nsec3_cover);
1116 		/* proof for wildcard itself */
1117 		/* in other words: nsec3 matching source of synthesis */
1118 		if(original->nsec3)
1119 			nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
1120 				original->nsec3->nsec3_cover);
1121 	}
1122 	else {	/* add nsec3 to prove rrset does not exist */
1123 		if(original->nsec3) {
1124 			if(!original->nsec3->nsec3_is_exact) {
1125 				/* go up to an existing parent */
1126 				while(original->parent && original->parent->nsec3 && !original->parent->nsec3->nsec3_is_exact)
1127 					original = original->parent;
1128 			}
1129 			nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
1130 				original->nsec3->nsec3_cover);
1131 			if(!original->nsec3->nsec3_is_exact) {
1132 				if(original->parent && original->parent->nsec3 && original->parent->nsec3->nsec3_is_exact)
1133 				    nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
1134 					original->parent->nsec3->nsec3_cover);
1135 
1136 			}
1137 		}
1138 	}
1139 }
1140 
1141 void
nsec3_answer_delegation(struct query * query,struct answer * answer)1142 nsec3_answer_delegation(struct query *query, struct answer *answer)
1143 {
1144 	if(!query->zone->nsec3_param)
1145 		return;
1146 	nsec3_add_ds_proof(query, answer, query->delegation_domain, 1);
1147 }
1148 
1149 int
domain_has_only_NSEC3(struct domain * domain,struct zone * zone)1150 domain_has_only_NSEC3(struct domain* domain, struct zone* zone)
1151 {
1152 	/* check for only NSEC3/RRSIG */
1153 	rrset_type* rrset = domain->rrsets;
1154 	int nsec3_seen = 0;
1155 	while(rrset)
1156 	{
1157 		if(!zone || rrset->zone == zone)
1158 		{
1159 			if(rrset->rrs[0].type == TYPE_NSEC3)
1160 				nsec3_seen = 1;
1161 			else if(rrset->rrs[0].type != TYPE_RRSIG)
1162 				return 0;
1163 		}
1164 		rrset = rrset->next;
1165 	}
1166 	return nsec3_seen;
1167 }
1168 
1169 void
nsec3_answer_authoritative(struct domain ** match,struct query * query,struct answer * answer,struct domain * closest_encloser,const dname_type * qname)1170 nsec3_answer_authoritative(struct domain** match, struct query *query,
1171 	struct answer *answer, struct domain* closest_encloser,
1172 	const dname_type* qname)
1173 {
1174 	if(!query->zone->nsec3_param)
1175 		return;
1176 	assert(match);
1177 	/* there is a match, this has 1 RRset, which is NSEC3, but qtype is not. */
1178         /* !is_existing: no RR types exist at the QNAME, nor at any descendant of QNAME */
1179 	if(*match && !(*match)->is_existing &&
1180 #if 0
1181 		query->qtype != TYPE_NSEC3 &&
1182 #endif
1183 		domain_has_only_NSEC3(*match, query->zone))
1184 	{
1185 		/* act as if the NSEC3 domain did not exist, name error */
1186 		*match = 0;
1187 		/* all nsec3s are directly below the apex, that is closest encloser */
1188 		if(query->zone->apex->nsec3 &&
1189 			query->zone->apex->nsec3->nsec3_is_exact)
1190 			nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
1191 				query->zone->apex->nsec3->nsec3_cover);
1192 		/* disprove the nsec3 record. */
1193 		if(closest_encloser->nsec3)
1194 			nsec3_add_rrset(query, answer, AUTHORITY_SECTION, closest_encloser->nsec3->nsec3_cover);
1195 		/* disprove a wildcard */
1196 		if(query->zone->apex->nsec3)
1197 			nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
1198 				query->zone->apex->nsec3->nsec3_wcard_child_cover);
1199 		if (domain_wildcard_child(query->zone->apex)) {
1200 			/* wildcard exists below the domain */
1201 			/* wildcard and nsec3 domain clash. server failure. */
1202 			RCODE_SET(query->packet, RCODE_SERVFAIL);
1203 			/* RFC 8914 - Extended DNS Errors
1204 			 * 4.21. Extended DNS Error Code 0 - Other */
1205 			ASSIGN_EDE_CODE_AND_STRING_LITERAL(query->edns.ede,
1206 				EDE_OTHER, "Wildcard and NSEC3 domain clash");
1207 		}
1208 		return;
1209 	}
1210 	else if(*match && (*match)->is_existing &&
1211 #if 0
1212 		query->qtype != TYPE_NSEC3 &&
1213 #endif
1214 		(domain_has_only_NSEC3(*match, query->zone) ||
1215 		!domain_find_any_rrset(*match, query->zone)))
1216 	{
1217 		/* this looks like a NSEC3 domain, but is actually an empty non-terminal. */
1218 		nsec3_answer_nodata(query, answer, *match);
1219 		return;
1220 	}
1221 	if(!*match) {
1222 		/* name error, domain does not exist */
1223 		nsec3_add_closest_encloser_proof(query, answer, closest_encloser,
1224 			qname);
1225 		if(closest_encloser->nsec3)
1226 			nsec3_add_rrset(query, answer, AUTHORITY_SECTION,
1227 				closest_encloser->nsec3->nsec3_wcard_child_cover);
1228 	}
1229 }
1230 
1231 #endif /* NSEC3 */
1232