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