wg.conf.5: Fix a typo (in-inline comments are *not* allowed)
[dragonfly.git] / contrib / ldns / dnssec_zone.c
blob7be6791e7f5db6a44074dcd9360b5066148f3541
1 /*
2 * special zone file structures and functions for better dnssec handling
3 */
5 #include <ldns/config.h>
7 #include <ldns/ldns.h>
9 ldns_dnssec_rrs *
10 ldns_dnssec_rrs_new(void)
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;
20 INLINE void
21 ldns_dnssec_rrs_free_internal(ldns_dnssec_rrs *rrs, int deep)
23 ldns_dnssec_rrs *next;
24 while (rrs) {
25 next = rrs->next;
26 if (deep) {
27 ldns_rr_free(rrs->rr);
29 LDNS_FREE(rrs);
30 rrs = next;
34 void
35 ldns_dnssec_rrs_free(ldns_dnssec_rrs *rrs)
37 ldns_dnssec_rrs_free_internal(rrs, 0);
40 void
41 ldns_dnssec_rrs_deep_free(ldns_dnssec_rrs *rrs)
43 ldns_dnssec_rrs_free_internal(rrs, 1);
46 ldns_status
47 ldns_dnssec_rrs_add_rr(ldns_dnssec_rrs *rrs, ldns_rr *rr)
49 int cmp;
50 ldns_dnssec_rrs *new_rrs;
51 if (!rrs || !rr) {
52 return LDNS_STATUS_ERR;
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;
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;
75 /* Silently ignore equal rr's */
76 return LDNS_STATUS_OK;
79 void
80 ldns_dnssec_rrs_print_fmt(FILE *out, const ldns_output_format *fmt,
81 const ldns_dnssec_rrs *rrs)
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);
90 if (rrs->next) {
91 ldns_dnssec_rrs_print_fmt(out, fmt, rrs->next);
96 void
97 ldns_dnssec_rrs_print(FILE *out, const ldns_dnssec_rrs *rrs)
99 ldns_dnssec_rrs_print_fmt(out, ldns_output_format_default, rrs);
103 ldns_dnssec_rrsets *
104 ldns_dnssec_rrsets_new(void)
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;
116 INLINE void
117 ldns_dnssec_rrsets_free_internal(ldns_dnssec_rrsets *rrsets, int deep)
119 if (rrsets) {
120 if (rrsets->rrs) {
121 ldns_dnssec_rrs_free_internal(rrsets->rrs, deep);
123 if (rrsets->next) {
124 ldns_dnssec_rrsets_free_internal(rrsets->next, deep);
126 if (rrsets->signatures) {
127 ldns_dnssec_rrs_free_internal(rrsets->signatures, deep);
129 LDNS_FREE(rrsets);
133 void
134 ldns_dnssec_rrsets_free(ldns_dnssec_rrsets *rrsets)
136 ldns_dnssec_rrsets_free_internal(rrsets, 0);
139 void
140 ldns_dnssec_rrsets_deep_free(ldns_dnssec_rrsets *rrsets)
142 ldns_dnssec_rrsets_free_internal(rrsets, 1);
145 ldns_rr_type
146 ldns_dnssec_rrsets_type(const ldns_dnssec_rrsets *rrsets)
148 if (rrsets) {
149 return rrsets->type;
150 } else {
151 return 0;
155 ldns_status
156 ldns_dnssec_rrsets_set_type(ldns_dnssec_rrsets *rrsets,
157 ldns_rr_type type)
159 if (rrsets) {
160 rrsets->type = type;
161 return LDNS_STATUS_OK;
163 return LDNS_STATUS_ERR;
166 static ldns_dnssec_rrsets *
167 ldns_dnssec_rrsets_new_frm_rr(ldns_rr *rr)
169 ldns_dnssec_rrsets *new_rrsets;
170 ldns_rr_type rr_type;
171 bool rrsig;
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;
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;
188 new_rrsets->type = rr_type;
189 return new_rrsets;
192 ldns_status
193 ldns_dnssec_rrsets_add_rr(ldns_dnssec_rrsets *rrsets, ldns_rr *rr)
195 ldns_dnssec_rrsets *new_rrsets;
196 ldns_rr_type rr_type;
197 bool rrsig = false;
198 ldns_status result = LDNS_STATUS_OK;
200 if (!rrsets || !rr) {
201 return LDNS_STATUS_ERR;
204 rr_type = ldns_rr_get_type(rr);
206 if (rr_type == LDNS_RR_TYPE_RRSIG) {
207 rrsig = true;
208 rr_type = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
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;
221 return LDNS_STATUS_OK;
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;
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;
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;
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;
269 return result;
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)
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
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);
293 if (follow && rrsets->next) {
294 ldns_dnssec_rrsets_print_soa_fmt(out, fmt,
295 rrsets->next, follow, show_soa);
301 void
302 ldns_dnssec_rrsets_print_fmt(FILE *out, const ldns_output_format *fmt,
303 const ldns_dnssec_rrsets *rrsets,
304 bool follow)
306 ldns_dnssec_rrsets_print_soa_fmt(out, fmt, rrsets, follow, true);
309 void
310 ldns_dnssec_rrsets_print(FILE *out, const ldns_dnssec_rrsets *rrsets, bool follow)
312 ldns_dnssec_rrsets_print_fmt(out, ldns_output_format_default,
313 rrsets, follow);
316 ldns_dnssec_name *
317 ldns_dnssec_name_new(void)
319 ldns_dnssec_name *new_name;
321 new_name = LDNS_CALLOC(ldns_dnssec_name, 1);
322 if (!new_name) {
323 return NULL;
326 * not needed anymore because CALLOC initializes everything to zero.
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;
334 new_name->is_glue = false;
335 new_name->hashed_name = NULL;
338 return new_name;
341 ldns_dnssec_name *
342 ldns_dnssec_name_new_frm_rr(ldns_rr *rr)
344 ldns_dnssec_name *new_name = ldns_dnssec_name_new();
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;
352 return new_name;
355 INLINE void
356 ldns_dnssec_name_free_internal(ldns_dnssec_name *name,
357 int deep)
359 if (name) {
360 if (name->name_alloced) {
361 ldns_rdf_deep_free(name->name);
363 if (name->rrsets) {
364 ldns_dnssec_rrsets_free_internal(name->rrsets, deep);
366 if (name->nsec && deep) {
367 ldns_rr_free(name->nsec);
369 if (name->nsec_signatures) {
370 ldns_dnssec_rrs_free_internal(name->nsec_signatures, deep);
372 if (name->hashed_name) {
373 /* Hashed name is always allocated when signing,
374 * so always deep free
376 ldns_rdf_deep_free(name->hashed_name);
378 LDNS_FREE(name);
382 void
383 ldns_dnssec_name_free(ldns_dnssec_name *name)
385 ldns_dnssec_name_free_internal(name, 0);
388 void
389 ldns_dnssec_name_deep_free(ldns_dnssec_name *name)
391 ldns_dnssec_name_free_internal(name, 1);
394 ldns_rdf *
395 ldns_dnssec_name_name(const ldns_dnssec_name *name)
397 if (name) {
398 return name->name;
400 return NULL;
403 bool
404 ldns_dnssec_name_is_glue(const ldns_dnssec_name *name)
406 if (name) {
407 return name->is_glue;
409 return false;
412 void
413 ldns_dnssec_name_set_name(ldns_dnssec_name *rrset,
414 ldns_rdf *dname)
416 if (rrset && dname) {
417 rrset->name = dname;
422 void
423 ldns_dnssec_name_set_nsec(ldns_dnssec_name *rrset, ldns_rr *nsec)
425 if (rrset && nsec) {
426 rrset->nsec = nsec;
431 ldns_dnssec_name_cmp(const void *a, const void *b)
433 ldns_dnssec_name *na = (ldns_dnssec_name *) a;
434 ldns_dnssec_name *nb = (ldns_dnssec_name *) b;
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;
448 ldns_status
449 ldns_dnssec_name_add_rr(ldns_dnssec_name *name,
450 ldns_rr *rr)
452 ldns_status result = LDNS_STATUS_OK;
453 ldns_rr_type rr_type;
454 ldns_rr_type typecovered = 0;
456 /* special handling for NSEC3 and NSECX covering RRSIGS */
458 if (!name || !rr) {
459 return LDNS_STATUS_ERR;
462 rr_type = ldns_rr_get_type(rr);
464 if (rr_type == LDNS_RR_TYPE_RRSIG) {
465 typecovered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
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;
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);
489 return result;
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;
497 result = name->rrsets;
498 while (result) {
499 if (result->type == type) {
500 return result;
501 } else {
502 result = result->next;
505 return NULL;
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)
513 ldns_rbnode_t *node;
515 if (!zone || !dname || !zone->names) {
516 return NULL;
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;
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)
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");
542 if(name->nsec) {
543 ldns_rr_print_fmt(out, fmt, name->nsec);
545 if (name->nsec_signatures) {
546 ldns_dnssec_rrs_print_fmt(out, fmt,
547 name->nsec_signatures);
549 } else if ((fmt->flags & LDNS_COMMENT_LAYOUT)) {
550 fprintf(out, "; <void>\n");
555 void
556 ldns_dnssec_name_print_fmt(FILE *out, const ldns_output_format *fmt,
557 const ldns_dnssec_name *name)
559 ldns_dnssec_name_print_soa_fmt(out, fmt, name, true);
562 void
563 ldns_dnssec_name_print(FILE *out, const ldns_dnssec_name *name)
565 ldns_dnssec_name_print_fmt(out, ldns_output_format_default, name);
569 ldns_dnssec_zone *
570 ldns_dnssec_zone_new(void)
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;
579 return zone;
582 static bool
583 rr_is_rrsig_covering(ldns_rr* rr, ldns_rr_type t)
585 return ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG
586 && ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr)) == t;
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.
595 #define FASTER_DNSSEC_ZONE_NEW_FRM_FP 1 /* Because of L2 cache efficiency */
597 static ldns_status
598 ldns_dnssec_zone_add_empty_nonterminals_nsec3(
599 ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s);
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);
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);
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)
616 ldns_rr* cur_rr;
617 size_t i;
619 ldns_rdf *my_origin = NULL;
620 ldns_rdf *my_prev = NULL;
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.
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();
639 ldns_status status;
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.'
649 bool ttl_from_TTL = false;
650 bool explicit_ttl = false;
651 #endif
653 ldns_rbtree_init(&todo_nsec3_ents, ldns_dname_compare_v);
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;
664 if (origin) {
665 if (!(my_origin = ldns_rdf_clone(origin))) {
666 status = LDNS_STATUS_MEM_ERR;
667 goto error;
669 if (!(my_prev = ldns_rdf_clone(origin))) {
670 status = LDNS_STATUS_MEM_ERR;
671 goto error;
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;
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)
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)
705 my_ttl = ldns_rr_ttl(cur_rr);
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.
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)
717 /* SIG without explicit ttl get ttl
718 * from the original_ttl field
719 * (RFC 2535 Section 7.2)
721 * Similarly for RRSIG, but stated less
722 * specifically in the spec.
723 * (RFC 4034 Section 3)
725 ldns_rr_set_ttl(cur_rr,
726 ldns_rdf2native_int32(
727 ldns_rr_rdf(rr, 3)));
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)
734 /* "TTLs of all RRs in an RRSet must be the same"
735 * (RFC 2881 Section 5.2)
737 ldns_rr_set_ttl(cur_rr, ldns_rr_ttl(prev_rr));
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) {
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);
753 status = LDNS_STATUS_OK;
755 } else if (status != LDNS_STATUS_OK)
756 goto error;
758 break;
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;
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;
774 case LDNS_STATUS_SYNTAX_INCLUDE:/* $include not implemented */
775 status = LDNS_STATUS_SYNTAX_INCLUDE_ERR_NOTIMPL;
776 break;
778 default:
779 goto error;
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;
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;
799 status = LDNS_STATUS_OK;
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);
810 if (z) {
811 *z = newzone;
812 newzone = NULL;
813 } else {
814 ldns_dnssec_zone_free(newzone);
815 newzone = NULL;
818 error:
819 #ifdef FASTER_DNSSEC_ZONE_NEW_FRM_FP
820 if (zone) {
821 ldns_zone_free(zone);
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);
829 if (my_origin) {
830 ldns_rdf_deep_free(my_origin);
832 if (my_prev) {
833 ldns_rdf_deep_free(my_prev);
835 if (newzone) {
836 ldns_dnssec_zone_free(newzone);
838 return status;
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))
845 return ldns_dnssec_zone_new_frm_fp_l(z, fp, origin, ttl, c, NULL);
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);
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);
862 static void
863 ldns_hashed_names_node_free(ldns_rbnode_t *node, void *arg) {
864 (void) arg;
865 LDNS_FREE(node);
868 void
869 ldns_dnssec_zone_free(ldns_dnssec_zone *zone)
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);
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);
884 LDNS_FREE(zone);
888 void
889 ldns_dnssec_zone_deep_free(ldns_dnssec_zone *zone)
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);
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);
904 LDNS_FREE(zone);
908 /* use for dname comparison in tree */
910 ldns_dname_compare_v(const void *a, const void *b) {
911 return ldns_dname_compare((ldns_rdf *)a, (ldns_rdf *)b);
914 static void
915 ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
916 ldns_dnssec_name* name, ldns_rr* nsec3rr);
918 static void
919 ldns_dnssec_zone_hashed_names_from_nsec3(
920 ldns_dnssec_zone* zone, ldns_rr* nsec3rr)
922 ldns_rbnode_t* current_node;
923 ldns_dnssec_name* current_name;
925 assert(zone != NULL);
926 assert(nsec3rr != NULL);
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);
933 zone->_nsec3params = nsec3rr;
935 /* So this is a NSEC3 zone.
936 * Calculate hashes for all names already in the zone
938 zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v);
939 if (zone->hashed_names == NULL) {
940 return;
942 for ( current_node = ldns_rbtree_first(zone->names)
943 ; current_node != LDNS_RBTREE_NULL
944 ; current_node = ldns_rbtree_next(current_node)
946 current_name = (ldns_dnssec_name *) current_node->data;
947 ldns_dnssec_name_make_hashed_name(zone, current_name, nsec3rr);
952 static void
953 ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
954 ldns_dnssec_name* name, ldns_rr* nsec3rr)
956 ldns_rbnode_t* new_node;
958 assert(name != NULL);
959 if (! zone->_nsec3params) {
960 if (! nsec3rr) {
961 return;
963 ldns_dnssec_zone_hashed_names_from_nsec3(zone, nsec3rr);
965 } else if (! nsec3rr) {
966 nsec3rr = zone->_nsec3params;
968 name->hashed_name = ldns_nsec3_hash_name_frm_nsec3(nsec3rr, name->name);
970 /* Also store in zone->hashed_names */
971 if ((new_node = LDNS_MALLOC(ldns_rbnode_t))) {
973 new_node->key = name->hashed_name;
974 new_node->data = name;
976 if (ldns_rbtree_insert(zone->hashed_names, new_node) == NULL) {
978 LDNS_FREE(new_node);
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;
989 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 && ! zone->_nsec3params){
991 ldns_dnssec_zone_hashed_names_from_nsec3(zone, rr);
993 if (zone->hashed_names == NULL) {
994 return NULL;
996 hashed_name = ldns_dname_label(ldns_rr_owner(rr), 0);
997 if (hashed_name == NULL) {
998 return NULL;
1000 to_return = ldns_rbtree_search(zone->hashed_names, hashed_name);
1001 ldns_rdf_deep_free(hashed_name);
1002 return to_return;
1005 ldns_status
1006 ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
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;
1013 if (!zone || !rr) {
1014 return LDNS_STATUS_ERR;
1017 if (!zone->names) {
1018 zone->names = ldns_rbtree_create(ldns_dname_compare_v);
1019 if(!zone->names) return LDNS_STATUS_MEM_ERR;
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));
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;
1033 } else {
1034 cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
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;
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);
1053 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
1054 zone->soa = cur_name;
1056 return result;
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)
1064 ldns_rbnode_t *node;
1065 ldns_dnssec_name *name;
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);
1077 void
1078 ldns_dnssec_zone_names_print(FILE *out, const ldns_rbtree_t *tree, bool print_soa)
1080 ldns_dnssec_zone_names_print_fmt(out, ldns_output_format_default,
1081 tree, print_soa);
1084 void
1085 ldns_dnssec_zone_print_fmt(FILE *out, const ldns_output_format *fmt,
1086 const ldns_dnssec_zone *zone)
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");
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");
1105 if (zone->names) {
1106 ldns_dnssec_zone_names_print_fmt(out, fmt,
1107 zone->names, false);
1112 void
1113 ldns_dnssec_zone_print(FILE *out, const ldns_dnssec_zone *zone)
1115 ldns_dnssec_zone_print_fmt(out, ldns_output_format_default, zone);
1118 static ldns_status
1119 ldns_dnssec_zone_add_empty_nonterminals_nsec3(
1120 ldns_dnssec_zone *zone, ldns_rbtree_t *nsec3s)
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;
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;
1133 if (!zone) {
1134 return LDNS_STATUS_ERR;
1136 if (zone->soa && zone->soa->name) {
1137 soa_label_count = ldns_dname_label_count(zone->soa->name);
1140 cur_node = ldns_rbtree_first(zone->names);
1141 while (cur_node != LDNS_RBTREE_NULL) {
1142 next_node = ldns_rbtree_next(cur_node);
1144 /* skip glue */
1145 while (next_node != LDNS_RBTREE_NULL &&
1146 next_node->data &&
1147 ((ldns_dnssec_name *)next_node->data)->is_glue
1149 next_node = ldns_rbtree_next(next_node);
1152 if (next_node == LDNS_RBTREE_NULL) {
1153 next_node = ldns_rbtree_first(zone->names);
1155 if (! cur_node->data || ! next_node->data) {
1156 return LDNS_STATUS_ERR;
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);
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)
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;
1177 l2 = ldns_dname_clone_from(next_name, i);
1179 if (!l1 || ldns_dname_compare(l1, l2) != 0) {
1180 /* We have an empty nonterminal, add it to the
1181 * tree
1183 ldns_rbnode_t *node = NULL;
1184 ldns_rdf *ent_name;
1186 if (!(ent_name = ldns_dname_clone_from(
1187 next_name, i))) {
1189 ldns_rdf_deep_free(l1);
1190 ldns_rdf_deep_free(l2);
1191 return LDNS_STATUS_MEM_ERR;
1194 if (nsec3s && zone->_nsec3params) {
1195 ldns_rdf *ent_hashed_name;
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;
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;
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;
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;
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);
1241 ldns_rdf_deep_free(l1);
1242 ldns_rdf_deep_free(l2);
1245 /* we might have inserted a new node after
1246 * the current one so we can't just use next()
1248 if (next_node != ldns_rbtree_first(zone->names)) {
1249 cur_node = next_node;
1250 } else {
1251 cur_node = LDNS_RBTREE_NULL;
1254 return LDNS_STATUS_OK;
1257 ldns_status
1258 ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
1260 return ldns_dnssec_zone_add_empty_nonterminals_nsec3(zone, NULL);
1263 bool
1264 ldns_dnssec_zone_is_nsec3_optout(const ldns_dnssec_zone* zone)
1266 ldns_rr* nsec3;
1267 ldns_rbnode_t* node;
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;
1278 node = ldns_rbtree_next(node);
1281 return false;
1285 * Stuff for calculating and verifying zone digests
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;
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;
1311 INLINE void
1312 dnssec_zone_rr_iter_set_state_for_next_name(dnssec_zone_rr_iter *i)
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;
1318 while (i->name && name != i->apex_name /* not apex */
1320 && ( ldns_dname_label_count(name) != i->apex_labs
1321 || ldns_dname_compare(name, i->apex_name)) /* not apex */
1323 && !ldns_dname_is_subdomain(name, i->apex_name) /* no sub */) {
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;
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;
1343 } else if (!i->nsec3_name) {
1344 i->rrsets = i->name->rrsets;
1345 i->state = DNSSEC_ZONE_RR_ITER_LT_RRSIG;
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;
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.
1361 * 1. There is no NSEC:
1363 * 1.1. All the RRs in the name->rrsets with type < RRSIG,
1364 * state: DNSSEC_ZONE_RR_ITER_LT_RRSIG
1366 * 1.2. Then all the RRSIGs from name->rrsets (likely none)
1367 * state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
1369 * 1.3. Finally the remaining RRs in name->rrsets (type > RRSIG)
1370 * state: DNSSEC_ZONE_RR_ITER_REST
1373 * 2. There is a NSEC of type NSEC with this name:
1375 * 2.1. All the RRs in the name->rrsets with type < RRSIG,
1376 * state: DNSSEC_ZONE_RR_ITER_LT_RRSIG
1378 * 2.2. Then all the RRSIGs from name->rrsets with type < NSEC
1379 * state: DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC
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
1386 * 2.4. Finally the remaining RRs in name->rrsets (type > RRSIG)
1387 * state: DNSSEC_ZONE_RR_ITER_REST
1390 * 3. There is a NSEC of type NSEC3 for this name:
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
1396 * otherwise follow path for "no NSEC" for the name for other RRsets
1398 static ldns_rr *
1399 dnssec_zone_rr_iter_next(dnssec_zone_rr_iter *i)
1401 ldns_rr *nsec3;
1403 for (;;) {
1404 if (i->rrs) {
1405 ldns_rr *rr = i->rrs->rr;
1406 i->rrs = i->rrs->next;
1407 return rr;
1409 switch (i->state) {
1410 case DNSSEC_ZONE_RR_ITER_LT_RRSIG:
1411 if (i->rrsets
1412 && i->rrsets->type < LDNS_RR_TYPE_RRSIG) {
1414 i->rrs = i->rrsets->rrs;
1415 i->rrsets = i->rrsets->next;
1416 break;
1418 i->rrsets4rrsigs = i->name->rrsets;
1419 if (i->name->nsec && ldns_rr_get_type(i->name->nsec)
1420 == LDNS_RR_TYPE_NSEC) {
1422 i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC;
1423 break;
1425 i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NO_NSEC;
1426 /* fallthrough */
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;
1434 i->state = DNSSEC_ZONE_RR_ITER_REST;
1435 /* fallthrough */
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;
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;
1448 dnssec_zone_rr_iter_set_state_for_next_name(i);
1449 break;
1451 case DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC:
1452 if (i->rrsets4rrsigs
1453 && i->rrsets4rrsigs->type < LDNS_RR_TYPE_NSEC) {
1455 i->rrs = i->rrsets4rrsigs->signatures;
1456 i->rrsets4rrsigs = i->rrsets4rrsigs->next;
1457 break;
1459 i->state = DNSSEC_ZONE_RR_ITER_RRSIGs_NSEC_REST;
1460 i->rrs = i->name->nsec_signatures;
1461 break;
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;
1469 i->state = DNSSEC_ZONE_RR_ITER_REST;
1470 return i->name->nsec;
1472 case DNSSEC_ZONE_RR_ITER_NSEC3:
1473 nsec3 = i->nsec3_name->nsec;
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;
1483 /* names for glue can be in the hashed_names
1484 * tree, but will not have a NSEC3
1486 } while (i->nsec3_name && !i->nsec3_name->nsec);
1488 dnssec_zone_rr_iter_set_state_for_next_name(i);
1489 return nsec3;
1491 case DNSSEC_ZONE_RR_ITER_FINI:
1492 return NULL;
1497 static ldns_rr *
1498 dnssec_zone_rr_iter_first(dnssec_zone_rr_iter *i, ldns_dnssec_zone *zone)
1500 if (!i || !zone)
1501 return NULL;
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;
1512 i->node = ldns_rbtree_first(zone->names);
1513 i->name = i->node == LDNS_RBTREE_NULL ? NULL
1514 : (ldns_dnssec_name *)i->node->data;
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);
1523 dnssec_zone_rr_iter_set_state_for_next_name(i);
1524 return dnssec_zone_rr_iter_next(i);
1527 enum enum_zonemd_scheme {
1528 ZONEMD_SCHEME_FIRST = 1,
1529 ZONEMD_SCHEME_SIMPLE = 1,
1530 ZONEMD_SCHEME_LAST = 1
1532 typedef enum enum_zonemd_scheme zonemd_scheme;
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
1540 typedef enum enum_zonemd_hash zonemd_hash;
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;
1550 typedef struct struct_zone_digester zone_digester;
1552 INLINE bool zone_digester_set(zone_digester *zd)
1553 { return zd && (zd->simple_sha384 || zd->simple_sha512); }
1555 INLINE void zone_digester_init(zone_digester *zd)
1556 { memset(zd, 0, sizeof(*zd)); }
1558 static ldns_status
1559 zone_digester_add(zone_digester *zd, zonemd_scheme scheme, zonemd_hash hash)
1561 if (!zd)
1562 return LDNS_STATUS_NULL;
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;
1571 else if (zd->simple_sha384) {
1572 zd->simple_sha384 = 0;
1573 zd->double_sha384 = 1;
1574 return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1576 ldns_sha384_init(&zd->sha384_CTX);
1577 zd->simple_sha384 = 1;
1578 break;
1580 case ZONEMD_HASH_SHA512:
1581 if (zd->double_sha512)
1582 return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1584 else if (zd->simple_sha512) {
1585 zd->simple_sha512 = 0;
1586 zd->double_sha512 = 1;
1587 return LDNS_STATUS_ZONEMD_DOUBLE_OCCURRENCE;
1589 ldns_sha512_init(&zd->sha512_CTX);
1590 zd->simple_sha512 = 1;
1591 break;
1592 default:
1593 return LDNS_STATUS_ZONEMD_UNKNOWN_HASH;
1595 break;
1596 default:
1597 return LDNS_STATUS_ZONEMD_UNKNOWN_SCHEME;
1599 return LDNS_STATUS_OK;
1602 static ldns_status
1603 zone_digester_update(zone_digester *zd, ldns_rr *rr)
1605 uint8_t data[65536];
1606 ldns_buffer buf;
1607 ldns_status st;
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;
1616 if ((st = ldns_rr2buffer_wire_canonical(&buf, rr, LDNS_SECTION_ANSWER)))
1617 return st;
1619 if (zd->simple_sha384)
1620 ldns_sha384_update(&zd->sha384_CTX, data, buf._position);
1622 if (zd->simple_sha512)
1623 ldns_sha512_update(&zd->sha512_CTX, data, buf._position);
1625 return LDNS_STATUS_OK;
1628 INLINE ldns_rr *
1629 new_zonemd(ldns_rr *soa, zonemd_hash hash)
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;
1638 if (!(rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_ZONEMD)))
1639 return NULL;
1641 if (!(rdf = ldns_rdf_clone(ldns_rr_owner(soa))))
1642 goto error;
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));
1648 if (!(rdf = ldns_rdf_clone(ldns_rr_rdf(soa, 2))))
1649 goto error;
1650 ldns_rr_set_rdf(rr, rdf, 0);
1652 if (!(rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, 1)))
1653 goto error;
1654 ldns_rr_set_rdf(rr, rdf, 1);
1656 if (!(rdf = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, hash)))
1657 goto error;
1658 ldns_rr_set_rdf(rr, rdf, 2);
1660 if (!(data = LDNS_XMALLOC(uint8_t, md_len)))
1661 goto error;
1663 if (!(rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, md_len, data)))
1664 goto error;
1665 ldns_rr_set_rdf(rr, rdf, 3);
1667 return rr;
1668 error:
1669 if (data)
1670 LDNS_FREE(data);
1671 ldns_rr_free(rr);
1672 return NULL;
1675 static ldns_rr_list *
1676 zone_digester_export(
1677 zone_digester *zd, ldns_rr *soa, ldns_status *ret_st)
1679 ldns_status st = LDNS_STATUS_OK;
1680 ldns_rr_list *rr_list = NULL;
1681 ldns_rr *sha384 = NULL;
1682 ldns_rr *sha512 = NULL;
1684 if (!zd || !soa)
1685 st = LDNS_STATUS_NULL;
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;
1691 else if (!(rr_list = ldns_rr_list_new()))
1692 st = LDNS_STATUS_MEM_ERR;
1694 else if (zd->simple_sha384
1695 && !(sha384 = new_zonemd(soa, ZONEMD_HASH_SHA384)))
1696 st = LDNS_STATUS_MEM_ERR;
1698 else if (zd->simple_sha512
1699 && !(sha512 = new_zonemd(soa, ZONEMD_HASH_SHA512)))
1700 st = LDNS_STATUS_MEM_ERR;
1702 else if (zd->simple_sha384
1703 && !ldns_rr_list_push_rr(rr_list, sha384))
1704 st = LDNS_STATUS_MEM_ERR;
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;
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;
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;
1732 static ldns_status
1733 ldns_digest_zone(ldns_dnssec_zone *zone, zone_digester *zd)
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 */
1740 if (!zone || !zd || !zone->soa || !zone->soa->name)
1741 return LDNS_STATUS_NULL;
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);
1759 return st;
1762 ldns_status
1763 ldns_dnssec_zone_verify_zonemd(ldns_dnssec_zone *zone)
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;
1774 if (!zone)
1775 return LDNS_STATUS_NULL;
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;
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;
1789 } else if (!zone->soa->hashed_name || !zone->hashed_names)
1790 return LDNS_STATUS_NO_ZONEMD;
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;
1804 /* ZONEMD at apex does really not exist */
1805 return LDNS_STATUS_OK;
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;
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;
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;
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;
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)));
1834 if (!zone_digester_set(&zd))
1835 return LDNS_STATUS_NO_VALID_ZONEMD;
1837 if ((st = ldns_digest_zone(zone, &zd)))
1838 return st;
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);
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;
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;
1857 if (ZONEMD_SCHEME_SIMPLE !=
1858 ldns_rdf2native_int8(ldns_rr_rdf(rrs->rr, 1)))
1859 continue;
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)
1869 valid_zonemds += 1;
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)
1879 valid_zonemds += 1;
1881 return valid_zonemds ? LDNS_STATUS_OK : LDNS_STATUS_NO_VALID_ZONEMD;
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)
1889 ldns_rr *rr = NULL;
1891 if (!rr_list || !rrs)
1892 return LDNS_STATUS_NULL;
1894 if (ldns_rr_list_rr_count(rr_list) == 0)
1895 return LDNS_STATUS_OK;
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);
1904 while ((rr = ldns_rr_list_pop_rr(rr_list))) {
1905 ldns_status st;
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);
1913 return LDNS_STATUS_OK;
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)
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;
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);
1935 if (signflags & LDNS_SIGN_WITH_ZONEMD_SIMPLE_SHA512)
1936 zone_digester_add(&zd, ZONEMD_SCHEME_SIMPLE
1937 , ZONEMD_HASH_SHA512);
1939 if ((st = ldns_digest_zone(zone, &zd)))
1940 return st;
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;
1948 if (!(zonemd_rr_list = zone_digester_export(&zd, soa_rr, &st)))
1949 return st;
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;
1969 zonemd_rrset->type = LDNS_RR_TYPE_ZONEMD;
1970 zonemd_rrset->next = *rrset_ref;
1971 *rrset_ref = zonemd_rrset;
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;
1984 #endif /* HAVE_SSL */