00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023
00024 #include <isc/mem.h>
00025 #include <isc/print.h>
00026 #include <isc/rwlock.h>
00027 #include <isc/string.h>
00028 #include <isc/util.h>
00029
00030 #include <dns/keytable.h>
00031 #include <dns/fixedname.h>
00032 #include <dns/rbt.h>
00033 #include <dns/result.h>
00034
00035 static void
00036 free_keynode(void *node, void *arg) {
00037 dns_keynode_t *keynode = node;
00038 isc_mem_t *mctx = arg;
00039
00040 dns_keynode_detachall(mctx, &keynode);
00041 }
00042
00043 isc_result_t
00044 dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep) {
00045 dns_keytable_t *keytable;
00046 isc_result_t result;
00047
00048
00049
00050
00051
00052 REQUIRE(keytablep != NULL && *keytablep == NULL);
00053
00054 keytable = isc_mem_get(mctx, sizeof(*keytable));
00055 if (keytable == NULL)
00056 return (ISC_R_NOMEMORY);
00057
00058 keytable->table = NULL;
00059 result = dns_rbt_create(mctx, free_keynode, mctx, &keytable->table);
00060 if (result != ISC_R_SUCCESS)
00061 goto cleanup_keytable;
00062
00063 result = isc_mutex_init(&keytable->lock);
00064 if (result != ISC_R_SUCCESS)
00065 goto cleanup_rbt;
00066
00067 result = isc_rwlock_init(&keytable->rwlock, 0, 0);
00068 if (result != ISC_R_SUCCESS)
00069 goto cleanup_lock;
00070
00071 keytable->mctx = NULL;
00072 isc_mem_attach(mctx, &keytable->mctx);
00073 keytable->active_nodes = 0;
00074 keytable->references = 1;
00075 keytable->magic = KEYTABLE_MAGIC;
00076 *keytablep = keytable;
00077
00078 return (ISC_R_SUCCESS);
00079
00080 cleanup_lock:
00081 DESTROYLOCK(&keytable->lock);
00082
00083 cleanup_rbt:
00084 dns_rbt_destroy(&keytable->table);
00085
00086 cleanup_keytable:
00087 isc_mem_putanddetach(&mctx, keytable, sizeof(*keytable));
00088
00089 return (result);
00090 }
00091
00092 void
00093 dns_keytable_attach(dns_keytable_t *source, dns_keytable_t **targetp) {
00094
00095
00096
00097
00098
00099 REQUIRE(VALID_KEYTABLE(source));
00100 REQUIRE(targetp != NULL && *targetp == NULL);
00101
00102 RWLOCK(&source->rwlock, isc_rwlocktype_write);
00103
00104 INSIST(source->references > 0);
00105 source->references++;
00106 INSIST(source->references != 0);
00107
00108 RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
00109
00110 *targetp = source;
00111 }
00112
00113 void
00114 dns_keytable_detach(dns_keytable_t **keytablep) {
00115 isc_boolean_t destroy = ISC_FALSE;
00116 dns_keytable_t *keytable;
00117
00118
00119
00120
00121
00122 REQUIRE(keytablep != NULL && VALID_KEYTABLE(*keytablep));
00123
00124 keytable = *keytablep;
00125
00126 RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
00127
00128 INSIST(keytable->references > 0);
00129 keytable->references--;
00130 LOCK(&keytable->lock);
00131 if (keytable->references == 0 && keytable->active_nodes == 0)
00132 destroy = ISC_TRUE;
00133 UNLOCK(&keytable->lock);
00134
00135 RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
00136
00137 if (destroy) {
00138 dns_rbt_destroy(&keytable->table);
00139 isc_rwlock_destroy(&keytable->rwlock);
00140 DESTROYLOCK(&keytable->lock);
00141 keytable->magic = 0;
00142 isc_mem_putanddetach(&keytable->mctx,
00143 keytable, sizeof(*keytable));
00144 }
00145
00146 *keytablep = NULL;
00147 }
00148
00149 static isc_result_t
00150 insert(dns_keytable_t *keytable, isc_boolean_t managed,
00151 dns_name_t *keyname, dst_key_t **keyp)
00152 {
00153 isc_result_t result;
00154 dns_keynode_t *knode = NULL;
00155 dns_rbtnode_t *node;
00156
00157 REQUIRE(keyp == NULL || *keyp != NULL);
00158 REQUIRE(VALID_KEYTABLE(keytable));
00159
00160 result = dns_keynode_create(keytable->mctx, &knode);
00161 if (result != ISC_R_SUCCESS)
00162 return (result);
00163
00164 knode->managed = managed;
00165
00166 RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
00167
00168 node = NULL;
00169 result = dns_rbt_addnode(keytable->table, keyname, &node);
00170
00171 if (keyp != NULL) {
00172 if (result == ISC_R_EXISTS) {
00173
00174 dns_keynode_t *k;
00175 for (k = node->data; k != NULL; k = k->next) {
00176 if (k->key == NULL) {
00177 k->key = *keyp;
00178 *keyp = NULL;
00179 break;
00180 }
00181 if (dst_key_compare(k->key, *keyp) == ISC_TRUE)
00182 break;
00183 }
00184
00185 if (k == NULL)
00186 result = ISC_R_SUCCESS;
00187 else if (*keyp != NULL)
00188 dst_key_free(keyp);
00189 }
00190
00191 if (result == ISC_R_SUCCESS) {
00192 knode->key = *keyp;
00193 knode->next = node->data;
00194 *keyp = NULL;
00195 }
00196 }
00197
00198 if (result == ISC_R_SUCCESS) {
00199 node->data = knode;
00200 knode = NULL;
00201 }
00202
00203
00204 if (result == ISC_R_EXISTS)
00205 result = ISC_R_SUCCESS;
00206
00207 RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
00208
00209 if (knode != NULL)
00210 dns_keynode_detach(keytable->mctx, &knode);
00211
00212 return (result);
00213 }
00214
00215 isc_result_t
00216 dns_keytable_add(dns_keytable_t *keytable, isc_boolean_t managed,
00217 dst_key_t **keyp)
00218 {
00219 REQUIRE(keyp != NULL && *keyp != NULL);
00220 return (insert(keytable, managed, dst_key_name(*keyp), keyp));
00221 }
00222
00223 isc_result_t
00224 dns_keytable_marksecure(dns_keytable_t *keytable, dns_name_t *name) {
00225 return (insert(keytable, ISC_TRUE, name, NULL));
00226 }
00227
00228 isc_result_t
00229 dns_keytable_delete(dns_keytable_t *keytable, dns_name_t *keyname) {
00230 isc_result_t result;
00231 dns_rbtnode_t *node = NULL;
00232
00233 REQUIRE(VALID_KEYTABLE(keytable));
00234 REQUIRE(keyname != NULL);
00235
00236 RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
00237 result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
00238 DNS_RBTFIND_NOOPTIONS, NULL, NULL);
00239 if (result == ISC_R_SUCCESS) {
00240 if (node->data != NULL)
00241 result = dns_rbt_deletenode(keytable->table,
00242 node, ISC_FALSE);
00243 else
00244 result = ISC_R_NOTFOUND;
00245 } else if (result == DNS_R_PARTIALMATCH)
00246 result = ISC_R_NOTFOUND;
00247 RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
00248
00249 return (result);
00250 }
00251
00252 isc_result_t
00253 dns_keytable_deletekeynode(dns_keytable_t *keytable, dst_key_t *dstkey) {
00254 isc_result_t result;
00255 dns_name_t *keyname;
00256 dns_rbtnode_t *node = NULL;
00257 dns_keynode_t *knode = NULL, **kprev = NULL;
00258
00259 REQUIRE(VALID_KEYTABLE(keytable));
00260 REQUIRE(dstkey != NULL);
00261
00262 keyname = dst_key_name(dstkey);
00263
00264 RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
00265 result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
00266 DNS_RBTFIND_NOOPTIONS, NULL, NULL);
00267
00268 if (result == DNS_R_PARTIALMATCH)
00269 result = ISC_R_NOTFOUND;
00270 if (result != ISC_R_SUCCESS)
00271 goto finish;
00272
00273 if (node->data == NULL) {
00274 result = ISC_R_NOTFOUND;
00275 goto finish;
00276 }
00277
00278 knode = node->data;
00279 if (knode->next == NULL && knode->key != NULL &&
00280 dst_key_compare(knode->key, dstkey) == ISC_TRUE)
00281 {
00282 result = dns_rbt_deletenode(keytable->table, node, ISC_FALSE);
00283 goto finish;
00284 }
00285
00286 kprev = (dns_keynode_t **) &node->data;
00287 while (knode != NULL) {
00288 if (knode->key != NULL &&
00289 dst_key_compare(knode->key, dstkey) == ISC_TRUE)
00290 break;
00291 kprev = &knode->next;
00292 knode = knode->next;
00293 }
00294
00295 if (knode != NULL) {
00296 if (knode->key != NULL)
00297 dst_key_free(&knode->key);
00298
00299
00300
00301
00302
00303
00304
00305 *kprev = knode->next;
00306 knode->next = NULL;
00307 dns_keynode_detach(keytable->mctx, &knode);
00308 } else
00309 result = DNS_R_PARTIALMATCH;
00310 finish:
00311 RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
00312 return (result);
00313 }
00314
00315 isc_result_t
00316 dns_keytable_find(dns_keytable_t *keytable, dns_name_t *keyname,
00317 dns_keynode_t **keynodep)
00318 {
00319 isc_result_t result;
00320 dns_rbtnode_t *node = NULL;
00321
00322 REQUIRE(VALID_KEYTABLE(keytable));
00323 REQUIRE(keyname != NULL);
00324 REQUIRE(keynodep != NULL && *keynodep == NULL);
00325
00326 RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
00327 result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
00328 DNS_RBTFIND_NOOPTIONS, NULL, NULL);
00329 if (result == ISC_R_SUCCESS) {
00330 if (node->data != NULL) {
00331 LOCK(&keytable->lock);
00332 keytable->active_nodes++;
00333 UNLOCK(&keytable->lock);
00334 dns_keynode_attach(node->data, keynodep);
00335 } else
00336 result = ISC_R_NOTFOUND;
00337 } else if (result == DNS_R_PARTIALMATCH)
00338 result = ISC_R_NOTFOUND;
00339 RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
00340
00341 return (result);
00342 }
00343
00344 isc_result_t
00345 dns_keytable_nextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
00346 dns_keynode_t **nextnodep)
00347 {
00348
00349
00350
00351
00352
00353 REQUIRE(VALID_KEYTABLE(keytable));
00354 REQUIRE(VALID_KEYNODE(keynode));
00355 REQUIRE(nextnodep != NULL && *nextnodep == NULL);
00356
00357 if (keynode->next == NULL)
00358 return (ISC_R_NOTFOUND);
00359
00360 dns_keynode_attach(keynode->next, nextnodep);
00361 LOCK(&keytable->lock);
00362 keytable->active_nodes++;
00363 UNLOCK(&keytable->lock);
00364
00365 return (ISC_R_SUCCESS);
00366 }
00367
00368 isc_result_t
00369 dns_keytable_findkeynode(dns_keytable_t *keytable, dns_name_t *name,
00370 dns_secalg_t algorithm, dns_keytag_t tag,
00371 dns_keynode_t **keynodep)
00372 {
00373 isc_result_t result;
00374 dns_keynode_t *knode;
00375 void *data;
00376
00377
00378
00379
00380
00381
00382 REQUIRE(VALID_KEYTABLE(keytable));
00383 REQUIRE(dns_name_isabsolute(name));
00384 REQUIRE(keynodep != NULL && *keynodep == NULL);
00385
00386 RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
00387
00388
00389
00390
00391
00392
00393
00394
00395 knode = NULL;
00396 data = NULL;
00397 result = dns_rbt_findname(keytable->table, name, 0, NULL, &data);
00398
00399 if (result == ISC_R_SUCCESS) {
00400 INSIST(data != NULL);
00401 for (knode = data; knode != NULL; knode = knode->next) {
00402 if (knode->key == NULL) {
00403 knode = NULL;
00404 break;
00405 }
00406 if (algorithm == dst_key_alg(knode->key)
00407 && tag == dst_key_id(knode->key))
00408 break;
00409 }
00410 if (knode != NULL) {
00411 LOCK(&keytable->lock);
00412 keytable->active_nodes++;
00413 UNLOCK(&keytable->lock);
00414 dns_keynode_attach(knode, keynodep);
00415 } else
00416 result = DNS_R_PARTIALMATCH;
00417 } else if (result == DNS_R_PARTIALMATCH)
00418 result = ISC_R_NOTFOUND;
00419
00420 RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
00421
00422 return (result);
00423 }
00424
00425 isc_result_t
00426 dns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
00427 dns_keynode_t **nextnodep)
00428 {
00429 isc_result_t result;
00430 dns_keynode_t *knode;
00431
00432
00433
00434
00435
00436
00437 REQUIRE(VALID_KEYTABLE(keytable));
00438 REQUIRE(VALID_KEYNODE(keynode));
00439 REQUIRE(nextnodep != NULL && *nextnodep == NULL);
00440
00441 for (knode = keynode->next; knode != NULL; knode = knode->next) {
00442 if (knode->key == NULL) {
00443 knode = NULL;
00444 break;
00445 }
00446 if (dst_key_alg(keynode->key) == dst_key_alg(knode->key) &&
00447 dst_key_id(keynode->key) == dst_key_id(knode->key))
00448 break;
00449 }
00450 if (knode != NULL) {
00451 LOCK(&keytable->lock);
00452 keytable->active_nodes++;
00453 UNLOCK(&keytable->lock);
00454 result = ISC_R_SUCCESS;
00455 dns_keynode_attach(knode, nextnodep);
00456 } else
00457 result = ISC_R_NOTFOUND;
00458
00459 return (result);
00460 }
00461
00462 isc_result_t
00463 dns_keytable_finddeepestmatch(dns_keytable_t *keytable, dns_name_t *name,
00464 dns_name_t *foundname)
00465 {
00466 isc_result_t result;
00467 void *data;
00468
00469
00470
00471
00472
00473 REQUIRE(VALID_KEYTABLE(keytable));
00474 REQUIRE(dns_name_isabsolute(name));
00475 REQUIRE(foundname != NULL);
00476
00477 RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
00478
00479 data = NULL;
00480 result = dns_rbt_findname(keytable->table, name, 0, foundname, &data);
00481
00482 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
00483 result = ISC_R_SUCCESS;
00484
00485 RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
00486
00487 return (result);
00488 }
00489
00490 void
00491 dns_keytable_attachkeynode(dns_keytable_t *keytable, dns_keynode_t *source,
00492 dns_keynode_t **target)
00493 {
00494
00495
00496
00497
00498 REQUIRE(VALID_KEYTABLE(keytable));
00499 REQUIRE(VALID_KEYNODE(source));
00500 REQUIRE(target != NULL && *target == NULL);
00501
00502 LOCK(&keytable->lock);
00503 keytable->active_nodes++;
00504 UNLOCK(&keytable->lock);
00505
00506 dns_keynode_attach(source, target);
00507 }
00508
00509 void
00510 dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep)
00511 {
00512
00513
00514
00515
00516 REQUIRE(VALID_KEYTABLE(keytable));
00517 REQUIRE(keynodep != NULL && VALID_KEYNODE(*keynodep));
00518
00519 LOCK(&keytable->lock);
00520 INSIST(keytable->active_nodes > 0);
00521 keytable->active_nodes--;
00522 UNLOCK(&keytable->lock);
00523
00524 dns_keynode_detach(keytable->mctx, keynodep);
00525 }
00526
00527 isc_result_t
00528 dns_keytable_issecuredomain(dns_keytable_t *keytable, dns_name_t *name,
00529 dns_name_t *foundname, isc_boolean_t *wantdnssecp)
00530 {
00531 isc_result_t result;
00532 dns_rbtnode_t *node = NULL;
00533
00534
00535
00536
00537
00538 REQUIRE(VALID_KEYTABLE(keytable));
00539 REQUIRE(dns_name_isabsolute(name));
00540 REQUIRE(wantdnssecp != NULL);
00541
00542 RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
00543
00544 result = dns_rbt_findnode(keytable->table, name, foundname, &node,
00545 NULL, DNS_RBTFIND_NOOPTIONS, NULL, NULL);
00546 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
00547 INSIST(node->data != NULL);
00548 *wantdnssecp = ISC_TRUE;
00549 result = ISC_R_SUCCESS;
00550 } else if (result == ISC_R_NOTFOUND) {
00551 *wantdnssecp = ISC_FALSE;
00552 result = ISC_R_SUCCESS;
00553 }
00554
00555 RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
00556
00557 return (result);
00558 }
00559
00560 static isc_result_t
00561 putstr(isc_buffer_t **b, const char *str) {
00562 isc_result_t result;
00563
00564 result = isc_buffer_reserve(b, strlen(str));
00565 if (result != ISC_R_SUCCESS)
00566 return (result);
00567
00568 isc_buffer_putstr(*b, str);
00569 return (ISC_R_SUCCESS);
00570 }
00571
00572 isc_result_t
00573 dns_keytable_dump(dns_keytable_t *keytable, FILE *fp) {
00574 isc_result_t result;
00575 isc_buffer_t *text = NULL;
00576
00577 REQUIRE(VALID_KEYTABLE(keytable));
00578 REQUIRE(fp != NULL);
00579
00580 result = isc_buffer_allocate(keytable->mctx, &text, 4096);
00581 if (result != ISC_R_SUCCESS)
00582 return (result);
00583
00584 result = dns_keytable_totext(keytable, &text);
00585
00586 if (isc_buffer_usedlength(text) != 0) {
00587 (void) putstr(&text, "\n");
00588 } else if (result == ISC_R_SUCCESS)
00589 (void) putstr(&text, "none");
00590 else {
00591 (void) putstr(&text, "could not dump key table: ");
00592 (void) putstr(&text, isc_result_totext(result));
00593 }
00594
00595 fprintf(fp, "%.*s", (int) isc_buffer_usedlength(text),
00596 (char *) isc_buffer_base(text));
00597
00598 isc_buffer_free(&text);
00599 return (result);
00600 }
00601
00602 isc_result_t
00603 dns_keytable_totext(dns_keytable_t *keytable, isc_buffer_t **text) {
00604 isc_result_t result;
00605 dns_keynode_t *knode;
00606 dns_rbtnode_t *node;
00607 dns_rbtnodechain_t chain;
00608
00609 REQUIRE(VALID_KEYTABLE(keytable));
00610 REQUIRE(text != NULL && *text != NULL);
00611
00612 RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
00613 dns_rbtnodechain_init(&chain, keytable->mctx);
00614 result = dns_rbtnodechain_first(&chain, keytable->table, NULL, NULL);
00615 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
00616 if (result == ISC_R_NOTFOUND)
00617 result = ISC_R_SUCCESS;
00618 goto cleanup;
00619 }
00620 for (;;) {
00621 char pbuf[DST_KEY_FORMATSIZE];
00622
00623 dns_rbtnodechain_current(&chain, NULL, NULL, &node);
00624 for (knode = node->data; knode != NULL; knode = knode->next) {
00625 char obuf[DNS_NAME_FORMATSIZE + 200];
00626 if (knode->key == NULL)
00627 continue;
00628 dst_key_format(knode->key, pbuf, sizeof(pbuf));
00629 snprintf(obuf, sizeof(obuf), "%s ; %s\n", pbuf,
00630 knode->managed ? "managed" : "trusted");
00631 result = putstr(text, obuf);
00632 if (result != ISC_R_SUCCESS)
00633 break;
00634 }
00635 result = dns_rbtnodechain_next(&chain, NULL, NULL);
00636 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
00637 if (result == ISC_R_NOMORE)
00638 result = ISC_R_SUCCESS;
00639 break;
00640 }
00641 }
00642
00643 cleanup:
00644 dns_rbtnodechain_invalidate(&chain);
00645 RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
00646 return (result);
00647 }
00648
00649 dst_key_t *
00650 dns_keynode_key(dns_keynode_t *keynode) {
00651
00652
00653
00654
00655
00656 REQUIRE(VALID_KEYNODE(keynode));
00657
00658 return (keynode->key);
00659 }
00660
00661 isc_boolean_t
00662 dns_keynode_managed(dns_keynode_t *keynode) {
00663
00664
00665
00666 REQUIRE(VALID_KEYNODE(keynode));
00667
00668 return (keynode->managed);
00669 }
00670
00671 isc_result_t
00672 dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target) {
00673 isc_result_t result;
00674 dns_keynode_t *knode = NULL;
00675
00676 REQUIRE(target != NULL && *target == NULL);
00677
00678 knode = isc_mem_get(mctx, sizeof(dns_keynode_t));
00679 if (knode == NULL)
00680 return (ISC_R_NOMEMORY);
00681
00682 knode->magic = KEYNODE_MAGIC;
00683 knode->managed = ISC_FALSE;
00684 knode->key = NULL;
00685 knode->next = NULL;
00686
00687 result = isc_refcount_init(&knode->refcount, 1);
00688 if (result != ISC_R_SUCCESS)
00689 return (result);
00690
00691 *target = knode;
00692 return (ISC_R_SUCCESS);
00693 }
00694
00695 void
00696 dns_keynode_attach(dns_keynode_t *source, dns_keynode_t **target) {
00697 REQUIRE(VALID_KEYNODE(source));
00698 isc_refcount_increment(&source->refcount, NULL);
00699 *target = source;
00700 }
00701
00702 void
00703 dns_keynode_detach(isc_mem_t *mctx, dns_keynode_t **keynode) {
00704 unsigned int refs;
00705 dns_keynode_t *node = *keynode;
00706 REQUIRE(VALID_KEYNODE(node));
00707 isc_refcount_decrement(&node->refcount, &refs);
00708 if (refs == 0) {
00709 if (node->key != NULL)
00710 dst_key_free(&node->key);
00711 isc_refcount_destroy(&node->refcount);
00712 isc_mem_put(mctx, node, sizeof(dns_keynode_t));
00713 }
00714 *keynode = NULL;
00715 }
00716
00717 void
00718 dns_keynode_detachall(isc_mem_t *mctx, dns_keynode_t **keynode) {
00719 dns_keynode_t *next = NULL, *node = *keynode;
00720 REQUIRE(VALID_KEYNODE(node));
00721 while (node != NULL) {
00722 next = node->next;
00723 dns_keynode_detach(mctx, &node);
00724 node = next;
00725 }
00726 *keynode = NULL;
00727 }