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 <stdbool.h>
17 
18 #include <isc/mem.h>
19 #include <isc/print.h>
20 #include <isc/refcount.h>
21 #include <isc/rwlock.h>
22 #include <isc/string.h> /* Required for HP/UX (and others?) */
23 #include <isc/util.h>
24 
25 #include <dns/dnssec.h>
26 #include <dns/fixedname.h>
27 #include <dns/keytable.h>
28 #include <dns/rbt.h>
29 #include <dns/rdata.h>
30 #include <dns/rdatalist.h>
31 #include <dns/rdataset.h>
32 #include <dns/rdatastruct.h>
33 #include <dns/result.h>
34 
35 #define KEYTABLE_MAGIC	   ISC_MAGIC('K', 'T', 'b', 'l')
36 #define VALID_KEYTABLE(kt) ISC_MAGIC_VALID(kt, KEYTABLE_MAGIC)
37 
38 #define KEYNODE_MAGIC	  ISC_MAGIC('K', 'N', 'o', 'd')
39 #define VALID_KEYNODE(kn) ISC_MAGIC_VALID(kn, KEYNODE_MAGIC)
40 
41 struct dns_keytable {
42 	/* Unlocked. */
43 	unsigned int magic;
44 	isc_mem_t *mctx;
45 	isc_refcount_t references;
46 	isc_rwlock_t rwlock;
47 	/* Locked by rwlock. */
48 	dns_rbt_t *table;
49 };
50 
51 struct dns_keynode {
52 	unsigned int magic;
53 	isc_mem_t *mctx;
54 	isc_refcount_t refcount;
55 	isc_rwlock_t rwlock;
56 	dns_rdatalist_t *dslist;
57 	dns_rdataset_t dsset;
58 	bool managed;
59 	bool initial;
60 };
61 
62 static dns_keynode_t *
63 new_keynode(dns_rdata_ds_t *ds, dns_keytable_t *keytable, bool managed,
64 	    bool initial);
65 
66 static void
67 keynode_disassociate(dns_rdataset_t *rdataset);
68 static isc_result_t
69 keynode_first(dns_rdataset_t *rdataset);
70 static isc_result_t
71 keynode_next(dns_rdataset_t *rdataset);
72 static void
73 keynode_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata);
74 static void
75 keynode_clone(dns_rdataset_t *source, dns_rdataset_t *target);
76 
77 static dns_rdatasetmethods_t methods = {
78 	keynode_disassociate,
79 	keynode_first,
80 	keynode_next,
81 	keynode_current,
82 	keynode_clone,
83 	NULL,
84 	NULL,
85 	NULL,
86 	NULL,
87 	NULL,
88 	NULL, /* settrust */
89 	NULL, /* expire */
90 	NULL, /* clearprefetch */
91 	NULL,
92 	NULL,
93 	NULL /* addglue */
94 };
95 
96 static void
keynode_attach(dns_keynode_t * source,dns_keynode_t ** target)97 keynode_attach(dns_keynode_t *source, dns_keynode_t **target) {
98 	REQUIRE(VALID_KEYNODE(source));
99 	isc_refcount_increment(&source->refcount);
100 	*target = source;
101 }
102 
103 static void
keynode_detach(isc_mem_t * mctx,dns_keynode_t ** keynodep)104 keynode_detach(isc_mem_t *mctx, dns_keynode_t **keynodep) {
105 	REQUIRE(keynodep != NULL && VALID_KEYNODE(*keynodep));
106 	dns_keynode_t *knode = *keynodep;
107 	*keynodep = NULL;
108 
109 	if (isc_refcount_decrement(&knode->refcount) == 1) {
110 		dns_rdata_t *rdata = NULL;
111 		isc_refcount_destroy(&knode->refcount);
112 		isc_rwlock_destroy(&knode->rwlock);
113 		if (knode->dslist != NULL) {
114 			for (rdata = ISC_LIST_HEAD(knode->dslist->rdata);
115 			     rdata != NULL;
116 			     rdata = ISC_LIST_HEAD(knode->dslist->rdata))
117 			{
118 				ISC_LIST_UNLINK(knode->dslist->rdata, rdata,
119 						link);
120 				isc_mem_put(mctx, rdata->data,
121 					    DNS_DS_BUFFERSIZE);
122 				isc_mem_put(mctx, rdata, sizeof(*rdata));
123 			}
124 
125 			isc_mem_put(mctx, knode->dslist,
126 				    sizeof(*knode->dslist));
127 			knode->dslist = NULL;
128 		}
129 		isc_mem_putanddetach(&knode->mctx, knode,
130 				     sizeof(dns_keynode_t));
131 	}
132 }
133 
134 static void
free_keynode(void * node,void * arg)135 free_keynode(void *node, void *arg) {
136 	dns_keynode_t *keynode = node;
137 	isc_mem_t *mctx = arg;
138 
139 	keynode_detach(mctx, &keynode);
140 }
141 
142 isc_result_t
dns_keytable_create(isc_mem_t * mctx,dns_keytable_t ** keytablep)143 dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep) {
144 	dns_keytable_t *keytable;
145 	isc_result_t result;
146 
147 	/*
148 	 * Create a keytable.
149 	 */
150 
151 	REQUIRE(keytablep != NULL && *keytablep == NULL);
152 
153 	keytable = isc_mem_get(mctx, sizeof(*keytable));
154 
155 	keytable->table = NULL;
156 	result = dns_rbt_create(mctx, free_keynode, mctx, &keytable->table);
157 	if (result != ISC_R_SUCCESS) {
158 		goto cleanup_keytable;
159 	}
160 
161 	isc_rwlock_init(&keytable->rwlock, 0, 0);
162 	isc_refcount_init(&keytable->references, 1);
163 
164 	keytable->mctx = NULL;
165 	isc_mem_attach(mctx, &keytable->mctx);
166 	keytable->magic = KEYTABLE_MAGIC;
167 	*keytablep = keytable;
168 
169 	return (ISC_R_SUCCESS);
170 
171 cleanup_keytable:
172 	isc_mem_putanddetach(&mctx, keytable, sizeof(*keytable));
173 
174 	return (result);
175 }
176 
177 void
dns_keytable_attach(dns_keytable_t * source,dns_keytable_t ** targetp)178 dns_keytable_attach(dns_keytable_t *source, dns_keytable_t **targetp) {
179 	REQUIRE(VALID_KEYTABLE(source));
180 	REQUIRE(targetp != NULL && *targetp == NULL);
181 
182 	isc_refcount_increment(&source->references);
183 
184 	*targetp = source;
185 }
186 
187 void
dns_keytable_detach(dns_keytable_t ** keytablep)188 dns_keytable_detach(dns_keytable_t **keytablep) {
189 	REQUIRE(keytablep != NULL && VALID_KEYTABLE(*keytablep));
190 	dns_keytable_t *keytable = *keytablep;
191 	*keytablep = NULL;
192 
193 	if (isc_refcount_decrement(&keytable->references) == 1) {
194 		isc_refcount_destroy(&keytable->references);
195 		dns_rbt_destroy(&keytable->table);
196 		isc_rwlock_destroy(&keytable->rwlock);
197 		keytable->magic = 0;
198 		isc_mem_putanddetach(&keytable->mctx, keytable,
199 				     sizeof(*keytable));
200 	}
201 }
202 
203 static void
add_ds(dns_keynode_t * knode,dns_rdata_ds_t * ds,isc_mem_t * mctx)204 add_ds(dns_keynode_t *knode, dns_rdata_ds_t *ds, isc_mem_t *mctx) {
205 	isc_result_t result;
206 	dns_rdata_t *dsrdata = NULL, *rdata = NULL;
207 	void *data = NULL;
208 	bool exists = false;
209 	isc_buffer_t b;
210 
211 	dsrdata = isc_mem_get(mctx, sizeof(*dsrdata));
212 	dns_rdata_init(dsrdata);
213 
214 	data = isc_mem_get(mctx, DNS_DS_BUFFERSIZE);
215 	isc_buffer_init(&b, data, DNS_DS_BUFFERSIZE);
216 
217 	result = dns_rdata_fromstruct(dsrdata, dns_rdataclass_in,
218 				      dns_rdatatype_ds, ds, &b);
219 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
220 
221 	RWLOCK(&knode->rwlock, isc_rwlocktype_write);
222 
223 	if (knode->dslist == NULL) {
224 		knode->dslist = isc_mem_get(mctx, sizeof(*knode->dslist));
225 		dns_rdatalist_init(knode->dslist);
226 		knode->dslist->rdclass = dns_rdataclass_in;
227 		knode->dslist->type = dns_rdatatype_ds;
228 
229 		INSIST(knode->dsset.methods == NULL);
230 		knode->dsset.methods = &methods;
231 		knode->dsset.rdclass = knode->dslist->rdclass;
232 		knode->dsset.type = knode->dslist->type;
233 		knode->dsset.covers = knode->dslist->covers;
234 		knode->dsset.ttl = knode->dslist->ttl;
235 		knode->dsset.private1 = knode;
236 		knode->dsset.private2 = NULL;
237 		knode->dsset.private3 = NULL;
238 		knode->dsset.privateuint4 = 0;
239 		knode->dsset.private5 = NULL;
240 		knode->dsset.trust = dns_trust_ultimate;
241 	}
242 
243 	for (rdata = ISC_LIST_HEAD(knode->dslist->rdata); rdata != NULL;
244 	     rdata = ISC_LIST_NEXT(rdata, link))
245 	{
246 		if (dns_rdata_compare(rdata, dsrdata) == 0) {
247 			exists = true;
248 			break;
249 		}
250 	}
251 
252 	if (exists) {
253 		isc_mem_put(mctx, dsrdata->data, DNS_DS_BUFFERSIZE);
254 		isc_mem_put(mctx, dsrdata, sizeof(*dsrdata));
255 	} else {
256 		ISC_LIST_APPEND(knode->dslist->rdata, dsrdata, link);
257 	}
258 
259 	RWUNLOCK(&knode->rwlock, isc_rwlocktype_write);
260 }
261 
262 static isc_result_t
delete_ds(dns_keytable_t * keytable,dns_rbtnode_t * node,dns_rdata_ds_t * ds)263 delete_ds(dns_keytable_t *keytable, dns_rbtnode_t *node, dns_rdata_ds_t *ds) {
264 	dns_keynode_t *knode = node->data;
265 	isc_result_t result;
266 	dns_rdata_t dsrdata = DNS_RDATA_INIT;
267 	dns_rdata_t *rdata = NULL;
268 	unsigned char data[DNS_DS_BUFFERSIZE];
269 	bool found = false;
270 	isc_buffer_t b;
271 
272 	RWLOCK(&knode->rwlock, isc_rwlocktype_read);
273 	if (knode->dslist == NULL) {
274 		RWUNLOCK(&knode->rwlock, isc_rwlocktype_read);
275 		return (ISC_R_SUCCESS);
276 	}
277 
278 	isc_buffer_init(&b, data, DNS_DS_BUFFERSIZE);
279 
280 	result = dns_rdata_fromstruct(&dsrdata, dns_rdataclass_in,
281 				      dns_rdatatype_ds, ds, &b);
282 	if (result != ISC_R_SUCCESS) {
283 		RWUNLOCK(&knode->rwlock, isc_rwlocktype_write);
284 		return (result);
285 	}
286 
287 	for (rdata = ISC_LIST_HEAD(knode->dslist->rdata); rdata != NULL;
288 	     rdata = ISC_LIST_NEXT(rdata, link))
289 	{
290 		if (dns_rdata_compare(rdata, &dsrdata) == 0) {
291 			found = true;
292 			break;
293 		}
294 	}
295 
296 	if (!found) {
297 		RWUNLOCK(&knode->rwlock, isc_rwlocktype_read);
298 		/*
299 		 * The keyname must have matched or we wouldn't be here,
300 		 * so we use DNS_R_PARTIALMATCH instead of ISC_R_NOTFOUND.
301 		 */
302 		return (DNS_R_PARTIALMATCH);
303 	}
304 
305 	/*
306 	 * Replace knode with a new instance without the DS.
307 	 */
308 	node->data = new_keynode(NULL, keytable, knode->managed,
309 				 knode->initial);
310 	for (rdata = ISC_LIST_HEAD(knode->dslist->rdata); rdata != NULL;
311 	     rdata = ISC_LIST_NEXT(rdata, link))
312 	{
313 		if (dns_rdata_compare(rdata, &dsrdata) != 0) {
314 			dns_rdata_ds_t ds0;
315 			result = dns_rdata_tostruct(rdata, &ds0, NULL);
316 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
317 			add_ds(node->data, &ds0, keytable->mctx);
318 		}
319 	}
320 	RWUNLOCK(&knode->rwlock, isc_rwlocktype_read);
321 
322 	keynode_detach(keytable->mctx, &knode);
323 
324 	return (ISC_R_SUCCESS);
325 }
326 
327 /*%
328  * Create a keynode for "ds" (or a null key node if "ds" is NULL), set
329  * "managed" and "initial" as requested and attach the keynode to
330  * to "node" in "keytable".
331  */
332 static dns_keynode_t *
new_keynode(dns_rdata_ds_t * ds,dns_keytable_t * keytable,bool managed,bool initial)333 new_keynode(dns_rdata_ds_t *ds, dns_keytable_t *keytable, bool managed,
334 	    bool initial) {
335 	dns_keynode_t *knode = NULL;
336 
337 	REQUIRE(VALID_KEYTABLE(keytable));
338 	REQUIRE(!initial || managed);
339 
340 	knode = isc_mem_get(keytable->mctx, sizeof(dns_keynode_t));
341 	*knode = (dns_keynode_t){ .magic = KEYNODE_MAGIC };
342 
343 	dns_rdataset_init(&knode->dsset);
344 	isc_refcount_init(&knode->refcount, 1);
345 	isc_rwlock_init(&knode->rwlock, 0, 0);
346 
347 	/*
348 	 * If a DS was supplied, initialize an rdatalist.
349 	 */
350 	if (ds != NULL) {
351 		add_ds(knode, ds, keytable->mctx);
352 	}
353 
354 	isc_mem_attach(keytable->mctx, &knode->mctx);
355 	knode->managed = managed;
356 	knode->initial = initial;
357 
358 	return (knode);
359 }
360 
361 /*%
362  * Add key trust anchor "ds" at "keyname" in "keytable".  If an anchor
363  * already exists at the requested name does not contain "ds", update it.
364  * If "ds" is NULL, add a null key to indicate that "keyname" should be
365  * treated as a secure domain without supplying key data which would allow
366  * the domain to be validated.
367  */
368 static isc_result_t
insert(dns_keytable_t * keytable,bool managed,bool initial,const dns_name_t * keyname,dns_rdata_ds_t * ds)369 insert(dns_keytable_t *keytable, bool managed, bool initial,
370        const dns_name_t *keyname, dns_rdata_ds_t *ds) {
371 	dns_rbtnode_t *node = NULL;
372 	isc_result_t result;
373 
374 	REQUIRE(VALID_KEYTABLE(keytable));
375 
376 	RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
377 
378 	result = dns_rbt_addnode(keytable->table, keyname, &node);
379 	if (result == ISC_R_SUCCESS) {
380 		/*
381 		 * There was no node for "keyname" in "keytable" yet, so one
382 		 * was created.  Create a new key node for the supplied
383 		 * trust anchor (or a null key node if "ds" is NULL)
384 		 * and attach it to the created node.
385 		 */
386 		node->data = new_keynode(ds, keytable, managed, initial);
387 	} else if (result == ISC_R_EXISTS) {
388 		/*
389 		 * A node already exists for "keyname" in "keytable".
390 		 */
391 		if (ds != NULL) {
392 			dns_keynode_t *knode = node->data;
393 			if (knode == NULL) {
394 				node->data = new_keynode(ds, keytable, managed,
395 							 initial);
396 			} else {
397 				add_ds(knode, ds, keytable->mctx);
398 			}
399 		}
400 		result = ISC_R_SUCCESS;
401 	}
402 
403 	RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
404 
405 	return (result);
406 }
407 
408 isc_result_t
dns_keytable_add(dns_keytable_t * keytable,bool managed,bool initial,dns_name_t * name,dns_rdata_ds_t * ds)409 dns_keytable_add(dns_keytable_t *keytable, bool managed, bool initial,
410 		 dns_name_t *name, dns_rdata_ds_t *ds) {
411 	REQUIRE(ds != NULL);
412 	REQUIRE(!initial || managed);
413 
414 	return (insert(keytable, managed, initial, name, ds));
415 }
416 
417 isc_result_t
dns_keytable_marksecure(dns_keytable_t * keytable,const dns_name_t * name)418 dns_keytable_marksecure(dns_keytable_t *keytable, const dns_name_t *name) {
419 	return (insert(keytable, true, false, name, NULL));
420 }
421 
422 isc_result_t
dns_keytable_delete(dns_keytable_t * keytable,const dns_name_t * keyname)423 dns_keytable_delete(dns_keytable_t *keytable, const dns_name_t *keyname) {
424 	isc_result_t result;
425 	dns_rbtnode_t *node = NULL;
426 
427 	REQUIRE(VALID_KEYTABLE(keytable));
428 	REQUIRE(keyname != NULL);
429 
430 	RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
431 	result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
432 				  DNS_RBTFIND_NOOPTIONS, NULL, NULL);
433 	if (result == ISC_R_SUCCESS) {
434 		if (node->data != NULL) {
435 			result = dns_rbt_deletenode(keytable->table, node,
436 						    false);
437 		} else {
438 			result = ISC_R_NOTFOUND;
439 		}
440 	} else if (result == DNS_R_PARTIALMATCH) {
441 		result = ISC_R_NOTFOUND;
442 	}
443 	RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
444 
445 	return (result);
446 }
447 
448 isc_result_t
dns_keytable_deletekey(dns_keytable_t * keytable,const dns_name_t * keyname,dns_rdata_dnskey_t * dnskey)449 dns_keytable_deletekey(dns_keytable_t *keytable, const dns_name_t *keyname,
450 		       dns_rdata_dnskey_t *dnskey) {
451 	isc_result_t result;
452 	dns_rbtnode_t *node = NULL;
453 	dns_keynode_t *knode = NULL;
454 	dns_rdata_t rdata = DNS_RDATA_INIT;
455 	unsigned char data[4096], digest[DNS_DS_BUFFERSIZE];
456 	dns_rdata_ds_t ds;
457 	isc_buffer_t b;
458 
459 	REQUIRE(VALID_KEYTABLE(keytable));
460 	REQUIRE(dnskey != NULL);
461 
462 	isc_buffer_init(&b, data, sizeof(data));
463 	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
464 			     dns_rdatatype_dnskey, dnskey, &b);
465 
466 	RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
467 	result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
468 				  DNS_RBTFIND_NOOPTIONS, NULL, NULL);
469 
470 	if (result == DNS_R_PARTIALMATCH) {
471 		result = ISC_R_NOTFOUND;
472 	}
473 	if (result != ISC_R_SUCCESS) {
474 		goto finish;
475 	}
476 
477 	if (node->data == NULL) {
478 		result = ISC_R_NOTFOUND;
479 		goto finish;
480 	}
481 
482 	knode = node->data;
483 
484 	RWLOCK(&knode->rwlock, isc_rwlocktype_read);
485 	if (knode->dslist == NULL) {
486 		RWUNLOCK(&knode->rwlock, isc_rwlocktype_read);
487 		result = DNS_R_PARTIALMATCH;
488 		goto finish;
489 	}
490 	RWUNLOCK(&knode->rwlock, isc_rwlocktype_read);
491 
492 	result = dns_ds_fromkeyrdata(keyname, &rdata, DNS_DSDIGEST_SHA256,
493 				     digest, &ds);
494 	if (result != ISC_R_SUCCESS) {
495 		goto finish;
496 	}
497 
498 	result = delete_ds(keytable, node, &ds);
499 
500 finish:
501 	RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
502 	return (result);
503 }
504 
505 isc_result_t
dns_keytable_find(dns_keytable_t * keytable,const dns_name_t * keyname,dns_keynode_t ** keynodep)506 dns_keytable_find(dns_keytable_t *keytable, const dns_name_t *keyname,
507 		  dns_keynode_t **keynodep) {
508 	isc_result_t result;
509 	dns_rbtnode_t *node = NULL;
510 
511 	REQUIRE(VALID_KEYTABLE(keytable));
512 	REQUIRE(keyname != NULL);
513 	REQUIRE(keynodep != NULL && *keynodep == NULL);
514 
515 	RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
516 	result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
517 				  DNS_RBTFIND_NOOPTIONS, NULL, NULL);
518 	if (result == ISC_R_SUCCESS) {
519 		if (node->data != NULL) {
520 			keynode_attach(node->data, keynodep);
521 		} else {
522 			result = ISC_R_NOTFOUND;
523 		}
524 	} else if (result == DNS_R_PARTIALMATCH) {
525 		result = ISC_R_NOTFOUND;
526 	}
527 	RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
528 
529 	return (result);
530 }
531 
532 isc_result_t
dns_keytable_finddeepestmatch(dns_keytable_t * keytable,const dns_name_t * name,dns_name_t * foundname)533 dns_keytable_finddeepestmatch(dns_keytable_t *keytable, const dns_name_t *name,
534 			      dns_name_t *foundname) {
535 	isc_result_t result;
536 	void *data;
537 
538 	/*
539 	 * Search for the deepest match in 'keytable'.
540 	 */
541 
542 	REQUIRE(VALID_KEYTABLE(keytable));
543 	REQUIRE(dns_name_isabsolute(name));
544 	REQUIRE(foundname != NULL);
545 
546 	RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
547 
548 	data = NULL;
549 	result = dns_rbt_findname(keytable->table, name, 0, foundname, &data);
550 
551 	if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
552 		result = ISC_R_SUCCESS;
553 	}
554 
555 	RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
556 
557 	return (result);
558 }
559 
560 void
dns_keytable_detachkeynode(dns_keytable_t * keytable,dns_keynode_t ** keynodep)561 dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep) {
562 	/*
563 	 * Give back a keynode found via dns_keytable_findkeynode().
564 	 */
565 
566 	REQUIRE(VALID_KEYTABLE(keytable));
567 	REQUIRE(keynodep != NULL && VALID_KEYNODE(*keynodep));
568 
569 	keynode_detach(keytable->mctx, keynodep);
570 }
571 
572 isc_result_t
dns_keytable_issecuredomain(dns_keytable_t * keytable,const dns_name_t * name,dns_name_t * foundname,bool * wantdnssecp)573 dns_keytable_issecuredomain(dns_keytable_t *keytable, const dns_name_t *name,
574 			    dns_name_t *foundname, bool *wantdnssecp) {
575 	isc_result_t result;
576 	dns_rbtnode_t *node = NULL;
577 
578 	/*
579 	 * Is 'name' at or beneath a trusted key?
580 	 */
581 
582 	REQUIRE(VALID_KEYTABLE(keytable));
583 	REQUIRE(dns_name_isabsolute(name));
584 	REQUIRE(wantdnssecp != NULL);
585 
586 	RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
587 
588 	result = dns_rbt_findnode(keytable->table, name, foundname, &node, NULL,
589 				  DNS_RBTFIND_NOOPTIONS, NULL, NULL);
590 	if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
591 		INSIST(node->data != NULL);
592 		*wantdnssecp = true;
593 		result = ISC_R_SUCCESS;
594 	} else if (result == ISC_R_NOTFOUND) {
595 		*wantdnssecp = false;
596 		result = ISC_R_SUCCESS;
597 	}
598 
599 	RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
600 
601 	return (result);
602 }
603 
604 static isc_result_t
putstr(isc_buffer_t ** b,const char * str)605 putstr(isc_buffer_t **b, const char *str) {
606 	isc_result_t result;
607 
608 	result = isc_buffer_reserve(b, strlen(str));
609 	if (result != ISC_R_SUCCESS) {
610 		return (result);
611 	}
612 
613 	isc_buffer_putstr(*b, str);
614 	return (ISC_R_SUCCESS);
615 }
616 
617 isc_result_t
dns_keytable_dump(dns_keytable_t * keytable,FILE * fp)618 dns_keytable_dump(dns_keytable_t *keytable, FILE *fp) {
619 	isc_result_t result;
620 	isc_buffer_t *text = NULL;
621 
622 	REQUIRE(VALID_KEYTABLE(keytable));
623 	REQUIRE(fp != NULL);
624 
625 	isc_buffer_allocate(keytable->mctx, &text, 4096);
626 
627 	result = dns_keytable_totext(keytable, &text);
628 
629 	if (isc_buffer_usedlength(text) != 0) {
630 		(void)putstr(&text, "\n");
631 	} else if (result == ISC_R_SUCCESS) {
632 		(void)putstr(&text, "none");
633 	} else {
634 		(void)putstr(&text, "could not dump key table: ");
635 		(void)putstr(&text, isc_result_totext(result));
636 	}
637 
638 	fprintf(fp, "%.*s", (int)isc_buffer_usedlength(text),
639 		(char *)isc_buffer_base(text));
640 
641 	isc_buffer_free(&text);
642 	return (result);
643 }
644 
645 static isc_result_t
keynode_dslist_totext(dns_name_t * name,dns_keynode_t * keynode,isc_buffer_t ** text)646 keynode_dslist_totext(dns_name_t *name, dns_keynode_t *keynode,
647 		      isc_buffer_t **text) {
648 	isc_result_t result;
649 	char namebuf[DNS_NAME_FORMATSIZE];
650 	char obuf[DNS_NAME_FORMATSIZE + 200];
651 	dns_rdataset_t dsset;
652 
653 	dns_name_format(name, namebuf, sizeof(namebuf));
654 
655 	dns_rdataset_init(&dsset);
656 	if (!dns_keynode_dsset(keynode, &dsset)) {
657 		return (ISC_R_SUCCESS);
658 	}
659 
660 	for (result = dns_rdataset_first(&dsset); result == ISC_R_SUCCESS;
661 	     result = dns_rdataset_next(&dsset))
662 	{
663 		char algbuf[DNS_SECALG_FORMATSIZE];
664 		dns_rdata_t rdata = DNS_RDATA_INIT;
665 		dns_rdata_ds_t ds;
666 
667 		dns_rdataset_current(&dsset, &rdata);
668 		result = dns_rdata_tostruct(&rdata, &ds, NULL);
669 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
670 
671 		dns_secalg_format(ds.algorithm, algbuf, sizeof(algbuf));
672 
673 		RWLOCK(&keynode->rwlock, isc_rwlocktype_read);
674 		snprintf(obuf, sizeof(obuf), "%s/%s/%d ; %s%s\n", namebuf,
675 			 algbuf, ds.key_tag,
676 			 keynode->initial ? "initializing " : "",
677 			 keynode->managed ? "managed" : "static");
678 		RWUNLOCK(&keynode->rwlock, isc_rwlocktype_read);
679 
680 		result = putstr(text, obuf);
681 		if (result != ISC_R_SUCCESS) {
682 			dns_rdataset_disassociate(&dsset);
683 			return (result);
684 		}
685 	}
686 	dns_rdataset_disassociate(&dsset);
687 
688 	return (ISC_R_SUCCESS);
689 }
690 
691 isc_result_t
dns_keytable_totext(dns_keytable_t * keytable,isc_buffer_t ** text)692 dns_keytable_totext(dns_keytable_t *keytable, isc_buffer_t **text) {
693 	isc_result_t result;
694 	dns_keynode_t *knode;
695 	dns_rbtnode_t *node;
696 	dns_rbtnodechain_t chain;
697 	dns_name_t *foundname, *origin, *fullname;
698 	dns_fixedname_t fixedfoundname, fixedorigin, fixedfullname;
699 
700 	REQUIRE(VALID_KEYTABLE(keytable));
701 	REQUIRE(text != NULL && *text != NULL);
702 
703 	origin = dns_fixedname_initname(&fixedorigin);
704 	fullname = dns_fixedname_initname(&fixedfullname);
705 	foundname = dns_fixedname_initname(&fixedfoundname);
706 
707 	RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
708 	dns_rbtnodechain_init(&chain);
709 	result = dns_rbtnodechain_first(&chain, keytable->table, NULL, NULL);
710 	if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
711 		if (result == ISC_R_NOTFOUND) {
712 			result = ISC_R_SUCCESS;
713 		}
714 		goto cleanup;
715 	}
716 	for (;;) {
717 		dns_rbtnodechain_current(&chain, foundname, origin, &node);
718 
719 		knode = node->data;
720 		if (knode != NULL && knode->dslist != NULL) {
721 			result = dns_name_concatenate(foundname, origin,
722 						      fullname, NULL);
723 			if (result != ISC_R_SUCCESS) {
724 				goto cleanup;
725 			}
726 
727 			result = keynode_dslist_totext(fullname, knode, text);
728 			if (result != ISC_R_SUCCESS) {
729 				goto cleanup;
730 			}
731 		}
732 
733 		result = dns_rbtnodechain_next(&chain, NULL, NULL);
734 		if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
735 			if (result == ISC_R_NOMORE) {
736 				result = ISC_R_SUCCESS;
737 			}
738 			break;
739 		}
740 	}
741 
742 cleanup:
743 	dns_rbtnodechain_invalidate(&chain);
744 	RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
745 	return (result);
746 }
747 
748 isc_result_t
dns_keytable_forall(dns_keytable_t * keytable,void (* func)(dns_keytable_t *,dns_keynode_t *,dns_name_t *,void *),void * arg)749 dns_keytable_forall(dns_keytable_t *keytable,
750 		    void (*func)(dns_keytable_t *, dns_keynode_t *,
751 				 dns_name_t *, void *),
752 		    void *arg) {
753 	isc_result_t result;
754 	dns_rbtnode_t *node;
755 	dns_rbtnodechain_t chain;
756 	dns_fixedname_t fixedfoundname, fixedorigin, fixedfullname;
757 	dns_name_t *foundname, *origin, *fullname;
758 
759 	REQUIRE(VALID_KEYTABLE(keytable));
760 
761 	origin = dns_fixedname_initname(&fixedorigin);
762 	fullname = dns_fixedname_initname(&fixedfullname);
763 	foundname = dns_fixedname_initname(&fixedfoundname);
764 
765 	RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
766 	dns_rbtnodechain_init(&chain);
767 	result = dns_rbtnodechain_first(&chain, keytable->table, NULL, NULL);
768 	if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
769 		if (result == ISC_R_NOTFOUND) {
770 			result = ISC_R_SUCCESS;
771 		}
772 		goto cleanup;
773 	}
774 
775 	for (;;) {
776 		dns_rbtnodechain_current(&chain, foundname, origin, &node);
777 		if (node->data != NULL) {
778 			result = dns_name_concatenate(foundname, origin,
779 						      fullname, NULL);
780 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
781 			(*func)(keytable, node->data, fullname, arg);
782 		}
783 		result = dns_rbtnodechain_next(&chain, NULL, NULL);
784 		if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
785 			if (result == ISC_R_NOMORE) {
786 				result = ISC_R_SUCCESS;
787 			}
788 			break;
789 		}
790 	}
791 
792 cleanup:
793 	dns_rbtnodechain_invalidate(&chain);
794 	RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
795 	return (result);
796 }
797 
798 bool
dns_keynode_dsset(dns_keynode_t * keynode,dns_rdataset_t * rdataset)799 dns_keynode_dsset(dns_keynode_t *keynode, dns_rdataset_t *rdataset) {
800 	bool result;
801 	REQUIRE(VALID_KEYNODE(keynode));
802 	REQUIRE(rdataset == NULL || DNS_RDATASET_VALID(rdataset));
803 
804 	RWLOCK(&keynode->rwlock, isc_rwlocktype_read);
805 	if (keynode->dslist != NULL) {
806 		if (rdataset != NULL) {
807 			keynode_clone(&keynode->dsset, rdataset);
808 		}
809 		result = true;
810 	} else {
811 		result = false;
812 	}
813 	RWUNLOCK(&keynode->rwlock, isc_rwlocktype_read);
814 	return (result);
815 }
816 
817 bool
dns_keynode_managed(dns_keynode_t * keynode)818 dns_keynode_managed(dns_keynode_t *keynode) {
819 	bool managed;
820 
821 	REQUIRE(VALID_KEYNODE(keynode));
822 
823 	RWLOCK(&keynode->rwlock, isc_rwlocktype_read);
824 	managed = keynode->managed;
825 	RWUNLOCK(&keynode->rwlock, isc_rwlocktype_read);
826 
827 	return (managed);
828 }
829 
830 bool
dns_keynode_initial(dns_keynode_t * keynode)831 dns_keynode_initial(dns_keynode_t *keynode) {
832 	bool initial;
833 
834 	REQUIRE(VALID_KEYNODE(keynode));
835 
836 	RWLOCK(&keynode->rwlock, isc_rwlocktype_read);
837 	initial = keynode->initial;
838 	RWUNLOCK(&keynode->rwlock, isc_rwlocktype_read);
839 
840 	return (initial);
841 }
842 
843 void
dns_keynode_trust(dns_keynode_t * keynode)844 dns_keynode_trust(dns_keynode_t *keynode) {
845 	REQUIRE(VALID_KEYNODE(keynode));
846 
847 	RWLOCK(&keynode->rwlock, isc_rwlocktype_write);
848 	keynode->initial = false;
849 	RWUNLOCK(&keynode->rwlock, isc_rwlocktype_write);
850 }
851 
852 static void
keynode_disassociate(dns_rdataset_t * rdataset)853 keynode_disassociate(dns_rdataset_t *rdataset) {
854 	dns_keynode_t *keynode;
855 
856 	REQUIRE(rdataset != NULL);
857 	REQUIRE(rdataset->methods == &methods);
858 
859 	rdataset->methods = NULL;
860 	keynode = rdataset->private1;
861 	rdataset->private1 = NULL;
862 
863 	keynode_detach(keynode->mctx, &keynode);
864 }
865 
866 static isc_result_t
keynode_first(dns_rdataset_t * rdataset)867 keynode_first(dns_rdataset_t *rdataset) {
868 	dns_keynode_t *keynode;
869 
870 	REQUIRE(rdataset != NULL);
871 	REQUIRE(rdataset->methods == &methods);
872 
873 	keynode = rdataset->private1;
874 	RWLOCK(&keynode->rwlock, isc_rwlocktype_read);
875 	rdataset->private2 = ISC_LIST_HEAD(keynode->dslist->rdata);
876 	RWUNLOCK(&keynode->rwlock, isc_rwlocktype_read);
877 
878 	if (rdataset->private2 == NULL) {
879 		return (ISC_R_NOMORE);
880 	}
881 
882 	return (ISC_R_SUCCESS);
883 }
884 
885 static isc_result_t
keynode_next(dns_rdataset_t * rdataset)886 keynode_next(dns_rdataset_t *rdataset) {
887 	dns_keynode_t *keynode;
888 	dns_rdata_t *rdata;
889 
890 	REQUIRE(rdataset != NULL);
891 	REQUIRE(rdataset->methods == &methods);
892 
893 	rdata = rdataset->private2;
894 	if (rdata == NULL) {
895 		return (ISC_R_NOMORE);
896 	}
897 
898 	keynode = rdataset->private1;
899 	RWLOCK(&keynode->rwlock, isc_rwlocktype_read);
900 	rdataset->private2 = ISC_LIST_NEXT(rdata, link);
901 	RWUNLOCK(&keynode->rwlock, isc_rwlocktype_read);
902 
903 	if (rdataset->private2 == NULL) {
904 		return (ISC_R_NOMORE);
905 	}
906 
907 	return (ISC_R_SUCCESS);
908 }
909 
910 static void
keynode_current(dns_rdataset_t * rdataset,dns_rdata_t * rdata)911 keynode_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
912 	dns_rdata_t *list_rdata;
913 
914 	REQUIRE(rdataset != NULL);
915 	REQUIRE(rdataset->methods == &methods);
916 
917 	list_rdata = rdataset->private2;
918 	INSIST(list_rdata != NULL);
919 
920 	dns_rdata_clone(list_rdata, rdata);
921 }
922 
923 static void
keynode_clone(dns_rdataset_t * source,dns_rdataset_t * target)924 keynode_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
925 	dns_keynode_t *keynode;
926 
927 	REQUIRE(source != NULL);
928 	REQUIRE(target != NULL);
929 	REQUIRE(source->methods == &methods);
930 
931 	keynode = source->private1;
932 	isc_refcount_increment(&keynode->refcount);
933 
934 	*target = *source;
935 
936 	/*
937 	 * Reset iterator state.
938 	 */
939 	target->private2 = NULL;
940 }
941