2000-02-23 23:31:33 +00:00
|
|
|
/*
|
2018-02-23 09:53:12 +01:00
|
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
2000-08-01 01:33:37 +00:00
|
|
|
*
|
2016-06-27 14:56:38 +10:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
2018-02-23 09:53:12 +01:00
|
|
|
*
|
|
|
|
* See the COPYRIGHT file distributed with this work for additional
|
|
|
|
* information regarding copyright ownership.
|
2000-02-23 23:31:33 +00:00
|
|
|
*/
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
|
|
|
|
/*! \file */
|
2000-06-22 22:00:42 +00:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
#include <stdbool.h>
|
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
#include <isc/mem.h>
|
2015-02-06 13:30:22 +11:00
|
|
|
#include <isc/print.h>
|
2018-01-24 18:55:56 +11:00
|
|
|
#include <isc/refcount.h>
|
2000-02-23 23:31:33 +00:00
|
|
|
#include <isc/rwlock.h>
|
2000-05-08 19:23:32 +00:00
|
|
|
#include <isc/string.h> /* Required for HP/UX (and others?) */
|
2000-02-23 23:31:33 +00:00
|
|
|
#include <isc/util.h>
|
|
|
|
|
|
|
|
#include <dns/keytable.h>
|
|
|
|
#include <dns/fixedname.h>
|
|
|
|
#include <dns/rbt.h>
|
2019-09-16 21:06:23 -07:00
|
|
|
#include <dns/rdata.h>
|
|
|
|
#include <dns/rdatalist.h>
|
|
|
|
#include <dns/rdataset.h>
|
|
|
|
#include <dns/rdatastruct.h>
|
2000-05-02 03:54:17 +00:00
|
|
|
#include <dns/result.h>
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2016-07-22 20:02:17 +10:00
|
|
|
#define KEYTABLE_MAGIC ISC_MAGIC('K', 'T', 'b', 'l')
|
|
|
|
#define VALID_KEYTABLE(kt) ISC_MAGIC_VALID(kt, KEYTABLE_MAGIC)
|
|
|
|
|
|
|
|
#define KEYNODE_MAGIC ISC_MAGIC('K', 'N', 'o', 'd')
|
|
|
|
#define VALID_KEYNODE(kn) ISC_MAGIC_VALID(kn, KEYNODE_MAGIC)
|
|
|
|
|
|
|
|
struct dns_keytable {
|
2016-07-22 23:46:17 +00:00
|
|
|
/* Unlocked. */
|
|
|
|
unsigned int magic;
|
|
|
|
isc_mem_t *mctx;
|
2019-07-23 09:52:02 -04:00
|
|
|
atomic_uint_fast32_t active_nodes;
|
2018-01-24 18:55:56 +11:00
|
|
|
isc_refcount_t references;
|
2016-07-22 23:46:17 +00:00
|
|
|
isc_rwlock_t rwlock;
|
|
|
|
/* Locked by rwlock. */
|
|
|
|
dns_rbt_t *table;
|
2016-07-22 20:02:17 +10:00
|
|
|
};
|
|
|
|
|
|
|
|
struct dns_keynode {
|
2016-07-22 23:46:17 +00:00
|
|
|
unsigned int magic;
|
|
|
|
isc_refcount_t refcount;
|
2019-09-16 21:06:23 -07:00
|
|
|
dst_key_t *key;
|
|
|
|
dns_rdatalist_t *dslist;
|
|
|
|
dns_rdataset_t dsset;
|
2019-09-15 16:36:16 -07:00
|
|
|
bool managed;
|
|
|
|
bool initial;
|
2019-09-16 21:06:23 -07:00
|
|
|
struct dns_keynode *next;
|
2016-07-22 20:02:17 +10:00
|
|
|
};
|
|
|
|
|
2000-04-05 17:19:43 +00:00
|
|
|
static void
|
|
|
|
free_keynode(void *node, void *arg) {
|
|
|
|
dns_keynode_t *keynode = node;
|
|
|
|
isc_mem_t *mctx = arg;
|
|
|
|
|
2009-12-03 15:40:03 +00:00
|
|
|
dns_keynode_detachall(mctx, &keynode);
|
2000-04-05 17:19:43 +00:00
|
|
|
}
|
|
|
|
|
2000-02-23 23:31:33 +00:00
|
|
|
isc_result_t
|
|
|
|
dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep) {
|
|
|
|
dns_keytable_t *keytable;
|
|
|
|
isc_result_t result;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create a keytable.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(keytablep != NULL && *keytablep == NULL);
|
|
|
|
|
2001-11-12 19:05:39 +00:00
|
|
|
keytable = isc_mem_get(mctx, sizeof(*keytable));
|
2000-02-23 23:31:33 +00:00
|
|
|
|
|
|
|
keytable->table = NULL;
|
2000-04-05 17:19:43 +00:00
|
|
|
result = dns_rbt_create(mctx, free_keynode, mctx, &keytable->table);
|
2018-01-24 18:55:56 +11:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-02-23 23:31:33 +00:00
|
|
|
goto cleanup_keytable;
|
2018-01-24 18:55:56 +11:00
|
|
|
}
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2018-01-24 18:55:56 +11:00
|
|
|
result = isc_rwlock_init(&keytable->rwlock, 0, 0);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-02-23 23:31:33 +00:00
|
|
|
goto cleanup_rbt;
|
2018-01-24 18:55:56 +11:00
|
|
|
}
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2019-07-23 09:52:02 -04:00
|
|
|
atomic_init(&keytable->active_nodes, 0);
|
2018-08-01 11:46:11 +02:00
|
|
|
isc_refcount_init(&keytable->references, 1);
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2013-02-20 21:39:05 -08:00
|
|
|
keytable->mctx = NULL;
|
|
|
|
isc_mem_attach(mctx, &keytable->mctx);
|
2000-02-24 00:33:02 +00:00
|
|
|
keytable->magic = KEYTABLE_MAGIC;
|
2000-02-23 23:31:33 +00:00
|
|
|
*keytablep = keytable;
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
|
2018-01-24 18:55:56 +11:00
|
|
|
cleanup_rbt:
|
2000-02-23 23:31:33 +00:00
|
|
|
dns_rbt_destroy(&keytable->table);
|
|
|
|
|
2018-01-24 18:55:56 +11:00
|
|
|
cleanup_keytable:
|
2013-02-20 21:39:05 -08:00
|
|
|
isc_mem_putanddetach(&mctx, keytable, sizeof(*keytable));
|
2000-02-23 23:31:33 +00:00
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_keytable_attach(dns_keytable_t *source, dns_keytable_t **targetp) {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Attach *targetp to source.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(source));
|
|
|
|
REQUIRE(targetp != NULL && *targetp == NULL);
|
|
|
|
|
2018-08-17 15:16:59 +02:00
|
|
|
isc_refcount_increment(&source->references);
|
2000-02-23 23:31:33 +00:00
|
|
|
|
|
|
|
*targetp = source;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_keytable_detach(dns_keytable_t **keytablep) {
|
|
|
|
REQUIRE(keytablep != NULL && VALID_KEYTABLE(*keytablep));
|
2018-08-28 10:18:59 +02:00
|
|
|
dns_keytable_t *keytable = *keytablep;
|
|
|
|
*keytablep = NULL;
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2018-08-17 15:16:59 +02:00
|
|
|
if (isc_refcount_decrement(&keytable->references) == 1) {
|
2018-01-24 18:55:56 +11:00
|
|
|
isc_refcount_destroy(&keytable->references);
|
2019-07-23 09:52:02 -04:00
|
|
|
REQUIRE(atomic_load_acquire(&keytable->active_nodes) == 0);
|
2000-02-23 23:31:33 +00:00
|
|
|
dns_rbt_destroy(&keytable->table);
|
|
|
|
isc_rwlock_destroy(&keytable->rwlock);
|
|
|
|
keytable->magic = 0;
|
2013-02-20 21:39:05 -08:00
|
|
|
isc_mem_putanddetach(&keytable->mctx,
|
|
|
|
keytable, sizeof(*keytable));
|
2000-02-23 23:31:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-16 21:06:23 -07:00
|
|
|
static void
|
|
|
|
free_dslist(isc_mem_t *mctx, dns_keynode_t *knode) {
|
|
|
|
dns_rdata_t *rdata = NULL;
|
|
|
|
|
|
|
|
for (rdata = ISC_LIST_HEAD(knode->dslist->rdata);
|
|
|
|
rdata != NULL;
|
|
|
|
rdata = ISC_LIST_HEAD(knode->dslist->rdata))
|
|
|
|
{
|
|
|
|
ISC_LIST_UNLINK(knode->dslist->rdata, rdata, link);
|
|
|
|
isc_mem_put(mctx, rdata->data, DNS_DS_BUFFERSIZE);
|
|
|
|
isc_mem_put(mctx, rdata, sizeof(*rdata));
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_mem_put(mctx, knode->dslist, sizeof(*knode->dslist));
|
|
|
|
knode->dslist = NULL;
|
|
|
|
}
|
|
|
|
|
2017-10-27 15:45:18 -07:00
|
|
|
/*%
|
2019-09-16 21:06:23 -07:00
|
|
|
* Search "node" for an empty or DS-style keynode, or a keynode for the
|
|
|
|
* exact same key as the one supplied in "keyp" and, if found, update it
|
|
|
|
* accordingly.
|
2017-10-27 15:45:18 -07:00
|
|
|
*/
|
2009-06-30 02:53:46 +00:00
|
|
|
static isc_result_t
|
2019-09-16 21:06:23 -07:00
|
|
|
update_keynode(dns_keytable_t *keytable, dns_rbtnode_t *node,
|
|
|
|
dst_key_t **keyp, bool initial)
|
|
|
|
{
|
2017-10-27 15:45:18 -07:00
|
|
|
dns_keynode_t *knode;
|
|
|
|
|
|
|
|
REQUIRE(keyp != NULL && *keyp != NULL);
|
|
|
|
REQUIRE(node != NULL);
|
|
|
|
|
|
|
|
for (knode = node->data; knode != NULL; knode = knode->next) {
|
|
|
|
if (knode->key == NULL) {
|
|
|
|
/*
|
2019-09-16 21:06:23 -07:00
|
|
|
* Null or DS-style keynode found. Detach
|
|
|
|
* the DS rdatalist if present. Attach the
|
|
|
|
* supplied key to it, transferring key
|
2017-10-27 15:45:18 -07:00
|
|
|
* ownership to the keytable.
|
|
|
|
*/
|
2019-09-16 21:06:23 -07:00
|
|
|
if (knode->dslist != NULL) {
|
|
|
|
free_dslist(keytable->mctx, knode);
|
|
|
|
}
|
|
|
|
|
2017-10-27 15:45:18 -07:00
|
|
|
knode->key = *keyp;
|
|
|
|
*keyp = NULL;
|
|
|
|
} else if (dst_key_compare(knode->key, *keyp)) {
|
|
|
|
/*
|
|
|
|
* Key node found for the supplied key. Free the
|
|
|
|
* supplied copy of the key and update the found key
|
|
|
|
* node's flags if necessary.
|
|
|
|
*/
|
|
|
|
dst_key_free(keyp);
|
2019-09-16 21:06:23 -07:00
|
|
|
} else {
|
|
|
|
continue;
|
2017-10-27 15:45:18 -07:00
|
|
|
}
|
2019-09-16 21:06:23 -07:00
|
|
|
|
|
|
|
if (!initial) {
|
|
|
|
dns_keynode_trust(knode);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
2017-10-27 15:45:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return (ISC_R_NOTFOUND);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*%
|
|
|
|
* Create a key node for "keyp" (or a null key node if "keyp" is NULL), set
|
|
|
|
* "managed" and "initial" as requested and make the created key node the first
|
|
|
|
* one attached to "node" in "keytable".
|
|
|
|
*/
|
|
|
|
static isc_result_t
|
2019-09-16 21:06:23 -07:00
|
|
|
prepend_keynode(dst_key_t **keyp, dns_rdata_ds_t *ds,
|
|
|
|
dns_rbtnode_t *node, dns_keytable_t *keytable,
|
|
|
|
bool managed, bool initial)
|
2009-06-30 02:53:46 +00:00
|
|
|
{
|
|
|
|
dns_keynode_t *knode = NULL;
|
2017-10-27 15:45:18 -07:00
|
|
|
isc_result_t result;
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2009-06-30 02:53:46 +00:00
|
|
|
REQUIRE(keyp == NULL || *keyp != NULL);
|
2000-02-23 23:31:33 +00:00
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
2017-10-27 15:45:18 -07:00
|
|
|
REQUIRE(!initial || managed);
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2009-06-30 02:53:46 +00:00
|
|
|
result = dns_keynode_create(keytable->mctx, &knode);
|
2017-10-27 15:45:18 -07:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2009-06-30 02:53:46 +00:00
|
|
|
return (result);
|
2017-10-27 15:45:18 -07:00
|
|
|
}
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2017-10-27 15:45:18 -07:00
|
|
|
/*
|
2019-09-16 21:06:23 -07:00
|
|
|
* If a dst_key was supplied, transfer its ownership to the keytable.
|
|
|
|
* Otherwise, if a DS was supplied, append it to the rdatalist
|
|
|
|
* (initializing if necessary).
|
2017-10-27 15:45:18 -07:00
|
|
|
*/
|
2019-09-16 21:06:23 -07:00
|
|
|
if (keyp != NULL) {
|
|
|
|
if (knode->dslist != NULL) {
|
|
|
|
free_dslist(keytable->mctx, knode);
|
|
|
|
}
|
2017-10-27 15:45:18 -07:00
|
|
|
knode->key = *keyp;
|
|
|
|
*keyp = NULL;
|
2019-09-16 21:06:23 -07:00
|
|
|
} else if (ds != NULL) {
|
|
|
|
dns_rdata_t *rdata = NULL;
|
|
|
|
void *data = NULL;
|
|
|
|
isc_buffer_t b;
|
|
|
|
|
|
|
|
if (knode->dslist == NULL) {
|
|
|
|
knode->dslist = isc_mem_get(keytable->mctx,
|
|
|
|
sizeof(*knode->dslist));
|
|
|
|
dns_rdatalist_init(knode->dslist);
|
|
|
|
knode->dslist->rdclass = dns_rdataclass_in;
|
|
|
|
knode->dslist->type = dns_rdatatype_ds;
|
|
|
|
knode->dslist->ttl = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
rdata = isc_mem_get(keytable->mctx, sizeof(*rdata));
|
|
|
|
dns_rdata_init(rdata);
|
|
|
|
|
|
|
|
data = isc_mem_get(keytable->mctx, DNS_DS_BUFFERSIZE);
|
|
|
|
isc_buffer_init(&b, data, DNS_DS_BUFFERSIZE);
|
|
|
|
|
|
|
|
result = dns_rdata_fromstruct(rdata, dns_rdataclass_in,
|
|
|
|
dns_rdatatype_ds, ds, &b);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
ISC_LIST_APPEND(knode->dslist->rdata, rdata, link);
|
|
|
|
|
|
|
|
if (dns_rdataset_isassociated(&knode->dsset)) {
|
|
|
|
dns_rdataset_disassociate(&knode->dsset);
|
|
|
|
}
|
|
|
|
|
|
|
|
result = dns_rdatalist_tordataset(knode->dslist,
|
|
|
|
&knode->dsset);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
knode->dsset.trust = dns_trust_ultimate;
|
2017-10-27 15:45:18 -07:00
|
|
|
}
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2017-10-27 15:45:18 -07:00
|
|
|
knode->managed = managed;
|
|
|
|
knode->initial = initial;
|
2019-09-16 21:06:23 -07:00
|
|
|
|
2017-10-27 15:45:18 -07:00
|
|
|
knode->next = node->data;
|
|
|
|
node->data = knode;
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2017-10-27 15:45:18 -07:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
2000-02-23 23:31:33 +00:00
|
|
|
|
2017-10-27 15:45:18 -07:00
|
|
|
/*%
|
|
|
|
* Add key "keyp" at "keyname" in "keytable". If the key already exists at the
|
|
|
|
* requested name, update its flags. If "keyp" is NULL, add a null key to
|
|
|
|
* indicate that "keyname" should be treated as a secure domain without
|
|
|
|
* supplying key data which would allow the domain to be validated.
|
|
|
|
*/
|
|
|
|
static isc_result_t
|
2018-04-17 08:29:14 -07:00
|
|
|
insert(dns_keytable_t *keytable, bool managed, bool initial,
|
2019-09-16 21:06:23 -07:00
|
|
|
const dns_name_t *keyname, dst_key_t **keyp, dns_rdata_ds_t *ds)
|
2017-10-27 15:45:18 -07:00
|
|
|
{
|
|
|
|
dns_rbtnode_t *node = NULL;
|
|
|
|
isc_result_t result;
|
2009-07-13 21:53:03 +00:00
|
|
|
|
2017-10-27 15:45:18 -07:00
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
2009-06-30 02:53:46 +00:00
|
|
|
|
2017-10-27 15:45:18 -07:00
|
|
|
RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
|
2009-06-30 02:53:46 +00:00
|
|
|
|
2017-10-27 15:45:18 -07:00
|
|
|
result = dns_rbt_addnode(keytable->table, keyname, &node);
|
2009-06-30 02:53:46 +00:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
2017-10-27 15:45:18 -07:00
|
|
|
/*
|
|
|
|
* There was no node for "keyname" in "keytable" yet, so one
|
2019-09-16 21:06:23 -07:00
|
|
|
* was created. Create a new key node for the supplied
|
|
|
|
* trust anchor (or a null key node if both "keyp" and
|
|
|
|
* "ds" are NULL) and attach it to the created node.
|
2017-10-27 15:45:18 -07:00
|
|
|
*/
|
2019-09-16 21:06:23 -07:00
|
|
|
result = prepend_keynode(keyp, ds, node, keytable,
|
|
|
|
managed, initial);
|
2017-10-27 15:45:18 -07:00
|
|
|
} else if (result == ISC_R_EXISTS) {
|
|
|
|
/*
|
|
|
|
* A node already exists for "keyname" in "keytable".
|
|
|
|
*/
|
2019-09-16 21:06:23 -07:00
|
|
|
if (keyp == NULL && ds == NULL) {
|
2017-10-27 15:45:18 -07:00
|
|
|
/*
|
|
|
|
* We were told to add a null key at "keyname", which
|
|
|
|
* means there is nothing left to do as there is either
|
|
|
|
* a null key at this node already or there is a
|
|
|
|
* non-null key node which would not be affected.
|
|
|
|
* Reset result to reflect the fact that the node for
|
|
|
|
* "keyname" is already marked as secure.
|
|
|
|
*/
|
|
|
|
result = ISC_R_SUCCESS;
|
2019-09-16 21:06:23 -07:00
|
|
|
} else if (keyp != NULL) {
|
2017-10-27 15:45:18 -07:00
|
|
|
/*
|
|
|
|
* We were told to add the key supplied in "keyp" at
|
|
|
|
* "keyname". Try to find an already existing key node
|
|
|
|
* we could reuse for the supplied key (i.e. a null key
|
|
|
|
* node or a key node for the exact same key) and, if
|
|
|
|
* found, update it accordingly.
|
|
|
|
*/
|
2019-09-16 21:06:23 -07:00
|
|
|
result = update_keynode(keytable, node, keyp, initial);
|
2017-10-27 15:45:18 -07:00
|
|
|
if (result == ISC_R_NOTFOUND) {
|
|
|
|
/*
|
|
|
|
* The node for "keyname" only contains key
|
|
|
|
* nodes for keys different than the supplied
|
|
|
|
* one. Create a new key node for the supplied
|
|
|
|
* key and prepend it before the others.
|
|
|
|
*/
|
2019-09-16 21:06:23 -07:00
|
|
|
result = prepend_keynode(keyp, NULL,
|
|
|
|
node, keytable,
|
2017-10-27 15:45:18 -07:00
|
|
|
managed, initial);
|
|
|
|
}
|
2019-09-16 21:06:23 -07:00
|
|
|
} else if (ds != NULL) {
|
|
|
|
result = prepend_keynode(NULL, ds, node, keytable,
|
|
|
|
managed, initial);
|
2017-10-27 15:45:18 -07:00
|
|
|
}
|
2000-02-23 23:31:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
|
|
|
|
|
2009-06-30 02:53:46 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2019-09-16 21:06:23 -07:00
|
|
|
dns_keytable_add(dns_keytable_t *keytable,
|
|
|
|
bool managed, bool initial,
|
|
|
|
dns_name_t *name, dst_key_t **keyp, dns_rdata_ds_t *ds)
|
2009-07-01 23:47:36 +00:00
|
|
|
{
|
2019-09-16 21:06:23 -07:00
|
|
|
REQUIRE(keyp == NULL || *keyp != NULL);
|
|
|
|
REQUIRE(keyp != NULL || ds != NULL);
|
2017-10-27 15:45:18 -07:00
|
|
|
REQUIRE(!initial || managed);
|
2019-09-16 21:06:23 -07:00
|
|
|
return (insert(keytable, managed, initial, name, keyp, ds));
|
2009-06-30 02:53:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2016-12-30 15:45:08 +11:00
|
|
|
dns_keytable_marksecure(dns_keytable_t *keytable, const dns_name_t *name) {
|
2019-09-16 21:06:23 -07:00
|
|
|
return (insert(keytable, true, false, name, NULL, NULL));
|
2009-06-30 02:53:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2016-12-30 15:45:08 +11:00
|
|
|
dns_keytable_delete(dns_keytable_t *keytable, const dns_name_t *keyname) {
|
2009-06-30 02:53:46 +00:00
|
|
|
isc_result_t result;
|
|
|
|
dns_rbtnode_t *node = NULL;
|
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
|
|
|
REQUIRE(keyname != NULL);
|
2009-07-01 23:47:36 +00:00
|
|
|
|
2009-06-30 02:53:46 +00:00
|
|
|
RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
|
|
|
|
result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
|
|
|
|
DNS_RBTFIND_NOOPTIONS, NULL, NULL);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
if (node->data != NULL)
|
|
|
|
result = dns_rbt_deletenode(keytable->table,
|
2018-04-17 08:29:14 -07:00
|
|
|
node, false);
|
2009-06-30 02:53:46 +00:00
|
|
|
else
|
|
|
|
result = ISC_R_NOTFOUND;
|
|
|
|
} else if (result == DNS_R_PARTIALMATCH)
|
|
|
|
result = ISC_R_NOTFOUND;
|
|
|
|
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_keytable_deletekeynode(dns_keytable_t *keytable, dst_key_t *dstkey) {
|
|
|
|
isc_result_t result;
|
|
|
|
dns_name_t *keyname;
|
|
|
|
dns_rbtnode_t *node = NULL;
|
|
|
|
dns_keynode_t *knode = NULL, **kprev = NULL;
|
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
|
|
|
REQUIRE(dstkey != NULL);
|
|
|
|
|
|
|
|
keyname = dst_key_name(dstkey);
|
|
|
|
|
|
|
|
RWLOCK(&keytable->rwlock, isc_rwlocktype_write);
|
|
|
|
result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
|
|
|
|
DNS_RBTFIND_NOOPTIONS, NULL, NULL);
|
|
|
|
|
|
|
|
if (result == DNS_R_PARTIALMATCH)
|
|
|
|
result = ISC_R_NOTFOUND;
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
goto finish;
|
|
|
|
|
|
|
|
if (node->data == NULL) {
|
|
|
|
result = ISC_R_NOTFOUND;
|
|
|
|
goto finish;
|
|
|
|
}
|
|
|
|
|
|
|
|
knode = node->data;
|
2015-02-05 17:18:15 -08:00
|
|
|
if (knode->next == NULL && knode->key != NULL &&
|
2018-04-17 08:29:14 -07:00
|
|
|
dst_key_compare(knode->key, dstkey) == true)
|
2015-02-05 17:18:15 -08:00
|
|
|
{
|
2018-04-17 08:29:14 -07:00
|
|
|
result = dns_rbt_deletenode(keytable->table, node, false);
|
2009-06-30 02:53:46 +00:00
|
|
|
goto finish;
|
|
|
|
}
|
2009-07-01 23:47:36 +00:00
|
|
|
|
2009-06-30 02:53:46 +00:00
|
|
|
kprev = (dns_keynode_t **) &node->data;
|
|
|
|
while (knode != NULL) {
|
2015-02-05 17:18:15 -08:00
|
|
|
if (knode->key != NULL &&
|
2018-04-17 08:29:14 -07:00
|
|
|
dst_key_compare(knode->key, dstkey) == true)
|
2009-06-30 02:53:46 +00:00
|
|
|
break;
|
2009-12-03 15:40:03 +00:00
|
|
|
kprev = &knode->next;
|
2009-06-30 02:53:46 +00:00
|
|
|
knode = knode->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (knode != NULL) {
|
|
|
|
if (knode->key != NULL)
|
|
|
|
dst_key_free(&knode->key);
|
|
|
|
/*
|
|
|
|
* This is equivalent to:
|
|
|
|
* dns_keynode_attach(knode->next, &tmp);
|
|
|
|
* dns_keynode_detach(kprev);
|
|
|
|
* dns_keynode_attach(tmp, &kprev);
|
|
|
|
* dns_keynode_detach(&tmp);
|
|
|
|
*/
|
|
|
|
*kprev = knode->next;
|
|
|
|
knode->next = NULL;
|
|
|
|
dns_keynode_detach(keytable->mctx, &knode);
|
|
|
|
} else
|
|
|
|
result = DNS_R_PARTIALMATCH;
|
|
|
|
finish:
|
|
|
|
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2016-12-30 15:45:08 +11:00
|
|
|
dns_keytable_find(dns_keytable_t *keytable, const dns_name_t *keyname,
|
2009-06-30 02:53:46 +00:00
|
|
|
dns_keynode_t **keynodep)
|
|
|
|
{
|
|
|
|
isc_result_t result;
|
|
|
|
dns_rbtnode_t *node = NULL;
|
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
|
|
|
REQUIRE(keyname != NULL);
|
|
|
|
REQUIRE(keynodep != NULL && *keynodep == NULL);
|
2009-07-01 23:47:36 +00:00
|
|
|
|
2009-06-30 02:53:46 +00:00
|
|
|
RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
|
|
|
|
result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
|
|
|
|
DNS_RBTFIND_NOOPTIONS, NULL, NULL);
|
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
if (node->data != NULL) {
|
2019-07-23 09:52:02 -04:00
|
|
|
dns_keytable_attachkeynode(keytable, node->data,
|
|
|
|
keynodep);
|
|
|
|
} else {
|
2009-06-30 02:53:46 +00:00
|
|
|
result = ISC_R_NOTFOUND;
|
2019-07-23 09:52:02 -04:00
|
|
|
}
|
|
|
|
} else if (result == DNS_R_PARTIALMATCH) {
|
2009-06-30 02:53:46 +00:00
|
|
|
result = ISC_R_NOTFOUND;
|
2019-07-23 09:52:02 -04:00
|
|
|
}
|
2009-06-30 02:53:46 +00:00
|
|
|
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
|
2000-02-23 23:31:33 +00:00
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2009-06-30 02:53:46 +00:00
|
|
|
isc_result_t
|
|
|
|
dns_keytable_nextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
|
|
|
|
dns_keynode_t **nextnodep)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Return the next key after 'keynode', regardless of
|
|
|
|
* properties.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
|
|
|
REQUIRE(VALID_KEYNODE(keynode));
|
|
|
|
REQUIRE(nextnodep != NULL && *nextnodep == NULL);
|
|
|
|
|
2019-09-16 21:06:23 -07:00
|
|
|
if (keynode->next == NULL) {
|
2009-06-30 02:53:46 +00:00
|
|
|
return (ISC_R_NOTFOUND);
|
2019-09-16 21:06:23 -07:00
|
|
|
}
|
2009-06-30 02:53:46 +00:00
|
|
|
|
2019-07-23 09:52:02 -04:00
|
|
|
dns_keytable_attachkeynode(keytable, keynode->next, nextnodep);
|
2009-06-30 02:53:46 +00:00
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2000-02-23 23:31:33 +00:00
|
|
|
isc_result_t
|
2016-12-30 15:45:08 +11:00
|
|
|
dns_keytable_findkeynode(dns_keytable_t *keytable, const dns_name_t *name,
|
2000-02-23 23:31:33 +00:00
|
|
|
dns_secalg_t algorithm, dns_keytag_t tag,
|
|
|
|
dns_keynode_t **keynodep)
|
|
|
|
{
|
|
|
|
isc_result_t result;
|
|
|
|
dns_keynode_t *knode;
|
|
|
|
void *data;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Search for a key named 'name', matching 'algorithm' and 'tag' in
|
|
|
|
* 'keytable'.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
|
|
|
REQUIRE(dns_name_isabsolute(name));
|
|
|
|
REQUIRE(keynodep != NULL && *keynodep == NULL);
|
|
|
|
|
|
|
|
RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
|
|
|
|
|
2005-12-04 23:54:01 +00:00
|
|
|
/*
|
|
|
|
* Note we don't want the DNS_R_PARTIALMATCH from dns_rbt_findname()
|
|
|
|
* as that indicates that 'name' was not found.
|
|
|
|
*
|
|
|
|
* DNS_R_PARTIALMATCH indicates that the name was found but we
|
|
|
|
* didn't get a match on algorithm and key id arguments.
|
|
|
|
*/
|
2000-02-23 23:31:33 +00:00
|
|
|
knode = NULL;
|
|
|
|
data = NULL;
|
2000-04-19 18:27:24 +00:00
|
|
|
result = dns_rbt_findname(keytable->table, name, 0, NULL, &data);
|
2000-02-23 23:31:33 +00:00
|
|
|
if (result == ISC_R_SUCCESS) {
|
|
|
|
INSIST(data != NULL);
|
2019-09-16 21:06:23 -07:00
|
|
|
|
2000-02-23 23:31:33 +00:00
|
|
|
for (knode = data; knode != NULL; knode = knode->next) {
|
2009-06-30 02:53:46 +00:00
|
|
|
if (knode->key == NULL) {
|
|
|
|
knode = NULL;
|
|
|
|
break;
|
|
|
|
}
|
2019-09-16 21:06:23 -07:00
|
|
|
if (algorithm == dst_key_alg(knode->key) &&
|
|
|
|
tag == dst_key_id(knode->key))
|
|
|
|
{
|
2000-02-23 23:31:33 +00:00
|
|
|
break;
|
2019-09-16 21:06:23 -07:00
|
|
|
}
|
2000-02-23 23:31:33 +00:00
|
|
|
}
|
|
|
|
if (knode != NULL) {
|
2019-07-23 09:52:02 -04:00
|
|
|
dns_keytable_attachkeynode(keytable, knode, keynodep);
|
2019-09-16 21:06:23 -07:00
|
|
|
} else {
|
2005-12-04 23:54:01 +00:00
|
|
|
result = DNS_R_PARTIALMATCH;
|
2019-09-16 21:06:23 -07:00
|
|
|
}
|
|
|
|
} else if (result == DNS_R_PARTIALMATCH) {
|
2000-02-23 23:31:33 +00:00
|
|
|
result = ISC_R_NOTFOUND;
|
2019-09-16 21:06:23 -07:00
|
|
|
}
|
2000-02-23 23:31:33 +00:00
|
|
|
|
|
|
|
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2000-05-19 20:25:55 +00:00
|
|
|
isc_result_t
|
|
|
|
dns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
|
|
|
|
dns_keynode_t **nextnodep)
|
|
|
|
{
|
|
|
|
isc_result_t result;
|
|
|
|
dns_keynode_t *knode;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Search for the next key with the same properties as 'keynode' in
|
|
|
|
* 'keytable'.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
|
|
|
REQUIRE(VALID_KEYNODE(keynode));
|
|
|
|
REQUIRE(nextnodep != NULL && *nextnodep == NULL);
|
|
|
|
|
|
|
|
for (knode = keynode->next; knode != NULL; knode = knode->next) {
|
2009-06-30 02:53:46 +00:00
|
|
|
if (knode->key == NULL) {
|
|
|
|
knode = NULL;
|
|
|
|
break;
|
|
|
|
}
|
2000-05-19 20:25:55 +00:00
|
|
|
if (dst_key_alg(keynode->key) == dst_key_alg(knode->key) &&
|
|
|
|
dst_key_id(keynode->key) == dst_key_id(knode->key))
|
2019-09-16 21:06:23 -07:00
|
|
|
{
|
2000-05-19 20:25:55 +00:00
|
|
|
break;
|
2019-09-16 21:06:23 -07:00
|
|
|
}
|
2000-05-19 20:25:55 +00:00
|
|
|
}
|
|
|
|
if (knode != NULL) {
|
2019-07-23 09:52:02 -04:00
|
|
|
dns_keytable_attachkeynode(keytable, knode, nextnodep);
|
2000-05-19 20:25:55 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
2019-09-16 21:06:23 -07:00
|
|
|
} else {
|
2000-05-19 20:25:55 +00:00
|
|
|
result = ISC_R_NOTFOUND;
|
2019-09-16 21:06:23 -07:00
|
|
|
}
|
2000-05-19 20:25:55 +00:00
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2000-04-18 17:47:17 +00:00
|
|
|
isc_result_t
|
2016-12-30 15:45:08 +11:00
|
|
|
dns_keytable_finddeepestmatch(dns_keytable_t *keytable, const dns_name_t *name,
|
2000-04-18 17:47:17 +00:00
|
|
|
dns_name_t *foundname)
|
|
|
|
{
|
|
|
|
isc_result_t result;
|
|
|
|
void *data;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Search for the deepest match in 'keytable'.
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
|
|
|
REQUIRE(dns_name_isabsolute(name));
|
|
|
|
REQUIRE(foundname != NULL);
|
|
|
|
|
|
|
|
RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
|
|
|
|
|
|
|
|
data = NULL;
|
2000-04-19 18:27:24 +00:00
|
|
|
result = dns_rbt_findname(keytable->table, name, 0, foundname, &data);
|
2000-04-18 17:47:17 +00:00
|
|
|
|
2019-09-16 21:06:23 -07:00
|
|
|
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
|
2000-04-18 17:47:17 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
2019-09-16 21:06:23 -07:00
|
|
|
}
|
2000-04-18 17:47:17 +00:00
|
|
|
|
|
|
|
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2009-12-03 15:40:03 +00:00
|
|
|
void
|
|
|
|
dns_keytable_attachkeynode(dns_keytable_t *keytable, dns_keynode_t *source,
|
|
|
|
dns_keynode_t **target)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Give back a keynode found via dns_keytable_findkeynode().
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
|
|
|
REQUIRE(VALID_KEYNODE(source));
|
|
|
|
REQUIRE(target != NULL && *target == NULL);
|
|
|
|
|
2019-07-23 09:52:02 -04:00
|
|
|
REQUIRE(atomic_fetch_add_relaxed(&keytable->active_nodes, 1) < UINT32_MAX);
|
2009-12-03 15:40:03 +00:00
|
|
|
|
|
|
|
dns_keynode_attach(source, target);
|
|
|
|
}
|
|
|
|
|
2000-02-23 23:31:33 +00:00
|
|
|
void
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep)
|
2000-02-23 23:31:33 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Give back a keynode found via dns_keytable_findkeynode().
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
|
|
|
REQUIRE(keynodep != NULL && VALID_KEYNODE(*keynodep));
|
|
|
|
|
2019-07-23 09:52:02 -04:00
|
|
|
REQUIRE(atomic_fetch_sub_release(&keytable->active_nodes, 1) > 0);
|
|
|
|
|
2009-06-30 02:53:46 +00:00
|
|
|
dns_keynode_detach(keytable->mctx, keynodep);
|
2000-02-23 23:31:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
2016-12-30 15:45:08 +11:00
|
|
|
dns_keytable_issecuredomain(dns_keytable_t *keytable, const dns_name_t *name,
|
2018-04-17 08:29:14 -07:00
|
|
|
dns_name_t *foundname, bool *wantdnssecp)
|
2000-02-23 23:31:33 +00:00
|
|
|
{
|
|
|
|
isc_result_t result;
|
2014-05-29 22:22:53 -07:00
|
|
|
dns_rbtnode_t *node = NULL;
|
2000-02-23 23:31:33 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Is 'name' at or beneath a trusted key?
|
|
|
|
*/
|
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
|
|
|
REQUIRE(dns_name_isabsolute(name));
|
|
|
|
REQUIRE(wantdnssecp != NULL);
|
|
|
|
|
|
|
|
RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
|
|
|
|
|
2014-05-29 22:22:53 -07:00
|
|
|
result = dns_rbt_findnode(keytable->table, name, foundname, &node,
|
|
|
|
NULL, DNS_RBTFIND_NOOPTIONS, NULL, NULL);
|
2000-02-23 23:31:33 +00:00
|
|
|
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
|
2014-05-29 22:22:53 -07:00
|
|
|
INSIST(node->data != NULL);
|
2018-04-17 08:29:14 -07:00
|
|
|
*wantdnssecp = true;
|
2000-03-16 23:57:02 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
2000-02-23 23:31:33 +00:00
|
|
|
} else if (result == ISC_R_NOTFOUND) {
|
2018-04-17 08:29:14 -07:00
|
|
|
*wantdnssecp = false;
|
2000-03-16 23:57:02 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
2000-02-23 23:31:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2015-02-05 17:18:15 -08:00
|
|
|
static isc_result_t
|
|
|
|
putstr(isc_buffer_t **b, const char *str) {
|
|
|
|
isc_result_t result;
|
|
|
|
|
|
|
|
result = isc_buffer_reserve(b, strlen(str));
|
2019-09-16 21:06:23 -07:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2015-02-05 17:18:15 -08:00
|
|
|
return (result);
|
2019-09-16 21:06:23 -07:00
|
|
|
}
|
2015-02-06 23:45:21 +00:00
|
|
|
|
2015-02-05 17:18:15 -08:00
|
|
|
isc_buffer_putstr(*b, str);
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2010-06-25 03:24:05 +00:00
|
|
|
isc_result_t
|
2015-02-05 17:18:15 -08:00
|
|
|
dns_keytable_dump(dns_keytable_t *keytable, FILE *fp) {
|
|
|
|
isc_result_t result;
|
|
|
|
isc_buffer_t *text = NULL;
|
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
|
|
|
REQUIRE(fp != NULL);
|
|
|
|
|
|
|
|
result = isc_buffer_allocate(keytable->mctx, &text, 4096);
|
|
|
|
if (result != ISC_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
|
|
|
|
result = dns_keytable_totext(keytable, &text);
|
|
|
|
|
|
|
|
if (isc_buffer_usedlength(text) != 0) {
|
|
|
|
(void) putstr(&text, "\n");
|
2019-09-16 21:06:23 -07:00
|
|
|
} else if (result == ISC_R_SUCCESS) {
|
2015-02-05 17:18:15 -08:00
|
|
|
(void) putstr(&text, "none");
|
2019-09-16 21:06:23 -07:00
|
|
|
} else {
|
2015-02-05 17:18:15 -08:00
|
|
|
(void) putstr(&text, "could not dump key table: ");
|
|
|
|
(void) putstr(&text, isc_result_totext(result));
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(fp, "%.*s", (int) isc_buffer_usedlength(text),
|
|
|
|
(char *) isc_buffer_base(text));
|
|
|
|
|
|
|
|
isc_buffer_free(&text);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2019-09-16 21:06:23 -07:00
|
|
|
static isc_result_t
|
|
|
|
keynode_dslist_totext(dns_name_t *name, dns_keynode_t *keynode,
|
|
|
|
isc_buffer_t **text)
|
|
|
|
{
|
|
|
|
isc_result_t result;
|
|
|
|
char namebuf[DNS_NAME_FORMATSIZE];
|
|
|
|
char obuf[DNS_NAME_FORMATSIZE + 200];
|
|
|
|
dns_rdataset_t *dsset = NULL;
|
|
|
|
|
|
|
|
dns_name_format(name, namebuf, sizeof(namebuf));
|
|
|
|
|
|
|
|
dsset = dns_keynode_dsset(keynode);
|
|
|
|
|
|
|
|
for (result = dns_rdataset_first(dsset);
|
|
|
|
result == ISC_R_SUCCESS;
|
|
|
|
result = dns_rdataset_next(dsset))
|
|
|
|
{
|
|
|
|
char algbuf[DNS_SECALG_FORMATSIZE];
|
|
|
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
|
|
|
dns_rdata_ds_t ds;
|
|
|
|
|
|
|
|
dns_rdataset_current(dsset, &rdata);
|
|
|
|
result = dns_rdata_tostruct(&rdata, &ds, NULL);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
|
|
|
|
dns_secalg_format(ds.algorithm, algbuf, sizeof(algbuf));
|
|
|
|
|
|
|
|
snprintf(obuf, sizeof(obuf), "%s/%s/%d ; %s%s (DS)\n",
|
|
|
|
namebuf, algbuf, ds.key_tag,
|
|
|
|
keynode->initial ? "initializing " : "",
|
|
|
|
keynode->managed ? "managed" : "static");
|
|
|
|
|
|
|
|
result = putstr(text, obuf);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2015-02-05 17:18:15 -08:00
|
|
|
isc_result_t
|
|
|
|
dns_keytable_totext(dns_keytable_t *keytable, isc_buffer_t **text) {
|
2010-06-25 03:24:05 +00:00
|
|
|
isc_result_t result;
|
|
|
|
dns_keynode_t *knode;
|
|
|
|
dns_rbtnode_t *node;
|
|
|
|
dns_rbtnodechain_t chain;
|
2019-09-16 21:06:23 -07:00
|
|
|
dns_name_t *foundname, *origin, *fullname;
|
|
|
|
dns_fixedname_t fixedfoundname, fixedorigin, fixedfullname;
|
2010-06-25 03:24:05 +00:00
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
2015-02-05 17:18:15 -08:00
|
|
|
REQUIRE(text != NULL && *text != NULL);
|
2010-06-25 03:24:05 +00:00
|
|
|
|
2019-09-16 21:06:23 -07:00
|
|
|
origin = dns_fixedname_initname(&fixedorigin);
|
|
|
|
fullname = dns_fixedname_initname(&fixedfullname);
|
|
|
|
foundname = dns_fixedname_initname(&fixedfoundname);
|
|
|
|
|
2010-06-25 03:24:05 +00:00
|
|
|
RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
|
2019-08-27 22:41:18 -07:00
|
|
|
dns_rbtnodechain_init(&chain);
|
2010-06-25 03:24:05 +00:00
|
|
|
result = dns_rbtnodechain_first(&chain, keytable->table, NULL, NULL);
|
2015-02-05 17:18:15 -08:00
|
|
|
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
|
2019-09-16 21:06:23 -07:00
|
|
|
if (result == ISC_R_NOTFOUND) {
|
2015-02-05 17:18:15 -08:00
|
|
|
result = ISC_R_SUCCESS;
|
2019-09-16 21:06:23 -07:00
|
|
|
}
|
2010-06-25 03:24:05 +00:00
|
|
|
goto cleanup;
|
2015-02-05 17:18:15 -08:00
|
|
|
}
|
2010-06-25 03:24:05 +00:00
|
|
|
for (;;) {
|
|
|
|
char pbuf[DST_KEY_FORMATSIZE];
|
|
|
|
|
2019-09-16 21:06:23 -07:00
|
|
|
dns_rbtnodechain_current(&chain, foundname, origin, &node);
|
|
|
|
|
|
|
|
knode = node->data;
|
|
|
|
if (knode != NULL && knode->dslist != NULL) {
|
|
|
|
result = dns_name_concatenate(foundname, origin,
|
|
|
|
fullname, NULL);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = keynode_dslist_totext(fullname, knode, text);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (; knode != NULL; knode = knode->next) {
|
2015-02-05 17:18:15 -08:00
|
|
|
char obuf[DNS_NAME_FORMATSIZE + 200];
|
2019-09-16 21:06:23 -07:00
|
|
|
|
|
|
|
if (knode->key == NULL) {
|
2014-02-27 16:42:35 -08:00
|
|
|
continue;
|
2019-09-16 21:06:23 -07:00
|
|
|
}
|
|
|
|
|
2010-06-25 03:24:05 +00:00
|
|
|
dst_key_format(knode->key, pbuf, sizeof(pbuf));
|
2017-10-27 15:45:18 -07:00
|
|
|
snprintf(obuf, sizeof(obuf), "%s ; %s%s\n", pbuf,
|
|
|
|
knode->initial ? "initializing " : "",
|
2018-08-15 16:59:45 -07:00
|
|
|
knode->managed ? "managed" : "static");
|
2019-09-16 21:06:23 -07:00
|
|
|
|
2015-02-05 17:18:15 -08:00
|
|
|
result = putstr(text, obuf);
|
2019-09-16 21:06:23 -07:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2015-02-05 17:18:15 -08:00
|
|
|
break;
|
2019-09-16 21:06:23 -07:00
|
|
|
}
|
2010-06-25 03:24:05 +00:00
|
|
|
}
|
2019-09-16 21:06:23 -07:00
|
|
|
|
2010-06-25 03:24:05 +00:00
|
|
|
result = dns_rbtnodechain_next(&chain, NULL, NULL);
|
|
|
|
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
|
2019-09-16 21:06:23 -07:00
|
|
|
if (result == ISC_R_NOMORE) {
|
2010-06-25 03:24:05 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
2019-09-16 21:06:23 -07:00
|
|
|
}
|
2010-06-25 03:24:05 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
dns_rbtnodechain_invalidate(&chain);
|
|
|
|
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2016-07-22 20:02:17 +10:00
|
|
|
isc_result_t
|
|
|
|
dns_keytable_forall(dns_keytable_t *keytable,
|
use DS-style trust anchor to verify 5011 key refresh query
note: this also needs further refactoring.
- when initializing RFC 5011 for a name, we populate the managed-keys
zone with KEYDATA records derived from the initial-key trust anchors.
however, with initial-ds trust anchors, there is no key. but the
managed-keys zone still must have a KEYDATA record for the name,
otherwise zone_refreshkeys() won't refresh that key. so, for
initial-ds trust anchors, we now add an empty KEYDATA record and set
the key refresh timer so that the real keys will be looked up as soon
as possible.
- when a key refresh query is done, we verify it against the
trust anchor; this is done in two ways, one with the DS RRset
set up during configuration if present, or with the keys linked
from each keynode in the list if not. because there are two different
verification methods, the loop structure is overly complex and should
be simplified.
- the keyfetch_done() and sync_keyzone() functions are both too long
and should be broken into smaller functions.
2019-09-17 09:09:41 -07:00
|
|
|
void (*func)(dns_keytable_t *, dns_keynode_t *,
|
|
|
|
dns_name_t *, void *),
|
2016-07-22 20:02:17 +10:00
|
|
|
void *arg)
|
|
|
|
{
|
|
|
|
isc_result_t result;
|
|
|
|
dns_rbtnode_t *node;
|
|
|
|
dns_rbtnodechain_t chain;
|
use DS-style trust anchor to verify 5011 key refresh query
note: this also needs further refactoring.
- when initializing RFC 5011 for a name, we populate the managed-keys
zone with KEYDATA records derived from the initial-key trust anchors.
however, with initial-ds trust anchors, there is no key. but the
managed-keys zone still must have a KEYDATA record for the name,
otherwise zone_refreshkeys() won't refresh that key. so, for
initial-ds trust anchors, we now add an empty KEYDATA record and set
the key refresh timer so that the real keys will be looked up as soon
as possible.
- when a key refresh query is done, we verify it against the
trust anchor; this is done in two ways, one with the DS RRset
set up during configuration if present, or with the keys linked
from each keynode in the list if not. because there are two different
verification methods, the loop structure is overly complex and should
be simplified.
- the keyfetch_done() and sync_keyzone() functions are both too long
and should be broken into smaller functions.
2019-09-17 09:09:41 -07:00
|
|
|
dns_fixedname_t fixedfoundname, fixedorigin, fixedfullname;
|
|
|
|
dns_name_t *foundname, *origin, *fullname;
|
2016-07-22 20:02:17 +10:00
|
|
|
|
|
|
|
REQUIRE(VALID_KEYTABLE(keytable));
|
|
|
|
|
use DS-style trust anchor to verify 5011 key refresh query
note: this also needs further refactoring.
- when initializing RFC 5011 for a name, we populate the managed-keys
zone with KEYDATA records derived from the initial-key trust anchors.
however, with initial-ds trust anchors, there is no key. but the
managed-keys zone still must have a KEYDATA record for the name,
otherwise zone_refreshkeys() won't refresh that key. so, for
initial-ds trust anchors, we now add an empty KEYDATA record and set
the key refresh timer so that the real keys will be looked up as soon
as possible.
- when a key refresh query is done, we verify it against the
trust anchor; this is done in two ways, one with the DS RRset
set up during configuration if present, or with the keys linked
from each keynode in the list if not. because there are two different
verification methods, the loop structure is overly complex and should
be simplified.
- the keyfetch_done() and sync_keyzone() functions are both too long
and should be broken into smaller functions.
2019-09-17 09:09:41 -07:00
|
|
|
origin = dns_fixedname_initname(&fixedorigin);
|
|
|
|
fullname = dns_fixedname_initname(&fixedfullname);
|
|
|
|
foundname = dns_fixedname_initname(&fixedfoundname);
|
|
|
|
|
2016-07-22 20:02:17 +10:00
|
|
|
RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
|
2019-08-27 22:41:18 -07:00
|
|
|
dns_rbtnodechain_init(&chain);
|
2016-07-22 20:02:17 +10:00
|
|
|
result = dns_rbtnodechain_first(&chain, keytable->table, NULL, NULL);
|
|
|
|
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
|
2019-09-16 21:06:23 -07:00
|
|
|
if (result == ISC_R_NOTFOUND) {
|
2016-07-22 20:02:17 +10:00
|
|
|
result = ISC_R_SUCCESS;
|
2019-09-16 21:06:23 -07:00
|
|
|
}
|
2016-07-22 20:02:17 +10:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2019-07-23 09:52:02 -04:00
|
|
|
REQUIRE(atomic_fetch_add_relaxed(&keytable->active_nodes, 1)
|
|
|
|
< UINT32_MAX);
|
2016-07-22 20:02:17 +10:00
|
|
|
for (;;) {
|
use DS-style trust anchor to verify 5011 key refresh query
note: this also needs further refactoring.
- when initializing RFC 5011 for a name, we populate the managed-keys
zone with KEYDATA records derived from the initial-key trust anchors.
however, with initial-ds trust anchors, there is no key. but the
managed-keys zone still must have a KEYDATA record for the name,
otherwise zone_refreshkeys() won't refresh that key. so, for
initial-ds trust anchors, we now add an empty KEYDATA record and set
the key refresh timer so that the real keys will be looked up as soon
as possible.
- when a key refresh query is done, we verify it against the
trust anchor; this is done in two ways, one with the DS RRset
set up during configuration if present, or with the keys linked
from each keynode in the list if not. because there are two different
verification methods, the loop structure is overly complex and should
be simplified.
- the keyfetch_done() and sync_keyzone() functions are both too long
and should be broken into smaller functions.
2019-09-17 09:09:41 -07:00
|
|
|
dns_rbtnodechain_current(&chain, foundname, origin, &node);
|
2019-09-16 21:06:23 -07:00
|
|
|
if (node->data != NULL) {
|
use DS-style trust anchor to verify 5011 key refresh query
note: this also needs further refactoring.
- when initializing RFC 5011 for a name, we populate the managed-keys
zone with KEYDATA records derived from the initial-key trust anchors.
however, with initial-ds trust anchors, there is no key. but the
managed-keys zone still must have a KEYDATA record for the name,
otherwise zone_refreshkeys() won't refresh that key. so, for
initial-ds trust anchors, we now add an empty KEYDATA record and set
the key refresh timer so that the real keys will be looked up as soon
as possible.
- when a key refresh query is done, we verify it against the
trust anchor; this is done in two ways, one with the DS RRset
set up during configuration if present, or with the keys linked
from each keynode in the list if not. because there are two different
verification methods, the loop structure is overly complex and should
be simplified.
- the keyfetch_done() and sync_keyzone() functions are both too long
and should be broken into smaller functions.
2019-09-17 09:09:41 -07:00
|
|
|
result = dns_name_concatenate(foundname, origin,
|
|
|
|
fullname, NULL);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
(*func)(keytable, node->data, fullname, arg);
|
2019-09-16 21:06:23 -07:00
|
|
|
}
|
2016-07-22 20:02:17 +10:00
|
|
|
result = dns_rbtnodechain_next(&chain, NULL, NULL);
|
|
|
|
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
|
2019-09-16 21:06:23 -07:00
|
|
|
if (result == ISC_R_NOMORE) {
|
2016-07-22 20:02:17 +10:00
|
|
|
result = ISC_R_SUCCESS;
|
2019-09-16 21:06:23 -07:00
|
|
|
}
|
2016-07-22 20:02:17 +10:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-07-23 09:52:02 -04:00
|
|
|
REQUIRE(atomic_fetch_sub_release(&keytable->active_nodes, 1) > 0);
|
2016-07-22 20:02:17 +10:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
dns_rbtnodechain_invalidate(&chain);
|
|
|
|
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2000-02-23 23:31:33 +00:00
|
|
|
dst_key_t *
|
|
|
|
dns_keynode_key(dns_keynode_t *keynode) {
|
|
|
|
REQUIRE(VALID_KEYNODE(keynode));
|
|
|
|
|
|
|
|
return (keynode->key);
|
|
|
|
}
|
2009-06-30 02:53:46 +00:00
|
|
|
|
2019-09-16 21:06:23 -07:00
|
|
|
dns_rdataset_t *
|
|
|
|
dns_keynode_dsset(dns_keynode_t *keynode) {
|
|
|
|
REQUIRE(VALID_KEYNODE(keynode));
|
|
|
|
|
|
|
|
if (keynode->dslist != NULL) {
|
|
|
|
return (&keynode->dsset);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2009-06-30 02:53:46 +00:00
|
|
|
dns_keynode_managed(dns_keynode_t *keynode) {
|
|
|
|
REQUIRE(VALID_KEYNODE(keynode));
|
|
|
|
|
|
|
|
return (keynode->managed);
|
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2017-10-27 15:45:18 -07:00
|
|
|
dns_keynode_initial(dns_keynode_t *keynode) {
|
|
|
|
REQUIRE(VALID_KEYNODE(keynode));
|
|
|
|
|
|
|
|
return (keynode->initial);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_keynode_trust(dns_keynode_t *keynode) {
|
|
|
|
REQUIRE(VALID_KEYNODE(keynode));
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
keynode->initial = false;
|
2017-10-27 15:45:18 -07:00
|
|
|
}
|
|
|
|
|
2009-06-30 02:53:46 +00:00
|
|
|
isc_result_t
|
|
|
|
dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target) {
|
2018-01-24 18:55:56 +11:00
|
|
|
dns_keynode_t *knode;
|
2009-06-30 02:53:46 +00:00
|
|
|
|
|
|
|
REQUIRE(target != NULL && *target == NULL);
|
|
|
|
|
|
|
|
knode = isc_mem_get(mctx, sizeof(dns_keynode_t));
|
|
|
|
|
|
|
|
knode->magic = KEYNODE_MAGIC;
|
2018-04-17 08:29:14 -07:00
|
|
|
knode->managed = false;
|
|
|
|
knode->initial = false;
|
2009-06-30 02:53:46 +00:00
|
|
|
knode->key = NULL;
|
2019-09-16 21:06:23 -07:00
|
|
|
knode->dslist = NULL;
|
|
|
|
dns_rdataset_init(&knode->dsset);
|
2009-06-30 02:53:46 +00:00
|
|
|
knode->next = NULL;
|
|
|
|
|
2018-08-01 11:46:11 +02:00
|
|
|
isc_refcount_init(&knode->refcount, 1);
|
2009-06-30 02:53:46 +00:00
|
|
|
|
|
|
|
*target = knode;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_keynode_attach(dns_keynode_t *source, dns_keynode_t **target) {
|
|
|
|
REQUIRE(VALID_KEYNODE(source));
|
2018-08-17 15:16:59 +02:00
|
|
|
isc_refcount_increment(&source->refcount);
|
2009-06-30 02:53:46 +00:00
|
|
|
*target = source;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2019-09-16 21:06:23 -07:00
|
|
|
dns_keynode_detach(isc_mem_t *mctx, dns_keynode_t **keynodep) {
|
|
|
|
REQUIRE(keynodep != NULL && VALID_KEYNODE(*keynodep));
|
|
|
|
dns_keynode_t *knode = *keynodep;
|
|
|
|
*keynodep = NULL;
|
2018-08-28 10:18:59 +02:00
|
|
|
|
2019-09-16 21:06:23 -07:00
|
|
|
if (isc_refcount_decrement(&knode->refcount) == 1) {
|
|
|
|
isc_refcount_destroy(&knode->refcount);
|
|
|
|
if (knode->key != NULL) {
|
|
|
|
dst_key_free(&knode->key);
|
|
|
|
}
|
|
|
|
if (knode->dslist != NULL) {
|
|
|
|
if (dns_rdataset_isassociated(&knode->dsset)) {
|
|
|
|
dns_rdataset_disassociate(&knode->dsset);
|
|
|
|
}
|
|
|
|
free_dslist(mctx, knode);
|
2018-08-28 10:18:59 +02:00
|
|
|
}
|
2019-09-16 21:06:23 -07:00
|
|
|
isc_mem_put(mctx, knode, sizeof(dns_keynode_t));
|
2009-06-30 02:53:46 +00:00
|
|
|
}
|
|
|
|
}
|
2009-12-03 15:40:03 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
dns_keynode_detachall(isc_mem_t *mctx, dns_keynode_t **keynode) {
|
|
|
|
dns_keynode_t *next = NULL, *node = *keynode;
|
|
|
|
REQUIRE(VALID_KEYNODE(node));
|
|
|
|
while (node != NULL) {
|
|
|
|
next = node->next;
|
|
|
|
dns_keynode_detach(mctx, &node);
|
|
|
|
node = next;
|
|
|
|
}
|
|
|
|
*keynode = NULL;
|
|
|
|
}
|