4 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
21 * Id: dnssec.c,v 1.115 2009/11/24 23:48:12 tbox Exp
30 #include <isc/buffer.h>
33 #include <isc/serial.h>
34 #include <isc/string.h>
39 #include <dns/dnssec.h>
40 #include <dns/fixedname.h>
41 #include <dns/keyvalues.h>
42 #include <dns/message.h>
43 #include <dns/rdata.h>
44 #include <dns/rdatalist.h>
45 #include <dns/rdataset.h>
46 #include <dns/rdatastruct.h>
47 #include <dns/result.h>
48 #include <dns/tsig.h> /* for DNS_TSIG_FUDGE */
50 #include <dst/result.h>
52 #define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR)
54 #define RETERR(x) do { \
56 if (result != ISC_R_SUCCESS) \
65 digest_callback(void *arg
, isc_region_t
*data
);
68 rdata_compare_wrapper(const void *rdata1
, const void *rdata2
);
71 rdataset_to_sortedarray(dns_rdataset_t
*set
, isc_mem_t
*mctx
,
72 dns_rdata_t
**rdata
, int *nrdata
);
75 digest_callback(void *arg
, isc_region_t
*data
) {
76 dst_context_t
*ctx
= arg
;
78 return (dst_context_adddata(ctx
, data
));
85 rdata_compare_wrapper(const void *rdata1
, const void *rdata2
) {
86 return (dns_rdata_compare((const dns_rdata_t
*)rdata1
,
87 (const dns_rdata_t
*)rdata2
));
91 * Sort the rdataset into an array.
94 rdataset_to_sortedarray(dns_rdataset_t
*set
, isc_mem_t
*mctx
,
95 dns_rdata_t
**rdata
, int *nrdata
)
100 dns_rdataset_t rdataset
;
102 n
= dns_rdataset_count(set
);
104 data
= isc_mem_get(mctx
, n
* sizeof(dns_rdata_t
));
106 return (ISC_R_NOMEMORY
);
108 dns_rdataset_init(&rdataset
);
109 dns_rdataset_clone(set
, &rdataset
);
110 ret
= dns_rdataset_first(&rdataset
);
111 if (ret
!= ISC_R_SUCCESS
) {
112 dns_rdataset_disassociate(&rdataset
);
113 isc_mem_put(mctx
, data
, n
* sizeof(dns_rdata_t
));
118 * Put them in the array.
121 dns_rdata_init(&data
[i
]);
122 dns_rdataset_current(&rdataset
, &data
[i
++]);
123 } while (dns_rdataset_next(&rdataset
) == ISC_R_SUCCESS
);
128 qsort(data
, n
, sizeof(dns_rdata_t
), rdata_compare_wrapper
);
131 dns_rdataset_disassociate(&rdataset
);
132 return (ISC_R_SUCCESS
);
136 dns_dnssec_keyfromrdata(dns_name_t
*name
, dns_rdata_t
*rdata
, isc_mem_t
*mctx
,
142 INSIST(name
!= NULL
);
143 INSIST(rdata
!= NULL
);
144 INSIST(mctx
!= NULL
);
146 INSIST(*key
== NULL
);
147 REQUIRE(rdata
->type
== dns_rdatatype_key
||
148 rdata
->type
== dns_rdatatype_dnskey
);
150 dns_rdata_toregion(rdata
, &r
);
151 isc_buffer_init(&b
, r
.base
, r
.length
);
152 isc_buffer_add(&b
, r
.length
);
153 return (dst_key_fromdns(name
, rdata
->rdclass
, &b
, mctx
, key
));
157 digest_sig(dst_context_t
*ctx
, dns_rdata_t
*sigrdata
, dns_rdata_rrsig_t
*sig
) {
160 dns_fixedname_t fname
;
162 dns_rdata_toregion(sigrdata
, &r
);
163 INSIST(r
.length
>= 19);
166 ret
= dst_context_adddata(ctx
, &r
);
167 if (ret
!= ISC_R_SUCCESS
)
169 dns_fixedname_init(&fname
);
170 RUNTIME_CHECK(dns_name_downcase(&sig
->signer
,
171 dns_fixedname_name(&fname
), NULL
)
173 dns_name_toregion(dns_fixedname_name(&fname
), &r
);
174 return (dst_context_adddata(ctx
, &r
));
178 dns_dnssec_sign(dns_name_t
*name
, dns_rdataset_t
*set
, dst_key_t
*key
,
179 isc_stdtime_t
*inception
, isc_stdtime_t
*expire
,
180 isc_mem_t
*mctx
, isc_buffer_t
*buffer
, dns_rdata_t
*sigrdata
)
182 dns_rdata_rrsig_t sig
;
183 dns_rdata_t tmpsigrdata
;
186 isc_buffer_t sigbuf
, envbuf
;
188 dst_context_t
*ctx
= NULL
;
190 isc_buffer_t
*databuf
= NULL
;
193 unsigned int sigsize
;
194 dns_fixedname_t fnewname
;
196 REQUIRE(name
!= NULL
);
197 REQUIRE(dns_name_countlabels(name
) <= 255);
198 REQUIRE(set
!= NULL
);
199 REQUIRE(key
!= NULL
);
200 REQUIRE(inception
!= NULL
);
201 REQUIRE(expire
!= NULL
);
202 REQUIRE(mctx
!= NULL
);
203 REQUIRE(sigrdata
!= NULL
);
205 if (*inception
>= *expire
)
206 return (DNS_R_INVALIDTIME
);
209 * Is the key allowed to sign data?
211 flags
= dst_key_flags(key
);
212 if (flags
& DNS_KEYTYPE_NOAUTH
)
213 return (DNS_R_KEYUNAUTHORIZED
);
214 if ((flags
& DNS_KEYFLAG_OWNERMASK
) != DNS_KEYOWNER_ZONE
)
215 return (DNS_R_KEYUNAUTHORIZED
);
218 sig
.common
.rdclass
= set
->rdclass
;
219 sig
.common
.rdtype
= dns_rdatatype_rrsig
;
220 ISC_LINK_INIT(&sig
.common
, link
);
222 dns_name_init(&sig
.signer
, NULL
);
223 dns_name_clone(dst_key_name(key
), &sig
.signer
);
225 sig
.covered
= set
->type
;
226 sig
.algorithm
= dst_key_alg(key
);
227 sig
.labels
= dns_name_countlabels(name
) - 1;
228 if (dns_name_iswildcard(name
))
230 sig
.originalttl
= set
->ttl
;
231 sig
.timesigned
= *inception
;
232 sig
.timeexpire
= *expire
;
233 sig
.keyid
= dst_key_id(key
);
234 ret
= dst_key_sigsize(key
, &sigsize
);
235 if (ret
!= ISC_R_SUCCESS
)
237 sig
.siglen
= sigsize
;
239 * The actual contents of sig.signature are not important yet, since
240 * they're not used in digest_sig().
242 sig
.signature
= isc_mem_get(mctx
, sig
.siglen
);
243 if (sig
.signature
== NULL
)
244 return (ISC_R_NOMEMORY
);
246 ret
= isc_buffer_allocate(mctx
, &databuf
, sigsize
+ 256 + 18);
247 if (ret
!= ISC_R_SUCCESS
)
248 goto cleanup_signature
;
250 dns_rdata_init(&tmpsigrdata
);
251 ret
= dns_rdata_fromstruct(&tmpsigrdata
, sig
.common
.rdclass
,
252 sig
.common
.rdtype
, &sig
, databuf
);
253 if (ret
!= ISC_R_SUCCESS
)
254 goto cleanup_databuf
;
256 ret
= dst_context_create(key
, mctx
, &ctx
);
257 if (ret
!= ISC_R_SUCCESS
)
258 goto cleanup_databuf
;
261 * Digest the SIG rdata.
263 ret
= digest_sig(ctx
, &tmpsigrdata
, &sig
);
264 if (ret
!= ISC_R_SUCCESS
)
265 goto cleanup_context
;
267 dns_fixedname_init(&fnewname
);
268 RUNTIME_CHECK(dns_name_downcase(name
, dns_fixedname_name(&fnewname
),
269 NULL
) == ISC_R_SUCCESS
);
270 dns_name_toregion(dns_fixedname_name(&fnewname
), &r
);
273 * Create an envelope for each rdata: <name|type|class|ttl>.
275 isc_buffer_init(&envbuf
, data
, sizeof(data
));
276 memcpy(data
, r
.base
, r
.length
);
277 isc_buffer_add(&envbuf
, r
.length
);
278 isc_buffer_putuint16(&envbuf
, set
->type
);
279 isc_buffer_putuint16(&envbuf
, set
->rdclass
);
280 isc_buffer_putuint32(&envbuf
, set
->ttl
);
282 ret
= rdataset_to_sortedarray(set
, mctx
, &rdatas
, &nrdatas
);
283 if (ret
!= ISC_R_SUCCESS
)
284 goto cleanup_context
;
285 isc_buffer_usedregion(&envbuf
, &r
);
287 for (i
= 0; i
< nrdatas
; i
++) {
295 if (i
> 0 && dns_rdata_compare(&rdatas
[i
], &rdatas
[i
-1]) == 0)
299 * Digest the envelope.
301 ret
= dst_context_adddata(ctx
, &r
);
302 if (ret
!= ISC_R_SUCCESS
)
306 * Digest the length of the rdata.
308 isc_buffer_init(&lenbuf
, &len
, sizeof(len
));
309 INSIST(rdatas
[i
].length
< 65536);
310 isc_buffer_putuint16(&lenbuf
, (isc_uint16_t
)rdatas
[i
].length
);
311 isc_buffer_usedregion(&lenbuf
, &lenr
);
312 ret
= dst_context_adddata(ctx
, &lenr
);
313 if (ret
!= ISC_R_SUCCESS
)
319 ret
= dns_rdata_digest(&rdatas
[i
], digest_callback
, ctx
);
320 if (ret
!= ISC_R_SUCCESS
)
324 isc_buffer_init(&sigbuf
, sig
.signature
, sig
.siglen
);
325 ret
= dst_context_sign(ctx
, &sigbuf
);
326 if (ret
!= ISC_R_SUCCESS
)
328 isc_buffer_usedregion(&sigbuf
, &r
);
329 if (r
.length
!= sig
.siglen
) {
333 memcpy(sig
.signature
, r
.base
, sig
.siglen
);
335 ret
= dns_rdata_fromstruct(sigrdata
, sig
.common
.rdclass
,
336 sig
.common
.rdtype
, &sig
, buffer
);
339 isc_mem_put(mctx
, rdatas
, nrdatas
* sizeof(dns_rdata_t
));
341 dst_context_destroy(&ctx
);
343 isc_buffer_free(&databuf
);
345 isc_mem_put(mctx
, sig
.signature
, sig
.siglen
);
351 dns_dnssec_verify2(dns_name_t
*name
, dns_rdataset_t
*set
, dst_key_t
*key
,
352 isc_boolean_t ignoretime
, isc_mem_t
*mctx
,
353 dns_rdata_t
*sigrdata
, dns_name_t
*wild
)
355 dns_rdata_rrsig_t sig
;
356 dns_fixedname_t fnewname
;
363 unsigned char data
[300];
364 dst_context_t
*ctx
= NULL
;
368 REQUIRE(name
!= NULL
);
369 REQUIRE(set
!= NULL
);
370 REQUIRE(key
!= NULL
);
371 REQUIRE(mctx
!= NULL
);
372 REQUIRE(sigrdata
!= NULL
&& sigrdata
->type
== dns_rdatatype_rrsig
);
374 ret
= dns_rdata_tostruct(sigrdata
, &sig
, NULL
);
375 if (ret
!= ISC_R_SUCCESS
)
378 if (set
->type
!= sig
.covered
)
379 return (DNS_R_SIGINVALID
);
381 if (isc_serial_lt(sig
.timeexpire
, sig
.timesigned
))
382 return (DNS_R_SIGINVALID
);
385 isc_stdtime_get(&now
);
388 * Is SIG temporally valid?
390 if (isc_serial_lt((isc_uint32_t
)now
, sig
.timesigned
))
391 return (DNS_R_SIGFUTURE
);
392 else if (isc_serial_lt(sig
.timeexpire
, (isc_uint32_t
)now
))
393 return (DNS_R_SIGEXPIRED
);
397 * NS, SOA and DNSSKEY records are signed by their owner.
398 * DS records are signed by the parent.
401 case dns_rdatatype_ns
:
402 case dns_rdatatype_soa
:
403 case dns_rdatatype_dnskey
:
404 if (!dns_name_equal(name
, &sig
.signer
))
405 return (DNS_R_SIGINVALID
);
407 case dns_rdatatype_ds
:
408 if (dns_name_equal(name
, &sig
.signer
))
409 return (DNS_R_SIGINVALID
);
412 if (!dns_name_issubdomain(name
, &sig
.signer
))
413 return (DNS_R_SIGINVALID
);
418 * Is the key allowed to sign data?
420 flags
= dst_key_flags(key
);
421 if (flags
& DNS_KEYTYPE_NOAUTH
)
422 return (DNS_R_KEYUNAUTHORIZED
);
423 if ((flags
& DNS_KEYFLAG_OWNERMASK
) != DNS_KEYOWNER_ZONE
)
424 return (DNS_R_KEYUNAUTHORIZED
);
426 ret
= dst_context_create(key
, mctx
, &ctx
);
427 if (ret
!= ISC_R_SUCCESS
)
431 * Digest the SIG rdata (not including the signature).
433 ret
= digest_sig(ctx
, sigrdata
, &sig
);
434 if (ret
!= ISC_R_SUCCESS
)
435 goto cleanup_context
;
438 * If the name is an expanded wildcard, use the wildcard name.
440 dns_fixedname_init(&fnewname
);
441 labels
= dns_name_countlabels(name
) - 1;
442 RUNTIME_CHECK(dns_name_downcase(name
, dns_fixedname_name(&fnewname
),
443 NULL
) == ISC_R_SUCCESS
);
444 if (labels
- sig
.labels
> 0)
445 dns_name_split(dns_fixedname_name(&fnewname
), sig
.labels
+ 1,
446 NULL
, dns_fixedname_name(&fnewname
));
448 dns_name_toregion(dns_fixedname_name(&fnewname
), &r
);
451 * Create an envelope for each rdata: <name|type|class|ttl>.
453 isc_buffer_init(&envbuf
, data
, sizeof(data
));
454 if (labels
- sig
.labels
> 0) {
455 isc_buffer_putuint8(&envbuf
, 1);
456 isc_buffer_putuint8(&envbuf
, '*');
457 memcpy(data
+ 2, r
.base
, r
.length
);
460 memcpy(data
, r
.base
, r
.length
);
461 isc_buffer_add(&envbuf
, r
.length
);
462 isc_buffer_putuint16(&envbuf
, set
->type
);
463 isc_buffer_putuint16(&envbuf
, set
->rdclass
);
464 isc_buffer_putuint32(&envbuf
, sig
.originalttl
);
466 ret
= rdataset_to_sortedarray(set
, mctx
, &rdatas
, &nrdatas
);
467 if (ret
!= ISC_R_SUCCESS
)
468 goto cleanup_context
;
470 isc_buffer_usedregion(&envbuf
, &r
);
472 for (i
= 0; i
< nrdatas
; i
++) {
480 if (i
> 0 && dns_rdata_compare(&rdatas
[i
], &rdatas
[i
-1]) == 0)
484 * Digest the envelope.
486 ret
= dst_context_adddata(ctx
, &r
);
487 if (ret
!= ISC_R_SUCCESS
)
491 * Digest the rdata length.
493 isc_buffer_init(&lenbuf
, &len
, sizeof(len
));
494 INSIST(rdatas
[i
].length
< 65536);
495 isc_buffer_putuint16(&lenbuf
, (isc_uint16_t
)rdatas
[i
].length
);
496 isc_buffer_usedregion(&lenbuf
, &lenr
);
501 ret
= dst_context_adddata(ctx
, &lenr
);
502 if (ret
!= ISC_R_SUCCESS
)
504 ret
= dns_rdata_digest(&rdatas
[i
], digest_callback
, ctx
);
505 if (ret
!= ISC_R_SUCCESS
)
509 r
.base
= sig
.signature
;
510 r
.length
= sig
.siglen
;
511 ret
= dst_context_verify(ctx
, &r
);
512 if (ret
== DST_R_VERIFYFAILURE
)
513 ret
= DNS_R_SIGINVALID
;
516 isc_mem_put(mctx
, rdatas
, nrdatas
* sizeof(dns_rdata_t
));
518 dst_context_destroy(&ctx
);
520 dns_rdata_freestruct(&sig
);
522 if (ret
== ISC_R_SUCCESS
&& labels
- sig
.labels
> 0) {
524 RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname
,
525 dns_fixedname_name(&fnewname
),
526 wild
, NULL
) == ISC_R_SUCCESS
);
527 ret
= DNS_R_FROMWILDCARD
;
533 dns_dnssec_verify(dns_name_t
*name
, dns_rdataset_t
*set
, dst_key_t
*key
,
534 isc_boolean_t ignoretime
, isc_mem_t
*mctx
,
535 dns_rdata_t
*sigrdata
)
539 result
= dns_dnssec_verify2(name
, set
, key
, ignoretime
, mctx
,
541 if (result
== DNS_R_FROMWILDCARD
)
542 result
= ISC_R_SUCCESS
;
547 key_active(dst_key_t
*key
) {
549 isc_stdtime_t now
, publish
, active
, revoke
, inactive
, delete;
550 isc_boolean_t pubset
= ISC_FALSE
, actset
= ISC_FALSE
;
551 isc_boolean_t revset
= ISC_FALSE
, inactset
= ISC_FALSE
;
552 isc_boolean_t delset
= ISC_FALSE
;
555 /* Is this an old-style key? */
556 result
= dst_key_getprivateformat(key
, &major
, &minor
);
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 isc_stdtime_get(&now
);
567 result
= dst_key_gettime(key
, DST_TIME_PUBLISH
, &publish
);
568 if (result
== ISC_R_SUCCESS
)
571 result
= dst_key_gettime(key
, DST_TIME_ACTIVATE
, &active
);
572 if (result
== ISC_R_SUCCESS
)
575 result
= dst_key_gettime(key
, DST_TIME_REVOKE
, &revoke
);
576 if (result
== ISC_R_SUCCESS
)
579 result
= dst_key_gettime(key
, DST_TIME_INACTIVE
, &inactive
);
580 if (result
== ISC_R_SUCCESS
)
583 result
= dst_key_gettime(key
, DST_TIME_DELETE
, &delete);
584 if (result
== ISC_R_SUCCESS
)
587 if ((inactset
&& inactive
<= now
) || (delset
&& delete <= now
))
590 if (revset
&& revoke
<= now
&& pubset
&& publish
<= now
)
593 if (actset
&& active
<= now
)
599 #define is_zone_key(key) ((dst_key_flags(key) & DNS_KEYFLAG_OWNERMASK) \
600 == DNS_KEYOWNER_ZONE)
603 dns_dnssec_findzonekeys2(dns_db_t
*db
, dns_dbversion_t
*ver
,
604 dns_dbnode_t
*node
, dns_name_t
*name
,
605 const char *directory
, isc_mem_t
*mctx
,
606 unsigned int maxkeys
, dst_key_t
**keys
,
609 dns_rdataset_t rdataset
;
610 dns_rdata_t rdata
= DNS_RDATA_INIT
;
612 dst_key_t
*pubkey
= NULL
;
613 unsigned int count
= 0;
615 REQUIRE(nkeys
!= NULL
);
616 REQUIRE(keys
!= NULL
);
619 dns_rdataset_init(&rdataset
);
620 RETERR(dns_db_findrdataset(db
, node
, ver
, dns_rdatatype_dnskey
, 0, 0,
622 RETERR(dns_rdataset_first(&rdataset
));
623 while (result
== ISC_R_SUCCESS
&& count
< maxkeys
) {
625 dns_rdataset_current(&rdataset
, &rdata
);
626 RETERR(dns_dnssec_keyfromrdata(name
, &rdata
, mctx
, &pubkey
));
627 if (!is_zone_key(pubkey
) ||
628 (dst_key_flags(pubkey
) & DNS_KEYTYPE_NOAUTH
) != 0)
630 /* Corrupted .key file? */
631 if (!dns_name_equal(name
, dst_key_name(pubkey
)))
634 result
= dst_key_fromfile(dst_key_name(pubkey
),
637 DST_TYPE_PUBLIC
|DST_TYPE_PRIVATE
,
642 * If the key was revoked and the private file
643 * doesn't exist, maybe it was revoked internally
644 * by named. Try loading the unrevoked version.
646 if (result
== ISC_R_FILENOTFOUND
) {
648 flags
= dst_key_flags(pubkey
);
649 if ((flags
& DNS_KEYFLAG_REVOKE
) != 0) {
650 dst_key_setflags(pubkey
,
651 flags
& ~DNS_KEYFLAG_REVOKE
);
652 result
= dst_key_fromfile(dst_key_name(pubkey
),
659 if (result
== ISC_R_SUCCESS
&&
660 dst_key_pubcompare(pubkey
, keys
[count
],
662 dst_key_setflags(keys
[count
], flags
);
664 dst_key_setflags(pubkey
, flags
);
668 if (result
== ISC_R_FILENOTFOUND
) {
669 keys
[count
] = pubkey
;
675 if (result
!= ISC_R_SUCCESS
)
679 * If a key is marked inactive, skip it
681 if (!key_active(keys
[count
])) {
682 dst_key_free(&keys
[count
]);
683 keys
[count
] = pubkey
;
689 if ((dst_key_flags(keys
[count
]) & DNS_KEYTYPE_NOAUTH
) != 0) {
690 /* We should never get here. */
691 dst_key_free(&keys
[count
]);
697 dst_key_free(&pubkey
);
698 dns_rdata_reset(&rdata
);
699 result
= dns_rdataset_next(&rdataset
);
701 if (result
!= ISC_R_NOMORE
)
704 result
= ISC_R_NOTFOUND
;
706 result
= ISC_R_SUCCESS
;
709 if (dns_rdataset_isassociated(&rdataset
))
710 dns_rdataset_disassociate(&rdataset
);
712 dst_key_free(&pubkey
);
713 if (result
!= ISC_R_SUCCESS
)
715 dst_key_free(&keys
[--count
]);
721 dns_dnssec_findzonekeys(dns_db_t
*db
, dns_dbversion_t
*ver
,
722 dns_dbnode_t
*node
, dns_name_t
*name
, isc_mem_t
*mctx
,
723 unsigned int maxkeys
, dst_key_t
**keys
,
726 return (dns_dnssec_findzonekeys2(db
, ver
, node
, name
, NULL
, mctx
,
727 maxkeys
, keys
, nkeys
));
731 dns_dnssec_signmessage(dns_message_t
*msg
, dst_key_t
*key
) {
732 dns_rdata_sig_t sig
; /* SIG(0) */
733 unsigned char data
[512];
734 unsigned char header
[DNS_MESSAGE_HEADERLEN
];
735 isc_buffer_t headerbuf
, databuf
, sigbuf
;
736 unsigned int sigsize
;
737 isc_buffer_t
*dynbuf
= NULL
;
739 dns_rdatalist_t
*datalist
;
740 dns_rdataset_t
*dataset
;
743 dst_context_t
*ctx
= NULL
;
746 isc_boolean_t signeedsfree
= ISC_TRUE
;
748 REQUIRE(msg
!= NULL
);
749 REQUIRE(key
!= NULL
);
751 if (is_response(msg
))
752 REQUIRE(msg
->query
.base
!= NULL
);
756 memset(&sig
, 0, sizeof(sig
));
759 sig
.common
.rdclass
= dns_rdataclass_any
;
760 sig
.common
.rdtype
= dns_rdatatype_sig
; /* SIG(0) */
761 ISC_LINK_INIT(&sig
.common
, link
);
764 sig
.algorithm
= dst_key_alg(key
);
765 sig
.labels
= 0; /* the root name */
768 isc_stdtime_get(&now
);
769 sig
.timesigned
= now
- DNS_TSIG_FUDGE
;
770 sig
.timeexpire
= now
+ DNS_TSIG_FUDGE
;
772 sig
.keyid
= dst_key_id(key
);
774 dns_name_init(&sig
.signer
, NULL
);
775 dns_name_clone(dst_key_name(key
), &sig
.signer
);
778 sig
.signature
= NULL
;
780 isc_buffer_init(&databuf
, data
, sizeof(data
));
782 RETERR(dst_context_create(key
, mctx
, &ctx
));
785 * Digest the fields of the SIG - we can cheat and use
786 * dns_rdata_fromstruct. Since siglen is 0, the digested data
787 * is identical to dns format.
789 RETERR(dns_rdata_fromstruct(NULL
, dns_rdataclass_any
,
790 dns_rdatatype_sig
/* SIG(0) */,
792 isc_buffer_usedregion(&databuf
, &r
);
793 RETERR(dst_context_adddata(ctx
, &r
));
796 * If this is a response, digest the query.
798 if (is_response(msg
))
799 RETERR(dst_context_adddata(ctx
, &msg
->query
));
804 isc_buffer_init(&headerbuf
, header
, sizeof(header
));
805 dns_message_renderheader(msg
, &headerbuf
);
806 isc_buffer_usedregion(&headerbuf
, &r
);
807 RETERR(dst_context_adddata(ctx
, &r
));
810 * Digest the remainder of the message.
812 isc_buffer_usedregion(msg
->buffer
, &r
);
813 isc_region_consume(&r
, DNS_MESSAGE_HEADERLEN
);
814 RETERR(dst_context_adddata(ctx
, &r
));
816 RETERR(dst_key_sigsize(key
, &sigsize
));
817 sig
.siglen
= sigsize
;
818 sig
.signature
= (unsigned char *) isc_mem_get(mctx
, sig
.siglen
);
819 if (sig
.signature
== NULL
) {
820 result
= ISC_R_NOMEMORY
;
824 isc_buffer_init(&sigbuf
, sig
.signature
, sig
.siglen
);
825 RETERR(dst_context_sign(ctx
, &sigbuf
));
826 dst_context_destroy(&ctx
);
829 RETERR(dns_message_gettemprdata(msg
, &rdata
));
830 RETERR(isc_buffer_allocate(msg
->mctx
, &dynbuf
, 1024));
831 RETERR(dns_rdata_fromstruct(rdata
, dns_rdataclass_any
,
832 dns_rdatatype_sig
/* SIG(0) */,
835 isc_mem_put(mctx
, sig
.signature
, sig
.siglen
);
836 signeedsfree
= ISC_FALSE
;
838 dns_message_takebuffer(msg
, &dynbuf
);
841 RETERR(dns_message_gettemprdatalist(msg
, &datalist
));
842 datalist
->rdclass
= dns_rdataclass_any
;
843 datalist
->type
= dns_rdatatype_sig
; /* SIG(0) */
844 datalist
->covers
= 0;
846 ISC_LIST_INIT(datalist
->rdata
);
847 ISC_LIST_APPEND(datalist
->rdata
, rdata
, link
);
849 RETERR(dns_message_gettemprdataset(msg
, &dataset
));
850 dns_rdataset_init(dataset
);
851 RUNTIME_CHECK(dns_rdatalist_tordataset(datalist
, dataset
) == ISC_R_SUCCESS
);
854 return (ISC_R_SUCCESS
);
858 isc_buffer_free(&dynbuf
);
860 isc_mem_put(mctx
, sig
.signature
, sig
.siglen
);
862 dst_context_destroy(&ctx
);
868 dns_dnssec_verifymessage(isc_buffer_t
*source
, dns_message_t
*msg
,
871 dns_rdata_sig_t sig
; /* SIG(0) */
872 unsigned char header
[DNS_MESSAGE_HEADERLEN
];
873 dns_rdata_t rdata
= DNS_RDATA_INIT
;
874 isc_region_t r
, source_r
, sig_r
, header_r
;
876 dst_context_t
*ctx
= NULL
;
879 isc_uint16_t addcount
;
880 isc_boolean_t signeedsfree
= ISC_FALSE
;
882 REQUIRE(source
!= NULL
);
883 REQUIRE(msg
!= NULL
);
884 REQUIRE(key
!= NULL
);
888 msg
->verify_attempted
= 1;
890 if (is_response(msg
)) {
891 if (msg
->query
.base
== NULL
)
892 return (DNS_R_UNEXPECTEDTSIG
);
895 isc_buffer_usedregion(source
, &source_r
);
897 RETERR(dns_rdataset_first(msg
->sig0
));
898 dns_rdataset_current(msg
->sig0
, &rdata
);
900 RETERR(dns_rdata_tostruct(&rdata
, &sig
, NULL
));
901 signeedsfree
= ISC_TRUE
;
903 if (sig
.labels
!= 0) {
904 result
= DNS_R_SIGINVALID
;
908 if (isc_serial_lt(sig
.timeexpire
, sig
.timesigned
)) {
909 result
= DNS_R_SIGINVALID
;
910 msg
->sig0status
= dns_tsigerror_badtime
;
914 isc_stdtime_get(&now
);
915 if (isc_serial_lt((isc_uint32_t
)now
, sig
.timesigned
)) {
916 result
= DNS_R_SIGFUTURE
;
917 msg
->sig0status
= dns_tsigerror_badtime
;
920 else if (isc_serial_lt(sig
.timeexpire
, (isc_uint32_t
)now
)) {
921 result
= DNS_R_SIGEXPIRED
;
922 msg
->sig0status
= dns_tsigerror_badtime
;
926 if (!dns_name_equal(dst_key_name(key
), &sig
.signer
)) {
927 result
= DNS_R_SIGINVALID
;
928 msg
->sig0status
= dns_tsigerror_badkey
;
932 RETERR(dst_context_create(key
, mctx
, &ctx
));
935 * Digest the SIG(0) record, except for the signature.
937 dns_rdata_toregion(&rdata
, &r
);
938 r
.length
-= sig
.siglen
;
939 RETERR(dst_context_adddata(ctx
, &r
));
942 * If this is a response, digest the query.
944 if (is_response(msg
))
945 RETERR(dst_context_adddata(ctx
, &msg
->query
));
948 * Extract the header.
950 memcpy(header
, source_r
.base
, DNS_MESSAGE_HEADERLEN
);
953 * Decrement the additional field counter.
955 memcpy(&addcount
, &header
[DNS_MESSAGE_HEADERLEN
- 2], 2);
956 addcount
= htons((isc_uint16_t
)(ntohs(addcount
) - 1));
957 memcpy(&header
[DNS_MESSAGE_HEADERLEN
- 2], &addcount
, 2);
960 * Digest the modified header.
962 header_r
.base
= (unsigned char *) header
;
963 header_r
.length
= DNS_MESSAGE_HEADERLEN
;
964 RETERR(dst_context_adddata(ctx
, &header_r
));
967 * Digest all non-SIG(0) records.
969 r
.base
= source_r
.base
+ DNS_MESSAGE_HEADERLEN
;
970 r
.length
= msg
->sigstart
- DNS_MESSAGE_HEADERLEN
;
971 RETERR(dst_context_adddata(ctx
, &r
));
973 sig_r
.base
= sig
.signature
;
974 sig_r
.length
= sig
.siglen
;
975 result
= dst_context_verify(ctx
, &sig_r
);
976 if (result
!= ISC_R_SUCCESS
) {
977 msg
->sig0status
= dns_tsigerror_badsig
;
981 msg
->verified_sig
= 1;
983 dst_context_destroy(&ctx
);
984 dns_rdata_freestruct(&sig
);
986 return (ISC_R_SUCCESS
);
990 dns_rdata_freestruct(&sig
);
992 dst_context_destroy(&ctx
);
998 * Does this key ('rdata') self sign the rrset ('rdataset')?
1001 dns_dnssec_selfsigns(dns_rdata_t
*rdata
, dns_name_t
*name
,
1002 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
,
1003 isc_boolean_t ignoretime
, isc_mem_t
*mctx
)
1005 dst_key_t
*dstkey
= NULL
;
1006 dns_keytag_t keytag
;
1007 dns_rdata_dnskey_t key
;
1008 dns_rdata_rrsig_t sig
;
1009 dns_rdata_t sigrdata
= DNS_RDATA_INIT
;
1010 isc_result_t result
;
1012 INSIST(rdataset
->type
== dns_rdatatype_key
||
1013 rdataset
->type
== dns_rdatatype_dnskey
);
1014 if (rdataset
->type
== dns_rdatatype_key
) {
1015 INSIST(sigrdataset
->type
== dns_rdatatype_sig
);
1016 INSIST(sigrdataset
->covers
== dns_rdatatype_key
);
1018 INSIST(sigrdataset
->type
== dns_rdatatype_rrsig
);
1019 INSIST(sigrdataset
->covers
== dns_rdatatype_dnskey
);
1022 result
= dns_dnssec_keyfromrdata(name
, rdata
, mctx
, &dstkey
);
1023 if (result
!= ISC_R_SUCCESS
)
1025 result
= dns_rdata_tostruct(rdata
, &key
, NULL
);
1026 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
1028 keytag
= dst_key_id(dstkey
);
1029 for (result
= dns_rdataset_first(sigrdataset
);
1030 result
== ISC_R_SUCCESS
;
1031 result
= dns_rdataset_next(sigrdataset
))
1033 dns_rdata_reset(&sigrdata
);
1034 dns_rdataset_current(sigrdataset
, &sigrdata
);
1035 result
= dns_rdata_tostruct(&sigrdata
, &sig
, NULL
);
1036 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
1038 if (sig
.algorithm
== key
.algorithm
&&
1039 sig
.keyid
== keytag
) {
1040 result
= dns_dnssec_verify2(name
, rdataset
, dstkey
,
1043 if (result
== ISC_R_SUCCESS
) {
1044 dst_key_free(&dstkey
);
1049 dst_key_free(&dstkey
);
1054 dns_dnsseckey_create(isc_mem_t
*mctx
, dst_key_t
**dstkey
,
1055 dns_dnsseckey_t
**dkp
)
1057 isc_result_t result
;
1058 dns_dnsseckey_t
*dk
;
1061 REQUIRE(dkp
!= NULL
&& *dkp
== NULL
);
1062 dk
= isc_mem_get(mctx
, sizeof(dns_dnsseckey_t
));
1064 return (ISC_R_NOMEMORY
);
1068 dk
->force_publish
= ISC_FALSE
;
1069 dk
->force_sign
= ISC_FALSE
;
1070 dk
->hint_publish
= ISC_FALSE
;
1071 dk
->hint_sign
= ISC_FALSE
;
1072 dk
->hint_remove
= ISC_FALSE
;
1073 dk
->first_sign
= ISC_FALSE
;
1074 dk
->is_active
= ISC_FALSE
;
1076 dk
->source
= dns_keysource_unknown
;
1080 dk
->ksk
= ISC_TF((dst_key_flags(dk
->key
) & DNS_KEYFLAG_KSK
) != 0);
1082 /* Is this an old-style key? */
1083 result
= dst_key_getprivateformat(dk
->key
, &major
, &minor
);
1085 /* Smart signing started with key format 1.3 */
1086 dk
->legacy
= ISC_TF(major
== 1 && minor
<= 2);
1088 ISC_LINK_INIT(dk
, link
);
1090 return (ISC_R_SUCCESS
);
1094 dns_dnsseckey_destroy(isc_mem_t
*mctx
, dns_dnsseckey_t
**dkp
) {
1095 dns_dnsseckey_t
*dk
;
1097 REQUIRE(dkp
!= NULL
&& *dkp
!= NULL
);
1099 if (dk
->key
!= NULL
)
1100 dst_key_free(&dk
->key
);
1101 isc_mem_put(mctx
, dk
, sizeof(dns_dnsseckey_t
));
1106 get_hints(dns_dnsseckey_t
*key
) {
1107 isc_result_t result
;
1108 isc_stdtime_t now
, publish
, active
, revoke
, inactive
, delete;
1109 isc_boolean_t pubset
= ISC_FALSE
, actset
= ISC_FALSE
;
1110 isc_boolean_t revset
= ISC_FALSE
, inactset
= ISC_FALSE
;
1111 isc_boolean_t delset
= ISC_FALSE
;
1113 REQUIRE(key
!= NULL
&& key
->key
!= NULL
);
1115 isc_stdtime_get(&now
);
1117 result
= dst_key_gettime(key
->key
, DST_TIME_PUBLISH
, &publish
);
1118 if (result
== ISC_R_SUCCESS
)
1121 result
= dst_key_gettime(key
->key
, DST_TIME_ACTIVATE
, &active
);
1122 if (result
== ISC_R_SUCCESS
)
1125 result
= dst_key_gettime(key
->key
, DST_TIME_REVOKE
, &revoke
);
1126 if (result
== ISC_R_SUCCESS
)
1129 result
= dst_key_gettime(key
->key
, DST_TIME_INACTIVE
, &inactive
);
1130 if (result
== ISC_R_SUCCESS
)
1131 inactset
= ISC_TRUE
;
1133 result
= dst_key_gettime(key
->key
, DST_TIME_DELETE
, &delete);
1134 if (result
== ISC_R_SUCCESS
)
1137 /* Metadata says publish (but possibly not activate) */
1138 if (pubset
&& publish
<= now
)
1139 key
->hint_publish
= ISC_TRUE
;
1141 /* Metadata says activate (so we must also publish) */
1142 if (actset
&& active
<= now
) {
1143 key
->hint_sign
= ISC_TRUE
;
1144 key
->hint_publish
= ISC_TRUE
;
1148 * Activation date is set (maybe in the future), but
1149 * publication date isn't. Most likely the user wants to
1150 * publish now and activate later.
1152 if (actset
&& !pubset
)
1153 key
->hint_publish
= ISC_TRUE
;
1156 * If activation date is in the future, make note of how far off
1158 if (key
->hint_publish
&& actset
&& active
> now
) {
1159 key
->prepublish
= active
- now
;
1163 * Key has been marked inactive: we can continue publishing,
1166 if (key
->hint_publish
&& inactset
&& inactive
<= now
) {
1167 key
->hint_sign
= ISC_FALSE
;
1171 * Metadata says revoke. If the key is published,
1172 * we *have to* sign with it per RFC5011--even if it was
1173 * not active before.
1175 * If it hasn't already been done, we should also revoke it now.
1177 if (key
->hint_publish
&& (revset
&& revoke
<= now
)) {
1179 key
->hint_sign
= ISC_TRUE
;
1180 flags
= dst_key_flags(key
->key
);
1181 if ((flags
& DNS_KEYFLAG_REVOKE
) == 0) {
1182 flags
|= DNS_KEYFLAG_REVOKE
;
1183 dst_key_setflags(key
->key
, flags
);
1188 * Metadata says delete, so don't publish this key or sign with it.
1190 if (delset
&& delete <= now
) {
1191 key
->hint_publish
= ISC_FALSE
;
1192 key
->hint_sign
= ISC_FALSE
;
1193 key
->hint_remove
= ISC_TRUE
;
1198 * Get a list of DNSSEC keys from the key repository
1201 dns_dnssec_findmatchingkeys(dns_name_t
*origin
, const char *directory
,
1202 isc_mem_t
*mctx
, dns_dnsseckeylist_t
*keylist
)
1204 isc_result_t result
= ISC_R_SUCCESS
;
1205 isc_boolean_t dir_open
= ISC_FALSE
;
1206 dns_dnsseckeylist_t list
;
1208 dns_dnsseckey_t
*key
= NULL
;
1209 dst_key_t
*dstkey
= NULL
;
1210 char namebuf
[DNS_NAME_FORMATSIZE
], *p
;
1214 REQUIRE(keylist
!= NULL
);
1215 ISC_LIST_INIT(list
);
1218 isc_buffer_init(&b
, namebuf
, sizeof(namebuf
) - 1);
1219 RETERR(dns_name_totext(origin
, ISC_FALSE
, &b
));
1220 len
= isc_buffer_usedlength(&b
);
1221 namebuf
[len
] = '\0';
1223 if (directory
== NULL
)
1225 RETERR(isc_dir_open(&dir
, directory
));
1226 dir_open
= ISC_TRUE
;
1228 while (isc_dir_read(&dir
) == ISC_R_SUCCESS
) {
1229 if (dir
.entry
.name
[0] == 'K' &&
1230 dir
.entry
.length
> len
+ 1 &&
1231 dir
.entry
.name
[len
+ 1] == '+' &&
1232 strncasecmp(dir
.entry
.name
+ 1, namebuf
, len
) == 0) {
1233 p
= strrchr(dir
.entry
.name
, '.');
1234 if (p
!= NULL
&& strcmp(p
, ".private") != 0)
1238 RETERR(dst_key_fromnamedfile(dir
.entry
.name
, directory
,
1239 DST_TYPE_PUBLIC
| DST_TYPE_PRIVATE
,
1242 RETERR(dns_dnsseckey_create(mctx
, &dstkey
, &key
));
1243 key
->source
= dns_keysource_repository
;
1247 dns_dnsseckey_destroy(mctx
, &key
);
1249 ISC_LIST_APPEND(list
, key
, link
);
1255 if (!ISC_LIST_EMPTY(list
))
1256 ISC_LIST_APPENDLIST(*keylist
, list
, link
);
1258 result
= ISC_R_NOTFOUND
;
1262 isc_dir_close(&dir
);
1263 INSIST(key
== NULL
);
1264 while ((key
= ISC_LIST_HEAD(list
)) != NULL
) {
1265 ISC_LIST_UNLINK(list
, key
, link
);
1266 INSIST(key
->key
!= NULL
);
1267 dst_key_free(&key
->key
);
1268 dns_dnsseckey_destroy(mctx
, &key
);
1271 dst_key_free(&dstkey
);
1276 * Add 'newkey' to 'keylist' if it's not already there.
1278 * If 'savekeys' is ISC_TRUE, then we need to preserve all
1279 * the keys in the keyset, regardless of whether they have
1280 * metadata indicating they should be deactivated or removed.
1283 addkey(dns_dnsseckeylist_t
*keylist
, dst_key_t
**newkey
,
1284 isc_boolean_t savekeys
, isc_mem_t
*mctx
)
1286 dns_dnsseckey_t
*key
;
1288 /* Skip duplicates */
1289 for (key
= ISC_LIST_HEAD(*keylist
);
1291 key
= ISC_LIST_NEXT(key
, link
)) {
1292 if (dst_key_id(key
->key
) == dst_key_id(*newkey
) &&
1293 dst_key_alg(key
->key
) == dst_key_alg(*newkey
) &&
1294 dns_name_equal(dst_key_name(key
->key
),
1295 dst_key_name(*newkey
)))
1301 * Found a match. If the old key was only public and the
1302 * new key is private, replace the old one; otherwise
1303 * leave it. But either way, mark the key as having
1304 * been found in the zone.
1306 if (dst_key_isprivate(key
->key
)) {
1307 dst_key_free(newkey
);
1308 } else if (dst_key_isprivate(*newkey
)) {
1309 dst_key_free(&key
->key
);
1313 key
->source
= dns_keysource_zoneapex
;
1317 dns_dnsseckey_create(mctx
, newkey
, &key
);
1318 if (key
->legacy
|| savekeys
) {
1319 key
->force_publish
= ISC_TRUE
;
1320 key
->force_sign
= dst_key_isprivate(key
->key
);
1322 key
->source
= dns_keysource_zoneapex
;
1323 ISC_LIST_APPEND(*keylist
, key
, link
);
1329 * Mark all keys which signed the DNSKEY/SOA RRsets as "active",
1330 * for future reference.
1333 mark_active_keys(dns_dnsseckeylist_t
*keylist
, dns_rdataset_t
*rrsigs
) {
1334 isc_result_t result
= ISC_R_SUCCESS
;
1335 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1336 dns_rdataset_t sigs
;
1337 dns_dnsseckey_t
*key
;
1339 REQUIRE(rrsigs
!= NULL
&& dns_rdataset_isassociated(rrsigs
));
1341 dns_rdataset_init(&sigs
);
1342 dns_rdataset_clone(rrsigs
, &sigs
);
1343 for (key
= ISC_LIST_HEAD(*keylist
);
1345 key
= ISC_LIST_NEXT(key
, link
)) {
1346 isc_uint16_t keyid
, sigid
;
1347 dns_secalg_t keyalg
, sigalg
;
1348 keyid
= dst_key_id(key
->key
);
1349 keyalg
= dst_key_alg(key
->key
);
1351 for (result
= dns_rdataset_first(&sigs
);
1352 result
== ISC_R_SUCCESS
;
1353 result
= dns_rdataset_next(&sigs
)) {
1354 dns_rdata_rrsig_t sig
;
1356 dns_rdata_reset(&rdata
);
1357 dns_rdataset_current(&sigs
, &rdata
);
1358 result
= dns_rdata_tostruct(&rdata
, &sig
, NULL
);
1359 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
1360 sigalg
= sig
.algorithm
;
1362 if (keyid
== sigid
&& keyalg
== sigalg
) {
1363 key
->is_active
= ISC_TRUE
;
1369 if (result
== ISC_R_NOMORE
)
1370 result
= ISC_R_SUCCESS
;
1372 if (dns_rdataset_isassociated(&sigs
))
1373 dns_rdataset_disassociate(&sigs
);
1378 * Add the contents of a DNSKEY rdataset 'keyset' to 'keylist'.
1381 dns_dnssec_keylistfromrdataset(dns_name_t
*origin
,
1382 const char *directory
, isc_mem_t
*mctx
,
1383 dns_rdataset_t
*keyset
, dns_rdataset_t
*keysigs
,
1384 dns_rdataset_t
*soasigs
, isc_boolean_t savekeys
,
1385 isc_boolean_t
public,
1386 dns_dnsseckeylist_t
*keylist
)
1388 dns_rdataset_t keys
;
1389 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1390 dst_key_t
*pubkey
= NULL
, *privkey
= NULL
;
1391 isc_result_t result
;
1393 REQUIRE(keyset
!= NULL
&& dns_rdataset_isassociated(keyset
));
1395 dns_rdataset_init(&keys
);
1397 dns_rdataset_clone(keyset
, &keys
);
1398 for (result
= dns_rdataset_first(&keys
);
1399 result
== ISC_R_SUCCESS
;
1400 result
= dns_rdataset_next(&keys
)) {
1401 dns_rdata_reset(&rdata
);
1402 dns_rdataset_current(&keys
, &rdata
);
1403 RETERR(dns_dnssec_keyfromrdata(origin
, &rdata
, mctx
, &pubkey
));
1405 if (!is_zone_key(pubkey
) ||
1406 (dst_key_flags(pubkey
) & DNS_KEYTYPE_NOAUTH
) != 0)
1409 /* Corrupted .key file? */
1410 if (!dns_name_equal(origin
, dst_key_name(pubkey
)))
1414 addkey(keylist
, &pubkey
, savekeys
, mctx
);
1418 result
= dst_key_fromfile(dst_key_name(pubkey
),
1420 dst_key_alg(pubkey
),
1421 DST_TYPE_PUBLIC
|DST_TYPE_PRIVATE
,
1422 directory
, mctx
, &privkey
);
1423 if (result
== ISC_R_FILENOTFOUND
) {
1424 addkey(keylist
, &pubkey
, savekeys
, mctx
);
1429 /* This should never happen. */
1430 if ((dst_key_flags(privkey
) & DNS_KEYTYPE_NOAUTH
) != 0)
1433 addkey(keylist
, &privkey
, savekeys
, mctx
);
1436 dst_key_free(&pubkey
);
1437 if (privkey
!= NULL
)
1438 dst_key_free(&privkey
);
1441 if (result
!= ISC_R_NOMORE
)
1444 if (keysigs
!= NULL
&& dns_rdataset_isassociated(keysigs
))
1445 RETERR(mark_active_keys(keylist
, keysigs
));
1447 if (soasigs
!= NULL
&& dns_rdataset_isassociated(soasigs
))
1448 RETERR(mark_active_keys(keylist
, soasigs
));
1450 result
= ISC_R_SUCCESS
;
1453 if (dns_rdataset_isassociated(&keys
))
1454 dns_rdataset_disassociate(&keys
);
1456 dst_key_free(&pubkey
);
1457 if (privkey
!= NULL
)
1458 dst_key_free(&privkey
);
1463 make_dnskey(dst_key_t
*key
, unsigned char *buf
, int bufsize
,
1464 dns_rdata_t
*target
)
1466 isc_result_t result
;
1470 isc_buffer_init(&b
, buf
, bufsize
);
1471 result
= dst_key_todns(key
, &b
);
1472 if (result
!= ISC_R_SUCCESS
)
1475 dns_rdata_reset(target
);
1476 isc_buffer_usedregion(&b
, &r
);
1477 dns_rdata_fromregion(target
, dst_key_class(key
),
1478 dns_rdatatype_dnskey
, &r
);
1479 return (ISC_R_SUCCESS
);
1483 publish_key(dns_diff_t
*diff
, dns_dnsseckey_t
*key
, dns_name_t
*origin
,
1484 dns_ttl_t ttl
, isc_mem_t
*mctx
, isc_boolean_t allzsk
,
1485 void (*report
)(const char *, ...))
1487 isc_result_t result
;
1488 dns_difftuple_t
*tuple
= NULL
;
1489 unsigned char buf
[DST_KEY_MAXSIZE
];
1490 dns_rdata_t dnskey
= DNS_RDATA_INIT
;
1493 dns_rdata_reset(&dnskey
);
1494 RETERR(make_dnskey(key
->key
, buf
, sizeof(buf
), &dnskey
));
1496 dns_secalg_format(dst_key_alg(key
->key
), alg
, sizeof(alg
));
1497 report("Fetching %s %d/%s from key %s.",
1498 key
->ksk
? (allzsk
? "KSK/ZSK" : "KSK") : "ZSK",
1499 dst_key_id(key
->key
), alg
,
1500 key
->source
== dns_keysource_user
? "file" : "repository");
1502 if (key
->prepublish
&& ttl
> key
->prepublish
) {
1503 char keystr
[DST_KEY_FORMATSIZE
];
1506 dst_key_format(key
->key
, keystr
, sizeof(keystr
));
1507 report("Key %s: Delaying activation to match the DNSKEY TTL.\n",
1510 isc_stdtime_get(&now
);
1511 dst_key_settime(key
->key
, DST_TIME_ACTIVATE
, now
+ ttl
);
1515 RETERR(dns_difftuple_create(mctx
, DNS_DIFFOP_ADD
, origin
, ttl
,
1517 dns_diff_appendminimal(diff
, &tuple
);
1518 result
= ISC_R_SUCCESS
;
1525 remove_key(dns_diff_t
*diff
, dns_dnsseckey_t
*key
, dns_name_t
*origin
,
1526 dns_ttl_t ttl
, isc_mem_t
*mctx
, const char *reason
,
1527 void (*report
)(const char *, ...))
1529 isc_result_t result
;
1530 dns_difftuple_t
*tuple
= NULL
;
1531 unsigned char buf
[DST_KEY_MAXSIZE
];
1532 dns_rdata_t dnskey
= DNS_RDATA_INIT
;
1535 dns_secalg_format(dst_key_alg(key
->key
), alg
, sizeof(alg
));
1536 report("Removing %s key %d/%s from DNSKEY RRset.",
1537 reason
, dst_key_id(key
->key
), alg
);
1539 RETERR(make_dnskey(key
->key
, buf
, sizeof(buf
), &dnskey
));
1540 RETERR(dns_difftuple_create(mctx
, DNS_DIFFOP_DEL
, origin
, ttl
, &dnskey
,
1542 dns_diff_appendminimal(diff
, &tuple
);
1543 result
= ISC_R_SUCCESS
;
1550 * Update 'keys' with information from 'newkeys'.
1552 * If 'removed' is not NULL, any keys that are being removed from
1553 * the zone will be added to the list for post-removal processing.
1556 dns_dnssec_updatekeys(dns_dnsseckeylist_t
*keys
, dns_dnsseckeylist_t
*newkeys
,
1557 dns_dnsseckeylist_t
*removed
, dns_name_t
*origin
,
1558 dns_ttl_t ttl
, dns_diff_t
*diff
, isc_boolean_t allzsk
,
1559 isc_mem_t
*mctx
, void (*report
)(const char *, ...))
1561 isc_result_t result
;
1562 dns_dnsseckey_t
*key
, *key1
, *key2
, *next
;
1565 * First, look through the existing key list to find keys
1566 * supplied from the command line which are not in the zone.
1567 * Update the zone to include them.
1569 for (key
= ISC_LIST_HEAD(*keys
);
1571 key
= ISC_LIST_NEXT(key
, link
)) {
1572 if (key
->source
== dns_keysource_user
&&
1573 (key
->hint_publish
|| key
->force_publish
)) {
1574 RETERR(publish_key(diff
, key
, origin
, ttl
,
1575 mctx
, allzsk
, report
));
1580 * Second, scan the list of newly found keys looking for matches
1581 * with known keys, and update accordingly.
1583 for (key1
= ISC_LIST_HEAD(*newkeys
); key1
!= NULL
; key1
= next
) {
1584 isc_boolean_t key_revoked
= ISC_FALSE
;
1586 next
= ISC_LIST_NEXT(key1
, link
);
1588 for (key2
= ISC_LIST_HEAD(*keys
);
1590 key2
= ISC_LIST_NEXT(key2
, link
)) {
1591 if (dst_key_pubcompare(key1
->key
, key2
->key
,
1594 r1
= dst_key_flags(key1
->key
) &
1596 r2
= dst_key_flags(key2
->key
) &
1598 key_revoked
= ISC_TF(r1
!= r2
);
1603 /* No match found in keys; add the new key. */
1605 dns_dnsseckey_t
*next
;
1607 next
= ISC_LIST_NEXT(key1
, link
);
1608 ISC_LIST_UNLINK(*newkeys
, key1
, link
);
1609 ISC_LIST_APPEND(*keys
, key1
, link
);
1611 if (key1
->source
!= dns_keysource_zoneapex
&&
1612 (key1
->hint_publish
|| key1
->force_publish
)) {
1613 RETERR(publish_key(diff
, key1
, origin
, ttl
,
1614 mctx
, allzsk
, report
));
1615 if (key1
->hint_sign
|| key1
->force_sign
)
1616 key1
->first_sign
= ISC_TRUE
;
1622 /* Match found: remove or update it as needed */
1623 if (key1
->hint_remove
) {
1624 RETERR(remove_key(diff
, key2
, origin
, ttl
, mctx
,
1625 "expired", report
));
1626 ISC_LIST_UNLINK(*keys
, key2
, link
);
1627 if (removed
!= NULL
)
1628 ISC_LIST_APPEND(*removed
, key2
, link
);
1630 dns_dnsseckey_destroy(mctx
, &key2
);
1631 } else if (key_revoked
&&
1632 (dst_key_flags(key1
->key
) & DNS_KEYFLAG_REVOKE
) != 0) {
1635 * A previously valid key has been revoked.
1636 * We need to remove the old version and pull
1639 RETERR(remove_key(diff
, key2
, origin
, ttl
, mctx
,
1640 "revoked", report
));
1641 ISC_LIST_UNLINK(*keys
, key2
, link
);
1642 if (removed
!= NULL
)
1643 ISC_LIST_APPEND(*removed
, key2
, link
);
1645 dns_dnsseckey_destroy(mctx
, &key2
);
1647 RETERR(publish_key(diff
, key1
, origin
, ttl
,
1648 mctx
, allzsk
, report
));
1649 ISC_LIST_UNLINK(*newkeys
, key1
, link
);
1650 ISC_LIST_APPEND(*keys
, key1
, link
);
1653 * XXX: The revoke flag is only defined for trust
1654 * anchors. Setting the flag on a non-KSK is legal,
1655 * but not defined in any RFC. It seems reasonable
1656 * to treat it the same as a KSK: keep it in the
1657 * zone, sign the DNSKEY set with it, but not
1658 * sign other records with it.
1660 key1
->ksk
= ISC_TRUE
;
1663 if (!key2
->is_active
&&
1664 (key1
->hint_sign
|| key1
->force_sign
))
1665 key2
->first_sign
= ISC_TRUE
;
1666 key2
->hint_sign
= key1
->hint_sign
;
1667 key2
->hint_publish
= key1
->hint_publish
;
1671 /* Free any leftover keys in newkeys */
1672 while (!ISC_LIST_EMPTY(*newkeys
)) {
1673 key1
= ISC_LIST_HEAD(*newkeys
);
1674 ISC_LIST_UNLINK(*newkeys
, key1
, link
);
1675 dns_dnsseckey_destroy(mctx
, &key1
);
1678 result
= ISC_R_SUCCESS
;