2 * Copyright (C) 2004-2011 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.
19 * $Id: dnssec.c,v 1.119.170.4 2011-05-06 21:07:50 each Exp $
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/tsig.h> /* for DNS_TSIG_FUDGE */
49 #include <dst/result.h>
51 #define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR)
53 #define RETERR(x) do { \
55 if (result != ISC_R_SUCCESS) \
64 digest_callback(void *arg, isc_region_t *data);
67 rdata_compare_wrapper(const void *rdata1, const void *rdata2);
70 rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx,
71 dns_rdata_t **rdata, int *nrdata);
74 digest_callback(void *arg, isc_region_t *data) {
75 dst_context_t *ctx = arg;
77 return (dst_context_adddata(ctx, data));
84 rdata_compare_wrapper(const void *rdata1, const void *rdata2) {
85 return (dns_rdata_compare((const dns_rdata_t *)rdata1,
86 (const dns_rdata_t *)rdata2));
90 * Sort the rdataset into an array.
93 rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx,
94 dns_rdata_t **rdata, int *nrdata)
99 dns_rdataset_t rdataset;
101 n = dns_rdataset_count(set);
103 data = isc_mem_get(mctx, n * sizeof(dns_rdata_t));
105 return (ISC_R_NOMEMORY);
107 dns_rdataset_init(&rdataset);
108 dns_rdataset_clone(set, &rdataset);
109 ret = dns_rdataset_first(&rdataset);
110 if (ret != ISC_R_SUCCESS) {
111 dns_rdataset_disassociate(&rdataset);
112 isc_mem_put(mctx, data, n * sizeof(dns_rdata_t));
117 * Put them in the array.
120 dns_rdata_init(&data[i]);
121 dns_rdataset_current(&rdataset, &data[i++]);
122 } while (dns_rdataset_next(&rdataset) == ISC_R_SUCCESS);
127 qsort(data, n, sizeof(dns_rdata_t), rdata_compare_wrapper);
130 dns_rdataset_disassociate(&rdataset);
131 return (ISC_R_SUCCESS);
135 dns_dnssec_keyfromrdata(dns_name_t *name, dns_rdata_t *rdata, isc_mem_t *mctx,
141 INSIST(name != NULL);
142 INSIST(rdata != NULL);
143 INSIST(mctx != NULL);
145 INSIST(*key == NULL);
146 REQUIRE(rdata->type == dns_rdatatype_key ||
147 rdata->type == dns_rdatatype_dnskey);
149 dns_rdata_toregion(rdata, &r);
150 isc_buffer_init(&b, r.base, r.length);
151 isc_buffer_add(&b, r.length);
152 return (dst_key_fromdns(name, rdata->rdclass, &b, mctx, key));
156 digest_sig(dst_context_t *ctx, dns_rdata_t *sigrdata, dns_rdata_rrsig_t *sig) {
159 dns_fixedname_t fname;
161 dns_rdata_toregion(sigrdata, &r);
162 INSIST(r.length >= 19);
165 ret = dst_context_adddata(ctx, &r);
166 if (ret != ISC_R_SUCCESS)
168 dns_fixedname_init(&fname);
169 RUNTIME_CHECK(dns_name_downcase(&sig->signer,
170 dns_fixedname_name(&fname), NULL)
172 dns_name_toregion(dns_fixedname_name(&fname), &r);
173 return (dst_context_adddata(ctx, &r));
177 dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
178 isc_stdtime_t *inception, isc_stdtime_t *expire,
179 isc_mem_t *mctx, isc_buffer_t *buffer, dns_rdata_t *sigrdata)
181 dns_rdata_rrsig_t sig;
182 dns_rdata_t tmpsigrdata;
185 isc_buffer_t sigbuf, envbuf;
187 dst_context_t *ctx = NULL;
189 isc_buffer_t *databuf = NULL;
192 unsigned int sigsize;
193 dns_fixedname_t fnewname;
195 REQUIRE(name != NULL);
196 REQUIRE(dns_name_countlabels(name) <= 255);
197 REQUIRE(set != NULL);
198 REQUIRE(key != NULL);
199 REQUIRE(inception != NULL);
200 REQUIRE(expire != NULL);
201 REQUIRE(mctx != NULL);
202 REQUIRE(sigrdata != NULL);
204 if (*inception >= *expire)
205 return (DNS_R_INVALIDTIME);
208 * Is the key allowed to sign data?
210 flags = dst_key_flags(key);
211 if (flags & DNS_KEYTYPE_NOAUTH)
212 return (DNS_R_KEYUNAUTHORIZED);
213 if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE)
214 return (DNS_R_KEYUNAUTHORIZED);
217 sig.common.rdclass = set->rdclass;
218 sig.common.rdtype = dns_rdatatype_rrsig;
219 ISC_LINK_INIT(&sig.common, link);
221 dns_name_init(&sig.signer, NULL);
222 dns_name_clone(dst_key_name(key), &sig.signer);
224 sig.covered = set->type;
225 sig.algorithm = dst_key_alg(key);
226 sig.labels = dns_name_countlabels(name) - 1;
227 if (dns_name_iswildcard(name))
229 sig.originalttl = set->ttl;
230 sig.timesigned = *inception;
231 sig.timeexpire = *expire;
232 sig.keyid = dst_key_id(key);
233 ret = dst_key_sigsize(key, &sigsize);
234 if (ret != ISC_R_SUCCESS)
236 sig.siglen = sigsize;
238 * The actual contents of sig.signature are not important yet, since
239 * they're not used in digest_sig().
241 sig.signature = isc_mem_get(mctx, sig.siglen);
242 if (sig.signature == NULL)
243 return (ISC_R_NOMEMORY);
245 ret = isc_buffer_allocate(mctx, &databuf, sigsize + 256 + 18);
246 if (ret != ISC_R_SUCCESS)
247 goto cleanup_signature;
249 dns_rdata_init(&tmpsigrdata);
250 ret = dns_rdata_fromstruct(&tmpsigrdata, sig.common.rdclass,
251 sig.common.rdtype, &sig, databuf);
252 if (ret != ISC_R_SUCCESS)
253 goto cleanup_databuf;
255 ret = dst_context_create(key, mctx, &ctx);
256 if (ret != ISC_R_SUCCESS)
257 goto cleanup_databuf;
260 * Digest the SIG rdata.
262 ret = digest_sig(ctx, &tmpsigrdata, &sig);
263 if (ret != ISC_R_SUCCESS)
264 goto cleanup_context;
266 dns_fixedname_init(&fnewname);
267 RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname),
268 NULL) == ISC_R_SUCCESS);
269 dns_name_toregion(dns_fixedname_name(&fnewname), &r);
272 * Create an envelope for each rdata: <name|type|class|ttl>.
274 isc_buffer_init(&envbuf, data, sizeof(data));
275 memcpy(data, r.base, r.length);
276 isc_buffer_add(&envbuf, r.length);
277 isc_buffer_putuint16(&envbuf, set->type);
278 isc_buffer_putuint16(&envbuf, set->rdclass);
279 isc_buffer_putuint32(&envbuf, set->ttl);
281 ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas);
282 if (ret != ISC_R_SUCCESS)
283 goto cleanup_context;
284 isc_buffer_usedregion(&envbuf, &r);
286 for (i = 0; i < nrdatas; i++) {
294 if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i-1]) == 0)
298 * Digest the envelope.
300 ret = dst_context_adddata(ctx, &r);
301 if (ret != ISC_R_SUCCESS)
305 * Digest the length of the rdata.
307 isc_buffer_init(&lenbuf, &len, sizeof(len));
308 INSIST(rdatas[i].length < 65536);
309 isc_buffer_putuint16(&lenbuf, (isc_uint16_t)rdatas[i].length);
310 isc_buffer_usedregion(&lenbuf, &lenr);
311 ret = dst_context_adddata(ctx, &lenr);
312 if (ret != ISC_R_SUCCESS)
318 ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx);
319 if (ret != ISC_R_SUCCESS)
323 isc_buffer_init(&sigbuf, sig.signature, sig.siglen);
324 ret = dst_context_sign(ctx, &sigbuf);
325 if (ret != ISC_R_SUCCESS)
327 isc_buffer_usedregion(&sigbuf, &r);
328 if (r.length != sig.siglen) {
332 memcpy(sig.signature, r.base, sig.siglen);
334 ret = dns_rdata_fromstruct(sigrdata, sig.common.rdclass,
335 sig.common.rdtype, &sig, buffer);
338 isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t));
340 dst_context_destroy(&ctx);
342 isc_buffer_free(&databuf);
344 isc_mem_put(mctx, sig.signature, sig.siglen);
350 dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
351 isc_boolean_t ignoretime, isc_mem_t *mctx,
352 dns_rdata_t *sigrdata, dns_name_t *wild)
354 dns_rdata_rrsig_t sig;
355 dns_fixedname_t fnewname;
362 unsigned char data[300];
363 dst_context_t *ctx = NULL;
367 REQUIRE(name != NULL);
368 REQUIRE(set != NULL);
369 REQUIRE(key != NULL);
370 REQUIRE(mctx != NULL);
371 REQUIRE(sigrdata != NULL && sigrdata->type == dns_rdatatype_rrsig);
373 ret = dns_rdata_tostruct(sigrdata, &sig, NULL);
374 if (ret != ISC_R_SUCCESS)
377 if (set->type != sig.covered)
378 return (DNS_R_SIGINVALID);
380 if (isc_serial_lt(sig.timeexpire, sig.timesigned))
381 return (DNS_R_SIGINVALID);
384 isc_stdtime_get(&now);
387 * Is SIG temporally valid?
389 if (isc_serial_lt((isc_uint32_t)now, sig.timesigned))
390 return (DNS_R_SIGFUTURE);
391 else if (isc_serial_lt(sig.timeexpire, (isc_uint32_t)now))
392 return (DNS_R_SIGEXPIRED);
396 * NS, SOA and DNSSKEY records are signed by their owner.
397 * DS records are signed by the parent.
400 case dns_rdatatype_ns:
401 case dns_rdatatype_soa:
402 case dns_rdatatype_dnskey:
403 if (!dns_name_equal(name, &sig.signer))
404 return (DNS_R_SIGINVALID);
406 case dns_rdatatype_ds:
407 if (dns_name_equal(name, &sig.signer))
408 return (DNS_R_SIGINVALID);
411 if (!dns_name_issubdomain(name, &sig.signer))
412 return (DNS_R_SIGINVALID);
417 * Is the key allowed to sign data?
419 flags = dst_key_flags(key);
420 if (flags & DNS_KEYTYPE_NOAUTH)
421 return (DNS_R_KEYUNAUTHORIZED);
422 if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE)
423 return (DNS_R_KEYUNAUTHORIZED);
425 ret = dst_context_create(key, mctx, &ctx);
426 if (ret != ISC_R_SUCCESS)
430 * Digest the SIG rdata (not including the signature).
432 ret = digest_sig(ctx, sigrdata, &sig);
433 if (ret != ISC_R_SUCCESS)
434 goto cleanup_context;
437 * If the name is an expanded wildcard, use the wildcard name.
439 dns_fixedname_init(&fnewname);
440 labels = dns_name_countlabels(name) - 1;
441 RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname),
442 NULL) == ISC_R_SUCCESS);
443 if (labels - sig.labels > 0)
444 dns_name_split(dns_fixedname_name(&fnewname), sig.labels + 1,
445 NULL, dns_fixedname_name(&fnewname));
447 dns_name_toregion(dns_fixedname_name(&fnewname), &r);
450 * Create an envelope for each rdata: <name|type|class|ttl>.
452 isc_buffer_init(&envbuf, data, sizeof(data));
453 if (labels - sig.labels > 0) {
454 isc_buffer_putuint8(&envbuf, 1);
455 isc_buffer_putuint8(&envbuf, '*');
456 memcpy(data + 2, r.base, r.length);
459 memcpy(data, r.base, r.length);
460 isc_buffer_add(&envbuf, r.length);
461 isc_buffer_putuint16(&envbuf, set->type);
462 isc_buffer_putuint16(&envbuf, set->rdclass);
463 isc_buffer_putuint32(&envbuf, sig.originalttl);
465 ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas);
466 if (ret != ISC_R_SUCCESS)
467 goto cleanup_context;
469 isc_buffer_usedregion(&envbuf, &r);
471 for (i = 0; i < nrdatas; i++) {
479 if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i-1]) == 0)
483 * Digest the envelope.
485 ret = dst_context_adddata(ctx, &r);
486 if (ret != ISC_R_SUCCESS)
490 * Digest the rdata length.
492 isc_buffer_init(&lenbuf, &len, sizeof(len));
493 INSIST(rdatas[i].length < 65536);
494 isc_buffer_putuint16(&lenbuf, (isc_uint16_t)rdatas[i].length);
495 isc_buffer_usedregion(&lenbuf, &lenr);
500 ret = dst_context_adddata(ctx, &lenr);
501 if (ret != ISC_R_SUCCESS)
503 ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx);
504 if (ret != ISC_R_SUCCESS)
508 r.base = sig.signature;
509 r.length = sig.siglen;
510 ret = dst_context_verify(ctx, &r);
511 if (ret == DST_R_VERIFYFAILURE)
512 ret = DNS_R_SIGINVALID;
515 isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t));
517 dst_context_destroy(&ctx);
519 dns_rdata_freestruct(&sig);
521 if (ret == ISC_R_SUCCESS && labels - sig.labels > 0) {
523 RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname,
524 dns_fixedname_name(&fnewname),
525 wild, NULL) == ISC_R_SUCCESS);
526 ret = DNS_R_FROMWILDCARD;
532 dns_dnssec_verify(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
533 isc_boolean_t ignoretime, isc_mem_t *mctx,
534 dns_rdata_t *sigrdata)
538 result = dns_dnssec_verify2(name, set, key, ignoretime, mctx,
540 if (result == DNS_R_FROMWILDCARD)
541 result = ISC_R_SUCCESS;
546 key_active(dst_key_t *key, isc_stdtime_t now) {
548 isc_stdtime_t publish, active, revoke, inactive, delete;
549 isc_boolean_t pubset = ISC_FALSE, actset = ISC_FALSE;
550 isc_boolean_t revset = ISC_FALSE, inactset = ISC_FALSE;
551 isc_boolean_t delset = ISC_FALSE;
554 /* Is this an old-style key? */
555 result = dst_key_getprivateformat(key, &major, &minor);
556 RUNTIME_CHECK(result == ISC_R_SUCCESS);
559 * Smart signing started with key format 1.3; prior to that, all
560 * keys are assumed active
562 if (major == 1 && minor <= 2)
565 result = dst_key_gettime(key, DST_TIME_PUBLISH, &publish);
566 if (result == ISC_R_SUCCESS)
569 result = dst_key_gettime(key, DST_TIME_ACTIVATE, &active);
570 if (result == ISC_R_SUCCESS)
573 result = dst_key_gettime(key, DST_TIME_REVOKE, &revoke);
574 if (result == ISC_R_SUCCESS)
577 result = dst_key_gettime(key, DST_TIME_INACTIVE, &inactive);
578 if (result == ISC_R_SUCCESS)
581 result = dst_key_gettime(key, DST_TIME_DELETE, &delete);
582 if (result == ISC_R_SUCCESS)
585 if ((inactset && inactive <= now) || (delset && delete <= now))
588 if (revset && revoke <= now && pubset && publish <= now)
591 if (actset && active <= now)
597 #define is_zone_key(key) ((dst_key_flags(key) & DNS_KEYFLAG_OWNERMASK) \
598 == DNS_KEYOWNER_ZONE)
601 dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver,
602 dns_dbnode_t *node, dns_name_t *name,
603 const char *directory, isc_mem_t *mctx,
604 unsigned int maxkeys, dst_key_t **keys,
607 dns_rdataset_t rdataset;
608 dns_rdata_t rdata = DNS_RDATA_INIT;
610 dst_key_t *pubkey = NULL;
611 unsigned int count = 0;
614 REQUIRE(nkeys != NULL);
615 REQUIRE(keys != NULL);
617 isc_stdtime_get(&now);
620 dns_rdataset_init(&rdataset);
621 RETERR(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0,
623 RETERR(dns_rdataset_first(&rdataset));
624 while (result == ISC_R_SUCCESS && count < maxkeys) {
626 dns_rdataset_current(&rdataset, &rdata);
627 RETERR(dns_dnssec_keyfromrdata(name, &rdata, mctx, &pubkey));
628 if (!is_zone_key(pubkey) ||
629 (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0)
631 /* Corrupted .key file? */
632 if (!dns_name_equal(name, dst_key_name(pubkey)))
635 result = dst_key_fromfile(dst_key_name(pubkey),
638 DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
643 * If the key was revoked and the private file
644 * doesn't exist, maybe it was revoked internally
645 * by named. Try loading the unrevoked version.
647 if (result == ISC_R_FILENOTFOUND) {
649 flags = dst_key_flags(pubkey);
650 if ((flags & DNS_KEYFLAG_REVOKE) != 0) {
651 dst_key_setflags(pubkey,
652 flags & ~DNS_KEYFLAG_REVOKE);
653 result = dst_key_fromfile(dst_key_name(pubkey),
660 if (result == ISC_R_SUCCESS &&
661 dst_key_pubcompare(pubkey, keys[count],
663 dst_key_setflags(keys[count], flags);
665 dst_key_setflags(pubkey, flags);
669 if (result != ISC_R_SUCCESS) {
670 char keybuf[DNS_NAME_FORMATSIZE];
671 char algbuf[DNS_SECALG_FORMATSIZE];
672 dns_name_format(dst_key_name(pubkey), keybuf,
674 dns_secalg_format(dst_key_alg(pubkey), algbuf,
676 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
677 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
678 "dns_dnssec_findzonekeys2: error "
679 "reading private key file %s/%s/%d: %s",
680 keybuf, algbuf, dst_key_id(pubkey),
681 isc_result_totext(result));
684 if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) {
685 keys[count] = pubkey;
691 if (result != ISC_R_SUCCESS)
695 * If a key is marked inactive, skip it
697 if (!key_active(keys[count], now)) {
698 dst_key_free(&keys[count]);
699 keys[count] = pubkey;
705 if ((dst_key_flags(keys[count]) & DNS_KEYTYPE_NOAUTH) != 0) {
706 /* We should never get here. */
707 dst_key_free(&keys[count]);
713 dst_key_free(&pubkey);
714 dns_rdata_reset(&rdata);
715 result = dns_rdataset_next(&rdataset);
717 if (result != ISC_R_NOMORE)
720 result = ISC_R_NOTFOUND;
722 result = ISC_R_SUCCESS;
725 if (dns_rdataset_isassociated(&rdataset))
726 dns_rdataset_disassociate(&rdataset);
728 dst_key_free(&pubkey);
729 if (result != ISC_R_SUCCESS)
731 dst_key_free(&keys[--count]);
737 dns_dnssec_findzonekeys(dns_db_t *db, dns_dbversion_t *ver,
738 dns_dbnode_t *node, dns_name_t *name, isc_mem_t *mctx,
739 unsigned int maxkeys, dst_key_t **keys,
742 return (dns_dnssec_findzonekeys2(db, ver, node, name, NULL, mctx,
743 maxkeys, keys, nkeys));
747 dns_dnssec_signmessage(dns_message_t *msg, dst_key_t *key) {
748 dns_rdata_sig_t sig; /* SIG(0) */
749 unsigned char data[512];
750 unsigned char header[DNS_MESSAGE_HEADERLEN];
751 isc_buffer_t headerbuf, databuf, sigbuf;
752 unsigned int sigsize;
753 isc_buffer_t *dynbuf = NULL;
755 dns_rdatalist_t *datalist;
756 dns_rdataset_t *dataset;
759 dst_context_t *ctx = NULL;
762 isc_boolean_t signeedsfree = ISC_TRUE;
764 REQUIRE(msg != NULL);
765 REQUIRE(key != NULL);
767 if (is_response(msg))
768 REQUIRE(msg->query.base != NULL);
772 memset(&sig, 0, sizeof(sig));
775 sig.common.rdclass = dns_rdataclass_any;
776 sig.common.rdtype = dns_rdatatype_sig; /* SIG(0) */
777 ISC_LINK_INIT(&sig.common, link);
780 sig.algorithm = dst_key_alg(key);
781 sig.labels = 0; /* the root name */
784 isc_stdtime_get(&now);
785 sig.timesigned = now - DNS_TSIG_FUDGE;
786 sig.timeexpire = now + DNS_TSIG_FUDGE;
788 sig.keyid = dst_key_id(key);
790 dns_name_init(&sig.signer, NULL);
791 dns_name_clone(dst_key_name(key), &sig.signer);
794 sig.signature = NULL;
796 isc_buffer_init(&databuf, data, sizeof(data));
798 RETERR(dst_context_create(key, mctx, &ctx));
801 * Digest the fields of the SIG - we can cheat and use
802 * dns_rdata_fromstruct. Since siglen is 0, the digested data
803 * is identical to dns format.
805 RETERR(dns_rdata_fromstruct(NULL, dns_rdataclass_any,
806 dns_rdatatype_sig /* SIG(0) */,
808 isc_buffer_usedregion(&databuf, &r);
809 RETERR(dst_context_adddata(ctx, &r));
812 * If this is a response, digest the query.
814 if (is_response(msg))
815 RETERR(dst_context_adddata(ctx, &msg->query));
820 isc_buffer_init(&headerbuf, header, sizeof(header));
821 dns_message_renderheader(msg, &headerbuf);
822 isc_buffer_usedregion(&headerbuf, &r);
823 RETERR(dst_context_adddata(ctx, &r));
826 * Digest the remainder of the message.
828 isc_buffer_usedregion(msg->buffer, &r);
829 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
830 RETERR(dst_context_adddata(ctx, &r));
832 RETERR(dst_key_sigsize(key, &sigsize));
833 sig.siglen = sigsize;
834 sig.signature = (unsigned char *) isc_mem_get(mctx, sig.siglen);
835 if (sig.signature == NULL) {
836 result = ISC_R_NOMEMORY;
840 isc_buffer_init(&sigbuf, sig.signature, sig.siglen);
841 RETERR(dst_context_sign(ctx, &sigbuf));
842 dst_context_destroy(&ctx);
845 RETERR(dns_message_gettemprdata(msg, &rdata));
846 RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 1024));
847 RETERR(dns_rdata_fromstruct(rdata, dns_rdataclass_any,
848 dns_rdatatype_sig /* SIG(0) */,
851 isc_mem_put(mctx, sig.signature, sig.siglen);
852 signeedsfree = ISC_FALSE;
854 dns_message_takebuffer(msg, &dynbuf);
857 RETERR(dns_message_gettemprdatalist(msg, &datalist));
858 datalist->rdclass = dns_rdataclass_any;
859 datalist->type = dns_rdatatype_sig; /* SIG(0) */
860 datalist->covers = 0;
862 ISC_LIST_INIT(datalist->rdata);
863 ISC_LIST_APPEND(datalist->rdata, rdata, link);
865 RETERR(dns_message_gettemprdataset(msg, &dataset));
866 dns_rdataset_init(dataset);
867 RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset) == ISC_R_SUCCESS);
870 return (ISC_R_SUCCESS);
874 isc_buffer_free(&dynbuf);
876 isc_mem_put(mctx, sig.signature, sig.siglen);
878 dst_context_destroy(&ctx);
884 dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg,
887 dns_rdata_sig_t sig; /* SIG(0) */
888 unsigned char header[DNS_MESSAGE_HEADERLEN];
889 dns_rdata_t rdata = DNS_RDATA_INIT;
890 isc_region_t r, source_r, sig_r, header_r;
892 dst_context_t *ctx = NULL;
895 isc_uint16_t addcount;
896 isc_boolean_t signeedsfree = ISC_FALSE;
898 REQUIRE(source != NULL);
899 REQUIRE(msg != NULL);
900 REQUIRE(key != NULL);
904 msg->verify_attempted = 1;
906 if (is_response(msg)) {
907 if (msg->query.base == NULL)
908 return (DNS_R_UNEXPECTEDTSIG);
911 isc_buffer_usedregion(source, &source_r);
913 RETERR(dns_rdataset_first(msg->sig0));
914 dns_rdataset_current(msg->sig0, &rdata);
916 RETERR(dns_rdata_tostruct(&rdata, &sig, NULL));
917 signeedsfree = ISC_TRUE;
919 if (sig.labels != 0) {
920 result = DNS_R_SIGINVALID;
924 if (isc_serial_lt(sig.timeexpire, sig.timesigned)) {
925 result = DNS_R_SIGINVALID;
926 msg->sig0status = dns_tsigerror_badtime;
930 isc_stdtime_get(&now);
931 if (isc_serial_lt((isc_uint32_t)now, sig.timesigned)) {
932 result = DNS_R_SIGFUTURE;
933 msg->sig0status = dns_tsigerror_badtime;
936 else if (isc_serial_lt(sig.timeexpire, (isc_uint32_t)now)) {
937 result = DNS_R_SIGEXPIRED;
938 msg->sig0status = dns_tsigerror_badtime;
942 if (!dns_name_equal(dst_key_name(key), &sig.signer)) {
943 result = DNS_R_SIGINVALID;
944 msg->sig0status = dns_tsigerror_badkey;
948 RETERR(dst_context_create(key, mctx, &ctx));
951 * Digest the SIG(0) record, except for the signature.
953 dns_rdata_toregion(&rdata, &r);
954 r.length -= sig.siglen;
955 RETERR(dst_context_adddata(ctx, &r));
958 * If this is a response, digest the query.
960 if (is_response(msg))
961 RETERR(dst_context_adddata(ctx, &msg->query));
964 * Extract the header.
966 memcpy(header, source_r.base, DNS_MESSAGE_HEADERLEN);
969 * Decrement the additional field counter.
971 memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
972 addcount = htons((isc_uint16_t)(ntohs(addcount) - 1));
973 memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
976 * Digest the modified header.
978 header_r.base = (unsigned char *) header;
979 header_r.length = DNS_MESSAGE_HEADERLEN;
980 RETERR(dst_context_adddata(ctx, &header_r));
983 * Digest all non-SIG(0) records.
985 r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
986 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
987 RETERR(dst_context_adddata(ctx, &r));
989 sig_r.base = sig.signature;
990 sig_r.length = sig.siglen;
991 result = dst_context_verify(ctx, &sig_r);
992 if (result != ISC_R_SUCCESS) {
993 msg->sig0status = dns_tsigerror_badsig;
997 msg->verified_sig = 1;
999 dst_context_destroy(&ctx);
1000 dns_rdata_freestruct(&sig);
1002 return (ISC_R_SUCCESS);
1006 dns_rdata_freestruct(&sig);
1008 dst_context_destroy(&ctx);
1014 * Does this key ('rdata') self sign the rrset ('rdataset')?
1017 dns_dnssec_selfsigns(dns_rdata_t *rdata, dns_name_t *name,
1018 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
1019 isc_boolean_t ignoretime, isc_mem_t *mctx)
1021 INSIST(rdataset->type == dns_rdatatype_key ||
1022 rdataset->type == dns_rdatatype_dnskey);
1023 if (rdataset->type == dns_rdatatype_key) {
1024 INSIST(sigrdataset->type == dns_rdatatype_sig);
1025 INSIST(sigrdataset->covers == dns_rdatatype_key);
1027 INSIST(sigrdataset->type == dns_rdatatype_rrsig);
1028 INSIST(sigrdataset->covers == dns_rdatatype_dnskey);
1031 return (dns_dnssec_signs(rdata, name, rdataset, sigrdataset,
1037 dns_dnssec_signs(dns_rdata_t *rdata, dns_name_t *name,
1038 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
1039 isc_boolean_t ignoretime, isc_mem_t *mctx)
1041 dst_key_t *dstkey = NULL;
1042 dns_keytag_t keytag;
1043 dns_rdata_dnskey_t key;
1044 dns_rdata_rrsig_t sig;
1045 dns_rdata_t sigrdata = DNS_RDATA_INIT;
1046 isc_result_t result;
1048 INSIST(sigrdataset->type == dns_rdatatype_rrsig);
1049 if (sigrdataset->covers != rdataset->type)
1052 result = dns_dnssec_keyfromrdata(name, rdata, mctx, &dstkey);
1053 if (result != ISC_R_SUCCESS)
1055 result = dns_rdata_tostruct(rdata, &key, NULL);
1056 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1058 keytag = dst_key_id(dstkey);
1059 for (result = dns_rdataset_first(sigrdataset);
1060 result == ISC_R_SUCCESS;
1061 result = dns_rdataset_next(sigrdataset))
1063 dns_rdata_reset(&sigrdata);
1064 dns_rdataset_current(sigrdataset, &sigrdata);
1065 result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
1066 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1068 if (sig.algorithm == key.algorithm &&
1069 sig.keyid == keytag) {
1070 result = dns_dnssec_verify2(name, rdataset, dstkey,
1073 if (result == ISC_R_SUCCESS) {
1074 dst_key_free(&dstkey);
1079 dst_key_free(&dstkey);
1084 dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey,
1085 dns_dnsseckey_t **dkp)
1087 isc_result_t result;
1088 dns_dnsseckey_t *dk;
1091 REQUIRE(dkp != NULL && *dkp == NULL);
1092 dk = isc_mem_get(mctx, sizeof(dns_dnsseckey_t));
1094 return (ISC_R_NOMEMORY);
1098 dk->force_publish = ISC_FALSE;
1099 dk->force_sign = ISC_FALSE;
1100 dk->hint_publish = ISC_FALSE;
1101 dk->hint_sign = ISC_FALSE;
1102 dk->hint_remove = ISC_FALSE;
1103 dk->first_sign = ISC_FALSE;
1104 dk->is_active = ISC_FALSE;
1106 dk->source = dns_keysource_unknown;
1110 dk->ksk = ISC_TF((dst_key_flags(dk->key) & DNS_KEYFLAG_KSK) != 0);
1112 /* Is this an old-style key? */
1113 result = dst_key_getprivateformat(dk->key, &major, &minor);
1114 INSIST(result == ISC_R_SUCCESS);
1116 /* Smart signing started with key format 1.3 */
1117 dk->legacy = ISC_TF(major == 1 && minor <= 2);
1119 ISC_LINK_INIT(dk, link);
1121 return (ISC_R_SUCCESS);
1125 dns_dnsseckey_destroy(isc_mem_t *mctx, dns_dnsseckey_t **dkp) {
1126 dns_dnsseckey_t *dk;
1128 REQUIRE(dkp != NULL && *dkp != NULL);
1130 if (dk->key != NULL)
1131 dst_key_free(&dk->key);
1132 isc_mem_put(mctx, dk, sizeof(dns_dnsseckey_t));
1137 get_hints(dns_dnsseckey_t *key) {
1138 isc_result_t result;
1139 isc_stdtime_t now, publish, active, revoke, inactive, delete;
1140 isc_boolean_t pubset = ISC_FALSE, actset = ISC_FALSE;
1141 isc_boolean_t revset = ISC_FALSE, inactset = ISC_FALSE;
1142 isc_boolean_t delset = ISC_FALSE;
1144 REQUIRE(key != NULL && key->key != NULL);
1146 isc_stdtime_get(&now);
1148 result = dst_key_gettime(key->key, DST_TIME_PUBLISH, &publish);
1149 if (result == ISC_R_SUCCESS)
1152 result = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active);
1153 if (result == ISC_R_SUCCESS)
1156 result = dst_key_gettime(key->key, DST_TIME_REVOKE, &revoke);
1157 if (result == ISC_R_SUCCESS)
1160 result = dst_key_gettime(key->key, DST_TIME_INACTIVE, &inactive);
1161 if (result == ISC_R_SUCCESS)
1162 inactset = ISC_TRUE;
1164 result = dst_key_gettime(key->key, DST_TIME_DELETE, &delete);
1165 if (result == ISC_R_SUCCESS)
1168 /* Metadata says publish (but possibly not activate) */
1169 if (pubset && publish <= now)
1170 key->hint_publish = ISC_TRUE;
1172 /* Metadata says activate (so we must also publish) */
1173 if (actset && active <= now) {
1174 key->hint_sign = ISC_TRUE;
1175 key->hint_publish = ISC_TRUE;
1179 * Activation date is set (maybe in the future), but
1180 * publication date isn't. Most likely the user wants to
1181 * publish now and activate later.
1183 if (actset && !pubset)
1184 key->hint_publish = ISC_TRUE;
1187 * If activation date is in the future, make note of how far off
1189 if (key->hint_publish && actset && active > now) {
1190 key->prepublish = active - now;
1194 * Key has been marked inactive: we can continue publishing,
1197 if (key->hint_publish && inactset && inactive <= now) {
1198 key->hint_sign = ISC_FALSE;
1202 * Metadata says revoke. If the key is published,
1203 * we *have to* sign with it per RFC5011--even if it was
1204 * not active before.
1206 * If it hasn't already been done, we should also revoke it now.
1208 if (key->hint_publish && (revset && revoke <= now)) {
1210 key->hint_sign = ISC_TRUE;
1211 flags = dst_key_flags(key->key);
1212 if ((flags & DNS_KEYFLAG_REVOKE) == 0) {
1213 flags |= DNS_KEYFLAG_REVOKE;
1214 dst_key_setflags(key->key, flags);
1219 * Metadata says delete, so don't publish this key or sign with it.
1221 if (delset && delete <= now) {
1222 key->hint_publish = ISC_FALSE;
1223 key->hint_sign = ISC_FALSE;
1224 key->hint_remove = ISC_TRUE;
1229 * Get a list of DNSSEC keys from the key repository
1232 dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory,
1233 isc_mem_t *mctx, dns_dnsseckeylist_t *keylist)
1235 isc_result_t result = ISC_R_SUCCESS;
1236 isc_boolean_t dir_open = ISC_FALSE;
1237 dns_dnsseckeylist_t list;
1239 dns_dnsseckey_t *key = NULL;
1240 dst_key_t *dstkey = NULL;
1241 char namebuf[DNS_NAME_FORMATSIZE], *p;
1245 REQUIRE(keylist != NULL);
1246 ISC_LIST_INIT(list);
1249 isc_buffer_init(&b, namebuf, sizeof(namebuf) - 1);
1250 RETERR(dns_name_totext(origin, ISC_FALSE, &b));
1251 len = isc_buffer_usedlength(&b);
1252 namebuf[len] = '\0';
1254 if (directory == NULL)
1256 RETERR(isc_dir_open(&dir, directory));
1257 dir_open = ISC_TRUE;
1259 while (isc_dir_read(&dir) == ISC_R_SUCCESS) {
1260 if (dir.entry.name[0] == 'K' &&
1261 dir.entry.length > len + 1 &&
1262 dir.entry.name[len + 1] == '+' &&
1263 strncasecmp(dir.entry.name + 1, namebuf, len) == 0) {
1264 p = strrchr(dir.entry.name, '.');
1265 if (p != NULL && strcmp(p, ".private") != 0)
1269 result = dst_key_fromnamedfile(dir.entry.name,
1275 if (result != ISC_R_SUCCESS) {
1276 isc_log_write(dns_lctx,
1277 DNS_LOGCATEGORY_GENERAL,
1278 DNS_LOGMODULE_DNSSEC,
1280 "dns_dnssec_findmatchingkeys: "
1281 "error reading key file %s: %s",
1283 isc_result_totext(result));
1287 RETERR(dns_dnsseckey_create(mctx, &dstkey, &key));
1288 key->source = dns_keysource_repository;
1292 dns_dnsseckey_destroy(mctx, &key);
1294 ISC_LIST_APPEND(list, key, link);
1300 if (!ISC_LIST_EMPTY(list))
1301 ISC_LIST_APPENDLIST(*keylist, list, link);
1303 result = ISC_R_NOTFOUND;
1307 isc_dir_close(&dir);
1308 INSIST(key == NULL);
1309 while ((key = ISC_LIST_HEAD(list)) != NULL) {
1310 ISC_LIST_UNLINK(list, key, link);
1311 INSIST(key->key != NULL);
1312 dst_key_free(&key->key);
1313 dns_dnsseckey_destroy(mctx, &key);
1316 dst_key_free(&dstkey);
1321 * Add 'newkey' to 'keylist' if it's not already there.
1323 * If 'savekeys' is ISC_TRUE, then we need to preserve all
1324 * the keys in the keyset, regardless of whether they have
1325 * metadata indicating they should be deactivated or removed.
1328 addkey(dns_dnsseckeylist_t *keylist, dst_key_t **newkey,
1329 isc_boolean_t savekeys, isc_mem_t *mctx)
1331 dns_dnsseckey_t *key;
1333 /* Skip duplicates */
1334 for (key = ISC_LIST_HEAD(*keylist);
1336 key = ISC_LIST_NEXT(key, link)) {
1337 if (dst_key_id(key->key) == dst_key_id(*newkey) &&
1338 dst_key_alg(key->key) == dst_key_alg(*newkey) &&
1339 dns_name_equal(dst_key_name(key->key),
1340 dst_key_name(*newkey)))
1346 * Found a match. If the old key was only public and the
1347 * new key is private, replace the old one; otherwise
1348 * leave it. But either way, mark the key as having
1349 * been found in the zone.
1351 if (dst_key_isprivate(key->key)) {
1352 dst_key_free(newkey);
1353 } else if (dst_key_isprivate(*newkey)) {
1354 dst_key_free(&key->key);
1358 key->source = dns_keysource_zoneapex;
1362 dns_dnsseckey_create(mctx, newkey, &key);
1363 if (key->legacy || savekeys) {
1364 key->force_publish = ISC_TRUE;
1365 key->force_sign = dst_key_isprivate(key->key);
1367 key->source = dns_keysource_zoneapex;
1368 ISC_LIST_APPEND(*keylist, key, link);
1374 * Mark all keys which signed the DNSKEY/SOA RRsets as "active",
1375 * for future reference.
1378 mark_active_keys(dns_dnsseckeylist_t *keylist, dns_rdataset_t *rrsigs) {
1379 isc_result_t result = ISC_R_SUCCESS;
1380 dns_rdata_t rdata = DNS_RDATA_INIT;
1381 dns_rdataset_t sigs;
1382 dns_dnsseckey_t *key;
1384 REQUIRE(rrsigs != NULL && dns_rdataset_isassociated(rrsigs));
1386 dns_rdataset_init(&sigs);
1387 dns_rdataset_clone(rrsigs, &sigs);
1388 for (key = ISC_LIST_HEAD(*keylist);
1390 key = ISC_LIST_NEXT(key, link)) {
1391 isc_uint16_t keyid, sigid;
1392 dns_secalg_t keyalg, sigalg;
1393 keyid = dst_key_id(key->key);
1394 keyalg = dst_key_alg(key->key);
1396 for (result = dns_rdataset_first(&sigs);
1397 result == ISC_R_SUCCESS;
1398 result = dns_rdataset_next(&sigs)) {
1399 dns_rdata_rrsig_t sig;
1401 dns_rdata_reset(&rdata);
1402 dns_rdataset_current(&sigs, &rdata);
1403 result = dns_rdata_tostruct(&rdata, &sig, NULL);
1404 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1405 sigalg = sig.algorithm;
1407 if (keyid == sigid && keyalg == sigalg) {
1408 key->is_active = ISC_TRUE;
1414 if (result == ISC_R_NOMORE)
1415 result = ISC_R_SUCCESS;
1417 if (dns_rdataset_isassociated(&sigs))
1418 dns_rdataset_disassociate(&sigs);
1423 * Add the contents of a DNSKEY rdataset 'keyset' to 'keylist'.
1426 dns_dnssec_keylistfromrdataset(dns_name_t *origin,
1427 const char *directory, isc_mem_t *mctx,
1428 dns_rdataset_t *keyset, dns_rdataset_t *keysigs,
1429 dns_rdataset_t *soasigs, isc_boolean_t savekeys,
1430 isc_boolean_t public,
1431 dns_dnsseckeylist_t *keylist)
1433 dns_rdataset_t keys;
1434 dns_rdata_t rdata = DNS_RDATA_INIT;
1435 dst_key_t *pubkey = NULL, *privkey = NULL;
1436 isc_result_t result;
1438 REQUIRE(keyset != NULL && dns_rdataset_isassociated(keyset));
1440 dns_rdataset_init(&keys);
1442 dns_rdataset_clone(keyset, &keys);
1443 for (result = dns_rdataset_first(&keys);
1444 result == ISC_R_SUCCESS;
1445 result = dns_rdataset_next(&keys)) {
1446 dns_rdata_reset(&rdata);
1447 dns_rdataset_current(&keys, &rdata);
1448 RETERR(dns_dnssec_keyfromrdata(origin, &rdata, mctx, &pubkey));
1450 if (!is_zone_key(pubkey) ||
1451 (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0)
1454 /* Corrupted .key file? */
1455 if (!dns_name_equal(origin, dst_key_name(pubkey)))
1459 addkey(keylist, &pubkey, savekeys, mctx);
1463 result = dst_key_fromfile(dst_key_name(pubkey),
1465 dst_key_alg(pubkey),
1466 DST_TYPE_PUBLIC|DST_TYPE_PRIVATE,
1467 directory, mctx, &privkey);
1470 * If the key was revoked and the private file
1471 * doesn't exist, maybe it was revoked internally
1472 * by named. Try loading the unrevoked version.
1474 if (result == ISC_R_FILENOTFOUND) {
1476 flags = dst_key_flags(pubkey);
1477 if ((flags & DNS_KEYFLAG_REVOKE) != 0) {
1478 dst_key_setflags(pubkey,
1479 flags & ~DNS_KEYFLAG_REVOKE);
1480 result = dst_key_fromfile(dst_key_name(pubkey),
1482 dst_key_alg(pubkey),
1487 if (result == ISC_R_SUCCESS &&
1488 dst_key_pubcompare(pubkey, privkey,
1490 dst_key_setflags(privkey, flags);
1492 dst_key_setflags(pubkey, flags);
1496 if (result != ISC_R_SUCCESS) {
1497 char keybuf[DNS_NAME_FORMATSIZE];
1498 char algbuf[DNS_SECALG_FORMATSIZE];
1499 dns_name_format(dst_key_name(pubkey), keybuf,
1501 dns_secalg_format(dst_key_alg(pubkey), algbuf,
1503 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
1504 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
1505 "dns_dnssec_keylistfromrdataset: error "
1506 "reading private key file %s/%s/%d: %s",
1507 keybuf, algbuf, dst_key_id(pubkey),
1508 isc_result_totext(result));
1511 if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) {
1512 addkey(keylist, &pubkey, savekeys, mctx);
1517 /* This should never happen. */
1518 if ((dst_key_flags(privkey) & DNS_KEYTYPE_NOAUTH) != 0)
1521 addkey(keylist, &privkey, savekeys, mctx);
1524 dst_key_free(&pubkey);
1525 if (privkey != NULL)
1526 dst_key_free(&privkey);
1529 if (result != ISC_R_NOMORE)
1532 if (keysigs != NULL && dns_rdataset_isassociated(keysigs))
1533 RETERR(mark_active_keys(keylist, keysigs));
1535 if (soasigs != NULL && dns_rdataset_isassociated(soasigs))
1536 RETERR(mark_active_keys(keylist, soasigs));
1538 result = ISC_R_SUCCESS;
1541 if (dns_rdataset_isassociated(&keys))
1542 dns_rdataset_disassociate(&keys);
1544 dst_key_free(&pubkey);
1545 if (privkey != NULL)
1546 dst_key_free(&privkey);
1551 make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize,
1552 dns_rdata_t *target)
1554 isc_result_t result;
1558 isc_buffer_init(&b, buf, bufsize);
1559 result = dst_key_todns(key, &b);
1560 if (result != ISC_R_SUCCESS)
1563 dns_rdata_reset(target);
1564 isc_buffer_usedregion(&b, &r);
1565 dns_rdata_fromregion(target, dst_key_class(key),
1566 dns_rdatatype_dnskey, &r);
1567 return (ISC_R_SUCCESS);
1571 publish_key(dns_diff_t *diff, dns_dnsseckey_t *key, dns_name_t *origin,
1572 dns_ttl_t ttl, isc_mem_t *mctx, isc_boolean_t allzsk,
1573 void (*report)(const char *, ...))
1575 isc_result_t result;
1576 dns_difftuple_t *tuple = NULL;
1577 unsigned char buf[DST_KEY_MAXSIZE];
1578 dns_rdata_t dnskey = DNS_RDATA_INIT;
1581 dns_rdata_reset(&dnskey);
1582 RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey));
1584 dns_secalg_format(dst_key_alg(key->key), alg, sizeof(alg));
1585 report("Fetching %s %d/%s from key %s.",
1586 key->ksk ? (allzsk ? "KSK/ZSK" : "KSK") : "ZSK",
1587 dst_key_id(key->key), alg,
1588 key->source == dns_keysource_user ? "file" : "repository");
1590 if (key->prepublish && ttl > key->prepublish) {
1591 char keystr[DST_KEY_FORMATSIZE];
1594 dst_key_format(key->key, keystr, sizeof(keystr));
1595 report("Key %s: Delaying activation to match the DNSKEY TTL.\n",
1598 isc_stdtime_get(&now);
1599 dst_key_settime(key->key, DST_TIME_ACTIVATE, now + ttl);
1603 RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_ADD, origin, ttl,
1605 dns_diff_appendminimal(diff, &tuple);
1606 result = ISC_R_SUCCESS;
1613 remove_key(dns_diff_t *diff, dns_dnsseckey_t *key, dns_name_t *origin,
1614 dns_ttl_t ttl, isc_mem_t *mctx, const char *reason,
1615 void (*report)(const char *, ...))
1617 isc_result_t result;
1618 dns_difftuple_t *tuple = NULL;
1619 unsigned char buf[DST_KEY_MAXSIZE];
1620 dns_rdata_t dnskey = DNS_RDATA_INIT;
1623 dns_secalg_format(dst_key_alg(key->key), alg, sizeof(alg));
1624 report("Removing %s key %d/%s from DNSKEY RRset.",
1625 reason, dst_key_id(key->key), alg);
1627 RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey));
1628 RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_DEL, origin, ttl, &dnskey,
1630 dns_diff_appendminimal(diff, &tuple);
1631 result = ISC_R_SUCCESS;
1638 * Update 'keys' with information from 'newkeys'.
1640 * If 'removed' is not NULL, any keys that are being removed from
1641 * the zone will be added to the list for post-removal processing.
1644 dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys,
1645 dns_dnsseckeylist_t *removed, dns_name_t *origin,
1646 dns_ttl_t ttl, dns_diff_t *diff, isc_boolean_t allzsk,
1647 isc_mem_t *mctx, void (*report)(const char *, ...))
1649 isc_result_t result;
1650 dns_dnsseckey_t *key, *key1, *key2, *next;
1653 * First, look through the existing key list to find keys
1654 * supplied from the command line which are not in the zone.
1655 * Update the zone to include them.
1657 for (key = ISC_LIST_HEAD(*keys);
1659 key = ISC_LIST_NEXT(key, link)) {
1660 if (key->source == dns_keysource_user &&
1661 (key->hint_publish || key->force_publish)) {
1662 RETERR(publish_key(diff, key, origin, ttl,
1663 mctx, allzsk, report));
1668 * Second, scan the list of newly found keys looking for matches
1669 * with known keys, and update accordingly.
1671 for (key1 = ISC_LIST_HEAD(*newkeys); key1 != NULL; key1 = next) {
1672 isc_boolean_t key_revoked = ISC_FALSE;
1674 next = ISC_LIST_NEXT(key1, link);
1676 for (key2 = ISC_LIST_HEAD(*keys);
1678 key2 = ISC_LIST_NEXT(key2, link)) {
1679 if (dst_key_pubcompare(key1->key, key2->key,
1682 r1 = dst_key_flags(key1->key) &
1684 r2 = dst_key_flags(key2->key) &
1686 key_revoked = ISC_TF(r1 != r2);
1691 /* No match found in keys; add the new key. */
1693 ISC_LIST_UNLINK(*newkeys, key1, link);
1694 ISC_LIST_APPEND(*keys, key1, link);
1696 if (key1->source != dns_keysource_zoneapex &&
1697 (key1->hint_publish || key1->force_publish)) {
1698 RETERR(publish_key(diff, key1, origin, ttl,
1699 mctx, allzsk, report));
1700 if (key1->hint_sign || key1->force_sign)
1701 key1->first_sign = ISC_TRUE;
1707 /* Match found: remove or update it as needed */
1708 if (key1->hint_remove) {
1709 RETERR(remove_key(diff, key2, origin, ttl, mctx,
1710 "expired", report));
1711 ISC_LIST_UNLINK(*keys, key2, link);
1712 if (removed != NULL)
1713 ISC_LIST_APPEND(*removed, key2, link);
1715 dns_dnsseckey_destroy(mctx, &key2);
1716 } else if (key_revoked &&
1717 (dst_key_flags(key1->key) & DNS_KEYFLAG_REVOKE) != 0) {
1720 * A previously valid key has been revoked.
1721 * We need to remove the old version and pull
1724 RETERR(remove_key(diff, key2, origin, ttl, mctx,
1725 "revoked", report));
1726 ISC_LIST_UNLINK(*keys, key2, link);
1727 if (removed != NULL)
1728 ISC_LIST_APPEND(*removed, key2, link);
1730 dns_dnsseckey_destroy(mctx, &key2);
1732 RETERR(publish_key(diff, key1, origin, ttl,
1733 mctx, allzsk, report));
1734 ISC_LIST_UNLINK(*newkeys, key1, link);
1735 ISC_LIST_APPEND(*keys, key1, link);
1738 * XXX: The revoke flag is only defined for trust
1739 * anchors. Setting the flag on a non-KSK is legal,
1740 * but not defined in any RFC. It seems reasonable
1741 * to treat it the same as a KSK: keep it in the
1742 * zone, sign the DNSKEY set with it, but not
1743 * sign other records with it.
1745 key1->ksk = ISC_TRUE;
1748 if (!key2->is_active &&
1749 (key1->hint_sign || key1->force_sign))
1750 key2->first_sign = ISC_TRUE;
1751 key2->hint_sign = key1->hint_sign;
1752 key2->hint_publish = key1->hint_publish;
1756 /* Free any leftover keys in newkeys */
1757 while (!ISC_LIST_EMPTY(*newkeys)) {
1758 key1 = ISC_LIST_HEAD(*newkeys);
1759 ISC_LIST_UNLINK(*newkeys, key1, link);
1760 dns_dnsseckey_destroy(mctx, &key1);
1763 result = ISC_R_SUCCESS;