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