1135446Strhodes/* 2254897Serwin * Copyright (C) 2004, 2005, 2007, 2009, 2010, 2013 Internet Systems Consortium, Inc. ("ISC") 3135446Strhodes * Copyright (C) 2000, 2001 Internet Software Consortium. 4135446Strhodes * 5193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any 6135446Strhodes * purpose with or without fee is hereby granted, provided that the above 7135446Strhodes * copyright notice and this permission notice appear in all copies. 8135446Strhodes * 9135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10135446Strhodes * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11135446Strhodes * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12135446Strhodes * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13135446Strhodes * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14135446Strhodes * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15135446Strhodes * PERFORMANCE OF THIS SOFTWARE. 16135446Strhodes */ 17135446Strhodes 18234010Sdougb/* $Id: keytable.c,v 1.41 2010/06/25 23:46:51 tbox Exp $ */ 19135446Strhodes 20170222Sdougb/*! \file */ 21170222Sdougb 22135446Strhodes#include <config.h> 23135446Strhodes 24135446Strhodes#include <isc/mem.h> 25135446Strhodes#include <isc/rwlock.h> 26135446Strhodes#include <isc/string.h> /* Required for HP/UX (and others?) */ 27135446Strhodes#include <isc/util.h> 28135446Strhodes 29135446Strhodes#include <dns/keytable.h> 30135446Strhodes#include <dns/fixedname.h> 31135446Strhodes#include <dns/rbt.h> 32135446Strhodes#include <dns/result.h> 33135446Strhodes 34135446Strhodesstatic void 35135446Strhodesfree_keynode(void *node, void *arg) { 36135446Strhodes dns_keynode_t *keynode = node; 37135446Strhodes isc_mem_t *mctx = arg; 38135446Strhodes 39224092Sdougb dns_keynode_detachall(mctx, &keynode); 40135446Strhodes} 41135446Strhodes 42135446Strhodesisc_result_t 43135446Strhodesdns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep) { 44135446Strhodes dns_keytable_t *keytable; 45135446Strhodes isc_result_t result; 46135446Strhodes 47135446Strhodes /* 48135446Strhodes * Create a keytable. 49135446Strhodes */ 50135446Strhodes 51135446Strhodes REQUIRE(keytablep != NULL && *keytablep == NULL); 52135446Strhodes 53135446Strhodes keytable = isc_mem_get(mctx, sizeof(*keytable)); 54135446Strhodes if (keytable == NULL) 55135446Strhodes return (ISC_R_NOMEMORY); 56135446Strhodes 57135446Strhodes keytable->table = NULL; 58135446Strhodes result = dns_rbt_create(mctx, free_keynode, mctx, &keytable->table); 59135446Strhodes if (result != ISC_R_SUCCESS) 60135446Strhodes goto cleanup_keytable; 61135446Strhodes 62135446Strhodes result = isc_mutex_init(&keytable->lock); 63170222Sdougb if (result != ISC_R_SUCCESS) 64135446Strhodes goto cleanup_rbt; 65135446Strhodes 66135446Strhodes result = isc_rwlock_init(&keytable->rwlock, 0, 0); 67170222Sdougb if (result != ISC_R_SUCCESS) 68135446Strhodes goto cleanup_lock; 69135446Strhodes 70254897Serwin keytable->mctx = NULL; 71254897Serwin isc_mem_attach(mctx, &keytable->mctx); 72135446Strhodes keytable->active_nodes = 0; 73135446Strhodes keytable->references = 1; 74135446Strhodes keytable->magic = KEYTABLE_MAGIC; 75135446Strhodes *keytablep = keytable; 76135446Strhodes 77135446Strhodes return (ISC_R_SUCCESS); 78135446Strhodes 79135446Strhodes cleanup_lock: 80135446Strhodes DESTROYLOCK(&keytable->lock); 81135446Strhodes 82135446Strhodes cleanup_rbt: 83135446Strhodes dns_rbt_destroy(&keytable->table); 84135446Strhodes 85135446Strhodes cleanup_keytable: 86254897Serwin isc_mem_putanddetach(&mctx, keytable, sizeof(*keytable)); 87135446Strhodes 88135446Strhodes return (result); 89135446Strhodes} 90135446Strhodes 91135446Strhodesvoid 92135446Strhodesdns_keytable_attach(dns_keytable_t *source, dns_keytable_t **targetp) { 93135446Strhodes 94135446Strhodes /* 95135446Strhodes * Attach *targetp to source. 96135446Strhodes */ 97135446Strhodes 98135446Strhodes REQUIRE(VALID_KEYTABLE(source)); 99135446Strhodes REQUIRE(targetp != NULL && *targetp == NULL); 100135446Strhodes 101135446Strhodes RWLOCK(&source->rwlock, isc_rwlocktype_write); 102135446Strhodes 103135446Strhodes INSIST(source->references > 0); 104135446Strhodes source->references++; 105135446Strhodes INSIST(source->references != 0); 106135446Strhodes 107135446Strhodes RWUNLOCK(&source->rwlock, isc_rwlocktype_write); 108135446Strhodes 109135446Strhodes *targetp = source; 110135446Strhodes} 111135446Strhodes 112135446Strhodesvoid 113135446Strhodesdns_keytable_detach(dns_keytable_t **keytablep) { 114135446Strhodes isc_boolean_t destroy = ISC_FALSE; 115135446Strhodes dns_keytable_t *keytable; 116135446Strhodes 117135446Strhodes /* 118135446Strhodes * Detach *keytablep from its keytable. 119135446Strhodes */ 120135446Strhodes 121135446Strhodes REQUIRE(keytablep != NULL && VALID_KEYTABLE(*keytablep)); 122135446Strhodes 123135446Strhodes keytable = *keytablep; 124135446Strhodes 125135446Strhodes RWLOCK(&keytable->rwlock, isc_rwlocktype_write); 126135446Strhodes 127135446Strhodes INSIST(keytable->references > 0); 128135446Strhodes keytable->references--; 129135446Strhodes LOCK(&keytable->lock); 130135446Strhodes if (keytable->references == 0 && keytable->active_nodes == 0) 131135446Strhodes destroy = ISC_TRUE; 132135446Strhodes UNLOCK(&keytable->lock); 133135446Strhodes 134135446Strhodes RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write); 135135446Strhodes 136135446Strhodes if (destroy) { 137135446Strhodes dns_rbt_destroy(&keytable->table); 138135446Strhodes isc_rwlock_destroy(&keytable->rwlock); 139135446Strhodes DESTROYLOCK(&keytable->lock); 140135446Strhodes keytable->magic = 0; 141254897Serwin isc_mem_putanddetach(&keytable->mctx, 142254897Serwin keytable, sizeof(*keytable)); 143135446Strhodes } 144135446Strhodes 145135446Strhodes *keytablep = NULL; 146135446Strhodes} 147135446Strhodes 148224092Sdougbstatic isc_result_t 149224092Sdougbinsert(dns_keytable_t *keytable, isc_boolean_t managed, 150224092Sdougb dns_name_t *keyname, dst_key_t **keyp) 151224092Sdougb{ 152135446Strhodes isc_result_t result; 153224092Sdougb dns_keynode_t *knode = NULL; 154135446Strhodes dns_rbtnode_t *node; 155135446Strhodes 156224092Sdougb REQUIRE(keyp == NULL || *keyp != NULL); 157135446Strhodes REQUIRE(VALID_KEYTABLE(keytable)); 158135446Strhodes 159224092Sdougb result = dns_keynode_create(keytable->mctx, &knode); 160224092Sdougb if (result != ISC_R_SUCCESS) 161224092Sdougb return (result); 162135446Strhodes 163224092Sdougb knode->managed = managed; 164135446Strhodes 165135446Strhodes RWLOCK(&keytable->rwlock, isc_rwlocktype_write); 166135446Strhodes 167135446Strhodes node = NULL; 168135446Strhodes result = dns_rbt_addnode(keytable->table, keyname, &node); 169135446Strhodes 170224092Sdougb if (keyp != NULL) { 171224092Sdougb if (result == ISC_R_EXISTS) { 172224092Sdougb /* Key already in table? */ 173224092Sdougb dns_keynode_t *k; 174224092Sdougb for (k = node->data; k != NULL; k = k->next) { 175224092Sdougb if (k->key == NULL) { 176224092Sdougb k->key = *keyp; 177224092Sdougb break; 178224092Sdougb } 179224092Sdougb if (dst_key_compare(k->key, *keyp) == ISC_TRUE) 180224092Sdougb break; 181224092Sdougb } 182224092Sdougb 183224092Sdougb if (k == NULL) 184224092Sdougb result = ISC_R_SUCCESS; 185224092Sdougb else 186224092Sdougb dst_key_free(keyp); 187224092Sdougb } 188224092Sdougb 189224092Sdougb if (result == ISC_R_SUCCESS) { 190224092Sdougb knode->key = *keyp; 191224092Sdougb knode->next = node->data; 192224092Sdougb *keyp = NULL; 193224092Sdougb } 194224092Sdougb } 195224092Sdougb 196224092Sdougb if (result == ISC_R_SUCCESS) { 197135446Strhodes node->data = knode; 198135446Strhodes knode = NULL; 199135446Strhodes } 200135446Strhodes 201224092Sdougb /* Key was already there? That's the same as a success */ 202224092Sdougb if (result == ISC_R_EXISTS) 203224092Sdougb result = ISC_R_SUCCESS; 204224092Sdougb 205135446Strhodes RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write); 206135446Strhodes 207135446Strhodes if (knode != NULL) 208224092Sdougb dns_keynode_detach(keytable->mctx, &knode); 209135446Strhodes 210135446Strhodes return (result); 211135446Strhodes} 212135446Strhodes 213135446Strhodesisc_result_t 214224092Sdougbdns_keytable_add(dns_keytable_t *keytable, isc_boolean_t managed, 215224092Sdougb dst_key_t **keyp) 216224092Sdougb{ 217224092Sdougb REQUIRE(keyp != NULL && *keyp != NULL); 218224092Sdougb return (insert(keytable, managed, dst_key_name(*keyp), keyp)); 219224092Sdougb} 220224092Sdougb 221224092Sdougbisc_result_t 222224092Sdougbdns_keytable_marksecure(dns_keytable_t *keytable, dns_name_t *name) { 223224092Sdougb return (insert(keytable, ISC_TRUE, name, NULL)); 224224092Sdougb} 225224092Sdougb 226224092Sdougbisc_result_t 227224092Sdougbdns_keytable_delete(dns_keytable_t *keytable, dns_name_t *keyname) { 228224092Sdougb isc_result_t result; 229224092Sdougb dns_rbtnode_t *node = NULL; 230224092Sdougb 231224092Sdougb REQUIRE(VALID_KEYTABLE(keytable)); 232224092Sdougb REQUIRE(keyname != NULL); 233224092Sdougb 234224092Sdougb RWLOCK(&keytable->rwlock, isc_rwlocktype_write); 235224092Sdougb result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL, 236224092Sdougb DNS_RBTFIND_NOOPTIONS, NULL, NULL); 237224092Sdougb if (result == ISC_R_SUCCESS) { 238224092Sdougb if (node->data != NULL) 239224092Sdougb result = dns_rbt_deletenode(keytable->table, 240224092Sdougb node, ISC_FALSE); 241224092Sdougb else 242224092Sdougb result = ISC_R_NOTFOUND; 243224092Sdougb } else if (result == DNS_R_PARTIALMATCH) 244224092Sdougb result = ISC_R_NOTFOUND; 245224092Sdougb RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write); 246224092Sdougb 247224092Sdougb return (result); 248224092Sdougb} 249224092Sdougb 250224092Sdougbisc_result_t 251224092Sdougbdns_keytable_deletekeynode(dns_keytable_t *keytable, dst_key_t *dstkey) { 252224092Sdougb isc_result_t result; 253224092Sdougb dns_name_t *keyname; 254224092Sdougb dns_rbtnode_t *node = NULL; 255224092Sdougb dns_keynode_t *knode = NULL, **kprev = NULL; 256224092Sdougb 257224092Sdougb REQUIRE(VALID_KEYTABLE(keytable)); 258224092Sdougb REQUIRE(dstkey != NULL); 259224092Sdougb 260224092Sdougb keyname = dst_key_name(dstkey); 261224092Sdougb 262224092Sdougb RWLOCK(&keytable->rwlock, isc_rwlocktype_write); 263224092Sdougb result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL, 264224092Sdougb DNS_RBTFIND_NOOPTIONS, NULL, NULL); 265224092Sdougb 266224092Sdougb if (result == DNS_R_PARTIALMATCH) 267224092Sdougb result = ISC_R_NOTFOUND; 268224092Sdougb if (result != ISC_R_SUCCESS) 269224092Sdougb goto finish; 270224092Sdougb 271224092Sdougb if (node->data == NULL) { 272224092Sdougb result = ISC_R_NOTFOUND; 273224092Sdougb goto finish; 274224092Sdougb } 275224092Sdougb 276224092Sdougb knode = node->data; 277224092Sdougb if (knode->next == NULL && 278224092Sdougb (knode->key == NULL || 279224092Sdougb dst_key_compare(knode->key, dstkey) == ISC_TRUE)) { 280224092Sdougb result = dns_rbt_deletenode(keytable->table, node, ISC_FALSE); 281224092Sdougb goto finish; 282224092Sdougb } 283224092Sdougb 284224092Sdougb kprev = (dns_keynode_t **) &node->data; 285224092Sdougb while (knode != NULL) { 286224092Sdougb if (dst_key_compare(knode->key, dstkey) == ISC_TRUE) 287224092Sdougb break; 288224092Sdougb kprev = &knode->next; 289224092Sdougb knode = knode->next; 290224092Sdougb } 291224092Sdougb 292224092Sdougb if (knode != NULL) { 293224092Sdougb if (knode->key != NULL) 294224092Sdougb dst_key_free(&knode->key); 295224092Sdougb /* 296224092Sdougb * This is equivalent to: 297224092Sdougb * dns_keynode_attach(knode->next, &tmp); 298224092Sdougb * dns_keynode_detach(kprev); 299224092Sdougb * dns_keynode_attach(tmp, &kprev); 300224092Sdougb * dns_keynode_detach(&tmp); 301224092Sdougb */ 302224092Sdougb *kprev = knode->next; 303224092Sdougb knode->next = NULL; 304224092Sdougb dns_keynode_detach(keytable->mctx, &knode); 305224092Sdougb } else 306224092Sdougb result = DNS_R_PARTIALMATCH; 307224092Sdougb finish: 308224092Sdougb RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write); 309224092Sdougb return (result); 310224092Sdougb} 311224092Sdougb 312224092Sdougbisc_result_t 313224092Sdougbdns_keytable_find(dns_keytable_t *keytable, dns_name_t *keyname, 314224092Sdougb dns_keynode_t **keynodep) 315224092Sdougb{ 316224092Sdougb isc_result_t result; 317224092Sdougb dns_rbtnode_t *node = NULL; 318224092Sdougb 319224092Sdougb REQUIRE(VALID_KEYTABLE(keytable)); 320224092Sdougb REQUIRE(keyname != NULL); 321224092Sdougb REQUIRE(keynodep != NULL && *keynodep == NULL); 322224092Sdougb 323224092Sdougb RWLOCK(&keytable->rwlock, isc_rwlocktype_read); 324224092Sdougb result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL, 325224092Sdougb DNS_RBTFIND_NOOPTIONS, NULL, NULL); 326224092Sdougb if (result == ISC_R_SUCCESS) { 327224092Sdougb if (node->data != NULL) { 328224092Sdougb LOCK(&keytable->lock); 329224092Sdougb keytable->active_nodes++; 330224092Sdougb UNLOCK(&keytable->lock); 331224092Sdougb dns_keynode_attach(node->data, keynodep); 332224092Sdougb } else 333224092Sdougb result = ISC_R_NOTFOUND; 334224092Sdougb } else if (result == DNS_R_PARTIALMATCH) 335224092Sdougb result = ISC_R_NOTFOUND; 336224092Sdougb RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read); 337224092Sdougb 338224092Sdougb return (result); 339224092Sdougb} 340224092Sdougb 341224092Sdougbisc_result_t 342224092Sdougbdns_keytable_nextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode, 343224092Sdougb dns_keynode_t **nextnodep) 344224092Sdougb{ 345224092Sdougb /* 346224092Sdougb * Return the next key after 'keynode', regardless of 347224092Sdougb * properties. 348224092Sdougb */ 349224092Sdougb 350224092Sdougb REQUIRE(VALID_KEYTABLE(keytable)); 351224092Sdougb REQUIRE(VALID_KEYNODE(keynode)); 352224092Sdougb REQUIRE(nextnodep != NULL && *nextnodep == NULL); 353224092Sdougb 354224092Sdougb if (keynode->next == NULL) 355224092Sdougb return (ISC_R_NOTFOUND); 356224092Sdougb 357224092Sdougb dns_keynode_attach(keynode->next, nextnodep); 358224092Sdougb LOCK(&keytable->lock); 359224092Sdougb keytable->active_nodes++; 360224092Sdougb UNLOCK(&keytable->lock); 361224092Sdougb 362224092Sdougb return (ISC_R_SUCCESS); 363224092Sdougb} 364224092Sdougb 365224092Sdougbisc_result_t 366135446Strhodesdns_keytable_findkeynode(dns_keytable_t *keytable, dns_name_t *name, 367135446Strhodes dns_secalg_t algorithm, dns_keytag_t tag, 368135446Strhodes dns_keynode_t **keynodep) 369135446Strhodes{ 370135446Strhodes isc_result_t result; 371135446Strhodes dns_keynode_t *knode; 372135446Strhodes void *data; 373135446Strhodes 374135446Strhodes /* 375135446Strhodes * Search for a key named 'name', matching 'algorithm' and 'tag' in 376135446Strhodes * 'keytable'. 377135446Strhodes */ 378135446Strhodes 379135446Strhodes REQUIRE(VALID_KEYTABLE(keytable)); 380135446Strhodes REQUIRE(dns_name_isabsolute(name)); 381135446Strhodes REQUIRE(keynodep != NULL && *keynodep == NULL); 382135446Strhodes 383135446Strhodes RWLOCK(&keytable->rwlock, isc_rwlocktype_read); 384135446Strhodes 385165071Sdougb /* 386165071Sdougb * Note we don't want the DNS_R_PARTIALMATCH from dns_rbt_findname() 387165071Sdougb * as that indicates that 'name' was not found. 388165071Sdougb * 389165071Sdougb * DNS_R_PARTIALMATCH indicates that the name was found but we 390165071Sdougb * didn't get a match on algorithm and key id arguments. 391165071Sdougb */ 392135446Strhodes knode = NULL; 393135446Strhodes data = NULL; 394135446Strhodes result = dns_rbt_findname(keytable->table, name, 0, NULL, &data); 395135446Strhodes 396135446Strhodes if (result == ISC_R_SUCCESS) { 397135446Strhodes INSIST(data != NULL); 398135446Strhodes for (knode = data; knode != NULL; knode = knode->next) { 399224092Sdougb if (knode->key == NULL) { 400224092Sdougb knode = NULL; 401224092Sdougb break; 402224092Sdougb } 403135446Strhodes if (algorithm == dst_key_alg(knode->key) 404135446Strhodes && tag == dst_key_id(knode->key)) 405135446Strhodes break; 406135446Strhodes } 407135446Strhodes if (knode != NULL) { 408135446Strhodes LOCK(&keytable->lock); 409135446Strhodes keytable->active_nodes++; 410135446Strhodes UNLOCK(&keytable->lock); 411224092Sdougb dns_keynode_attach(knode, keynodep); 412135446Strhodes } else 413165071Sdougb result = DNS_R_PARTIALMATCH; 414135446Strhodes } else if (result == DNS_R_PARTIALMATCH) 415135446Strhodes result = ISC_R_NOTFOUND; 416135446Strhodes 417135446Strhodes RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read); 418135446Strhodes 419135446Strhodes return (result); 420135446Strhodes} 421135446Strhodes 422135446Strhodesisc_result_t 423135446Strhodesdns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode, 424135446Strhodes dns_keynode_t **nextnodep) 425135446Strhodes{ 426135446Strhodes isc_result_t result; 427135446Strhodes dns_keynode_t *knode; 428135446Strhodes 429135446Strhodes /* 430135446Strhodes * Search for the next key with the same properties as 'keynode' in 431135446Strhodes * 'keytable'. 432135446Strhodes */ 433135446Strhodes 434135446Strhodes REQUIRE(VALID_KEYTABLE(keytable)); 435135446Strhodes REQUIRE(VALID_KEYNODE(keynode)); 436135446Strhodes REQUIRE(nextnodep != NULL && *nextnodep == NULL); 437135446Strhodes 438135446Strhodes for (knode = keynode->next; knode != NULL; knode = knode->next) { 439224092Sdougb if (knode->key == NULL) { 440224092Sdougb knode = NULL; 441224092Sdougb break; 442224092Sdougb } 443135446Strhodes if (dst_key_alg(keynode->key) == dst_key_alg(knode->key) && 444135446Strhodes dst_key_id(keynode->key) == dst_key_id(knode->key)) 445135446Strhodes break; 446135446Strhodes } 447135446Strhodes if (knode != NULL) { 448135446Strhodes LOCK(&keytable->lock); 449135446Strhodes keytable->active_nodes++; 450135446Strhodes UNLOCK(&keytable->lock); 451135446Strhodes result = ISC_R_SUCCESS; 452224092Sdougb dns_keynode_attach(knode, nextnodep); 453135446Strhodes } else 454135446Strhodes result = ISC_R_NOTFOUND; 455135446Strhodes 456135446Strhodes return (result); 457135446Strhodes} 458135446Strhodes 459135446Strhodesisc_result_t 460135446Strhodesdns_keytable_finddeepestmatch(dns_keytable_t *keytable, dns_name_t *name, 461135446Strhodes dns_name_t *foundname) 462135446Strhodes{ 463135446Strhodes isc_result_t result; 464135446Strhodes void *data; 465135446Strhodes 466135446Strhodes /* 467135446Strhodes * Search for the deepest match in 'keytable'. 468135446Strhodes */ 469135446Strhodes 470135446Strhodes REQUIRE(VALID_KEYTABLE(keytable)); 471135446Strhodes REQUIRE(dns_name_isabsolute(name)); 472135446Strhodes REQUIRE(foundname != NULL); 473135446Strhodes 474135446Strhodes RWLOCK(&keytable->rwlock, isc_rwlocktype_read); 475135446Strhodes 476135446Strhodes data = NULL; 477135446Strhodes result = dns_rbt_findname(keytable->table, name, 0, foundname, &data); 478135446Strhodes 479135446Strhodes if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) 480135446Strhodes result = ISC_R_SUCCESS; 481135446Strhodes 482135446Strhodes RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read); 483135446Strhodes 484135446Strhodes return (result); 485135446Strhodes} 486135446Strhodes 487135446Strhodesvoid 488224092Sdougbdns_keytable_attachkeynode(dns_keytable_t *keytable, dns_keynode_t *source, 489224092Sdougb dns_keynode_t **target) 490224092Sdougb{ 491224092Sdougb /* 492224092Sdougb * Give back a keynode found via dns_keytable_findkeynode(). 493224092Sdougb */ 494224092Sdougb 495224092Sdougb REQUIRE(VALID_KEYTABLE(keytable)); 496224092Sdougb REQUIRE(VALID_KEYNODE(source)); 497224092Sdougb REQUIRE(target != NULL && *target == NULL); 498224092Sdougb 499224092Sdougb LOCK(&keytable->lock); 500224092Sdougb keytable->active_nodes++; 501224092Sdougb UNLOCK(&keytable->lock); 502224092Sdougb 503224092Sdougb dns_keynode_attach(source, target); 504224092Sdougb} 505224092Sdougb 506224092Sdougbvoid 507135446Strhodesdns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep) 508135446Strhodes{ 509135446Strhodes /* 510135446Strhodes * Give back a keynode found via dns_keytable_findkeynode(). 511135446Strhodes */ 512135446Strhodes 513135446Strhodes REQUIRE(VALID_KEYTABLE(keytable)); 514135446Strhodes REQUIRE(keynodep != NULL && VALID_KEYNODE(*keynodep)); 515135446Strhodes 516135446Strhodes LOCK(&keytable->lock); 517135446Strhodes INSIST(keytable->active_nodes > 0); 518135446Strhodes keytable->active_nodes--; 519135446Strhodes UNLOCK(&keytable->lock); 520135446Strhodes 521224092Sdougb dns_keynode_detach(keytable->mctx, keynodep); 522135446Strhodes} 523135446Strhodes 524135446Strhodesisc_result_t 525135446Strhodesdns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name, 526135446Strhodes isc_boolean_t *wantdnssecp) 527135446Strhodes{ 528135446Strhodes isc_result_t result; 529135446Strhodes void *data; 530135446Strhodes 531135446Strhodes /* 532135446Strhodes * Is 'name' at or beneath a trusted key? 533135446Strhodes */ 534135446Strhodes 535135446Strhodes REQUIRE(VALID_KEYTABLE(keytable)); 536135446Strhodes REQUIRE(dns_name_isabsolute(name)); 537135446Strhodes REQUIRE(wantdnssecp != NULL); 538135446Strhodes 539135446Strhodes RWLOCK(&keytable->rwlock, isc_rwlocktype_read); 540135446Strhodes 541135446Strhodes data = NULL; 542135446Strhodes result = dns_rbt_findname(keytable->table, name, 0, NULL, &data); 543135446Strhodes 544135446Strhodes if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) { 545135446Strhodes INSIST(data != NULL); 546135446Strhodes *wantdnssecp = ISC_TRUE; 547135446Strhodes result = ISC_R_SUCCESS; 548135446Strhodes } else if (result == ISC_R_NOTFOUND) { 549135446Strhodes *wantdnssecp = ISC_FALSE; 550135446Strhodes result = ISC_R_SUCCESS; 551135446Strhodes } 552135446Strhodes 553135446Strhodes RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read); 554135446Strhodes 555135446Strhodes return (result); 556135446Strhodes} 557135446Strhodes 558224092Sdougbisc_result_t 559224092Sdougbdns_keytable_dump(dns_keytable_t *keytable, FILE *fp) 560224092Sdougb{ 561224092Sdougb isc_result_t result; 562224092Sdougb dns_keynode_t *knode; 563224092Sdougb dns_rbtnode_t *node; 564224092Sdougb dns_rbtnodechain_t chain; 565224092Sdougb 566224092Sdougb REQUIRE(VALID_KEYTABLE(keytable)); 567224092Sdougb 568224092Sdougb RWLOCK(&keytable->rwlock, isc_rwlocktype_read); 569224092Sdougb dns_rbtnodechain_init(&chain, keytable->mctx); 570224092Sdougb result = dns_rbtnodechain_first(&chain, keytable->table, NULL, NULL); 571224092Sdougb if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) 572224092Sdougb goto cleanup; 573224092Sdougb for (;;) { 574224092Sdougb char pbuf[DST_KEY_FORMATSIZE]; 575224092Sdougb 576224092Sdougb dns_rbtnodechain_current(&chain, NULL, NULL, &node); 577224092Sdougb for (knode = node->data; knode != NULL; knode = knode->next) { 578224092Sdougb dst_key_format(knode->key, pbuf, sizeof(pbuf)); 579224092Sdougb fprintf(fp, "%s ; %s\n", pbuf, 580224092Sdougb knode->managed ? "managed" : "trusted"); 581224092Sdougb } 582224092Sdougb result = dns_rbtnodechain_next(&chain, NULL, NULL); 583224092Sdougb if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { 584224092Sdougb if (result == ISC_R_NOMORE) 585224092Sdougb result = ISC_R_SUCCESS; 586224092Sdougb break; 587224092Sdougb } 588224092Sdougb } 589224092Sdougb 590224092Sdougb cleanup: 591224092Sdougb dns_rbtnodechain_invalidate(&chain); 592224092Sdougb RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read); 593224092Sdougb return (result); 594224092Sdougb} 595224092Sdougb 596135446Strhodesdst_key_t * 597135446Strhodesdns_keynode_key(dns_keynode_t *keynode) { 598135446Strhodes 599135446Strhodes /* 600135446Strhodes * Get the DST key associated with keynode. 601135446Strhodes */ 602135446Strhodes 603135446Strhodes REQUIRE(VALID_KEYNODE(keynode)); 604135446Strhodes 605135446Strhodes return (keynode->key); 606135446Strhodes} 607224092Sdougb 608224092Sdougbisc_boolean_t 609224092Sdougbdns_keynode_managed(dns_keynode_t *keynode) { 610224092Sdougb /* 611224092Sdougb * Is this a managed key? 612224092Sdougb */ 613224092Sdougb REQUIRE(VALID_KEYNODE(keynode)); 614224092Sdougb 615224092Sdougb return (keynode->managed); 616224092Sdougb} 617224092Sdougb 618224092Sdougbisc_result_t 619224092Sdougbdns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target) { 620224092Sdougb isc_result_t result; 621224092Sdougb dns_keynode_t *knode = NULL; 622224092Sdougb 623224092Sdougb REQUIRE(target != NULL && *target == NULL); 624224092Sdougb 625224092Sdougb knode = isc_mem_get(mctx, sizeof(dns_keynode_t)); 626224092Sdougb if (knode == NULL) 627224092Sdougb return (ISC_R_NOMEMORY); 628224092Sdougb 629224092Sdougb knode->magic = KEYNODE_MAGIC; 630224092Sdougb knode->managed = ISC_FALSE; 631224092Sdougb knode->key = NULL; 632224092Sdougb knode->next = NULL; 633224092Sdougb 634224092Sdougb result = isc_refcount_init(&knode->refcount, 1); 635224092Sdougb if (result != ISC_R_SUCCESS) 636224092Sdougb return (result); 637224092Sdougb 638224092Sdougb *target = knode; 639224092Sdougb return (ISC_R_SUCCESS); 640224092Sdougb} 641224092Sdougb 642224092Sdougbvoid 643224092Sdougbdns_keynode_attach(dns_keynode_t *source, dns_keynode_t **target) { 644224092Sdougb REQUIRE(VALID_KEYNODE(source)); 645224092Sdougb isc_refcount_increment(&source->refcount, NULL); 646224092Sdougb *target = source; 647224092Sdougb} 648224092Sdougb 649224092Sdougbvoid 650224092Sdougbdns_keynode_detach(isc_mem_t *mctx, dns_keynode_t **keynode) { 651224092Sdougb unsigned int refs; 652224092Sdougb dns_keynode_t *node = *keynode; 653224092Sdougb REQUIRE(VALID_KEYNODE(node)); 654224092Sdougb isc_refcount_decrement(&node->refcount, &refs); 655224092Sdougb if (refs == 0) { 656224092Sdougb if (node->key != NULL) 657224092Sdougb dst_key_free(&node->key); 658224092Sdougb isc_refcount_destroy(&node->refcount); 659224092Sdougb isc_mem_put(mctx, node, sizeof(dns_keynode_t)); 660224092Sdougb } 661224092Sdougb *keynode = NULL; 662224092Sdougb} 663224092Sdougb 664224092Sdougbvoid 665224092Sdougbdns_keynode_detachall(isc_mem_t *mctx, dns_keynode_t **keynode) { 666224092Sdougb dns_keynode_t *next = NULL, *node = *keynode; 667224092Sdougb REQUIRE(VALID_KEYNODE(node)); 668224092Sdougb while (node != NULL) { 669224092Sdougb next = node->next; 670224092Sdougb dns_keynode_detach(mctx, &node); 671224092Sdougb node = next; 672224092Sdougb } 673224092Sdougb *keynode = NULL; 674224092Sdougb} 675