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