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 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 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 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 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* 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 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* 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* 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 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 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 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 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* 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) 395 return zone->nsec3_last; 396 return NULL; 397 } 398 399 400 /** clear hash tree. Called from nsec3_clear_precompile() only. */ 401 static void 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 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 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 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 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* 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* 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 return; 981 } 982 else 983 { 984 /* cover proves the qname does not exist */ 985 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, cover); 986 } 987 } 988 989 static void 990 nsec3_add_closest_encloser_proof( 991 struct query* query, struct answer* answer, 992 struct domain* closest_encloser, const dname_type* qname) 993 { 994 if(!closest_encloser) 995 return; 996 /* prove that below closest encloser nothing exists */ 997 nsec3_add_nonexist_proof(query, answer, closest_encloser, qname); 998 /* proof that closest encloser exists */ 999 if(closest_encloser->nsec3 && closest_encloser->nsec3->nsec3_is_exact) 1000 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1001 closest_encloser->nsec3->nsec3_cover); 1002 } 1003 1004 void 1005 nsec3_answer_wildcard(struct query *query, struct answer *answer, 1006 struct domain *wildcard, const dname_type* qname) 1007 { 1008 if(!wildcard) 1009 return; 1010 if(!query->zone->nsec3_param) 1011 return; 1012 nsec3_add_nonexist_proof(query, answer, wildcard, qname); 1013 } 1014 1015 static void 1016 nsec3_add_ds_proof(struct query *query, struct answer *answer, 1017 struct domain *domain, int delegpt) 1018 { 1019 /* assert we are above the zone cut */ 1020 assert(domain != query->zone->apex); 1021 if(domain->nsec3 && domain->nsec3->nsec3_ds_parent_is_exact) { 1022 /* use NSEC3 record from above the zone cut. */ 1023 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1024 domain->nsec3->nsec3_ds_parent_cover); 1025 } else if (!delegpt && domain->nsec3 && domain->nsec3->nsec3_is_exact 1026 && nsec3_domain_part_of_zone(domain->nsec3->nsec3_cover, 1027 query->zone)) { 1028 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1029 domain->nsec3->nsec3_cover); 1030 } else { 1031 /* prove closest provable encloser */ 1032 domain_type* par = domain->parent; 1033 domain_type* prev_par = 0; 1034 1035 while(par && (!par->nsec3 || !par->nsec3->nsec3_is_exact)) 1036 { 1037 prev_par = par; 1038 par = par->parent; 1039 } 1040 assert(par); /* parent zone apex must be provable, thus this ends */ 1041 if(!par->nsec3) return; 1042 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1043 par->nsec3->nsec3_cover); 1044 /* we took several steps to go to the provable parent, so 1045 the one below it has no exact nsec3, disprove it. 1046 disprove is easy, it has a prehashed cover ptr. */ 1047 if(prev_par && prev_par->nsec3) { 1048 assert(prev_par != domain && 1049 !prev_par->nsec3->nsec3_is_exact); 1050 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1051 prev_par->nsec3->nsec3_cover); 1052 } 1053 /* add optout range from parent zone */ 1054 /* note: no check of optout bit, resolver checks it */ 1055 if(domain->nsec3) 1056 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1057 domain->nsec3->nsec3_ds_parent_cover); 1058 } 1059 } 1060 1061 void 1062 nsec3_answer_nodata(struct query* query, struct answer* answer, 1063 struct domain* original) 1064 { 1065 if(!query->zone->nsec3_param) 1066 return; 1067 /* nodata when asking for secure delegation */ 1068 if(query->qtype == TYPE_DS) 1069 { 1070 if(original == query->zone->apex) { 1071 /* DS at zone apex, but server not authoritative for parent zone */ 1072 /* so answer at the child zone level */ 1073 if(original->nsec3 && original->nsec3->nsec3_is_exact) 1074 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1075 original->nsec3->nsec3_cover); 1076 return; 1077 } 1078 /* query->zone must be the parent zone */ 1079 nsec3_add_ds_proof(query, answer, original, 0); 1080 } 1081 /* the nodata is result from a wildcard match */ 1082 else if (original==original->wildcard_child_closest_match 1083 && label_is_wildcard(dname_name(domain_dname(original)))) { 1084 /* denial for wildcard is already there */ 1085 1086 /* add parent proof to have a closest encloser proof for wildcard parent */ 1087 /* in other words: nsec3 matching closest encloser */ 1088 if(original->parent && original->parent->nsec3 && 1089 original->parent->nsec3->nsec3_is_exact) 1090 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1091 original->parent->nsec3->nsec3_cover); 1092 /* proof for wildcard itself */ 1093 /* in other words: nsec3 matching source of synthesis */ 1094 if(original->nsec3) 1095 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1096 original->nsec3->nsec3_cover); 1097 } 1098 else { /* add nsec3 to prove rrset does not exist */ 1099 if(original->nsec3) { 1100 if(!original->nsec3->nsec3_is_exact) { 1101 /* go up to an existing parent */ 1102 while(original->parent && original->parent->nsec3 && !original->parent->nsec3->nsec3_is_exact) 1103 original = original->parent; 1104 } 1105 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1106 original->nsec3->nsec3_cover); 1107 if(!original->nsec3->nsec3_is_exact) { 1108 if(original->parent && original->parent->nsec3 && original->parent->nsec3->nsec3_is_exact) 1109 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1110 original->parent->nsec3->nsec3_cover); 1111 1112 } 1113 } 1114 } 1115 } 1116 1117 void 1118 nsec3_answer_delegation(struct query *query, struct answer *answer) 1119 { 1120 if(!query->zone->nsec3_param) 1121 return; 1122 nsec3_add_ds_proof(query, answer, query->delegation_domain, 1); 1123 } 1124 1125 int 1126 domain_has_only_NSEC3(struct domain* domain, struct zone* zone) 1127 { 1128 /* check for only NSEC3/RRSIG */ 1129 rrset_type* rrset = domain->rrsets; 1130 int nsec3_seen = 0; 1131 while(rrset) 1132 { 1133 if(!zone || rrset->zone == zone) 1134 { 1135 if(rrset->rrs[0].type == TYPE_NSEC3) 1136 nsec3_seen = 1; 1137 else if(rrset->rrs[0].type != TYPE_RRSIG) 1138 return 0; 1139 } 1140 rrset = rrset->next; 1141 } 1142 return nsec3_seen; 1143 } 1144 1145 void 1146 nsec3_answer_authoritative(struct domain** match, struct query *query, 1147 struct answer *answer, struct domain* closest_encloser, 1148 const dname_type* qname) 1149 { 1150 if(!query->zone->nsec3_param) 1151 return; 1152 assert(match); 1153 /* there is a match, this has 1 RRset, which is NSEC3, but qtype is not. */ 1154 /* !is_existing: no RR types exist at the QNAME, nor at any descendant of QNAME */ 1155 if(*match && !(*match)->is_existing && 1156 #if 0 1157 query->qtype != TYPE_NSEC3 && 1158 #endif 1159 domain_has_only_NSEC3(*match, query->zone)) 1160 { 1161 /* act as if the NSEC3 domain did not exist, name error */ 1162 *match = 0; 1163 /* all nsec3s are directly below the apex, that is closest encloser */ 1164 if(query->zone->apex->nsec3 && 1165 query->zone->apex->nsec3->nsec3_is_exact) 1166 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1167 query->zone->apex->nsec3->nsec3_cover); 1168 /* disprove the nsec3 record. */ 1169 if(closest_encloser->nsec3) 1170 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, closest_encloser->nsec3->nsec3_cover); 1171 /* disprove a wildcard */ 1172 if(query->zone->apex->nsec3) 1173 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1174 query->zone->apex->nsec3->nsec3_wcard_child_cover); 1175 if (domain_wildcard_child(query->zone->apex)) { 1176 /* wildcard exists below the domain */ 1177 /* wildcard and nsec3 domain clash. server failure. */ 1178 RCODE_SET(query->packet, RCODE_SERVFAIL); 1179 } 1180 return; 1181 } 1182 else if(*match && (*match)->is_existing && 1183 #if 0 1184 query->qtype != TYPE_NSEC3 && 1185 #endif 1186 (domain_has_only_NSEC3(*match, query->zone) || 1187 !domain_find_any_rrset(*match, query->zone))) 1188 { 1189 /* this looks like a NSEC3 domain, but is actually an empty non-terminal. */ 1190 nsec3_answer_nodata(query, answer, *match); 1191 return; 1192 } 1193 if(!*match) { 1194 /* name error, domain does not exist */ 1195 nsec3_add_closest_encloser_proof(query, answer, closest_encloser, 1196 qname); 1197 if(closest_encloser->nsec3) 1198 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1199 closest_encloser->nsec3->nsec3_wcard_child_cover); 1200 } 1201 } 1202 1203 #endif /* NSEC3 */ 1204