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