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