1 /* 2 * special zone file structures and functions for better dnssec handling 3 */ 4 5 #include <ldns/config.h> 6 7 #include <ldns/ldns.h> 8 9 ldns_dnssec_rrs * 10 ldns_dnssec_rrs_new(void) 11 { 12 ldns_dnssec_rrs *new_rrs; 13 new_rrs = LDNS_MALLOC(ldns_dnssec_rrs); 14 if(!new_rrs) return NULL; 15 new_rrs->rr = NULL; 16 new_rrs->next = NULL; 17 return new_rrs; 18 } 19 20 INLINE void 21 ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep) 22 { 23 ldns_dnssec_rrs *next; 24 while (rrs) { 25 next = rrs->next; 26 if (deep) { 27 ldns_rr_free(rrs->rr); 28 } 29 LDNS_FREE(rrs); 30 rrs = next; 31 } 32 } 33 34 void 35 ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs) 36 { 37 ldns_dnssec_rrs_free_internal(rrs, 0); 38 } 39 40 void 41 ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs) 42 { 43 ldns_dnssec_rrs_free_internal(rrs, 1); 44 } 45 46 ldns_status 47 ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr) 48 { 49 int cmp; 50 ldns_dnssec_rrs *new_rrs; 51 if (!rrs || !rr) { 52 return LDNS_STATUS_ERR; 53 } 54 55 /* this could be done more efficiently; name and type should already 56 be equal */ 57 cmp = ldns_rr_compare(rrs->rr, rr); 58 if (cmp < 0) { 59 if (rrs->next) { 60 return ldns_dnssec_rrs_add_rr(rrs->next, rr); 61 } else { 62 new_rrs = ldns_dnssec_rrs_new(); 63 new_rrs->rr = rr; 64 rrs->next = new_rrs; 65 } 66 } else if (cmp > 0) { 67 /* put the current old rr in the new next, put the new 68 rr in the current container */ 69 new_rrs = ldns_dnssec_rrs_new(); 70 new_rrs->rr = rrs->rr; 71 new_rrs->next = rrs->next; 72 rrs->rr = rr; 73 rrs->next = new_rrs; 74 } 75 /* Silently ignore equal rr's */ 76 return LDNS_STATUS_OK; 77 } 78 79 void 80 ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt, 81 const ldns_dnssec_rrs *rrs) 82 { 83 if (!rrs) { 84 if ((fmt->flags & LDNS_COMMENT_LAYOUT)) 85 fprintf(out, "; <void>"); 86 } else { 87 if (rrs->rr) { 88 ldns_rr_print_fmt(out, fmt, rrs->rr); 89 } 90 if (rrs->next) { 91 ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next); 92 } 93 } 94 } 95 96 void 97 ldns_dnssec_rrs_print(FILE *out, const ldns_dnssec_rrs *rrs) 98 { 99 ldns_dnssec_rrs_print_fmt(out, ldns_output_format_default, rrs); 100 } 101 102 103 ldns_dnssec_rrsets * 104 ldns_dnssec_rrsets_new(void) 105 { 106 ldns_dnssec_rrsets *new_rrsets; 107 new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets); 108 if(!new_rrsets) return NULL; 109 new_rrsets->rrs = NULL; 110 new_rrsets->type = 0; 111 new_rrsets->signatures = NULL; 112 new_rrsets->next = NULL; 113 return new_rrsets; 114 } 115 116 INLINE void 117 ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep) 118 { 119 if (rrsets) { 120 if (rrsets->rrs) { 121 ldns_dnssec_rrs_free_internal(rrsets->rrs, deep); 122 } 123 if (rrsets->next) { 124 ldns_dnssec_rrsets_free_internal(rrsets->next, deep); 125 } 126 if (rrsets->signatures) { 127 ldns_dnssec_rrs_free_internal(rrsets->signatures, deep); 128 } 129 LDNS_FREE(rrsets); 130 } 131 } 132 133 void 134 ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets) 135 { 136 ldns_dnssec_rrsets_free_internal(rrsets, 0); 137 } 138 139 void 140 ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets) 141 { 142 ldns_dnssec_rrsets_free_internal(rrsets, 1); 143 } 144 145 ldns_rr_type 146 ldns_dnssec_rrsets_type(const ldns_dnssec_rrsets *rrsets) 147 { 148 if (rrsets) { 149 return rrsets->type; 150 } else { 151 return 0; 152 } 153 } 154 155 ldns_status 156 ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets, 157 ldns_rr_type type) 158 { 159 if (rrsets) { 160 rrsets->type = type; 161 return LDNS_STATUS_OK; 162 } 163 return LDNS_STATUS_ERR; 164 } 165 166 static ldns_dnssec_rrsets * 167 ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr) 168 { 169 ldns_dnssec_rrsets *new_rrsets; 170 ldns_rr_type rr_type; 171 bool rrsig; 172 173 new_rrsets = ldns_dnssec_rrsets_new(); 174 rr_type = ldns_rr_get_type(rr); 175 if (rr_type == LDNS_RR_TYPE_RRSIG) { 176 rrsig = true; 177 rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); 178 } else { 179 rrsig = false; 180 } 181 if (!rrsig) { 182 new_rrsets->rrs = ldns_dnssec_rrs_new(); 183 new_rrsets->rrs->rr = rr; 184 } else { 185 new_rrsets->signatures = ldns_dnssec_rrs_new(); 186 new_rrsets->signatures->rr = rr; 187 } 188 new_rrsets->type = rr_type; 189 return new_rrsets; 190 } 191 192 ldns_status 193 ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr) 194 { 195 ldns_dnssec_rrsets *new_rrsets; 196 ldns_rr_type rr_type; 197 bool rrsig = false; 198 ldns_status result = LDNS_STATUS_OK; 199 200 if (!rrsets || !rr) { 201 return LDNS_STATUS_ERR; 202 } 203 204 rr_type = ldns_rr_get_type(rr); 205 206 if (rr_type == LDNS_RR_TYPE_RRSIG) { 207 rrsig = true; 208 rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); 209 } 210 211 if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) { 212 if (!rrsig) { 213 rrsets->rrs = ldns_dnssec_rrs_new(); 214 rrsets->rrs->rr = rr; 215 rrsets->type = rr_type; 216 } else { 217 rrsets->signatures = ldns_dnssec_rrs_new(); 218 rrsets->signatures->rr = rr; 219 rrsets->type = rr_type; 220 } 221 return LDNS_STATUS_OK; 222 } 223 224 if (rr_type > ldns_dnssec_rrsets_type(rrsets)) { 225 if (rrsets->next) { 226 result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr); 227 } else { 228 new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr); 229 rrsets->next = new_rrsets; 230 } 231 } else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) { 232 /* move the current one into the new next, 233 replace field of current with data from new rr */ 234 new_rrsets = ldns_dnssec_rrsets_new(); 235 new_rrsets->rrs = rrsets->rrs; 236 new_rrsets->type = rrsets->type; 237 new_rrsets->signatures = rrsets->signatures; 238 new_rrsets->next = rrsets->next; 239 if (!rrsig) { 240 rrsets->rrs = ldns_dnssec_rrs_new(); 241 rrsets->rrs->rr = rr; 242 rrsets->signatures = NULL; 243 } else { 244 rrsets->rrs = NULL; 245 rrsets->signatures = ldns_dnssec_rrs_new(); 246 rrsets->signatures->rr = rr; 247 } 248 rrsets->type = rr_type; 249 rrsets->next = new_rrsets; 250 } else { 251 /* equal, add to current rrsets */ 252 if (rrsig) { 253 if (rrsets->signatures) { 254 result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr); 255 } else { 256 rrsets->signatures = ldns_dnssec_rrs_new(); 257 rrsets->signatures->rr = rr; 258 } 259 } else { 260 if (rrsets->rrs) { 261 result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr); 262 } else { 263 rrsets->rrs = ldns_dnssec_rrs_new(); 264 rrsets->rrs->rr = rr; 265 } 266 } 267 } 268 269 return result; 270 } 271 272 static void 273 ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt, 274 const ldns_dnssec_rrsets *rrsets, 275 bool follow, 276 bool show_soa) 277 { 278 if (!rrsets) { 279 if ((fmt->flags & LDNS_COMMENT_LAYOUT)) 280 fprintf(out, "; <void>\n"); 281 } else { 282 if (rrsets->rrs && 283 (show_soa || 284 ldns_rr_get_type(rrsets->rrs->rr) != LDNS_RR_TYPE_SOA 285 ) 286 ) { 287 ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs); 288 if (rrsets->signatures) { 289 ldns_dnssec_rrs_print_fmt(out, fmt, 290 rrsets->signatures); 291 } 292 } 293 if (follow && rrsets->next) { 294 ldns_dnssec_rrsets_print_soa_fmt(out, fmt, 295 rrsets->next, follow, show_soa); 296 } 297 } 298 } 299 300 301 void 302 ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt, 303 const ldns_dnssec_rrsets *rrsets, 304 bool follow) 305 { 306 ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true); 307 } 308 309 void 310 ldns_dnssec_rrsets_print(FILE *out, const ldns_dnssec_rrsets *rrsets, bool follow) 311 { 312 ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default, 313 rrsets, follow); 314 } 315 316 ldns_dnssec_name * 317 ldns_dnssec_name_new(void) 318 { 319 ldns_dnssec_name *new_name; 320 321 new_name = LDNS_CALLOC(ldns_dnssec_name, 1); 322 if (!new_name) { 323 return NULL; 324 } 325 /* 326 * not needed anymore because CALLOC initalizes everything to zero. 327 328 new_name->name = NULL; 329 new_name->rrsets = NULL; 330 new_name->name_alloced = false; 331 new_name->nsec = NULL; 332 new_name->nsec_signatures = NULL; 333 334 new_name->is_glue = false; 335 new_name->hashed_name = NULL; 336 337 */ 338 return new_name; 339 } 340 341 ldns_dnssec_name * 342 ldns_dnssec_name_new_frm_rr(ldns_rr *rr) 343 { 344 ldns_dnssec_name *new_name = ldns_dnssec_name_new(); 345 346 new_name->name = ldns_rr_owner(rr); 347 if(ldns_dnssec_name_add_rr(new_name, rr) != LDNS_STATUS_OK) { 348 ldns_dnssec_name_free(new_name); 349 return NULL; 350 } 351 352 return new_name; 353 } 354 355 INLINE void 356 ldns_dnssec_name_free_internal(ldns_dnssec_name *name, 357 int deep) 358 { 359 if (name) { 360 if (name->name_alloced) { 361 ldns_rdf_deep_free(name->name); 362 } 363 if (name->rrsets) { 364 ldns_dnssec_rrsets_free_internal(name->rrsets, deep); 365 } 366 if (name->nsec && deep) { 367 ldns_rr_free(name->nsec); 368 } 369 if (name->nsec_signatures) { 370 ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep); 371 } 372 if (name->hashed_name) { 373 if (deep) { 374 ldns_rdf_deep_free(name->hashed_name); 375 } 376 } 377 LDNS_FREE(name); 378 } 379 } 380 381 void 382 ldns_dnssec_name_free(ldns_dnssec_name *name) 383 { 384 ldns_dnssec_name_free_internal(name, 0); 385 } 386 387 void 388 ldns_dnssec_name_deep_free(ldns_dnssec_name *name) 389 { 390 ldns_dnssec_name_free_internal(name, 1); 391 } 392 393 ldns_rdf * 394 ldns_dnssec_name_name(const ldns_dnssec_name *name) 395 { 396 if (name) { 397 return name->name; 398 } 399 return NULL; 400 } 401 402 bool 403 ldns_dnssec_name_is_glue(const ldns_dnssec_name *name) 404 { 405 if (name) { 406 return name->is_glue; 407 } 408 return false; 409 } 410 411 void 412 ldns_dnssec_name_set_name(ldns_dnssec_name *rrset, 413 ldns_rdf *dname) 414 { 415 if (rrset && dname) { 416 rrset->name = dname; 417 } 418 } 419 420 421 void 422 ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec) 423 { 424 if (rrset && nsec) { 425 rrset->nsec = nsec; 426 } 427 } 428 429 int 430 ldns_dnssec_name_cmp(const void *a, const void *b) 431 { 432 ldns_dnssec_name *na = (ldns_dnssec_name *) a; 433 ldns_dnssec_name *nb = (ldns_dnssec_name *) b; 434 435 if (na && nb) { 436 return ldns_dname_compare(ldns_dnssec_name_name(na), 437 ldns_dnssec_name_name(nb)); 438 } else if (na) { 439 return 1; 440 } else if (nb) { 441 return -1; 442 } else { 443 return 0; 444 } 445 } 446 447 ldns_status 448 ldns_dnssec_name_add_rr(ldns_dnssec_name *name, 449 ldns_rr *rr) 450 { 451 ldns_status result = LDNS_STATUS_OK; 452 ldns_rr_type rr_type; 453 ldns_rr_type typecovered = 0; 454 455 /* special handling for NSEC3 and NSECX covering RRSIGS */ 456 457 if (!name || !rr) { 458 return LDNS_STATUS_ERR; 459 } 460 461 rr_type = ldns_rr_get_type(rr); 462 463 if (rr_type == LDNS_RR_TYPE_RRSIG) { 464 typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); 465 } 466 467 if (rr_type == LDNS_RR_TYPE_NSEC || 468 rr_type == LDNS_RR_TYPE_NSEC3) { 469 /* XX check if is already set (and error?) */ 470 name->nsec = rr; 471 } else if (typecovered == LDNS_RR_TYPE_NSEC || 472 typecovered == LDNS_RR_TYPE_NSEC3) { 473 if (name->nsec_signatures) { 474 result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr); 475 } else { 476 name->nsec_signatures = ldns_dnssec_rrs_new(); 477 name->nsec_signatures->rr = rr; 478 } 479 } else { 480 /* it's a 'normal' RR, add it to the right rrset */ 481 if (name->rrsets) { 482 result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr); 483 } else { 484 name->rrsets = ldns_dnssec_rrsets_new(); 485 result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr); 486 } 487 } 488 return result; 489 } 490 491 ldns_dnssec_rrsets * 492 ldns_dnssec_name_find_rrset(const ldns_dnssec_name *name, 493 ldns_rr_type type) { 494 ldns_dnssec_rrsets *result; 495 496 result = name->rrsets; 497 while (result) { 498 if (result->type == type) { 499 return result; 500 } else { 501 result = result->next; 502 } 503 } 504 return NULL; 505 } 506 507 ldns_dnssec_rrsets * 508 ldns_dnssec_zone_find_rrset(const ldns_dnssec_zone *zone, 509 const ldns_rdf *dname, 510 ldns_rr_type type) 511 { 512 ldns_rbnode_t *node; 513 514 if (!zone || !dname || !zone->names) { 515 return NULL; 516 } 517 518 node = ldns_rbtree_search(zone->names, dname); 519 if (node) { 520 return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data, 521 type); 522 } else { 523 return NULL; 524 } 525 } 526 527 static void 528 ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt, 529 const ldns_dnssec_name *name, 530 bool show_soa) 531 { 532 if (name) { 533 if(name->rrsets) { 534 ldns_dnssec_rrsets_print_soa_fmt(out, fmt, 535 name->rrsets, true, show_soa); 536 } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) { 537 fprintf(out, ";; Empty nonterminal: "); 538 ldns_rdf_print(out, name->name); 539 fprintf(out, "\n"); 540 } 541 if(name->nsec) { 542 ldns_rr_print_fmt(out, fmt, name->nsec); 543 } 544 if (name->nsec_signatures) { 545 ldns_dnssec_rrs_print_fmt(out, fmt, 546 name->nsec_signatures); 547 } 548 } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) { 549 fprintf(out, "; <void>\n"); 550 } 551 } 552 553 554 void 555 ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt, 556 const ldns_dnssec_name *name) 557 { 558 ldns_dnssec_name_print_soa_fmt(out, fmt, name, true); 559 } 560 561 void 562 ldns_dnssec_name_print(FILE *out, const ldns_dnssec_name *name) 563 { 564 ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name); 565 } 566 567 568 ldns_dnssec_zone * 569 ldns_dnssec_zone_new(void) 570 { 571 ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone); 572 if(!zone) return NULL; 573 zone->soa = NULL; 574 zone->names = NULL; 575 zone->hashed_names = NULL; 576 zone->_nsec3params = NULL; 577 578 return zone; 579 } 580 581 static bool 582 rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t) 583 { 584 return ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG 585 && ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t; 586 } 587 588 /* When the zone is first read into an list and then inserted into an 589 * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next) 590 * to each other. Because ldns-verify-zone (the only program that uses this 591 * function) uses the rbtree mostly for sequentual walking, this results 592 * in a speed increase (of 15% on linux) because we have less CPU-cache misses. 593 */ 594 #define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */ 595 596 static ldns_status 597 ldns_dnssec_zone_add_empty_nonterminals_nsec3( 598 ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s); 599 600 static void 601 ldns_todo_nsec3_ents_node_free(ldns_rbnode_t *node, void *arg) { 602 (void) arg; 603 ldns_rdf_deep_free((ldns_rdf *)node->key); 604 LDNS_FREE(node); 605 } 606 607 ldns_status 608 ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* origin, 609 uint32_t ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr) 610 { 611 ldns_rr* cur_rr; 612 size_t i; 613 614 ldns_rdf *my_origin = NULL; 615 ldns_rdf *my_prev = NULL; 616 617 ldns_dnssec_zone *newzone = ldns_dnssec_zone_new(); 618 /* NSEC3s may occur before the names they refer to. We must remember 619 them and add them to the name later on, after the name is read. 620 We track not yet matching NSEC3s*n the todo_nsec3s list */ 621 ldns_rr_list* todo_nsec3s = ldns_rr_list_new(); 622 /* when reading NSEC3s, there is a chance that we encounter nsecs 623 for empty nonterminals, whose nonterminals we cannot derive yet 624 because the needed information is to be read later. 625 626 nsec3_ents (where ent is e.n.t.; i.e. empty non terminal) will 627 hold the NSEC3s that still didn't have a matching name in the 628 zone tree, even after all names were read. They can only match 629 after the zone is equiped with all the empty non terminals. */ 630 ldns_rbtree_t todo_nsec3_ents; 631 ldns_rbnode_t *new_node; 632 ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new(); 633 634 ldns_status status; 635 636 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP 637 ldns_zone* zone = NULL; 638 #else 639 uint32_t my_ttl = ttl; 640 #endif 641 642 ldns_rbtree_init(&todo_nsec3_ents, ldns_dname_compare_v); 643 644 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP 645 status = ldns_zone_new_frm_fp_l(&zone, fp, origin,ttl, c, line_nr); 646 if (status != LDNS_STATUS_OK) 647 goto error; 648 #endif 649 if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) { 650 status = LDNS_STATUS_MEM_ERR; 651 goto error; 652 } 653 if (origin) { 654 if (!(my_origin = ldns_rdf_clone(origin))) { 655 status = LDNS_STATUS_MEM_ERR; 656 goto error; 657 } 658 if (!(my_prev = ldns_rdf_clone(origin))) { 659 status = LDNS_STATUS_MEM_ERR; 660 goto error; 661 } 662 } 663 664 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP 665 if (ldns_zone_soa(zone)) { 666 status = ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone)); 667 if (status != LDNS_STATUS_OK) 668 goto error; 669 } 670 for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) { 671 cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i); 672 status = LDNS_STATUS_OK; 673 #else 674 while (!feof(fp)) { 675 status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin, 676 &my_prev, line_nr); 677 678 #endif 679 switch (status) { 680 case LDNS_STATUS_OK: 681 682 status = ldns_dnssec_zone_add_rr(newzone, cur_rr); 683 if (status == 684 LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) { 685 686 if (rr_is_rrsig_covering(cur_rr, 687 LDNS_RR_TYPE_NSEC3)){ 688 ldns_rr_list_push_rr(todo_nsec3_rrsigs, 689 cur_rr); 690 } else { 691 ldns_rr_list_push_rr(todo_nsec3s, 692 cur_rr); 693 } 694 status = LDNS_STATUS_OK; 695 696 } else if (status != LDNS_STATUS_OK) 697 goto error; 698 699 break; 700 701 702 case LDNS_STATUS_SYNTAX_EMPTY: /* empty line was seen */ 703 case LDNS_STATUS_SYNTAX_TTL: /* the ttl was set*/ 704 case LDNS_STATUS_SYNTAX_ORIGIN: /* the origin was set*/ 705 status = LDNS_STATUS_OK; 706 break; 707 708 case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */ 709 status = LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL; 710 break; 711 712 default: 713 goto error; 714 } 715 } 716 717 for (i = 0; status == LDNS_STATUS_OK && 718 i < ldns_rr_list_rr_count(todo_nsec3s); i++) { 719 cur_rr = ldns_rr_list_rr(todo_nsec3s, i); 720 status = ldns_dnssec_zone_add_rr(newzone, cur_rr); 721 if (status == LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) { 722 if (!(new_node = LDNS_MALLOC(ldns_rbnode_t))) { 723 status = LDNS_STATUS_MEM_ERR; 724 break; 725 } 726 new_node->key = ldns_dname_label(ldns_rr_owner(cur_rr), 0); 727 new_node->data = cur_rr; 728 if (!ldns_rbtree_insert(&todo_nsec3_ents, new_node)) { 729 LDNS_FREE(new_node); 730 status = LDNS_STATUS_MEM_ERR; 731 break; 732 } 733 status = LDNS_STATUS_OK; 734 } 735 } 736 if (todo_nsec3_ents.count > 0) 737 (void) ldns_dnssec_zone_add_empty_nonterminals_nsec3( 738 newzone, &todo_nsec3_ents); 739 for (i = 0; status == LDNS_STATUS_OK && 740 i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++) { 741 cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i); 742 status = ldns_dnssec_zone_add_rr(newzone, cur_rr); 743 } 744 if (z) { 745 *z = newzone; 746 newzone = NULL; 747 } else { 748 ldns_dnssec_zone_free(newzone); 749 } 750 751 error: 752 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP 753 if (zone) { 754 ldns_zone_free(zone); 755 } 756 #endif 757 ldns_rr_list_free(todo_nsec3_rrsigs); 758 ldns_traverse_postorder(&todo_nsec3_ents, 759 ldns_todo_nsec3_ents_node_free, NULL); 760 ldns_rr_list_free(todo_nsec3s); 761 762 if (my_origin) { 763 ldns_rdf_deep_free(my_origin); 764 } 765 if (my_prev) { 766 ldns_rdf_deep_free(my_prev); 767 } 768 if (newzone) { 769 ldns_dnssec_zone_free(newzone); 770 } 771 return status; 772 } 773 774 ldns_status 775 ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* origin, 776 uint32_t ttl, ldns_rr_class ATTR_UNUSED(c)) 777 { 778 return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL); 779 } 780 781 static void 782 ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) { 783 (void) arg; 784 ldns_dnssec_name_free((ldns_dnssec_name *)node->data); 785 LDNS_FREE(node); 786 } 787 788 static void 789 ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) { 790 (void) arg; 791 ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data); 792 LDNS_FREE(node); 793 } 794 795 void 796 ldns_dnssec_zone_free(ldns_dnssec_zone *zone) 797 { 798 if (zone) { 799 if (zone->names) { 800 /* destroy all name structures within the tree */ 801 ldns_traverse_postorder(zone->names, 802 ldns_dnssec_name_node_free, 803 NULL); 804 LDNS_FREE(zone->names); 805 } 806 LDNS_FREE(zone); 807 } 808 } 809 810 void 811 ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone) 812 { 813 if (zone) { 814 if (zone->names) { 815 /* destroy all name structures within the tree */ 816 ldns_traverse_postorder(zone->names, 817 ldns_dnssec_name_node_deep_free, 818 NULL); 819 LDNS_FREE(zone->names); 820 } 821 LDNS_FREE(zone); 822 } 823 } 824 825 /* use for dname comparison in tree */ 826 int 827 ldns_dname_compare_v(const void *a, const void *b) { 828 return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b); 829 } 830 831 static void 832 ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone, 833 ldns_dnssec_name* name, ldns_rr* nsec3rr); 834 835 static void 836 ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) { 837 (void) arg; 838 LDNS_FREE(node); 839 } 840 841 static void 842 ldns_dnssec_zone_hashed_names_from_nsec3( 843 ldns_dnssec_zone* zone, ldns_rr* nsec3rr) 844 { 845 ldns_rbnode_t* current_node; 846 ldns_dnssec_name* current_name; 847 848 assert(zone != NULL); 849 assert(nsec3rr != NULL); 850 851 if (zone->hashed_names) { 852 ldns_traverse_postorder(zone->hashed_names, 853 ldns_hashed_names_node_free, NULL); 854 LDNS_FREE(zone->hashed_names); 855 } 856 zone->_nsec3params = nsec3rr; 857 858 /* So this is a NSEC3 zone. 859 * Calculate hashes for all names already in the zone 860 */ 861 zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v); 862 if (zone->hashed_names == NULL) { 863 return; 864 } 865 for ( current_node = ldns_rbtree_first(zone->names) 866 ; current_node != LDNS_RBTREE_NULL 867 ; current_node = ldns_rbtree_next(current_node) 868 ) { 869 current_name = (ldns_dnssec_name *) current_node->data; 870 ldns_dnssec_name_make_hashed_name(zone, current_name, nsec3rr); 871 872 } 873 } 874 875 static void 876 ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone, 877 ldns_dnssec_name* name, ldns_rr* nsec3rr) 878 { 879 ldns_rbnode_t* new_node; 880 881 assert(name != NULL); 882 if (! zone->_nsec3params) { 883 if (! nsec3rr) { 884 return; 885 } 886 ldns_dnssec_zone_hashed_names_from_nsec3(zone, nsec3rr); 887 888 } else if (! nsec3rr) { 889 nsec3rr = zone->_nsec3params; 890 } 891 name->hashed_name = ldns_nsec3_hash_name_frm_nsec3(nsec3rr, name->name); 892 893 /* Also store in zone->hashed_names */ 894 if ((new_node = LDNS_MALLOC(ldns_rbnode_t))) { 895 896 new_node->key = name->hashed_name; 897 new_node->data = name; 898 899 if (ldns_rbtree_insert(zone->hashed_names, new_node) == NULL) { 900 901 LDNS_FREE(new_node); 902 } 903 } 904 } 905 906 907 static ldns_rbnode_t * 908 ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, ldns_rr *rr) { 909 ldns_rdf *hashed_name; 910 911 hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0); 912 if (hashed_name == NULL) { 913 return NULL; 914 } 915 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 && ! zone->_nsec3params){ 916 917 ldns_dnssec_zone_hashed_names_from_nsec3(zone, rr); 918 } 919 if (zone->hashed_names == NULL) { 920 ldns_rdf_deep_free(hashed_name); 921 return NULL; 922 } 923 return ldns_rbtree_search(zone->hashed_names, hashed_name); 924 } 925 926 ldns_status 927 ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr) 928 { 929 ldns_status result = LDNS_STATUS_OK; 930 ldns_dnssec_name *cur_name; 931 ldns_rbnode_t *cur_node; 932 ldns_rr_type type_covered = 0; 933 934 if (!zone || !rr) { 935 return LDNS_STATUS_ERR; 936 } 937 938 if (!zone->names) { 939 zone->names = ldns_rbtree_create(ldns_dname_compare_v); 940 if(!zone->names) return LDNS_STATUS_MEM_ERR; 941 } 942 943 /* we need the original of the hashed name if this is 944 an NSEC3, or an RRSIG that covers an NSEC3 */ 945 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) { 946 type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); 947 } 948 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 || 949 type_covered == LDNS_RR_TYPE_NSEC3) { 950 cur_node = ldns_dnssec_zone_find_nsec3_original(zone, rr); 951 if (!cur_node) { 952 return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND; 953 } 954 } else { 955 cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr)); 956 } 957 if (!cur_node) { 958 /* add */ 959 cur_name = ldns_dnssec_name_new_frm_rr(rr); 960 if(!cur_name) return LDNS_STATUS_MEM_ERR; 961 cur_node = LDNS_MALLOC(ldns_rbnode_t); 962 if(!cur_node) { 963 ldns_dnssec_name_free(cur_name); 964 return LDNS_STATUS_MEM_ERR; 965 } 966 cur_node->key = ldns_rr_owner(rr); 967 cur_node->data = cur_name; 968 (void)ldns_rbtree_insert(zone->names, cur_node); 969 ldns_dnssec_name_make_hashed_name(zone, cur_name, NULL); 970 } else { 971 cur_name = (ldns_dnssec_name *) cur_node->data; 972 result = ldns_dnssec_name_add_rr(cur_name, rr); 973 } 974 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) { 975 zone->soa = cur_name; 976 } 977 return result; 978 } 979 980 void 981 ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt, 982 const ldns_rbtree_t *tree, 983 bool print_soa) 984 { 985 ldns_rbnode_t *node; 986 ldns_dnssec_name *name; 987 988 node = ldns_rbtree_first(tree); 989 while (node != LDNS_RBTREE_NULL) { 990 name = (ldns_dnssec_name *) node->data; 991 ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa); 992 if ((fmt->flags & LDNS_COMMENT_LAYOUT)) 993 fprintf(out, ";\n"); 994 node = ldns_rbtree_next(node); 995 } 996 } 997 998 void 999 ldns_dnssec_zone_names_print(FILE *out, const ldns_rbtree_t *tree, bool print_soa) 1000 { 1001 ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default, 1002 tree, print_soa); 1003 } 1004 1005 void 1006 ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt, 1007 const ldns_dnssec_zone *zone) 1008 { 1009 if (zone) { 1010 if (zone->soa) { 1011 if ((fmt->flags & LDNS_COMMENT_LAYOUT)) { 1012 fprintf(out, ";; Zone: "); 1013 ldns_rdf_print(out, ldns_dnssec_name_name( 1014 zone->soa)); 1015 fprintf(out, "\n;\n"); 1016 } 1017 ldns_dnssec_rrsets_print_fmt(out, fmt, 1018 ldns_dnssec_name_find_rrset( 1019 zone->soa, 1020 LDNS_RR_TYPE_SOA), 1021 false); 1022 if ((fmt->flags & LDNS_COMMENT_LAYOUT)) 1023 fprintf(out, ";\n"); 1024 } 1025 1026 if (zone->names) { 1027 ldns_dnssec_zone_names_print_fmt(out, fmt, 1028 zone->names, false); 1029 } 1030 } 1031 } 1032 1033 void 1034 ldns_dnssec_zone_print(FILE *out, const ldns_dnssec_zone *zone) 1035 { 1036 ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone); 1037 } 1038 1039 static ldns_status 1040 ldns_dnssec_zone_add_empty_nonterminals_nsec3( 1041 ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s) 1042 { 1043 ldns_dnssec_name *new_name; 1044 ldns_rdf *cur_name; 1045 ldns_rdf *next_name; 1046 ldns_rbnode_t *cur_node, *next_node, *new_node; 1047 1048 /* for the detection */ 1049 uint16_t i, cur_label_count, next_label_count; 1050 uint16_t soa_label_count = 0; 1051 ldns_rdf *l1, *l2; 1052 int lpos; 1053 1054 if (!zone) { 1055 return LDNS_STATUS_ERR; 1056 } 1057 if (zone->soa && zone->soa->name) { 1058 soa_label_count = ldns_dname_label_count(zone->soa->name); 1059 } 1060 1061 cur_node = ldns_rbtree_first(zone->names); 1062 while (cur_node != LDNS_RBTREE_NULL) { 1063 next_node = ldns_rbtree_next(cur_node); 1064 1065 /* skip glue */ 1066 while (next_node != LDNS_RBTREE_NULL && 1067 next_node->data && 1068 ((ldns_dnssec_name *)next_node->data)->is_glue 1069 ) { 1070 next_node = ldns_rbtree_next(next_node); 1071 } 1072 1073 if (next_node == LDNS_RBTREE_NULL) { 1074 next_node = ldns_rbtree_first(zone->names); 1075 } 1076 if (! cur_node->data || ! next_node->data) { 1077 return LDNS_STATUS_ERR; 1078 } 1079 cur_name = ((ldns_dnssec_name *)cur_node->data)->name; 1080 next_name = ((ldns_dnssec_name *)next_node->data)->name; 1081 cur_label_count = ldns_dname_label_count(cur_name); 1082 next_label_count = ldns_dname_label_count(next_name); 1083 1084 /* Since the names are in canonical order, we can 1085 * recognize empty non-terminals by their labels; 1086 * every label after the first one on the next owner 1087 * name is a non-terminal if it either does not exist 1088 * in the current name or is different from the same 1089 * label in the current name (counting from the end) 1090 */ 1091 for (i = 1; i < next_label_count - soa_label_count; i++) { 1092 lpos = (int)cur_label_count - (int)next_label_count + (int)i; 1093 if (lpos >= 0) { 1094 l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos); 1095 } else { 1096 l1 = NULL; 1097 } 1098 l2 = ldns_dname_clone_from(next_name, i); 1099 1100 if (!l1 || ldns_dname_compare(l1, l2) != 0) { 1101 /* We have an empty nonterminal, add it to the 1102 * tree 1103 */ 1104 ldns_rbnode_t *node = NULL; 1105 ldns_rdf *ent_name; 1106 1107 if (!(ent_name = ldns_dname_clone_from( 1108 next_name, i))) 1109 return LDNS_STATUS_MEM_ERR; 1110 1111 if (nsec3s && zone->_nsec3params) { 1112 ldns_rdf *ent_hashed_name; 1113 1114 if (!(ent_hashed_name = 1115 ldns_nsec3_hash_name_frm_nsec3( 1116 zone->_nsec3params, 1117 ent_name))) 1118 return LDNS_STATUS_MEM_ERR; 1119 node = ldns_rbtree_search(nsec3s, 1120 ent_hashed_name); 1121 if (!node) { 1122 ldns_rdf_deep_free(l1); 1123 ldns_rdf_deep_free(l2); 1124 continue; 1125 } 1126 } 1127 new_name = ldns_dnssec_name_new(); 1128 if (!new_name) { 1129 return LDNS_STATUS_MEM_ERR; 1130 } 1131 new_name->name = ent_name; 1132 if (!new_name->name) { 1133 ldns_dnssec_name_free(new_name); 1134 return LDNS_STATUS_MEM_ERR; 1135 } 1136 new_name->name_alloced = true; 1137 new_node = LDNS_MALLOC(ldns_rbnode_t); 1138 if (!new_node) { 1139 ldns_dnssec_name_free(new_name); 1140 return LDNS_STATUS_MEM_ERR; 1141 } 1142 new_node->key = new_name->name; 1143 new_node->data = new_name; 1144 (void)ldns_rbtree_insert(zone->names, new_node); 1145 ldns_dnssec_name_make_hashed_name( 1146 zone, new_name, NULL); 1147 if (node) 1148 (void) ldns_dnssec_zone_add_rr(zone, 1149 (ldns_rr *)node->data); 1150 } 1151 ldns_rdf_deep_free(l1); 1152 ldns_rdf_deep_free(l2); 1153 } 1154 1155 /* we might have inserted a new node after 1156 * the current one so we can't just use next() 1157 */ 1158 if (next_node != ldns_rbtree_first(zone->names)) { 1159 cur_node = next_node; 1160 } else { 1161 cur_node = LDNS_RBTREE_NULL; 1162 } 1163 } 1164 return LDNS_STATUS_OK; 1165 } 1166 1167 ldns_status 1168 ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone) 1169 { 1170 return ldns_dnssec_zone_add_empty_nonterminals_nsec3(zone, NULL); 1171 } 1172 1173 bool 1174 ldns_dnssec_zone_is_nsec3_optout(const ldns_dnssec_zone* zone) 1175 { 1176 ldns_rr* nsec3; 1177 ldns_rbnode_t* node; 1178 1179 if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) { 1180 node = ldns_rbtree_first(zone->names); 1181 while (node != LDNS_RBTREE_NULL) { 1182 nsec3 = ((ldns_dnssec_name*)node->data)->nsec; 1183 if (nsec3 &&ldns_rr_get_type(nsec3) 1184 == LDNS_RR_TYPE_NSEC3 && 1185 ldns_nsec3_optout(nsec3)) { 1186 return true; 1187 } 1188 node = ldns_rbtree_next(node); 1189 } 1190 } 1191 return false; 1192 } 1193