1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * SPDX-License-Identifier: MPL-2.0
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public
7 * License, v. 2.0. If a copy of the MPL was not distributed with this
8 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9 *
10 * See the COPYRIGHT file distributed with this work for additional
11 * information regarding copyright ownership.
12 */
13
14 /*! \file */
15
16 #include <ctype.h>
17 #include <inttypes.h>
18 #include <stdbool.h>
19 #include <stdlib.h>
20
21 #include <isc/buffer.h>
22 #include <isc/dir.h>
23 #include <isc/mem.h>
24 #include <isc/print.h>
25 #include <isc/serial.h>
26 #include <isc/string.h>
27 #include <isc/util.h>
28
29 #include <pk11/site.h>
30
31 #include <dns/db.h>
32 #include <dns/diff.h>
33 #include <dns/dnssec.h>
34 #include <dns/fixedname.h>
35 #include <dns/kasp.h>
36 #include <dns/keyvalues.h>
37 #include <dns/log.h>
38 #include <dns/message.h>
39 #include <dns/rdata.h>
40 #include <dns/rdatalist.h>
41 #include <dns/rdataset.h>
42 #include <dns/rdatastruct.h>
43 #include <dns/result.h>
44 #include <dns/stats.h>
45 #include <dns/tsig.h> /* for DNS_TSIG_FUDGE */
46
47 #include <dst/result.h>
48
49 LIBDNS_EXTERNAL_DATA isc_stats_t *dns_dnssec_stats;
50
51 #define is_response(msg) ((msg->flags & DNS_MESSAGEFLAG_QR) != 0)
52
53 #define RETERR(x) \
54 do { \
55 result = (x); \
56 if (result != ISC_R_SUCCESS) \
57 goto failure; \
58 } while (0)
59
60 #define TYPE_SIGN 0
61 #define TYPE_VERIFY 1
62
63 static isc_result_t
64 digest_callback(void *arg, isc_region_t *data);
65
66 static int
67 rdata_compare_wrapper(const void *rdata1, const void *rdata2);
68
69 static isc_result_t
70 rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx,
71 dns_rdata_t **rdata, int *nrdata);
72
73 static isc_result_t
digest_callback(void * arg,isc_region_t * data)74 digest_callback(void *arg, isc_region_t *data) {
75 dst_context_t *ctx = arg;
76
77 return (dst_context_adddata(ctx, data));
78 }
79
80 static inline void
inc_stat(isc_statscounter_t counter)81 inc_stat(isc_statscounter_t counter) {
82 if (dns_dnssec_stats != NULL) {
83 isc_stats_increment(dns_dnssec_stats, counter);
84 }
85 }
86
87 /*
88 * Make qsort happy.
89 */
90 static int
rdata_compare_wrapper(const void * rdata1,const void * rdata2)91 rdata_compare_wrapper(const void *rdata1, const void *rdata2) {
92 return (dns_rdata_compare((const dns_rdata_t *)rdata1,
93 (const dns_rdata_t *)rdata2));
94 }
95
96 /*
97 * Sort the rdataset into an array.
98 */
99 static isc_result_t
rdataset_to_sortedarray(dns_rdataset_t * set,isc_mem_t * mctx,dns_rdata_t ** rdata,int * nrdata)100 rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx,
101 dns_rdata_t **rdata, int *nrdata) {
102 isc_result_t ret;
103 int i = 0, n;
104 dns_rdata_t *data;
105 dns_rdataset_t rdataset;
106
107 n = dns_rdataset_count(set);
108
109 data = isc_mem_get(mctx, n * sizeof(dns_rdata_t));
110
111 dns_rdataset_init(&rdataset);
112 dns_rdataset_clone(set, &rdataset);
113 ret = dns_rdataset_first(&rdataset);
114 if (ret != ISC_R_SUCCESS) {
115 dns_rdataset_disassociate(&rdataset);
116 isc_mem_put(mctx, data, n * sizeof(dns_rdata_t));
117 return (ret);
118 }
119
120 /*
121 * Put them in the array.
122 */
123 do {
124 dns_rdata_init(&data[i]);
125 dns_rdataset_current(&rdataset, &data[i++]);
126 } while (dns_rdataset_next(&rdataset) == ISC_R_SUCCESS);
127
128 /*
129 * Sort the array.
130 */
131 qsort(data, n, sizeof(dns_rdata_t), rdata_compare_wrapper);
132 *rdata = data;
133 *nrdata = n;
134 dns_rdataset_disassociate(&rdataset);
135 return (ISC_R_SUCCESS);
136 }
137
138 isc_result_t
dns_dnssec_keyfromrdata(const dns_name_t * name,const dns_rdata_t * rdata,isc_mem_t * mctx,dst_key_t ** key)139 dns_dnssec_keyfromrdata(const dns_name_t *name, const dns_rdata_t *rdata,
140 isc_mem_t *mctx, dst_key_t **key) {
141 isc_buffer_t b;
142 isc_region_t r;
143
144 INSIST(name != NULL);
145 INSIST(rdata != NULL);
146 INSIST(mctx != NULL);
147 INSIST(key != NULL);
148 INSIST(*key == NULL);
149 REQUIRE(rdata->type == dns_rdatatype_key ||
150 rdata->type == dns_rdatatype_dnskey);
151
152 dns_rdata_toregion(rdata, &r);
153 isc_buffer_init(&b, r.base, r.length);
154 isc_buffer_add(&b, r.length);
155 return (dst_key_fromdns(name, rdata->rdclass, &b, mctx, key));
156 }
157
158 static isc_result_t
digest_sig(dst_context_t * ctx,bool downcase,dns_rdata_t * sigrdata,dns_rdata_rrsig_t * rrsig)159 digest_sig(dst_context_t *ctx, bool downcase, dns_rdata_t *sigrdata,
160 dns_rdata_rrsig_t *rrsig) {
161 isc_region_t r;
162 isc_result_t ret;
163 dns_fixedname_t fname;
164
165 dns_rdata_toregion(sigrdata, &r);
166 INSIST(r.length >= 19);
167
168 r.length = 18;
169 ret = dst_context_adddata(ctx, &r);
170 if (ret != ISC_R_SUCCESS) {
171 return (ret);
172 }
173 if (downcase) {
174 dns_fixedname_init(&fname);
175
176 RUNTIME_CHECK(dns_name_downcase(&rrsig->signer,
177 dns_fixedname_name(&fname),
178 NULL) == ISC_R_SUCCESS);
179 dns_name_toregion(dns_fixedname_name(&fname), &r);
180 } else {
181 dns_name_toregion(&rrsig->signer, &r);
182 }
183
184 return (dst_context_adddata(ctx, &r));
185 }
186
187 isc_result_t
dns_dnssec_sign(const dns_name_t * name,dns_rdataset_t * set,dst_key_t * key,isc_stdtime_t * inception,isc_stdtime_t * expire,isc_mem_t * mctx,isc_buffer_t * buffer,dns_rdata_t * sigrdata)188 dns_dnssec_sign(const dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
189 isc_stdtime_t *inception, isc_stdtime_t *expire,
190 isc_mem_t *mctx, isc_buffer_t *buffer, dns_rdata_t *sigrdata) {
191 dns_rdata_rrsig_t sig;
192 dns_rdata_t tmpsigrdata;
193 dns_rdata_t *rdatas;
194 int nrdatas, i;
195 isc_buffer_t sigbuf, envbuf;
196 isc_region_t r;
197 dst_context_t *ctx = NULL;
198 isc_result_t ret;
199 isc_buffer_t *databuf = NULL;
200 char data[256 + 8];
201 uint32_t flags;
202 unsigned int sigsize;
203 dns_fixedname_t fnewname;
204 dns_fixedname_t fsigner;
205
206 REQUIRE(name != NULL);
207 REQUIRE(dns_name_countlabels(name) <= 255);
208 REQUIRE(set != NULL);
209 REQUIRE(key != NULL);
210 REQUIRE(inception != NULL);
211 REQUIRE(expire != NULL);
212 REQUIRE(mctx != NULL);
213 REQUIRE(sigrdata != NULL);
214
215 if (*inception >= *expire) {
216 return (DNS_R_INVALIDTIME);
217 }
218
219 /*
220 * Is the key allowed to sign data?
221 */
222 flags = dst_key_flags(key);
223 if ((flags & DNS_KEYTYPE_NOAUTH) != 0) {
224 return (DNS_R_KEYUNAUTHORIZED);
225 }
226 if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE) {
227 return (DNS_R_KEYUNAUTHORIZED);
228 }
229
230 sig.mctx = mctx;
231 sig.common.rdclass = set->rdclass;
232 sig.common.rdtype = dns_rdatatype_rrsig;
233 ISC_LINK_INIT(&sig.common, link);
234
235 /*
236 * Downcase signer.
237 */
238 dns_name_init(&sig.signer, NULL);
239 dns_fixedname_init(&fsigner);
240 RUNTIME_CHECK(dns_name_downcase(dst_key_name(key),
241 dns_fixedname_name(&fsigner),
242 NULL) == ISC_R_SUCCESS);
243 dns_name_clone(dns_fixedname_name(&fsigner), &sig.signer);
244
245 sig.covered = set->type;
246 sig.algorithm = dst_key_alg(key);
247 sig.labels = dns_name_countlabels(name) - 1;
248 if (dns_name_iswildcard(name)) {
249 sig.labels--;
250 }
251 sig.originalttl = set->ttl;
252 sig.timesigned = *inception;
253 sig.timeexpire = *expire;
254 sig.keyid = dst_key_id(key);
255 ret = dst_key_sigsize(key, &sigsize);
256 if (ret != ISC_R_SUCCESS) {
257 return (ret);
258 }
259 sig.siglen = sigsize;
260 /*
261 * The actual contents of sig.signature are not important yet, since
262 * they're not used in digest_sig().
263 */
264 sig.signature = isc_mem_get(mctx, sig.siglen);
265
266 isc_buffer_allocate(mctx, &databuf, sigsize + 256 + 18);
267
268 dns_rdata_init(&tmpsigrdata);
269 ret = dns_rdata_fromstruct(&tmpsigrdata, sig.common.rdclass,
270 sig.common.rdtype, &sig, databuf);
271 if (ret != ISC_R_SUCCESS) {
272 goto cleanup_databuf;
273 }
274
275 ret = dst_context_create(key, mctx, DNS_LOGCATEGORY_DNSSEC, true, 0,
276 &ctx);
277 if (ret != ISC_R_SUCCESS) {
278 goto cleanup_databuf;
279 }
280
281 /*
282 * Digest the SIG rdata.
283 */
284 ret = digest_sig(ctx, false, &tmpsigrdata, &sig);
285 if (ret != ISC_R_SUCCESS) {
286 goto cleanup_context;
287 }
288
289 dns_fixedname_init(&fnewname);
290 RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname),
291 NULL) == ISC_R_SUCCESS);
292 dns_name_toregion(dns_fixedname_name(&fnewname), &r);
293
294 /*
295 * Create an envelope for each rdata: <name|type|class|ttl>.
296 */
297 isc_buffer_init(&envbuf, data, sizeof(data));
298 memmove(data, r.base, r.length);
299 isc_buffer_add(&envbuf, r.length);
300 isc_buffer_putuint16(&envbuf, set->type);
301 isc_buffer_putuint16(&envbuf, set->rdclass);
302 isc_buffer_putuint32(&envbuf, set->ttl);
303
304 ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas);
305 if (ret != ISC_R_SUCCESS) {
306 goto cleanup_context;
307 }
308 isc_buffer_usedregion(&envbuf, &r);
309
310 for (i = 0; i < nrdatas; i++) {
311 uint16_t len;
312 isc_buffer_t lenbuf;
313 isc_region_t lenr;
314
315 /*
316 * Skip duplicates.
317 */
318 if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i - 1]) == 0)
319 {
320 continue;
321 }
322
323 /*
324 * Digest the envelope.
325 */
326 ret = dst_context_adddata(ctx, &r);
327 if (ret != ISC_R_SUCCESS) {
328 goto cleanup_array;
329 }
330
331 /*
332 * Digest the length of the rdata.
333 */
334 isc_buffer_init(&lenbuf, &len, sizeof(len));
335 INSIST(rdatas[i].length < 65536);
336 isc_buffer_putuint16(&lenbuf, (uint16_t)rdatas[i].length);
337 isc_buffer_usedregion(&lenbuf, &lenr);
338 ret = dst_context_adddata(ctx, &lenr);
339 if (ret != ISC_R_SUCCESS) {
340 goto cleanup_array;
341 }
342
343 /*
344 * Digest the rdata.
345 */
346 ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx);
347 if (ret != ISC_R_SUCCESS) {
348 goto cleanup_array;
349 }
350 }
351
352 isc_buffer_init(&sigbuf, sig.signature, sig.siglen);
353 ret = dst_context_sign(ctx, &sigbuf);
354 if (ret != ISC_R_SUCCESS) {
355 goto cleanup_array;
356 }
357 isc_buffer_usedregion(&sigbuf, &r);
358 if (r.length != sig.siglen) {
359 ret = ISC_R_NOSPACE;
360 goto cleanup_array;
361 }
362
363 ret = dns_rdata_fromstruct(sigrdata, sig.common.rdclass,
364 sig.common.rdtype, &sig, buffer);
365
366 cleanup_array:
367 isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t));
368 cleanup_context:
369 dst_context_destroy(&ctx);
370 cleanup_databuf:
371 isc_buffer_free(&databuf);
372 isc_mem_put(mctx, sig.signature, sig.siglen);
373
374 return (ret);
375 }
376
377 isc_result_t
dns_dnssec_verify(const dns_name_t * name,dns_rdataset_t * set,dst_key_t * key,bool ignoretime,unsigned int maxbits,isc_mem_t * mctx,dns_rdata_t * sigrdata,dns_name_t * wild)378 dns_dnssec_verify(const dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
379 bool ignoretime, unsigned int maxbits, isc_mem_t *mctx,
380 dns_rdata_t *sigrdata, dns_name_t *wild) {
381 dns_rdata_rrsig_t sig;
382 dns_fixedname_t fnewname;
383 isc_region_t r;
384 isc_buffer_t envbuf;
385 dns_rdata_t *rdatas;
386 int nrdatas, i;
387 isc_stdtime_t now;
388 isc_result_t ret;
389 unsigned char data[300];
390 dst_context_t *ctx = NULL;
391 int labels = 0;
392 uint32_t flags;
393 bool downcase = false;
394
395 REQUIRE(name != NULL);
396 REQUIRE(set != NULL);
397 REQUIRE(key != NULL);
398 REQUIRE(mctx != NULL);
399 REQUIRE(sigrdata != NULL && sigrdata->type == dns_rdatatype_rrsig);
400
401 ret = dns_rdata_tostruct(sigrdata, &sig, NULL);
402 if (ret != ISC_R_SUCCESS) {
403 return (ret);
404 }
405
406 if (set->type != sig.covered) {
407 return (DNS_R_SIGINVALID);
408 }
409
410 if (isc_serial_lt(sig.timeexpire, sig.timesigned)) {
411 inc_stat(dns_dnssecstats_fail);
412 return (DNS_R_SIGINVALID);
413 }
414
415 if (!ignoretime) {
416 isc_stdtime_get(&now);
417
418 /*
419 * Is SIG temporally valid?
420 */
421 if (isc_serial_lt((uint32_t)now, sig.timesigned)) {
422 inc_stat(dns_dnssecstats_fail);
423 return (DNS_R_SIGFUTURE);
424 } else if (isc_serial_lt(sig.timeexpire, (uint32_t)now)) {
425 inc_stat(dns_dnssecstats_fail);
426 return (DNS_R_SIGEXPIRED);
427 }
428 }
429
430 /*
431 * NS, SOA and DNSSKEY records are signed by their owner.
432 * DS records are signed by the parent.
433 */
434 switch (set->type) {
435 case dns_rdatatype_ns:
436 case dns_rdatatype_soa:
437 case dns_rdatatype_dnskey:
438 if (!dns_name_equal(name, &sig.signer)) {
439 inc_stat(dns_dnssecstats_fail);
440 return (DNS_R_SIGINVALID);
441 }
442 break;
443 case dns_rdatatype_ds:
444 if (dns_name_equal(name, &sig.signer)) {
445 inc_stat(dns_dnssecstats_fail);
446 return (DNS_R_SIGINVALID);
447 }
448 /* FALLTHROUGH */
449 default:
450 if (!dns_name_issubdomain(name, &sig.signer)) {
451 inc_stat(dns_dnssecstats_fail);
452 return (DNS_R_SIGINVALID);
453 }
454 break;
455 }
456
457 /*
458 * Is the key allowed to sign data?
459 */
460 flags = dst_key_flags(key);
461 if ((flags & DNS_KEYTYPE_NOAUTH) != 0) {
462 inc_stat(dns_dnssecstats_fail);
463 return (DNS_R_KEYUNAUTHORIZED);
464 }
465 if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE) {
466 inc_stat(dns_dnssecstats_fail);
467 return (DNS_R_KEYUNAUTHORIZED);
468 }
469
470 again:
471 ret = dst_context_create(key, mctx, DNS_LOGCATEGORY_DNSSEC, false,
472 maxbits, &ctx);
473 if (ret != ISC_R_SUCCESS) {
474 goto cleanup_struct;
475 }
476
477 /*
478 * Digest the SIG rdata (not including the signature).
479 */
480 ret = digest_sig(ctx, downcase, sigrdata, &sig);
481 if (ret != ISC_R_SUCCESS) {
482 goto cleanup_context;
483 }
484
485 /*
486 * If the name is an expanded wildcard, use the wildcard name.
487 */
488 dns_fixedname_init(&fnewname);
489 labels = dns_name_countlabels(name) - 1;
490 RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname),
491 NULL) == ISC_R_SUCCESS);
492 if (labels - sig.labels > 0) {
493 dns_name_split(dns_fixedname_name(&fnewname), sig.labels + 1,
494 NULL, dns_fixedname_name(&fnewname));
495 }
496
497 dns_name_toregion(dns_fixedname_name(&fnewname), &r);
498
499 /*
500 * Create an envelope for each rdata: <name|type|class|ttl>.
501 */
502 isc_buffer_init(&envbuf, data, sizeof(data));
503 if (labels - sig.labels > 0) {
504 isc_buffer_putuint8(&envbuf, 1);
505 isc_buffer_putuint8(&envbuf, '*');
506 memmove(data + 2, r.base, r.length);
507 } else {
508 memmove(data, r.base, r.length);
509 }
510 isc_buffer_add(&envbuf, r.length);
511 isc_buffer_putuint16(&envbuf, set->type);
512 isc_buffer_putuint16(&envbuf, set->rdclass);
513 isc_buffer_putuint32(&envbuf, sig.originalttl);
514
515 ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas);
516 if (ret != ISC_R_SUCCESS) {
517 goto cleanup_context;
518 }
519
520 isc_buffer_usedregion(&envbuf, &r);
521
522 for (i = 0; i < nrdatas; i++) {
523 uint16_t len;
524 isc_buffer_t lenbuf;
525 isc_region_t lenr;
526
527 /*
528 * Skip duplicates.
529 */
530 if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i - 1]) == 0)
531 {
532 continue;
533 }
534
535 /*
536 * Digest the envelope.
537 */
538 ret = dst_context_adddata(ctx, &r);
539 if (ret != ISC_R_SUCCESS) {
540 goto cleanup_array;
541 }
542
543 /*
544 * Digest the rdata length.
545 */
546 isc_buffer_init(&lenbuf, &len, sizeof(len));
547 INSIST(rdatas[i].length < 65536);
548 isc_buffer_putuint16(&lenbuf, (uint16_t)rdatas[i].length);
549 isc_buffer_usedregion(&lenbuf, &lenr);
550
551 /*
552 * Digest the rdata.
553 */
554 ret = dst_context_adddata(ctx, &lenr);
555 if (ret != ISC_R_SUCCESS) {
556 goto cleanup_array;
557 }
558 ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx);
559 if (ret != ISC_R_SUCCESS) {
560 goto cleanup_array;
561 }
562 }
563
564 r.base = sig.signature;
565 r.length = sig.siglen;
566 ret = dst_context_verify2(ctx, maxbits, &r);
567 if (ret == ISC_R_SUCCESS && downcase) {
568 char namebuf[DNS_NAME_FORMATSIZE];
569 dns_name_format(&sig.signer, namebuf, sizeof(namebuf));
570 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
571 DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1),
572 "successfully validated after lower casing "
573 "signer '%s'",
574 namebuf);
575 inc_stat(dns_dnssecstats_downcase);
576 } else if (ret == ISC_R_SUCCESS) {
577 inc_stat(dns_dnssecstats_asis);
578 }
579
580 cleanup_array:
581 isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t));
582 cleanup_context:
583 dst_context_destroy(&ctx);
584 if (ret == DST_R_VERIFYFAILURE && !downcase) {
585 downcase = true;
586 goto again;
587 }
588 cleanup_struct:
589 dns_rdata_freestruct(&sig);
590
591 if (ret == DST_R_VERIFYFAILURE) {
592 ret = DNS_R_SIGINVALID;
593 }
594
595 if (ret != ISC_R_SUCCESS) {
596 inc_stat(dns_dnssecstats_fail);
597 }
598
599 if (ret == ISC_R_SUCCESS && labels - sig.labels > 0) {
600 if (wild != NULL) {
601 RUNTIME_CHECK(dns_name_concatenate(
602 dns_wildcardname,
603 dns_fixedname_name(&fnewname),
604 wild, NULL) == ISC_R_SUCCESS);
605 }
606 inc_stat(dns_dnssecstats_wildcard);
607 ret = DNS_R_FROMWILDCARD;
608 }
609 return (ret);
610 }
611
612 bool
dns_dnssec_keyactive(dst_key_t * key,isc_stdtime_t now)613 dns_dnssec_keyactive(dst_key_t *key, isc_stdtime_t now) {
614 isc_result_t result;
615 isc_stdtime_t publish, active, revoke, remove;
616 bool hint_publish, hint_zsign, hint_ksign, hint_revoke, hint_remove;
617 int major, minor;
618 bool ksk = false, zsk = false;
619 isc_result_t ret;
620
621 /* Is this an old-style key? */
622 result = dst_key_getprivateformat(key, &major, &minor);
623 RUNTIME_CHECK(result == ISC_R_SUCCESS);
624
625 /* Is this a KSK? */
626 ret = dst_key_getbool(key, DST_BOOL_KSK, &ksk);
627 if (ret != ISC_R_SUCCESS) {
628 ksk = ((dst_key_flags(key) & DNS_KEYFLAG_KSK) != 0);
629 }
630 ret = dst_key_getbool(key, DST_BOOL_ZSK, &zsk);
631 if (ret != ISC_R_SUCCESS) {
632 zsk = ((dst_key_flags(key) & DNS_KEYFLAG_KSK) == 0);
633 }
634
635 /*
636 * Smart signing started with key format 1.3; prior to that, all
637 * keys are assumed active.
638 */
639 if (major == 1 && minor <= 2) {
640 return (true);
641 }
642
643 hint_publish = dst_key_is_published(key, now, &publish);
644 hint_zsign = dst_key_is_signing(key, DST_BOOL_ZSK, now, &active);
645 hint_ksign = dst_key_is_signing(key, DST_BOOL_KSK, now, &active);
646 hint_revoke = dst_key_is_revoked(key, now, &revoke);
647 hint_remove = dst_key_is_removed(key, now, &remove);
648
649 if (hint_remove) {
650 return (false);
651 }
652 if (hint_publish && hint_revoke) {
653 return (true);
654 }
655 if (hint_zsign && zsk) {
656 return (true);
657 }
658 if (hint_ksign && ksk) {
659 return (true);
660 }
661 return (false);
662 }
663
664 /*%<
665 * Indicate whether a key is scheduled to to have CDS/CDNSKEY records
666 * published now.
667 *
668 * Returns true if.
669 * - kasp says the DS record should be published (e.g. the DS state is in
670 * RUMOURED or OMNIPRESENT state).
671 * Or:
672 * - SyncPublish is set and in the past, AND
673 * - SyncDelete is unset or in the future
674 */
675 static bool
syncpublish(dst_key_t * key,isc_stdtime_t now)676 syncpublish(dst_key_t *key, isc_stdtime_t now) {
677 isc_result_t result;
678 isc_stdtime_t when;
679 dst_key_state_t state;
680 int major, minor;
681 bool publish;
682
683 /*
684 * Is this an old-style key?
685 */
686 result = dst_key_getprivateformat(key, &major, &minor);
687 RUNTIME_CHECK(result == ISC_R_SUCCESS);
688
689 /*
690 * Smart signing started with key format 1.3
691 */
692 if (major == 1 && minor <= 2) {
693 return (false);
694 }
695
696 /* Check kasp state first. */
697 result = dst_key_getstate(key, DST_KEY_DS, &state);
698 if (result == ISC_R_SUCCESS) {
699 return (state == DST_KEY_STATE_RUMOURED ||
700 state == DST_KEY_STATE_OMNIPRESENT);
701 }
702
703 /* If no kasp state, check timings. */
704 publish = false;
705 result = dst_key_gettime(key, DST_TIME_SYNCPUBLISH, &when);
706 if (result == ISC_R_SUCCESS && when <= now) {
707 publish = true;
708 }
709 result = dst_key_gettime(key, DST_TIME_SYNCDELETE, &when);
710 if (result == ISC_R_SUCCESS && when < now) {
711 publish = false;
712 }
713 return (publish);
714 }
715
716 /*%<
717 * Indicate whether a key is scheduled to to have CDS/CDNSKEY records
718 * deleted now.
719 *
720 * Returns true if:
721 * - kasp says the DS record should be unpublished (e.g. the DS state is in
722 * UNRETENTIVE or HIDDEN state).
723 * Or:
724 * - SyncDelete is set and in the past.
725 */
726 static bool
syncdelete(dst_key_t * key,isc_stdtime_t now)727 syncdelete(dst_key_t *key, isc_stdtime_t now) {
728 isc_result_t result;
729 isc_stdtime_t when;
730 dst_key_state_t state;
731 int major, minor;
732
733 /*
734 * Is this an old-style key?
735 */
736 result = dst_key_getprivateformat(key, &major, &minor);
737 RUNTIME_CHECK(result == ISC_R_SUCCESS);
738
739 /*
740 * Smart signing started with key format 1.3.
741 */
742 if (major == 1 && minor <= 2) {
743 return (false);
744 }
745
746 /* Check kasp state first. */
747 result = dst_key_getstate(key, DST_KEY_DS, &state);
748 if (result == ISC_R_SUCCESS) {
749 return (state == DST_KEY_STATE_UNRETENTIVE ||
750 state == DST_KEY_STATE_HIDDEN);
751 }
752
753 /* If no kasp state, check timings. */
754 result = dst_key_gettime(key, DST_TIME_SYNCDELETE, &when);
755 if (result != ISC_R_SUCCESS) {
756 return (false);
757 }
758 if (when <= now) {
759 return (true);
760 }
761 return (false);
762 }
763
764 #define is_zone_key(key) \
765 ((dst_key_flags(key) & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE)
766
767 isc_result_t
dns_dnssec_findzonekeys(dns_db_t * db,dns_dbversion_t * ver,dns_dbnode_t * node,const dns_name_t * name,const char * directory,isc_stdtime_t now,isc_mem_t * mctx,unsigned int maxkeys,dst_key_t ** keys,unsigned int * nkeys)768 dns_dnssec_findzonekeys(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
769 const dns_name_t *name, const char *directory,
770 isc_stdtime_t now, isc_mem_t *mctx,
771 unsigned int maxkeys, dst_key_t **keys,
772 unsigned int *nkeys) {
773 dns_rdataset_t rdataset;
774 dns_rdata_t rdata = DNS_RDATA_INIT;
775 isc_result_t result;
776 dst_key_t *pubkey = NULL;
777 unsigned int count = 0;
778
779 REQUIRE(nkeys != NULL);
780 REQUIRE(keys != NULL);
781
782 *nkeys = 0;
783 memset(keys, 0, sizeof(*keys) * maxkeys);
784 dns_rdataset_init(&rdataset);
785 RETERR(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0,
786 &rdataset, NULL));
787 RETERR(dns_rdataset_first(&rdataset));
788 while (result == ISC_R_SUCCESS && count < maxkeys) {
789 pubkey = NULL;
790 dns_rdataset_current(&rdataset, &rdata);
791 RETERR(dns_dnssec_keyfromrdata(name, &rdata, mctx, &pubkey));
792 dst_key_setttl(pubkey, rdataset.ttl);
793
794 if (!is_zone_key(pubkey) ||
795 (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0) {
796 goto next;
797 }
798 /* Corrupted .key file? */
799 if (!dns_name_equal(name, dst_key_name(pubkey))) {
800 goto next;
801 }
802 keys[count] = NULL;
803 result = dst_key_fromfile(
804 dst_key_name(pubkey), dst_key_id(pubkey),
805 dst_key_alg(pubkey),
806 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE,
807 directory, mctx, &keys[count]);
808
809 /*
810 * If the key was revoked and the private file
811 * doesn't exist, maybe it was revoked internally
812 * by named. Try loading the unrevoked version.
813 */
814 if (result == ISC_R_FILENOTFOUND) {
815 uint32_t flags;
816 flags = dst_key_flags(pubkey);
817 if ((flags & DNS_KEYFLAG_REVOKE) != 0) {
818 dst_key_setflags(pubkey,
819 flags & ~DNS_KEYFLAG_REVOKE);
820 result = dst_key_fromfile(
821 dst_key_name(pubkey),
822 dst_key_id(pubkey), dst_key_alg(pubkey),
823 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE |
824 DST_TYPE_STATE,
825 directory, mctx, &keys[count]);
826 if (result == ISC_R_SUCCESS &&
827 dst_key_pubcompare(pubkey, keys[count],
828 false)) {
829 dst_key_setflags(keys[count], flags);
830 }
831 dst_key_setflags(pubkey, flags);
832 }
833 }
834
835 if (result != ISC_R_SUCCESS) {
836 char filename[DNS_NAME_FORMATSIZE +
837 DNS_SECALG_FORMATSIZE +
838 sizeof("key file for //65535")];
839 isc_result_t result2;
840 isc_buffer_t buf;
841
842 isc_buffer_init(&buf, filename, NAME_MAX);
843 result2 = dst_key_getfilename(
844 dst_key_name(pubkey), dst_key_id(pubkey),
845 dst_key_alg(pubkey),
846 (DST_TYPE_PUBLIC | DST_TYPE_PRIVATE |
847 DST_TYPE_STATE),
848 directory, mctx, &buf);
849 if (result2 != ISC_R_SUCCESS) {
850 char namebuf[DNS_NAME_FORMATSIZE];
851 char algbuf[DNS_SECALG_FORMATSIZE];
852
853 dns_name_format(dst_key_name(pubkey), namebuf,
854 sizeof(namebuf));
855 dns_secalg_format(dst_key_alg(pubkey), algbuf,
856 sizeof(algbuf));
857 snprintf(filename, sizeof(filename) - 1,
858 "key file for %s/%s/%d", namebuf,
859 algbuf, dst_key_id(pubkey));
860 }
861
862 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
863 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
864 "dns_dnssec_findzonekeys2: error "
865 "reading %s: %s",
866 filename, isc_result_totext(result));
867 }
868
869 if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) {
870 keys[count] = pubkey;
871 pubkey = NULL;
872 count++;
873 goto next;
874 }
875
876 if (result != ISC_R_SUCCESS) {
877 goto failure;
878 }
879
880 /*
881 * If a key is marked inactive, skip it
882 */
883 if (!dns_dnssec_keyactive(keys[count], now)) {
884 dst_key_setinactive(pubkey, true);
885 dst_key_free(&keys[count]);
886 keys[count] = pubkey;
887 pubkey = NULL;
888 count++;
889 goto next;
890 }
891
892 /*
893 * Whatever the key's default TTL may have
894 * been, the rdataset TTL takes priority.
895 */
896 dst_key_setttl(keys[count], rdataset.ttl);
897
898 if ((dst_key_flags(keys[count]) & DNS_KEYTYPE_NOAUTH) != 0) {
899 /* We should never get here. */
900 dst_key_free(&keys[count]);
901 goto next;
902 }
903 count++;
904 next:
905 if (pubkey != NULL) {
906 dst_key_free(&pubkey);
907 }
908 dns_rdata_reset(&rdata);
909 result = dns_rdataset_next(&rdataset);
910 }
911 if (result != ISC_R_NOMORE) {
912 goto failure;
913 }
914 if (count == 0) {
915 result = ISC_R_NOTFOUND;
916 } else {
917 result = ISC_R_SUCCESS;
918 }
919
920 failure:
921 if (dns_rdataset_isassociated(&rdataset)) {
922 dns_rdataset_disassociate(&rdataset);
923 }
924 if (pubkey != NULL) {
925 dst_key_free(&pubkey);
926 }
927 if (result != ISC_R_SUCCESS) {
928 while (count > 0) {
929 dst_key_free(&keys[--count]);
930 }
931 }
932 *nkeys = count;
933 return (result);
934 }
935
936 isc_result_t
dns_dnssec_signmessage(dns_message_t * msg,dst_key_t * key)937 dns_dnssec_signmessage(dns_message_t *msg, dst_key_t *key) {
938 dns_rdata_sig_t sig; /* SIG(0) */
939 unsigned char data[512];
940 unsigned char header[DNS_MESSAGE_HEADERLEN];
941 isc_buffer_t headerbuf, databuf, sigbuf;
942 unsigned int sigsize;
943 isc_buffer_t *dynbuf = NULL;
944 dns_rdata_t *rdata;
945 dns_rdatalist_t *datalist;
946 dns_rdataset_t *dataset;
947 isc_region_t r;
948 isc_stdtime_t now;
949 dst_context_t *ctx = NULL;
950 isc_mem_t *mctx;
951 isc_result_t result;
952
953 REQUIRE(msg != NULL);
954 REQUIRE(key != NULL);
955
956 if (is_response(msg)) {
957 REQUIRE(msg->query.base != NULL);
958 }
959
960 mctx = msg->mctx;
961
962 memset(&sig, 0, sizeof(sig));
963
964 sig.mctx = mctx;
965 sig.common.rdclass = dns_rdataclass_any;
966 sig.common.rdtype = dns_rdatatype_sig; /* SIG(0) */
967 ISC_LINK_INIT(&sig.common, link);
968
969 sig.covered = 0;
970 sig.algorithm = dst_key_alg(key);
971 sig.labels = 0; /* the root name */
972 sig.originalttl = 0;
973
974 isc_stdtime_get(&now);
975 sig.timesigned = now - DNS_TSIG_FUDGE;
976 sig.timeexpire = now + DNS_TSIG_FUDGE;
977
978 sig.keyid = dst_key_id(key);
979
980 dns_name_init(&sig.signer, NULL);
981 dns_name_clone(dst_key_name(key), &sig.signer);
982
983 sig.siglen = 0;
984 sig.signature = NULL;
985
986 isc_buffer_init(&databuf, data, sizeof(data));
987
988 RETERR(dst_context_create(key, mctx, DNS_LOGCATEGORY_DNSSEC, true, 0,
989 &ctx));
990
991 /*
992 * Digest the fields of the SIG - we can cheat and use
993 * dns_rdata_fromstruct. Since siglen is 0, the digested data
994 * is identical to dns format.
995 */
996 RETERR(dns_rdata_fromstruct(NULL, dns_rdataclass_any,
997 dns_rdatatype_sig /* SIG(0) */, &sig,
998 &databuf));
999 isc_buffer_usedregion(&databuf, &r);
1000 RETERR(dst_context_adddata(ctx, &r));
1001
1002 /*
1003 * If this is a response, digest the query.
1004 */
1005 if (is_response(msg)) {
1006 RETERR(dst_context_adddata(ctx, &msg->query));
1007 }
1008
1009 /*
1010 * Digest the header.
1011 */
1012 isc_buffer_init(&headerbuf, header, sizeof(header));
1013 dns_message_renderheader(msg, &headerbuf);
1014 isc_buffer_usedregion(&headerbuf, &r);
1015 RETERR(dst_context_adddata(ctx, &r));
1016
1017 /*
1018 * Digest the remainder of the message.
1019 */
1020 isc_buffer_usedregion(msg->buffer, &r);
1021 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
1022 RETERR(dst_context_adddata(ctx, &r));
1023
1024 RETERR(dst_key_sigsize(key, &sigsize));
1025 sig.siglen = sigsize;
1026 sig.signature = isc_mem_get(mctx, sig.siglen);
1027
1028 isc_buffer_init(&sigbuf, sig.signature, sig.siglen);
1029 RETERR(dst_context_sign(ctx, &sigbuf));
1030 dst_context_destroy(&ctx);
1031
1032 rdata = NULL;
1033 RETERR(dns_message_gettemprdata(msg, &rdata));
1034 isc_buffer_allocate(msg->mctx, &dynbuf, 1024);
1035 RETERR(dns_rdata_fromstruct(rdata, dns_rdataclass_any,
1036 dns_rdatatype_sig /* SIG(0) */, &sig,
1037 dynbuf));
1038
1039 isc_mem_put(mctx, sig.signature, sig.siglen);
1040
1041 dns_message_takebuffer(msg, &dynbuf);
1042
1043 datalist = NULL;
1044 RETERR(dns_message_gettemprdatalist(msg, &datalist));
1045 datalist->rdclass = dns_rdataclass_any;
1046 datalist->type = dns_rdatatype_sig; /* SIG(0) */
1047 ISC_LIST_APPEND(datalist->rdata, rdata, link);
1048 dataset = NULL;
1049 RETERR(dns_message_gettemprdataset(msg, &dataset));
1050 RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset) ==
1051 ISC_R_SUCCESS);
1052 msg->sig0 = dataset;
1053
1054 return (ISC_R_SUCCESS);
1055
1056 failure:
1057 if (dynbuf != NULL) {
1058 isc_buffer_free(&dynbuf);
1059 }
1060 if (sig.signature != NULL) {
1061 isc_mem_put(mctx, sig.signature, sig.siglen);
1062 }
1063 if (ctx != NULL) {
1064 dst_context_destroy(&ctx);
1065 }
1066
1067 return (result);
1068 }
1069
1070 isc_result_t
dns_dnssec_verifymessage(isc_buffer_t * source,dns_message_t * msg,dst_key_t * key)1071 dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg,
1072 dst_key_t *key) {
1073 dns_rdata_sig_t sig; /* SIG(0) */
1074 unsigned char header[DNS_MESSAGE_HEADERLEN];
1075 dns_rdata_t rdata = DNS_RDATA_INIT;
1076 isc_region_t r, source_r, sig_r, header_r;
1077 isc_stdtime_t now;
1078 dst_context_t *ctx = NULL;
1079 isc_mem_t *mctx;
1080 isc_result_t result;
1081 uint16_t addcount, addcount_n;
1082 bool signeedsfree = false;
1083
1084 REQUIRE(source != NULL);
1085 REQUIRE(msg != NULL);
1086 REQUIRE(key != NULL);
1087
1088 mctx = msg->mctx;
1089
1090 msg->verify_attempted = 1;
1091 msg->verified_sig = 0;
1092 msg->sig0status = dns_tsigerror_badsig;
1093
1094 if (is_response(msg)) {
1095 if (msg->query.base == NULL) {
1096 return (DNS_R_UNEXPECTEDTSIG);
1097 }
1098 }
1099
1100 isc_buffer_usedregion(source, &source_r);
1101
1102 RETERR(dns_rdataset_first(msg->sig0));
1103 dns_rdataset_current(msg->sig0, &rdata);
1104
1105 RETERR(dns_rdata_tostruct(&rdata, &sig, NULL));
1106 signeedsfree = true;
1107
1108 if (sig.labels != 0) {
1109 result = DNS_R_SIGINVALID;
1110 goto failure;
1111 }
1112
1113 if (isc_serial_lt(sig.timeexpire, sig.timesigned)) {
1114 result = DNS_R_SIGINVALID;
1115 msg->sig0status = dns_tsigerror_badtime;
1116 goto failure;
1117 }
1118
1119 isc_stdtime_get(&now);
1120 if (isc_serial_lt((uint32_t)now, sig.timesigned)) {
1121 result = DNS_R_SIGFUTURE;
1122 msg->sig0status = dns_tsigerror_badtime;
1123 goto failure;
1124 } else if (isc_serial_lt(sig.timeexpire, (uint32_t)now)) {
1125 result = DNS_R_SIGEXPIRED;
1126 msg->sig0status = dns_tsigerror_badtime;
1127 goto failure;
1128 }
1129
1130 if (!dns_name_equal(dst_key_name(key), &sig.signer)) {
1131 result = DNS_R_SIGINVALID;
1132 msg->sig0status = dns_tsigerror_badkey;
1133 goto failure;
1134 }
1135
1136 RETERR(dst_context_create(key, mctx, DNS_LOGCATEGORY_DNSSEC, false, 0,
1137 &ctx));
1138
1139 /*
1140 * Digest the SIG(0) record, except for the signature.
1141 */
1142 dns_rdata_toregion(&rdata, &r);
1143 r.length -= sig.siglen;
1144 RETERR(dst_context_adddata(ctx, &r));
1145
1146 /*
1147 * If this is a response, digest the query.
1148 */
1149 if (is_response(msg)) {
1150 RETERR(dst_context_adddata(ctx, &msg->query));
1151 }
1152
1153 /*
1154 * Extract the header.
1155 */
1156 memmove(header, source_r.base, DNS_MESSAGE_HEADERLEN);
1157
1158 /*
1159 * Decrement the additional field counter.
1160 */
1161 memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
1162 addcount_n = ntohs(addcount);
1163 addcount = htons((uint16_t)(addcount_n - 1));
1164 memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
1165
1166 /*
1167 * Digest the modified header.
1168 */
1169 header_r.base = (unsigned char *)header;
1170 header_r.length = DNS_MESSAGE_HEADERLEN;
1171 RETERR(dst_context_adddata(ctx, &header_r));
1172
1173 /*
1174 * Digest all non-SIG(0) records.
1175 */
1176 r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
1177 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
1178 RETERR(dst_context_adddata(ctx, &r));
1179
1180 sig_r.base = sig.signature;
1181 sig_r.length = sig.siglen;
1182 result = dst_context_verify(ctx, &sig_r);
1183 if (result != ISC_R_SUCCESS) {
1184 msg->sig0status = dns_tsigerror_badsig;
1185 goto failure;
1186 }
1187
1188 msg->verified_sig = 1;
1189 msg->sig0status = dns_rcode_noerror;
1190
1191 dst_context_destroy(&ctx);
1192 dns_rdata_freestruct(&sig);
1193
1194 return (ISC_R_SUCCESS);
1195
1196 failure:
1197 if (signeedsfree) {
1198 dns_rdata_freestruct(&sig);
1199 }
1200 if (ctx != NULL) {
1201 dst_context_destroy(&ctx);
1202 }
1203
1204 return (result);
1205 }
1206
1207 /*%
1208 * Does this key ('rdata') self sign the rrset ('rdataset')?
1209 */
1210 bool
dns_dnssec_selfsigns(dns_rdata_t * rdata,const dns_name_t * name,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset,bool ignoretime,isc_mem_t * mctx)1211 dns_dnssec_selfsigns(dns_rdata_t *rdata, const dns_name_t *name,
1212 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
1213 bool ignoretime, isc_mem_t *mctx) {
1214 INSIST(rdataset->type == dns_rdatatype_key ||
1215 rdataset->type == dns_rdatatype_dnskey);
1216 if (rdataset->type == dns_rdatatype_key) {
1217 INSIST(sigrdataset->type == dns_rdatatype_sig);
1218 INSIST(sigrdataset->covers == dns_rdatatype_key);
1219 } else {
1220 INSIST(sigrdataset->type == dns_rdatatype_rrsig);
1221 INSIST(sigrdataset->covers == dns_rdatatype_dnskey);
1222 }
1223
1224 return (dns_dnssec_signs(rdata, name, rdataset, sigrdataset, ignoretime,
1225 mctx));
1226 }
1227
1228 bool
dns_dnssec_signs(dns_rdata_t * rdata,const dns_name_t * name,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset,bool ignoretime,isc_mem_t * mctx)1229 dns_dnssec_signs(dns_rdata_t *rdata, const dns_name_t *name,
1230 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
1231 bool ignoretime, isc_mem_t *mctx) {
1232 dst_key_t *dstkey = NULL;
1233 dns_keytag_t keytag;
1234 dns_rdata_dnskey_t key;
1235 dns_rdata_rrsig_t sig;
1236 dns_rdata_t sigrdata = DNS_RDATA_INIT;
1237 isc_result_t result;
1238
1239 INSIST(sigrdataset->type == dns_rdatatype_rrsig);
1240 if (sigrdataset->covers != rdataset->type) {
1241 return (false);
1242 }
1243
1244 result = dns_dnssec_keyfromrdata(name, rdata, mctx, &dstkey);
1245 if (result != ISC_R_SUCCESS) {
1246 return (false);
1247 }
1248 result = dns_rdata_tostruct(rdata, &key, NULL);
1249 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1250
1251 keytag = dst_key_id(dstkey);
1252 for (result = dns_rdataset_first(sigrdataset); result == ISC_R_SUCCESS;
1253 result = dns_rdataset_next(sigrdataset))
1254 {
1255 dns_rdata_reset(&sigrdata);
1256 dns_rdataset_current(sigrdataset, &sigrdata);
1257 result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
1258 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1259
1260 if (sig.algorithm == key.algorithm && sig.keyid == keytag) {
1261 result = dns_dnssec_verify(name, rdataset, dstkey,
1262 ignoretime, 0, mctx,
1263 &sigrdata, NULL);
1264 if (result == ISC_R_SUCCESS) {
1265 dst_key_free(&dstkey);
1266 return (true);
1267 }
1268 }
1269 }
1270 dst_key_free(&dstkey);
1271 return (false);
1272 }
1273
1274 isc_result_t
dns_dnsseckey_create(isc_mem_t * mctx,dst_key_t ** dstkey,dns_dnsseckey_t ** dkp)1275 dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey,
1276 dns_dnsseckey_t **dkp) {
1277 isc_result_t result;
1278 dns_dnsseckey_t *dk;
1279 int major, minor;
1280
1281 REQUIRE(dkp != NULL && *dkp == NULL);
1282 dk = isc_mem_get(mctx, sizeof(dns_dnsseckey_t));
1283
1284 dk->key = *dstkey;
1285 *dstkey = NULL;
1286 dk->force_publish = false;
1287 dk->force_sign = false;
1288 dk->hint_publish = false;
1289 dk->hint_sign = false;
1290 dk->hint_revoke = false;
1291 dk->hint_remove = false;
1292 dk->first_sign = false;
1293 dk->is_active = false;
1294 dk->purge = false;
1295 dk->prepublish = 0;
1296 dk->source = dns_keysource_unknown;
1297 dk->index = 0;
1298
1299 /* KSK or ZSK? */
1300 result = dst_key_getbool(dk->key, DST_BOOL_KSK, &dk->ksk);
1301 if (result != ISC_R_SUCCESS) {
1302 dk->ksk = ((dst_key_flags(dk->key) & DNS_KEYFLAG_KSK) != 0);
1303 }
1304 result = dst_key_getbool(dk->key, DST_BOOL_ZSK, &dk->zsk);
1305 if (result != ISC_R_SUCCESS) {
1306 dk->zsk = ((dst_key_flags(dk->key) & DNS_KEYFLAG_KSK) == 0);
1307 }
1308
1309 /* Is this an old-style key? */
1310 result = dst_key_getprivateformat(dk->key, &major, &minor);
1311 INSIST(result == ISC_R_SUCCESS);
1312
1313 /* Smart signing started with key format 1.3 */
1314 dk->legacy = (major == 1 && minor <= 2);
1315
1316 ISC_LINK_INIT(dk, link);
1317 *dkp = dk;
1318 return (ISC_R_SUCCESS);
1319 }
1320
1321 void
dns_dnsseckey_destroy(isc_mem_t * mctx,dns_dnsseckey_t ** dkp)1322 dns_dnsseckey_destroy(isc_mem_t *mctx, dns_dnsseckey_t **dkp) {
1323 dns_dnsseckey_t *dk;
1324
1325 REQUIRE(dkp != NULL && *dkp != NULL);
1326 dk = *dkp;
1327 *dkp = NULL;
1328 if (dk->key != NULL) {
1329 dst_key_free(&dk->key);
1330 }
1331 isc_mem_put(mctx, dk, sizeof(dns_dnsseckey_t));
1332 }
1333
1334 void
dns_dnssec_get_hints(dns_dnsseckey_t * key,isc_stdtime_t now)1335 dns_dnssec_get_hints(dns_dnsseckey_t *key, isc_stdtime_t now) {
1336 isc_stdtime_t publish = 0, active = 0, revoke = 0, remove = 0;
1337
1338 REQUIRE(key != NULL && key->key != NULL);
1339
1340 key->hint_publish = dst_key_is_published(key->key, now, &publish);
1341 key->hint_sign = dst_key_is_signing(key->key, DST_BOOL_ZSK, now,
1342 &active);
1343 key->hint_revoke = dst_key_is_revoked(key->key, now, &revoke);
1344 key->hint_remove = dst_key_is_removed(key->key, now, &remove);
1345
1346 /*
1347 * Activation date is set (maybe in the future), but publication date
1348 * isn't. Most likely the user wants to publish now and activate later.
1349 * Most likely because this is true for most rollovers, except for:
1350 * 1. The unpopular ZSK Double-RRSIG method.
1351 * 2. When introducing a new algorithm.
1352 * These two cases are rare enough that we will set hint_publish
1353 * anyway when hint_sign is set, because BIND 9 natively does not
1354 * support the ZSK Double-RRSIG method, and when introducing a new
1355 * algorithm, we strive to publish its signatures and DNSKEY records
1356 * at the same time.
1357 */
1358 if (key->hint_sign && publish == 0) {
1359 key->hint_publish = true;
1360 }
1361
1362 /*
1363 * If activation date is in the future, make note of how far off.
1364 */
1365 if (key->hint_publish && active > now) {
1366 key->prepublish = active - now;
1367 }
1368
1369 /*
1370 * Metadata says revoke. If the key is published, we *have to* sign
1371 * with it per RFC5011 -- even if it was not active before.
1372 *
1373 * If it hasn't already been done, we should also revoke it now.
1374 */
1375 if (key->hint_publish && key->hint_revoke) {
1376 uint32_t flags;
1377 key->hint_sign = true;
1378 flags = dst_key_flags(key->key);
1379 if ((flags & DNS_KEYFLAG_REVOKE) == 0) {
1380 flags |= DNS_KEYFLAG_REVOKE;
1381 dst_key_setflags(key->key, flags);
1382 }
1383 }
1384
1385 /*
1386 * Metadata says delete, so don't publish this key or sign with it
1387 * (note that signatures of a removed key may still be reused).
1388 */
1389 if (key->hint_remove) {
1390 key->hint_publish = false;
1391 key->hint_sign = false;
1392 }
1393 }
1394
1395 /*%
1396 * Get a list of DNSSEC keys from the key repository.
1397 */
1398 isc_result_t
dns_dnssec_findmatchingkeys(const dns_name_t * origin,const char * directory,isc_stdtime_t now,isc_mem_t * mctx,dns_dnsseckeylist_t * keylist)1399 dns_dnssec_findmatchingkeys(const dns_name_t *origin, const char *directory,
1400 isc_stdtime_t now, isc_mem_t *mctx,
1401 dns_dnsseckeylist_t *keylist) {
1402 isc_result_t result = ISC_R_SUCCESS;
1403 bool dir_open = false;
1404 dns_dnsseckeylist_t list;
1405 isc_dir_t dir;
1406 dns_dnsseckey_t *key = NULL;
1407 dst_key_t *dstkey = NULL;
1408 char namebuf[DNS_NAME_FORMATSIZE];
1409 isc_buffer_t b;
1410 unsigned int len, i, alg;
1411
1412 REQUIRE(keylist != NULL);
1413 ISC_LIST_INIT(list);
1414 isc_dir_init(&dir);
1415
1416 isc_buffer_init(&b, namebuf, sizeof(namebuf) - 1);
1417 RETERR(dns_name_tofilenametext(origin, false, &b));
1418 len = isc_buffer_usedlength(&b);
1419 namebuf[len] = '\0';
1420
1421 if (directory == NULL) {
1422 directory = ".";
1423 }
1424 RETERR(isc_dir_open(&dir, directory));
1425 dir_open = true;
1426
1427 while (isc_dir_read(&dir) == ISC_R_SUCCESS) {
1428 if (dir.entry.name[0] != 'K' || dir.entry.length < len + 1 ||
1429 dir.entry.name[len + 1] != '+' ||
1430 strncasecmp(dir.entry.name + 1, namebuf, len) != 0)
1431 {
1432 continue;
1433 }
1434
1435 alg = 0;
1436 for (i = len + 1 + 1; i < dir.entry.length; i++) {
1437 if (!isdigit((unsigned char)dir.entry.name[i])) {
1438 break;
1439 }
1440 alg *= 10;
1441 alg += dir.entry.name[i] - '0';
1442 }
1443
1444 /*
1445 * Did we not read exactly 3 digits?
1446 * Did we overflow?
1447 * Did we correctly terminate?
1448 */
1449 if (i != len + 1 + 1 + 3 || i >= dir.entry.length ||
1450 dir.entry.name[i] != '+') {
1451 continue;
1452 }
1453
1454 for (i++; i < dir.entry.length; i++) {
1455 if (!isdigit((unsigned char)dir.entry.name[i])) {
1456 break;
1457 }
1458 }
1459
1460 /*
1461 * Did we not read exactly 5 more digits?
1462 * Did we overflow?
1463 * Did we correctly terminate?
1464 */
1465 if (i != len + 1 + 1 + 3 + 1 + 5 || i >= dir.entry.length ||
1466 strcmp(dir.entry.name + i, ".private") != 0)
1467 {
1468 continue;
1469 }
1470
1471 dstkey = NULL;
1472 result = dst_key_fromnamedfile(
1473 dir.entry.name, directory,
1474 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE,
1475 mctx, &dstkey);
1476
1477 switch (alg) {
1478 case DST_ALG_HMACMD5:
1479 case DST_ALG_HMACSHA1:
1480 case DST_ALG_HMACSHA224:
1481 case DST_ALG_HMACSHA256:
1482 case DST_ALG_HMACSHA384:
1483 case DST_ALG_HMACSHA512:
1484 if (result == DST_R_BADKEYTYPE) {
1485 continue;
1486 }
1487 }
1488
1489 if (result != ISC_R_SUCCESS) {
1490 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
1491 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
1492 "dns_dnssec_findmatchingkeys: "
1493 "error reading key file %s: %s",
1494 dir.entry.name,
1495 isc_result_totext(result));
1496 continue;
1497 }
1498
1499 RETERR(dns_dnsseckey_create(mctx, &dstkey, &key));
1500 key->source = dns_keysource_repository;
1501 dns_dnssec_get_hints(key, now);
1502
1503 if (key->legacy) {
1504 dns_dnsseckey_destroy(mctx, &key);
1505 } else {
1506 ISC_LIST_APPEND(list, key, link);
1507 key = NULL;
1508 }
1509 }
1510
1511 if (!ISC_LIST_EMPTY(list)) {
1512 result = ISC_R_SUCCESS;
1513 ISC_LIST_APPENDLIST(*keylist, list, link);
1514 } else {
1515 result = ISC_R_NOTFOUND;
1516 }
1517
1518 failure:
1519 if (dir_open) {
1520 isc_dir_close(&dir);
1521 }
1522 INSIST(key == NULL);
1523 while ((key = ISC_LIST_HEAD(list)) != NULL) {
1524 ISC_LIST_UNLINK(list, key, link);
1525 INSIST(key->key != NULL);
1526 dst_key_free(&key->key);
1527 dns_dnsseckey_destroy(mctx, &key);
1528 }
1529 if (dstkey != NULL) {
1530 dst_key_free(&dstkey);
1531 }
1532 return (result);
1533 }
1534
1535 /*%
1536 * Add 'newkey' to 'keylist' if it's not already there.
1537 *
1538 * If 'savekeys' is true, then we need to preserve all
1539 * the keys in the keyset, regardless of whether they have
1540 * metadata indicating they should be deactivated or removed.
1541 */
1542 static isc_result_t
addkey(dns_dnsseckeylist_t * keylist,dst_key_t ** newkey,bool savekeys,isc_mem_t * mctx)1543 addkey(dns_dnsseckeylist_t *keylist, dst_key_t **newkey, bool savekeys,
1544 isc_mem_t *mctx) {
1545 dns_dnsseckey_t *key;
1546 isc_result_t result;
1547
1548 /* Skip duplicates */
1549 for (key = ISC_LIST_HEAD(*keylist); key != NULL;
1550 key = ISC_LIST_NEXT(key, link)) {
1551 if (dst_key_id(key->key) == dst_key_id(*newkey) &&
1552 dst_key_alg(key->key) == dst_key_alg(*newkey) &&
1553 dns_name_equal(dst_key_name(key->key),
1554 dst_key_name(*newkey)))
1555 {
1556 break;
1557 }
1558 }
1559
1560 if (key != NULL) {
1561 /*
1562 * Found a match. If the old key was only public and the
1563 * new key is private, replace the old one; otherwise
1564 * leave it. But either way, mark the key as having
1565 * been found in the zone.
1566 */
1567 if (dst_key_isprivate(key->key)) {
1568 dst_key_free(newkey);
1569 } else if (dst_key_isprivate(*newkey)) {
1570 dst_key_free(&key->key);
1571 key->key = *newkey;
1572 }
1573
1574 key->source = dns_keysource_zoneapex;
1575 return (ISC_R_SUCCESS);
1576 }
1577
1578 result = dns_dnsseckey_create(mctx, newkey, &key);
1579 if (result != ISC_R_SUCCESS) {
1580 return (result);
1581 }
1582 if (key->legacy || savekeys) {
1583 key->force_publish = true;
1584 key->force_sign = dst_key_isprivate(key->key);
1585 }
1586 key->source = dns_keysource_zoneapex;
1587 ISC_LIST_APPEND(*keylist, key, link);
1588 *newkey = NULL;
1589 return (ISC_R_SUCCESS);
1590 }
1591
1592 /*%
1593 * Mark all keys which signed the DNSKEY/SOA RRsets as "active",
1594 * for future reference.
1595 */
1596 static isc_result_t
mark_active_keys(dns_dnsseckeylist_t * keylist,dns_rdataset_t * rrsigs)1597 mark_active_keys(dns_dnsseckeylist_t *keylist, dns_rdataset_t *rrsigs) {
1598 isc_result_t result = ISC_R_SUCCESS;
1599 dns_rdata_t rdata = DNS_RDATA_INIT;
1600 dns_rdataset_t sigs;
1601 dns_dnsseckey_t *key;
1602
1603 REQUIRE(rrsigs != NULL && dns_rdataset_isassociated(rrsigs));
1604
1605 dns_rdataset_init(&sigs);
1606 dns_rdataset_clone(rrsigs, &sigs);
1607 for (key = ISC_LIST_HEAD(*keylist); key != NULL;
1608 key = ISC_LIST_NEXT(key, link)) {
1609 uint16_t keyid, sigid;
1610 dns_secalg_t keyalg, sigalg;
1611 keyid = dst_key_id(key->key);
1612 keyalg = dst_key_alg(key->key);
1613
1614 for (result = dns_rdataset_first(&sigs);
1615 result == ISC_R_SUCCESS; result = dns_rdataset_next(&sigs))
1616 {
1617 dns_rdata_rrsig_t sig;
1618
1619 dns_rdata_reset(&rdata);
1620 dns_rdataset_current(&sigs, &rdata);
1621 result = dns_rdata_tostruct(&rdata, &sig, NULL);
1622 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1623 sigalg = sig.algorithm;
1624 sigid = sig.keyid;
1625 if (keyid == sigid && keyalg == sigalg) {
1626 key->is_active = true;
1627 break;
1628 }
1629 }
1630 }
1631
1632 if (result == ISC_R_NOMORE) {
1633 result = ISC_R_SUCCESS;
1634 }
1635
1636 if (dns_rdataset_isassociated(&sigs)) {
1637 dns_rdataset_disassociate(&sigs);
1638 }
1639 return (result);
1640 }
1641
1642 /*%
1643 * Add the contents of a DNSKEY rdataset 'keyset' to 'keylist'.
1644 */
1645 isc_result_t
dns_dnssec_keylistfromrdataset(const dns_name_t * origin,const char * directory,isc_mem_t * mctx,dns_rdataset_t * keyset,dns_rdataset_t * keysigs,dns_rdataset_t * soasigs,bool savekeys,bool publickey,dns_dnsseckeylist_t * keylist)1646 dns_dnssec_keylistfromrdataset(const dns_name_t *origin, const char *directory,
1647 isc_mem_t *mctx, dns_rdataset_t *keyset,
1648 dns_rdataset_t *keysigs, dns_rdataset_t *soasigs,
1649 bool savekeys, bool publickey,
1650 dns_dnsseckeylist_t *keylist) {
1651 dns_rdataset_t keys;
1652 dns_rdata_t rdata = DNS_RDATA_INIT;
1653 dst_key_t *dnskey = NULL, *pubkey = NULL, *privkey = NULL;
1654 isc_result_t result;
1655
1656 REQUIRE(keyset != NULL && dns_rdataset_isassociated(keyset));
1657
1658 dns_rdataset_init(&keys);
1659
1660 dns_rdataset_clone(keyset, &keys);
1661 for (result = dns_rdataset_first(&keys); result == ISC_R_SUCCESS;
1662 result = dns_rdataset_next(&keys))
1663 {
1664 dns_rdata_reset(&rdata);
1665 dns_rdataset_current(&keys, &rdata);
1666
1667 REQUIRE(rdata.type == dns_rdatatype_key ||
1668 rdata.type == dns_rdatatype_dnskey);
1669 REQUIRE(rdata.length > 3);
1670
1671 /* Skip unsupported algorithms */
1672 if (!dst_algorithm_supported(rdata.data[3])) {
1673 goto skip;
1674 }
1675
1676 RETERR(dns_dnssec_keyfromrdata(origin, &rdata, mctx, &dnskey));
1677 dst_key_setttl(dnskey, keys.ttl);
1678
1679 if (!is_zone_key(dnskey) ||
1680 (dst_key_flags(dnskey) & DNS_KEYTYPE_NOAUTH) != 0) {
1681 goto skip;
1682 }
1683
1684 /* Corrupted .key file? */
1685 if (!dns_name_equal(origin, dst_key_name(dnskey))) {
1686 goto skip;
1687 }
1688
1689 if (publickey) {
1690 RETERR(addkey(keylist, &dnskey, savekeys, mctx));
1691 goto skip;
1692 }
1693
1694 /* Try to read the public key. */
1695 result = dst_key_fromfile(
1696 dst_key_name(dnskey), dst_key_id(dnskey),
1697 dst_key_alg(dnskey), (DST_TYPE_PUBLIC | DST_TYPE_STATE),
1698 directory, mctx, &pubkey);
1699 if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) {
1700 result = ISC_R_SUCCESS;
1701 }
1702 RETERR(result);
1703
1704 /* Now read the private key. */
1705 result = dst_key_fromfile(
1706 dst_key_name(dnskey), dst_key_id(dnskey),
1707 dst_key_alg(dnskey),
1708 (DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE),
1709 directory, mctx, &privkey);
1710
1711 /*
1712 * If the key was revoked and the private file
1713 * doesn't exist, maybe it was revoked internally
1714 * by named. Try loading the unrevoked version.
1715 */
1716 if (result == ISC_R_FILENOTFOUND) {
1717 uint32_t flags;
1718 flags = dst_key_flags(dnskey);
1719 if ((flags & DNS_KEYFLAG_REVOKE) != 0) {
1720 dst_key_setflags(dnskey,
1721 flags & ~DNS_KEYFLAG_REVOKE);
1722 result = dst_key_fromfile(
1723 dst_key_name(dnskey),
1724 dst_key_id(dnskey), dst_key_alg(dnskey),
1725 (DST_TYPE_PUBLIC | DST_TYPE_PRIVATE |
1726 DST_TYPE_STATE),
1727 directory, mctx, &privkey);
1728 if (result == ISC_R_SUCCESS &&
1729 dst_key_pubcompare(dnskey, privkey, false))
1730 {
1731 dst_key_setflags(privkey, flags);
1732 }
1733 dst_key_setflags(dnskey, flags);
1734 }
1735 }
1736
1737 if (result != ISC_R_SUCCESS) {
1738 char filename[DNS_NAME_FORMATSIZE +
1739 DNS_SECALG_FORMATSIZE +
1740 sizeof("key file for //65535")];
1741 isc_result_t result2;
1742 isc_buffer_t buf;
1743
1744 isc_buffer_init(&buf, filename, NAME_MAX);
1745 result2 = dst_key_getfilename(
1746 dst_key_name(dnskey), dst_key_id(dnskey),
1747 dst_key_alg(dnskey),
1748 (DST_TYPE_PUBLIC | DST_TYPE_PRIVATE |
1749 DST_TYPE_STATE),
1750 directory, mctx, &buf);
1751 if (result2 != ISC_R_SUCCESS) {
1752 char namebuf[DNS_NAME_FORMATSIZE];
1753 char algbuf[DNS_SECALG_FORMATSIZE];
1754
1755 dns_name_format(dst_key_name(dnskey), namebuf,
1756 sizeof(namebuf));
1757 dns_secalg_format(dst_key_alg(dnskey), algbuf,
1758 sizeof(algbuf));
1759 snprintf(filename, sizeof(filename) - 1,
1760 "key file for %s/%s/%d", namebuf,
1761 algbuf, dst_key_id(dnskey));
1762 }
1763
1764 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
1765 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
1766 "dns_dnssec_keylistfromrdataset: error "
1767 "reading %s: %s",
1768 filename, isc_result_totext(result));
1769 }
1770
1771 if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) {
1772 if (pubkey != NULL) {
1773 RETERR(addkey(keylist, &pubkey, savekeys,
1774 mctx));
1775 } else {
1776 RETERR(addkey(keylist, &dnskey, savekeys,
1777 mctx));
1778 }
1779 goto skip;
1780 }
1781 RETERR(result);
1782
1783 /* This should never happen. */
1784 if ((dst_key_flags(privkey) & DNS_KEYTYPE_NOAUTH) != 0) {
1785 goto skip;
1786 }
1787
1788 /*
1789 * Whatever the key's default TTL may have
1790 * been, the rdataset TTL takes priority.
1791 */
1792 dst_key_setttl(privkey, dst_key_getttl(dnskey));
1793
1794 RETERR(addkey(keylist, &privkey, savekeys, mctx));
1795 skip:
1796 if (dnskey != NULL) {
1797 dst_key_free(&dnskey);
1798 }
1799 if (pubkey != NULL) {
1800 dst_key_free(&pubkey);
1801 }
1802 if (privkey != NULL) {
1803 dst_key_free(&privkey);
1804 }
1805 }
1806
1807 if (result != ISC_R_NOMORE) {
1808 RETERR(result);
1809 }
1810
1811 if (keysigs != NULL && dns_rdataset_isassociated(keysigs)) {
1812 RETERR(mark_active_keys(keylist, keysigs));
1813 }
1814
1815 if (soasigs != NULL && dns_rdataset_isassociated(soasigs)) {
1816 RETERR(mark_active_keys(keylist, soasigs));
1817 }
1818
1819 result = ISC_R_SUCCESS;
1820
1821 failure:
1822 if (dns_rdataset_isassociated(&keys)) {
1823 dns_rdataset_disassociate(&keys);
1824 }
1825 if (dnskey != NULL) {
1826 dst_key_free(&dnskey);
1827 }
1828 if (pubkey != NULL) {
1829 dst_key_free(&pubkey);
1830 }
1831 if (privkey != NULL) {
1832 dst_key_free(&privkey);
1833 }
1834 return (result);
1835 }
1836
1837 static isc_result_t
make_dnskey(dst_key_t * key,unsigned char * buf,int bufsize,dns_rdata_t * target)1838 make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize,
1839 dns_rdata_t *target) {
1840 isc_result_t result;
1841 isc_buffer_t b;
1842 isc_region_t r;
1843
1844 isc_buffer_init(&b, buf, bufsize);
1845 result = dst_key_todns(key, &b);
1846 if (result != ISC_R_SUCCESS) {
1847 return (result);
1848 }
1849
1850 dns_rdata_reset(target);
1851 isc_buffer_usedregion(&b, &r);
1852 dns_rdata_fromregion(target, dst_key_class(key), dns_rdatatype_dnskey,
1853 &r);
1854 return (ISC_R_SUCCESS);
1855 }
1856
1857 static isc_result_t
addrdata(dns_rdata_t * rdata,dns_diff_t * diff,const dns_name_t * origin,dns_ttl_t ttl,isc_mem_t * mctx)1858 addrdata(dns_rdata_t *rdata, dns_diff_t *diff, const dns_name_t *origin,
1859 dns_ttl_t ttl, isc_mem_t *mctx) {
1860 isc_result_t result;
1861 dns_difftuple_t *tuple = NULL;
1862
1863 RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_ADD, origin, ttl, rdata,
1864 &tuple));
1865 dns_diff_appendminimal(diff, &tuple);
1866
1867 failure:
1868 return (result);
1869 }
1870
1871 static isc_result_t
delrdata(dns_rdata_t * rdata,dns_diff_t * diff,const dns_name_t * origin,dns_ttl_t ttl,isc_mem_t * mctx)1872 delrdata(dns_rdata_t *rdata, dns_diff_t *diff, const dns_name_t *origin,
1873 dns_ttl_t ttl, isc_mem_t *mctx) {
1874 isc_result_t result;
1875 dns_difftuple_t *tuple = NULL;
1876
1877 RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_DEL, origin, ttl, rdata,
1878 &tuple));
1879 dns_diff_appendminimal(diff, &tuple);
1880
1881 failure:
1882 return (result);
1883 }
1884
1885 static isc_result_t
publish_key(dns_diff_t * diff,dns_dnsseckey_t * key,const dns_name_t * origin,dns_ttl_t ttl,isc_mem_t * mctx,void (* report)(const char *,...))1886 publish_key(dns_diff_t *diff, dns_dnsseckey_t *key, const dns_name_t *origin,
1887 dns_ttl_t ttl, isc_mem_t *mctx, void (*report)(const char *, ...)) {
1888 isc_result_t result;
1889 unsigned char buf[DST_KEY_MAXSIZE];
1890 char keystr[DST_KEY_FORMATSIZE];
1891 dns_rdata_t dnskey = DNS_RDATA_INIT;
1892
1893 dns_rdata_reset(&dnskey);
1894 RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey));
1895 dst_key_format(key->key, keystr, sizeof(keystr));
1896
1897 report("Fetching %s (%s) from key %s.", keystr,
1898 key->ksk ? (key->zsk ? "CSK" : "KSK") : "ZSK",
1899 key->source == dns_keysource_user ? "file" : "repository");
1900
1901 if (key->prepublish && ttl > key->prepublish) {
1902 isc_stdtime_t now;
1903
1904 report("Key %s: Delaying activation to match the DNSKEY TTL.",
1905 keystr, ttl);
1906
1907 isc_stdtime_get(&now);
1908 dst_key_settime(key->key, DST_TIME_ACTIVATE, now + ttl);
1909 }
1910
1911 /* publish key */
1912 result = addrdata(&dnskey, diff, origin, ttl, mctx);
1913
1914 failure:
1915 return (result);
1916 }
1917
1918 static isc_result_t
remove_key(dns_diff_t * diff,dns_dnsseckey_t * key,const dns_name_t * origin,dns_ttl_t ttl,isc_mem_t * mctx,const char * reason,void (* report)(const char *,...))1919 remove_key(dns_diff_t *diff, dns_dnsseckey_t *key, const dns_name_t *origin,
1920 dns_ttl_t ttl, isc_mem_t *mctx, const char *reason,
1921 void (*report)(const char *, ...)) {
1922 isc_result_t result;
1923 unsigned char buf[DST_KEY_MAXSIZE];
1924 dns_rdata_t dnskey = DNS_RDATA_INIT;
1925 char alg[80];
1926
1927 dns_secalg_format(dst_key_alg(key->key), alg, sizeof(alg));
1928 report("Removing %s key %d/%s from DNSKEY RRset.", reason,
1929 dst_key_id(key->key), alg);
1930
1931 RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey));
1932 result = delrdata(&dnskey, diff, origin, ttl, mctx);
1933
1934 failure:
1935 return (result);
1936 }
1937
1938 static bool
exists(dns_rdataset_t * rdataset,dns_rdata_t * rdata)1939 exists(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
1940 isc_result_t result;
1941 dns_rdataset_t trdataset;
1942
1943 dns_rdataset_init(&trdataset);
1944 dns_rdataset_clone(rdataset, &trdataset);
1945 for (result = dns_rdataset_first(&trdataset); result == ISC_R_SUCCESS;
1946 result = dns_rdataset_next(&trdataset))
1947 {
1948 dns_rdata_t current = DNS_RDATA_INIT;
1949
1950 dns_rdataset_current(&trdataset, ¤t);
1951 if (dns_rdata_compare(rdata, ¤t) == 0) {
1952 dns_rdataset_disassociate(&trdataset);
1953 return (true);
1954 }
1955 }
1956 dns_rdataset_disassociate(&trdataset);
1957 return (false);
1958 }
1959
1960 isc_result_t
dns_dnssec_syncupdate(dns_dnsseckeylist_t * keys,dns_dnsseckeylist_t * rmkeys,dns_rdataset_t * cds,dns_rdataset_t * cdnskey,isc_stdtime_t now,dns_ttl_t ttl,dns_diff_t * diff,isc_mem_t * mctx)1961 dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
1962 dns_rdataset_t *cds, dns_rdataset_t *cdnskey,
1963 isc_stdtime_t now, dns_ttl_t ttl, dns_diff_t *diff,
1964 isc_mem_t *mctx) {
1965 unsigned char dsbuf1[DNS_DS_BUFFERSIZE];
1966 unsigned char dsbuf2[DNS_DS_BUFFERSIZE];
1967 unsigned char keybuf[DST_KEY_MAXSIZE];
1968 isc_result_t result;
1969 dns_dnsseckey_t *key;
1970
1971 for (key = ISC_LIST_HEAD(*keys); key != NULL;
1972 key = ISC_LIST_NEXT(key, link)) {
1973 dns_rdata_t cds_sha1 = DNS_RDATA_INIT;
1974 dns_rdata_t cds_sha256 = DNS_RDATA_INIT;
1975 dns_rdata_t cdnskeyrdata = DNS_RDATA_INIT;
1976 dns_name_t *origin = dst_key_name(key->key);
1977
1978 RETERR(make_dnskey(key->key, keybuf, sizeof(keybuf),
1979 &cdnskeyrdata));
1980
1981 /*
1982 * We construct the SHA-1 version of the record so we can
1983 * delete any old records generated by previous versions of
1984 * BIND. We only add SHA-256 records.
1985 *
1986 * XXXMPA we need to be able to specify the DS algorithms
1987 * to be used here and below with rmkeys.
1988 */
1989 RETERR(dns_ds_buildrdata(origin, &cdnskeyrdata,
1990 DNS_DSDIGEST_SHA1, dsbuf1, &cds_sha1));
1991 RETERR(dns_ds_buildrdata(origin, &cdnskeyrdata,
1992 DNS_DSDIGEST_SHA256, dsbuf2,
1993 &cds_sha256));
1994
1995 /*
1996 * Now that the we have created the DS records convert
1997 * the rdata to CDNSKEY and CDS for comparison.
1998 */
1999 cdnskeyrdata.type = dns_rdatatype_cdnskey;
2000 cds_sha1.type = dns_rdatatype_cds;
2001 cds_sha256.type = dns_rdatatype_cds;
2002
2003 if (syncpublish(key->key, now)) {
2004 char keystr[DST_KEY_FORMATSIZE];
2005 dst_key_format(key->key, keystr, sizeof(keystr));
2006
2007 if (!dns_rdataset_isassociated(cdnskey) ||
2008 !exists(cdnskey, &cdnskeyrdata)) {
2009 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
2010 DNS_LOGMODULE_DNSSEC,
2011 ISC_LOG_INFO,
2012 "CDS for key %s is now published",
2013 keystr);
2014 RETERR(addrdata(&cdnskeyrdata, diff, origin,
2015 ttl, mctx));
2016 }
2017 /* Only publish SHA-256 (SHA-1 is deprecated) */
2018 if (!dns_rdataset_isassociated(cds) ||
2019 !exists(cds, &cds_sha256)) {
2020 isc_log_write(
2021 dns_lctx, DNS_LOGCATEGORY_GENERAL,
2022 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
2023 "CDNSKEY for key %s is now published",
2024 keystr);
2025 RETERR(addrdata(&cds_sha256, diff, origin, ttl,
2026 mctx));
2027 }
2028 }
2029
2030 if (syncdelete(key->key, now)) {
2031 char keystr[DST_KEY_FORMATSIZE];
2032 dst_key_format(key->key, keystr, sizeof(keystr));
2033
2034 if (dns_rdataset_isassociated(cds)) {
2035 /* Delete both SHA-1 and SHA-256 */
2036 if (exists(cds, &cds_sha1)) {
2037 isc_log_write(dns_lctx,
2038 DNS_LOGCATEGORY_GENERAL,
2039 DNS_LOGMODULE_DNSSEC,
2040 ISC_LOG_INFO,
2041 "CDS (SHA-1) for key %s "
2042 "is now deleted",
2043 keystr);
2044 RETERR(delrdata(&cds_sha1, diff, origin,
2045 cds->ttl, mctx));
2046 }
2047 if (exists(cds, &cds_sha256)) {
2048 isc_log_write(dns_lctx,
2049 DNS_LOGCATEGORY_GENERAL,
2050 DNS_LOGMODULE_DNSSEC,
2051 ISC_LOG_INFO,
2052 "CDS (SHA-256) for key "
2053 "%s is now deleted",
2054 keystr);
2055 RETERR(delrdata(&cds_sha256, diff,
2056 origin, cds->ttl,
2057 mctx));
2058 }
2059 }
2060
2061 if (dns_rdataset_isassociated(cdnskey)) {
2062 if (exists(cdnskey, &cdnskeyrdata)) {
2063 isc_log_write(dns_lctx,
2064 DNS_LOGCATEGORY_GENERAL,
2065 DNS_LOGMODULE_DNSSEC,
2066 ISC_LOG_INFO,
2067 "CDNSKEY for key %s is "
2068 "now deleted",
2069 keystr);
2070 RETERR(delrdata(&cdnskeyrdata, diff,
2071 origin, cdnskey->ttl,
2072 mctx));
2073 }
2074 }
2075 }
2076 }
2077
2078 if (!dns_rdataset_isassociated(cds) &&
2079 !dns_rdataset_isassociated(cdnskey)) {
2080 return (ISC_R_SUCCESS);
2081 }
2082
2083 /*
2084 * Unconditionally remove CDS/DNSKEY records for removed keys.
2085 */
2086 for (key = ISC_LIST_HEAD(*rmkeys); key != NULL;
2087 key = ISC_LIST_NEXT(key, link)) {
2088 dns_rdata_t cds_sha1 = DNS_RDATA_INIT;
2089 dns_rdata_t cds_sha256 = DNS_RDATA_INIT;
2090 dns_rdata_t cdnskeyrdata = DNS_RDATA_INIT;
2091 dns_name_t *origin = dst_key_name(key->key);
2092
2093 char keystr[DST_KEY_FORMATSIZE];
2094 dst_key_format(key->key, keystr, sizeof(keystr));
2095
2096 RETERR(make_dnskey(key->key, keybuf, sizeof(keybuf),
2097 &cdnskeyrdata));
2098
2099 if (dns_rdataset_isassociated(cds)) {
2100 RETERR(dns_ds_buildrdata(origin, &cdnskeyrdata,
2101 DNS_DSDIGEST_SHA1, dsbuf1,
2102 &cds_sha1));
2103 RETERR(dns_ds_buildrdata(origin, &cdnskeyrdata,
2104 DNS_DSDIGEST_SHA256, dsbuf2,
2105 &cds_sha256));
2106 if (exists(cds, &cds_sha1)) {
2107 isc_log_write(
2108 dns_lctx, DNS_LOGCATEGORY_GENERAL,
2109 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
2110 "CDS (SHA-1) for key %s is now deleted",
2111 keystr);
2112 RETERR(delrdata(&cds_sha1, diff, origin,
2113 cds->ttl, mctx));
2114 }
2115 if (exists(cds, &cds_sha256)) {
2116 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
2117 DNS_LOGMODULE_DNSSEC,
2118 ISC_LOG_INFO,
2119 "CDS (SHA-256) for key %s is now "
2120 "deleted",
2121 keystr);
2122 RETERR(delrdata(&cds_sha256, diff, origin,
2123 cds->ttl, mctx));
2124 }
2125 }
2126
2127 if (dns_rdataset_isassociated(cdnskey)) {
2128 if (exists(cdnskey, &cdnskeyrdata)) {
2129 isc_log_write(
2130 dns_lctx, DNS_LOGCATEGORY_GENERAL,
2131 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
2132 "CDNSKEY for key %s is now deleted",
2133 keystr);
2134 RETERR(delrdata(&cdnskeyrdata, diff, origin,
2135 cdnskey->ttl, mctx));
2136 }
2137 }
2138 }
2139
2140 result = ISC_R_SUCCESS;
2141
2142 failure:
2143 return (result);
2144 }
2145
2146 isc_result_t
dns_dnssec_syncdelete(dns_rdataset_t * cds,dns_rdataset_t * cdnskey,dns_name_t * origin,dns_rdataclass_t zclass,dns_ttl_t ttl,dns_diff_t * diff,isc_mem_t * mctx,bool dnssec_insecure)2147 dns_dnssec_syncdelete(dns_rdataset_t *cds, dns_rdataset_t *cdnskey,
2148 dns_name_t *origin, dns_rdataclass_t zclass,
2149 dns_ttl_t ttl, dns_diff_t *diff, isc_mem_t *mctx,
2150 bool dnssec_insecure) {
2151 unsigned char dsbuf[5] = { 0, 0, 0, 0, 0 }; /* CDS DELETE rdata */
2152 unsigned char keybuf[5] = { 0, 0, 3, 0, 0 }; /* CDNSKEY DELETE rdata */
2153 char namebuf[DNS_NAME_FORMATSIZE];
2154 dns_rdata_t cds_delete = DNS_RDATA_INIT;
2155 dns_rdata_t cdnskey_delete = DNS_RDATA_INIT;
2156 isc_region_t r;
2157 isc_result_t result;
2158
2159 r.base = keybuf;
2160 r.length = sizeof(keybuf);
2161 dns_rdata_fromregion(&cdnskey_delete, zclass, dns_rdatatype_cdnskey,
2162 &r);
2163
2164 r.base = dsbuf;
2165 r.length = sizeof(dsbuf);
2166 dns_rdata_fromregion(&cds_delete, zclass, dns_rdatatype_cds, &r);
2167
2168 dns_name_format(origin, namebuf, sizeof(namebuf));
2169
2170 if (dnssec_insecure) {
2171 if (!dns_rdataset_isassociated(cdnskey) ||
2172 !exists(cdnskey, &cdnskey_delete)) {
2173 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
2174 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
2175 "CDNSKEY (DELETE) for zone %s is now "
2176 "published",
2177 namebuf);
2178 RETERR(addrdata(&cdnskey_delete, diff, origin, ttl,
2179 mctx));
2180 }
2181
2182 if (!dns_rdataset_isassociated(cds) ||
2183 !exists(cds, &cds_delete)) {
2184 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
2185 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
2186 "CDS (DELETE) for zone %s is now "
2187 "published",
2188 namebuf);
2189 RETERR(addrdata(&cds_delete, diff, origin, ttl, mctx));
2190 }
2191 } else {
2192 if (dns_rdataset_isassociated(cdnskey) &&
2193 exists(cdnskey, &cdnskey_delete)) {
2194 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
2195 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
2196 "CDNSKEY (DELETE) for zone %s is now "
2197 "deleted",
2198 namebuf);
2199 RETERR(delrdata(&cdnskey_delete, diff, origin,
2200 cdnskey->ttl, mctx));
2201 }
2202
2203 if (dns_rdataset_isassociated(cds) && exists(cds, &cds_delete))
2204 {
2205 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
2206 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
2207 "CDS (DELETE) for zone %s is now "
2208 "deleted",
2209 namebuf);
2210 RETERR(delrdata(&cds_delete, diff, origin, cds->ttl,
2211 mctx));
2212 }
2213 }
2214
2215 result = ISC_R_SUCCESS;
2216
2217 failure:
2218 return (result);
2219 }
2220
2221 /*
2222 * Update 'keys' with information from 'newkeys'.
2223 *
2224 * If 'removed' is not NULL, any keys that are being removed from
2225 * the zone will be added to the list for post-removal processing.
2226 */
2227 isc_result_t
dns_dnssec_updatekeys(dns_dnsseckeylist_t * keys,dns_dnsseckeylist_t * newkeys,dns_dnsseckeylist_t * removed,const dns_name_t * origin,dns_ttl_t hint_ttl,dns_diff_t * diff,isc_mem_t * mctx,void (* report)(const char *,...))2228 dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys,
2229 dns_dnsseckeylist_t *removed, const dns_name_t *origin,
2230 dns_ttl_t hint_ttl, dns_diff_t *diff, isc_mem_t *mctx,
2231 void (*report)(const char *, ...)) {
2232 isc_result_t result;
2233 dns_dnsseckey_t *key, *key1, *key2, *next;
2234 bool found_ttl = false;
2235 dns_ttl_t ttl = hint_ttl;
2236
2237 /*
2238 * First, look through the existing key list to find keys
2239 * supplied from the command line which are not in the zone.
2240 * Update the zone to include them.
2241 *
2242 * Also, if there are keys published in the zone already,
2243 * use their TTL for all subsequent published keys.
2244 */
2245 for (key = ISC_LIST_HEAD(*keys); key != NULL;
2246 key = ISC_LIST_NEXT(key, link)) {
2247 if (key->source == dns_keysource_user &&
2248 (key->hint_publish || key->force_publish))
2249 {
2250 RETERR(publish_key(diff, key, origin, ttl, mctx,
2251 report));
2252 }
2253 if (key->source == dns_keysource_zoneapex) {
2254 ttl = dst_key_getttl(key->key);
2255 found_ttl = true;
2256 }
2257 }
2258
2259 /*
2260 * If there were no existing keys, use the smallest nonzero
2261 * TTL of the keys found in the repository.
2262 */
2263 if (!found_ttl && !ISC_LIST_EMPTY(*newkeys)) {
2264 dns_ttl_t shortest = 0;
2265
2266 for (key = ISC_LIST_HEAD(*newkeys); key != NULL;
2267 key = ISC_LIST_NEXT(key, link)) {
2268 dns_ttl_t thisttl = dst_key_getttl(key->key);
2269 if (thisttl != 0 &&
2270 (shortest == 0 || thisttl < shortest)) {
2271 shortest = thisttl;
2272 }
2273 }
2274
2275 if (shortest != 0) {
2276 ttl = shortest;
2277 }
2278 }
2279
2280 /*
2281 * Second, scan the list of newly found keys looking for matches
2282 * with known keys, and update accordingly.
2283 */
2284 for (key1 = ISC_LIST_HEAD(*newkeys); key1 != NULL; key1 = next) {
2285 bool key_revoked = false;
2286 char keystr1[DST_KEY_FORMATSIZE];
2287 char keystr2[DST_KEY_FORMATSIZE];
2288
2289 next = ISC_LIST_NEXT(key1, link);
2290
2291 for (key2 = ISC_LIST_HEAD(*keys); key2 != NULL;
2292 key2 = ISC_LIST_NEXT(key2, link))
2293 {
2294 int f1 = dst_key_flags(key1->key);
2295 int f2 = dst_key_flags(key2->key);
2296 int nr1 = f1 & ~DNS_KEYFLAG_REVOKE;
2297 int nr2 = f2 & ~DNS_KEYFLAG_REVOKE;
2298 if (nr1 == nr2 &&
2299 dst_key_alg(key1->key) == dst_key_alg(key2->key) &&
2300 dst_key_pubcompare(key1->key, key2->key, true))
2301 {
2302 int r1, r2;
2303 r1 = dst_key_flags(key1->key) &
2304 DNS_KEYFLAG_REVOKE;
2305 r2 = dst_key_flags(key2->key) &
2306 DNS_KEYFLAG_REVOKE;
2307 key_revoked = (r1 != r2);
2308 break;
2309 }
2310 }
2311
2312 /* Printable version of key1 (the newly acquired key) */
2313 dst_key_format(key1->key, keystr1, sizeof(keystr1));
2314
2315 /* No match found in keys; add the new key. */
2316 if (key2 == NULL) {
2317 ISC_LIST_UNLINK(*newkeys, key1, link);
2318 ISC_LIST_APPEND(*keys, key1, link);
2319
2320 if (key1->source != dns_keysource_zoneapex &&
2321 (key1->hint_publish || key1->force_publish))
2322 {
2323 RETERR(publish_key(diff, key1, origin, ttl,
2324 mctx, report));
2325 isc_log_write(
2326 dns_lctx, DNS_LOGCATEGORY_DNSSEC,
2327 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
2328 "DNSKEY %s (%s) is now published",
2329 keystr1,
2330 key1->ksk ? (key1->zsk ? "CSK" : "KSK")
2331 : "ZSK");
2332 if (key1->hint_sign || key1->force_sign) {
2333 key1->first_sign = true;
2334 isc_log_write(
2335 dns_lctx,
2336 DNS_LOGCATEGORY_DNSSEC,
2337 DNS_LOGMODULE_DNSSEC,
2338 ISC_LOG_INFO,
2339 "DNSKEY %s (%s) is now "
2340 "active",
2341 keystr1,
2342 key1->ksk ? (key1->zsk ? "CSK"
2343 : "KSK")
2344 : "ZSK");
2345 }
2346 }
2347
2348 continue;
2349 }
2350
2351 /* Printable version of key2 (the old key, if any) */
2352 dst_key_format(key2->key, keystr2, sizeof(keystr2));
2353
2354 /* Copy key metadata. */
2355 dst_key_copy_metadata(key2->key, key1->key);
2356
2357 /* Match found: remove or update it as needed */
2358 if (key1->hint_remove) {
2359 RETERR(remove_key(diff, key2, origin, ttl, mctx,
2360 "expired", report));
2361 ISC_LIST_UNLINK(*keys, key2, link);
2362
2363 if (removed != NULL) {
2364 ISC_LIST_APPEND(*removed, key2, link);
2365 isc_log_write(
2366 dns_lctx, DNS_LOGCATEGORY_DNSSEC,
2367 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
2368 "DNSKEY %s (%s) is now deleted",
2369 keystr2,
2370 key2->ksk ? (key2->zsk ? "CSK" : "KSK")
2371 : "ZSK");
2372 } else {
2373 dns_dnsseckey_destroy(mctx, &key2);
2374 }
2375 } else if (key_revoked &&
2376 (dst_key_flags(key1->key) & DNS_KEYFLAG_REVOKE) != 0)
2377 {
2378 /*
2379 * A previously valid key has been revoked.
2380 * We need to remove the old version and pull
2381 * in the new one.
2382 */
2383 RETERR(remove_key(diff, key2, origin, ttl, mctx,
2384 "revoked", report));
2385 ISC_LIST_UNLINK(*keys, key2, link);
2386 if (removed != NULL) {
2387 ISC_LIST_APPEND(*removed, key2, link);
2388 isc_log_write(
2389 dns_lctx, DNS_LOGCATEGORY_DNSSEC,
2390 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
2391 "DNSKEY %s (%s) is now revoked; "
2392 "new ID is %05d",
2393 keystr2,
2394 key2->ksk ? (key2->zsk ? "CSK" : "KSK")
2395 : "ZSK",
2396 dst_key_id(key1->key));
2397 } else {
2398 dns_dnsseckey_destroy(mctx, &key2);
2399 }
2400
2401 RETERR(publish_key(diff, key1, origin, ttl, mctx,
2402 report));
2403 ISC_LIST_UNLINK(*newkeys, key1, link);
2404 ISC_LIST_APPEND(*keys, key1, link);
2405
2406 /*
2407 * XXX: The revoke flag is only defined for trust
2408 * anchors. Setting the flag on a non-KSK is legal,
2409 * but not defined in any RFC. It seems reasonable
2410 * to treat it the same as a KSK: keep it in the
2411 * zone, sign the DNSKEY set with it, but not
2412 * sign other records with it.
2413 */
2414 key1->ksk = true;
2415 continue;
2416 } else {
2417 if (!key2->is_active &&
2418 (key1->hint_sign || key1->force_sign)) {
2419 key2->first_sign = true;
2420 isc_log_write(
2421 dns_lctx, DNS_LOGCATEGORY_DNSSEC,
2422 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
2423 "DNSKEY %s (%s) is now active", keystr1,
2424 key1->ksk ? (key1->zsk ? "CSK" : "KSK")
2425 : "ZSK");
2426 } else if (key2->is_active && !key1->hint_sign &&
2427 !key1->force_sign) {
2428 isc_log_write(
2429 dns_lctx, DNS_LOGCATEGORY_DNSSEC,
2430 DNS_LOGMODULE_DNSSEC, ISC_LOG_INFO,
2431 "DNSKEY %s (%s) is now inactive",
2432 keystr1,
2433 key1->ksk ? (key1->zsk ? "CSK" : "KSK")
2434 : "ZSK");
2435 }
2436
2437 key2->hint_sign = key1->hint_sign;
2438 key2->hint_publish = key1->hint_publish;
2439 }
2440 }
2441
2442 /* Free any leftover keys in newkeys */
2443 while (!ISC_LIST_EMPTY(*newkeys)) {
2444 key1 = ISC_LIST_HEAD(*newkeys);
2445 ISC_LIST_UNLINK(*newkeys, key1, link);
2446 dns_dnsseckey_destroy(mctx, &key1);
2447 }
2448
2449 result = ISC_R_SUCCESS;
2450
2451 failure:
2452 return (result);
2453 }
2454
2455 isc_result_t
dns_dnssec_matchdskey(dns_name_t * name,dns_rdata_t * dsrdata,dns_rdataset_t * keyset,dns_rdata_t * keyrdata)2456 dns_dnssec_matchdskey(dns_name_t *name, dns_rdata_t *dsrdata,
2457 dns_rdataset_t *keyset, dns_rdata_t *keyrdata) {
2458 isc_result_t result;
2459 unsigned char buf[DNS_DS_BUFFERSIZE];
2460 dns_keytag_t keytag;
2461 dns_rdata_dnskey_t key;
2462 dns_rdata_ds_t ds;
2463 isc_region_t r;
2464
2465 result = dns_rdata_tostruct(dsrdata, &ds, NULL);
2466 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2467
2468 for (result = dns_rdataset_first(keyset); result == ISC_R_SUCCESS;
2469 result = dns_rdataset_next(keyset))
2470 {
2471 dns_rdata_t newdsrdata = DNS_RDATA_INIT;
2472
2473 dns_rdata_reset(keyrdata);
2474 dns_rdataset_current(keyset, keyrdata);
2475
2476 result = dns_rdata_tostruct(keyrdata, &key, NULL);
2477 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2478
2479 dns_rdata_toregion(keyrdata, &r);
2480 keytag = dst_region_computeid(&r);
2481
2482 if (ds.key_tag != keytag || ds.algorithm != key.algorithm) {
2483 continue;
2484 }
2485
2486 result = dns_ds_buildrdata(name, keyrdata, ds.digest_type, buf,
2487 &newdsrdata);
2488 if (result != ISC_R_SUCCESS) {
2489 continue;
2490 }
2491
2492 if (dns_rdata_compare(dsrdata, &newdsrdata) == 0) {
2493 break;
2494 }
2495 }
2496 if (result == ISC_R_NOMORE) {
2497 result = ISC_R_NOTFOUND;
2498 }
2499
2500 return (result);
2501 }
2502