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