xref: /dragonfly/contrib/ldns/dnssec_zone.c (revision 7733acb50455a11cc2ee36edd926ff0fa3361e9a)
1 /*
2  * special zone file structures and functions for better dnssec handling
3  */
4 
5 #include <ldns/config.h>
6 
7 #include <ldns/ldns.h>
8 
9 ldns_dnssec_rrs *
ldns_dnssec_rrs_new(void)10 ldns_dnssec_rrs_new(void)
11 {
12           ldns_dnssec_rrs *new_rrs;
13           new_rrs = LDNS_MALLOC(ldns_dnssec_rrs);
14         if(!new_rrs) return NULL;
15           new_rrs->rr = NULL;
16           new_rrs->next = NULL;
17           return new_rrs;
18 }
19 
20 INLINE void
ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs * rrs,int deep)21 ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep)
22 {
23           ldns_dnssec_rrs *next;
24           while (rrs) {
25                     next = rrs->next;
26                     if (deep) {
27                               ldns_rr_free(rrs->rr);
28                     }
29                     LDNS_FREE(rrs);
30                     rrs = next;
31           }
32 }
33 
34 void
ldns_dnssec_rrs_free(ldns_dnssec_rrs * rrs)35 ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs)
36 {
37           ldns_dnssec_rrs_free_internal(rrs, 0);
38 }
39 
40 void
ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs * rrs)41 ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs)
42 {
43           ldns_dnssec_rrs_free_internal(rrs, 1);
44 }
45 
46 ldns_status
ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs * rrs,ldns_rr * rr)47 ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr)
48 {
49           int cmp;
50           ldns_dnssec_rrs *new_rrs;
51           if (!rrs || !rr) {
52                     return LDNS_STATUS_ERR;
53           }
54 
55           /* this could be done more efficiently; name and type should already
56              be equal */
57           cmp = ldns_rr_compare(rrs->rr, rr);
58           if (cmp < 0) {
59                     if (rrs->next) {
60                               return ldns_dnssec_rrs_add_rr(rrs->next, rr);
61                     } else {
62                               new_rrs = ldns_dnssec_rrs_new();
63                               new_rrs->rr = rr;
64                               rrs->next = new_rrs;
65                     }
66           } else if (cmp > 0) {
67                     /* put the current old rr in the new next, put the new
68                        rr in the current container */
69                     new_rrs = ldns_dnssec_rrs_new();
70                     new_rrs->rr = rrs->rr;
71                     new_rrs->next = rrs->next;
72                     rrs->rr = rr;
73                     rrs->next = new_rrs;
74           }
75           /* Silently ignore equal rr's */
76           return LDNS_STATUS_OK;
77 }
78 
79 void
ldns_dnssec_rrs_print_fmt(FILE * out,const ldns_output_format * fmt,const ldns_dnssec_rrs * rrs)80 ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt,
81                  const ldns_dnssec_rrs *rrs)
82 {
83           if (!rrs) {
84                     if ((fmt->flags & LDNS_COMMENT_LAYOUT))
85                               fprintf(out, "; <void>");
86           } else {
87                     if (rrs->rr) {
88                               ldns_rr_print_fmt(out, fmt, rrs->rr);
89                     }
90                     if (rrs->next) {
91                               ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next);
92                     }
93           }
94 }
95 
96 void
ldns_dnssec_rrs_print(FILE * out,const ldns_dnssec_rrs * rrs)97 ldns_dnssec_rrs_print(FILE *out, const ldns_dnssec_rrs *rrs)
98 {
99           ldns_dnssec_rrs_print_fmt(out, ldns_output_format_default, rrs);
100 }
101 
102 
103 ldns_dnssec_rrsets *
ldns_dnssec_rrsets_new(void)104 ldns_dnssec_rrsets_new(void)
105 {
106           ldns_dnssec_rrsets *new_rrsets;
107           new_rrsets = LDNS_MALLOC(ldns_dnssec_rrsets);
108         if(!new_rrsets) return NULL;
109           new_rrsets->rrs = NULL;
110           new_rrsets->type = 0;
111           new_rrsets->signatures = NULL;
112           new_rrsets->next = NULL;
113           return new_rrsets;
114 }
115 
116 INLINE void
ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets * rrsets,int deep)117 ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep)
118 {
119           if (rrsets) {
120                     if (rrsets->rrs) {
121                               ldns_dnssec_rrs_free_internal(rrsets->rrs, deep);
122                     }
123                     if (rrsets->next) {
124                               ldns_dnssec_rrsets_free_internal(rrsets->next, deep);
125                     }
126                     if (rrsets->signatures) {
127                               ldns_dnssec_rrs_free_internal(rrsets->signatures, deep);
128                     }
129                     LDNS_FREE(rrsets);
130           }
131 }
132 
133 void
ldns_dnssec_rrsets_free(ldns_dnssec_rrsets * rrsets)134 ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets)
135 {
136           ldns_dnssec_rrsets_free_internal(rrsets, 0);
137 }
138 
139 void
ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets * rrsets)140 ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets)
141 {
142           ldns_dnssec_rrsets_free_internal(rrsets, 1);
143 }
144 
145 ldns_rr_type
ldns_dnssec_rrsets_type(const ldns_dnssec_rrsets * rrsets)146 ldns_dnssec_rrsets_type(const ldns_dnssec_rrsets *rrsets)
147 {
148           if (rrsets) {
149                     return rrsets->type;
150           } else {
151                     return 0;
152           }
153 }
154 
155 ldns_status
ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets * rrsets,ldns_rr_type type)156 ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets,
157                                                      ldns_rr_type type)
158 {
159           if (rrsets) {
160                     rrsets->type = type;
161                     return LDNS_STATUS_OK;
162           }
163           return LDNS_STATUS_ERR;
164 }
165 
166 static ldns_dnssec_rrsets *
ldns_dnssec_rrsets_new_frm_rr(ldns_rr * rr)167 ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr)
168 {
169           ldns_dnssec_rrsets *new_rrsets;
170           ldns_rr_type rr_type;
171           bool rrsig;
172 
173           new_rrsets = ldns_dnssec_rrsets_new();
174           rr_type = ldns_rr_get_type(rr);
175           if (rr_type == LDNS_RR_TYPE_RRSIG) {
176                     rrsig = true;
177                     rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
178           } else {
179                     rrsig = false;
180           }
181           if (!rrsig) {
182                     new_rrsets->rrs = ldns_dnssec_rrs_new();
183                     new_rrsets->rrs->rr = rr;
184           } else {
185                     new_rrsets->signatures = ldns_dnssec_rrs_new();
186                     new_rrsets->signatures->rr = rr;
187           }
188           new_rrsets->type = rr_type;
189           return new_rrsets;
190 }
191 
192 ldns_status
ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets * rrsets,ldns_rr * rr)193 ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr)
194 {
195           ldns_dnssec_rrsets *new_rrsets;
196           ldns_rr_type rr_type;
197           bool rrsig = false;
198           ldns_status result = LDNS_STATUS_OK;
199 
200           if (!rrsets || !rr) {
201                     return LDNS_STATUS_ERR;
202           }
203 
204           rr_type = ldns_rr_get_type(rr);
205 
206           if (rr_type == LDNS_RR_TYPE_RRSIG) {
207                     rrsig = true;
208                     rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
209           }
210 
211           if (!rrsets->rrs && rrsets->type == 0 && !rrsets->signatures) {
212                     if (!rrsig) {
213                               rrsets->rrs = ldns_dnssec_rrs_new();
214                               rrsets->rrs->rr = rr;
215                               rrsets->type = rr_type;
216                     } else {
217                               rrsets->signatures = ldns_dnssec_rrs_new();
218                               rrsets->signatures->rr = rr;
219                               rrsets->type = rr_type;
220                     }
221                     return LDNS_STATUS_OK;
222           }
223 
224           if (rr_type > ldns_dnssec_rrsets_type(rrsets)) {
225                     if (rrsets->next) {
226                               result = ldns_dnssec_rrsets_add_rr(rrsets->next, rr);
227                     } else {
228                               new_rrsets = ldns_dnssec_rrsets_new_frm_rr(rr);
229                               rrsets->next = new_rrsets;
230                     }
231           } else if (rr_type < ldns_dnssec_rrsets_type(rrsets)) {
232                     /* move the current one into the new next,
233                        replace field of current with data from new rr */
234                     new_rrsets = ldns_dnssec_rrsets_new();
235                     new_rrsets->rrs = rrsets->rrs;
236                     new_rrsets->type = rrsets->type;
237                     new_rrsets->signatures = rrsets->signatures;
238                     new_rrsets->next = rrsets->next;
239                     if (!rrsig) {
240                               rrsets->rrs = ldns_dnssec_rrs_new();
241                               rrsets->rrs->rr = rr;
242                               rrsets->signatures = NULL;
243                     } else {
244                               rrsets->rrs = NULL;
245                               rrsets->signatures = ldns_dnssec_rrs_new();
246                               rrsets->signatures->rr = rr;
247                     }
248                     rrsets->type = rr_type;
249                     rrsets->next = new_rrsets;
250           } else {
251                     /* equal, add to current rrsets */
252                     if (rrsig) {
253                               if (rrsets->signatures) {
254                                         result = ldns_dnssec_rrs_add_rr(rrsets->signatures, rr);
255                               } else {
256                                         rrsets->signatures = ldns_dnssec_rrs_new();
257                                         rrsets->signatures->rr = rr;
258                               }
259                     } else {
260                               if (rrsets->rrs) {
261                                         result = ldns_dnssec_rrs_add_rr(rrsets->rrs, rr);
262                               } else {
263                                         rrsets->rrs = ldns_dnssec_rrs_new();
264                                         rrsets->rrs->rr = rr;
265                               }
266                     }
267           }
268 
269           return result;
270 }
271 
272 static void
ldns_dnssec_rrsets_print_soa_fmt(FILE * out,const ldns_output_format * fmt,const ldns_dnssec_rrsets * rrsets,bool follow,bool show_soa)273 ldns_dnssec_rrsets_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
274                     const ldns_dnssec_rrsets *rrsets,
275                     bool follow,
276                     bool show_soa)
277 {
278           if (!rrsets) {
279                     if ((fmt->flags & LDNS_COMMENT_LAYOUT))
280                               fprintf(out, "; <void>\n");
281           } else {
282                     if (rrsets->rrs &&
283                         (show_soa ||
284                               ldns_rr_get_type(rrsets->rrs->rr) != LDNS_RR_TYPE_SOA
285                         )
286                        ) {
287                               ldns_dnssec_rrs_print_fmt(out, fmt, rrsets->rrs);
288                               if (rrsets->signatures) {
289                                         ldns_dnssec_rrs_print_fmt(out, fmt,
290                                                             rrsets->signatures);
291                               }
292                     }
293                     if (follow && rrsets->next) {
294                               ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
295                                                   rrsets->next, follow, show_soa);
296                     }
297           }
298 }
299 
300 
301 void
ldns_dnssec_rrsets_print_fmt(FILE * out,const ldns_output_format * fmt,const ldns_dnssec_rrsets * rrsets,bool follow)302 ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt,
303                     const ldns_dnssec_rrsets *rrsets,
304                     bool follow)
305 {
306           ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true);
307 }
308 
309 void
ldns_dnssec_rrsets_print(FILE * out,const ldns_dnssec_rrsets * rrsets,bool follow)310 ldns_dnssec_rrsets_print(FILE *out, const ldns_dnssec_rrsets *rrsets, bool follow)
311 {
312           ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default,
313                               rrsets, follow);
314 }
315 
316 ldns_dnssec_name *
ldns_dnssec_name_new(void)317 ldns_dnssec_name_new(void)
318 {
319           ldns_dnssec_name *new_name;
320 
321           new_name = LDNS_CALLOC(ldns_dnssec_name, 1);
322           if (!new_name) {
323                     return NULL;
324           }
325           /*
326            * not needed anymore because CALLOC initializes everything to zero.
327 
328           new_name->name = NULL;
329           new_name->rrsets = NULL;
330           new_name->name_alloced = false;
331           new_name->nsec = NULL;
332           new_name->nsec_signatures = NULL;
333 
334           new_name->is_glue = false;
335           new_name->hashed_name = NULL;
336 
337            */
338           return new_name;
339 }
340 
341 ldns_dnssec_name *
ldns_dnssec_name_new_frm_rr(ldns_rr * rr)342 ldns_dnssec_name_new_frm_rr(ldns_rr *rr)
343 {
344           ldns_dnssec_name *new_name = ldns_dnssec_name_new();
345 
346           new_name->name = ldns_rr_owner(rr);
347           if(ldns_dnssec_name_add_rr(new_name, rr) != LDNS_STATUS_OK) {
348                     ldns_dnssec_name_free(new_name);
349                     return NULL;
350           }
351 
352           return new_name;
353 }
354 
355 INLINE void
ldns_dnssec_name_free_internal(ldns_dnssec_name * name,int deep)356 ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
357                                int deep)
358 {
359           if (name) {
360                     if (name->name_alloced) {
361                               ldns_rdf_deep_free(name->name);
362                     }
363                     if (name->rrsets) {
364                               ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
365                     }
366                     if (name->nsec && deep) {
367                               ldns_rr_free(name->nsec);
368                     }
369                     if (name->nsec_signatures) {
370                               ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
371                     }
372                     if (name->hashed_name) {
373                               /* Hashed name is always allocated when signing,
374                                * so always deep free
375                                */
376                               ldns_rdf_deep_free(name->hashed_name);
377                     }
378                     LDNS_FREE(name);
379           }
380 }
381 
382 void
ldns_dnssec_name_free(ldns_dnssec_name * name)383 ldns_dnssec_name_free(ldns_dnssec_name *name)
384 {
385   ldns_dnssec_name_free_internal(name, 0);
386 }
387 
388 void
ldns_dnssec_name_deep_free(ldns_dnssec_name * name)389 ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
390 {
391   ldns_dnssec_name_free_internal(name, 1);
392 }
393 
394 ldns_rdf *
ldns_dnssec_name_name(const ldns_dnssec_name * name)395 ldns_dnssec_name_name(const ldns_dnssec_name *name)
396 {
397           if (name) {
398                     return name->name;
399           }
400           return NULL;
401 }
402 
403 bool
ldns_dnssec_name_is_glue(const ldns_dnssec_name * name)404 ldns_dnssec_name_is_glue(const ldns_dnssec_name *name)
405 {
406           if (name) {
407                     return name->is_glue;
408           }
409           return false;
410 }
411 
412 void
ldns_dnssec_name_set_name(ldns_dnssec_name * rrset,ldns_rdf * dname)413 ldns_dnssec_name_set_name(ldns_dnssec_name *rrset,
414                                                    ldns_rdf *dname)
415 {
416           if (rrset && dname) {
417                     rrset->name = dname;
418           }
419 }
420 
421 
422 void
ldns_dnssec_name_set_nsec(ldns_dnssec_name * rrset,ldns_rr * nsec)423 ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec)
424 {
425           if (rrset && nsec) {
426                     rrset->nsec = nsec;
427           }
428 }
429 
430 int
ldns_dnssec_name_cmp(const void * a,const void * b)431 ldns_dnssec_name_cmp(const void *a, const void *b)
432 {
433           ldns_dnssec_name *na = (ldns_dnssec_name *) a;
434           ldns_dnssec_name *nb = (ldns_dnssec_name *) b;
435 
436           if (na && nb) {
437                     return ldns_dname_compare(ldns_dnssec_name_name(na),
438                                                                        ldns_dnssec_name_name(nb));
439           } else if (na) {
440                     return 1;
441           } else if (nb) {
442                     return -1;
443           } else {
444                     return 0;
445           }
446 }
447 
448 ldns_status
ldns_dnssec_name_add_rr(ldns_dnssec_name * name,ldns_rr * rr)449 ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
450                                             ldns_rr *rr)
451 {
452           ldns_status result = LDNS_STATUS_OK;
453           ldns_rr_type rr_type;
454           ldns_rr_type typecovered = 0;
455 
456           /* special handling for NSEC3 and NSECX covering RRSIGS */
457 
458           if (!name || !rr) {
459                     return LDNS_STATUS_ERR;
460           }
461 
462           rr_type = ldns_rr_get_type(rr);
463 
464           if (rr_type == LDNS_RR_TYPE_RRSIG) {
465                     typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
466           }
467 
468           if (rr_type == LDNS_RR_TYPE_NSEC ||
469               rr_type == LDNS_RR_TYPE_NSEC3) {
470                     /* XX check if is already set (and error?) */
471                     name->nsec = rr;
472           } else if (typecovered == LDNS_RR_TYPE_NSEC ||
473                                typecovered == LDNS_RR_TYPE_NSEC3) {
474                     if (name->nsec_signatures) {
475                               result = ldns_dnssec_rrs_add_rr(name->nsec_signatures, rr);
476                     } else {
477                               name->nsec_signatures = ldns_dnssec_rrs_new();
478                               name->nsec_signatures->rr = rr;
479                     }
480           } else {
481                     /* it's a 'normal' RR, add it to the right rrset */
482                     if (name->rrsets) {
483                               result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
484                     } else {
485                               name->rrsets = ldns_dnssec_rrsets_new();
486                               result = ldns_dnssec_rrsets_add_rr(name->rrsets, rr);
487                     }
488           }
489           return result;
490 }
491 
492 ldns_dnssec_rrsets *
ldns_dnssec_name_find_rrset(const ldns_dnssec_name * name,ldns_rr_type type)493 ldns_dnssec_name_find_rrset(const ldns_dnssec_name *name,
494                                                      ldns_rr_type type) {
495           ldns_dnssec_rrsets *result;
496 
497           result = name->rrsets;
498           while (result) {
499                     if (result->type == type) {
500                               return result;
501                     } else {
502                               result = result->next;
503                     }
504           }
505           return NULL;
506 }
507 
508 ldns_dnssec_rrsets *
ldns_dnssec_zone_find_rrset(const ldns_dnssec_zone * zone,const ldns_rdf * dname,ldns_rr_type type)509 ldns_dnssec_zone_find_rrset(const ldns_dnssec_zone *zone,
510                                                      const ldns_rdf *dname,
511                                                      ldns_rr_type type)
512 {
513           ldns_rbnode_t *node;
514 
515           if (!zone || !dname || !zone->names) {
516                     return NULL;
517           }
518 
519           node = ldns_rbtree_search(zone->names, dname);
520           if (node) {
521                     return ldns_dnssec_name_find_rrset((ldns_dnssec_name *)node->data,
522                                                                                           type);
523           } else {
524                     return NULL;
525           }
526 }
527 
528 static void
ldns_dnssec_name_print_soa_fmt(FILE * out,const ldns_output_format * fmt,const ldns_dnssec_name * name,bool show_soa)529 ldns_dnssec_name_print_soa_fmt(FILE *out, const ldns_output_format *fmt,
530                     const ldns_dnssec_name *name,
531                     bool show_soa)
532 {
533           if (name) {
534                     if(name->rrsets) {
535                               ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
536                                                   name->rrsets, true, show_soa);
537                     } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
538                               fprintf(out, ";; Empty nonterminal: ");
539                               ldns_rdf_print(out, name->name);
540                               fprintf(out, "\n");
541                     }
542                     if(name->nsec) {
543                               ldns_rr_print_fmt(out, fmt, name->nsec);
544                     }
545                     if (name->nsec_signatures) {
546                               ldns_dnssec_rrs_print_fmt(out, fmt,
547                                                   name->nsec_signatures);
548                     }
549           } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
550                     fprintf(out, "; <void>\n");
551           }
552 }
553 
554 
555 void
ldns_dnssec_name_print_fmt(FILE * out,const ldns_output_format * fmt,const ldns_dnssec_name * name)556 ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt,
557                     const ldns_dnssec_name *name)
558 {
559           ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
560 }
561 
562 void
ldns_dnssec_name_print(FILE * out,const ldns_dnssec_name * name)563 ldns_dnssec_name_print(FILE *out, const ldns_dnssec_name *name)
564 {
565           ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name);
566 }
567 
568 
569 ldns_dnssec_zone *
ldns_dnssec_zone_new(void)570 ldns_dnssec_zone_new(void)
571 {
572           ldns_dnssec_zone *zone = LDNS_MALLOC(ldns_dnssec_zone);
573         if(!zone) return NULL;
574           zone->soa = NULL;
575           zone->names = NULL;
576           zone->hashed_names = NULL;
577           zone->_nsec3params = NULL;
578 
579           return zone;
580 }
581 
582 static bool
rr_is_rrsig_covering(ldns_rr * rr,ldns_rr_type t)583 rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
584 {
585           return     ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
586                     && ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t;
587 }
588 
589 /* When the zone is first read into an list and then inserted into an
590  * ldns_dnssec_zone (rbtree) the nodes of the rbtree are allocated close (next)
591  * to each other. Because ldns-verify-zone (the only program that uses this
592  * function) uses the rbtree mostly for sequential walking, this results
593  * in a speed increase (of 15% on linux) because we have less CPU-cache misses.
594  */
595 #define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
596 
597 static ldns_status
598 ldns_dnssec_zone_add_empty_nonterminals_nsec3(
599                     ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s);
600 
601 static void
ldns_todo_nsec3_ents_node_free(ldns_rbnode_t * node,void * arg)602 ldns_todo_nsec3_ents_node_free(ldns_rbnode_t *node, void *arg) {
603           (void) arg;
604           ldns_rdf_deep_free((ldns_rdf *)node->key);
605           LDNS_FREE(node);
606 }
607 
608 ldns_status _ldns_rr_new_frm_fp_l_internal(ldns_rr **newrr, FILE *fp,
609                     uint32_t *default_ttl, ldns_rdf **origin, ldns_rdf **prev,
610                     int *line_nr, bool *explicit_ttl);
611 
612 ldns_status
ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone ** z,FILE * fp,const ldns_rdf * origin,uint32_t default_ttl,ldns_rr_class ATTR_UNUSED (c),int * line_nr)613 ldns_dnssec_zone_new_frm_fp_l(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* origin,
614                     uint32_t default_ttl, ldns_rr_class ATTR_UNUSED(c), int* line_nr)
615 {
616           ldns_rr* cur_rr;
617           size_t i;
618 
619           ldns_rdf *my_origin = NULL;
620           ldns_rdf *my_prev = NULL;
621 
622           ldns_dnssec_zone *newzone = ldns_dnssec_zone_new();
623           /* NSEC3s may occur before the names they refer to. We must remember
624              them and add them to the name later on, after the name is read.
625              We track not yet  matching NSEC3s*n the todo_nsec3s list */
626           ldns_rr_list* todo_nsec3s = ldns_rr_list_new();
627           /* when reading NSEC3s, there is a chance that we encounter nsecs
628              for empty nonterminals, whose nonterminals we cannot derive yet
629              because the needed information is to be read later.
630 
631              nsec3_ents (where ent is e.n.t.; i.e. empty non terminal) will
632              hold the NSEC3s that still didn't have a matching name in the
633              zone tree, even after all names were read.  They can only match
634              after the zone is equipped with all the empty non terminals. */
635           ldns_rbtree_t todo_nsec3_ents;
636           ldns_rbnode_t *new_node;
637           ldns_rr_list* todo_nsec3_rrsigs = ldns_rr_list_new();
638 
639           ldns_status status;
640 
641 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
642           ldns_zone* zone = NULL;
643 #else
644           ldns_rr  *prev_rr = NULL;
645           uint32_t   my_ttl = default_ttl;
646           /* RFC 1035 Section 5.1, says 'Omitted class and TTL values are default
647            * to the last explicitly stated values.'
648            */
649           bool ttl_from_TTL = false;
650           bool explicit_ttl = false;
651 #endif
652 
653           ldns_rbtree_init(&todo_nsec3_ents, ldns_dname_compare_v);
654 
655 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
656           status = ldns_zone_new_frm_fp_l(&zone, fp, origin, default_ttl, c, line_nr);
657           if (status != LDNS_STATUS_OK)
658                     goto error;
659 #endif
660           if (!newzone || !todo_nsec3s || !todo_nsec3_rrsigs ) {
661                     status = LDNS_STATUS_MEM_ERR;
662                     goto error;
663           }
664           if (origin) {
665                     if (!(my_origin = ldns_rdf_clone(origin))) {
666                               status = LDNS_STATUS_MEM_ERR;
667                               goto error;
668                     }
669                     if (!(my_prev   = ldns_rdf_clone(origin))) {
670                               status = LDNS_STATUS_MEM_ERR;
671                               goto error;
672                     }
673           }
674 
675 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
676           if (ldns_zone_soa(zone)) {
677                     status = ldns_dnssec_zone_add_rr(newzone, ldns_zone_soa(zone));
678                     if (status != LDNS_STATUS_OK)
679                               goto error;
680           }
681           for (i = 0; i < ldns_rr_list_rr_count(ldns_zone_rrs(zone)); i++) {
682                     cur_rr = ldns_rr_list_rr(ldns_zone_rrs(zone), i);
683                     status = LDNS_STATUS_OK;
684 #else
685           while (!feof(fp)) {
686                     /* If ttl came from $TTL line, then it should be the default.
687                      * (RFC 2308 Section 4)
688                      * Otherwise it "defaults to the last explicitly stated value"
689                      * (RFC 1035 Section 5.1)
690                      */
691                     if (ttl_from_TTL)
692                               my_ttl = default_ttl;
693                     status = ldns_rr_new_frm_fp_l(&cur_rr, fp, &my_ttl, &my_origin,
694                                         &my_prev, line_nr, &explicit_ttl);
695 #endif
696                     switch (status) {
697                     case LDNS_STATUS_OK:
698 #ifndef FASTER_DNSSEC_ZONE_NEW_FRM_FP
699                               if (explicit_ttl) {
700                                         if (!ttl_from_TTL) {
701                                                   /* No $TTL, so ttl "defaults to the
702                                                    * last explicitly stated value"
703                                                    * (RFC 1035 Section 5.1)
704                                                    */
705                                                   my_ttl = ldns_rr_ttl(cur_rr);
706                                         }
707                               /* When ttl is implicit, try to adhere to the rules as
708                                * much as possible. (also for compatibility with bind)
709                                * This was changed when fixing an issue with ZONEMD
710                                * which hashes the TTL too.
711                                */
712                               } else if (ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_SIG
713                                      ||  ldns_rr_get_type(cur_rr) == LDNS_RR_TYPE_RRSIG) {
714                                         if (ldns_rr_rd_count(cur_rr) >= 4
715                                         &&  ldns_rdf_get_type(ldns_rr_rdf(cur_rr, 3)) == LDNS_RDF_TYPE_INT32)
716 
717                                                   /* SIG without explicit ttl get ttl
718                                                    * from the original_ttl field
719                                                    * (RFC 2535 Section 7.2)
720                                                    *
721                                                    * Similarly for RRSIG, but stated less
722                                                    * specifically in the spec.
723                                                    * (RFC 4034 Section 3)
724                                                    */
725                                                   ldns_rr_set_ttl(cur_rr,
726                                                       ldns_rdf2native_int32(
727                                                           ldns_rr_rdf(rr, 3)));
728 
729                               } else if (prev_rr
730                                      &&  ldns_rr_get_type(prev_rr) == ldns_rr_get_type(cur_rr)
731                                      &&  ldns_dname_compare( ldns_rr_owner(prev_rr)
732                                                            , ldns_rr_owner(cur_rr)) == 0)
733 
734                                         /* "TTLs of all RRs in an RRSet must be the same"
735                                          * (RFC 2881 Section 5.2)
736                                          */
737                                         ldns_rr_set_ttl(cur_rr, ldns_rr_ttl(prev_rr));
738 
739                               prev_rr = cur_rr;
740 #endif
741                               status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
742                               if (status ==
743                                         LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
744 
745                                         if (rr_is_rrsig_covering(cur_rr,
746                                                                       LDNS_RR_TYPE_NSEC3)){
747                                                   ldns_rr_list_push_rr(todo_nsec3_rrsigs,
748                                                                       cur_rr);
749                                         } else {
750                                                   ldns_rr_list_push_rr(todo_nsec3s,
751                                                                       cur_rr);
752                                         }
753                                         status = LDNS_STATUS_OK;
754 
755                               } else if (status != LDNS_STATUS_OK)
756                                         goto error;
757 
758                               break;
759 
760                     case LDNS_STATUS_SYNTAX_TTL:  /* the ttl was set*/
761 #ifndef FASTER_DNSSEC_ZONE_NEW_FRM_FP
762                               default_ttl = my_ttl;
763                               ttl_from_TTL = true;
764 #endif
765                               status = LDNS_STATUS_OK;
766                               break;
767 
768 
769                     case LDNS_STATUS_SYNTAX_EMPTY:          /* empty line was seen */
770                     case LDNS_STATUS_SYNTAX_ORIGIN:         /* the origin was set*/
771                               status = LDNS_STATUS_OK;
772                               break;
773 
774                     case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
775                               status =  LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
776                               break;
777 
778                     default:
779                               goto error;
780                     }
781           }
782 
783           for (i = 0; status == LDNS_STATUS_OK &&
784                               i < ldns_rr_list_rr_count(todo_nsec3s); i++) {
785                     cur_rr = ldns_rr_list_rr(todo_nsec3s, i);
786                     status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
787                     if (status == LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND) {
788                               if (!(new_node = LDNS_MALLOC(ldns_rbnode_t))) {
789                                         status = LDNS_STATUS_MEM_ERR;
790                                         break;
791                               }
792                               new_node->key  = ldns_dname_label(ldns_rr_owner(cur_rr), 0);
793                               new_node->data = cur_rr;
794                               if (!ldns_rbtree_insert(&todo_nsec3_ents, new_node)) {
795                                         LDNS_FREE(new_node);
796                                         status = LDNS_STATUS_MEM_ERR;
797                                         break;
798                               }
799                               status = LDNS_STATUS_OK;
800                     }
801           }
802           if (todo_nsec3_ents.count > 0)
803                     (void) ldns_dnssec_zone_add_empty_nonterminals_nsec3(
804                                         newzone, &todo_nsec3_ents);
805           for (i = 0; status == LDNS_STATUS_OK &&
806                               i < ldns_rr_list_rr_count(todo_nsec3_rrsigs); i++) {
807                     cur_rr = ldns_rr_list_rr(todo_nsec3_rrsigs, i);
808                     status = ldns_dnssec_zone_add_rr(newzone, cur_rr);
809           }
810           if (z) {
811                     *z = newzone;
812                     newzone = NULL;
813           } else {
814                     ldns_dnssec_zone_free(newzone);
815                     newzone = NULL;
816           }
817 
818 error:
819 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
820           if (zone) {
821                     ldns_zone_free(zone);
822           }
823 #endif
824           ldns_rr_list_free(todo_nsec3_rrsigs);
825           ldns_traverse_postorder(&todo_nsec3_ents,
826                               ldns_todo_nsec3_ents_node_free, NULL);
827           ldns_rr_list_free(todo_nsec3s);
828 
829           if (my_origin) {
830                     ldns_rdf_deep_free(my_origin);
831           }
832           if (my_prev) {
833                     ldns_rdf_deep_free(my_prev);
834           }
835           if (newzone) {
836                     ldns_dnssec_zone_free(newzone);
837           }
838           return status;
839 }
840 
841 ldns_status
842 ldns_dnssec_zone_new_frm_fp(ldns_dnssec_zone** z, FILE* fp, const ldns_rdf* origin,
843                     uint32_t ttl, ldns_rr_class ATTR_UNUSED(c))
844 {
845           return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
846 }
847 
848 static void
849 ldns_dnssec_name_node_free(ldns_rbnode_t *node, void *arg) {
850           (void) arg;
851           ldns_dnssec_name_free((ldns_dnssec_name *)node->data);
852           LDNS_FREE(node);
853 }
854 
855 static void
856 ldns_dnssec_name_node_deep_free(ldns_rbnode_t *node, void *arg) {
857           (void) arg;
858           ldns_dnssec_name_deep_free((ldns_dnssec_name *)node->data);
859           LDNS_FREE(node);
860 }
861 
862 static void
863 ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) {
864           (void) arg;
865           LDNS_FREE(node);
866 }
867 
868 void
869 ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
870 {
871           if (zone) {
872                     if (zone->hashed_names) {
873                               ldns_traverse_postorder(zone->hashed_names,
874                                                   ldns_hashed_names_node_free, NULL);
875                               LDNS_FREE(zone->hashed_names);
876                     }
877                     if (zone->names) {
878                               /* destroy all name structures within the tree */
879                               ldns_traverse_postorder(zone->names,
880                                                                 ldns_dnssec_name_node_free,
881                                                                 NULL);
882                               LDNS_FREE(zone->names);
883                     }
884                     LDNS_FREE(zone);
885           }
886 }
887 
888 void
889 ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
890 {
891           if (zone) {
892                     if (zone->hashed_names) {
893                               ldns_traverse_postorder(zone->hashed_names,
894                                                   ldns_hashed_names_node_free, NULL);
895                               LDNS_FREE(zone->hashed_names);
896                     }
897                     if (zone->names) {
898                               /* destroy all name structures within the tree */
899                               ldns_traverse_postorder(zone->names,
900                                                                 ldns_dnssec_name_node_deep_free,
901                                                                 NULL);
902                               LDNS_FREE(zone->names);
903                     }
904                     LDNS_FREE(zone);
905           }
906 }
907 
908 /* use for dname comparison in tree */
909 int
910 ldns_dname_compare_v(const void *a, const void *b) {
911           return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
912 }
913 
914 static void
915 ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
916                     ldns_dnssec_name* name, ldns_rr* nsec3rr);
917 
918 static void
919 ldns_dnssec_zone_hashed_names_from_nsec3(
920                     ldns_dnssec_zone* zone, ldns_rr* nsec3rr)
921 {
922           ldns_rbnode_t* current_node;
923           ldns_dnssec_name* current_name;
924 
925           assert(zone != NULL);
926           assert(nsec3rr != NULL);
927 
928           if (zone->hashed_names) {
929                     ldns_traverse_postorder(zone->hashed_names,
930                                         ldns_hashed_names_node_free, NULL);
931                     LDNS_FREE(zone->hashed_names);
932           }
933           zone->_nsec3params = nsec3rr;
934 
935           /* So this is a NSEC3 zone.
936           * Calculate hashes for all names already in the zone
937           */
938           zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v);
939           if (zone->hashed_names == NULL) {
940                     return;
941           }
942           for ( current_node  = ldns_rbtree_first(zone->names)
943               ; current_node != LDNS_RBTREE_NULL
944               ; current_node  = ldns_rbtree_next(current_node)
945               ) {
946                     current_name = (ldns_dnssec_name *) current_node->data;
947                     ldns_dnssec_name_make_hashed_name(zone, current_name, nsec3rr);
948 
949           }
950 }
951 
952 static void
953 ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
954                     ldns_dnssec_name* name, ldns_rr* nsec3rr)
955 {
956           ldns_rbnode_t* new_node;
957 
958           assert(name != NULL);
959           if (! zone->_nsec3params) {
960                     if (! nsec3rr) {
961                               return;
962                     }
963                     ldns_dnssec_zone_hashed_names_from_nsec3(zone, nsec3rr);
964 
965           } else if (! nsec3rr) {
966                     nsec3rr = zone->_nsec3params;
967           }
968           name->hashed_name = ldns_nsec3_hash_name_frm_nsec3(nsec3rr, name->name);
969 
970           /* Also store in zone->hashed_names */
971           if ((new_node = LDNS_MALLOC(ldns_rbnode_t))) {
972 
973                     new_node->key  = name->hashed_name;
974                     new_node->data = name;
975 
976                     if (ldns_rbtree_insert(zone->hashed_names, new_node) == NULL) {
977 
978                                         LDNS_FREE(new_node);
979                     }
980           }
981 }
982 
983 
984 static ldns_rbnode_t *
985 ldns_dnssec_zone_find_nsec3_original(ldns_dnssec_zone *zone, ldns_rr *rr) {
986           ldns_rdf *hashed_name;
987           ldns_rbnode_t *to_return;
988 
989           if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 && ! zone->_nsec3params){
990 
991                     ldns_dnssec_zone_hashed_names_from_nsec3(zone, rr);
992           }
993           if (zone->hashed_names == NULL) {
994                     return NULL;
995           }
996           hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
997           if (hashed_name == NULL) {
998                     return NULL;
999           }
1000           to_return = ldns_rbtree_search(zone->hashed_names, hashed_name);
1001           ldns_rdf_deep_free(hashed_name);
1002           return to_return;
1003 }
1004 
1005 ldns_status
1006 ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
1007 {
1008           ldns_status result = LDNS_STATUS_OK;
1009           ldns_dnssec_name *cur_name;
1010           ldns_rbnode_t *cur_node;
1011           ldns_rr_type type_covered = 0;
1012 
1013           if (!zone || !rr) {
1014                     return LDNS_STATUS_ERR;
1015           }
1016 
1017           if (!zone->names) {
1018                     zone->names = ldns_rbtree_create(ldns_dname_compare_v);
1019                 if(!zone->names) return LDNS_STATUS_MEM_ERR;
1020           }
1021 
1022           /* we need the original of the hashed name if this is
1023              an NSEC3, or an RRSIG that covers an NSEC3 */
1024           if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) {
1025                     type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
1026           }
1027           if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 ||
1028               type_covered == LDNS_RR_TYPE_NSEC3) {
1029                     cur_node = ldns_dnssec_zone_find_nsec3_original(zone, rr);
1030                     if (!cur_node) {
1031                               return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND;
1032                     }
1033           } else {
1034                     cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
1035           }
1036           if (!cur_node) {
1037                     /* add */
1038                     cur_name = ldns_dnssec_name_new_frm_rr(rr);
1039                 if(!cur_name) return LDNS_STATUS_MEM_ERR;
1040                     cur_node = LDNS_MALLOC(ldns_rbnode_t);
1041                 if(!cur_node) {
1042                         ldns_dnssec_name_free(cur_name);
1043                         return LDNS_STATUS_MEM_ERR;
1044                 }
1045                     cur_node->key = ldns_rr_owner(rr);
1046                     cur_node->data = cur_name;
1047                     (void)ldns_rbtree_insert(zone->names, cur_node);
1048                     ldns_dnssec_name_make_hashed_name(zone, cur_name, NULL);
1049           } else {
1050                     cur_name = (ldns_dnssec_name *) cur_node->data;
1051                     result = ldns_dnssec_name_add_rr(cur_name, rr);
1052           }
1053           if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
1054                     zone->soa = cur_name;
1055           }
1056           return result;
1057 }
1058 
1059 void
1060 ldns_dnssec_zone_names_print_fmt(FILE *out, const ldns_output_format *fmt,
1061                     const ldns_rbtree_t *tree,
1062                     bool print_soa)
1063 {
1064           ldns_rbnode_t *node;
1065           ldns_dnssec_name *name;
1066 
1067           node = ldns_rbtree_first(tree);
1068           while (node != LDNS_RBTREE_NULL) {
1069                     name = (ldns_dnssec_name *) node->data;
1070                     ldns_dnssec_name_print_soa_fmt(out, fmt, name, print_soa);
1071                     if ((fmt->flags & LDNS_COMMENT_LAYOUT))
1072                               fprintf(out, ";\n");
1073                     node = ldns_rbtree_next(node);
1074           }
1075 }
1076 
1077 void
1078 ldns_dnssec_zone_names_print(FILE *out, const ldns_rbtree_t *tree, bool print_soa)
1079 {
1080           ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default,
1081                            tree, print_soa);
1082 }
1083 
1084 void
1085 ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt,
1086                  const ldns_dnssec_zone *zone)
1087 {
1088           if (zone) {
1089                     if (zone->soa) {
1090                               if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
1091                                         fprintf(out, ";; Zone: ");
1092                                         ldns_rdf_print(out, ldns_dnssec_name_name(
1093                                                                       zone->soa));
1094                                         fprintf(out, "\n;\n");
1095                               }
1096                               ldns_dnssec_rrsets_print_fmt(out, fmt,
1097                                                   ldns_dnssec_name_find_rrset(
1098                                                             zone->soa,
1099                                                             LDNS_RR_TYPE_SOA),
1100                                                   false);
1101                               if ((fmt->flags & LDNS_COMMENT_LAYOUT))
1102                                         fprintf(out, ";\n");
1103                     }
1104 
1105                     if (zone->names) {
1106                               ldns_dnssec_zone_names_print_fmt(out, fmt,
1107                                                   zone->names, false);
1108                     }
1109           }
1110 }
1111 
1112 void
1113 ldns_dnssec_zone_print(FILE *out, const ldns_dnssec_zone *zone)
1114 {
1115           ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone);
1116 }
1117 
1118 static ldns_status
1119 ldns_dnssec_zone_add_empty_nonterminals_nsec3(
1120                     ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s)
1121 {
1122           ldns_dnssec_name *new_name;
1123           ldns_rdf *cur_name;
1124           ldns_rdf *next_name;
1125           ldns_rbnode_t *cur_node, *next_node, *new_node;
1126 
1127           /* for the detection */
1128           uint16_t i, cur_label_count, next_label_count;
1129           uint16_t soa_label_count = 0;
1130           ldns_rdf *l1, *l2;
1131           int lpos;
1132 
1133           if (!zone) {
1134                     return LDNS_STATUS_ERR;
1135           }
1136           if (zone->soa && zone->soa->name) {
1137                     soa_label_count = ldns_dname_label_count(zone->soa->name);
1138           }
1139 
1140           cur_node = ldns_rbtree_first(zone->names);
1141           while (cur_node != LDNS_RBTREE_NULL) {
1142                     next_node = ldns_rbtree_next(cur_node);
1143 
1144                     /* skip glue */
1145                     while (next_node != LDNS_RBTREE_NULL &&
1146                            next_node->data &&
1147                            ((ldns_dnssec_name *)next_node->data)->is_glue
1148                     ) {
1149                               next_node = ldns_rbtree_next(next_node);
1150                     }
1151 
1152                     if (next_node == LDNS_RBTREE_NULL) {
1153                               next_node = ldns_rbtree_first(zone->names);
1154                     }
1155                     if (! cur_node->data || ! next_node->data) {
1156                               return LDNS_STATUS_ERR;
1157                     }
1158                     cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
1159                     next_name = ((ldns_dnssec_name *)next_node->data)->name;
1160                     cur_label_count = ldns_dname_label_count(cur_name);
1161                     next_label_count = ldns_dname_label_count(next_name);
1162 
1163                     /* Since the names are in canonical order, we can
1164                      * recognize empty non-terminals by their labels;
1165                      * every label after the first one on the next owner
1166                      * name is a non-terminal if it either does not exist
1167                      * in the current name or is different from the same
1168                      * label in the current name (counting from the end)
1169                      */
1170                     for (i = 1; i < next_label_count - soa_label_count; i++) {
1171                               lpos = (int)cur_label_count - (int)next_label_count + (int)i;
1172                               if (lpos >= 0) {
1173                                         l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
1174                               } else {
1175                                         l1 = NULL;
1176                               }
1177                               l2 = ldns_dname_clone_from(next_name, i);
1178 
1179                               if (!l1 || ldns_dname_compare(l1, l2) != 0) {
1180                                         /* We have an empty nonterminal, add it to the
1181                                          * tree
1182                                          */
1183                                         ldns_rbnode_t *node = NULL;
1184                                         ldns_rdf *ent_name;
1185 
1186                                         if (!(ent_name = ldns_dname_clone_from(
1187                                                             next_name, i))) {
1188 
1189                                                   ldns_rdf_deep_free(l1);
1190                                                   ldns_rdf_deep_free(l2);
1191                                                   return LDNS_STATUS_MEM_ERR;
1192                                         }
1193 
1194                                         if (nsec3s && zone->_nsec3params) {
1195                                                   ldns_rdf *ent_hashed_name;
1196 
1197                                                   if (!(ent_hashed_name =
1198                                                       ldns_nsec3_hash_name_frm_nsec3(
1199                                                                       zone->_nsec3params,
1200                                                                       ent_name))) {
1201                                                             ldns_rdf_deep_free(l1);
1202                                                             ldns_rdf_deep_free(l2);
1203                                                             ldns_rdf_deep_free(ent_name);
1204                                                             return LDNS_STATUS_MEM_ERR;
1205                                                   }
1206                                                   node = ldns_rbtree_search(nsec3s,
1207                                                                       ent_hashed_name);
1208                                                   ldns_rdf_deep_free(ent_hashed_name);
1209                                                   if (!node) {
1210                                                             ldns_rdf_deep_free(l1);
1211                                                             ldns_rdf_deep_free(l2);
1212                                                             ldns_rdf_deep_free(ent_name);
1213                                                             continue;
1214                                                   }
1215                                         }
1216                                         new_name = ldns_dnssec_name_new();
1217                                         if (!new_name) {
1218                                                   ldns_rdf_deep_free(l1);
1219                                                   ldns_rdf_deep_free(l2);
1220                                                   ldns_rdf_deep_free(ent_name);
1221                                                   return LDNS_STATUS_MEM_ERR;
1222                                         }
1223                                         new_name->name = ent_name;
1224                                         new_name->name_alloced = true;
1225                                         new_node = LDNS_MALLOC(ldns_rbnode_t);
1226                                         if (!new_node) {
1227                                                   ldns_rdf_deep_free(l1);
1228                                                   ldns_rdf_deep_free(l2);
1229                                                   ldns_dnssec_name_free(new_name);
1230                                                   return LDNS_STATUS_MEM_ERR;
1231                                         }
1232                                         new_node->key = new_name->name;
1233                                         new_node->data = new_name;
1234                                         (void)ldns_rbtree_insert(zone->names, new_node);
1235                                         ldns_dnssec_name_make_hashed_name(
1236                                                             zone, new_name, NULL);
1237                                         if (node)
1238                                                   (void) ldns_dnssec_zone_add_rr(zone,
1239                                                                       (ldns_rr *)node->data);
1240                               }
1241                               ldns_rdf_deep_free(l1);
1242                               ldns_rdf_deep_free(l2);
1243                     }
1244 
1245                     /* we might have inserted a new node after
1246                      * the current one so we can't just use next()
1247                      */
1248                     if (next_node != ldns_rbtree_first(zone->names)) {
1249                               cur_node = next_node;
1250                     } else {
1251                               cur_node = LDNS_RBTREE_NULL;
1252                     }
1253           }
1254           return LDNS_STATUS_OK;
1255 }
1256 
1257 ldns_status
1258 ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
1259 {
1260           return ldns_dnssec_zone_add_empty_nonterminals_nsec3(zone, NULL);
1261 }
1262 
1263 bool
1264 ldns_dnssec_zone_is_nsec3_optout(const ldns_dnssec_zone* zone)
1265 {
1266           ldns_rr* nsec3;
1267           ldns_rbnode_t* node;
1268 
1269           if (ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_NSEC3PARAM)) {
1270                     node = ldns_rbtree_first(zone->names);
1271                     while (node != LDNS_RBTREE_NULL) {
1272                               nsec3 = ((ldns_dnssec_name*)node->data)->nsec;
1273                               if (nsec3 &&ldns_rr_get_type(nsec3)
1274                                                   == LDNS_RR_TYPE_NSEC3 &&
1275                                                   ldns_nsec3_optout(nsec3)) {
1276                                         return true;
1277                               }
1278                               node = ldns_rbtree_next(node);
1279                     }
1280           }
1281           return false;
1282 }
1283 
1284 /*
1285  * Stuff for calculating and verifying zone digests
1286  */
1287 typedef enum dnssec_zone_rr_iter_state {
1288             DNSSEC_ZONE_RR_ITER_LT_RRSIG
1289           , DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1290           , DNSSEC_ZONE_RR_ITER_REST
1291           , DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC
1292           , DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC_REST
1293           , DNSSEC_ZONE_RR_ITER_NSEC3
1294           , DNSSEC_ZONE_RR_ITER_FINI
1295 } dnssec_zone_rr_iter_state;
1296 
1297 typedef struct dnssec_zone_rr_iter {
1298           ldns_dnssec_zone         *zone;
1299           ldns_rbnode_t            *node;
1300           ldns_dnssec_name         *name;
1301           ldns_dnssec_rrsets       *rrsets;
1302           ldns_dnssec_rrs          *rrs;
1303           ldns_dnssec_rrsets       *rrsets4rrsigs;
1304           ldns_rbnode_t            *nsec3_node;
1305           ldns_dnssec_name         *nsec3_name;
1306           dnssec_zone_rr_iter_state state;
1307           ldns_rdf                 *apex_name;
1308           uint8_t                   apex_labs;
1309 } dnssec_zone_rr_iter;
1310 
1311 INLINE void
1312 dnssec_zone_rr_iter_set_state_for_next_name(dnssec_zone_rr_iter *i)
1313 {
1314           /* Make sure the i->name is "in zone" (i.e. below the apex) */
1315           if (i->apex_name) {
1316                     ldns_rdf *name = (ldns_rdf *)i->node->key;
1317 
1318                     while (i->name && name != i->apex_name        /* not apex */
1319 
1320                     && (  ldns_dname_label_count(name) != i->apex_labs
1321                        || ldns_dname_compare(name, i->apex_name)) /* not apex */
1322 
1323                     && !ldns_dname_is_subdomain(name, i->apex_name) /* no sub */) {
1324 
1325                               /* next name */
1326                               i->node = ldns_rbtree_next(i->node);
1327                               if (i->node == LDNS_RBTREE_NULL)
1328                                         i->name = NULL;
1329                               else {
1330                                         i->name = (ldns_dnssec_name *)i->node->data;
1331                                         name = (ldns_rdf *)i->node->key;
1332                               }
1333                     }
1334           }
1335           /* determine state */
1336           if (!i->name) {
1337                     if (!i->nsec3_name)
1338                               i->state = DNSSEC_ZONE_RR_ITER_FINI;
1339                     else {
1340                               i->rrs = i->nsec3_name->nsec_signatures;
1341                               i->state = DNSSEC_ZONE_RR_ITER_NSEC3;
1342                     }
1343           } else if (!i->nsec3_name) {
1344                     i->rrsets = i->name->rrsets;
1345                     i->state = DNSSEC_ZONE_RR_ITER_LT_RRSIG;
1346 
1347           } else if (ldns_dname_compare( ldns_rr_owner(i->nsec3_name->nsec)
1348                                        , (ldns_rdf *)i->node->key) < 0) {
1349                     i->rrs = i->nsec3_name->nsec_signatures;
1350                     i->state = DNSSEC_ZONE_RR_ITER_NSEC3;
1351           } else {
1352                     i->rrsets = i->name->rrsets;
1353                     i->state = DNSSEC_ZONE_RR_ITER_LT_RRSIG;
1354           }
1355 }
1356 
1357 /**
1358  * Iterate over the RR's in the ldns_dnssec_zone in canonical order.
1359  * There are three possible paths through the RR's in a ldns_dnssec_name.
1360  *
1361  * 1. There is no NSEC:
1362  *
1363  *    1.1. All the RRs in the name->rrsets with type < RRSIG,
1364  *         state: DNSSEC_ZONE_RR_ITER_LT_RRSIG
1365  *
1366  *    1.2. Then all the RRSIGs from name->rrsets (likely none)
1367  *         state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1368  *
1369  *    1.3. Finally the remaining RRs in name->rrsets (type > RRSIG)
1370  *         state: DNSSEC_ZONE_RR_ITER_REST
1371  *
1372  *
1373  * 2. There is a NSEC of type NSEC with this name:
1374  *
1375  *    2.1. All the RRs in the name->rrsets with type < RRSIG,
1376  *         state: DNSSEC_ZONE_RR_ITER_LT_RRSIG
1377  *
1378  *    2.2. Then all the RRSIGs from name->rrsets with type < NSEC
1379  *         state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1380  *
1381  *    2.3. Then the signatures of the NSEC RR, followed by
1382  *         the signatures of the remaining name->rrsets (type > NSEC),
1383  *         followed by the NSEC rr.
1384  *         state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1385  *
1386  *    2.4. Finally the remaining RRs in name->rrsets (type > RRSIG)
1387  *         state: DNSSEC_ZONE_RR_ITER_REST
1388  *
1389  *
1390  * 3. There is a NSEC of type NSEC3 for this name:
1391  *
1392  *    3.1. If the NSEC3 name is before the name for other RRsets in the zone,
1393  *         Then all signatures of the NSEC3 RR, followed by the NSEC3
1394  *         state: DNSSEC_ZONE_RR_ITER_NSEC3
1395  *
1396  *         otherwise follow path for "no NSEC" for the name for other RRsets
1397  */
1398 static ldns_rr *
1399 dnssec_zone_rr_iter_next(dnssec_zone_rr_iter *i)
1400 {
1401           ldns_rr *nsec3;
1402 
1403           for (;;) {
1404                     if (i->rrs) {
1405                               ldns_rr *rr = i->rrs->rr;
1406                               i->rrs = i->rrs->next;
1407                               return rr;
1408                     }
1409                     switch (i->state) {
1410                     case DNSSEC_ZONE_RR_ITER_LT_RRSIG:
1411                               if (i->rrsets
1412                               &&  i->rrsets->type < LDNS_RR_TYPE_RRSIG) {
1413 
1414                                         i->rrs = i->rrsets->rrs;
1415                                         i->rrsets = i->rrsets->next;
1416                                         break;
1417                               }
1418                               i->rrsets4rrsigs = i->name->rrsets;
1419                               if (i->name->nsec && ldns_rr_get_type(i->name->nsec)
1420                                                              == LDNS_RR_TYPE_NSEC) {
1421 
1422                                         i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC;
1423                                         break;
1424                               }
1425                               i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC;
1426                               /* fallthrough */
1427 
1428                     case DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC:
1429                               if (i->rrsets4rrsigs) {
1430                                         i->rrs = i->rrsets4rrsigs->signatures;
1431                                         i->rrsets4rrsigs = i->rrsets4rrsigs->next;
1432                                         break;
1433                               }
1434                               i->state = DNSSEC_ZONE_RR_ITER_REST;
1435                               /* fallthrough */
1436 
1437                     case DNSSEC_ZONE_RR_ITER_REST:
1438                               if (i->rrsets) {
1439                                         i->rrs = i->rrsets->rrs;
1440                                         i->rrsets = i->rrsets->next;
1441                                         break;
1442                               }
1443                               /* next name */
1444                               i->node = ldns_rbtree_next(i->node);
1445                               i->name = i->node == LDNS_RBTREE_NULL ? NULL
1446                                         : (ldns_dnssec_name *)i->node->data;
1447 
1448                               dnssec_zone_rr_iter_set_state_for_next_name(i);
1449                               break;
1450 
1451                     case DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC:
1452                               if (i->rrsets4rrsigs
1453                               &&  i->rrsets4rrsigs->type < LDNS_RR_TYPE_NSEC) {
1454 
1455                                         i->rrs = i->rrsets4rrsigs->signatures;
1456                                         i->rrsets4rrsigs = i->rrsets4rrsigs->next;
1457                                         break;
1458                               }
1459                               i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC_REST;
1460                               i->rrs = i->name->nsec_signatures;
1461                               break;
1462 
1463                     case DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC_REST:
1464                               if (i->rrsets4rrsigs) {
1465                                         i->rrs = i->rrsets4rrsigs->signatures;
1466                                         i->rrsets4rrsigs = i->rrsets4rrsigs->next;
1467                                         break;
1468                               }
1469                               i->state = DNSSEC_ZONE_RR_ITER_REST;
1470                               return i->name->nsec;
1471 
1472                     case DNSSEC_ZONE_RR_ITER_NSEC3:
1473                               nsec3 = i->nsec3_name->nsec;
1474 
1475                               /* next nsec3 */
1476                               do {
1477                                         i->nsec3_node
1478                                             = ldns_rbtree_next(i->nsec3_node);
1479                                         i->nsec3_name
1480                                             = i->nsec3_node == LDNS_RBTREE_NULL ? NULL
1481                                             : (ldns_dnssec_name*)i->nsec3_node->data;
1482 
1483                                         /* names for glue can be in the hashed_names
1484                                          * tree, but will not have a NSEC3
1485                                          */
1486                               } while (i->nsec3_name && !i->nsec3_name->nsec);
1487 
1488                               dnssec_zone_rr_iter_set_state_for_next_name(i);
1489                               return nsec3;
1490 
1491                     case DNSSEC_ZONE_RR_ITER_FINI:
1492                               return NULL;
1493                     }
1494           }
1495 }
1496 
1497 static ldns_rr *
1498 dnssec_zone_rr_iter_first(dnssec_zone_rr_iter *i, ldns_dnssec_zone *zone)
1499 {
1500           if (!i || !zone)
1501                     return NULL;
1502 
1503           memset(i, 0, sizeof(*i));
1504           i->zone = zone;
1505           if (zone->soa && zone->soa->name) {
1506                     i->apex_name = zone->soa->name;
1507                     i->apex_labs = ldns_dname_label_count(i->apex_name);
1508           } else
1509                     i->apex_name = NULL;
1510 
1511 
1512           i->node = ldns_rbtree_first(zone->names);
1513           i->name = i->node == LDNS_RBTREE_NULL ? NULL
1514                     : (ldns_dnssec_name *)i->node->data;
1515 
1516           if (zone->hashed_names) {
1517                     do {
1518                               i->nsec3_node = ldns_rbtree_first(zone->hashed_names);
1519                               i->nsec3_name = i->nsec3_node == LDNS_RBTREE_NULL ?NULL
1520                                               : (ldns_dnssec_name*)i->nsec3_node->data;
1521                     } while (i->nsec3_name && !i->nsec3_name->nsec);
1522           }
1523           dnssec_zone_rr_iter_set_state_for_next_name(i);
1524           return dnssec_zone_rr_iter_next(i);
1525 }
1526 
1527 enum enum_zonemd_scheme {
1528         ZONEMD_SCHEME_FIRST  = 1,
1529         ZONEMD_SCHEME_SIMPLE = 1,
1530         ZONEMD_SCHEME_LAST   = 1
1531 };
1532 typedef enum enum_zonemd_scheme zonemd_scheme;
1533 
1534 enum enum_zonemd_hash {
1535         ZONEMD_HASH_FIRST  = 1,
1536         ZONEMD_HASH_SHA384 = 1,
1537         ZONEMD_HASH_SHA512 = 2,
1538         ZONEMD_HASH_LAST   = 2
1539 };
1540 typedef enum enum_zonemd_hash zonemd_hash;
1541 
1542 struct struct_zone_digester {
1543         ldns_sha384_CTX sha384_CTX;
1544         ldns_sha512_CTX sha512_CTX;
1545         unsigned simple_sha384 : 1;
1546         unsigned simple_sha512 : 1;
1547         unsigned double_sha384 : 1;
1548         unsigned double_sha512 : 1;
1549 };
1550 typedef struct struct_zone_digester zone_digester;
1551 
1552 INLINE bool zone_digester_set(zone_digester *zd)
1553 { return zd && (zd->simple_sha384 || zd->simple_sha512); }
1554 
1555 INLINE void zone_digester_init(zone_digester *zd)
1556 { memset(zd, 0, sizeof(*zd)); }
1557 
1558 static ldns_status
1559 zone_digester_add(zone_digester *zd, zonemd_scheme scheme, zonemd_hash hash)
1560 {
1561           if (!zd)
1562                     return LDNS_STATUS_NULL;
1563 
1564           switch (scheme) {
1565           case ZONEMD_SCHEME_SIMPLE:
1566                     switch (hash) {
1567                     case ZONEMD_HASH_SHA384:
1568                               if (zd->double_sha384)
1569                                         return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1570 
1571                               else if (zd->simple_sha384) {
1572                                         zd->simple_sha384 = 0;
1573                                         zd->double_sha384 = 1;
1574                                         return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1575                               }
1576                               ldns_sha384_init(&zd->sha384_CTX);
1577                               zd->simple_sha384 = 1;
1578                               break;
1579 
1580                     case ZONEMD_HASH_SHA512:
1581                               if (zd->double_sha512)
1582                                         return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1583 
1584                               else if (zd->simple_sha512) {
1585                                         zd->simple_sha512 = 0;
1586                                         zd->double_sha512 = 1;
1587                                         return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1588                               }
1589                               ldns_sha512_init(&zd->sha512_CTX);
1590                               zd->simple_sha512 = 1;
1591                               break;
1592                     default:
1593                               return LDNS_STATUS_ZONEMD_UNKNOWN_HASH;
1594                     }
1595                     break;
1596           default:
1597                     return LDNS_STATUS_ZONEMD_UNKNOWN_SCHEME;
1598           }
1599           return LDNS_STATUS_OK;
1600 }
1601 
1602 static ldns_status
1603 zone_digester_update(zone_digester *zd, ldns_rr *rr)
1604 {
1605           uint8_t data[65536];
1606           ldns_buffer buf;
1607           ldns_status st;
1608 
1609           buf._data = data;
1610           buf._position = 0;
1611           buf._limit = sizeof(data);
1612           buf._capacity = sizeof(data);
1613           buf._fixed = 1;
1614           buf._status = LDNS_STATUS_OK;
1615 
1616           if ((st = ldns_rr2buffer_wire_canonical(&buf, rr, LDNS_SECTION_ANSWER)))
1617                     return st;
1618 
1619           if (zd->simple_sha384)
1620                     ldns_sha384_update(&zd->sha384_CTX, data, buf._position);
1621 
1622           if (zd->simple_sha512)
1623                     ldns_sha512_update(&zd->sha512_CTX, data, buf._position);
1624 
1625           return LDNS_STATUS_OK;
1626 }
1627 
1628 INLINE ldns_rr *
1629 new_zonemd(ldns_rr *soa, zonemd_hash hash)
1630 {
1631           ldns_rr  *rr     = NULL;
1632           uint8_t  *data   = NULL;
1633           ldns_rdf *rdf;
1634           size_t    md_len = hash == ZONEMD_HASH_SHA384
1635                            ? LDNS_SHA384_DIGEST_LENGTH
1636                            : LDNS_SHA512_DIGEST_LENGTH;
1637 
1638           if (!(rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_ZONEMD)))
1639                     return NULL;
1640 
1641           if (!(rdf = ldns_rdf_clone(ldns_rr_owner(soa))))
1642                     goto error;
1643 
1644           ldns_rr_set_owner(rr, rdf);
1645           ldns_rr_set_class(rr, ldns_rr_get_class(soa));
1646           ldns_rr_set_ttl(rr, ldns_rr_ttl(soa));
1647 
1648           if (!(rdf = ldns_rdf_clone(ldns_rr_rdf(soa, 2))))
1649                     goto error;
1650           ldns_rr_set_rdf(rr, rdf, 0);
1651 
1652           if (!(rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, 1)))
1653                     goto error;
1654           ldns_rr_set_rdf(rr, rdf, 1);
1655 
1656           if (!(rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, hash)))
1657                     goto error;
1658           ldns_rr_set_rdf(rr, rdf, 2);
1659 
1660           if (!(data = LDNS_XMALLOC(uint8_t, md_len)))
1661                     goto error;
1662 
1663           if (!(rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, md_len, data)))
1664                     goto error;
1665           ldns_rr_set_rdf(rr, rdf, 3);
1666 
1667           return rr;
1668 error:
1669           if (data)
1670                     LDNS_FREE(data);
1671           ldns_rr_free(rr);
1672           return NULL;
1673 }
1674 
1675 static ldns_rr_list *
1676 zone_digester_export(
1677                     zone_digester *zd, ldns_rr *soa, ldns_status *ret_st)
1678 {
1679           ldns_status st = LDNS_STATUS_OK;
1680           ldns_rr_list *rr_list = NULL;
1681           ldns_rr *sha384 = NULL;
1682           ldns_rr *sha512 = NULL;
1683 
1684           if (!zd || !soa)
1685                     st = LDNS_STATUS_NULL;
1686 
1687           else if (ldns_rr_get_type(soa) != LDNS_RR_TYPE_SOA
1688                ||  ldns_rr_rd_count(soa) < 3)
1689                     st = LDNS_STATUS_ZONEMD_INVALID_SOA;
1690 
1691           else if (!(rr_list = ldns_rr_list_new()))
1692                     st = LDNS_STATUS_MEM_ERR;
1693 
1694           else if (zd->simple_sha384
1695                && !(sha384 = new_zonemd(soa, ZONEMD_HASH_SHA384)))
1696                     st = LDNS_STATUS_MEM_ERR;
1697 
1698           else if (zd->simple_sha512
1699                && !(sha512 = new_zonemd(soa, ZONEMD_HASH_SHA512)))
1700                     st = LDNS_STATUS_MEM_ERR;
1701 
1702           else if (zd->simple_sha384
1703                && !ldns_rr_list_push_rr(rr_list, sha384))
1704                     st = LDNS_STATUS_MEM_ERR;
1705 
1706           else if (zd->simple_sha512
1707                && !ldns_rr_list_push_rr(rr_list, sha512)) {
1708                     if (zd->simple_sha384)
1709                               sha384 = NULL; /* deleted by ldns_rr_list_deep_free */
1710                     st = LDNS_STATUS_MEM_ERR;
1711 
1712           } else {
1713                     if (sha384)
1714                               ldns_sha384_final( ldns_rdf_data(ldns_rr_rdf(sha384,3))
1715                                                , &zd->sha384_CTX);
1716                     if (sha512)
1717                               ldns_sha512_final( ldns_rdf_data(ldns_rr_rdf(sha512,3))
1718                                                , &zd->sha512_CTX);
1719                     return rr_list;
1720           }
1721           if (ret_st)
1722                     *ret_st = st;
1723           if (sha384)
1724                     ldns_rr_free(sha384);
1725           if (sha512)
1726                     ldns_rr_free(sha512);
1727           if (rr_list)
1728                     ldns_rr_list_deep_free(rr_list);
1729           return NULL;
1730 }
1731 
1732 static ldns_status
1733 ldns_digest_zone(ldns_dnssec_zone *zone, zone_digester *zd)
1734 {
1735           ldns_status st = LDNS_STATUS_OK;
1736           dnssec_zone_rr_iter rr_iter;
1737           ldns_rr *rr;
1738           ldns_rdf *apex_name; /* name of zone apex */
1739 
1740           if (!zone || !zd || !zone->soa || !zone->soa->name)
1741                     return LDNS_STATUS_NULL;
1742 
1743           apex_name = zone->soa->name;
1744           for ( rr = dnssec_zone_rr_iter_first(&rr_iter, zone)
1745               ; rr && !st
1746               ; rr = dnssec_zone_rr_iter_next(&rr_iter)) {
1747                     /* Skip apex ZONEMD RRs */
1748                     if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_ZONEMD
1749                     && !ldns_dname_compare(ldns_rr_owner(rr), apex_name))
1750                               continue;
1751                     /* Skip RRSIGs for apex ZONEMD RRs */
1752                     if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
1753                     &&  LDNS_RR_TYPE_ZONEMD == ldns_rdf2rr_type(
1754                                         ldns_rr_rrsig_typecovered(rr))
1755                     && !ldns_dname_compare(ldns_rr_owner(rr), apex_name))
1756                               continue;
1757                     st = zone_digester_update(zd, rr);
1758           }
1759           return st;
1760 }
1761 
1762 ldns_status
1763 ldns_dnssec_zone_verify_zonemd(ldns_dnssec_zone *zone)
1764 {
1765           ldns_dnssec_rrsets *zonemd, *soa;
1766           zone_digester zd;
1767           ldns_dnssec_rrs *rrs;
1768           ldns_rr *soa_rr;
1769           ldns_status st;
1770           uint8_t simple_sha384[LDNS_SHA384_DIGEST_LENGTH];
1771           uint8_t simple_sha512[LDNS_SHA512_DIGEST_LENGTH];
1772           size_t valid_zonemds;
1773 
1774           if (!zone)
1775                     return LDNS_STATUS_NULL;
1776 
1777           zonemd = ldns_dnssec_zone_find_rrset(
1778                               zone, zone->soa->name, LDNS_RR_TYPE_ZONEMD);
1779           if (!zonemd) {
1780                     ldns_rbnode_t *nsec3_node;
1781 
1782                     /* we need proof of non-existence for ZONEMD at the apex */
1783                     if (zone->soa->nsec) {
1784                               if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(
1785                                                                       zone->soa->nsec),
1786                                                             LDNS_RR_TYPE_ZONEMD))
1787                                         return LDNS_STATUS_NO_ZONEMD;
1788 
1789                     } else if (!zone->soa->hashed_name || !zone->hashed_names)
1790                               return LDNS_STATUS_NO_ZONEMD;
1791 
1792                     else if (LDNS_RBTREE_NULL ==
1793                         (nsec3_node = ldns_rbtree_search( zone->hashed_names
1794                                                                 , zone->soa->hashed_name)))
1795                               return LDNS_STATUS_NO_ZONEMD;
1796                     else {
1797                               ldns_dnssec_name *nsec3
1798                                         = (ldns_dnssec_name *)nsec3_node->data;
1799                               if (ldns_nsec_bitmap_covers_type(ldns_nsec_get_bitmap(
1800                                                                       nsec3->nsec),
1801                                                             LDNS_RR_TYPE_ZONEMD))
1802                                         return LDNS_STATUS_NO_ZONEMD;
1803                     }
1804                     /* ZONEMD at apex does really not exist */
1805                     return LDNS_STATUS_OK;
1806           }
1807           soa = ldns_dnssec_zone_find_rrset(
1808                               zone, zone->soa->name, LDNS_RR_TYPE_SOA);
1809           if (!soa || !soa->rrs || !soa->rrs->rr)
1810                     return LDNS_STATUS_ZONEMD_INVALID_SOA;
1811 
1812           soa_rr = soa->rrs->rr;
1813           if (ldns_rr_get_type(soa_rr) != LDNS_RR_TYPE_SOA
1814           ||  ldns_rr_rd_count(soa_rr) < 3)
1815                     return LDNS_STATUS_ZONEMD_INVALID_SOA;
1816 
1817           zone_digester_init(&zd);
1818           for (rrs = zonemd->rrs; rrs; rrs = rrs->next) {
1819                     if (!rrs->rr
1820                     ||  ldns_rr_get_type(rrs->rr) != LDNS_RR_TYPE_ZONEMD
1821                     ||  ldns_rr_rd_count(rrs->rr) < 4)
1822                               continue;
1823 
1824                     /* serial should match SOA's serial */
1825                     if (ldns_rdf2native_int32(ldns_rr_rdf(soa_rr, 2))
1826                         != ldns_rdf2native_int32(ldns_rr_rdf(rrs->rr, 0)))
1827                               continue;
1828 
1829                     /* Add (scheme, hash) to digester */
1830                     zone_digester_add(&zd,
1831                                         ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr, 1)),
1832                                         ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr, 2)));
1833           }
1834           if (!zone_digester_set(&zd))
1835                     return LDNS_STATUS_NO_VALID_ZONEMD;
1836 
1837           if ((st = ldns_digest_zone(zone, &zd)))
1838                     return st;
1839 
1840           if (zd.simple_sha384)
1841                     ldns_sha384_final(simple_sha384, &zd.sha384_CTX);
1842           if (zd.simple_sha512)
1843                     ldns_sha512_final(simple_sha512, &zd.sha512_CTX);
1844 
1845           valid_zonemds = 0;
1846           for (rrs = zonemd->rrs; rrs; rrs = rrs->next) {
1847                     if (!rrs->rr
1848                     ||  ldns_rr_get_type(rrs->rr) != LDNS_RR_TYPE_ZONEMD
1849                     ||  ldns_rr_rd_count(rrs->rr) < 4)
1850                               continue;
1851 
1852                     /* serial should match SOA's serial */
1853                     if (ldns_rdf2native_int32(ldns_rr_rdf(soa_rr, 2))
1854                         != ldns_rdf2native_int32(ldns_rr_rdf(rrs->rr, 0)))
1855                               continue;
1856 
1857                     if (ZONEMD_SCHEME_SIMPLE !=
1858                                         ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr, 1)))
1859                               continue;
1860 
1861                     if (ZONEMD_HASH_SHA384
1862                                         == ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr,2))
1863                     &&  LDNS_SHA384_DIGEST_LENGTH
1864                                         == ldns_rdf_size(ldns_rr_rdf(rrs->rr, 3))
1865                     &&  memcmp( simple_sha384
1866                                 , ldns_rdf_data(ldns_rr_rdf(rrs->rr, 3))
1867                               , LDNS_SHA384_DIGEST_LENGTH) == 0)
1868 
1869                               valid_zonemds += 1;
1870 
1871                     if (ZONEMD_HASH_SHA512
1872                                         == ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr,2))
1873                     &&  LDNS_SHA512_DIGEST_LENGTH
1874                                         == ldns_rdf_size(ldns_rr_rdf(rrs->rr, 3))
1875                     &&  memcmp( simple_sha512
1876                                 , ldns_rdf_data(ldns_rr_rdf(rrs->rr, 3))
1877                               , LDNS_SHA512_DIGEST_LENGTH) == 0)
1878 
1879                               valid_zonemds += 1;
1880           }
1881           return valid_zonemds ? LDNS_STATUS_OK : LDNS_STATUS_NO_VALID_ZONEMD;
1882 }
1883 
1884 #ifdef HAVE_SSL
1885 static ldns_status
1886 rr_list2dnssec_rrs(ldns_rr_list *rr_list, ldns_dnssec_rrs **rrs,
1887                     ldns_rr_list *new_rrs)
1888 {
1889           ldns_rr *rr = NULL;
1890 
1891           if (!rr_list || !rrs)
1892                     return LDNS_STATUS_NULL;
1893 
1894           if (ldns_rr_list_rr_count(rr_list) == 0)
1895                     return LDNS_STATUS_OK;
1896 
1897           if (!*rrs) {
1898                     if (!(*rrs = ldns_dnssec_rrs_new()))
1899                               return LDNS_STATUS_MEM_ERR;
1900                     (*rrs)->rr = ldns_rr_list_pop_rr(rr_list);
1901                     if (new_rrs)
1902                               ldns_rr_list_push_rr(new_rrs, (*rrs)->rr);
1903           }
1904           while ((rr = ldns_rr_list_pop_rr(rr_list))) {
1905                     ldns_status st;
1906 
1907                     if ((st = ldns_dnssec_rrs_add_rr(*rrs, rr))) {
1908                               ldns_rr_list_push_rr(rr_list, rr);
1909                               return st;
1910                     } else if (new_rrs)
1911                               ldns_rr_list_push_rr(new_rrs, rr);
1912           }
1913           return LDNS_STATUS_OK;
1914 }
1915 
1916 
1917 ldns_status
1918 dnssec_zone_equip_zonemd(ldns_dnssec_zone *zone,
1919                     ldns_rr_list *new_rrs, ldns_key_list *key_list, int signflags)
1920 {
1921           ldns_status st = LDNS_STATUS_OK;
1922           zone_digester zd;
1923           ldns_rr_list *zonemd_rr_list = NULL;
1924           ldns_rr_list *zonemd_rrsigs = NULL;
1925           ldns_dnssec_rrsets *soa_rrset;
1926           ldns_rr *soa_rr = NULL;
1927           ldns_dnssec_rrsets **rrset_ref;
1928           ldns_dnssec_rrsets *zonemd_rrset;
1929 
1930           zone_digester_init(&zd);
1931           if (signflags & LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA384)
1932                     zone_digester_add(&zd, ZONEMD_SCHEME_SIMPLE
1933                                          , ZONEMD_HASH_SHA384);
1934 
1935           if (signflags & LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA512)
1936                     zone_digester_add(&zd, ZONEMD_SCHEME_SIMPLE
1937                                          , ZONEMD_HASH_SHA512);
1938 
1939           if ((st = ldns_digest_zone(zone, &zd)))
1940                     return st;
1941 
1942           soa_rrset = ldns_dnssec_zone_find_rrset(
1943                               zone, zone->soa->name, LDNS_RR_TYPE_SOA);
1944           if (!soa_rrset || !soa_rrset->rrs || !soa_rrset->rrs->rr)
1945                     return LDNS_STATUS_ZONEMD_INVALID_SOA;
1946           soa_rr = soa_rrset->rrs->rr;
1947 
1948           if (!(zonemd_rr_list = zone_digester_export(&zd, soa_rr, &st)))
1949                     return st;
1950 
1951           /* - replace or add ZONEMD rrset */
1952           rrset_ref = &zone->soa->rrsets; /* scan rrsets at apex */
1953           while (*rrset_ref && (*rrset_ref)->type < LDNS_RR_TYPE_ZONEMD)
1954                     rrset_ref = &(*rrset_ref)->next;
1955           if (*rrset_ref && (*rrset_ref)->type == LDNS_RR_TYPE_ZONEMD) {
1956                     /* reuse zonemd rrset */
1957                     zonemd_rrset = *rrset_ref;
1958                     ldns_dnssec_rrs_free(zonemd_rrset->rrs);
1959                     zonemd_rrset->rrs = NULL;
1960                     ldns_dnssec_rrs_free(zonemd_rrset->signatures);
1961                     zonemd_rrset->signatures = NULL;
1962           } else {
1963                     /* insert zonemd rrset */
1964                     zonemd_rrset = ldns_dnssec_rrsets_new();
1965                     if (!zonemd_rrset) {
1966                               ldns_rr_list_deep_free(zonemd_rr_list);
1967                               return LDNS_STATUS_MEM_ERR;
1968                     }
1969                     zonemd_rrset->type = LDNS_RR_TYPE_ZONEMD;
1970                     zonemd_rrset->next = *rrset_ref;
1971                     *rrset_ref = zonemd_rrset;
1972           }
1973           if ((zonemd_rrsigs = ldns_sign_public(zonemd_rr_list, key_list)))
1974                     st = rr_list2dnssec_rrs(  zonemd_rrsigs
1975                                            , &zonemd_rrset->signatures, new_rrs);
1976           if (!st)
1977                     st = rr_list2dnssec_rrs(  zonemd_rr_list
1978                                            , &zonemd_rrset->rrs, new_rrs);
1979           ldns_rr_list_deep_free(zonemd_rr_list);
1980           ldns_rr_list_deep_free(zonemd_rrsigs);
1981           return st;
1982 }
1983 
1984 #endif /* HAVE_SSL */
1985 
1986