nsec3.c revision 1.1.1.6
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 */ 25static int 26cmp_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 */ 39static int 40cmp_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 */ 53static int 54cmp_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 */ 68static int 69cmp_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 79void 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 91static void 92detect_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 102const dname_type * 103nsec3_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 113void 114nsec3_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 */ 130static void 131nsec3_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 149static void 150nsec3_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 163static int 164nsec3_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 176static rr_type* 177check_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 227static void 228nsec3param_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 247static struct rr* 248db_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 286static struct rr* 287udb_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 328void 329nsec3_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 */ 343static int 344nsec3_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 359int 360nsec3_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 367int 368nsec3_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 382struct domain* 383nsec3_chain_find_prev(struct zone* zone, struct domain* domain) 384{ 385 if(domain->nsec3 && domain->nsec3->nsec3_node.key) { 386 /* see if there is a prev */ 387 rbnode_type* r = rbtree_previous(&domain->nsec3->nsec3_node); 388 if(r != RBTREE_NULL) { 389 /* found a previous, which is not the root-node in 390 * the prehash tree (and thus points to the tree) */ 391 return (domain_type*)r->key; 392 } 393 } 394 if(zone->nsec3_last && zone->nsec3_last != domain) 395 return zone->nsec3_last; 396 return NULL; 397} 398 399 400/** clear hash tree. Called from nsec3_clear_precompile() only. */ 401static void 402hash_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 424void 425nsec3_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 */ 470int 471nsec3_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 */ 482int 483nsec3_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 */ 490int 491nsec3_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 499zone_type* 500nsec3_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 523zone_type* 524nsec3_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 532int 533nsec3_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 566void 567nsec3_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 598void 599nsec3_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 621static void 622parse_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 637void 638nsec3_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 651void 652nsec3_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 (n==0)?0:(int)(c*((unsigned long)100)/n))); 681 } 682 } 683 region_destroy(tmpregion); 684} 685 686void 687prehash_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 716static void 717init_lookup_key_hash_tree(domain_type* d, uint8_t* hash) 718{ memcpy(d->nsec3->hash_wc->hash.hash, hash, NSEC3_HASH_LEN); } 719 720static void 721init_lookup_key_wc_tree(domain_type* d, uint8_t* hash) 722{ memcpy(d->nsec3->hash_wc->wc.hash, hash, NSEC3_HASH_LEN); } 723 724static void 725init_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 */ 729static int 730process_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 */ 763static void 764process_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 */ 800static void 801process_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 */ 866static void 867process_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 894void 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 */ 922static void 923nsec3_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. */ 934static void 935nsec3_add_nonexist_proof(struct query* query, struct answer* answer, 936 struct domain* encloser, const dname_type* qname) 937{ 938 uint8_t hash[NSEC3_HASH_LEN]; 939 const dname_type* to_prove; 940 domain_type* cover=0; 941 assert(encloser); 942 /* if query=a.b.c.d encloser=c.d. then proof needed for b.c.d. */ 943 /* if query=a.b.c.d encloser=*.c.d. then proof needed for b.c.d. */ 944 to_prove = dname_partial_copy(query->region, qname, 945 dname_label_match_count(qname, domain_dname(encloser))+1); 946 /* generate proof that one label below closest encloser does not exist */ 947 nsec3_hash_and_store(query->zone, to_prove, hash); 948 if(nsec3_find_cover(query->zone, hash, sizeof(hash), &cover)) 949 { 950 /* exact match, hash collision */ 951 domain_type* walk; 952 char hashbuf[512]; 953 char reversebuf[512]; 954 (void)b32_ntop(hash, sizeof(hash), hashbuf, sizeof(hashbuf)); 955 snprintf(reversebuf, sizeof(reversebuf), "(no name in the zone hashes to this nsec3 record)"); 956 walk = query->zone->apex; 957 while(walk) { 958 if(walk->nsec3 && walk->nsec3->nsec3_cover == cover) { 959 snprintf(reversebuf, sizeof(reversebuf), 960 "%s %s", domain_to_string(walk), 961 walk->nsec3->nsec3_is_exact?"exact":"no_exact_hash_match"); 962 if(walk->nsec3->nsec3_is_exact) 963 break; 964 } 965 if(walk->nsec3 && walk->nsec3->nsec3_ds_parent_cover == cover) { 966 snprintf(reversebuf, sizeof(reversebuf), 967 "%s %s", domain_to_string(walk), 968 walk->nsec3->nsec3_ds_parent_is_exact?"exact":"no_exact_hash_match"); 969 if(walk->nsec3->nsec3_ds_parent_is_exact) 970 break; 971 } 972 walk = domain_next(walk); 973 } 974 975 976 /* the hashed name of the query corresponds to an existing name. */ 977 VERBOSITY(3, (LOG_ERR, "nsec3 hash collision for name=%s hash=%s reverse=%s", 978 dname_to_string(to_prove, NULL), hashbuf, reversebuf)); 979 RCODE_SET(query->packet, RCODE_SERVFAIL); 980 /* RFC 8914 - Extended DNS Errors 981 * 4.21. Extended DNS Error Code 0 - Other */ 982 ASSIGN_EDE_CODE_AND_STRING_LITERAL(query->edns.ede, 983 EDE_OTHER, "NSEC3 hash collision"); 984 return; 985 } 986 else 987 { 988 /* cover proves the qname does not exist */ 989 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, cover); 990 } 991} 992 993static void 994nsec3_add_closest_encloser_proof( 995 struct query* query, struct answer* answer, 996 struct domain* closest_encloser, const dname_type* qname) 997{ 998 if(!closest_encloser) 999 return; 1000 /* prove that below closest encloser nothing exists */ 1001 nsec3_add_nonexist_proof(query, answer, closest_encloser, qname); 1002 /* proof that closest encloser exists */ 1003 if(closest_encloser->nsec3 && closest_encloser->nsec3->nsec3_is_exact) 1004 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1005 closest_encloser->nsec3->nsec3_cover); 1006} 1007 1008void 1009nsec3_answer_wildcard(struct query *query, struct answer *answer, 1010 struct domain *wildcard, const dname_type* qname) 1011{ 1012 if(!wildcard) 1013 return; 1014 if(!query->zone->nsec3_param) 1015 return; 1016 nsec3_add_nonexist_proof(query, answer, wildcard, qname); 1017} 1018 1019static void 1020nsec3_add_ds_proof(struct query *query, struct answer *answer, 1021 struct domain *domain, int delegpt) 1022{ 1023 /* assert we are above the zone cut */ 1024 assert(domain != query->zone->apex); 1025 if(domain->nsec3 && domain->nsec3->nsec3_ds_parent_is_exact) { 1026 /* use NSEC3 record from above the zone cut. */ 1027 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1028 domain->nsec3->nsec3_ds_parent_cover); 1029 } else if (!delegpt && domain->nsec3 && domain->nsec3->nsec3_is_exact 1030 && nsec3_domain_part_of_zone(domain->nsec3->nsec3_cover, 1031 query->zone)) { 1032 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1033 domain->nsec3->nsec3_cover); 1034 } else { 1035 /* prove closest provable encloser */ 1036 domain_type* par = domain->parent; 1037 domain_type* prev_par = 0; 1038 1039 while(par && (!par->nsec3 || !par->nsec3->nsec3_is_exact)) 1040 { 1041 prev_par = par; 1042 par = par->parent; 1043 } 1044 assert(par); /* parent zone apex must be provable, thus this ends */ 1045 if(!par->nsec3) return; 1046 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1047 par->nsec3->nsec3_cover); 1048 /* we took several steps to go to the provable parent, so 1049 the one below it has no exact nsec3, disprove it. 1050 disprove is easy, it has a prehashed cover ptr. */ 1051 if(prev_par && prev_par->nsec3) { 1052 assert(prev_par != domain && 1053 !prev_par->nsec3->nsec3_is_exact); 1054 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1055 prev_par->nsec3->nsec3_cover); 1056 } else { 1057 /* the exact case was handled earlier, so this is 1058 * with a closest-encloser proof, if in the part 1059 * before the else the closest encloser proof is done, 1060 * then we do not need to add a DS here because 1061 * the optout proof is already complete. If not, 1062 * we add the nsec3 here to complete the closest 1063 * encloser proof with a next closer */ 1064 /* add optout range from parent zone */ 1065 /* note: no check of optout bit, resolver checks it */ 1066 if(domain->nsec3) { 1067 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1068 domain->nsec3->nsec3_ds_parent_cover); 1069 } 1070 } 1071 } 1072} 1073 1074void 1075nsec3_answer_nodata(struct query* query, struct answer* answer, 1076 struct domain* original) 1077{ 1078 if(!query->zone->nsec3_param) 1079 return; 1080 /* nodata when asking for secure delegation */ 1081 if(query->qtype == TYPE_DS) 1082 { 1083 if(original == query->zone->apex) { 1084 /* DS at zone apex, but server not authoritative for parent zone */ 1085 /* so answer at the child zone level */ 1086 if(original->nsec3 && original->nsec3->nsec3_is_exact) 1087 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1088 original->nsec3->nsec3_cover); 1089 return; 1090 } 1091 /* query->zone must be the parent zone */ 1092 nsec3_add_ds_proof(query, answer, original, 0); 1093 /* if the DS is from a wildcard match */ 1094 if (original==original->wildcard_child_closest_match 1095 && label_is_wildcard(dname_name(domain_dname(original)))) { 1096 /* denial for wildcard is already there */ 1097 /* add parent proof to have a closest encloser proof for wildcard parent */ 1098 /* in other words: nsec3 matching closest encloser */ 1099 if(original->parent && original->parent->nsec3 && 1100 original->parent->nsec3->nsec3_is_exact) 1101 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1102 original->parent->nsec3->nsec3_cover); 1103 } 1104 } 1105 /* the nodata is result from a wildcard match */ 1106 else if (original==original->wildcard_child_closest_match 1107 && label_is_wildcard(dname_name(domain_dname(original)))) { 1108 /* denial for wildcard is already there */ 1109 1110 /* add parent proof to have a closest encloser proof for wildcard parent */ 1111 /* in other words: nsec3 matching closest encloser */ 1112 if(original->parent && original->parent->nsec3 && 1113 original->parent->nsec3->nsec3_is_exact) 1114 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1115 original->parent->nsec3->nsec3_cover); 1116 /* proof for wildcard itself */ 1117 /* in other words: nsec3 matching source of synthesis */ 1118 if(original->nsec3) 1119 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1120 original->nsec3->nsec3_cover); 1121 } 1122 else { /* add nsec3 to prove rrset does not exist */ 1123 if(original->nsec3) { 1124 if(!original->nsec3->nsec3_is_exact) { 1125 /* go up to an existing parent */ 1126 while(original->parent && original->parent->nsec3 && !original->parent->nsec3->nsec3_is_exact) 1127 original = original->parent; 1128 } 1129 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1130 original->nsec3->nsec3_cover); 1131 if(!original->nsec3->nsec3_is_exact) { 1132 if(original->parent && original->parent->nsec3 && original->parent->nsec3->nsec3_is_exact) 1133 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1134 original->parent->nsec3->nsec3_cover); 1135 1136 } 1137 } 1138 } 1139} 1140 1141void 1142nsec3_answer_delegation(struct query *query, struct answer *answer) 1143{ 1144 if(!query->zone->nsec3_param) 1145 return; 1146 nsec3_add_ds_proof(query, answer, query->delegation_domain, 1); 1147} 1148 1149int 1150domain_has_only_NSEC3(struct domain* domain, struct zone* zone) 1151{ 1152 /* check for only NSEC3/RRSIG */ 1153 rrset_type* rrset = domain->rrsets; 1154 int nsec3_seen = 0; 1155 while(rrset) 1156 { 1157 if(!zone || rrset->zone == zone) 1158 { 1159 if(rrset->rrs[0].type == TYPE_NSEC3) 1160 nsec3_seen = 1; 1161 else if(rrset->rrs[0].type != TYPE_RRSIG) 1162 return 0; 1163 } 1164 rrset = rrset->next; 1165 } 1166 return nsec3_seen; 1167} 1168 1169void 1170nsec3_answer_authoritative(struct domain** match, struct query *query, 1171 struct answer *answer, struct domain* closest_encloser, 1172 const dname_type* qname) 1173{ 1174 if(!query->zone->nsec3_param) 1175 return; 1176 assert(match); 1177 /* there is a match, this has 1 RRset, which is NSEC3, but qtype is not. */ 1178 /* !is_existing: no RR types exist at the QNAME, nor at any descendant of QNAME */ 1179 if(*match && !(*match)->is_existing && 1180#if 0 1181 query->qtype != TYPE_NSEC3 && 1182#endif 1183 domain_has_only_NSEC3(*match, query->zone)) 1184 { 1185 /* act as if the NSEC3 domain did not exist, name error */ 1186 *match = 0; 1187 /* all nsec3s are directly below the apex, that is closest encloser */ 1188 if(query->zone->apex->nsec3 && 1189 query->zone->apex->nsec3->nsec3_is_exact) 1190 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1191 query->zone->apex->nsec3->nsec3_cover); 1192 /* disprove the nsec3 record. */ 1193 if(closest_encloser->nsec3) 1194 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, closest_encloser->nsec3->nsec3_cover); 1195 /* disprove a wildcard */ 1196 if(query->zone->apex->nsec3) 1197 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1198 query->zone->apex->nsec3->nsec3_wcard_child_cover); 1199 if (domain_wildcard_child(query->zone->apex)) { 1200 /* wildcard exists below the domain */ 1201 /* wildcard and nsec3 domain clash. server failure. */ 1202 RCODE_SET(query->packet, RCODE_SERVFAIL); 1203 /* RFC 8914 - Extended DNS Errors 1204 * 4.21. Extended DNS Error Code 0 - Other */ 1205 ASSIGN_EDE_CODE_AND_STRING_LITERAL(query->edns.ede, 1206 EDE_OTHER, "Wildcard and NSEC3 domain clash"); 1207 } 1208 return; 1209 } 1210 else if(*match && (*match)->is_existing && 1211#if 0 1212 query->qtype != TYPE_NSEC3 && 1213#endif 1214 (domain_has_only_NSEC3(*match, query->zone) || 1215 !domain_find_any_rrset(*match, query->zone))) 1216 { 1217 /* this looks like a NSEC3 domain, but is actually an empty non-terminal. */ 1218 nsec3_answer_nodata(query, answer, *match); 1219 return; 1220 } 1221 if(!*match) { 1222 /* name error, domain does not exist */ 1223 nsec3_add_closest_encloser_proof(query, answer, closest_encloser, 1224 qname); 1225 if(closest_encloser->nsec3) 1226 nsec3_add_rrset(query, answer, AUTHORITY_SECTION, 1227 closest_encloser->nsec3->nsec3_wcard_child_cover); 1228 } 1229} 1230 1231#endif /* NSEC3 */ 1232