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 newzone = NULL; 750 } 751 752 error: 753 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP 754 if (zone) { 755 ldns_zone_free(zone); 756 } 757 #endif 758 ldns_rr_list_free(todo_nsec3_rrsigs); 759 ldns_traverse_postorder(&todo_nsec3_ents, 760 ldns_todo_nsec3_ents_node_free, NULL); 761 ldns_rr_list_free(todo_nsec3s); 762 763 if (my_origin) { 764 ldns_rdf_deep_free(my_origin); 765 } 766 if (my_prev) { 767 ldns_rdf_deep_free(my_prev); 768 } 769 if (newzone) { 770 ldns_dnssec_zone_free(newzone); 771 } 772 return status; 773 } 774 775 ldns_status 776 ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* origin, 777 uint32_t ttl, ldns_rr_class ATTR_UNUSED(c)) 778 { 779 return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL); 780 } 781 782 static void 783 ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) { 784 (void) arg; 785 ldns_dnssec_name_free((ldns_dnssec_name *)node->data); 786 LDNS_FREE(node); 787 } 788 789 static void 790 ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) { 791 (void) arg; 792 ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data); 793 LDNS_FREE(node); 794 } 795 796 void 797 ldns_dnssec_zone_free(ldns_dnssec_zone *zone) 798 { 799 if (zone) { 800 if (zone->names) { 801 /* destroy all name structures within the tree */ 802 ldns_traverse_postorder(zone->names, 803 ldns_dnssec_name_node_free, 804 NULL); 805 LDNS_FREE(zone->names); 806 } 807 LDNS_FREE(zone); 808 } 809 } 810 811 void 812 ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone) 813 { 814 if (zone) { 815 if (zone->names) { 816 /* destroy all name structures within the tree */ 817 ldns_traverse_postorder(zone->names, 818 ldns_dnssec_name_node_deep_free, 819 NULL); 820 LDNS_FREE(zone->names); 821 } 822 LDNS_FREE(zone); 823 } 824 } 825 826 /* use for dname comparison in tree */ 827 int 828 ldns_dname_compare_v(const void *a, const void *b) { 829 return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b); 830 } 831 832 static void 833 ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone, 834 ldns_dnssec_name* name, ldns_rr* nsec3rr); 835 836 static void 837 ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) { 838 (void) arg; 839 LDNS_FREE(node); 840 } 841 842 static void 843 ldns_dnssec_zone_hashed_names_from_nsec3( 844 ldns_dnssec_zone* zone, ldns_rr* nsec3rr) 845 { 846 ldns_rbnode_t* current_node; 847 ldns_dnssec_name* current_name; 848 849 assert(zone != NULL); 850 assert(nsec3rr != NULL); 851 852 if (zone->hashed_names) { 853 ldns_traverse_postorder(zone->hashed_names, 854 ldns_hashed_names_node_free, NULL); 855 LDNS_FREE(zone->hashed_names); 856 } 857 zone->_nsec3params = nsec3rr; 858 859 /* So this is a NSEC3 zone. 860 * Calculate hashes for all names already in the zone 861 */ 862 zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v); 863 if (zone->hashed_names == NULL) { 864 return; 865 } 866 for ( current_node = ldns_rbtree_first(zone->names) 867 ; current_node != LDNS_RBTREE_NULL 868 ; current_node = ldns_rbtree_next(current_node) 869 ) { 870 current_name = (ldns_dnssec_name *) current_node->data; 871 ldns_dnssec_name_make_hashed_name(zone, current_name, nsec3rr); 872 873 } 874 } 875 876 static void 877 ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone, 878 ldns_dnssec_name* name, ldns_rr* nsec3rr) 879 { 880 ldns_rbnode_t* new_node; 881 882 assert(name != NULL); 883 if (! zone->_nsec3params) { 884 if (! nsec3rr) { 885 return; 886 } 887 ldns_dnssec_zone_hashed_names_from_nsec3(zone, nsec3rr); 888 889 } else if (! nsec3rr) { 890 nsec3rr = zone->_nsec3params; 891 } 892 name->hashed_name = ldns_nsec3_hash_name_frm_nsec3(nsec3rr, name->name); 893 894 /* Also store in zone->hashed_names */ 895 if ((new_node = LDNS_MALLOC(ldns_rbnode_t))) { 896 897 new_node->key = name->hashed_name; 898 new_node->data = name; 899 900 if (ldns_rbtree_insert(zone->hashed_names, new_node) == NULL) { 901 902 LDNS_FREE(new_node); 903 } 904 } 905 } 906 907 908 static ldns_rbnode_t * 909 ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, ldns_rr *rr) { 910 ldns_rdf *hashed_name; 911 912 hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0); 913 if (hashed_name == NULL) { 914 return NULL; 915 } 916 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 && ! zone->_nsec3params){ 917 918 ldns_dnssec_zone_hashed_names_from_nsec3(zone, rr); 919 } 920 if (zone->hashed_names == NULL) { 921 ldns_rdf_deep_free(hashed_name); 922 return NULL; 923 } 924 return ldns_rbtree_search(zone->hashed_names, hashed_name); 925 } 926 927 ldns_status 928 ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr) 929 { 930 ldns_status result = LDNS_STATUS_OK; 931 ldns_dnssec_name *cur_name; 932 ldns_rbnode_t *cur_node; 933 ldns_rr_type type_covered = 0; 934 935 if (!zone || !rr) { 936 return LDNS_STATUS_ERR; 937 } 938 939 if (!zone->names) { 940 zone->names = ldns_rbtree_create(ldns_dname_compare_v); 941 if(!zone->names) return LDNS_STATUS_MEM_ERR; 942 } 943 944 /* we need the original of the hashed name if this is 945 an NSEC3, or an RRSIG that covers an NSEC3 */ 946 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) { 947 type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)); 948 } 949 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 || 950 type_covered == LDNS_RR_TYPE_NSEC3) { 951 cur_node = ldns_dnssec_zone_find_nsec3_original(zone, rr); 952 if (!cur_node) { 953 return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND; 954 } 955 } else { 956 cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr)); 957 } 958 if (!cur_node) { 959 /* add */ 960 cur_name = ldns_dnssec_name_new_frm_rr(rr); 961 if(!cur_name) return LDNS_STATUS_MEM_ERR; 962 cur_node = LDNS_MALLOC(ldns_rbnode_t); 963 if(!cur_node) { 964 ldns_dnssec_name_free(cur_name); 965 return LDNS_STATUS_MEM_ERR; 966 } 967 cur_node->key = ldns_rr_owner(rr); 968 cur_node->data = cur_name; 969 (void)ldns_rbtree_insert(zone->names, cur_node); 970 ldns_dnssec_name_make_hashed_name(zone, cur_name, NULL); 971 } else { 972 cur_name = (ldns_dnssec_name *) cur_node->data; 973 result = ldns_dnssec_name_add_rr(cur_name, rr); 974 } 975 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) { 976 zone->soa = cur_name; 977 } 978 return result; 979 } 980 981 void 982 ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt, 983 const ldns_rbtree_t *tree, 984 bool print_soa) 985 { 986 ldns_rbnode_t *node; 987 ldns_dnssec_name *name; 988 989 node = ldns_rbtree_first(tree); 990 while (node != LDNS_RBTREE_NULL) { 991 name = (ldns_dnssec_name *) node->data; 992 ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa); 993 if ((fmt->flags & LDNS_COMMENT_LAYOUT)) 994 fprintf(out, ";\n"); 995 node = ldns_rbtree_next(node); 996 } 997 } 998 999 void 1000 ldns_dnssec_zone_names_print(FILE *out, const ldns_rbtree_t *tree, bool print_soa) 1001 { 1002 ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default, 1003 tree, print_soa); 1004 } 1005 1006 void 1007 ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt, 1008 const ldns_dnssec_zone *zone) 1009 { 1010 if (zone) { 1011 if (zone->soa) { 1012 if ((fmt->flags & LDNS_COMMENT_LAYOUT)) { 1013 fprintf(out, ";; Zone: "); 1014 ldns_rdf_print(out, ldns_dnssec_name_name( 1015 zone->soa)); 1016 fprintf(out, "\n;\n"); 1017 } 1018 ldns_dnssec_rrsets_print_fmt(out, fmt, 1019 ldns_dnssec_name_find_rrset( 1020 zone->soa, 1021 LDNS_RR_TYPE_SOA), 1022 false); 1023 if ((fmt->flags & LDNS_COMMENT_LAYOUT)) 1024 fprintf(out, ";\n"); 1025 } 1026 1027 if (zone->names) { 1028 ldns_dnssec_zone_names_print_fmt(out, fmt, 1029 zone->names, false); 1030 } 1031 } 1032 } 1033 1034 void 1035 ldns_dnssec_zone_print(FILE *out, const ldns_dnssec_zone *zone) 1036 { 1037 ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone); 1038 } 1039 1040 static ldns_status 1041 ldns_dnssec_zone_add_empty_nonterminals_nsec3( 1042 ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s) 1043 { 1044 ldns_dnssec_name *new_name; 1045 ldns_rdf *cur_name; 1046 ldns_rdf *next_name; 1047 ldns_rbnode_t *cur_node, *next_node, *new_node; 1048 1049 /* for the detection */ 1050 uint16_t i, cur_label_count, next_label_count; 1051 uint16_t soa_label_count = 0; 1052 ldns_rdf *l1, *l2; 1053 int lpos; 1054 1055 if (!zone) { 1056 return LDNS_STATUS_ERR; 1057 } 1058 if (zone->soa && zone->soa->name) { 1059 soa_label_count = ldns_dname_label_count(zone->soa->name); 1060 } 1061 1062 cur_node = ldns_rbtree_first(zone->names); 1063 while (cur_node != LDNS_RBTREE_NULL) { 1064 next_node = ldns_rbtree_next(cur_node); 1065 1066 /* skip glue */ 1067 while (next_node != LDNS_RBTREE_NULL && 1068 next_node->data && 1069 ((ldns_dnssec_name *)next_node->data)->is_glue 1070 ) { 1071 next_node = ldns_rbtree_next(next_node); 1072 } 1073 1074 if (next_node == LDNS_RBTREE_NULL) { 1075 next_node = ldns_rbtree_first(zone->names); 1076 } 1077 if (! cur_node->data || ! next_node->data) { 1078 return LDNS_STATUS_ERR; 1079 } 1080 cur_name = ((ldns_dnssec_name *)cur_node->data)->name; 1081 next_name = ((ldns_dnssec_name *)next_node->data)->name; 1082 cur_label_count = ldns_dname_label_count(cur_name); 1083 next_label_count = ldns_dname_label_count(next_name); 1084 1085 /* Since the names are in canonical order, we can 1086 * recognize empty non-terminals by their labels; 1087 * every label after the first one on the next owner 1088 * name is a non-terminal if it either does not exist 1089 * in the current name or is different from the same 1090 * label in the current name (counting from the end) 1091 */ 1092 for (i = 1; i < next_label_count - soa_label_count; i++) { 1093 lpos = (int)cur_label_count - (int)next_label_count + (int)i; 1094 if (lpos >= 0) { 1095 l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos); 1096 } else { 1097 l1 = NULL; 1098 } 1099 l2 = ldns_dname_clone_from(next_name, i); 1100 1101 if (!l1 || ldns_dname_compare(l1, l2) != 0) { 1102 /* We have an empty nonterminal, add it to the 1103 * tree 1104 */ 1105 ldns_rbnode_t *node = NULL; 1106 ldns_rdf *ent_name; 1107 1108 if (!(ent_name = ldns_dname_clone_from( 1109 next_name, i))) { 1110 1111 ldns_rdf_deep_free(l1); 1112 ldns_rdf_deep_free(l2); 1113 return LDNS_STATUS_MEM_ERR; 1114 } 1115 1116 if (nsec3s && zone->_nsec3params) { 1117 ldns_rdf *ent_hashed_name; 1118 1119 if (!(ent_hashed_name = 1120 ldns_nsec3_hash_name_frm_nsec3( 1121 zone->_nsec3params, 1122 ent_name))) { 1123 ldns_rdf_deep_free(l1); 1124 ldns_rdf_deep_free(l2); 1125 ldns_rdf_deep_free(ent_name); 1126 return LDNS_STATUS_MEM_ERR; 1127 } 1128 node = ldns_rbtree_search(nsec3s, 1129 ent_hashed_name); 1130 if (!node) { 1131 ldns_rdf_deep_free(l1); 1132 ldns_rdf_deep_free(l2); 1133 ldns_rdf_deep_free(ent_name); 1134 continue; 1135 } 1136 } 1137 new_name = ldns_dnssec_name_new(); 1138 if (!new_name) { 1139 ldns_rdf_deep_free(l1); 1140 ldns_rdf_deep_free(l2); 1141 ldns_rdf_deep_free(ent_name); 1142 return LDNS_STATUS_MEM_ERR; 1143 } 1144 new_name->name = ent_name; 1145 new_name->name_alloced = true; 1146 new_node = LDNS_MALLOC(ldns_rbnode_t); 1147 if (!new_node) { 1148 ldns_rdf_deep_free(l1); 1149 ldns_rdf_deep_free(l2); 1150 ldns_dnssec_name_free(new_name); 1151 return LDNS_STATUS_MEM_ERR; 1152 } 1153 new_node->key = new_name->name; 1154 new_node->data = new_name; 1155 (void)ldns_rbtree_insert(zone->names, new_node); 1156 ldns_dnssec_name_make_hashed_name( 1157 zone, new_name, NULL); 1158 if (node) 1159 (void) ldns_dnssec_zone_add_rr(zone, 1160 (ldns_rr *)node->data); 1161 } 1162 ldns_rdf_deep_free(l1); 1163 ldns_rdf_deep_free(l2); 1164 } 1165 1166 /* we might have inserted a new node after 1167 * the current one so we can't just use next() 1168 */ 1169 if (next_node != ldns_rbtree_first(zone->names)) { 1170 cur_node = next_node; 1171 } else { 1172 cur_node = LDNS_RBTREE_NULL; 1173 } 1174 } 1175 return LDNS_STATUS_OK; 1176 } 1177 1178 ldns_status 1179 ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone) 1180 { 1181 return ldns_dnssec_zone_add_empty_nonterminals_nsec3(zone, NULL); 1182 } 1183 1184 bool 1185 ldns_dnssec_zone_is_nsec3_optout(const ldns_dnssec_zone* zone) 1186 { 1187 ldns_rr* nsec3; 1188 ldns_rbnode_t* node; 1189 1190 if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) { 1191 node = ldns_rbtree_first(zone->names); 1192 while (node != LDNS_RBTREE_NULL) { 1193 nsec3 = ((ldns_dnssec_name*)node->data)->nsec; 1194 if (nsec3 &&ldns_rr_get_type(nsec3) 1195 == LDNS_RR_TYPE_NSEC3 && 1196 ldns_nsec3_optout(nsec3)) { 1197 return true; 1198 } 1199 node = ldns_rbtree_next(node); 1200 } 1201 } 1202 return false; 1203 } 1204