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