2 * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
28 #include <isc/buffer.h>
31 #include <isc/serial.h>
32 #include <isc/string.h>
37 #include <dns/dnssec.h>
38 #include <dns/fixedname.h>
39 #include <dns/keyvalues.h>
41 #include <dns/message.h>
42 #include <dns/rdata.h>
43 #include <dns/rdatalist.h>
44 #include <dns/rdataset.h>
45 #include <dns/rdatastruct.h>
46 #include <dns/result.h>
47 #include <dns/stats.h>
48 #include <dns/tsig.h> /* for DNS_TSIG_FUDGE */
50 #include <dst/result.h>
52 LIBDNS_EXTERNAL_DATA isc_stats_t *dns_dnssec_stats;
54 #define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR)
56 #define RETERR(x) do { \
58 if (result != ISC_R_SUCCESS) \
67 digest_callback(void *arg, isc_region_t *data);
70 rdata_compare_wrapper(const void *rdata1, const void *rdata2);
73 rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx,
74 dns_rdata_t **rdata, int *nrdata);
77 digest_callback(void *arg, isc_region_t *data) {
78 dst_context_t *ctx = arg;
80 return (dst_context_adddata(ctx, data));
84 inc_stat(isc_statscounter_t counter) {
85 if (dns_dnssec_stats != NULL)
86 isc_stats_increment(dns_dnssec_stats, counter);
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));
99 * Sort the rdataset into an array.
102 rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx,
103 dns_rdata_t **rdata, int *nrdata)
108 dns_rdataset_t rdataset;
110 n = dns_rdataset_count(set);
112 data = isc_mem_get(mctx, n * sizeof(dns_rdata_t));
114 return (ISC_R_NOMEMORY);
116 dns_rdataset_init(&rdataset);
117 dns_rdataset_clone(set, &rdataset);
118 ret = dns_rdataset_first(&rdataset);
119 if (ret != ISC_R_SUCCESS) {
120 dns_rdataset_disassociate(&rdataset);
121 isc_mem_put(mctx, data, n * sizeof(dns_rdata_t));
126 * Put them in the array.
129 dns_rdata_init(&data[i]);
130 dns_rdataset_current(&rdataset, &data[i++]);
131 } while (dns_rdataset_next(&rdataset) == ISC_R_SUCCESS);
136 qsort(data, n, sizeof(dns_rdata_t), rdata_compare_wrapper);
139 dns_rdataset_disassociate(&rdataset);
140 return (ISC_R_SUCCESS);
144 dns_dnssec_keyfromrdata(dns_name_t *name, dns_rdata_t *rdata, isc_mem_t *mctx,
150 INSIST(name != NULL);
151 INSIST(rdata != NULL);
152 INSIST(mctx != NULL);
154 INSIST(*key == NULL);
155 REQUIRE(rdata->type == dns_rdatatype_key ||
156 rdata->type == dns_rdatatype_dnskey);
158 dns_rdata_toregion(rdata, &r);
159 isc_buffer_init(&b, r.base, r.length);
160 isc_buffer_add(&b, r.length);
161 return (dst_key_fromdns(name, rdata->rdclass, &b, mctx, key));
165 digest_sig(dst_context_t *ctx, isc_boolean_t downcase, dns_rdata_t *sigrdata,
166 dns_rdata_rrsig_t *rrsig)
170 dns_fixedname_t fname;
172 dns_rdata_toregion(sigrdata, &r);
173 INSIST(r.length >= 19);
176 ret = dst_context_adddata(ctx, &r);
177 if (ret != ISC_R_SUCCESS)
180 dns_fixedname_init(&fname);
182 RUNTIME_CHECK(dns_name_downcase(&rrsig->signer,
183 dns_fixedname_name(&fname),
184 NULL) == ISC_R_SUCCESS);
185 dns_name_toregion(dns_fixedname_name(&fname), &r);
187 dns_name_toregion(&rrsig->signer, &r);
189 return (dst_context_adddata(ctx, &r));
193 dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
194 isc_stdtime_t *inception, isc_stdtime_t *expire,
195 isc_mem_t *mctx, isc_buffer_t *buffer, dns_rdata_t *sigrdata)
197 dns_rdata_rrsig_t sig;
198 dns_rdata_t tmpsigrdata;
201 isc_buffer_t sigbuf, envbuf;
203 dst_context_t *ctx = NULL;
205 isc_buffer_t *databuf = NULL;
208 unsigned int sigsize;
209 dns_fixedname_t fnewname;
210 dns_fixedname_t fsigner;
212 REQUIRE(name != NULL);
213 REQUIRE(dns_name_countlabels(name) <= 255);
214 REQUIRE(set != NULL);
215 REQUIRE(key != NULL);
216 REQUIRE(inception != NULL);
217 REQUIRE(expire != NULL);
218 REQUIRE(mctx != NULL);
219 REQUIRE(sigrdata != NULL);
221 if (*inception >= *expire)
222 return (DNS_R_INVALIDTIME);
225 * Is the key allowed to sign data?
227 flags = dst_key_flags(key);
228 if (flags & DNS_KEYTYPE_NOAUTH)
229 return (DNS_R_KEYUNAUTHORIZED);
230 if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE)
231 return (DNS_R_KEYUNAUTHORIZED);
234 sig.common.rdclass = set->rdclass;
235 sig.common.rdtype = dns_rdatatype_rrsig;
236 ISC_LINK_INIT(&sig.common, link);
241 dns_name_init(&sig.signer, NULL);
242 dns_fixedname_init(&fsigner);
243 RUNTIME_CHECK(dns_name_downcase(dst_key_name(key),
244 dns_fixedname_name(&fsigner), NULL) == ISC_R_SUCCESS);
245 dns_name_clone(dns_fixedname_name(&fsigner), &sig.signer);
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))
252 sig.originalttl = set->ttl;
253 sig.timesigned = *inception;
254 sig.timeexpire = *expire;
255 sig.keyid = dst_key_id(key);
256 ret = dst_key_sigsize(key, &sigsize);
257 if (ret != ISC_R_SUCCESS)
259 sig.siglen = sigsize;
261 * The actual contents of sig.signature are not important yet, since
262 * they're not used in digest_sig().
264 sig.signature = isc_mem_get(mctx, sig.siglen);
265 if (sig.signature == NULL)
266 return (ISC_R_NOMEMORY);
268 ret = isc_buffer_allocate(mctx, &databuf, sigsize + 256 + 18);
269 if (ret != ISC_R_SUCCESS)
270 goto cleanup_signature;
272 dns_rdata_init(&tmpsigrdata);
273 ret = dns_rdata_fromstruct(&tmpsigrdata, sig.common.rdclass,
274 sig.common.rdtype, &sig, databuf);
275 if (ret != ISC_R_SUCCESS)
276 goto cleanup_databuf;
278 ret = dst_context_create2(key, mctx, DNS_LOGCATEGORY_DNSSEC, &ctx);
279 if (ret != ISC_R_SUCCESS)
280 goto cleanup_databuf;
283 * Digest the SIG rdata.
285 ret = digest_sig(ctx, ISC_FALSE, &tmpsigrdata, &sig);
286 if (ret != ISC_R_SUCCESS)
287 goto cleanup_context;
289 dns_fixedname_init(&fnewname);
290 RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname),
291 NULL) == ISC_R_SUCCESS);
292 dns_name_toregion(dns_fixedname_name(&fnewname), &r);
295 * Create an envelope for each rdata: <name|type|class|ttl>.
297 isc_buffer_init(&envbuf, data, sizeof(data));
298 memmove(data, r.base, r.length);
299 isc_buffer_add(&envbuf, r.length);
300 isc_buffer_putuint16(&envbuf, set->type);
301 isc_buffer_putuint16(&envbuf, set->rdclass);
302 isc_buffer_putuint32(&envbuf, set->ttl);
304 ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas);
305 if (ret != ISC_R_SUCCESS)
306 goto cleanup_context;
307 isc_buffer_usedregion(&envbuf, &r);
309 for (i = 0; i < nrdatas; i++) {
317 if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i-1]) == 0)
321 * Digest the envelope.
323 ret = dst_context_adddata(ctx, &r);
324 if (ret != ISC_R_SUCCESS)
328 * Digest the length of the rdata.
330 isc_buffer_init(&lenbuf, &len, sizeof(len));
331 INSIST(rdatas[i].length < 65536);
332 isc_buffer_putuint16(&lenbuf, (isc_uint16_t)rdatas[i].length);
333 isc_buffer_usedregion(&lenbuf, &lenr);
334 ret = dst_context_adddata(ctx, &lenr);
335 if (ret != ISC_R_SUCCESS)
341 ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx);
342 if (ret != ISC_R_SUCCESS)
346 isc_buffer_init(&sigbuf, sig.signature, sig.siglen);
347 ret = dst_context_sign(ctx, &sigbuf);
348 if (ret != ISC_R_SUCCESS)
350 isc_buffer_usedregion(&sigbuf, &r);
351 if (r.length != sig.siglen) {
356 ret = dns_rdata_fromstruct(sigrdata, sig.common.rdclass,
357 sig.common.rdtype, &sig, buffer);
360 isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t));
362 dst_context_destroy(&ctx);
364 isc_buffer_free(&databuf);
366 isc_mem_put(mctx, sig.signature, sig.siglen);
372 dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
373 isc_boolean_t ignoretime, isc_mem_t *mctx,
374 dns_rdata_t *sigrdata, dns_name_t *wild)
376 return (dns_dnssec_verify3(name, set, key, ignoretime, 0, mctx,
381 dns_dnssec_verify3(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
382 isc_boolean_t ignoretime, unsigned int maxbits,
383 isc_mem_t *mctx, dns_rdata_t *sigrdata, dns_name_t *wild)
385 dns_rdata_rrsig_t sig;
386 dns_fixedname_t fnewname;
393 unsigned char data[300];
394 dst_context_t *ctx = NULL;
397 isc_boolean_t downcase = ISC_FALSE;
399 REQUIRE(name != NULL);
400 REQUIRE(set != NULL);
401 REQUIRE(key != NULL);
402 REQUIRE(mctx != NULL);
403 REQUIRE(sigrdata != NULL && sigrdata->type == dns_rdatatype_rrsig);
405 ret = dns_rdata_tostruct(sigrdata, &sig, NULL);
406 if (ret != ISC_R_SUCCESS)
409 if (set->type != sig.covered)
410 return (DNS_R_SIGINVALID);
412 if (isc_serial_lt(sig.timeexpire, sig.timesigned)) {
413 inc_stat(dns_dnssecstats_fail);
414 return (DNS_R_SIGINVALID);
418 isc_stdtime_get(&now);
421 * Is SIG temporally valid?
423 if (isc_serial_lt((isc_uint32_t)now, sig.timesigned)) {
424 inc_stat(dns_dnssecstats_fail);
425 return (DNS_R_SIGFUTURE);
426 } else if (isc_serial_lt(sig.timeexpire, (isc_uint32_t)now)) {
427 inc_stat(dns_dnssecstats_fail);
428 return (DNS_R_SIGEXPIRED);
433 * NS, SOA and DNSSKEY records are signed by their owner.
434 * DS records are signed by the parent.
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);
445 case dns_rdatatype_ds:
446 if (dns_name_equal(name, &sig.signer)) {
447 inc_stat(dns_dnssecstats_fail);
448 return (DNS_R_SIGINVALID);
452 if (!dns_name_issubdomain(name, &sig.signer)) {
453 inc_stat(dns_dnssecstats_fail);
454 return (DNS_R_SIGINVALID);
460 * Is the key allowed to sign data?
462 flags = dst_key_flags(key);
463 if (flags & DNS_KEYTYPE_NOAUTH) {
464 inc_stat(dns_dnssecstats_fail);
465 return (DNS_R_KEYUNAUTHORIZED);
467 if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE) {
468 inc_stat(dns_dnssecstats_fail);
469 return (DNS_R_KEYUNAUTHORIZED);
473 ret = dst_context_create2(key, mctx, DNS_LOGCATEGORY_DNSSEC, &ctx);
474 if (ret != ISC_R_SUCCESS)
478 * Digest the SIG rdata (not including the signature).
480 ret = digest_sig(ctx, downcase, sigrdata, &sig);
481 if (ret != ISC_R_SUCCESS)
482 goto cleanup_context;
485 * If the name is an expanded wildcard, use the wildcard name.
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));
495 dns_name_toregion(dns_fixedname_name(&fnewname), &r);
498 * Create an envelope for each rdata: <name|type|class|ttl>.
500 isc_buffer_init(&envbuf, data, sizeof(data));
501 if (labels - sig.labels > 0) {
502 isc_buffer_putuint8(&envbuf, 1);
503 isc_buffer_putuint8(&envbuf, '*');
504 memmove(data + 2, r.base, r.length);
507 memmove(data, r.base, r.length);
508 isc_buffer_add(&envbuf, r.length);
509 isc_buffer_putuint16(&envbuf, set->type);
510 isc_buffer_putuint16(&envbuf, set->rdclass);
511 isc_buffer_putuint32(&envbuf, sig.originalttl);
513 ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas);
514 if (ret != ISC_R_SUCCESS)
515 goto cleanup_context;
517 isc_buffer_usedregion(&envbuf, &r);
519 for (i = 0; i < nrdatas; i++) {
527 if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i-1]) == 0)
531 * Digest the envelope.
533 ret = dst_context_adddata(ctx, &r);
534 if (ret != ISC_R_SUCCESS)
538 * Digest the rdata length.
540 isc_buffer_init(&lenbuf, &len, sizeof(len));
541 INSIST(rdatas[i].length < 65536);
542 isc_buffer_putuint16(&lenbuf, (isc_uint16_t)rdatas[i].length);
543 isc_buffer_usedregion(&lenbuf, &lenr);
548 ret = dst_context_adddata(ctx, &lenr);
549 if (ret != ISC_R_SUCCESS)
551 ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx);
552 if (ret != ISC_R_SUCCESS)
556 r.base = sig.signature;
557 r.length = sig.siglen;
558 ret = dst_context_verify2(ctx, maxbits, &r);
559 if (ret == ISC_R_SUCCESS && downcase) {
560 char namebuf[DNS_NAME_FORMATSIZE];
561 dns_name_format(&sig.signer, namebuf, sizeof(namebuf));
562 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
563 DNS_LOGMODULE_DNSSEC, ISC_LOG_DEBUG(1),
564 "successfully validated after lower casing "
565 "signer '%s'", namebuf);
566 inc_stat(dns_dnssecstats_downcase);
567 } else if (ret == ISC_R_SUCCESS)
568 inc_stat(dns_dnssecstats_asis);
571 isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t));
573 dst_context_destroy(&ctx);
574 if (ret == DST_R_VERIFYFAILURE && !downcase) {
579 dns_rdata_freestruct(&sig);
581 if (ret == DST_R_VERIFYFAILURE)
582 ret = DNS_R_SIGINVALID;
584 if (ret != ISC_R_SUCCESS)
585 inc_stat(dns_dnssecstats_fail);
587 if (ret == ISC_R_SUCCESS && labels - sig.labels > 0) {
589 RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname,
590 dns_fixedname_name(&fnewname),
591 wild, NULL) == ISC_R_SUCCESS);
592 inc_stat(dns_dnssecstats_wildcard);
593 ret = DNS_R_FROMWILDCARD;
599 dns_dnssec_verify(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
600 isc_boolean_t ignoretime, isc_mem_t *mctx,
601 dns_rdata_t *sigrdata)
605 result = dns_dnssec_verify2(name, set, key, ignoretime, mctx,
607 if (result == DNS_R_FROMWILDCARD)
608 result = ISC_R_SUCCESS;
613 dns_dnssec_keyactive(dst_key_t *key, isc_stdtime_t now) {
615 isc_stdtime_t publish, active, revoke, inactive, delete;
616 isc_boolean_t pubset = ISC_FALSE, actset = ISC_FALSE;
617 isc_boolean_t revset = ISC_FALSE, inactset = ISC_FALSE;
618 isc_boolean_t delset = ISC_FALSE;
621 /* Is this an old-style key? */
622 result = dst_key_getprivateformat(key, &major, &minor);
623 RUNTIME_CHECK(result == ISC_R_SUCCESS);
626 * Smart signing started with key format 1.3; prior to that, all
627 * keys are assumed active
629 if (major == 1 && minor <= 2)
632 result = dst_key_gettime(key, DST_TIME_PUBLISH, &publish);
633 if (result == ISC_R_SUCCESS)
636 result = dst_key_gettime(key, DST_TIME_ACTIVATE, &active);
637 if (result == ISC_R_SUCCESS)
640 result = dst_key_gettime(key, DST_TIME_REVOKE, &revoke);
641 if (result == ISC_R_SUCCESS)
644 result = dst_key_gettime(key, DST_TIME_INACTIVE, &inactive);
645 if (result == ISC_R_SUCCESS)
648 result = dst_key_gettime(key, DST_TIME_DELETE, &delete);
649 if (result == ISC_R_SUCCESS)
652 if ((inactset && inactive <= now) || (delset && delete <= now))
655 if (revset && revoke <= now && pubset && publish <= now)
658 if (actset && active <= now)
664 #define is_zone_key(key) ((dst_key_flags(key) & DNS_KEYFLAG_OWNERMASK) \
665 == DNS_KEYOWNER_ZONE)
668 dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver,
669 dns_dbnode_t *node, dns_name_t *name,
670 const char *directory, isc_mem_t *mctx,
671 unsigned int maxkeys, dst_key_t **keys,
674 dns_rdataset_t rdataset;
675 dns_rdata_t rdata = DNS_RDATA_INIT;
677 dst_key_t *pubkey = NULL;
678 unsigned int count = 0;
681 REQUIRE(nkeys != NULL);
682 REQUIRE(keys != NULL);
684 isc_stdtime_get(&now);
687 memset(keys, 0, sizeof(*keys) * maxkeys);
688 dns_rdataset_init(&rdataset);
689 RETERR(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0,
691 RETERR(dns_rdataset_first(&rdataset));
692 while (result == ISC_R_SUCCESS && count < maxkeys) {
694 dns_rdataset_current(&rdataset, &rdata);
695 RETERR(dns_dnssec_keyfromrdata(name, &rdata, mctx, &pubkey));
696 dst_key_setttl(pubkey, rdataset.ttl);
698 if (!is_zone_key(pubkey) ||
699 (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0)
701 /* Corrupted .key file? */
702 if (!dns_name_equal(name, dst_key_name(pubkey)))
705 result = dst_key_fromfile(dst_key_name(pubkey),
708 DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
713 * If the key was revoked and the private file
714 * doesn't exist, maybe it was revoked internally
715 * by named. Try loading the unrevoked version.
717 if (result == ISC_R_FILENOTFOUND) {
719 flags = dst_key_flags(pubkey);
720 if ((flags & DNS_KEYFLAG_REVOKE) != 0) {
721 dst_key_setflags(pubkey,
722 flags & ~DNS_KEYFLAG_REVOKE);
723 result = dst_key_fromfile(dst_key_name(pubkey),
730 if (result == ISC_R_SUCCESS &&
731 dst_key_pubcompare(pubkey, keys[count],
733 dst_key_setflags(keys[count], flags);
735 dst_key_setflags(pubkey, flags);
739 if (result != ISC_R_SUCCESS) {
740 char keybuf[DNS_NAME_FORMATSIZE];
741 char algbuf[DNS_SECALG_FORMATSIZE];
742 dns_name_format(dst_key_name(pubkey), keybuf,
744 dns_secalg_format(dst_key_alg(pubkey), algbuf,
746 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
747 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
748 "dns_dnssec_findzonekeys2: error "
749 "reading private key file %s/%s/%d: %s",
750 keybuf, algbuf, dst_key_id(pubkey),
751 isc_result_totext(result));
754 if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) {
755 keys[count] = pubkey;
761 if (result != ISC_R_SUCCESS)
765 * If a key is marked inactive, skip it
767 if (!dns_dnssec_keyactive(keys[count], now)) {
768 dst_key_setinactive(pubkey, ISC_TRUE);
769 dst_key_free(&keys[count]);
770 keys[count] = pubkey;
777 * Whatever the key's default TTL may have
778 * been, the rdataset TTL takes priority.
780 dst_key_setttl(keys[count], rdataset.ttl);
782 if ((dst_key_flags(keys[count]) & DNS_KEYTYPE_NOAUTH) != 0) {
783 /* We should never get here. */
784 dst_key_free(&keys[count]);
790 dst_key_free(&pubkey);
791 dns_rdata_reset(&rdata);
792 result = dns_rdataset_next(&rdataset);
794 if (result != ISC_R_NOMORE)
797 result = ISC_R_NOTFOUND;
799 result = ISC_R_SUCCESS;
802 if (dns_rdataset_isassociated(&rdataset))
803 dns_rdataset_disassociate(&rdataset);
805 dst_key_free(&pubkey);
806 if (result != ISC_R_SUCCESS)
808 dst_key_free(&keys[--count]);
814 dns_dnssec_findzonekeys(dns_db_t *db, dns_dbversion_t *ver,
815 dns_dbnode_t *node, dns_name_t *name, isc_mem_t *mctx,
816 unsigned int maxkeys, dst_key_t **keys,
819 return (dns_dnssec_findzonekeys2(db, ver, node, name, NULL, mctx,
820 maxkeys, keys, nkeys));
824 dns_dnssec_signmessage(dns_message_t *msg, dst_key_t *key) {
825 dns_rdata_sig_t sig; /* SIG(0) */
826 unsigned char data[512];
827 unsigned char header[DNS_MESSAGE_HEADERLEN];
828 isc_buffer_t headerbuf, databuf, sigbuf;
829 unsigned int sigsize;
830 isc_buffer_t *dynbuf = NULL;
832 dns_rdatalist_t *datalist;
833 dns_rdataset_t *dataset;
836 dst_context_t *ctx = NULL;
839 isc_boolean_t signeedsfree = ISC_TRUE;
841 REQUIRE(msg != NULL);
842 REQUIRE(key != NULL);
844 if (is_response(msg))
845 REQUIRE(msg->query.base != NULL);
849 memset(&sig, 0, sizeof(sig));
852 sig.common.rdclass = dns_rdataclass_any;
853 sig.common.rdtype = dns_rdatatype_sig; /* SIG(0) */
854 ISC_LINK_INIT(&sig.common, link);
857 sig.algorithm = dst_key_alg(key);
858 sig.labels = 0; /* the root name */
861 isc_stdtime_get(&now);
862 sig.timesigned = now - DNS_TSIG_FUDGE;
863 sig.timeexpire = now + DNS_TSIG_FUDGE;
865 sig.keyid = dst_key_id(key);
867 dns_name_init(&sig.signer, NULL);
868 dns_name_clone(dst_key_name(key), &sig.signer);
871 sig.signature = NULL;
873 isc_buffer_init(&databuf, data, sizeof(data));
875 RETERR(dst_context_create2(key, mctx, DNS_LOGCATEGORY_DNSSEC, &ctx));
878 * Digest the fields of the SIG - we can cheat and use
879 * dns_rdata_fromstruct. Since siglen is 0, the digested data
880 * is identical to dns format.
882 RETERR(dns_rdata_fromstruct(NULL, dns_rdataclass_any,
883 dns_rdatatype_sig /* SIG(0) */,
885 isc_buffer_usedregion(&databuf, &r);
886 RETERR(dst_context_adddata(ctx, &r));
889 * If this is a response, digest the query.
891 if (is_response(msg))
892 RETERR(dst_context_adddata(ctx, &msg->query));
897 isc_buffer_init(&headerbuf, header, sizeof(header));
898 dns_message_renderheader(msg, &headerbuf);
899 isc_buffer_usedregion(&headerbuf, &r);
900 RETERR(dst_context_adddata(ctx, &r));
903 * Digest the remainder of the message.
905 isc_buffer_usedregion(msg->buffer, &r);
906 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
907 RETERR(dst_context_adddata(ctx, &r));
909 RETERR(dst_key_sigsize(key, &sigsize));
910 sig.siglen = sigsize;
911 sig.signature = (unsigned char *) isc_mem_get(mctx, sig.siglen);
912 if (sig.signature == NULL) {
913 result = ISC_R_NOMEMORY;
917 isc_buffer_init(&sigbuf, sig.signature, sig.siglen);
918 RETERR(dst_context_sign(ctx, &sigbuf));
919 dst_context_destroy(&ctx);
922 RETERR(dns_message_gettemprdata(msg, &rdata));
923 RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 1024));
924 RETERR(dns_rdata_fromstruct(rdata, dns_rdataclass_any,
925 dns_rdatatype_sig /* SIG(0) */,
928 isc_mem_put(mctx, sig.signature, sig.siglen);
929 signeedsfree = ISC_FALSE;
931 dns_message_takebuffer(msg, &dynbuf);
934 RETERR(dns_message_gettemprdatalist(msg, &datalist));
935 datalist->rdclass = dns_rdataclass_any;
936 datalist->type = dns_rdatatype_sig; /* SIG(0) */
937 datalist->covers = 0;
939 ISC_LIST_INIT(datalist->rdata);
940 ISC_LIST_APPEND(datalist->rdata, rdata, link);
942 RETERR(dns_message_gettemprdataset(msg, &dataset));
943 dns_rdataset_init(dataset);
944 RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset) == ISC_R_SUCCESS);
947 return (ISC_R_SUCCESS);
951 isc_buffer_free(&dynbuf);
953 isc_mem_put(mctx, sig.signature, sig.siglen);
955 dst_context_destroy(&ctx);
961 dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg,
964 dns_rdata_sig_t sig; /* SIG(0) */
965 unsigned char header[DNS_MESSAGE_HEADERLEN];
966 dns_rdata_t rdata = DNS_RDATA_INIT;
967 isc_region_t r, source_r, sig_r, header_r;
969 dst_context_t *ctx = NULL;
972 isc_uint16_t addcount;
973 isc_boolean_t signeedsfree = ISC_FALSE;
975 REQUIRE(source != NULL);
976 REQUIRE(msg != NULL);
977 REQUIRE(key != NULL);
981 msg->verify_attempted = 1;
983 if (is_response(msg)) {
984 if (msg->query.base == NULL)
985 return (DNS_R_UNEXPECTEDTSIG);
988 isc_buffer_usedregion(source, &source_r);
990 RETERR(dns_rdataset_first(msg->sig0));
991 dns_rdataset_current(msg->sig0, &rdata);
993 RETERR(dns_rdata_tostruct(&rdata, &sig, NULL));
994 signeedsfree = ISC_TRUE;
996 if (sig.labels != 0) {
997 result = DNS_R_SIGINVALID;
1001 if (isc_serial_lt(sig.timeexpire, sig.timesigned)) {
1002 result = DNS_R_SIGINVALID;
1003 msg->sig0status = dns_tsigerror_badtime;
1007 isc_stdtime_get(&now);
1008 if (isc_serial_lt((isc_uint32_t)now, sig.timesigned)) {
1009 result = DNS_R_SIGFUTURE;
1010 msg->sig0status = dns_tsigerror_badtime;
1013 else if (isc_serial_lt(sig.timeexpire, (isc_uint32_t)now)) {
1014 result = DNS_R_SIGEXPIRED;
1015 msg->sig0status = dns_tsigerror_badtime;
1019 if (!dns_name_equal(dst_key_name(key), &sig.signer)) {
1020 result = DNS_R_SIGINVALID;
1021 msg->sig0status = dns_tsigerror_badkey;
1025 RETERR(dst_context_create2(key, mctx, DNS_LOGCATEGORY_DNSSEC, &ctx));
1028 * Digest the SIG(0) record, except for the signature.
1030 dns_rdata_toregion(&rdata, &r);
1031 r.length -= sig.siglen;
1032 RETERR(dst_context_adddata(ctx, &r));
1035 * If this is a response, digest the query.
1037 if (is_response(msg))
1038 RETERR(dst_context_adddata(ctx, &msg->query));
1041 * Extract the header.
1043 memmove(header, source_r.base, DNS_MESSAGE_HEADERLEN);
1046 * Decrement the additional field counter.
1048 memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
1049 addcount = htons((isc_uint16_t)(ntohs(addcount) - 1));
1050 memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
1053 * Digest the modified header.
1055 header_r.base = (unsigned char *) header;
1056 header_r.length = DNS_MESSAGE_HEADERLEN;
1057 RETERR(dst_context_adddata(ctx, &header_r));
1060 * Digest all non-SIG(0) records.
1062 r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
1063 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
1064 RETERR(dst_context_adddata(ctx, &r));
1066 sig_r.base = sig.signature;
1067 sig_r.length = sig.siglen;
1068 result = dst_context_verify(ctx, &sig_r);
1069 if (result != ISC_R_SUCCESS) {
1070 msg->sig0status = dns_tsigerror_badsig;
1074 msg->verified_sig = 1;
1076 dst_context_destroy(&ctx);
1077 dns_rdata_freestruct(&sig);
1079 return (ISC_R_SUCCESS);
1083 dns_rdata_freestruct(&sig);
1085 dst_context_destroy(&ctx);
1091 * Does this key ('rdata') self sign the rrset ('rdataset')?
1094 dns_dnssec_selfsigns(dns_rdata_t *rdata, dns_name_t *name,
1095 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
1096 isc_boolean_t ignoretime, isc_mem_t *mctx)
1098 INSIST(rdataset->type == dns_rdatatype_key ||
1099 rdataset->type == dns_rdatatype_dnskey);
1100 if (rdataset->type == dns_rdatatype_key) {
1101 INSIST(sigrdataset->type == dns_rdatatype_sig);
1102 INSIST(sigrdataset->covers == dns_rdatatype_key);
1104 INSIST(sigrdataset->type == dns_rdatatype_rrsig);
1105 INSIST(sigrdataset->covers == dns_rdatatype_dnskey);
1108 return (dns_dnssec_signs(rdata, name, rdataset, sigrdataset,
1114 dns_dnssec_signs(dns_rdata_t *rdata, dns_name_t *name,
1115 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
1116 isc_boolean_t ignoretime, isc_mem_t *mctx)
1118 dst_key_t *dstkey = NULL;
1119 dns_keytag_t keytag;
1120 dns_rdata_dnskey_t key;
1121 dns_rdata_rrsig_t sig;
1122 dns_rdata_t sigrdata = DNS_RDATA_INIT;
1123 isc_result_t result;
1125 INSIST(sigrdataset->type == dns_rdatatype_rrsig);
1126 if (sigrdataset->covers != rdataset->type)
1129 result = dns_dnssec_keyfromrdata(name, rdata, mctx, &dstkey);
1130 if (result != ISC_R_SUCCESS)
1132 result = dns_rdata_tostruct(rdata, &key, NULL);
1133 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1135 keytag = dst_key_id(dstkey);
1136 for (result = dns_rdataset_first(sigrdataset);
1137 result == ISC_R_SUCCESS;
1138 result = dns_rdataset_next(sigrdataset))
1140 dns_rdata_reset(&sigrdata);
1141 dns_rdataset_current(sigrdataset, &sigrdata);
1142 result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
1143 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1145 if (sig.algorithm == key.algorithm &&
1146 sig.keyid == keytag) {
1147 result = dns_dnssec_verify2(name, rdataset, dstkey,
1150 if (result == ISC_R_SUCCESS) {
1151 dst_key_free(&dstkey);
1156 dst_key_free(&dstkey);
1161 dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey,
1162 dns_dnsseckey_t **dkp)
1164 isc_result_t result;
1165 dns_dnsseckey_t *dk;
1168 REQUIRE(dkp != NULL && *dkp == NULL);
1169 dk = isc_mem_get(mctx, sizeof(dns_dnsseckey_t));
1171 return (ISC_R_NOMEMORY);
1175 dk->force_publish = ISC_FALSE;
1176 dk->force_sign = ISC_FALSE;
1177 dk->hint_publish = ISC_FALSE;
1178 dk->hint_sign = ISC_FALSE;
1179 dk->hint_remove = ISC_FALSE;
1180 dk->first_sign = ISC_FALSE;
1181 dk->is_active = ISC_FALSE;
1183 dk->source = dns_keysource_unknown;
1187 dk->ksk = ISC_TF((dst_key_flags(dk->key) & DNS_KEYFLAG_KSK) != 0);
1189 /* Is this an old-style key? */
1190 result = dst_key_getprivateformat(dk->key, &major, &minor);
1191 INSIST(result == ISC_R_SUCCESS);
1193 /* Smart signing started with key format 1.3 */
1194 dk->legacy = ISC_TF(major == 1 && minor <= 2);
1196 ISC_LINK_INIT(dk, link);
1198 return (ISC_R_SUCCESS);
1202 dns_dnsseckey_destroy(isc_mem_t *mctx, dns_dnsseckey_t **dkp) {
1203 dns_dnsseckey_t *dk;
1205 REQUIRE(dkp != NULL && *dkp != NULL);
1207 if (dk->key != NULL)
1208 dst_key_free(&dk->key);
1209 isc_mem_put(mctx, dk, sizeof(dns_dnsseckey_t));
1214 get_hints(dns_dnsseckey_t *key, isc_stdtime_t now) {
1215 isc_result_t result;
1216 isc_stdtime_t publish, active, revoke, inactive, delete;
1217 isc_boolean_t pubset = ISC_FALSE, actset = ISC_FALSE;
1218 isc_boolean_t revset = ISC_FALSE, inactset = ISC_FALSE;
1219 isc_boolean_t delset = ISC_FALSE;
1221 REQUIRE(key != NULL && key->key != NULL);
1223 result = dst_key_gettime(key->key, DST_TIME_PUBLISH, &publish);
1224 if (result == ISC_R_SUCCESS)
1227 result = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active);
1228 if (result == ISC_R_SUCCESS)
1231 result = dst_key_gettime(key->key, DST_TIME_REVOKE, &revoke);
1232 if (result == ISC_R_SUCCESS)
1235 result = dst_key_gettime(key->key, DST_TIME_INACTIVE, &inactive);
1236 if (result == ISC_R_SUCCESS)
1237 inactset = ISC_TRUE;
1239 result = dst_key_gettime(key->key, DST_TIME_DELETE, &delete);
1240 if (result == ISC_R_SUCCESS)
1243 /* Metadata says publish (but possibly not activate) */
1244 if (pubset && publish <= now)
1245 key->hint_publish = ISC_TRUE;
1247 /* Metadata says activate (so we must also publish) */
1248 if (actset && active <= now) {
1249 key->hint_sign = ISC_TRUE;
1250 key->hint_publish = ISC_TRUE;
1254 * Activation date is set (maybe in the future), but
1255 * publication date isn't. Most likely the user wants to
1256 * publish now and activate later.
1258 if (actset && !pubset)
1259 key->hint_publish = ISC_TRUE;
1262 * If activation date is in the future, make note of how far off
1264 if (key->hint_publish && actset && active > now) {
1265 key->prepublish = active - now;
1269 * Key has been marked inactive: we can continue publishing,
1272 if (key->hint_publish && inactset && inactive <= now) {
1273 key->hint_sign = ISC_FALSE;
1277 * Metadata says revoke. If the key is published,
1278 * we *have to* sign with it per RFC5011--even if it was
1279 * not active before.
1281 * If it hasn't already been done, we should also revoke it now.
1283 if (key->hint_publish && (revset && revoke <= now)) {
1285 key->hint_sign = ISC_TRUE;
1286 flags = dst_key_flags(key->key);
1287 if ((flags & DNS_KEYFLAG_REVOKE) == 0) {
1288 flags |= DNS_KEYFLAG_REVOKE;
1289 dst_key_setflags(key->key, flags);
1294 * Metadata says delete, so don't publish this key or sign with it.
1296 if (delset && delete <= now) {
1297 key->hint_publish = ISC_FALSE;
1298 key->hint_sign = ISC_FALSE;
1299 key->hint_remove = ISC_TRUE;
1304 * Get a list of DNSSEC keys from the key repository
1307 dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory,
1308 isc_mem_t *mctx, dns_dnsseckeylist_t *keylist)
1310 isc_result_t result = ISC_R_SUCCESS;
1311 isc_boolean_t dir_open = ISC_FALSE;
1312 dns_dnsseckeylist_t list;
1314 dns_dnsseckey_t *key = NULL;
1315 dst_key_t *dstkey = NULL;
1316 char namebuf[DNS_NAME_FORMATSIZE];
1318 unsigned int len, i;
1321 REQUIRE(keylist != NULL);
1322 ISC_LIST_INIT(list);
1325 isc_buffer_init(&b, namebuf, sizeof(namebuf) - 1);
1326 RETERR(dns_name_tofilenametext(origin, ISC_FALSE, &b));
1327 len = isc_buffer_usedlength(&b);
1328 namebuf[len] = '\0';
1330 if (directory == NULL)
1332 RETERR(isc_dir_open(&dir, directory));
1333 dir_open = ISC_TRUE;
1335 isc_stdtime_get(&now);
1337 while (isc_dir_read(&dir) == ISC_R_SUCCESS) {
1338 if (dir.entry.name[0] != 'K' ||
1339 dir.entry.length < len + 1 ||
1340 dir.entry.name[len + 1] != '+' ||
1341 strncasecmp(dir.entry.name + 1, namebuf, len) != 0)
1344 for (i = len + 1 + 1; i < dir.entry.length ; i++)
1345 if (dir.entry.name[i] < '0' || dir.entry.name[i] > '9')
1348 if (i == len + 1 + 1 || i >= dir.entry.length ||
1349 dir.entry.name[i] != '+')
1352 for (i++ ; i < dir.entry.length ; i++)
1353 if (dir.entry.name[i] < '0' || dir.entry.name[i] > '9')
1356 if (strcmp(dir.entry.name + i, ".private") != 0)
1360 result = dst_key_fromnamedfile(dir.entry.name,
1366 if (result != ISC_R_SUCCESS) {
1367 isc_log_write(dns_lctx,
1368 DNS_LOGCATEGORY_GENERAL,
1369 DNS_LOGMODULE_DNSSEC,
1371 "dns_dnssec_findmatchingkeys: "
1372 "error reading key file %s: %s",
1374 isc_result_totext(result));
1378 RETERR(dns_dnsseckey_create(mctx, &dstkey, &key));
1379 key->source = dns_keysource_repository;
1380 get_hints(key, now);
1383 dns_dnsseckey_destroy(mctx, &key);
1385 ISC_LIST_APPEND(list, key, link);
1390 if (!ISC_LIST_EMPTY(list)) {
1391 result = ISC_R_SUCCESS;
1392 ISC_LIST_APPENDLIST(*keylist, list, link);
1394 result = ISC_R_NOTFOUND;
1398 isc_dir_close(&dir);
1399 INSIST(key == NULL);
1400 while ((key = ISC_LIST_HEAD(list)) != NULL) {
1401 ISC_LIST_UNLINK(list, key, link);
1402 INSIST(key->key != NULL);
1403 dst_key_free(&key->key);
1404 dns_dnsseckey_destroy(mctx, &key);
1407 dst_key_free(&dstkey);
1412 * Add 'newkey' to 'keylist' if it's not already there.
1414 * If 'savekeys' is ISC_TRUE, then we need to preserve all
1415 * the keys in the keyset, regardless of whether they have
1416 * metadata indicating they should be deactivated or removed.
1419 addkey(dns_dnsseckeylist_t *keylist, dst_key_t **newkey,
1420 isc_boolean_t savekeys, isc_mem_t *mctx)
1422 dns_dnsseckey_t *key;
1423 isc_result_t result;
1425 /* Skip duplicates */
1426 for (key = ISC_LIST_HEAD(*keylist);
1428 key = ISC_LIST_NEXT(key, link)) {
1429 if (dst_key_id(key->key) == dst_key_id(*newkey) &&
1430 dst_key_alg(key->key) == dst_key_alg(*newkey) &&
1431 dns_name_equal(dst_key_name(key->key),
1432 dst_key_name(*newkey)))
1438 * Found a match. If the old key was only public and the
1439 * new key is private, replace the old one; otherwise
1440 * leave it. But either way, mark the key as having
1441 * been found in the zone.
1443 if (dst_key_isprivate(key->key)) {
1444 dst_key_free(newkey);
1445 } else if (dst_key_isprivate(*newkey)) {
1446 dst_key_free(&key->key);
1450 key->source = dns_keysource_zoneapex;
1451 return (ISC_R_SUCCESS);
1454 result = dns_dnsseckey_create(mctx, newkey, &key);
1455 if (result != ISC_R_SUCCESS)
1457 if (key->legacy || savekeys) {
1458 key->force_publish = ISC_TRUE;
1459 key->force_sign = dst_key_isprivate(key->key);
1461 key->source = dns_keysource_zoneapex;
1462 ISC_LIST_APPEND(*keylist, key, link);
1464 return (ISC_R_SUCCESS);
1469 * Mark all keys which signed the DNSKEY/SOA RRsets as "active",
1470 * for future reference.
1473 mark_active_keys(dns_dnsseckeylist_t *keylist, dns_rdataset_t *rrsigs) {
1474 isc_result_t result = ISC_R_SUCCESS;
1475 dns_rdata_t rdata = DNS_RDATA_INIT;
1476 dns_rdataset_t sigs;
1477 dns_dnsseckey_t *key;
1479 REQUIRE(rrsigs != NULL && dns_rdataset_isassociated(rrsigs));
1481 dns_rdataset_init(&sigs);
1482 dns_rdataset_clone(rrsigs, &sigs);
1483 for (key = ISC_LIST_HEAD(*keylist);
1485 key = ISC_LIST_NEXT(key, link)) {
1486 isc_uint16_t keyid, sigid;
1487 dns_secalg_t keyalg, sigalg;
1488 keyid = dst_key_id(key->key);
1489 keyalg = dst_key_alg(key->key);
1491 for (result = dns_rdataset_first(&sigs);
1492 result == ISC_R_SUCCESS;
1493 result = dns_rdataset_next(&sigs)) {
1494 dns_rdata_rrsig_t sig;
1496 dns_rdata_reset(&rdata);
1497 dns_rdataset_current(&sigs, &rdata);
1498 result = dns_rdata_tostruct(&rdata, &sig, NULL);
1499 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1500 sigalg = sig.algorithm;
1502 if (keyid == sigid && keyalg == sigalg) {
1503 key->is_active = ISC_TRUE;
1509 if (result == ISC_R_NOMORE)
1510 result = ISC_R_SUCCESS;
1512 if (dns_rdataset_isassociated(&sigs))
1513 dns_rdataset_disassociate(&sigs);
1518 * Add the contents of a DNSKEY rdataset 'keyset' to 'keylist'.
1521 dns_dnssec_keylistfromrdataset(dns_name_t *origin,
1522 const char *directory, isc_mem_t *mctx,
1523 dns_rdataset_t *keyset, dns_rdataset_t *keysigs,
1524 dns_rdataset_t *soasigs, isc_boolean_t savekeys,
1525 isc_boolean_t public,
1526 dns_dnsseckeylist_t *keylist)
1528 dns_rdataset_t keys;
1529 dns_rdata_t rdata = DNS_RDATA_INIT;
1530 dst_key_t *pubkey = NULL, *privkey = NULL;
1531 isc_result_t result;
1533 REQUIRE(keyset != NULL && dns_rdataset_isassociated(keyset));
1535 dns_rdataset_init(&keys);
1537 dns_rdataset_clone(keyset, &keys);
1538 for (result = dns_rdataset_first(&keys);
1539 result == ISC_R_SUCCESS;
1540 result = dns_rdataset_next(&keys)) {
1541 dns_rdata_reset(&rdata);
1542 dns_rdataset_current(&keys, &rdata);
1543 RETERR(dns_dnssec_keyfromrdata(origin, &rdata, mctx, &pubkey));
1544 dst_key_setttl(pubkey, keys.ttl);
1546 if (!is_zone_key(pubkey) ||
1547 (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0)
1550 /* Corrupted .key file? */
1551 if (!dns_name_equal(origin, dst_key_name(pubkey)))
1555 RETERR(addkey(keylist, &pubkey, savekeys, mctx));
1559 result = dst_key_fromfile(dst_key_name(pubkey),
1561 dst_key_alg(pubkey),
1562 DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
1563 directory, mctx, &privkey);
1566 * If the key was revoked and the private file
1567 * doesn't exist, maybe it was revoked internally
1568 * by named. Try loading the unrevoked version.
1570 if (result == ISC_R_FILENOTFOUND) {
1572 flags = dst_key_flags(pubkey);
1573 if ((flags & DNS_KEYFLAG_REVOKE) != 0) {
1574 dst_key_setflags(pubkey,
1575 flags & ~DNS_KEYFLAG_REVOKE);
1576 result = dst_key_fromfile(dst_key_name(pubkey),
1578 dst_key_alg(pubkey),
1583 if (result == ISC_R_SUCCESS &&
1584 dst_key_pubcompare(pubkey, privkey,
1586 dst_key_setflags(privkey, flags);
1588 dst_key_setflags(pubkey, flags);
1592 if (result != ISC_R_SUCCESS) {
1593 char keybuf[DNS_NAME_FORMATSIZE];
1594 char algbuf[DNS_SECALG_FORMATSIZE];
1595 dns_name_format(dst_key_name(pubkey), keybuf,
1597 dns_secalg_format(dst_key_alg(pubkey), algbuf,
1599 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
1600 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
1601 "dns_dnssec_keylistfromrdataset: error "
1602 "reading private key file %s/%s/%d: %s",
1603 keybuf, algbuf, dst_key_id(pubkey),
1604 isc_result_totext(result));
1607 if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) {
1608 RETERR(addkey(keylist, &pubkey, savekeys, mctx));
1613 /* This should never happen. */
1614 if ((dst_key_flags(privkey) & DNS_KEYTYPE_NOAUTH) != 0)
1618 * Whatever the key's default TTL may have
1619 * been, the rdataset TTL takes priority.
1621 dst_key_setttl(privkey, dst_key_getttl(pubkey));
1623 RETERR(addkey(keylist, &privkey, savekeys, mctx));
1626 dst_key_free(&pubkey);
1627 if (privkey != NULL)
1628 dst_key_free(&privkey);
1631 if (result != ISC_R_NOMORE)
1634 if (keysigs != NULL && dns_rdataset_isassociated(keysigs))
1635 RETERR(mark_active_keys(keylist, keysigs));
1637 if (soasigs != NULL && dns_rdataset_isassociated(soasigs))
1638 RETERR(mark_active_keys(keylist, soasigs));
1640 result = ISC_R_SUCCESS;
1643 if (dns_rdataset_isassociated(&keys))
1644 dns_rdataset_disassociate(&keys);
1646 dst_key_free(&pubkey);
1647 if (privkey != NULL)
1648 dst_key_free(&privkey);
1653 make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize,
1654 dns_rdata_t *target)
1656 isc_result_t result;
1660 isc_buffer_init(&b, buf, bufsize);
1661 result = dst_key_todns(key, &b);
1662 if (result != ISC_R_SUCCESS)
1665 dns_rdata_reset(target);
1666 isc_buffer_usedregion(&b, &r);
1667 dns_rdata_fromregion(target, dst_key_class(key),
1668 dns_rdatatype_dnskey, &r);
1669 return (ISC_R_SUCCESS);
1673 publish_key(dns_diff_t *diff, dns_dnsseckey_t *key, dns_name_t *origin,
1674 dns_ttl_t ttl, isc_mem_t *mctx, isc_boolean_t allzsk,
1675 void (*report)(const char *, ...))
1677 isc_result_t result;
1678 dns_difftuple_t *tuple = NULL;
1679 unsigned char buf[DST_KEY_MAXSIZE];
1680 dns_rdata_t dnskey = DNS_RDATA_INIT;
1683 dns_rdata_reset(&dnskey);
1684 RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey));
1686 dns_secalg_format(dst_key_alg(key->key), alg, sizeof(alg));
1687 report("Fetching %s %d/%s from key %s.",
1688 key->ksk ? (allzsk ? "KSK/ZSK" : "KSK") : "ZSK",
1689 dst_key_id(key->key), alg,
1690 key->source == dns_keysource_user ? "file" : "repository");
1692 if (key->prepublish && ttl > key->prepublish) {
1693 char keystr[DST_KEY_FORMATSIZE];
1696 dst_key_format(key->key, keystr, sizeof(keystr));
1697 report("Key %s: Delaying activation to match the DNSKEY TTL.\n",
1700 isc_stdtime_get(&now);
1701 dst_key_settime(key->key, DST_TIME_ACTIVATE, now + ttl);
1705 RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_ADD, origin, ttl,
1707 dns_diff_appendminimal(diff, &tuple);
1708 result = ISC_R_SUCCESS;
1715 remove_key(dns_diff_t *diff, dns_dnsseckey_t *key, dns_name_t *origin,
1716 dns_ttl_t ttl, isc_mem_t *mctx, const char *reason,
1717 void (*report)(const char *, ...))
1719 isc_result_t result;
1720 dns_difftuple_t *tuple = NULL;
1721 unsigned char buf[DST_KEY_MAXSIZE];
1722 dns_rdata_t dnskey = DNS_RDATA_INIT;
1725 dns_secalg_format(dst_key_alg(key->key), alg, sizeof(alg));
1726 report("Removing %s key %d/%s from DNSKEY RRset.",
1727 reason, dst_key_id(key->key), alg);
1729 RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey));
1730 RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_DEL, origin, ttl, &dnskey,
1732 dns_diff_appendminimal(diff, &tuple);
1733 result = ISC_R_SUCCESS;
1740 * Update 'keys' with information from 'newkeys'.
1742 * If 'removed' is not NULL, any keys that are being removed from
1743 * the zone will be added to the list for post-removal processing.
1746 dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys,
1747 dns_dnsseckeylist_t *removed, dns_name_t *origin,
1748 dns_ttl_t hint_ttl, dns_diff_t *diff,
1749 isc_boolean_t allzsk, isc_mem_t *mctx,
1750 void (*report)(const char *, ...))
1752 isc_result_t result;
1753 dns_dnsseckey_t *key, *key1, *key2, *next;
1754 isc_boolean_t found_ttl = ISC_FALSE;
1755 dns_ttl_t ttl = hint_ttl;
1758 * First, look through the existing key list to find keys
1759 * supplied from the command line which are not in the zone.
1760 * Update the zone to include them.
1762 * Also, if there are keys published in the zone already,
1763 * use their TTL for all subsequent published keys.
1765 for (key = ISC_LIST_HEAD(*keys);
1767 key = ISC_LIST_NEXT(key, link)) {
1768 if (key->source == dns_keysource_user &&
1769 (key->hint_publish || key->force_publish)) {
1770 RETERR(publish_key(diff, key, origin, ttl,
1771 mctx, allzsk, report));
1773 if (key->source == dns_keysource_zoneapex) {
1774 ttl = dst_key_getttl(key->key);
1775 found_ttl = ISC_TRUE;
1780 * If there were no existing keys, use the smallest nonzero
1781 * TTL of the keys found in the repository.
1783 if (!found_ttl && !ISC_LIST_EMPTY(*newkeys)) {
1784 dns_ttl_t shortest = 0;
1786 for (key = ISC_LIST_HEAD(*newkeys);
1788 key = ISC_LIST_NEXT(key, link)) {
1789 dns_ttl_t thisttl = dst_key_getttl(key->key);
1791 (shortest == 0 || thisttl < shortest))
1800 * Second, scan the list of newly found keys looking for matches
1801 * with known keys, and update accordingly.
1803 for (key1 = ISC_LIST_HEAD(*newkeys); key1 != NULL; key1 = next) {
1804 isc_boolean_t key_revoked = ISC_FALSE;
1806 next = ISC_LIST_NEXT(key1, link);
1808 for (key2 = ISC_LIST_HEAD(*keys);
1810 key2 = ISC_LIST_NEXT(key2, link)) {
1811 int f1 = dst_key_flags(key1->key);
1812 int f2 = dst_key_flags(key2->key);
1813 int nr1 = f1 & ~DNS_KEYFLAG_REVOKE;
1814 int nr2 = f2 & ~DNS_KEYFLAG_REVOKE;
1816 dst_key_alg(key1->key) == dst_key_alg(key2->key) &&
1817 dst_key_pubcompare(key1->key, key2->key,
1820 r1 = dst_key_flags(key1->key) &
1822 r2 = dst_key_flags(key2->key) &
1824 key_revoked = ISC_TF(r1 != r2);
1829 /* No match found in keys; add the new key. */
1831 ISC_LIST_UNLINK(*newkeys, key1, link);
1832 ISC_LIST_APPEND(*keys, key1, link);
1834 if (key1->source != dns_keysource_zoneapex &&
1835 (key1->hint_publish || key1->force_publish)) {
1836 RETERR(publish_key(diff, key1, origin, ttl,
1837 mctx, allzsk, report));
1838 if (key1->hint_sign || key1->force_sign)
1839 key1->first_sign = ISC_TRUE;
1845 /* Match found: remove or update it as needed */
1846 if (key1->hint_remove) {
1847 RETERR(remove_key(diff, key2, origin, ttl, mctx,
1848 "expired", report));
1849 ISC_LIST_UNLINK(*keys, key2, link);
1850 if (removed != NULL)
1851 ISC_LIST_APPEND(*removed, key2, link);
1853 dns_dnsseckey_destroy(mctx, &key2);
1854 } else if (key_revoked &&
1855 (dst_key_flags(key1->key) & DNS_KEYFLAG_REVOKE) != 0) {
1858 * A previously valid key has been revoked.
1859 * We need to remove the old version and pull
1862 RETERR(remove_key(diff, key2, origin, ttl, mctx,
1863 "revoked", report));
1864 ISC_LIST_UNLINK(*keys, key2, link);
1865 if (removed != NULL)
1866 ISC_LIST_APPEND(*removed, key2, link);
1868 dns_dnsseckey_destroy(mctx, &key2);
1870 RETERR(publish_key(diff, key1, origin, ttl,
1871 mctx, allzsk, report));
1872 ISC_LIST_UNLINK(*newkeys, key1, link);
1873 ISC_LIST_APPEND(*keys, key1, link);
1876 * XXX: The revoke flag is only defined for trust
1877 * anchors. Setting the flag on a non-KSK is legal,
1878 * but not defined in any RFC. It seems reasonable
1879 * to treat it the same as a KSK: keep it in the
1880 * zone, sign the DNSKEY set with it, but not
1881 * sign other records with it.
1883 key1->ksk = ISC_TRUE;
1886 if (!key2->is_active &&
1887 (key1->hint_sign || key1->force_sign))
1888 key2->first_sign = ISC_TRUE;
1889 key2->hint_sign = key1->hint_sign;
1890 key2->hint_publish = key1->hint_publish;
1894 /* Free any leftover keys in newkeys */
1895 while (!ISC_LIST_EMPTY(*newkeys)) {
1896 key1 = ISC_LIST_HEAD(*newkeys);
1897 ISC_LIST_UNLINK(*newkeys, key1, link);
1898 dns_dnsseckey_destroy(mctx, &key1);
1901 result = ISC_R_SUCCESS;