]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ldns/dnssec_zone.c
ldns: Upgrade to 1.8.3.
[FreeBSD/FreeBSD.git] / contrib / ldns / dnssec_zone.c
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 #include <ldns/internal.h>
9
10 ldns_dnssec_rrs *
11 ldns_dnssec_rrs_new(void)
12 {
13         ldns_dnssec_rrs *new_rrs;
14         new_rrs = LDNS_MALLOC(ldns_dnssec_rrs);
15         if(!new_rrs) return NULL;
16         new_rrs->rr = NULL;
17         new_rrs->next = NULL;
18         return new_rrs;
19 }
20
21 INLINE void
22 ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep)
23 {
24         ldns_dnssec_rrs *next;
25         while (rrs) {
26                 next = rrs->next;
27                 if (deep) {
28                         ldns_rr_free(rrs->rr);
29                 }
30                 LDNS_FREE(rrs);
31                 rrs = next;
32         }
33 }
34
35 void
36 ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs)
37 {
38         ldns_dnssec_rrs_free_internal(rrs, 0);
39 }
40
41 void
42 ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs)
43 {
44         ldns_dnssec_rrs_free_internal(rrs, 1);
45 }
46
47 ldns_status
48 ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr)
49 {
50         int cmp;
51         ldns_dnssec_rrs *new_rrs;
52         if (!rrs || !rr) {
53                 return LDNS_STATUS_ERR;
54         }
55
56         /* this could be done more efficiently; name and type should already
57            be equal */
58         cmp = ldns_rr_compare(rrs->rr, rr);
59         if (cmp < 0) {
60                 if (rrs->next) {
61                         return ldns_dnssec_rrs_add_rr(rrs->next, rr);
62                 } else {
63                         new_rrs = ldns_dnssec_rrs_new();
64                         new_rrs->rr = rr;
65                         rrs->next = new_rrs;
66                 }
67         } else if (cmp > 0) {
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;
73                 rrs->rr = rr;
74                 rrs->next = new_rrs;
75         }
76         /* Silently ignore equal rr's */
77         return LDNS_STATUS_OK;
78 }
79
80 void
81 ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt,
82                const ldns_dnssec_rrs *rrs)
83 {
84         if (!rrs) {
85                 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
86                         fprintf(out, "; <void>");
87         } else {
88                 if (rrs->rr) {
89                         ldns_rr_print_fmt(out, fmt, rrs->rr);
90                 }
91                 if (rrs->next) {
92                         ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next);
93                 }
94         }
95 }
96
97 void
98 ldns_dnssec_rrs_print(FILE *out, const ldns_dnssec_rrs *rrs)
99 {
100         ldns_dnssec_rrs_print_fmt(out, ldns_output_format_default, rrs);
101 }
102
103
104 ldns_dnssec_rrsets *
105 ldns_dnssec_rrsets_new(void)
106 {
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;
114         return new_rrsets;
115 }
116
117 INLINE void
118 ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep)
119 {
120         if (rrsets) {
121                 if (rrsets->rrs) {
122                         ldns_dnssec_rrs_free_internal(rrsets->rrs, deep);
123                 }
124                 if (rrsets->next) {
125                         ldns_dnssec_rrsets_free_internal(rrsets->next, deep);
126                 }
127                 if (rrsets->signatures) {
128                         ldns_dnssec_rrs_free_internal(rrsets->signatures, deep);
129                 }
130                 LDNS_FREE(rrsets);
131         }
132 }
133
134 void
135 ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets)
136 {
137         ldns_dnssec_rrsets_free_internal(rrsets, 0);
138 }
139
140 void
141 ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets)
142 {
143         ldns_dnssec_rrsets_free_internal(rrsets, 1);
144 }
145
146 ldns_rr_type
147 ldns_dnssec_rrsets_type(const ldns_dnssec_rrsets *rrsets)
148 {
149         if (rrsets) {
150                 return rrsets->type;
151         } else {
152                 return 0;
153         }
154 }
155
156 ldns_status
157 ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets,
158                                            ldns_rr_type type)
159 {
160         if (rrsets) {
161                 rrsets->type = type;
162                 return LDNS_STATUS_OK;
163         }
164         return LDNS_STATUS_ERR;
165 }
166
167 static ldns_dnssec_rrsets *
168 ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr)
169 {
170         ldns_dnssec_rrsets *new_rrsets;
171         ldns_rr_type rr_type;
172         bool rrsig;
173
174         new_rrsets = ldns_dnssec_rrsets_new();
175         rr_type = ldns_rr_get_type(rr);
176         if (rr_type == LDNS_RR_TYPE_RRSIG) {
177                 rrsig = true;
178                 rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
179         } else {
180                 rrsig = false;
181         }
182         if (!rrsig) {
183                 new_rrsets->rrs = ldns_dnssec_rrs_new();
184                 new_rrsets->rrs->rr = rr;
185         } else {
186                 new_rrsets->signatures = ldns_dnssec_rrs_new();
187                 new_rrsets->signatures->rr = rr;
188         }
189         new_rrsets->type = rr_type;
190         return new_rrsets;
191 }
192
193 ldns_status
194 ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr)
195 {
196         ldns_dnssec_rrsets *new_rrsets;
197         ldns_rr_type rr_type;
198         bool rrsig = false;
199         ldns_status result = LDNS_STATUS_OK;
200
201         if (!rrsets || !rr) {
202                 return LDNS_STATUS_ERR;
203         }
204
205         rr_type = ldns_rr_get_type(rr);
206
207         if (rr_type == LDNS_RR_TYPE_RRSIG) {
208                 rrsig = true;
209                 rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
210         }
211
212         if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) {
213                 if (!rrsig) {
214                         rrsets->rrs = ldns_dnssec_rrs_new();
215                         rrsets->rrs->rr = rr;
216                         rrsets->type = rr_type;
217                 } else {
218                         rrsets->signatures = ldns_dnssec_rrs_new();
219                         rrsets->signatures->rr = rr;
220                         rrsets->type = rr_type;
221                 }
222                 return LDNS_STATUS_OK;
223         }
224
225         if (rr_type > ldns_dnssec_rrsets_type(rrsets)) {
226                 if (rrsets->next) {
227                         result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr);
228                 } else {
229                         new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr);
230                         rrsets->next = new_rrsets;
231                 }
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;
240                 if (!rrsig) {
241                         rrsets->rrs = ldns_dnssec_rrs_new();
242                         rrsets->rrs->rr = rr;
243                         rrsets->signatures = NULL;
244                 } else {
245                         rrsets->rrs = NULL;
246                         rrsets->signatures = ldns_dnssec_rrs_new();
247                         rrsets->signatures->rr = rr;
248                 }
249                 rrsets->type = rr_type;
250                 rrsets->next = new_rrsets;
251         } else {
252                 /* equal, add to current rrsets */
253                 if (rrsig) {
254                         if (rrsets->signatures) {
255                                 result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr);
256                         } else {
257                                 rrsets->signatures = ldns_dnssec_rrs_new();
258                                 rrsets->signatures->rr = rr;
259                         }
260                 } else {
261                         if (rrsets->rrs) {
262                                 result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr);
263                         } else {
264                                 rrsets->rrs = ldns_dnssec_rrs_new();
265                                 rrsets->rrs->rr = rr;
266                         }
267                 }
268         }
269
270         return result;
271 }
272
273 static void
274 ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
275                 const ldns_dnssec_rrsets *rrsets,
276                 bool follow,
277                 bool show_soa)
278 {
279         if (!rrsets) {
280                 if ((fmt->flags & LDNS_COMMENT_LAYOUT))
281                         fprintf(out, "; <void>\n");
282         } else {
283                 if (rrsets->rrs &&
284                     (show_soa ||
285                         ldns_rr_get_type(rrsets->rrs->rr) != LDNS_RR_TYPE_SOA
286                     )
287                    ) {
288                         ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs);
289                         if (rrsets->signatures) {
290                                 ldns_dnssec_rrs_print_fmt(out, fmt, 
291                                                 rrsets->signatures);
292                         }
293                 }
294                 if (follow && rrsets->next) {
295                         ldns_dnssec_rrsets_print_soa_fmt(out, fmt, 
296                                         rrsets->next, follow, show_soa);
297                 }
298         }
299 }
300
301
302 void
303 ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt,
304                 const ldns_dnssec_rrsets *rrsets, 
305                 bool follow)
306 {
307         ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true);
308 }
309
310 void
311 ldns_dnssec_rrsets_print(FILE *out, const ldns_dnssec_rrsets *rrsets, bool follow)
312 {
313         ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default, 
314                         rrsets, follow);
315 }
316
317 ldns_dnssec_name *
318 ldns_dnssec_name_new(void)
319 {
320         ldns_dnssec_name *new_name;
321
322         new_name = LDNS_CALLOC(ldns_dnssec_name, 1);
323         if (!new_name) {
324                 return NULL;
325         }
326         /*
327          * not needed anymore because CALLOC initializes everything to zero.
328
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;
334
335         new_name->is_glue = false;
336         new_name->hashed_name = NULL;
337
338          */
339         return new_name;
340 }
341
342 ldns_dnssec_name *
343 ldns_dnssec_name_new_frm_rr(ldns_rr *rr)
344 {
345         ldns_dnssec_name *new_name = ldns_dnssec_name_new();
346
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);
350                 return NULL;
351         }
352
353         return new_name;
354 }
355
356 INLINE void
357 ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
358                                int deep)
359 {
360         if (name) {
361                 if (name->name_alloced) {
362                         ldns_rdf_deep_free(name->name);
363                 }
364                 if (name->rrsets) {
365                         ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
366                 }
367                 if (name->nsec && deep) {
368                         ldns_rr_free(name->nsec);
369                 }
370                 if (name->nsec_signatures) {
371                         ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
372                 }
373                 if (name->hashed_name) {
374                         /* Hashed name is always allocated when signing,
375                          * so always deep free
376                          */
377                         ldns_rdf_deep_free(name->hashed_name);
378                 }
379                 LDNS_FREE(name);
380         }
381 }
382
383 void
384 ldns_dnssec_name_free(ldns_dnssec_name *name)
385 {
386   ldns_dnssec_name_free_internal(name, 0);
387 }
388
389 void
390 ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
391 {
392   ldns_dnssec_name_free_internal(name, 1);
393 }
394
395 ldns_rdf *
396 ldns_dnssec_name_name(const ldns_dnssec_name *name)
397 {
398         if (name) {
399                 return name->name;
400         }
401         return NULL;
402 }
403
404 bool
405 ldns_dnssec_name_is_glue(const ldns_dnssec_name *name)
406 {
407         if (name) {
408                 return name->is_glue;
409         }
410         return false;
411 }
412
413 void
414 ldns_dnssec_name_set_name(ldns_dnssec_name *rrset,
415                                          ldns_rdf *dname)
416 {
417         if (rrset && dname) {
418                 rrset->name = dname;
419         }
420 }
421
422
423 void
424 ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec)
425 {
426         if (rrset && nsec) {
427                 rrset->nsec = nsec;
428         }
429 }
430
431 int
432 ldns_dnssec_name_cmp(const void *a, const void *b)
433 {
434         ldns_dnssec_name *na = (ldns_dnssec_name *) a;
435         ldns_dnssec_name *nb = (ldns_dnssec_name *) b;
436
437         if (na && nb) {
438                 return ldns_dname_compare(ldns_dnssec_name_name(na),
439                                                          ldns_dnssec_name_name(nb));
440         } else if (na) {
441                 return 1;
442         } else if (nb) {
443                 return -1;
444         } else {
445                 return 0;
446         }
447 }
448
449 ldns_status
450 ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
451                                     ldns_rr *rr)
452 {
453         ldns_status result = LDNS_STATUS_OK;
454         ldns_rr_type rr_type;
455         ldns_rr_type typecovered = 0;
456
457         /* special handling for NSEC3 and NSECX covering RRSIGS */
458
459         if (!name || !rr) {
460                 return LDNS_STATUS_ERR;
461         }
462
463         rr_type = ldns_rr_get_type(rr);
464
465         if (rr_type == LDNS_RR_TYPE_RRSIG) {
466                 typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
467         }
468
469         if (rr_type == LDNS_RR_TYPE_NSEC ||
470             rr_type == LDNS_RR_TYPE_NSEC3) {
471                 /* XX check if is already set (and error?) */
472                 name->nsec = rr;
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);
477                 } else {
478                         name->nsec_signatures = ldns_dnssec_rrs_new();
479                         name->nsec_signatures->rr = rr;
480                 }
481         } else {
482                 /* it's a 'normal' RR, add it to the right rrset */
483                 if (name->rrsets) {
484                         result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
485                 } else {
486                         name->rrsets = ldns_dnssec_rrsets_new();
487                         result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
488                 }
489         }
490         return result;
491 }
492
493 ldns_dnssec_rrsets *
494 ldns_dnssec_name_find_rrset(const ldns_dnssec_name *name,
495                                            ldns_rr_type type) {
496         ldns_dnssec_rrsets *result;
497
498         result = name->rrsets;
499         while (result) {
500                 if (result->type == type) {
501                         return result;
502                 } else {
503                         result = result->next;
504                 }
505         }
506         return NULL;
507 }
508
509 ldns_dnssec_rrsets *
510 ldns_dnssec_zone_find_rrset(const ldns_dnssec_zone *zone,
511                                            const ldns_rdf *dname,
512                                            ldns_rr_type type)
513 {
514         ldns_rbnode_t *node;
515
516         if (!zone || !dname || !zone->names) {
517                 return NULL;
518         }
519
520         node = ldns_rbtree_search(zone->names, dname);
521         if (node) {
522                 return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data,
523                                                                         type);
524         } else {
525                 return NULL;
526         }
527 }
528
529 static void
530 ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
531                 const ldns_dnssec_name *name, 
532                 bool show_soa)
533 {
534         if (name) {
535                 if(name->rrsets) {
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);
541                         fprintf(out, "\n");
542                 }
543                 if(name->nsec) {
544                         ldns_rr_print_fmt(out, fmt, name->nsec);
545                 }
546                 if (name->nsec_signatures) {
547                         ldns_dnssec_rrs_print_fmt(out, fmt, 
548                                         name->nsec_signatures);
549                 }
550         } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
551                 fprintf(out, "; <void>\n");
552         }
553 }
554
555
556 void
557 ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt,
558                 const ldns_dnssec_name *name)
559 {
560         ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
561 }
562
563 void
564 ldns_dnssec_name_print(FILE *out, const ldns_dnssec_name *name)
565 {
566         ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name);
567 }
568
569
570 ldns_dnssec_zone *
571 ldns_dnssec_zone_new(void)
572 {
573         ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone);
574         if(!zone) return NULL;
575         zone->soa = NULL;
576         zone->names = NULL;
577         zone->hashed_names = NULL;
578         zone->_nsec3params = NULL;
579
580         return zone;
581 }
582
583 static bool
584 rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
585 {
586         return     ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
587                 && ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t;
588 }
589
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.
595  */
596 #define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
597
598 static ldns_status
599 ldns_dnssec_zone_add_empty_nonterminals_nsec3(
600                 ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s);
601
602 static void
603 ldns_todo_nsec3_ents_node_free(ldns_rbnode_t *node, void *arg) {
604         (void) arg;
605         ldns_rdf_deep_free((ldns_rdf *)node->key);
606         LDNS_FREE(node);
607 }
608
609 ldns_status
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)
612 {
613         ldns_rr* cur_rr;
614         size_t i;
615
616         ldns_rdf *my_origin = NULL;
617         ldns_rdf *my_prev = NULL;
618
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.
627
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();
635
636         ldns_status status;
637
638 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
639         ldns_zone* zone = NULL;
640 #else
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.'
645          */
646         bool ttl_from_TTL = false;
647         bool explicit_ttl = false;
648 #endif
649
650         ldns_rbtree_init(&todo_nsec3_ents, ldns_dname_compare_v);
651
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)
655                 goto error;
656 #endif
657         if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) {
658                 status = LDNS_STATUS_MEM_ERR;
659                 goto error;
660         }
661         if (origin) {
662                 if (!(my_origin = ldns_rdf_clone(origin))) {
663                         status = LDNS_STATUS_MEM_ERR;
664                         goto error;
665                 }
666                 if (!(my_prev   = ldns_rdf_clone(origin))) {
667                         status = LDNS_STATUS_MEM_ERR;
668                         goto error;
669                 }
670         }
671
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)
676                         goto error;
677         }
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;
681 #else
682         while (!feof(fp)) {
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)
687                  */
688                 if (ttl_from_TTL)
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);
692 #endif
693                 switch (status) {
694                 case LDNS_STATUS_OK:
695 #ifndef FASTER_DNSSEC_ZONE_NEW_FRM_FP
696                         if (explicit_ttl) {
697                                 if (!ttl_from_TTL) {
698                                         /* No $TTL, so ttl "defaults to the
699                                          * last explicitly stated value"
700                                          * (RFC 1035 Section 5.1)
701                                          */
702                                         my_ttl = ldns_rr_ttl(cur_rr);
703                                 }
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.
708                          */
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)
713
714                                         /* SIG without explicit ttl get ttl
715                                          * from the original_ttl field
716                                          * (RFC 2535 Section 7.2)
717                                          *
718                                          * Similarly for RRSIG, but stated less
719                                          * specifically in the spec.
720                                          * (RFC 4034 Section 3)
721                                          */
722                                         ldns_rr_set_ttl(cur_rr,
723                                             ldns_rdf2native_int32(
724                                                 ldns_rr_rdf(rr, 3)));
725
726                         } else if (prev_rr
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)
730
731                                 /* "TTLs of all RRs in an RRSet must be the same"
732                                  * (RFC 2881 Section 5.2)
733                                  */
734                                 ldns_rr_set_ttl(cur_rr, ldns_rr_ttl(prev_rr));
735
736                         prev_rr = cur_rr;
737 #endif
738                         status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
739                         if (status ==
740                                 LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
741
742                                 if (rr_is_rrsig_covering(cur_rr,
743                                                         LDNS_RR_TYPE_NSEC3)){
744                                         ldns_rr_list_push_rr(todo_nsec3_rrsigs,
745                                                         cur_rr);
746                                 } else {
747                                         ldns_rr_list_push_rr(todo_nsec3s,
748                                                         cur_rr);
749                                 }
750                                 status = LDNS_STATUS_OK;
751
752                         } else if (status != LDNS_STATUS_OK)
753                                 goto error;
754
755                         break;
756
757                 case LDNS_STATUS_SYNTAX_TTL:    /* the ttl was set*/
758 #ifndef FASTER_DNSSEC_ZONE_NEW_FRM_FP
759                         default_ttl = my_ttl;
760                         ttl_from_TTL = true;
761 #endif
762                         status = LDNS_STATUS_OK;
763                         break;
764
765
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;
769                         break;
770
771                 case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
772                         status =  LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
773                         break;
774
775                 default:
776                         goto error;
777                 }
778         }
779
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;
787                                 break;
788                         }
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)) {
792                                 LDNS_FREE(new_node);
793                                 status = LDNS_STATUS_MEM_ERR;
794                                 break;
795                         }
796                         status = LDNS_STATUS_OK;
797                 }
798         }
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);
806         }
807         if (z) {
808                 *z = newzone;
809                 newzone = NULL;
810         } else {
811                 ldns_dnssec_zone_free(newzone);
812                 newzone = NULL;
813         }
814
815 error:
816 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
817         if (zone) {
818                 ldns_zone_free(zone);
819         }
820 #endif
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);
825
826         if (my_origin) {
827                 ldns_rdf_deep_free(my_origin);
828         }
829         if (my_prev) {
830                 ldns_rdf_deep_free(my_prev);
831         }
832         if (newzone) {
833                 ldns_dnssec_zone_free(newzone);
834         }
835         return status;
836 }
837
838 ldns_status
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))
841 {
842         return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
843 }
844
845 static void
846 ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
847         (void) arg;
848         ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
849         LDNS_FREE(node);
850 }
851
852 static void
853 ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
854         (void) arg;
855         ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data);
856         LDNS_FREE(node);
857 }
858
859 static void
860 ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) {
861         (void) arg;
862         LDNS_FREE(node);
863 }
864
865 void
866 ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
867 {
868         if (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);
873                 }
874                 if (zone->names) {
875                         /* destroy all name structures within the tree */
876                         ldns_traverse_postorder(zone->names,
877                                                     ldns_dnssec_name_node_free,
878                                                     NULL);
879                         LDNS_FREE(zone->names);
880                 }
881                 LDNS_FREE(zone);
882         }
883 }
884
885 void
886 ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
887 {
888         if (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);
893                 }
894                 if (zone->names) {
895                         /* destroy all name structures within the tree */
896                         ldns_traverse_postorder(zone->names,
897                                                     ldns_dnssec_name_node_deep_free,
898                                                     NULL);
899                         LDNS_FREE(zone->names);
900                 }
901                 LDNS_FREE(zone);
902         }
903 }
904
905 /* use for dname comparison in tree */
906 int
907 ldns_dname_compare_v(const void *a, const void *b) {
908         return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
909 }
910
911 static void
912 ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
913                 ldns_dnssec_name* name, ldns_rr* nsec3rr);
914
915 static void
916 ldns_dnssec_zone_hashed_names_from_nsec3(
917                 ldns_dnssec_zone* zone, ldns_rr* nsec3rr)
918 {
919         ldns_rbnode_t* current_node;
920         ldns_dnssec_name* current_name;
921
922         assert(zone != NULL);
923         assert(nsec3rr != NULL);
924
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);
929         }
930         zone->_nsec3params = nsec3rr;
931
932         /* So this is a NSEC3 zone.
933         * Calculate hashes for all names already in the zone
934         */
935         zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v);
936         if (zone->hashed_names == NULL) {
937                 return;
938         }
939         for ( current_node  = ldns_rbtree_first(zone->names)
940             ; current_node != LDNS_RBTREE_NULL
941             ; current_node  = ldns_rbtree_next(current_node)
942             ) {
943                 current_name = (ldns_dnssec_name *) current_node->data;
944                 ldns_dnssec_name_make_hashed_name(zone, current_name, nsec3rr);
945
946         }
947 }
948
949 static void
950 ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
951                 ldns_dnssec_name* name, ldns_rr* nsec3rr)
952 {
953         ldns_rbnode_t* new_node;
954
955         assert(name != NULL);
956         if (! zone->_nsec3params) {
957                 if (! nsec3rr) {
958                         return;
959                 }
960                 ldns_dnssec_zone_hashed_names_from_nsec3(zone, nsec3rr);
961
962         } else if (! nsec3rr) {
963                 nsec3rr = zone->_nsec3params;
964         }
965         name->hashed_name = ldns_nsec3_hash_name_frm_nsec3(nsec3rr, name->name);
966
967         /* Also store in zone->hashed_names */
968         if ((new_node = LDNS_MALLOC(ldns_rbnode_t))) {
969
970                 new_node->key  = name->hashed_name;
971                 new_node->data = name;
972
973                 if (ldns_rbtree_insert(zone->hashed_names, new_node) == NULL) {
974
975                                 LDNS_FREE(new_node);
976                 }
977         }
978 }
979
980
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;
985
986         if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 && ! zone->_nsec3params){
987
988                 ldns_dnssec_zone_hashed_names_from_nsec3(zone, rr);
989         }
990         if (zone->hashed_names == NULL) {
991                 return NULL;
992         }
993         hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
994         if (hashed_name == NULL) {
995                 return NULL;
996         }
997         to_return = ldns_rbtree_search(zone->hashed_names, hashed_name);
998         ldns_rdf_deep_free(hashed_name);
999         return to_return;
1000 }
1001
1002 ldns_status
1003 ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
1004 {
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;
1009
1010         if (!zone || !rr) {
1011                 return LDNS_STATUS_ERR;
1012         }
1013
1014         if (!zone->names) {
1015                 zone->names = ldns_rbtree_create(ldns_dname_compare_v);
1016                 if(!zone->names) return LDNS_STATUS_MEM_ERR;
1017         }
1018
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));
1023         }
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);
1027                 if (!cur_node) {
1028                         return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND;
1029                 }
1030         } else {
1031                 cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
1032         }
1033         if (!cur_node) {
1034                 /* add */
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);
1038                 if(!cur_node) {
1039                         ldns_dnssec_name_free(cur_name);
1040                         return LDNS_STATUS_MEM_ERR;
1041                 }
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);
1046         } else {
1047                 cur_name = (ldns_dnssec_name *) cur_node->data;
1048                 result = ldns_dnssec_name_add_rr(cur_name, rr);
1049         }
1050         if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
1051                 zone->soa = cur_name;
1052         }
1053         return result;
1054 }
1055
1056 void
1057 ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
1058                 const ldns_rbtree_t *tree, 
1059                 bool print_soa)
1060 {
1061         ldns_rbnode_t *node;
1062         ldns_dnssec_name *name;
1063
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);
1071         }
1072 }
1073
1074 void
1075 ldns_dnssec_zone_names_print(FILE *out, const ldns_rbtree_t *tree, bool print_soa)
1076 {
1077         ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default,
1078                        tree, print_soa);
1079 }
1080
1081 void
1082 ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt,
1083                const ldns_dnssec_zone *zone)
1084 {
1085         if (zone) {
1086                 if (zone->soa) {
1087                         if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
1088                                 fprintf(out, ";; Zone: ");
1089                                 ldns_rdf_print(out, ldns_dnssec_name_name(
1090                                                         zone->soa));
1091                                 fprintf(out, "\n;\n");
1092                         }
1093                         ldns_dnssec_rrsets_print_fmt(out, fmt,
1094                                         ldns_dnssec_name_find_rrset(
1095                                                 zone->soa, 
1096                                                 LDNS_RR_TYPE_SOA), 
1097                                         false);
1098                         if ((fmt->flags & LDNS_COMMENT_LAYOUT))
1099                                 fprintf(out, ";\n");
1100                 }
1101
1102                 if (zone->names) {
1103                         ldns_dnssec_zone_names_print_fmt(out, fmt, 
1104                                         zone->names, false);
1105                 }
1106         }
1107 }
1108
1109 void
1110 ldns_dnssec_zone_print(FILE *out, const ldns_dnssec_zone *zone)
1111 {
1112         ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone);
1113 }
1114
1115 static ldns_status
1116 ldns_dnssec_zone_add_empty_nonterminals_nsec3(
1117                 ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s)
1118 {
1119         ldns_dnssec_name *new_name;
1120         ldns_rdf *cur_name;
1121         ldns_rdf *next_name;
1122         ldns_rbnode_t *cur_node, *next_node, *new_node;
1123
1124         /* for the detection */
1125         uint16_t i, cur_label_count, next_label_count;
1126         uint16_t soa_label_count = 0;
1127         ldns_rdf *l1, *l2;
1128         int lpos;
1129
1130         if (!zone) {
1131                 return LDNS_STATUS_ERR;
1132         }
1133         if (zone->soa && zone->soa->name) {
1134                 soa_label_count = ldns_dname_label_count(zone->soa->name);
1135         }
1136         
1137         cur_node = ldns_rbtree_first(zone->names);
1138         while (cur_node != LDNS_RBTREE_NULL) {
1139                 next_node = ldns_rbtree_next(cur_node);
1140                 
1141                 /* skip glue */
1142                 while (next_node != LDNS_RBTREE_NULL && 
1143                        next_node->data &&
1144                        ((ldns_dnssec_name *)next_node->data)->is_glue
1145                 ) {
1146                         next_node = ldns_rbtree_next(next_node);
1147                 }
1148
1149                 if (next_node == LDNS_RBTREE_NULL) {
1150                         next_node = ldns_rbtree_first(zone->names);
1151                 }
1152                 if (! cur_node->data || ! next_node->data) {
1153                         return LDNS_STATUS_ERR;
1154                 }
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);
1159
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)
1166                  */
1167                 for (i = 1; i < next_label_count - soa_label_count; i++) {
1168                         lpos = (int)cur_label_count - (int)next_label_count + (int)i;
1169                         if (lpos >= 0) {
1170                                 l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
1171                         } else {
1172                                 l1 = NULL;
1173                         }
1174                         l2 = ldns_dname_clone_from(next_name, i);
1175
1176                         if (!l1 || ldns_dname_compare(l1, l2) != 0) {
1177                                 /* We have an empty nonterminal, add it to the
1178                                  * tree
1179                                  */
1180                                 ldns_rbnode_t *node = NULL;
1181                                 ldns_rdf *ent_name;
1182
1183                                 if (!(ent_name = ldns_dname_clone_from(
1184                                                 next_name, i))) {
1185                                         
1186                                         ldns_rdf_deep_free(l1);
1187                                         ldns_rdf_deep_free(l2);
1188                                         return LDNS_STATUS_MEM_ERR;
1189                                 }
1190
1191                                 if (nsec3s && zone->_nsec3params) {
1192                                         ldns_rdf *ent_hashed_name;
1193
1194                                         if (!(ent_hashed_name =
1195                                             ldns_nsec3_hash_name_frm_nsec3(
1196                                                         zone->_nsec3params,
1197                                                         ent_name))) {
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;
1202                                         }
1203                                         node = ldns_rbtree_search(nsec3s, 
1204                                                         ent_hashed_name);
1205                                         ldns_rdf_deep_free(ent_hashed_name);
1206                                         if (!node) {
1207                                                 ldns_rdf_deep_free(l1);
1208                                                 ldns_rdf_deep_free(l2);
1209                                                 ldns_rdf_deep_free(ent_name);
1210                                                 continue;
1211                                         }
1212                                 }
1213                                 new_name = ldns_dnssec_name_new();
1214                                 if (!new_name) {
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;
1219                                 }
1220                                 new_name->name = ent_name;
1221                                 new_name->name_alloced = true;
1222                                 new_node = LDNS_MALLOC(ldns_rbnode_t);
1223                                 if (!new_node) {
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;
1228                                 }
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);
1234                                 if (node)
1235                                         (void) ldns_dnssec_zone_add_rr(zone,
1236                                                         (ldns_rr *)node->data);
1237                         }
1238                         ldns_rdf_deep_free(l1);
1239                         ldns_rdf_deep_free(l2);
1240                 }
1241                 
1242                 /* we might have inserted a new node after
1243                  * the current one so we can't just use next()
1244                  */
1245                 if (next_node != ldns_rbtree_first(zone->names)) {
1246                         cur_node = next_node;
1247                 } else {
1248                         cur_node = LDNS_RBTREE_NULL;
1249                 }
1250         }
1251         return LDNS_STATUS_OK;
1252 }
1253
1254 ldns_status
1255 ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
1256 {
1257         return ldns_dnssec_zone_add_empty_nonterminals_nsec3(zone, NULL);
1258 }
1259
1260 bool
1261 ldns_dnssec_zone_is_nsec3_optout(const ldns_dnssec_zone* zone)
1262 {
1263         ldns_rr* nsec3;
1264         ldns_rbnode_t* node;
1265
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)) {
1273                                 return true;
1274                         }
1275                         node = ldns_rbtree_next(node);
1276                 }
1277         }
1278         return false;
1279 }
1280
1281 /*
1282  * Stuff for calculating and verifying zone digests
1283  */
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;
1293
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;
1305         uint8_t                   apex_labs;
1306 } dnssec_zone_rr_iter;
1307
1308 INLINE void
1309 dnssec_zone_rr_iter_set_state_for_next_name(dnssec_zone_rr_iter *i)
1310 {
1311         /* Make sure the i->name is "in zone" (i.e. below the apex) */
1312         if (i->apex_name) {
1313                 ldns_rdf *name = (ldns_rdf *)i->node->key;
1314
1315                 while (i->name && name != i->apex_name        /* not apex */
1316
1317                 && (  ldns_dname_label_count(name) != i->apex_labs
1318                    || ldns_dname_compare(name, i->apex_name)) /* not apex */
1319
1320                 && !ldns_dname_is_subdomain(name, i->apex_name) /* no sub */) {
1321
1322                         /* next name */
1323                         i->node = ldns_rbtree_next(i->node);
1324                         if (i->node == LDNS_RBTREE_NULL)
1325                                 i->name = NULL;
1326                         else {
1327                                 i->name = (ldns_dnssec_name *)i->node->data;
1328                                 name = (ldns_rdf *)i->node->key;
1329                         }
1330                 }
1331         }
1332         /* determine state */
1333         if (!i->name) {
1334                 if (!i->nsec3_name)
1335                         i->state = DNSSEC_ZONE_RR_ITER_FINI;
1336                 else {
1337                         i->rrs = i->nsec3_name->nsec_signatures;
1338                         i->state = DNSSEC_ZONE_RR_ITER_NSEC3;
1339                 }
1340         } else if (!i->nsec3_name) {
1341                 i->rrsets = i->name->rrsets;
1342                 i->state = DNSSEC_ZONE_RR_ITER_LT_RRSIG;
1343
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;
1348         } else {
1349                 i->rrsets = i->name->rrsets;
1350                 i->state = DNSSEC_ZONE_RR_ITER_LT_RRSIG;
1351         }
1352 }
1353
1354 /**
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.
1357  * 
1358  * 1. There is no NSEC:
1359  *
1360  *    1.1. All the RRs in the name->rrsets with type < RRSIG,
1361  *         state: DNSSEC_ZONE_RR_ITER_LT_RRSIG
1362  *
1363  *    1.2. Then all the RRSIGs from name->rrsets (likely none)
1364  *         state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1365  *
1366  *    1.3. Finally the remaining RRs in name->rrsets (type > RRSIG)
1367  *         state: DNSSEC_ZONE_RR_ITER_REST
1368  *
1369  *
1370  * 2. There is a NSEC of type NSEC with this name:
1371  *
1372  *    2.1. All the RRs in the name->rrsets with type < RRSIG,
1373  *         state: DNSSEC_ZONE_RR_ITER_LT_RRSIG
1374  *
1375  *    2.2. Then all the RRSIGs from name->rrsets with type < NSEC
1376  *         state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1377  *
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
1382  *
1383  *    2.4. Finally the remaining RRs in name->rrsets (type > RRSIG)
1384  *         state: DNSSEC_ZONE_RR_ITER_REST
1385  *
1386  *
1387  * 3. There is a NSEC of type NSEC3 for this name:
1388  *
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
1392  *
1393  *         otherwise follow path for "no NSEC" for the name for other RRsets
1394  */
1395 static ldns_rr *
1396 dnssec_zone_rr_iter_next(dnssec_zone_rr_iter *i)
1397 {
1398         ldns_rr *nsec3;
1399
1400         for (;;) {
1401                 if (i->rrs) {
1402                         ldns_rr *rr = i->rrs->rr;
1403                         i->rrs = i->rrs->next;
1404                         return rr;
1405                 }
1406                 switch (i->state) {
1407                 case DNSSEC_ZONE_RR_ITER_LT_RRSIG:
1408                         if (i->rrsets
1409                         &&  i->rrsets->type < LDNS_RR_TYPE_RRSIG) {
1410
1411                                 i->rrs = i->rrsets->rrs;
1412                                 i->rrsets = i->rrsets->next;
1413                                 break;
1414                         }
1415                         i->rrsets4rrsigs = i->name->rrsets;
1416                         if (i->name->nsec && ldns_rr_get_type(i->name->nsec)
1417                                                        == LDNS_RR_TYPE_NSEC) {
1418
1419                                 i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC;
1420                                 break;
1421                         }
1422                         i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC;
1423                         /* fallthrough */
1424
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;
1429                                 break;
1430                         }
1431                         i->state = DNSSEC_ZONE_RR_ITER_REST;
1432                         /* fallthrough */
1433
1434                 case DNSSEC_ZONE_RR_ITER_REST:
1435                         if (i->rrsets) {
1436                                 i->rrs = i->rrsets->rrs;
1437                                 i->rrsets = i->rrsets->next;
1438                                 break;
1439                         }
1440                         /* next name */
1441                         i->node = ldns_rbtree_next(i->node);
1442                         i->name = i->node == LDNS_RBTREE_NULL ? NULL
1443                                 : (ldns_dnssec_name *)i->node->data;
1444
1445                         dnssec_zone_rr_iter_set_state_for_next_name(i);
1446                         break;
1447
1448                 case DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC:
1449                         if (i->rrsets4rrsigs
1450                         &&  i->rrsets4rrsigs->type < LDNS_RR_TYPE_NSEC) {
1451
1452                                 i->rrs = i->rrsets4rrsigs->signatures;
1453                                 i->rrsets4rrsigs = i->rrsets4rrsigs->next;
1454                                 break;
1455                         }
1456                         i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC_REST;
1457                         i->rrs = i->name->nsec_signatures;
1458                         break;
1459
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;
1464                                 break;
1465                         }
1466                         i->state = DNSSEC_ZONE_RR_ITER_REST;
1467                         return i->name->nsec;
1468
1469                 case DNSSEC_ZONE_RR_ITER_NSEC3:
1470                         nsec3 = i->nsec3_name->nsec;
1471
1472                         /* next nsec3 */
1473                         do {
1474                                 i->nsec3_node
1475                                     = ldns_rbtree_next(i->nsec3_node);
1476                                 i->nsec3_name
1477                                     = i->nsec3_node == LDNS_RBTREE_NULL ? NULL
1478                                     : (ldns_dnssec_name*)i->nsec3_node->data;
1479
1480                                 /* names for glue can be in the hashed_names 
1481                                  * tree, but will not have a NSEC3 
1482                                  */
1483                         } while (i->nsec3_name && !i->nsec3_name->nsec);
1484
1485                         dnssec_zone_rr_iter_set_state_for_next_name(i);
1486                         return nsec3;
1487
1488                 case DNSSEC_ZONE_RR_ITER_FINI:
1489                         return NULL;
1490                 }
1491         }
1492 }
1493
1494 static ldns_rr *
1495 dnssec_zone_rr_iter_first(dnssec_zone_rr_iter *i, ldns_dnssec_zone *zone)
1496 {
1497         if (!i || !zone)
1498                 return NULL;
1499
1500         memset(i, 0, sizeof(*i));
1501         i->zone = zone;
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);
1505         } else
1506                 i->apex_name = NULL;
1507
1508
1509         i->node = ldns_rbtree_first(zone->names);
1510         i->name = i->node == LDNS_RBTREE_NULL ? NULL
1511                 : (ldns_dnssec_name *)i->node->data;
1512
1513         if (zone->hashed_names) {
1514                 do {
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);
1519         }
1520         dnssec_zone_rr_iter_set_state_for_next_name(i);
1521         return dnssec_zone_rr_iter_next(i);
1522 }
1523
1524 enum enum_zonemd_scheme {
1525         ZONEMD_SCHEME_FIRST  = 1,
1526         ZONEMD_SCHEME_SIMPLE = 1,
1527         ZONEMD_SCHEME_LAST   = 1
1528 };
1529 typedef enum enum_zonemd_scheme zonemd_scheme;
1530
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
1536 };
1537 typedef enum enum_zonemd_hash zonemd_hash;
1538
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;
1546 };
1547 typedef struct struct_zone_digester zone_digester;
1548
1549 INLINE bool zone_digester_set(zone_digester *zd)
1550 { return zd && (zd->simple_sha384 || zd->simple_sha512); }
1551
1552 INLINE void zone_digester_init(zone_digester *zd)
1553 { memset(zd, 0, sizeof(*zd)); }
1554
1555 static ldns_status
1556 zone_digester_add(zone_digester *zd, zonemd_scheme scheme, zonemd_hash hash)
1557 {
1558         if (!zd)
1559                 return LDNS_STATUS_NULL;
1560
1561         switch (scheme) {
1562         case ZONEMD_SCHEME_SIMPLE:
1563                 switch (hash) {
1564                 case ZONEMD_HASH_SHA384:
1565                         if (zd->double_sha384)
1566                                 return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1567
1568                         else if (zd->simple_sha384) {
1569                                 zd->simple_sha384 = 0;
1570                                 zd->double_sha384 = 1;
1571                                 return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1572                         }
1573                         ldns_sha384_init(&zd->sha384_CTX);
1574                         zd->simple_sha384 = 1;
1575                         break;
1576
1577                 case ZONEMD_HASH_SHA512:
1578                         if (zd->double_sha512)
1579                                 return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1580
1581                         else if (zd->simple_sha512) {
1582                                 zd->simple_sha512 = 0;
1583                                 zd->double_sha512 = 1;
1584                                 return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1585                         }
1586                         ldns_sha512_init(&zd->sha512_CTX);
1587                         zd->simple_sha512 = 1;
1588                         break;
1589                 default:
1590                         return LDNS_STATUS_ZONEMD_UNKNOWN_HASH;
1591                 }
1592                 break;
1593         default:
1594                 return LDNS_STATUS_ZONEMD_UNKNOWN_SCHEME;
1595         }
1596         return LDNS_STATUS_OK;
1597 }
1598
1599 static ldns_status
1600 zone_digester_update(zone_digester *zd, ldns_rr *rr)
1601 {
1602         uint8_t data[65536];
1603         ldns_buffer buf;
1604         ldns_status st;
1605         
1606         buf._data = data;
1607         buf._position = 0;
1608         buf._limit = sizeof(data);
1609         buf._capacity = sizeof(data);
1610         buf._fixed = 1;
1611         buf._status = LDNS_STATUS_OK;
1612
1613         if ((st = ldns_rr2buffer_wire_canonical(&buf, rr, LDNS_SECTION_ANSWER)))
1614                 return st;
1615
1616         if (zd->simple_sha384)
1617                 ldns_sha384_update(&zd->sha384_CTX, data, buf._position);
1618
1619         if (zd->simple_sha512)
1620                 ldns_sha512_update(&zd->sha512_CTX, data, buf._position);
1621
1622         return LDNS_STATUS_OK;
1623 }
1624
1625 INLINE ldns_rr *
1626 new_zonemd(ldns_rr *soa, zonemd_hash hash)
1627 {
1628         ldns_rr  *rr     = NULL;
1629         uint8_t  *data   = NULL;
1630         ldns_rdf *rdf;
1631         size_t    md_len = hash == ZONEMD_HASH_SHA384
1632                          ? LDNS_SHA384_DIGEST_LENGTH
1633                          : LDNS_SHA512_DIGEST_LENGTH;
1634
1635         if (!(rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_ZONEMD)))
1636                 return NULL;
1637
1638         if (!(rdf = ldns_rdf_clone(ldns_rr_owner(soa))))
1639                 goto error;
1640
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));
1644
1645         if (!(rdf = ldns_rdf_clone(ldns_rr_rdf(soa, 2))))
1646                 goto error;
1647         ldns_rr_set_rdf(rr, rdf, 0);
1648
1649         if (!(rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, 1)))
1650                 goto error;
1651         ldns_rr_set_rdf(rr, rdf, 1);
1652
1653         if (!(rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, hash)))
1654                 goto error;
1655         ldns_rr_set_rdf(rr, rdf, 2);
1656
1657         if (!(data = LDNS_XMALLOC(uint8_t, md_len)))
1658                 goto error;
1659
1660         if (!(rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, md_len, data)))
1661                 goto error;
1662         ldns_rr_set_rdf(rr, rdf, 3);
1663
1664         return rr;
1665 error:
1666         if (data)
1667                 LDNS_FREE(data);
1668         ldns_rr_free(rr);
1669         return NULL;
1670 }
1671
1672 static ldns_rr_list *
1673 zone_digester_export(
1674                 zone_digester *zd, ldns_rr *soa, ldns_status *ret_st)
1675 {
1676         ldns_status st = LDNS_STATUS_OK;
1677         ldns_rr_list *rr_list = NULL;
1678         ldns_rr *sha384 = NULL;
1679         ldns_rr *sha512 = NULL;
1680
1681         if (!zd || !soa)
1682                 st = LDNS_STATUS_NULL;
1683
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;
1687
1688         else if (!(rr_list = ldns_rr_list_new()))
1689                 st = LDNS_STATUS_MEM_ERR;
1690
1691         else if (zd->simple_sha384
1692              && !(sha384 = new_zonemd(soa, ZONEMD_HASH_SHA384)))
1693                 st = LDNS_STATUS_MEM_ERR;
1694
1695         else if (zd->simple_sha512
1696              && !(sha512 = new_zonemd(soa, ZONEMD_HASH_SHA512)))
1697                 st = LDNS_STATUS_MEM_ERR;
1698
1699         else if (zd->simple_sha384
1700              && !ldns_rr_list_push_rr(rr_list, sha384))
1701                 st = LDNS_STATUS_MEM_ERR;
1702
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;
1708
1709         } else {
1710                 if (sha384)
1711                         ldns_sha384_final( ldns_rdf_data(ldns_rr_rdf(sha384,3))
1712                                          , &zd->sha384_CTX);
1713                 if (sha512)
1714                         ldns_sha512_final( ldns_rdf_data(ldns_rr_rdf(sha512,3))
1715                                          , &zd->sha512_CTX);
1716                 return rr_list;
1717         }
1718         if (ret_st)
1719                 *ret_st = st;
1720         if (sha384)
1721                 ldns_rr_free(sha384);
1722         if (sha512)
1723                 ldns_rr_free(sha512);
1724         if (rr_list)
1725                 ldns_rr_list_deep_free(rr_list);
1726         return NULL;
1727 }
1728
1729 static ldns_status
1730 ldns_digest_zone(ldns_dnssec_zone *zone, zone_digester *zd)
1731 {
1732         ldns_status st = LDNS_STATUS_OK;
1733         dnssec_zone_rr_iter rr_iter;
1734         ldns_rr *rr;
1735         ldns_rdf *apex_name; /* name of zone apex */
1736
1737         if (!zone || !zd || !zone->soa || !zone->soa->name)
1738                 return LDNS_STATUS_NULL;
1739
1740         apex_name = zone->soa->name;
1741         for ( rr = dnssec_zone_rr_iter_first(&rr_iter, zone)
1742             ; rr && !st
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))
1747                         continue;
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))
1753                         continue;
1754                 st = zone_digester_update(zd, rr);
1755         }
1756         return st;
1757 }
1758
1759 ldns_status
1760 ldns_dnssec_zone_verify_zonemd(ldns_dnssec_zone *zone)
1761 {
1762         ldns_dnssec_rrsets *zonemd, *soa;
1763         zone_digester zd;
1764         ldns_dnssec_rrs *rrs;
1765         ldns_rr *soa_rr;
1766         ldns_status st;
1767         uint8_t simple_sha384[LDNS_SHA384_DIGEST_LENGTH];
1768         uint8_t simple_sha512[LDNS_SHA512_DIGEST_LENGTH];
1769         size_t valid_zonemds;
1770
1771         if (!zone)
1772                 return LDNS_STATUS_NULL;
1773
1774         zonemd = ldns_dnssec_zone_find_rrset(
1775                         zone, zone->soa->name, LDNS_RR_TYPE_ZONEMD);
1776         if (!zonemd) {
1777                 ldns_rbnode_t *nsec3_node;
1778
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(
1782                                                         zone->soa->nsec),
1783                                                 LDNS_RR_TYPE_ZONEMD))
1784                                 return LDNS_STATUS_NO_ZONEMD;
1785
1786                 } else if (!zone->soa->hashed_name || !zone->hashed_names)
1787                         return LDNS_STATUS_NO_ZONEMD;
1788
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;
1793                 else {
1794                         ldns_dnssec_name *nsec3
1795                                 = (ldns_dnssec_name *)nsec3_node->data;
1796                         if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(
1797                                                         nsec3->nsec),
1798                                                 LDNS_RR_TYPE_ZONEMD))
1799                                 return LDNS_STATUS_NO_ZONEMD;
1800                 }
1801                 /* ZONEMD at apex does really not exist */
1802                 return LDNS_STATUS_OK;
1803         }
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;
1808
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;
1813
1814         zone_digester_init(&zd);
1815         for (rrs = zonemd->rrs; rrs; rrs = rrs->next) {
1816                 if (!rrs->rr
1817                 ||  ldns_rr_get_type(rrs->rr) != LDNS_RR_TYPE_ZONEMD
1818                 ||  ldns_rr_rd_count(rrs->rr) < 4)
1819                         continue;
1820
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)))
1824                         continue;
1825                 
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)));
1830         }
1831         if (!zone_digester_set(&zd))
1832                 return LDNS_STATUS_NO_VALID_ZONEMD;
1833
1834         if ((st = ldns_digest_zone(zone, &zd)))
1835                 return st;
1836
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);
1841
1842         valid_zonemds = 0;
1843         for (rrs = zonemd->rrs; rrs; rrs = rrs->next) {
1844                 if (!rrs->rr
1845                 ||  ldns_rr_get_type(rrs->rr) != LDNS_RR_TYPE_ZONEMD
1846                 ||  ldns_rr_rd_count(rrs->rr) < 4)
1847                         continue;
1848
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)))
1852                         continue;
1853                 
1854                 if (ZONEMD_SCHEME_SIMPLE !=
1855                                 ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr, 1)))
1856                         continue;
1857
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)
1865
1866                         valid_zonemds += 1;
1867
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)
1875
1876                         valid_zonemds += 1;
1877         }
1878         return valid_zonemds ? LDNS_STATUS_OK : LDNS_STATUS_NO_VALID_ZONEMD;
1879 }
1880
1881 #ifdef HAVE_SSL
1882 static ldns_status
1883 rr_list2dnssec_rrs(ldns_rr_list *rr_list, ldns_dnssec_rrs **rrs,
1884                 ldns_rr_list *new_rrs)
1885 {
1886         ldns_rr *rr = NULL;
1887
1888         if (!rr_list || !rrs)
1889                 return LDNS_STATUS_NULL;
1890
1891         if (ldns_rr_list_rr_count(rr_list) == 0)
1892                 return LDNS_STATUS_OK;
1893
1894         if (!*rrs) {
1895                 if (!(*rrs = ldns_dnssec_rrs_new()))
1896                         return LDNS_STATUS_MEM_ERR;
1897                 (*rrs)->rr = ldns_rr_list_pop_rr(rr_list);
1898                 if (new_rrs)
1899                         ldns_rr_list_push_rr(new_rrs, (*rrs)->rr);
1900         }
1901         while ((rr = ldns_rr_list_pop_rr(rr_list))) {
1902                 ldns_status st;
1903                
1904                 if ((st = ldns_dnssec_rrs_add_rr(*rrs, rr))) {
1905                         ldns_rr_list_push_rr(rr_list, rr);
1906                         return st;
1907                 } else if (new_rrs)
1908                         ldns_rr_list_push_rr(new_rrs, rr);
1909         }
1910         return LDNS_STATUS_OK;
1911 }
1912
1913
1914 ldns_status
1915 dnssec_zone_equip_zonemd(ldns_dnssec_zone *zone,
1916                 ldns_rr_list *new_rrs, ldns_key_list *key_list, int signflags)
1917 {
1918         ldns_status st = LDNS_STATUS_OK;
1919         zone_digester zd;
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;
1926
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);
1931
1932         if (signflags & LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA512)
1933                 zone_digester_add(&zd, ZONEMD_SCHEME_SIMPLE
1934                                      , ZONEMD_HASH_SHA512);
1935
1936         if ((st = ldns_digest_zone(zone, &zd)))
1937                 return st;
1938
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;
1944
1945         if (!(zonemd_rr_list = zone_digester_export(&zd, soa_rr, &st)))
1946                 return st;
1947         
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;
1959         } else {
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;
1965                 }
1966                 zonemd_rrset->type = LDNS_RR_TYPE_ZONEMD;
1967                 zonemd_rrset->next = *rrset_ref;
1968                 *rrset_ref = zonemd_rrset;
1969         }
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);
1973         if (!st)
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);
1978         return st;
1979 }
1980
1981 #endif /* HAVE_SSL */
1982