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