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