2 * special zone file structures and functions for better dnssec handling
5 #include <ldns/config.h>
8 #include <ldns/internal.h>
11 ldns_dnssec_rrs_new(void)
13 ldns_dnssec_rrs *new_rrs;
14 new_rrs = LDNS_MALLOC(ldns_dnssec_rrs);
15 if(!new_rrs) return NULL;
22 ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep)
24 ldns_dnssec_rrs *next;
28 ldns_rr_free(rrs->rr);
36 ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs)
38 ldns_dnssec_rrs_free_internal(rrs, 0);
42 ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs)
44 ldns_dnssec_rrs_free_internal(rrs, 1);
48 ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr)
51 ldns_dnssec_rrs *new_rrs;
53 return LDNS_STATUS_ERR;
56 /* this could be done more efficiently; name and type should already
58 cmp = ldns_rr_compare(rrs->rr, rr);
61 return ldns_dnssec_rrs_add_rr(rrs->next, rr);
63 new_rrs = ldns_dnssec_rrs_new();
68 /* put the current old rr in the new next, put the new
69 rr in the current container */
70 new_rrs = ldns_dnssec_rrs_new();
71 new_rrs->rr = rrs->rr;
72 new_rrs->next = rrs->next;
76 /* Silently ignore equal rr's */
77 return LDNS_STATUS_OK;
81 ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt,
82 const ldns_dnssec_rrs *rrs)
85 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
86 fprintf(out, "; <void>");
89 ldns_rr_print_fmt(out, fmt, rrs->rr);
92 ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next);
98 ldns_dnssec_rrs_print(FILE *out, const ldns_dnssec_rrs *rrs)
100 ldns_dnssec_rrs_print_fmt(out, ldns_output_format_default, rrs);
105 ldns_dnssec_rrsets_new(void)
107 ldns_dnssec_rrsets *new_rrsets;
108 new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets);
109 if(!new_rrsets) return NULL;
110 new_rrsets->rrs = NULL;
111 new_rrsets->type = 0;
112 new_rrsets->signatures = NULL;
113 new_rrsets->next = NULL;
118 ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep)
122 ldns_dnssec_rrs_free_internal(rrsets->rrs, deep);
125 ldns_dnssec_rrsets_free_internal(rrsets->next, deep);
127 if (rrsets->signatures) {
128 ldns_dnssec_rrs_free_internal(rrsets->signatures, deep);
135 ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets)
137 ldns_dnssec_rrsets_free_internal(rrsets, 0);
141 ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets)
143 ldns_dnssec_rrsets_free_internal(rrsets, 1);
147 ldns_dnssec_rrsets_type(const ldns_dnssec_rrsets *rrsets)
157 ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets,
162 return LDNS_STATUS_OK;
164 return LDNS_STATUS_ERR;
167 static ldns_dnssec_rrsets *
168 ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr)
170 ldns_dnssec_rrsets *new_rrsets;
171 ldns_rr_type rr_type;
174 new_rrsets = ldns_dnssec_rrsets_new();
175 rr_type = ldns_rr_get_type(rr);
176 if (rr_type == LDNS_RR_TYPE_RRSIG) {
178 rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
183 new_rrsets->rrs = ldns_dnssec_rrs_new();
184 new_rrsets->rrs->rr = rr;
186 new_rrsets->signatures = ldns_dnssec_rrs_new();
187 new_rrsets->signatures->rr = rr;
189 new_rrsets->type = rr_type;
194 ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr)
196 ldns_dnssec_rrsets *new_rrsets;
197 ldns_rr_type rr_type;
199 ldns_status result = LDNS_STATUS_OK;
201 if (!rrsets || !rr) {
202 return LDNS_STATUS_ERR;
205 rr_type = ldns_rr_get_type(rr);
207 if (rr_type == LDNS_RR_TYPE_RRSIG) {
209 rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
212 if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) {
214 rrsets->rrs = ldns_dnssec_rrs_new();
215 rrsets->rrs->rr = rr;
216 rrsets->type = rr_type;
218 rrsets->signatures = ldns_dnssec_rrs_new();
219 rrsets->signatures->rr = rr;
220 rrsets->type = rr_type;
222 return LDNS_STATUS_OK;
225 if (rr_type > ldns_dnssec_rrsets_type(rrsets)) {
227 result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr);
229 new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr);
230 rrsets->next = new_rrsets;
232 } else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) {
233 /* move the current one into the new next,
234 replace field of current with data from new rr */
235 new_rrsets = ldns_dnssec_rrsets_new();
236 new_rrsets->rrs = rrsets->rrs;
237 new_rrsets->type = rrsets->type;
238 new_rrsets->signatures = rrsets->signatures;
239 new_rrsets->next = rrsets->next;
241 rrsets->rrs = ldns_dnssec_rrs_new();
242 rrsets->rrs->rr = rr;
243 rrsets->signatures = NULL;
246 rrsets->signatures = ldns_dnssec_rrs_new();
247 rrsets->signatures->rr = rr;
249 rrsets->type = rr_type;
250 rrsets->next = new_rrsets;
252 /* equal, add to current rrsets */
254 if (rrsets->signatures) {
255 result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr);
257 rrsets->signatures = ldns_dnssec_rrs_new();
258 rrsets->signatures->rr = rr;
262 result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr);
264 rrsets->rrs = ldns_dnssec_rrs_new();
265 rrsets->rrs->rr = rr;
274 ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
275 const ldns_dnssec_rrsets *rrsets,
280 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
281 fprintf(out, "; <void>\n");
285 ldns_rr_get_type(rrsets->rrs->rr) != LDNS_RR_TYPE_SOA
288 ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs);
289 if (rrsets->signatures) {
290 ldns_dnssec_rrs_print_fmt(out, fmt,
294 if (follow && rrsets->next) {
295 ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
296 rrsets->next, follow, show_soa);
303 ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt,
304 const ldns_dnssec_rrsets *rrsets,
307 ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true);
311 ldns_dnssec_rrsets_print(FILE *out, const ldns_dnssec_rrsets *rrsets, bool follow)
313 ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default,
318 ldns_dnssec_name_new(void)
320 ldns_dnssec_name *new_name;
322 new_name = LDNS_CALLOC(ldns_dnssec_name, 1);
327 * not needed anymore because CALLOC initializes everything to zero.
329 new_name->name = NULL;
330 new_name->rrsets = NULL;
331 new_name->name_alloced = false;
332 new_name->nsec = NULL;
333 new_name->nsec_signatures = NULL;
335 new_name->is_glue = false;
336 new_name->hashed_name = NULL;
343 ldns_dnssec_name_new_frm_rr(ldns_rr *rr)
345 ldns_dnssec_name *new_name = ldns_dnssec_name_new();
347 new_name->name = ldns_rr_owner(rr);
348 if(ldns_dnssec_name_add_rr(new_name, rr) != LDNS_STATUS_OK) {
349 ldns_dnssec_name_free(new_name);
357 ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
361 if (name->name_alloced) {
362 ldns_rdf_deep_free(name->name);
365 ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
367 if (name->nsec && deep) {
368 ldns_rr_free(name->nsec);
370 if (name->nsec_signatures) {
371 ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
373 if (name->hashed_name) {
374 /* Hashed name is always allocated when signing,
375 * so always deep free
377 ldns_rdf_deep_free(name->hashed_name);
384 ldns_dnssec_name_free(ldns_dnssec_name *name)
386 ldns_dnssec_name_free_internal(name, 0);
390 ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
392 ldns_dnssec_name_free_internal(name, 1);
396 ldns_dnssec_name_name(const ldns_dnssec_name *name)
405 ldns_dnssec_name_is_glue(const ldns_dnssec_name *name)
408 return name->is_glue;
414 ldns_dnssec_name_set_name(ldns_dnssec_name *rrset,
417 if (rrset && dname) {
424 ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec)
432 ldns_dnssec_name_cmp(const void *a, const void *b)
434 ldns_dnssec_name *na = (ldns_dnssec_name *) a;
435 ldns_dnssec_name *nb = (ldns_dnssec_name *) b;
438 return ldns_dname_compare(ldns_dnssec_name_name(na),
439 ldns_dnssec_name_name(nb));
450 ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
453 ldns_status result = LDNS_STATUS_OK;
454 ldns_rr_type rr_type;
455 ldns_rr_type typecovered = 0;
457 /* special handling for NSEC3 and NSECX covering RRSIGS */
460 return LDNS_STATUS_ERR;
463 rr_type = ldns_rr_get_type(rr);
465 if (rr_type == LDNS_RR_TYPE_RRSIG) {
466 typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
469 if (rr_type == LDNS_RR_TYPE_NSEC ||
470 rr_type == LDNS_RR_TYPE_NSEC3) {
471 /* XX check if is already set (and error?) */
473 } else if (typecovered == LDNS_RR_TYPE_NSEC ||
474 typecovered == LDNS_RR_TYPE_NSEC3) {
475 if (name->nsec_signatures) {
476 result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr);
478 name->nsec_signatures = ldns_dnssec_rrs_new();
479 name->nsec_signatures->rr = rr;
482 /* it's a 'normal' RR, add it to the right rrset */
484 result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
486 name->rrsets = ldns_dnssec_rrsets_new();
487 result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
494 ldns_dnssec_name_find_rrset(const ldns_dnssec_name *name,
496 ldns_dnssec_rrsets *result;
498 result = name->rrsets;
500 if (result->type == type) {
503 result = result->next;
510 ldns_dnssec_zone_find_rrset(const ldns_dnssec_zone *zone,
511 const ldns_rdf *dname,
516 if (!zone || !dname || !zone->names) {
520 node = ldns_rbtree_search(zone->names, dname);
522 return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data,
530 ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
531 const ldns_dnssec_name *name,
536 ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
537 name->rrsets, true, show_soa);
538 } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
539 fprintf(out, ";; Empty nonterminal: ");
540 ldns_rdf_print(out, name->name);
544 ldns_rr_print_fmt(out, fmt, name->nsec);
546 if (name->nsec_signatures) {
547 ldns_dnssec_rrs_print_fmt(out, fmt,
548 name->nsec_signatures);
550 } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
551 fprintf(out, "; <void>\n");
557 ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt,
558 const ldns_dnssec_name *name)
560 ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
564 ldns_dnssec_name_print(FILE *out, const ldns_dnssec_name *name)
566 ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name);
571 ldns_dnssec_zone_new(void)
573 ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone);
574 if(!zone) return NULL;
577 zone->hashed_names = NULL;
578 zone->_nsec3params = NULL;
584 rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
586 return ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
587 && ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t;
590 /* When the zone is first read into an list and then inserted into an
591 * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next)
592 * to each other. Because ldns-verify-zone (the only program that uses this
593 * function) uses the rbtree mostly for sequential walking, this results
594 * in a speed increase (of 15% on linux) because we have less CPU-cache misses.
596 #define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
599 ldns_dnssec_zone_add_empty_nonterminals_nsec3(
600 ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s);
603 ldns_todo_nsec3_ents_node_free(ldns_rbnode_t *node, void *arg) {
605 ldns_rdf_deep_free((ldns_rdf *)node->key);
610 ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* origin,
611 uint32_t default_ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr)
616 ldns_rdf *my_origin = NULL;
617 ldns_rdf *my_prev = NULL;
619 ldns_dnssec_zone *newzone = ldns_dnssec_zone_new();
620 /* NSEC3s may occur before the names they refer to. We must remember
621 them and add them to the name later on, after the name is read.
622 We track not yet matching NSEC3s*n the todo_nsec3s list */
623 ldns_rr_list* todo_nsec3s = ldns_rr_list_new();
624 /* when reading NSEC3s, there is a chance that we encounter nsecs
625 for empty nonterminals, whose nonterminals we cannot derive yet
626 because the needed information is to be read later.
628 nsec3_ents (where ent is e.n.t.; i.e. empty non terminal) will
629 hold the NSEC3s that still didn't have a matching name in the
630 zone tree, even after all names were read. They can only match
631 after the zone is equipped with all the empty non terminals. */
632 ldns_rbtree_t todo_nsec3_ents;
633 ldns_rbnode_t *new_node;
634 ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
638 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
639 ldns_zone* zone = NULL;
641 ldns_rr *prev_rr = NULL;
642 uint32_t my_ttl = default_ttl;
643 /* RFC 1035 Section 5.1, says 'Omitted class and TTL values are default
644 * to the last explicitly stated values.'
646 bool ttl_from_TTL = false;
647 bool explicit_ttl = false;
650 ldns_rbtree_init(&todo_nsec3_ents, ldns_dname_compare_v);
652 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
653 status = ldns_zone_new_frm_fp_l(&zone, fp, origin, default_ttl, c, line_nr);
654 if (status != LDNS_STATUS_OK)
657 if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) {
658 status = LDNS_STATUS_MEM_ERR;
662 if (!(my_origin = ldns_rdf_clone(origin))) {
663 status = LDNS_STATUS_MEM_ERR;
666 if (!(my_prev = ldns_rdf_clone(origin))) {
667 status = LDNS_STATUS_MEM_ERR;
672 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
673 if (ldns_zone_soa(zone)) {
674 status = ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone));
675 if (status != LDNS_STATUS_OK)
678 for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
679 cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
680 status = LDNS_STATUS_OK;
683 /* If ttl came from $TTL line, then it should be the default.
684 * (RFC 2308 Section 4)
685 * Otherwise it "defaults to the last explicitly stated value"
686 * (RFC 1035 Section 5.1)
689 my_ttl = default_ttl;
690 status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin,
691 &my_prev, line_nr, &explicit_ttl);
695 #ifndef FASTER_DNSSEC_ZONE_NEW_FRM_FP
698 /* No $TTL, so ttl "defaults to the
699 * last explicitly stated value"
700 * (RFC 1035 Section 5.1)
702 my_ttl = ldns_rr_ttl(cur_rr);
704 /* When ttl is implicit, try to adhere to the rules as
705 * much as possible. (also for compatibility with bind)
706 * This was changed when fixing an issue with ZONEMD
707 * which hashes the TTL too.
709 } else if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SIG
710 || ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_RRSIG) {
711 if (ldns_rr_rd_count(cur_rr) >= 4
712 && ldns_rdf_get_type(ldns_rr_rdf(cur_rr, 3)) == LDNS_RDF_TYPE_INT32)
714 /* SIG without explicit ttl get ttl
715 * from the original_ttl field
716 * (RFC 2535 Section 7.2)
718 * Similarly for RRSIG, but stated less
719 * specifically in the spec.
720 * (RFC 4034 Section 3)
722 ldns_rr_set_ttl(cur_rr,
723 ldns_rdf2native_int32(
724 ldns_rr_rdf(rr, 3)));
727 && ldns_rr_get_type(prev_rr) == ldns_rr_get_type(cur_rr)
728 && ldns_dname_compare( ldns_rr_owner(prev_rr)
729 , ldns_rr_owner(cur_rr)) == 0)
731 /* "TTLs of all RRs in an RRSet must be the same"
732 * (RFC 2881 Section 5.2)
734 ldns_rr_set_ttl(cur_rr, ldns_rr_ttl(prev_rr));
738 status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
740 LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
742 if (rr_is_rrsig_covering(cur_rr,
743 LDNS_RR_TYPE_NSEC3)){
744 ldns_rr_list_push_rr(todo_nsec3_rrsigs,
747 ldns_rr_list_push_rr(todo_nsec3s,
750 status = LDNS_STATUS_OK;
752 } else if (status != LDNS_STATUS_OK)
757 case LDNS_STATUS_SYNTAX_TTL: /* the ttl was set*/
758 #ifndef FASTER_DNSSEC_ZONE_NEW_FRM_FP
759 default_ttl = my_ttl;
762 status = LDNS_STATUS_OK;
766 case LDNS_STATUS_SYNTAX_EMPTY: /* empty line was seen */
767 case LDNS_STATUS_SYNTAX_ORIGIN: /* the origin was set*/
768 status = LDNS_STATUS_OK;
771 case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
772 status = LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
780 for (i = 0; status == LDNS_STATUS_OK &&
781 i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
782 cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
783 status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
784 if (status == LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
785 if (!(new_node = LDNS_MALLOC(ldns_rbnode_t))) {
786 status = LDNS_STATUS_MEM_ERR;
789 new_node->key = ldns_dname_label(ldns_rr_owner(cur_rr), 0);
790 new_node->data = cur_rr;
791 if (!ldns_rbtree_insert(&todo_nsec3_ents, new_node)) {
793 status = LDNS_STATUS_MEM_ERR;
796 status = LDNS_STATUS_OK;
799 if (todo_nsec3_ents.count > 0)
800 (void) ldns_dnssec_zone_add_empty_nonterminals_nsec3(
801 newzone, &todo_nsec3_ents);
802 for (i = 0; status == LDNS_STATUS_OK &&
803 i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++) {
804 cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
805 status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
811 ldns_dnssec_zone_free(newzone);
816 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
818 ldns_zone_free(zone);
821 ldns_rr_list_free(todo_nsec3_rrsigs);
822 ldns_traverse_postorder(&todo_nsec3_ents,
823 ldns_todo_nsec3_ents_node_free, NULL);
824 ldns_rr_list_free(todo_nsec3s);
827 ldns_rdf_deep_free(my_origin);
830 ldns_rdf_deep_free(my_prev);
833 ldns_dnssec_zone_free(newzone);
839 ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* origin,
840 uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
842 return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
846 ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
848 ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
853 ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
855 ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data);
860 ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) {
866 ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
869 if (zone->hashed_names) {
870 ldns_traverse_postorder(zone->hashed_names,
871 ldns_hashed_names_node_free, NULL);
872 LDNS_FREE(zone->hashed_names);
875 /* destroy all name structures within the tree */
876 ldns_traverse_postorder(zone->names,
877 ldns_dnssec_name_node_free,
879 LDNS_FREE(zone->names);
886 ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
889 if (zone->hashed_names) {
890 ldns_traverse_postorder(zone->hashed_names,
891 ldns_hashed_names_node_free, NULL);
892 LDNS_FREE(zone->hashed_names);
895 /* destroy all name structures within the tree */
896 ldns_traverse_postorder(zone->names,
897 ldns_dnssec_name_node_deep_free,
899 LDNS_FREE(zone->names);
905 /* use for dname comparison in tree */
907 ldns_dname_compare_v(const void *a, const void *b) {
908 return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
912 ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
913 ldns_dnssec_name* name, ldns_rr* nsec3rr);
916 ldns_dnssec_zone_hashed_names_from_nsec3(
917 ldns_dnssec_zone* zone, ldns_rr* nsec3rr)
919 ldns_rbnode_t* current_node;
920 ldns_dnssec_name* current_name;
922 assert(zone != NULL);
923 assert(nsec3rr != NULL);
925 if (zone->hashed_names) {
926 ldns_traverse_postorder(zone->hashed_names,
927 ldns_hashed_names_node_free, NULL);
928 LDNS_FREE(zone->hashed_names);
930 zone->_nsec3params = nsec3rr;
932 /* So this is a NSEC3 zone.
933 * Calculate hashes for all names already in the zone
935 zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v);
936 if (zone->hashed_names == NULL) {
939 for ( current_node = ldns_rbtree_first(zone->names)
940 ; current_node != LDNS_RBTREE_NULL
941 ; current_node = ldns_rbtree_next(current_node)
943 current_name = (ldns_dnssec_name *) current_node->data;
944 ldns_dnssec_name_make_hashed_name(zone, current_name, nsec3rr);
950 ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
951 ldns_dnssec_name* name, ldns_rr* nsec3rr)
953 ldns_rbnode_t* new_node;
955 assert(name != NULL);
956 if (! zone->_nsec3params) {
960 ldns_dnssec_zone_hashed_names_from_nsec3(zone, nsec3rr);
962 } else if (! nsec3rr) {
963 nsec3rr = zone->_nsec3params;
965 name->hashed_name = ldns_nsec3_hash_name_frm_nsec3(nsec3rr, name->name);
967 /* Also store in zone->hashed_names */
968 if ((new_node = LDNS_MALLOC(ldns_rbnode_t))) {
970 new_node->key = name->hashed_name;
971 new_node->data = name;
973 if (ldns_rbtree_insert(zone->hashed_names, new_node) == NULL) {
981 static ldns_rbnode_t *
982 ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, ldns_rr *rr) {
983 ldns_rdf *hashed_name;
984 ldns_rbnode_t *to_return;
986 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 && ! zone->_nsec3params){
988 ldns_dnssec_zone_hashed_names_from_nsec3(zone, rr);
990 if (zone->hashed_names == NULL) {
993 hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
994 if (hashed_name == NULL) {
997 to_return = ldns_rbtree_search(zone->hashed_names, hashed_name);
998 ldns_rdf_deep_free(hashed_name);
1003 ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
1005 ldns_status result = LDNS_STATUS_OK;
1006 ldns_dnssec_name *cur_name;
1007 ldns_rbnode_t *cur_node;
1008 ldns_rr_type type_covered = 0;
1011 return LDNS_STATUS_ERR;
1015 zone->names = ldns_rbtree_create(ldns_dname_compare_v);
1016 if(!zone->names) return LDNS_STATUS_MEM_ERR;
1019 /* we need the original of the hashed name if this is
1020 an NSEC3, or an RRSIG that covers an NSEC3 */
1021 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) {
1022 type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
1024 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 ||
1025 type_covered == LDNS_RR_TYPE_NSEC3) {
1026 cur_node = ldns_dnssec_zone_find_nsec3_original(zone, rr);
1028 return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND;
1031 cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
1035 cur_name = ldns_dnssec_name_new_frm_rr(rr);
1036 if(!cur_name) return LDNS_STATUS_MEM_ERR;
1037 cur_node = LDNS_MALLOC(ldns_rbnode_t);
1039 ldns_dnssec_name_free(cur_name);
1040 return LDNS_STATUS_MEM_ERR;
1042 cur_node->key = ldns_rr_owner(rr);
1043 cur_node->data = cur_name;
1044 (void)ldns_rbtree_insert(zone->names, cur_node);
1045 ldns_dnssec_name_make_hashed_name(zone, cur_name, NULL);
1047 cur_name = (ldns_dnssec_name *) cur_node->data;
1048 result = ldns_dnssec_name_add_rr(cur_name, rr);
1050 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
1051 zone->soa = cur_name;
1057 ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
1058 const ldns_rbtree_t *tree,
1061 ldns_rbnode_t *node;
1062 ldns_dnssec_name *name;
1064 node = ldns_rbtree_first(tree);
1065 while (node != LDNS_RBTREE_NULL) {
1066 name = (ldns_dnssec_name *) node->data;
1067 ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa);
1068 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
1069 fprintf(out, ";\n");
1070 node = ldns_rbtree_next(node);
1075 ldns_dnssec_zone_names_print(FILE *out, const ldns_rbtree_t *tree, bool print_soa)
1077 ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default,
1082 ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt,
1083 const ldns_dnssec_zone *zone)
1087 if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
1088 fprintf(out, ";; Zone: ");
1089 ldns_rdf_print(out, ldns_dnssec_name_name(
1091 fprintf(out, "\n;\n");
1093 ldns_dnssec_rrsets_print_fmt(out, fmt,
1094 ldns_dnssec_name_find_rrset(
1098 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
1099 fprintf(out, ";\n");
1103 ldns_dnssec_zone_names_print_fmt(out, fmt,
1104 zone->names, false);
1110 ldns_dnssec_zone_print(FILE *out, const ldns_dnssec_zone *zone)
1112 ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone);
1116 ldns_dnssec_zone_add_empty_nonterminals_nsec3(
1117 ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s)
1119 ldns_dnssec_name *new_name;
1121 ldns_rdf *next_name;
1122 ldns_rbnode_t *cur_node, *next_node, *new_node;
1124 /* for the detection */
1125 uint16_t i, cur_label_count, next_label_count;
1126 uint16_t soa_label_count = 0;
1131 return LDNS_STATUS_ERR;
1133 if (zone->soa && zone->soa->name) {
1134 soa_label_count = ldns_dname_label_count(zone->soa->name);
1137 cur_node = ldns_rbtree_first(zone->names);
1138 while (cur_node != LDNS_RBTREE_NULL) {
1139 next_node = ldns_rbtree_next(cur_node);
1142 while (next_node != LDNS_RBTREE_NULL &&
1144 ((ldns_dnssec_name *)next_node->data)->is_glue
1146 next_node = ldns_rbtree_next(next_node);
1149 if (next_node == LDNS_RBTREE_NULL) {
1150 next_node = ldns_rbtree_first(zone->names);
1152 if (! cur_node->data || ! next_node->data) {
1153 return LDNS_STATUS_ERR;
1155 cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
1156 next_name = ((ldns_dnssec_name *)next_node->data)->name;
1157 cur_label_count = ldns_dname_label_count(cur_name);
1158 next_label_count = ldns_dname_label_count(next_name);
1160 /* Since the names are in canonical order, we can
1161 * recognize empty non-terminals by their labels;
1162 * every label after the first one on the next owner
1163 * name is a non-terminal if it either does not exist
1164 * in the current name or is different from the same
1165 * label in the current name (counting from the end)
1167 for (i = 1; i < next_label_count - soa_label_count; i++) {
1168 lpos = (int)cur_label_count - (int)next_label_count + (int)i;
1170 l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
1174 l2 = ldns_dname_clone_from(next_name, i);
1176 if (!l1 || ldns_dname_compare(l1, l2) != 0) {
1177 /* We have an empty nonterminal, add it to the
1180 ldns_rbnode_t *node = NULL;
1183 if (!(ent_name = ldns_dname_clone_from(
1186 ldns_rdf_deep_free(l1);
1187 ldns_rdf_deep_free(l2);
1188 return LDNS_STATUS_MEM_ERR;
1191 if (nsec3s && zone->_nsec3params) {
1192 ldns_rdf *ent_hashed_name;
1194 if (!(ent_hashed_name =
1195 ldns_nsec3_hash_name_frm_nsec3(
1198 ldns_rdf_deep_free(l1);
1199 ldns_rdf_deep_free(l2);
1200 ldns_rdf_deep_free(ent_name);
1201 return LDNS_STATUS_MEM_ERR;
1203 node = ldns_rbtree_search(nsec3s,
1205 ldns_rdf_deep_free(ent_hashed_name);
1207 ldns_rdf_deep_free(l1);
1208 ldns_rdf_deep_free(l2);
1209 ldns_rdf_deep_free(ent_name);
1213 new_name = ldns_dnssec_name_new();
1215 ldns_rdf_deep_free(l1);
1216 ldns_rdf_deep_free(l2);
1217 ldns_rdf_deep_free(ent_name);
1218 return LDNS_STATUS_MEM_ERR;
1220 new_name->name = ent_name;
1221 new_name->name_alloced = true;
1222 new_node = LDNS_MALLOC(ldns_rbnode_t);
1224 ldns_rdf_deep_free(l1);
1225 ldns_rdf_deep_free(l2);
1226 ldns_dnssec_name_free(new_name);
1227 return LDNS_STATUS_MEM_ERR;
1229 new_node->key = new_name->name;
1230 new_node->data = new_name;
1231 (void)ldns_rbtree_insert(zone->names, new_node);
1232 ldns_dnssec_name_make_hashed_name(
1233 zone, new_name, NULL);
1235 (void) ldns_dnssec_zone_add_rr(zone,
1236 (ldns_rr *)node->data);
1238 ldns_rdf_deep_free(l1);
1239 ldns_rdf_deep_free(l2);
1242 /* we might have inserted a new node after
1243 * the current one so we can't just use next()
1245 if (next_node != ldns_rbtree_first(zone->names)) {
1246 cur_node = next_node;
1248 cur_node = LDNS_RBTREE_NULL;
1251 return LDNS_STATUS_OK;
1255 ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
1257 return ldns_dnssec_zone_add_empty_nonterminals_nsec3(zone, NULL);
1261 ldns_dnssec_zone_is_nsec3_optout(const ldns_dnssec_zone* zone)
1264 ldns_rbnode_t* node;
1266 if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) {
1267 node = ldns_rbtree_first(zone->names);
1268 while (node != LDNS_RBTREE_NULL) {
1269 nsec3 = ((ldns_dnssec_name*)node->data)->nsec;
1270 if (nsec3 &&ldns_rr_get_type(nsec3)
1271 == LDNS_RR_TYPE_NSEC3 &&
1272 ldns_nsec3_optout(nsec3)) {
1275 node = ldns_rbtree_next(node);
1282 * Stuff for calculating and verifying zone digests
1284 typedef enum dnssec_zone_rr_iter_state {
1285 DNSSEC_ZONE_RR_ITER_LT_RRSIG
1286 , DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1287 , DNSSEC_ZONE_RR_ITER_REST
1288 , DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC
1289 , DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC_REST
1290 , DNSSEC_ZONE_RR_ITER_NSEC3
1291 , DNSSEC_ZONE_RR_ITER_FINI
1292 } dnssec_zone_rr_iter_state;
1294 typedef struct dnssec_zone_rr_iter {
1295 ldns_dnssec_zone *zone;
1296 ldns_rbnode_t *node;
1297 ldns_dnssec_name *name;
1298 ldns_dnssec_rrsets *rrsets;
1299 ldns_dnssec_rrs *rrs;
1300 ldns_dnssec_rrsets *rrsets4rrsigs;
1301 ldns_rbnode_t *nsec3_node;
1302 ldns_dnssec_name *nsec3_name;
1303 dnssec_zone_rr_iter_state state;
1304 ldns_rdf *apex_name;
1306 } dnssec_zone_rr_iter;
1309 dnssec_zone_rr_iter_set_state_for_next_name(dnssec_zone_rr_iter *i)
1311 /* Make sure the i->name is "in zone" (i.e. below the apex) */
1313 ldns_rdf *name = (ldns_rdf *)i->node->key;
1315 while (i->name && name != i->apex_name /* not apex */
1317 && ( ldns_dname_label_count(name) != i->apex_labs
1318 || ldns_dname_compare(name, i->apex_name)) /* not apex */
1320 && !ldns_dname_is_subdomain(name, i->apex_name) /* no sub */) {
1323 i->node = ldns_rbtree_next(i->node);
1324 if (i->node == LDNS_RBTREE_NULL)
1327 i->name = (ldns_dnssec_name *)i->node->data;
1328 name = (ldns_rdf *)i->node->key;
1332 /* determine state */
1335 i->state = DNSSEC_ZONE_RR_ITER_FINI;
1337 i->rrs = i->nsec3_name->nsec_signatures;
1338 i->state = DNSSEC_ZONE_RR_ITER_NSEC3;
1340 } else if (!i->nsec3_name) {
1341 i->rrsets = i->name->rrsets;
1342 i->state = DNSSEC_ZONE_RR_ITER_LT_RRSIG;
1344 } else if (ldns_dname_compare( ldns_rr_owner(i->nsec3_name->nsec)
1345 , (ldns_rdf *)i->node->key) < 0) {
1346 i->rrs = i->nsec3_name->nsec_signatures;
1347 i->state = DNSSEC_ZONE_RR_ITER_NSEC3;
1349 i->rrsets = i->name->rrsets;
1350 i->state = DNSSEC_ZONE_RR_ITER_LT_RRSIG;
1355 * Iterate over the RR's in the ldns_dnssec_zone in canonical order.
1356 * There are three possible paths through the RR's in a ldns_dnssec_name.
1358 * 1. There is no NSEC:
1360 * 1.1. All the RRs in the name->rrsets with type < RRSIG,
1361 * state: DNSSEC_ZONE_RR_ITER_LT_RRSIG
1363 * 1.2. Then all the RRSIGs from name->rrsets (likely none)
1364 * state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1366 * 1.3. Finally the remaining RRs in name->rrsets (type > RRSIG)
1367 * state: DNSSEC_ZONE_RR_ITER_REST
1370 * 2. There is a NSEC of type NSEC with this name:
1372 * 2.1. All the RRs in the name->rrsets with type < RRSIG,
1373 * state: DNSSEC_ZONE_RR_ITER_LT_RRSIG
1375 * 2.2. Then all the RRSIGs from name->rrsets with type < NSEC
1376 * state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1378 * 2.3. Then the signatures of the NSEC RR, followed by
1379 * the signatures of the remaining name->rrsets (type > NSEC),
1380 * followed by the NSEC rr.
1381 * state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1383 * 2.4. Finally the remaining RRs in name->rrsets (type > RRSIG)
1384 * state: DNSSEC_ZONE_RR_ITER_REST
1387 * 3. There is a NSEC of type NSEC3 for this name:
1389 * 3.1. If the NSEC3 name is before the name for other RRsets in the zone,
1390 * Then all signatures of the NSEC3 RR, followed by the NSEC3
1391 * state: DNSSEC_ZONE_RR_ITER_NSEC3
1393 * otherwise follow path for "no NSEC" for the name for other RRsets
1396 dnssec_zone_rr_iter_next(dnssec_zone_rr_iter *i)
1402 ldns_rr *rr = i->rrs->rr;
1403 i->rrs = i->rrs->next;
1407 case DNSSEC_ZONE_RR_ITER_LT_RRSIG:
1409 && i->rrsets->type < LDNS_RR_TYPE_RRSIG) {
1411 i->rrs = i->rrsets->rrs;
1412 i->rrsets = i->rrsets->next;
1415 i->rrsets4rrsigs = i->name->rrsets;
1416 if (i->name->nsec && ldns_rr_get_type(i->name->nsec)
1417 == LDNS_RR_TYPE_NSEC) {
1419 i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC;
1422 i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC;
1425 case DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC:
1426 if (i->rrsets4rrsigs) {
1427 i->rrs = i->rrsets4rrsigs->signatures;
1428 i->rrsets4rrsigs = i->rrsets4rrsigs->next;
1431 i->state = DNSSEC_ZONE_RR_ITER_REST;
1434 case DNSSEC_ZONE_RR_ITER_REST:
1436 i->rrs = i->rrsets->rrs;
1437 i->rrsets = i->rrsets->next;
1441 i->node = ldns_rbtree_next(i->node);
1442 i->name = i->node == LDNS_RBTREE_NULL ? NULL
1443 : (ldns_dnssec_name *)i->node->data;
1445 dnssec_zone_rr_iter_set_state_for_next_name(i);
1448 case DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC:
1449 if (i->rrsets4rrsigs
1450 && i->rrsets4rrsigs->type < LDNS_RR_TYPE_NSEC) {
1452 i->rrs = i->rrsets4rrsigs->signatures;
1453 i->rrsets4rrsigs = i->rrsets4rrsigs->next;
1456 i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC_REST;
1457 i->rrs = i->name->nsec_signatures;
1460 case DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC_REST:
1461 if (i->rrsets4rrsigs) {
1462 i->rrs = i->rrsets4rrsigs->signatures;
1463 i->rrsets4rrsigs = i->rrsets4rrsigs->next;
1466 i->state = DNSSEC_ZONE_RR_ITER_REST;
1467 return i->name->nsec;
1469 case DNSSEC_ZONE_RR_ITER_NSEC3:
1470 nsec3 = i->nsec3_name->nsec;
1475 = ldns_rbtree_next(i->nsec3_node);
1477 = i->nsec3_node == LDNS_RBTREE_NULL ? NULL
1478 : (ldns_dnssec_name*)i->nsec3_node->data;
1480 /* names for glue can be in the hashed_names
1481 * tree, but will not have a NSEC3
1483 } while (i->nsec3_name && !i->nsec3_name->nsec);
1485 dnssec_zone_rr_iter_set_state_for_next_name(i);
1488 case DNSSEC_ZONE_RR_ITER_FINI:
1495 dnssec_zone_rr_iter_first(dnssec_zone_rr_iter *i, ldns_dnssec_zone *zone)
1500 memset(i, 0, sizeof(*i));
1502 if (zone->soa && zone->soa->name) {
1503 i->apex_name = zone->soa->name;
1504 i->apex_labs = ldns_dname_label_count(i->apex_name);
1506 i->apex_name = NULL;
1509 i->node = ldns_rbtree_first(zone->names);
1510 i->name = i->node == LDNS_RBTREE_NULL ? NULL
1511 : (ldns_dnssec_name *)i->node->data;
1513 if (zone->hashed_names) {
1515 i->nsec3_node = ldns_rbtree_first(zone->hashed_names);
1516 i->nsec3_name = i->nsec3_node == LDNS_RBTREE_NULL ?NULL
1517 : (ldns_dnssec_name*)i->nsec3_node->data;
1518 } while (i->nsec3_name && !i->nsec3_name->nsec);
1520 dnssec_zone_rr_iter_set_state_for_next_name(i);
1521 return dnssec_zone_rr_iter_next(i);
1524 enum enum_zonemd_scheme {
1525 ZONEMD_SCHEME_FIRST = 1,
1526 ZONEMD_SCHEME_SIMPLE = 1,
1527 ZONEMD_SCHEME_LAST = 1
1529 typedef enum enum_zonemd_scheme zonemd_scheme;
1531 enum enum_zonemd_hash {
1532 ZONEMD_HASH_FIRST = 1,
1533 ZONEMD_HASH_SHA384 = 1,
1534 ZONEMD_HASH_SHA512 = 2,
1535 ZONEMD_HASH_LAST = 2
1537 typedef enum enum_zonemd_hash zonemd_hash;
1539 struct struct_zone_digester {
1540 ldns_sha384_CTX sha384_CTX;
1541 ldns_sha512_CTX sha512_CTX;
1542 unsigned simple_sha384 : 1;
1543 unsigned simple_sha512 : 1;
1544 unsigned double_sha384 : 1;
1545 unsigned double_sha512 : 1;
1547 typedef struct struct_zone_digester zone_digester;
1549 INLINE bool zone_digester_set(zone_digester *zd)
1550 { return zd && (zd->simple_sha384 || zd->simple_sha512); }
1552 INLINE void zone_digester_init(zone_digester *zd)
1553 { memset(zd, 0, sizeof(*zd)); }
1556 zone_digester_add(zone_digester *zd, zonemd_scheme scheme, zonemd_hash hash)
1559 return LDNS_STATUS_NULL;
1562 case ZONEMD_SCHEME_SIMPLE:
1564 case ZONEMD_HASH_SHA384:
1565 if (zd->double_sha384)
1566 return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1568 else if (zd->simple_sha384) {
1569 zd->simple_sha384 = 0;
1570 zd->double_sha384 = 1;
1571 return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1573 ldns_sha384_init(&zd->sha384_CTX);
1574 zd->simple_sha384 = 1;
1577 case ZONEMD_HASH_SHA512:
1578 if (zd->double_sha512)
1579 return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1581 else if (zd->simple_sha512) {
1582 zd->simple_sha512 = 0;
1583 zd->double_sha512 = 1;
1584 return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1586 ldns_sha512_init(&zd->sha512_CTX);
1587 zd->simple_sha512 = 1;
1590 return LDNS_STATUS_ZONEMD_UNKNOWN_HASH;
1594 return LDNS_STATUS_ZONEMD_UNKNOWN_SCHEME;
1596 return LDNS_STATUS_OK;
1600 zone_digester_update(zone_digester *zd, ldns_rr *rr)
1602 uint8_t data[65536];
1608 buf._limit = sizeof(data);
1609 buf._capacity = sizeof(data);
1611 buf._status = LDNS_STATUS_OK;
1613 if ((st = ldns_rr2buffer_wire_canonical(&buf, rr, LDNS_SECTION_ANSWER)))
1616 if (zd->simple_sha384)
1617 ldns_sha384_update(&zd->sha384_CTX, data, buf._position);
1619 if (zd->simple_sha512)
1620 ldns_sha512_update(&zd->sha512_CTX, data, buf._position);
1622 return LDNS_STATUS_OK;
1626 new_zonemd(ldns_rr *soa, zonemd_hash hash)
1629 uint8_t *data = NULL;
1631 size_t md_len = hash == ZONEMD_HASH_SHA384
1632 ? LDNS_SHA384_DIGEST_LENGTH
1633 : LDNS_SHA512_DIGEST_LENGTH;
1635 if (!(rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_ZONEMD)))
1638 if (!(rdf = ldns_rdf_clone(ldns_rr_owner(soa))))
1641 ldns_rr_set_owner(rr, rdf);
1642 ldns_rr_set_class(rr, ldns_rr_get_class(soa));
1643 ldns_rr_set_ttl(rr, ldns_rr_ttl(soa));
1645 if (!(rdf = ldns_rdf_clone(ldns_rr_rdf(soa, 2))))
1647 ldns_rr_set_rdf(rr, rdf, 0);
1649 if (!(rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, 1)))
1651 ldns_rr_set_rdf(rr, rdf, 1);
1653 if (!(rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, hash)))
1655 ldns_rr_set_rdf(rr, rdf, 2);
1657 if (!(data = LDNS_XMALLOC(uint8_t, md_len)))
1660 if (!(rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, md_len, data)))
1662 ldns_rr_set_rdf(rr, rdf, 3);
1672 static ldns_rr_list *
1673 zone_digester_export(
1674 zone_digester *zd, ldns_rr *soa, ldns_status *ret_st)
1676 ldns_status st = LDNS_STATUS_OK;
1677 ldns_rr_list *rr_list = NULL;
1678 ldns_rr *sha384 = NULL;
1679 ldns_rr *sha512 = NULL;
1682 st = LDNS_STATUS_NULL;
1684 else if (ldns_rr_get_type(soa) != LDNS_RR_TYPE_SOA
1685 || ldns_rr_rd_count(soa) < 3)
1686 st = LDNS_STATUS_ZONEMD_INVALID_SOA;
1688 else if (!(rr_list = ldns_rr_list_new()))
1689 st = LDNS_STATUS_MEM_ERR;
1691 else if (zd->simple_sha384
1692 && !(sha384 = new_zonemd(soa, ZONEMD_HASH_SHA384)))
1693 st = LDNS_STATUS_MEM_ERR;
1695 else if (zd->simple_sha512
1696 && !(sha512 = new_zonemd(soa, ZONEMD_HASH_SHA512)))
1697 st = LDNS_STATUS_MEM_ERR;
1699 else if (zd->simple_sha384
1700 && !ldns_rr_list_push_rr(rr_list, sha384))
1701 st = LDNS_STATUS_MEM_ERR;
1703 else if (zd->simple_sha512
1704 && !ldns_rr_list_push_rr(rr_list, sha512)) {
1705 if (zd->simple_sha384)
1706 sha384 = NULL; /* deleted by ldns_rr_list_deep_free */
1707 st = LDNS_STATUS_MEM_ERR;
1711 ldns_sha384_final( ldns_rdf_data(ldns_rr_rdf(sha384,3))
1714 ldns_sha512_final( ldns_rdf_data(ldns_rr_rdf(sha512,3))
1721 ldns_rr_free(sha384);
1723 ldns_rr_free(sha512);
1725 ldns_rr_list_deep_free(rr_list);
1730 ldns_digest_zone(ldns_dnssec_zone *zone, zone_digester *zd)
1732 ldns_status st = LDNS_STATUS_OK;
1733 dnssec_zone_rr_iter rr_iter;
1735 ldns_rdf *apex_name; /* name of zone apex */
1737 if (!zone || !zd || !zone->soa || !zone->soa->name)
1738 return LDNS_STATUS_NULL;
1740 apex_name = zone->soa->name;
1741 for ( rr = dnssec_zone_rr_iter_first(&rr_iter, zone)
1743 ; rr = dnssec_zone_rr_iter_next(&rr_iter)) {
1744 /* Skip apex ZONEMD RRs */
1745 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_ZONEMD
1746 && !ldns_dname_compare(ldns_rr_owner(rr), apex_name))
1748 /* Skip RRSIGs for apex ZONEMD RRs */
1749 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
1750 && LDNS_RR_TYPE_ZONEMD == ldns_rdf2rr_type(
1751 ldns_rr_rrsig_typecovered(rr))
1752 && !ldns_dname_compare(ldns_rr_owner(rr), apex_name))
1754 st = zone_digester_update(zd, rr);
1760 ldns_dnssec_zone_verify_zonemd(ldns_dnssec_zone *zone)
1762 ldns_dnssec_rrsets *zonemd, *soa;
1764 ldns_dnssec_rrs *rrs;
1767 uint8_t simple_sha384[LDNS_SHA384_DIGEST_LENGTH];
1768 uint8_t simple_sha512[LDNS_SHA512_DIGEST_LENGTH];
1769 size_t valid_zonemds;
1772 return LDNS_STATUS_NULL;
1774 zonemd = ldns_dnssec_zone_find_rrset(
1775 zone, zone->soa->name, LDNS_RR_TYPE_ZONEMD);
1777 ldns_rbnode_t *nsec3_node;
1779 /* we need proof of non-existence for ZONEMD at the apex */
1780 if (zone->soa->nsec) {
1781 if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(
1783 LDNS_RR_TYPE_ZONEMD))
1784 return LDNS_STATUS_NO_ZONEMD;
1786 } else if (!zone->soa->hashed_name || !zone->hashed_names)
1787 return LDNS_STATUS_NO_ZONEMD;
1789 else if (LDNS_RBTREE_NULL ==
1790 (nsec3_node = ldns_rbtree_search( zone->hashed_names
1791 , zone->soa->hashed_name)))
1792 return LDNS_STATUS_NO_ZONEMD;
1794 ldns_dnssec_name *nsec3
1795 = (ldns_dnssec_name *)nsec3_node->data;
1796 if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(
1798 LDNS_RR_TYPE_ZONEMD))
1799 return LDNS_STATUS_NO_ZONEMD;
1801 /* ZONEMD at apex does really not exist */
1802 return LDNS_STATUS_OK;
1804 soa = ldns_dnssec_zone_find_rrset(
1805 zone, zone->soa->name, LDNS_RR_TYPE_SOA);
1806 if (!soa || !soa->rrs || !soa->rrs->rr)
1807 return LDNS_STATUS_ZONEMD_INVALID_SOA;
1809 soa_rr = soa->rrs->rr;
1810 if (ldns_rr_get_type(soa_rr) != LDNS_RR_TYPE_SOA
1811 || ldns_rr_rd_count(soa_rr) < 3)
1812 return LDNS_STATUS_ZONEMD_INVALID_SOA;
1814 zone_digester_init(&zd);
1815 for (rrs = zonemd->rrs; rrs; rrs = rrs->next) {
1817 || ldns_rr_get_type(rrs->rr) != LDNS_RR_TYPE_ZONEMD
1818 || ldns_rr_rd_count(rrs->rr) < 4)
1821 /* serial should match SOA's serial */
1822 if (ldns_rdf2native_int32(ldns_rr_rdf(soa_rr, 2))
1823 != ldns_rdf2native_int32(ldns_rr_rdf(rrs->rr, 0)))
1826 /* Add (scheme, hash) to digester */
1827 zone_digester_add(&zd,
1828 ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr, 1)),
1829 ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr, 2)));
1831 if (!zone_digester_set(&zd))
1832 return LDNS_STATUS_NO_VALID_ZONEMD;
1834 if ((st = ldns_digest_zone(zone, &zd)))
1837 if (zd.simple_sha384)
1838 ldns_sha384_final(simple_sha384, &zd.sha384_CTX);
1839 if (zd.simple_sha512)
1840 ldns_sha512_final(simple_sha512, &zd.sha512_CTX);
1843 for (rrs = zonemd->rrs; rrs; rrs = rrs->next) {
1845 || ldns_rr_get_type(rrs->rr) != LDNS_RR_TYPE_ZONEMD
1846 || ldns_rr_rd_count(rrs->rr) < 4)
1849 /* serial should match SOA's serial */
1850 if (ldns_rdf2native_int32(ldns_rr_rdf(soa_rr, 2))
1851 != ldns_rdf2native_int32(ldns_rr_rdf(rrs->rr, 0)))
1854 if (ZONEMD_SCHEME_SIMPLE !=
1855 ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr, 1)))
1858 if (ZONEMD_HASH_SHA384
1859 == ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr,2))
1860 && LDNS_SHA384_DIGEST_LENGTH
1861 == ldns_rdf_size(ldns_rr_rdf(rrs->rr, 3))
1862 && memcmp( simple_sha384
1863 , ldns_rdf_data(ldns_rr_rdf(rrs->rr, 3))
1864 , LDNS_SHA384_DIGEST_LENGTH) == 0)
1868 if (ZONEMD_HASH_SHA512
1869 == ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr,2))
1870 && LDNS_SHA512_DIGEST_LENGTH
1871 == ldns_rdf_size(ldns_rr_rdf(rrs->rr, 3))
1872 && memcmp( simple_sha512
1873 , ldns_rdf_data(ldns_rr_rdf(rrs->rr, 3))
1874 , LDNS_SHA512_DIGEST_LENGTH) == 0)
1878 return valid_zonemds ? LDNS_STATUS_OK : LDNS_STATUS_NO_VALID_ZONEMD;
1883 rr_list2dnssec_rrs(ldns_rr_list *rr_list, ldns_dnssec_rrs **rrs,
1884 ldns_rr_list *new_rrs)
1888 if (!rr_list || !rrs)
1889 return LDNS_STATUS_NULL;
1891 if (ldns_rr_list_rr_count(rr_list) == 0)
1892 return LDNS_STATUS_OK;
1895 if (!(*rrs = ldns_dnssec_rrs_new()))
1896 return LDNS_STATUS_MEM_ERR;
1897 (*rrs)->rr = ldns_rr_list_pop_rr(rr_list);
1899 ldns_rr_list_push_rr(new_rrs, (*rrs)->rr);
1901 while ((rr = ldns_rr_list_pop_rr(rr_list))) {
1904 if ((st = ldns_dnssec_rrs_add_rr(*rrs, rr))) {
1905 ldns_rr_list_push_rr(rr_list, rr);
1908 ldns_rr_list_push_rr(new_rrs, rr);
1910 return LDNS_STATUS_OK;
1915 dnssec_zone_equip_zonemd(ldns_dnssec_zone *zone,
1916 ldns_rr_list *new_rrs, ldns_key_list *key_list, int signflags)
1918 ldns_status st = LDNS_STATUS_OK;
1920 ldns_rr_list *zonemd_rr_list = NULL;
1921 ldns_rr_list *zonemd_rrsigs = NULL;
1922 ldns_dnssec_rrsets *soa_rrset;
1923 ldns_rr *soa_rr = NULL;
1924 ldns_dnssec_rrsets **rrset_ref;
1925 ldns_dnssec_rrsets *zonemd_rrset;
1927 zone_digester_init(&zd);
1928 if (signflags & LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA384)
1929 zone_digester_add(&zd, ZONEMD_SCHEME_SIMPLE
1930 , ZONEMD_HASH_SHA384);
1932 if (signflags & LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA512)
1933 zone_digester_add(&zd, ZONEMD_SCHEME_SIMPLE
1934 , ZONEMD_HASH_SHA512);
1936 if ((st = ldns_digest_zone(zone, &zd)))
1939 soa_rrset = ldns_dnssec_zone_find_rrset(
1940 zone, zone->soa->name, LDNS_RR_TYPE_SOA);
1941 if (!soa_rrset || !soa_rrset->rrs || !soa_rrset->rrs->rr)
1942 return LDNS_STATUS_ZONEMD_INVALID_SOA;
1943 soa_rr = soa_rrset->rrs->rr;
1945 if (!(zonemd_rr_list = zone_digester_export(&zd, soa_rr, &st)))
1948 /* - replace or add ZONEMD rrset */
1949 rrset_ref = &zone->soa->rrsets; /* scan rrsets at apex */
1950 while (*rrset_ref && (*rrset_ref)->type < LDNS_RR_TYPE_ZONEMD)
1951 rrset_ref = &(*rrset_ref)->next;
1952 if (*rrset_ref && (*rrset_ref)->type == LDNS_RR_TYPE_ZONEMD) {
1953 /* reuse zonemd rrset */
1954 zonemd_rrset = *rrset_ref;
1955 ldns_dnssec_rrs_free(zonemd_rrset->rrs);
1956 zonemd_rrset->rrs = NULL;
1957 ldns_dnssec_rrs_free(zonemd_rrset->signatures);
1958 zonemd_rrset->signatures = NULL;
1960 /* insert zonemd rrset */
1961 zonemd_rrset = ldns_dnssec_rrsets_new();
1962 if (!zonemd_rrset) {
1963 ldns_rr_list_deep_free(zonemd_rr_list);
1964 return LDNS_STATUS_MEM_ERR;
1966 zonemd_rrset->type = LDNS_RR_TYPE_ZONEMD;
1967 zonemd_rrset->next = *rrset_ref;
1968 *rrset_ref = zonemd_rrset;
1970 if ((zonemd_rrsigs = ldns_sign_public(zonemd_rr_list, key_list)))
1971 st = rr_list2dnssec_rrs( zonemd_rrsigs
1972 , &zonemd_rrset->signatures, new_rrs);
1974 st = rr_list2dnssec_rrs( zonemd_rr_list
1975 , &zonemd_rrset->rrs, new_rrs);
1976 ldns_rr_list_deep_free(zonemd_rr_list);
1977 ldns_rr_list_deep_free(zonemd_rrsigs);
1981 #endif /* HAVE_SSL */