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