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