File Coverage

src/ldns/dnssec_zone.c
Criterion Covered Total %
statement 0 574 0.0
branch 0 346 0.0
condition n/a
subroutine n/a
pod n/a
total 0 920 0.0


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