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