OpenDNSSEC-signer 2.1.13
rrset.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2009 NLNet Labs. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 */
26
32#include "config.h"
33#include "file.h"
34#include "hsm.h"
35#include "log.h"
36#include "util.h"
37#include "compat.h"
38#include "signer/rrset.h"
39#include "signer/zone.h"
40
41static const char* rrset_str = "rrset";
42
47void
48log_rr(ldns_rr* rr, const char* pre, int level)
49{
50 char* str = NULL;
51 size_t i = 0;
52
53 if (ods_log_get_level() < level) {
54 return;
55 }
56 str = ldns_rr2str(rr);
57 if (!str) {
58 ods_log_error("[%s] %s: Error converting RR to string", rrset_str,
59 pre?pre:"");
60 return;
61 }
62 str[(strlen(str))-1] = '\0';
63 /* replace tabs with white space */
64 for (i=0; i < strlen(str); i++) {
65 if (str[i] == '\t') {
66 str[i] = ' ';
67 }
68 }
69 if (level == LOG_EMERG) {
70 ods_fatal_exit("[%s] %s: %s", rrset_str, pre?pre:"", str);
71 } else if (level == LOG_ALERT) {
72 ods_log_alert("[%s] %s: %s", rrset_str, pre?pre:"", str);
73 } else if (level == LOG_CRIT) {
74 ods_log_crit("[%s] %s: %s", rrset_str, pre?pre:"", str);
75 } else if (level == LOG_ERR) {
76 ods_log_error("[%s] %s: %s", rrset_str, pre?pre:"", str);
77 } else if (level == LOG_WARNING) {
78 ods_log_warning("[%s] %s: %s", rrset_str, pre?pre:"", str);
79 } else if (level == LOG_NOTICE) {
80 ods_log_info("[%s] %s: %s", rrset_str, pre?pre:"", str);
81 } else if (level == LOG_INFO) {
82 ods_log_verbose("[%s] %s: %s", rrset_str, pre?pre:"", str);
83 } else if (level == LOG_DEBUG) {
84 ods_log_debug("[%s] %s: %s", rrset_str, pre?pre:"", str);
85 } else if (level == LOG_DEEEBUG) {
86 ods_log_deeebug("[%s] %s: %s", rrset_str, pre?pre:"", str);
87 } else {
88 ods_log_deeebug("[%s] %s: %s", rrset_str, pre?pre:"", str);
89 }
90 free((void*)str);
91}
92
93
98void
99log_rrset(ldns_rdf* dname, ldns_rr_type type, const char* pre, int level)
100{
101 char* str = NULL;
102 size_t i = 0;
103
104 if (ods_log_get_level() < level) {
105 return;
106 }
107 str = ldns_rdf2str(dname);
108 if (!str) {
109 return;
110 }
111 str[(strlen(str))-1] = '\0';
112 /* replace tabs with white space */
113 for (i=0; i < strlen(str); i++) {
114 if (str[i] == '\t') {
115 str[i] = ' ';
116 }
117 }
118 if (level == LOG_EMERG) {
119 ods_fatal_exit("[%s] %s: <%s,%s>", rrset_str, pre?pre:"", str,
120 rrset_type2str(type));
121 } else if (level == LOG_ALERT) {
122 ods_log_alert("[%s] %s: <%s,%s>", rrset_str, pre?pre:"", str,
123 rrset_type2str(type));
124 } else if (level == LOG_CRIT) {
125 ods_log_crit("[%s] %s: <%s,%s>", rrset_str, pre?pre:"", str,
126 rrset_type2str(type));
127 } else if (level == LOG_ERR) {
128 ods_log_error("[%s] %s: <%s,%s>", rrset_str, pre?pre:"", str,
129 rrset_type2str(type));
130 } else if (level == LOG_WARNING) {
131 ods_log_warning("[%s] %s: <%s,%s>", rrset_str, pre?pre:"", str,
132 rrset_type2str(type));
133 } else if (level == LOG_NOTICE) {
134 ods_log_info("[%s] %s: <%s,%s>", rrset_str, pre?pre:"", str,
135 rrset_type2str(type));
136 } else if (level == LOG_INFO) {
137 ods_log_verbose("[%s] %s: <%s,%s>", rrset_str, pre?pre:"", str,
138 rrset_type2str(type));
139 } else if (level == LOG_DEBUG) {
140 ods_log_debug("[%s] %s: <%s,%s>", rrset_str, pre?pre:"", str,
141 rrset_type2str(type));
142 } else if (level == LOG_DEEEBUG) {
143 ods_log_deeebug("[%s] %s: <%s,%s>", rrset_str, pre?pre:"", str,
144 rrset_type2str(type));
145 } else {
146 ods_log_deeebug("[%s] %s: <%s,%s>", rrset_str, pre?pre:"", str,
147 rrset_type2str(type));
148 }
149 free((void*)str);
150}
151
152
157const char*
158rrset_type2str(ldns_rr_type type)
159{
160 if (type == LDNS_RR_TYPE_IXFR) {
161 return "IXFR";
162 } else if (type == LDNS_RR_TYPE_AXFR) {
163 return "AXFR";
164 } else if (type == LDNS_RR_TYPE_MAILB) {
165 return "MAILB";
166 } else if (type == LDNS_RR_TYPE_MAILA) {
167 return "MAILA";
168 } else if (type == LDNS_RR_TYPE_ANY) {
169 return "ANY";
170 } else {
171 const ldns_rr_descriptor* descriptor = ldns_rr_descript(type);
172 if (descriptor && descriptor->_name) {
173 return descriptor->_name;
174 }
175 }
176 return "TYPE???";
177}
178
179static int
180memberdestroy(void* dummy, void* member)
181{
182 rrsig_type* sig = (rrsig_type*) member;
183 (void)dummy;
184 free((void*) sig->key_locator);
185 sig->key_locator = NULL;
186 /* The rrs may still be in use by IXFRs so cannot do ldns_rr_free(sig->rr); */
187 ldns_rr_free(sig->rr);
188 sig->owner = NULL;
189 sig->rr = NULL;
190 return 0;
191}
192
193
199rrset_create(zone_type* zone, ldns_rr_type type)
200{
201 rrset_type* rrset = NULL;
202 if (!type || !zone) {
203 return NULL;
204 }
205 CHECKALLOC(rrset = (rrset_type*) malloc(sizeof(rrset_type)));
206 if (!rrset) {
207 ods_log_error("[%s] unable to create RRset %u: allocator_alloc() "
208 "failed", rrset_str, (unsigned) type);
209 return NULL;
210 }
211 rrset->next = NULL;
212 rrset->rrs = NULL;
213 rrset->domain = NULL;
214 rrset->zone = zone;
215 rrset->rrtype = type;
216 rrset->rr_count = 0;
217 collection_create_array(&rrset->rrsigs, sizeof(rrsig_type), rrset->zone->rrstore);
218 rrset->needs_signing = 0;
219 return rrset;
220}
221
222collection_class
224{
225 collection_class klass;
226 collection_class_allocated(&klass, NULL, memberdestroy);
227 return klass;
228}
229
230
235rr_type*
236rrset_lookup_rr(rrset_type* rrset, ldns_rr* rr)
237{
238 ldns_status lstatus = LDNS_STATUS_OK;
239 int cmp = 0;
240 size_t i = 0;
241
242 if (!rrset || !rr || rrset->rr_count <= 0) {
243 return NULL;
244 }
245 for (i=0; i < rrset->rr_count; i++) {
246 lstatus = util_dnssec_rrs_compare(rrset->rrs[i].rr, rr, &cmp);
247 if (lstatus != LDNS_STATUS_OK) {
248 ods_log_error("[%s] unable to lookup RR: compare failed (%s)",
249 rrset_str, ldns_get_errorstr_by_id(lstatus));
250 return NULL;
251 }
252 if (!cmp) { /* equal */
253 return &rrset->rrs[i];
254 }
255 }
256 return NULL;
257}
258
262uint32_t
263rrset_lookup_ttl(rrset_type* rrset, uint32_t default_ttl)
264{
265 for (int i = 0; i < rrset->rr_count; i++) {
266 if (!rrset->rrs[i].is_added) continue;
267 return ldns_rr_ttl(rrset->rrs[i].rr);
268 }
269 return default_ttl;
270}
271
272
277size_t
279{
280 size_t i = 0;
281 size_t count = 0;
282 if (!rrset) {
283 return 0;
284 }
285 for (i=0; i < rrset->rr_count; i++) {
286 if (rrset->rrs[i].is_added) {
287 count++;
288 }
289 }
290 return count;
291}
292
293
298rr_type*
299rrset_add_rr(rrset_type* rrset, ldns_rr* rr)
300{
301 rr_type* rrs_old = NULL;
302
303 ods_log_assert(rrset);
304 ods_log_assert(rr);
305 ods_log_assert(rrset->rrtype == ldns_rr_get_type(rr));
306
307 rrs_old = rrset->rrs;
308 CHECKALLOC(rrset->rrs = (rr_type*) malloc((rrset->rr_count + 1) * sizeof(rr_type)));
309 if (!rrset->rrs) {
310 ods_fatal_exit("[%s] fatal unable to add RR: allocator_alloc() failed",
311 rrset_str);
312 }
313 if (rrs_old) {
314 memcpy(rrset->rrs, rrs_old, (rrset->rr_count) * sizeof(rr_type));
315 }
316 free(rrs_old);
317 rrset->rr_count++;
318 rrset->rrs[rrset->rr_count - 1].owner = rrset->domain;
319 rrset->rrs[rrset->rr_count - 1].rr = rr;
320 rrset->rrs[rrset->rr_count - 1].exists = 0;
321 rrset->rrs[rrset->rr_count - 1].is_added = 1;
322 rrset->rrs[rrset->rr_count - 1].is_removed = 0;
323 rrset->needs_signing = 1;
324 log_rr(rr, "+RR", LOG_DEEEBUG);
325 return &rrset->rrs[rrset->rr_count -1];
326}
327
328
333void
334rrset_del_rr(rrset_type* rrset, uint16_t rrnum)
335{
336 rr_type* rrs_orig = NULL;
337
338 ods_log_assert(rrset);
339 ods_log_assert(rrnum < rrset->rr_count);
340
341 log_rr(rrset->rrs[rrnum].rr, "-RR", LOG_DEEEBUG);
342 rrset->rrs[rrnum].owner = NULL; /* who owns owner? */
343 ldns_rr_free(rrset->rrs[rrnum].rr);
344 while (rrnum < rrset->rr_count-1) {
345 rrset->rrs[rrnum] = rrset->rrs[rrnum+1];
346 rrnum++;
347 }
348 memset(&rrset->rrs[rrset->rr_count-1], 0, sizeof(rr_type));
349 rrs_orig = rrset->rrs;
350 CHECKALLOC(rrset->rrs = (rr_type*) malloc((rrset->rr_count - 1) * sizeof(rr_type)));
351 if(!rrset->rrs) {
352 ods_fatal_exit("[%s] fatal unable to delete RR: allocator_alloc() failed",
353 rrset_str);
354 }
355 memcpy(rrset->rrs, rrs_orig, (rrset->rr_count -1) * sizeof(rr_type));
356 free(rrs_orig);
357 rrset->rr_count--;
358 rrset->needs_signing = 1;
359}
360
365void
366rrset_diff(rrset_type* rrset, unsigned is_ixfr, unsigned more_coming)
367{
368 zone_type* zone = NULL;
369 uint16_t i = 0;
370 uint8_t del_sigs = 0;
371 if (!rrset) {
372 return;
373 }
374 zone = (zone_type*) rrset->zone;
375 /* CAUTION: both iterator and condition (implicit) are changed
376 * within the loop. */
377 for (i=0; i < rrset->rr_count; i++) {
378 if (rrset->rrs[i].is_added) {
379 if (!rrset->rrs[i].exists) {
380 /* ixfr +RR */
381 if (zone->db->is_initialized) {
382 pthread_mutex_lock(&zone->ixfr->ixfr_lock);
383 ixfr_add_rr(zone->ixfr, rrset->rrs[i].rr);
384 pthread_mutex_unlock(&zone->ixfr->ixfr_lock);
385 }
386 del_sigs = 1;
387 }
388 rrset->rrs[i].exists = 1;
389 if ((rrset->rrtype == LDNS_RR_TYPE_DNSKEY) && more_coming) {
390 continue;
391 }
392 rrset->rrs[i].is_added = 0;
393 } else if (!is_ixfr || rrset->rrs[i].is_removed) {
394 if (rrset->rrs[i].exists && zone->db->is_initialized) {
395 /* ixfr -RR */
396 pthread_mutex_lock(&zone->ixfr->ixfr_lock);
397 ixfr_del_rr(zone->ixfr, rrset->rrs[i].rr);
398 pthread_mutex_unlock(&zone->ixfr->ixfr_lock);
399 }
400 rrset->rrs[i].exists = 0;
401 rrset_del_rr(rrset, i);
402 del_sigs = 1;
403 i--;
404 }
405 }
406 if (del_sigs) {
407 rrset_drop_rrsigs(zone, rrset);
408 }
409}
410
415void
417{
418 rrsig_type* rrsig;
419 while((rrsig = collection_iterator(rrset->rrsigs))) {
420 /* ixfr -RRSIG */
421 if (zone->db->is_initialized) {
422 pthread_mutex_lock(&zone->ixfr->ixfr_lock);
423 ixfr_del_rr(zone->ixfr, rrsig->rr);
424 pthread_mutex_unlock(&zone->ixfr->ixfr_lock);
425 }
426 collection_del_cursor(rrset->rrsigs);
427 }
428}
429
434void
435rrset_add_rrsig(rrset_type* rrset, ldns_rr* rr,
436 const char* locator, uint32_t flags)
437{
438 rrsig_type rrsig;
439 ods_log_assert(rrset);
440 ods_log_assert(rr);
441 ods_log_assert(ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG);
442 rrsig.owner = rrset->domain;
443 rrsig.rr = rr;
444 rrsig.key_locator = locator;
445 rrsig.key_flags = flags;
446 collection_add(rrset->rrsigs, &rrsig);
447}
448
453static ldns_rr_list*
454rrset2rrlist(rrset_type* rrset)
455{
456 ldns_rr_list* rr_list = NULL;
457 int ret = 0;
458 size_t i = 0;
459 rr_list = ldns_rr_list_new();
460 for (i=0; i < rrset->rr_count; i++) {
461 if (!rrset->rrs[i].exists) {
462 log_rr(rrset->rrs[i].rr, "RR does not exist", LOG_WARNING);
463 continue;
464 }
465 ret = (int) ldns_rr_list_push_rr(rr_list, rrset->rrs[i].rr);
466 if (!ret) {
467 ldns_rr_list_free(rr_list);
468 return NULL;
469 }
470 if (rrset->rrtype == LDNS_RR_TYPE_CNAME ||
471 rrset->rrtype == LDNS_RR_TYPE_DNAME) {
472 /* singleton types */
473 return rr_list;
474 }
475 }
476 ldns_rr_list_sort(rr_list);
477 return rr_list;
478}
479
480
485static void
486rrset_sigvalid_period(signconf_type* sc, ldns_rr_type rrtype, time_t signtime,
487 time_t* inception, time_t* expiration)
488{
489 time_t jitter = 0;
490 time_t offset = 0;
491 time_t validity = 0;
492 time_t random_jitter = 0;
493 if (!sc || !rrtype || !signtime) {
494 return;
495 }
496 jitter = duration2time(sc->sig_jitter);
497 if (jitter) {
498 random_jitter = ods_rand(jitter*2);
499 }
500 offset = duration2time(sc->sig_inception_offset);
501 switch (rrtype) {
502 case LDNS_RR_TYPE_NSEC:
503 case LDNS_RR_TYPE_NSEC3:
504 validity = duration2time(sc->sig_validity_denial);
505 break;
506 case LDNS_RR_TYPE_DNSKEY:
507 if (sc->sig_validity_keyset != NULL && duration2time(sc->sig_validity_keyset) > 0) {
508 validity = duration2time(sc->sig_validity_keyset);
509 } else {
510 validity = duration2time(sc->sig_validity_default);
511 }
512 break;
513 default:
514 validity = duration2time(sc->sig_validity_default);
515 }
516 *inception = signtime - offset;
517 *expiration = (signtime + validity + random_jitter) - jitter;
518}
519
520
524};
525
526static int
527rrsigkeyismatching(rrsig_type* rrsig, key_type* key)
528{
529 if(rrsig->key_flags == key->flags && !strcmp(rrsig->key_locator,key->locator)) {
530 return 1;
531 } else {
532 return 0;
533 }
534}
535
536static void
537rrsigkeymatching(signconf_type* signconf, int nrrsigs, rrsig_type** rrsigs, struct rrsigkeymatching** rrsigkeymatchingptr, int* nrrsigkeymatchingptr)
538{
539 int nmatches = 0;
540 struct rrsigkeymatching* matches = malloc(sizeof(struct rrsigkeymatching) * (signconf->keys->count + nrrsigs));
541 for(int i=0; i<nrrsigs; i++) {
542 matches[nmatches].signature = rrsigs[i];
543 matches[nmatches].key = NULL;
544 ++nmatches;
545 }
546 for(int keyidx=0; keyidx<signconf->keys->count; keyidx++) {
547 int matchidx;
548 for(matchidx=0; matchidx<nmatches; matchidx++) {
549 if(matches[matchidx].signature && rrsigkeyismatching(matches[matchidx].signature, &signconf->keys->keys[keyidx])) {
550 matches[matchidx].key = &signconf->keys->keys[keyidx];
551 break;
552 }
553 }
554 if(matchidx==nmatches) {
555 matches[nmatches].signature = NULL;
556 matches[nmatches].key = &signconf->keys->keys[keyidx];
557 ++nmatches;
558 }
559 }
560 *rrsigkeymatchingptr = matches;
561 *nrrsigkeymatchingptr = nmatches;
562}
563
564
569ods_status
570rrset_sign(hsm_ctx_t* ctx, rrset_type* rrset, time_t signtime)
571{
572 ods_status status;
573 zone_type* zone = NULL;
574 uint32_t newsigs = 0;
575 uint32_t reusedsigs = 0;
576 ldns_rr* rrsig = NULL;
578 ldns_rr_list* rr_list = NULL;
579 ldns_rr_list* rr_list_clone = NULL;
580 const char* locator = NULL;
581 time_t inception = 0;
582 time_t expiration = 0;
583 size_t i = 0, j;
584 domain_type* domain = NULL;
585 ldns_rr_type dstatus = LDNS_RR_TYPE_FIRST;
586 ldns_rr_type delegpt = LDNS_RR_TYPE_FIRST;
587 uint8_t algorithm = 0;
588
589 ods_log_assert(ctx);
590 ods_log_assert(rrset);
591 zone = (zone_type*) rrset->zone;
592 ods_log_assert(zone);
593 ods_log_assert(zone->signconf);
594 /* Recycle signatures */
595 if (rrset->rrtype == LDNS_RR_TYPE_NSEC ||
596 rrset->rrtype == LDNS_RR_TYPE_NSEC3) {
597 dstatus = LDNS_RR_TYPE_SOA;
598 delegpt = LDNS_RR_TYPE_SOA;
599 } else {
600 domain = (domain_type*) rrset->domain;
601 dstatus = domain_is_occluded(domain);
602 delegpt = domain_is_delegpt(domain);
603 }
604
605 int nrrsigs;
606 for(nrrsigs=0; (signature = collection_iterator(rrset->rrsigs)); nrrsigs++)
607 ;
608 rrsig_type** rrsigs = malloc(sizeof(rrsig_type*) * nrrsigs);
609 for(i=0; (signature = collection_iterator(rrset->rrsigs)); i++) {
610 assert(signature);
611 rrsigs[i] = signature;
612 }
613 struct rrsigkeymatching* matchedsignatures = NULL;
614 int nmatchedsignatures;
615 rrsigkeymatching(zone->signconf, nrrsigs, rrsigs, &matchedsignatures, &nmatchedsignatures);
616
617 rrset->needs_signing = 0;
618
619 ods_log_assert(rrset->rrs);
620 ods_log_assert(rrset->rrs[0].rr);
621
622 /* Skip delegation, glue and occluded RRsets */
623 if (dstatus != LDNS_RR_TYPE_SOA) {
624 log_rrset(ldns_rr_owner(rrset->rrs[0].rr), rrset->rrtype,
625 "skip signing occluded RRset", LOG_DEEEBUG);
626 free(rrsigs);
627 free(matchedsignatures);
628 return ODS_STATUS_OK;
629 }
630 if (delegpt != LDNS_RR_TYPE_SOA && rrset->rrtype != LDNS_RR_TYPE_DS) {
631 log_rrset(ldns_rr_owner(rrset->rrs[0].rr), rrset->rrtype,
632 "skip signing delegation RRset", LOG_DEEEBUG);
633 free(rrsigs);
634 free(matchedsignatures);
635 return ODS_STATUS_OK;
636 }
637
638 log_rrset(ldns_rr_owner(rrset->rrs[0].rr), rrset->rrtype,
639 "sign RRset", LOG_DEEEBUG);
640 ods_log_assert(dstatus == LDNS_RR_TYPE_SOA ||
641 (delegpt == LDNS_RR_TYPE_SOA || rrset->rrtype == LDNS_RR_TYPE_DS));
642 /* Transmogrify rrset */
643 rr_list = rrset2rrlist(rrset);
644 if (ldns_rr_list_rr_count(rr_list) <= 0) {
645 /* Empty RRset, no signatures needed */
646 ldns_rr_list_free(rr_list);
647 free(rrsigs);
648 free(matchedsignatures);
649 return ODS_STATUS_OK;
650 }
651 /* Use rr_list_clone for signing, keep the original rr_list untouched for case preservation */
652 rr_list_clone = ldns_rr_list_clone(rr_list);
653
654 /* Further in the code the ORIG_TTL field for the signature will be set
655 * to the TTL of the first RR in the list. We must make sure all RR's
656 * have the same TTL when signing. We do not need to publish these TTLs.
657 * We find the smallest TTL as other software seems to do this.
658 **/
659 uint32_t min_ttl = ldns_rr_ttl(ldns_rr_list_rr(rr_list_clone, 0));
660 for (i = 1; i < ldns_rr_list_rr_count(rr_list_clone); i++) {
661 uint32_t rr_ttl = ldns_rr_ttl(ldns_rr_list_rr(rr_list_clone, i));
662 if (rr_ttl < min_ttl) min_ttl = rr_ttl;
663 }
664 for (i = 0; i < ldns_rr_list_rr_count(rr_list_clone); i++) {
665 ldns_rr_set_ttl(ldns_rr_list_rr(rr_list_clone, i), min_ttl);
666 }
667
668 assert(zone->signconf);
669 /* Calculate signature validity */
670 rrset_sigvalid_period(zone->signconf, rrset->rrtype, signtime,
671 &inception, &expiration);
672 uint32_t refresh = 0;
673 if (zone->signconf && zone->signconf->sig_refresh_interval) {
674 refresh = (uint32_t) (signtime + duration2time(zone->signconf->sig_refresh_interval));
675 }
676
677 /* for each signature-key pair, determine whether the signature is valid and/or the key
678 * should produce a signature.
679 */
680 for (int i = 0; i < nmatchedsignatures; i++) {
681 if (matchedsignatures[i].signature) {
682 assert(matchedsignatures[i].signature->rr);
683 expiration = ldns_rdf2native_int32(ldns_rr_rrsig_expiration(matchedsignatures[i].signature->rr));
684 inception = ldns_rdf2native_int32(ldns_rr_rrsig_inception(matchedsignatures[i].signature->rr));
685 }
686 if (matchedsignatures[i].key && matchedsignatures[i].key->ksk && !matchedsignatures[i].key->zsk && rrset->rrtype != LDNS_RR_TYPE_DNSKEY) {
687 /* If KSK (not CSK) don't sign non-DNSKEY RRsets */
688 matchedsignatures[i].key = NULL;
689 matchedsignatures[i].signature = NULL;
690 } else if (matchedsignatures[i].key && !matchedsignatures[i].key->ksk && !matchedsignatures[i].key->zsk && rrset->rrtype != LDNS_RR_TYPE_DNSKEY && !matchedsignatures[i].signature) {
691 /* Drop keys that aren't ZSK or KSK and still have signatures */
692 matchedsignatures[i].key = NULL;
693 } else if (matchedsignatures[i].key && !matchedsignatures[i].key->ksk && !matchedsignatures[i].key->zsk && rrset->rrtype != LDNS_RR_TYPE_DNSKEY && !matchedsignatures[i].key->publish) {
694 matchedsignatures[i].key = NULL;
695 matchedsignatures[i].signature = NULL;
696 } else if (matchedsignatures[i].key && !matchedsignatures[i].key->ksk && !matchedsignatures[i].key->zsk && rrset->rrtype == LDNS_RR_TYPE_DNSKEY) {
697 matchedsignatures[i].key = NULL;
698 matchedsignatures[i].signature = NULL;
699 } else if (matchedsignatures[i].key && !matchedsignatures[i].key->ksk && matchedsignatures[i].key->zsk && rrset->rrtype == LDNS_RR_TYPE_DNSKEY) {
700 /* If ZSK (not CSK) don't sign DNSKEY RRset */
701 matchedsignatures[i].key = NULL;
702 matchedsignatures[i].signature = NULL;
703 } else if (matchedsignatures[i].key && matchedsignatures[i].key->ksk && matchedsignatures[i].key->locator == NULL) {
704 /* If key has no locator, and should be pre-signed dnskey RR, skip */
705 matchedsignatures[i].key = NULL;
706 } else if (refresh <= (uint32_t) signtime) {
707 /* If Refresh is disabled, drop all signatures */
708 matchedsignatures[i].signature = NULL;
709 } else if (matchedsignatures[i].signature && expiration < refresh && matchedsignatures[i].key && !matchedsignatures[i].key->ksk && !matchedsignatures[i].key->zsk) {
710 /* Signature has expired but key not used for signing anymore */
711 matchedsignatures[i].signature = NULL;
712 matchedsignatures[i].key = NULL;
713 } else if (matchedsignatures[i].signature && expiration < refresh) {
714 /* Expiration - Refresh has passed */
715 matchedsignatures[i].signature = NULL;
716 } else if (matchedsignatures[i].signature && inception > (uint32_t) signtime) {
717 /* Inception has not yet passed */
718 matchedsignatures[i].signature = NULL;
719 } else if (matchedsignatures[i].signature && !matchedsignatures[i].key) {
720 /* Orphaned signatures */
721 matchedsignatures[i].signature = NULL;
722 } else if (dstatus != LDNS_RR_TYPE_SOA || (delegpt != LDNS_RR_TYPE_SOA && rrset->rrtype != LDNS_RR_TYPE_DS)) {
723 /* Skip delegation, glue and occluded RRsets */
724 matchedsignatures[i].key = NULL;
725 matchedsignatures[i].signature = NULL;
726 } else {
727 ods_log_assert(dstatus == LDNS_RR_TYPE_SOA || (delegpt == LDNS_RR_TYPE_SOA || rrset->rrtype == LDNS_RR_TYPE_DS));
728 }
729 }
730 /* At this time, each signature, key pair is valid, if there is a signature and a key, it is valid, if there is
731 * no key, there should be no signature, if there is no key, there should be no signature. However for DNS
732 * optimization, there needs to be no signature, if there is a signature for another key with the same algorithm
733 * that is still valid.
734 */
735 for (int i = 0; i < nmatchedsignatures; i++) {
736 if (!matchedsignatures[i].signature && matchedsignatures[i].key) {
737 /* We now know this key doesn't sign the set, we will only
738 * sign when there isn't already an active key for that algorithm
739 */
740 int j;
741 for (j = 0; j < nmatchedsignatures; j++) {
742 if (j != i) {
743 if (matchedsignatures[j].key && matchedsignatures[j].key->publish && matchedsignatures[j].signature && matchedsignatures[j].key->algorithm == matchedsignatures[i].key->algorithm) {
744 break;
745 }
746 }
747 }
748 if (j < nmatchedsignatures) {
749 matchedsignatures[i].key = NULL;
750 matchedsignatures[i].signature = NULL;
751 }
752 }
753 }
754
755 /* For each of the existing signatures, if they are no longer present in the output, delete them
756 * The rrsigs array is guaranteed to line up with the mathcedsignatures array
757 */
758 if (zone->db->is_initialized) {
759 pthread_mutex_lock(&zone->ixfr->ixfr_lock);
760 for(i=0; i<nrrsigs; i++) {
761 if(matchedsignatures[i].signature == NULL) {
762 if (rrsigs[i] != NULL) {
763 ixfr_del_rr(zone->ixfr, rrsigs[i]->rr);
764 }
765 }
766 }
767 pthread_mutex_unlock(&zone->ixfr->ixfr_lock);
768 }
769 for(i=0; i<nrrsigs; i++) {
770 if(matchedsignatures[i].signature == NULL) {
771 if (rrsigs[i] != NULL) {
772 while((signature = collection_iterator(rrset->rrsigs))) {
773 if(signature == rrsigs[i]) {
774 collection_del_cursor(rrset->rrsigs);
775 }
776 }
777 }
778 } else
779 ++reusedsigs;
780 }
781 /* only at this time we have no need for the list anymore (just the list) */
782 free(rrsigs);
783
784 /* Calculate signature validity for new signatures */
785 rrset_sigvalid_period(zone->signconf, rrset->rrtype, signtime, &inception, &expiration);
786 /* for each missing signature (no signature, but with key in the tuplie list) produce a signature */
787 for (int i = 0; i < nmatchedsignatures; i++) {
788 if (!matchedsignatures[i].signature && matchedsignatures[i].key) {
789 /* Sign the RRset with this key */
790 ods_log_deeebug("[%s] signing RRset[%i] with key %s", rrset_str,
791 rrset->rrtype, zone->signconf->keys->keys[i].locator);
792 rrsig = lhsm_sign(ctx, rr_list_clone, matchedsignatures[i].key,
793 zone->apex, inception, expiration);
794 if (!rrsig) {
795 ods_log_crit("[%s] unable to sign RRset[%i]: lhsm_sign() failed",
796 rrset_str, rrset->rrtype);
797 free(matchedsignatures);
798 ldns_rr_list_free(rr_list);
799 ldns_rr_list_free(rr_list_clone);
800 return ODS_STATUS_HSM_ERR;
801 }
802 /* Add signature */
803 locator = strdup(matchedsignatures[i].key->locator);
804 rrset_add_rrsig(rrset, rrsig, locator, matchedsignatures[i].key->flags);
805 newsigs++;
806 /* ixfr +RRSIG */
807 if (zone->db->is_initialized) {
808 pthread_mutex_lock(&zone->ixfr->ixfr_lock);
809 ixfr_add_rr(zone->ixfr, rrsig);
810 pthread_mutex_unlock(&zone->ixfr->ixfr_lock);
811 }
812 }
813 }
814 /* Add signatures for DNSKEY if have been configured to be added explicitjy */
815 if(rrset->rrtype == LDNS_RR_TYPE_DNSKEY && zone->signconf->dnskey_signature) {
816 for(i=0; zone->signconf->dnskey_signature[i]; i++) {
817 rrsig = NULL;
818 if ((status = rrset_getliteralrr(&rrsig, zone->signconf->dnskey_signature[i], duration2time(zone->signconf->dnskey_ttl), zone->apex)) != ODS_STATUS_OK) {
819 ods_log_error("[%s] unable to publish dnskeys for zone %s: "
820 "error decoding literal dnskey", rrset_str, zone->name);
821 ldns_rr_list_deep_free(rr_list_clone);
822 return status;
823 }
824 /* Add signature */
825 rrset_add_rrsig(rrset, rrsig, NULL, 0);
826 newsigs++;
827 /* ixfr +RRSIG */
828 if (zone->db->is_initialized) {
829 pthread_mutex_lock(&zone->ixfr->ixfr_lock);
830 ixfr_add_rr(zone->ixfr, rrsig);
831 pthread_mutex_unlock(&zone->ixfr->ixfr_lock);
832 }
833 }
834 }
835
836 /* RRset signing completed */
837 free(matchedsignatures);
838 ldns_rr_list_free(rr_list);
839 ldns_rr_list_deep_free(rr_list_clone);
840 pthread_mutex_lock(&zone->stats->stats_lock);
841 if (rrset->rrtype == LDNS_RR_TYPE_SOA) {
842 zone->stats->sig_soa_count += newsigs;
843 }
844 zone->stats->sig_count += newsigs;
845 zone->stats->sig_reuse += reusedsigs;
846 pthread_mutex_unlock(&zone->stats->stats_lock);
847 return ODS_STATUS_OK;
848}
849
850ods_status
851rrset_getliteralrr(ldns_rr** dnskey, const char *resourcerecord, uint32_t ttl, ldns_rdf* apex)
852{
853 uint8_t dnskeystring[4096];
854 ldns_status ldnsstatus;
855 int len;
856 if ((len = b64_pton(resourcerecord, dnskeystring, sizeof (dnskeystring) - 2)) < 0) {
857 return ODS_STATUS_PARSE_ERR;
858 }
859 dnskeystring[len] = '\0';
860 if ((ldnsstatus = ldns_rr_new_frm_str(dnskey, (const char*) dnskeystring, ttl, apex, NULL)) != LDNS_STATUS_OK) {
861 return ODS_STATUS_PARSE_ERR;
862 }
863 return ODS_STATUS_OK;
864}
865
870void
871rrset_print(FILE* fd, rrset_type* rrset, int skip_rrsigs,
872 ods_status* status)
873{
874 rrsig_type* rrsig;
875 uint16_t i = 0;
876 ods_status result = ODS_STATUS_OK;
877
878 if (!rrset || !fd) {
879 ods_log_crit("[%s] unable to print RRset: rrset or fd missing",
880 rrset_str);
881 if (status) {
882 *status = ODS_STATUS_ASSERT_ERR;
883 }
884 } else {
885 for (i=0; i < rrset->rr_count; i++) {
886 if (rrset->rrs[i].exists) {
887 result = util_rr_print(fd, rrset->rrs[i].rr);
888 if (rrset->rrtype == LDNS_RR_TYPE_CNAME ||
889 rrset->rrtype == LDNS_RR_TYPE_DNAME) {
890 /* singleton types */
891 break;
892 }
893 if (result != ODS_STATUS_OK) {
894 zone_type* zone = (zone_type*) rrset->zone;
895 log_rrset(ldns_rr_owner(rrset->rrs[i].rr), rrset->rrtype,
896 "error printing RRset", LOG_CRIT);
897 zone->adoutbound->error = 1;
898 break;
899 }
900 }
901 }
902 if (! skip_rrsigs) {
903 result = ODS_STATUS_OK;
904 while((rrsig = collection_iterator(rrset->rrsigs))) {
905 if (result == ODS_STATUS_OK) {
906 result = util_rr_print(fd, rrsig->rr);
907 if (result != ODS_STATUS_OK) {
908 zone_type* zone = rrset->zone;
909 log_rrset(ldns_rr_owner(rrset->rrs[i].rr), rrset->rrtype,
910 "error printing RRset", LOG_CRIT);
911 zone->adoutbound->error = 1;
912 }
913 }
914 }
915 }
916 if (status) {
917 *status = result;
918 }
919 }
920}
921
922
927void
929{
930 uint16_t i = 0;
931 if (!rrset) {
932 return;
933 }
934 rrset_cleanup(rrset->next);
935 rrset->next = NULL;
936 rrset->domain = NULL;
937 for (i=0; i < rrset->rr_count; i++) {
938 ldns_rr_free(rrset->rrs[i].rr);
939 rrset->rrs[i].owner = NULL;
940 }
941 collection_destroy(&rrset->rrsigs);
942 free(rrset->rrs);
943 free(rrset);
944}
945
950void
951rrset_backup2(FILE* fd, rrset_type* rrset)
952{
953 rrsig_type* rrsig;
954 char* str = NULL;
955 if (!rrset || !fd) {
956 return;
957 }
958 while((rrsig = collection_iterator(rrset->rrsigs))) {
959 if ((str = ldns_rr2str(rrsig->rr))) {
960 fprintf(fd, "%.*s; {locator %s flags %u}\n", (int)strlen(str)-1, str,
961 rrsig->key_locator, rrsig->key_flags);
962 free(str);
963 }
964 }
965}
ldns_rr_type domain_is_delegpt(domain_type *domain)
Definition: domain.c:344
ldns_rr_type domain_is_occluded(domain_type *domain)
Definition: domain.c:369
ldns_rr * lhsm_sign(hsm_ctx_t *ctx, ldns_rr_list *rrset, key_type *key_id, ldns_rdf *owner, time_t inception, time_t expiration)
Definition: hsm.c:138
void ixfr_del_rr(ixfr_type *ixfr, ldns_rr *rr)
Definition: ixfr.c:131
void ixfr_add_rr(ixfr_type *ixfr, ldns_rr *rr)
Definition: ixfr.c:106
ods_status rrset_sign(hsm_ctx_t *ctx, rrset_type *rrset, time_t signtime)
Definition: rrset.c:570
rr_type * rrset_lookup_rr(rrset_type *rrset, ldns_rr *rr)
Definition: rrset.c:236
size_t rrset_count_rr_is_added(rrset_type *rrset)
Definition: rrset.c:278
rr_type * rrset_add_rr(rrset_type *rrset, ldns_rr *rr)
Definition: rrset.c:299
collection_class rrset_store_initialize()
Definition: rrset.c:223
ods_status rrset_getliteralrr(ldns_rr **dnskey, const char *resourcerecord, uint32_t ttl, ldns_rdf *apex)
Definition: rrset.c:851
void rrset_del_rr(rrset_type *rrset, uint16_t rrnum)
Definition: rrset.c:334
void rrset_drop_rrsigs(zone_type *zone, rrset_type *rrset)
Definition: rrset.c:416
void rrset_diff(rrset_type *rrset, unsigned is_ixfr, unsigned more_coming)
Definition: rrset.c:366
rrset_type * rrset_create(zone_type *zone, ldns_rr_type type)
Definition: rrset.c:199
void log_rr(ldns_rr *rr, const char *pre, int level)
Definition: rrset.c:48
void rrset_cleanup(rrset_type *rrset)
Definition: rrset.c:928
void log_rrset(ldns_rdf *dname, ldns_rr_type type, const char *pre, int level)
Definition: rrset.c:99
void rrset_add_rrsig(rrset_type *rrset, ldns_rr *rr, const char *locator, uint32_t flags)
Definition: rrset.c:435
void rrset_backup2(FILE *fd, rrset_type *rrset)
Definition: rrset.c:951
const char * rrset_type2str(ldns_rr_type type)
Definition: rrset.c:158
uint32_t rrset_lookup_ttl(rrset_type *rrset, uint32_t default_ttl)
Definition: rrset.c:263
void rrset_print(FILE *fd, rrset_type *rrset, int skip_rrsigs, ods_status *status)
Definition: rrset.c:871
unsigned error
Definition: adapter.h:63
pthread_mutex_t ixfr_lock
Definition: ixfr.h:64
uint8_t algorithm
Definition: keys.h:55
int ksk
Definition: keys.h:58
const char * locator
Definition: keys.h:53
int publish
Definition: keys.h:57
uint32_t flags
Definition: keys.h:56
int zsk
Definition: keys.h:59
size_t count
Definition: keys.h:69
key_type * keys
Definition: keys.h:68
unsigned is_initialized
Definition: namedb.h:57
ldns_rr * rr
Definition: rrset.h:52
domain_type * owner
Definition: rrset.h:53
unsigned is_removed
Definition: rrset.h:56
unsigned exists
Definition: rrset.h:54
unsigned is_added
Definition: rrset.h:55
size_t rr_count
Definition: rrset.h:65
rr_type * rrs
Definition: rrset.h:64
unsigned needs_signing
Definition: rrset.h:67
ldns_rr_type rrtype
Definition: rrset.h:63
rrset_type * next
Definition: rrset.h:60
zone_type * zone
Definition: rrset.h:61
domain_type * domain
Definition: rrset.h:62
collection_t rrsigs
Definition: rrset.h:66
uint32_t key_flags
Definition: rrset.h:48
ldns_rr * rr
Definition: rrset.h:45
const char * key_locator
Definition: rrset.h:47
domain_type * owner
Definition: rrset.h:46
key_type * key
Definition: rrset.c:523
rrsig_type * signature
Definition: rrset.c:522
keylist_type * keys
Definition: signconf.h:64
duration_type * sig_jitter
Definition: signconf.h:51
duration_type * sig_refresh_interval
Definition: signconf.h:47
duration_type * sig_inception_offset
Definition: signconf.h:52
const char ** dnskey_signature
Definition: signconf.h:63
duration_type * sig_validity_keyset
Definition: signconf.h:50
duration_type * sig_validity_denial
Definition: signconf.h:49
duration_type * dnskey_ttl
Definition: signconf.h:62
duration_type * sig_validity_default
Definition: signconf.h:48
uint32_t sig_reuse
Definition: stats.h:58
pthread_mutex_t stats_lock
Definition: stats.h:63
uint32_t sig_soa_count
Definition: stats.h:57
uint32_t sig_count
Definition: stats.h:56
collection_class rrstore
Definition: zone.h:89
signconf_type * signconf
Definition: zone.h:77
stats_type * stats
Definition: zone.h:85
namedb_type * db
Definition: zone.h:79
ldns_rdf * apex
Definition: zone.h:61
ixfr_type * ixfr
Definition: zone.h:80
const char * name
Definition: zone.h:69
adapter_type * adoutbound
Definition: zone.h:75