2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-30 14:07:59 +00:00

Merge branch '1237-keytable-refactoring' into 'master'

Resolve "refactor dns_keytable"

Closes #1237

See merge request isc-projects/bind9!2798
This commit is contained in:
Evan Hunt 2020-01-14 18:10:16 +00:00
commit 72b3b458d3
16 changed files with 646 additions and 1361 deletions

View File

@ -700,11 +700,12 @@ configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config,
}
static isc_result_t
ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **keyp,
dns_rdata_ds_t **dsp, const char **namestrp, isc_mem_t *mctx)
ta_fromconfig(const cfg_obj_t *key, bool *initialp, const char **namestrp,
unsigned char *digest, dns_rdata_ds_t *ds)
{
isc_result_t result;
dns_rdata_dnskey_t keystruct;
dns_rdata_ds_t *ds = NULL;
dns_rdata_t rdata = DNS_RDATA_INIT;
uint32_t rdata1, rdata2, rdata3;
const char *datastr = NULL, *namestr = NULL;
unsigned char data[4096];
@ -715,8 +716,6 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **keyp,
dns_fixedname_t fname;
dns_name_t *name = NULL;
isc_buffer_t namebuf;
isc_result_t result;
dst_key_t *dstkey = NULL;
const char *atstr = NULL;
enum {
INIT_DNSKEY,
@ -726,9 +725,8 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **keyp,
TRUSTED
} anchortype;
REQUIRE(keyp != NULL && *keyp == NULL);
REQUIRE(dsp != NULL && *dsp == NULL);
REQUIRE(namestrp != NULL && *namestrp == NULL);
REQUIRE(ds != NULL);
/* if DNSKEY, flags; if DS, key tag */
rdata1 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata1"));
@ -775,6 +773,13 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **keyp,
isc_buffer_init(&databuf, data, sizeof(data));
isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
*ds = (dns_rdata_ds_t){
.common.rdclass = dns_rdataclass_in,
.common.rdtype = dns_rdatatype_ds
};
ISC_LINK_INIT(&ds->common, link);
switch(anchortype) {
case INIT_DNSKEY:
case STATIC_DNSKEY:
@ -802,7 +807,7 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **keyp,
if (rdata2 > 0xff) {
CHECKM(ISC_R_RANGE, "key protocol");
}
if (rdata3> 0xff) {
if (rdata3 > 0xff) {
CHECKM(ISC_R_RANGE, "key algorithm");
}
@ -810,30 +815,25 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **keyp,
keystruct.protocol = (uint8_t)rdata2;
keystruct.algorithm = (uint8_t)rdata3;
if (!dst_algorithm_supported(keystruct.algorithm)) {
CHECK(DST_R_UNSUPPORTEDALG);
}
datastr = cfg_obj_asstring(cfg_tuple_get(key, "data"));
CHECK(isc_base64_decodestring(datastr, &databuf));
isc_buffer_usedregion(&databuf, &r);
keystruct.datalen = r.length;
keystruct.data = r.base;
CHECK(dns_rdata_fromstruct(NULL, keystruct.common.rdclass,
CHECK(dns_rdata_fromstruct(&rdata, keystruct.common.rdclass,
keystruct.common.rdtype,
&keystruct, &rrdatabuf));
CHECK(dst_key_fromdns(name, dns_rdataclass_in,
&rrdatabuf, mctx, &dstkey));
*keyp = dstkey;
CHECK(dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256,
digest, ds));
break;
case INIT_DS:
case STATIC_DS:
ds = isc_mem_get(mctx, sizeof(*ds));
ds->common.rdclass = dns_rdataclass_in;
ds->common.rdtype = dns_rdatatype_ds;
ds->mctx = NULL;
ISC_LINK_INIT(&ds->common, link);
if (rdata1 > 0xffff) {
CHECKM(ISC_R_RANGE, "key tag");
}
@ -878,13 +878,10 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **keyp,
break;
}
ds->mctx = mctx;
ds->length = r.length;
ds->digest = isc_mem_allocate(mctx, r.length);
ds->digest = digest;
memmove(ds->digest, r.base, r.length);
*dsp = ds;
ds = NULL;
break;
default:
@ -895,15 +892,6 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **keyp,
return (ISC_R_SUCCESS);
cleanup:
if (dstkey != NULL) {
dst_key_free(&dstkey);
}
if (ds != NULL) {
dns_rdata_freestruct(ds);
isc_mem_put(mctx, ds, sizeof(*ds));
}
return (result);
}
@ -921,46 +909,30 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **keyp,
static isc_result_t
process_key(const cfg_obj_t *key, dns_keytable_t *secroots,
const dns_name_t *keyname_match, dns_resolver_t *resolver,
bool managed, isc_mem_t *mctx)
bool managed)
{
dns_fixedname_t fkeyname;
dns_name_t *keyname = NULL;
const char *namestr = NULL;
dst_key_t *dstkey = NULL;
dns_rdata_ds_t *ds = NULL;
unsigned int keyalg;
dns_rdata_ds_t ds;
isc_result_t result;
bool initializing = managed;
unsigned char digest[ISC_MAX_MD_SIZE];
isc_buffer_t b;
result = ta_fromconfig(key, &initializing, &dstkey, &ds,
&namestr, mctx);
result = ta_fromconfig(key, &initializing, &namestr, digest, &ds);
switch (result) {
case ISC_R_SUCCESS:
/*
* Trust anchor was parsed correctly. If dstkey is
* not NULL, then it was a key anchor, its algorithm
* is supported by the crypto library, and it is not
* revoked. If dstkey is NULL, then it was a DS
* trust anchor instead.
* Trust anchor was parsed correctly.
*/
if (dstkey != NULL) {
keyname = dst_key_name(dstkey);
keyalg = dst_key_alg(dstkey);
} else {
isc_buffer_t b;
INSIST(ds != NULL);
isc_buffer_constinit(&b, namestr, strlen(namestr));
isc_buffer_add(&b, strlen(namestr));
keyname = dns_fixedname_initname(&fkeyname);
result = dns_name_fromtext(keyname, &b,
dns_rootname, 0, NULL);
if (result != ISC_R_SUCCESS) {
return (result);
}
keyalg = ds->algorithm;
isc_buffer_constinit(&b, namestr, strlen(namestr));
isc_buffer_add(&b, strlen(namestr));
keyname = dns_fixedname_initname(&fkeyname);
result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL);
if (result != ISC_R_SUCCESS) {
return (result);
}
break;
case DST_R_UNSUPPORTEDALG:
@ -1011,7 +983,8 @@ process_key(const cfg_obj_t *key, dns_keytable_t *secroots,
* its owner name. If it does not, do not load the key and log a
* warning, but do not prevent further keys from being processed.
*/
if (!dns_resolver_algorithm_supported(resolver, keyname, keyalg)) {
if (!dns_resolver_algorithm_supported(resolver, keyname, ds.algorithm))
{
cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING,
"ignoring %s for '%s': algorithm is disabled",
initializing ? "initial-key" : "static-key",
@ -1026,29 +999,10 @@ process_key(const cfg_obj_t *key, dns_keytable_t *secroots,
* managed, so we use 'initializing' twice here, for both the
* 'managed' and 'initializing' arguments to dns_keytable_add().
*/
result = dns_keytable_add(secroots, initializing,
initializing, keyname,
dstkey != NULL ? &dstkey : NULL,
ds);
result = dns_keytable_add(secroots, initializing, initializing,
keyname, &ds);
done:
/*
* Ensure 'dstkey' does not leak. Note that if dns_keytable_add()
* succeeds, ownership of the key structure is transferred to the key
* table, i.e. 'dstkey' is set to NULL.
*/
if (dstkey != NULL) {
dst_key_free(&dstkey);
}
/*
* Free 'ds'.
*/
if (ds != NULL) {
dns_rdata_freestruct(ds);
isc_mem_put(mctx, ds, sizeof(*ds));
}
return (result);
}
@ -1059,7 +1013,7 @@ process_key(const cfg_obj_t *key, dns_keytable_t *secroots,
*/
static isc_result_t
load_view_keys(const cfg_obj_t *keys, dns_view_t *view, bool managed,
const dns_name_t *keyname, isc_mem_t *mctx)
const dns_name_t *keyname)
{
const cfg_listelt_t *elt, *elt2;
const cfg_obj_t *keylist;
@ -1078,9 +1032,8 @@ load_view_keys(const cfg_obj_t *keys, dns_view_t *view, bool managed,
elt2 != NULL;
elt2 = cfg_list_next(elt2))
{
CHECK(process_key(cfg_listelt_value(elt2),
secroots, keyname, view->resolver,
managed, mctx));
CHECK(process_key(cfg_listelt_value(elt2), secroots,
keyname, view->resolver, managed));
}
}
@ -1238,7 +1191,7 @@ configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig,
if (builtin_keys != NULL) {
CHECK(load_view_keys(builtin_keys, view, true,
dns_rootname, mctx));
dns_rootname));
}
if (!keyloaded(view, dns_rootname)) {
@ -1251,17 +1204,13 @@ configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig,
}
if (view->rdclass == dns_rdataclass_in) {
CHECK(load_view_keys(view_keys, view, false, NULL, mctx));
CHECK(load_view_keys(view_trust_anchors, view, true, NULL,
mctx));
CHECK(load_view_keys(view_managed_keys, view, true, NULL,
mctx));
CHECK(load_view_keys(view_keys, view, false, NULL));
CHECK(load_view_keys(view_trust_anchors, view, true, NULL));
CHECK(load_view_keys(view_managed_keys, view, true, NULL));
CHECK(load_view_keys(global_keys, view, false, NULL, mctx));
CHECK(load_view_keys(global_trust_anchors, view, true,
NULL, mctx));
CHECK(load_view_keys(global_managed_keys, view, true,
NULL, mctx));
CHECK(load_view_keys(global_keys, view, false, NULL));
CHECK(load_view_keys(global_trust_anchors, view, true, NULL));
CHECK(load_view_keys(global_managed_keys, view, true, NULL));
}
/*
@ -6835,11 +6784,7 @@ struct dotat_arg {
* reported in the TAT query.
*/
static isc_result_t
get_tat_qname(dns_name_t *target, dns_name_t *keyname,
dns_keytable_t *keytable, dns_keynode_t *keynode)
{
dns_keynode_t *firstnode = keynode;
dns_keynode_t *nextnode = NULL;
get_tat_qname(dns_name_t *target, dns_name_t *keyname, dns_keynode_t *keynode) {
dns_rdataset_t *dsset = NULL;
unsigned int i, n = 0;
uint16_t ids[12];
@ -6866,23 +6811,6 @@ get_tat_qname(dns_name_t *target, dns_name_t *keyname,
n++;
}
}
} else {
do {
dst_key_t *key = dns_keynode_key(keynode);
if (key != NULL) {
if (n < (sizeof(ids)/sizeof(ids[0]))) {
ids[n] = dst_key_id(key);
n++;
}
}
nextnode = NULL;
(void)dns_keytable_nextkeynode(keytable, keynode,
&nextnode);
if (keynode != firstnode) {
dns_keytable_detachkeynode(keytable, &keynode);
}
keynode = nextnode;
} while (keynode != NULL);
}
if (n == 0) {
@ -6938,7 +6866,7 @@ dotat(dns_keytable_t *keytable, dns_keynode_t *keynode,
task = dotat_arg->task;
tatname = dns_fixedname_initname(&fixed);
result = get_tat_qname(tatname, keyname, keytable, keynode);
result = get_tat_qname(tatname, keyname, keynode);
if (result != ISC_R_SUCCESS) {
return;
}

View File

@ -3700,12 +3700,12 @@ status=$((status+ret))
# DNSSEC tests related to unsupported, disabled and revoked trust anchors.
#
# This nameserver (ns8) is loaded with a bunch of trust anchors. Some of them
# are good (enabled.managed, enabled.trusted, secure.managed, secure.trusted),
# and some of them are bad (disabled.managed, revoked.managed, unsupported.managed,
# disabled.trusted, revoked.trusted, unsupported.trusted). Make sure that the bad
# trust anchors are ignored. This is tested by looking for the corresponding
# lines in the logfile.
# This nameserver (ns8) is loaded with a bunch of trust anchors. Some of
# them are good (enabled.managed, enabled.trusted, secure.managed,
# secure.trusted), and some of them are bad (disabled.managed,
# revoked.managed, unsupported.managed, disabled.trusted, revoked.trusted,
# unsupported.trusted). Make sure that the bad trust anchors are ignored.
# This is tested by looking for the corresponding lines in the logfile.
echo_i "checking that keys with unsupported algorithms and disabled algorithms are ignored ($n)"
ret=0
grep -q "ignoring static-key for 'disabled\.trusted\.': algorithm is disabled" ns8/named.run || ret=1

View File

@ -14,6 +14,7 @@
#include <isc/app.h>
#include <isc/buffer.h>
#include <isc/md.h>
#include <isc/mem.h>
#include <isc/mutex.h>
#include <isc/portset.h>
@ -1498,6 +1499,7 @@ dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass,
dns_keytable_t *secroots = NULL;
dns_name_t *name = NULL;
char dsbuf[DNS_DS_BUFFERSIZE];
unsigned char digest[ISC_MAX_MD_SIZE];
dns_rdata_ds_t ds;
dns_decompress_t dctx;
dns_rdata_t rdata;
@ -1515,33 +1517,28 @@ dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass,
DE_CONST(keyname, name);
switch (rdtype) {
case dns_rdatatype_dnskey:
result = dst_key_fromdns(keyname, rdclass, databuf,
client->mctx, &dstkey);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
CHECK(dns_keytable_add(secroots, false, false,
name, &dstkey, NULL));
break;
case dns_rdatatype_ds:
isc_buffer_init(&b, dsbuf, sizeof(dsbuf));
dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
dns_rdata_init(&rdata);
isc_buffer_setactive(databuf, isc_buffer_usedlength(databuf));
CHECK(dns_rdata_fromwire(&rdata, rdclass, rdtype,
databuf, &dctx, 0, &b));
dns_decompress_invalidate(&dctx);
CHECK(dns_rdata_tostruct(&rdata, &ds, NULL));
CHECK(dns_keytable_add(secroots, false, false,
name, NULL, &ds));
break;
default:
if (rdtype != dns_rdatatype_dnskey && rdtype != dns_rdatatype_ds) {
result = ISC_R_NOTIMPLEMENTED;
goto cleanup;
}
isc_buffer_init(&b, dsbuf, sizeof(dsbuf));
dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
dns_rdata_init(&rdata);
isc_buffer_setactive(databuf, isc_buffer_usedlength(databuf));
CHECK(dns_rdata_fromwire(&rdata, rdclass, rdtype,
databuf, &dctx, 0, &b));
dns_decompress_invalidate(&dctx);
if (rdtype == dns_rdatatype_ds) {
CHECK(dns_rdata_tostruct(&rdata, &ds, NULL));
} else {
CHECK(dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256,
digest, &ds));
}
CHECK(dns_keytable_add(secroots, false, false, name, &ds));
cleanup:
if (dstkey != NULL) {
dst_key_free(&dstkey);

View File

@ -29,20 +29,17 @@
#include <dst/dst.h>
isc_result_t
dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
dns_dsdigest_t digest_type, unsigned char *buffer,
dns_rdata_t *rdata)
dns_ds_fromkeyrdata(const dns_name_t *owner, dns_rdata_t *key,
dns_dsdigest_t digest_type, unsigned char *digest,
dns_rdata_ds_t *dsrdata)
{
isc_result_t result;
dns_fixedname_t fname;
dns_name_t *name;
unsigned char digest[ISC_MAX_MD_SIZE];
unsigned int digestlen;
isc_region_t r;
isc_buffer_t b;
dns_rdata_ds_t ds;
isc_md_t *md;
isc_md_type_t md_type = 0;
isc_result_t ret;
REQUIRE(key != NULL);
REQUIRE(key->type == dns_rdatatype_dnskey ||
@ -73,51 +70,68 @@ dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
name = dns_fixedname_initname(&fname);
(void)dns_name_downcase(owner, name, NULL);
memset(buffer, 0, DNS_DS_BUFFERSIZE);
isc_buffer_init(&b, buffer, DNS_DS_BUFFERSIZE);
md = isc_md_new();
if (md == NULL) {
return (ISC_R_NOMEMORY);
}
ret = isc_md_init(md, md_type);
if (ret != ISC_R_SUCCESS) {
result = isc_md_init(md, md_type);
if (result != ISC_R_SUCCESS) {
goto end;
}
dns_name_toregion(name, &r);
ret = isc_md_update(md, r.base, r.length);
if (ret != ISC_R_SUCCESS) {
result = isc_md_update(md, r.base, r.length);
if (result != ISC_R_SUCCESS) {
goto end;
}
dns_rdata_toregion(key, &r);
INSIST(r.length >= 4);
ret = isc_md_update(md, r.base, r.length);
if (ret != ISC_R_SUCCESS) {
result = isc_md_update(md, r.base, r.length);
if (result != ISC_R_SUCCESS) {
goto end;
}
ret = isc_md_final(md, digest, &digestlen);
if (ret != ISC_R_SUCCESS) {
result = isc_md_final(md, digest, &digestlen);
if (result != ISC_R_SUCCESS) {
goto end;
}
ds.mctx = NULL;
ds.common.rdclass = key->rdclass;
ds.common.rdtype = dns_rdatatype_ds;
ds.algorithm = r.base[3];
ds.key_tag = dst_region_computeid(&r);
ds.digest_type = digest_type;
ds.digest = digest;
ds.length = digestlen;
dsrdata->mctx = NULL;
dsrdata->common.rdclass = key->rdclass;
dsrdata->common.rdtype = dns_rdatatype_ds;
dsrdata->algorithm = r.base[3];
dsrdata->key_tag = dst_region_computeid(&r);
dsrdata->digest_type = digest_type;
dsrdata->digest = digest;
dsrdata->length = digestlen;
ret = dns_rdata_fromstruct(rdata, key->rdclass, dns_rdatatype_ds,
&ds, &b);
end:
isc_md_free(md);
return (ret);
return (result);
}
isc_result_t
dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
dns_dsdigest_t digest_type, unsigned char *buffer,
dns_rdata_t *rdata)
{
isc_result_t result;
unsigned char digest[ISC_MAX_MD_SIZE];
dns_rdata_ds_t ds;
isc_buffer_t b;
result = dns_ds_fromkeyrdata(owner, key, digest_type, digest, &ds);
if (result != ISC_R_SUCCESS) {
return (result);
}
memset(buffer, 0, DNS_DS_BUFFERSIZE);
isc_buffer_init(&b, buffer, DNS_DS_BUFFERSIZE);
result = dns_rdata_fromstruct(rdata, key->rdclass, dns_rdatatype_ds,
&ds, &b);
return (result);
}

View File

@ -15,6 +15,7 @@
#include <isc/lang.h>
#include <dns/rdatastruct.h>
#include <dns/types.h>
#define DNS_DSDIGEST_SHA1 (1)
@ -29,16 +30,30 @@
ISC_LANG_BEGINDECLS
isc_result_t
dns_ds_fromkeyrdata(const dns_name_t *owner, dns_rdata_t *key,
dns_dsdigest_t digest_type, unsigned char *digest,
dns_rdata_ds_t *dsrdata);
/*%<
* Build a DS rdata structure from a key.
*
* Requires:
*\li key Points to a valid DNSKEY or CDNSKEY record.
*\li buffer Points to a buffer of at least
* #ISC_MAX_MD_SIZE bytes.
*/
isc_result_t
dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
dns_dsdigest_t digest_type, unsigned char *buffer,
dns_rdata_t *rdata);
/*%<
* Build the rdata of a DS record.
* Similar to dns_ds_fromkeyrdata(), but copies the DS into a
* dns_rdata object.
*
* Requires:
*\li key Points to a valid DNSKEY or CDNSKEY record.
*\li buffer Points to a temporary buffer of at least
*\li buffer Points to a buffer of at least
* #DNS_DS_BUFFERSIZE bytes.
*\li rdata Points to an initialized dns_rdata_t.
*

View File

@ -106,13 +106,11 @@ dns_keytable_detach(dns_keytable_t **keytablep);
*/
isc_result_t
dns_keytable_add(dns_keytable_t *keytable,
bool managed, bool initial,
dns_name_t *name, dst_key_t **keyp, dns_rdata_ds_t *ds);
dns_keytable_add(dns_keytable_t *keytable, bool managed, bool initial,
dns_name_t *name, dns_rdata_ds_t *ds);
/*%<
* Add a key to 'keytable'. The keynode associated with 'name'
* is updated with either the key referenced in '*keyp'
* or with the DS specified in 'ds'.
* is updated with the DS specified in 'ds'.
*
* The value of keynode->managed is set to 'managed', and the
* value of keynode->initial is set to 'initial'. (Note: 'initial'
@ -123,28 +121,15 @@ dns_keytable_add(dns_keytable_t *keytable,
*
* Notes:
*
*\li Ownership of *keyp is transferred to the keytable.
*\li If 'keyp' is not NULL and DS-style keys already exist
* in the table for this name, they are freed before adding
* the new key.
*\li If 'ds' is not NULL and key-style keys already exist
* in the table for this name, return ISC_R_EXISTS. DS keys
* can be updated to key-style, but not vice versa.
*\li If the key already exists in the table, ISC_R_EXISTS is
* returned and the new key is freed.
*\li If the key already exists in the table, adding it again
* has no effect and ISC_R_SUCCESS is returned.
*
* Requires:
*
*\li 'keytable' points to a valid keytable.
*
*\li 'ds' is not NULL.
*\li if 'initial' is true then 'managed' must also be true.
*
*\li keyp != NULL && *keyp is a valid dst_key_t *.
*
* Ensures:
*
*\li On success, *keyp == NULL
*
* Returns:
*
*\li ISC_R_SUCCESS
@ -185,7 +170,7 @@ dns_keytable_marksecure(dns_keytable_t *keytable, const dns_name_t *name);
isc_result_t
dns_keytable_delete(dns_keytable_t *keytable, const dns_name_t *keyname);
/*%<
* Delete node(s) from 'keytable' matching name 'keyname'
* Delete all trust anchors from 'keytable' matching name 'keyname'
*
* Requires:
*
@ -201,15 +186,16 @@ dns_keytable_delete(dns_keytable_t *keytable, const dns_name_t *keyname);
*/
isc_result_t
dns_keytable_deletekeynode(dns_keytable_t *keytable, dst_key_t *dstkey);
dns_keytable_deletekey(dns_keytable_t *keytable, const dns_name_t *keyname,
dns_rdata_dnskey_t *dnskey);
/*%<
* Delete node(s) from 'keytable' containing copies of the key pointed
* to by 'dstkey'
* Remove the trust anchor matching the name 'keyname' and the DNSKEY
* rdata struct 'dnskey' from 'keytable'.
*
* Requires:
*
*\li 'keytable' points to a valid keytable.
*\li 'dstkey' is not NULL
*\li 'dnskey' is not NULL
*
* Returns:
*
@ -222,9 +208,8 @@ isc_result_t
dns_keytable_find(dns_keytable_t *keytable, const dns_name_t *keyname,
dns_keynode_t **keynodep);
/*%<
* Search for the first instance of a key named 'name' in 'keytable',
* without regard to keyid and algorithm. Use dns_keytable_nextkeynode()
* to find subsequent instances.
* Search for the first instance of a trust anchor named 'name' in
* 'keytable', without regard to keyid and algorithm.
*
* Requires:
*
@ -242,78 +227,6 @@ dns_keytable_find(dns_keytable_t *keytable, const dns_name_t *keyname,
*\li Any other result indicates an error.
*/
isc_result_t
dns_keytable_nextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
dns_keynode_t **nextnodep);
/*%<
* Return for the next key after 'keynode' in 'keytable', without regard to
* keyid and algorithm.
*
* Requires:
*
*\li 'keytable' is a valid keytable.
*
*\li 'keynode' is a valid keynode.
*
*\li nextnodep != NULL && *nextnodep == NULL
*
* Returns:
*
*\li ISC_R_SUCCESS
*\li ISC_R_NOTFOUND
*
*\li Any other result indicates an error.
*/
isc_result_t
dns_keytable_findkeynode(dns_keytable_t *keytable, const dns_name_t *name,
dns_secalg_t algorithm, dns_keytag_t tag,
dns_keynode_t **keynodep);
/*%<
* Search for a key named 'name', matching 'algorithm' and 'tag' in
* 'keytable'. This finds the first instance which matches. Use
* dns_keytable_findnextkeynode() to find other instances.
*
* Requires:
*
*\li 'keytable' is a valid keytable.
*
*\li 'name' is a valid absolute name.
*
*\li keynodep != NULL && *keynodep == NULL
*
* Returns:
*
*\li ISC_R_SUCCESS
*\li DNS_R_PARTIALMATCH the name existed in the keytable.
*\li ISC_R_NOTFOUND
*
*\li Any other result indicates an error.
*/
isc_result_t
dns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
dns_keynode_t **nextnodep);
/*%<
* Search for the next key with the same properties as 'keynode' in
* 'keytable' as found by dns_keytable_findkeynode().
*
* Requires:
*
*\li 'keytable' is a valid keytable.
*
*\li 'keynode' is a valid keynode.
*
*\li nextnodep != NULL && *nextnodep == NULL
*
* Returns:
*
*\li ISC_R_SUCCESS
*\li ISC_R_NOTFOUND
*
*\li Any other result indicates an error.
*/
isc_result_t
dns_keytable_finddeepestmatch(dns_keytable_t *keytable, const dns_name_t *name,
dns_name_t *foundname);
@ -337,33 +250,13 @@ dns_keytable_finddeepestmatch(dns_keytable_t *keytable, const dns_name_t *name,
*/
void
dns_keytable_attachkeynode(dns_keytable_t *keytable, dns_keynode_t *source,
dns_keynode_t **target);
dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep);
/*%<
* Attach a keynode and and increment the active_nodes counter in a
* corresponding keytable.
* Detach a keynode found via dns_keytable_find().
*
* Requires:
*
*\li 'keytable' is a valid keytable.
*
*\li 'source' is a valid keynode.
*
*\li 'target' is not null and '*target' is null.
*/
void
dns_keytable_detachkeynode(dns_keytable_t *keytable,
dns_keynode_t **keynodep);
/*%<
* Give back a keynode found via dns_keytable_findkeynode().
*
* Requires:
*
*\li 'keytable' is a valid keytable.
*
*\li *keynodep is a valid keynode returned by a call to
* dns_keytable_findkeynode().
*\li *keynodep is a valid keynode returned by a call to dns_keytable_find().
*
* Ensures:
*
@ -412,12 +305,6 @@ dns_keytable_totext(dns_keytable_t *keytable, isc_buffer_t **buf);
* Dump the keytable to buffer at 'buf'
*/
dst_key_t *
dns_keynode_key(dns_keynode_t *keynode);
/*%<
* Get the DST key associated with keynode.
*/
dns_rdataset_t *
dns_keynode_dsset(dns_keynode_t *keynode);
/*%<
@ -450,31 +337,6 @@ dns_keynode_trust(dns_keynode_t *keynode);
* trusted: no longer an initializing key.
*/
isc_result_t
dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target);
/*%<
* Allocate space for a keynode
*/
void
dns_keynode_attach(dns_keynode_t *source, dns_keynode_t **target);
/*%<
* Attach keynode 'source' to '*target'
*/
void
dns_keynode_detach(isc_mem_t *mctx, dns_keynode_t **target);
/*%<
* Detach a single keynode, without touching any keynodes that
* may be pointed to by its 'next' pointer
*/
void
dns_keynode_detachall(isc_mem_t *mctx, dns_keynode_t **target);
/*%<
* Detach a keynode and all its succesors.
*/
isc_result_t
dns_keytable_forall(dns_keytable_t *keytable,
void (*func)(dns_keytable_t *, dns_keynode_t *,

View File

@ -128,6 +128,7 @@ struct dns_validator {
dns_validator_t * subvalidator;
dns_validator_t * parent;
dns_keytable_t * keytable;
dns_keynode_t * keynode;
dst_key_t * key;
dns_rdata_rrsig_t * siginfo;
isc_task_t * task;

View File

@ -1221,7 +1221,7 @@ dns_view_ntacovers(dns_view_t *view, isc_stdtime_t now,
void
dns_view_untrust(dns_view_t *view, const dns_name_t *keyname,
dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx);
dns_rdata_dnskey_t *dnskey);
/*%<
* Remove keys that match 'keyname' and 'dnskey' from the views trust
* anchors.
@ -1235,7 +1235,6 @@ dns_view_untrust(dns_view_t *view, const dns_name_t *keyname,
* Requires:
* \li 'view' is valid.
* \li 'keyname' is valid.
* \li 'mctx' is valid.
* \li 'dnskey' is valid.
*/

View File

@ -21,6 +21,7 @@
#include <isc/string.h> /* Required for HP/UX (and others?) */
#include <isc/util.h>
#include <dns/dnssec.h>
#include <dns/keytable.h>
#include <dns/fixedname.h>
#include <dns/rbt.h>
@ -40,7 +41,6 @@ struct dns_keytable {
/* Unlocked. */
unsigned int magic;
isc_mem_t *mctx;
atomic_uint_fast32_t active_nodes;
isc_refcount_t references;
isc_rwlock_t rwlock;
/* Locked by rwlock. */
@ -50,20 +50,58 @@ struct dns_keytable {
struct dns_keynode {
unsigned int magic;
isc_refcount_t refcount;
dst_key_t *key;
dns_rdatalist_t *dslist;
dns_rdataset_t dsset;
bool managed;
bool initial;
struct dns_keynode *next;
};
static void
keynode_attach(dns_keynode_t *source, dns_keynode_t **target) {
REQUIRE(VALID_KEYNODE(source));
isc_refcount_increment(&source->refcount);
*target = source;
}
static void
keynode_detach(isc_mem_t *mctx, dns_keynode_t **keynodep) {
REQUIRE(keynodep != NULL && VALID_KEYNODE(*keynodep));
dns_keynode_t *knode = *keynodep;
*keynodep = NULL;
if (isc_refcount_decrement(&knode->refcount) == 1) {
dns_rdata_t *rdata = NULL;
isc_refcount_destroy(&knode->refcount);
if (knode->dslist != NULL) {
if (dns_rdataset_isassociated(&knode->dsset)) {
dns_rdataset_disassociate(&knode->dsset);
}
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;
}
isc_mem_put(mctx, knode, sizeof(dns_keynode_t));
}
}
static void
free_keynode(void *node, void *arg) {
dns_keynode_t *keynode = node;
isc_mem_t *mctx = arg;
dns_keynode_detachall(mctx, &keynode);
keynode_detach(mctx, &keynode);
}
isc_result_t
@ -90,7 +128,6 @@ dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep) {
goto cleanup_rbt;
}
atomic_init(&keytable->active_nodes, 0);
isc_refcount_init(&keytable->references, 1);
keytable->mctx = NULL;
@ -111,11 +148,6 @@ dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep) {
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);
@ -132,7 +164,6 @@ dns_keytable_detach(dns_keytable_t **keytablep) {
if (isc_refcount_decrement(&keytable->references) == 1) {
isc_refcount_destroy(&keytable->references);
REQUIRE(atomic_load_acquire(&keytable->active_nodes) == 0);
dns_rbt_destroy(&keytable->table);
isc_rwlock_destroy(&keytable->rwlock);
keytable->magic = 0;
@ -141,164 +172,160 @@ dns_keytable_detach(dns_keytable_t **keytablep) {
}
}
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;
}
/*%
* 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.
*/
static isc_result_t
update_keynode(dns_keytable_t *keytable, dns_rbtnode_t *node,
dst_key_t **keyp, bool initial)
{
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) {
/*
* Null or DS-style keynode found. Detach
* the DS rdatalist if present. Attach the
* supplied key to it, transferring key
* ownership to the keytable.
*/
if (knode->dslist != NULL) {
free_dslist(keytable->mctx, knode);
}
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);
} else {
continue;
}
if (!initial) {
dns_keynode_trust(knode);
}
return (ISC_R_SUCCESS);
}
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
prepend_keynode(dst_key_t **keyp, dns_rdata_ds_t *ds,
dns_rbtnode_t *node, dns_keytable_t *keytable,
bool managed, bool initial)
{
dns_keynode_t *knode = NULL;
add_ds(dns_keynode_t *knode, dns_rdata_ds_t *ds, isc_mem_t *mctx) {
isc_result_t result;
dns_rdata_t *dsrdata = NULL, *rdata = NULL;
void *data = NULL;
bool exists = false;
isc_buffer_t b;
REQUIRE(keyp == NULL || *keyp != NULL);
REQUIRE(VALID_KEYTABLE(keytable));
REQUIRE(!initial || managed);
if (knode->dslist == NULL) {
knode->dslist = isc_mem_get(mctx, sizeof(*knode->dslist));
dns_rdatalist_init(knode->dslist);
knode->dslist->rdclass = dns_rdataclass_in;
knode->dslist->type = dns_rdatatype_ds;
}
result = dns_keynode_create(keytable->mctx, &knode);
dsrdata = isc_mem_get(mctx, sizeof(*dsrdata));
dns_rdata_init(dsrdata);
data = isc_mem_get(mctx, DNS_DS_BUFFERSIZE);
isc_buffer_init(&b, data, DNS_DS_BUFFERSIZE);
result = dns_rdata_fromstruct(dsrdata, dns_rdataclass_in,
dns_rdatatype_ds, ds, &b);
if (result != ISC_R_SUCCESS) {
return (result);
}
for (rdata = ISC_LIST_HEAD(knode->dslist->rdata);
rdata != NULL;
rdata = ISC_LIST_NEXT(rdata, link))
{
if (dns_rdata_compare(rdata, dsrdata) == 0) {
exists = true;
break;
}
}
if (exists) {
isc_mem_put(mctx, dsrdata->data, DNS_DS_BUFFERSIZE);
isc_mem_put(mctx, dsrdata, sizeof(*dsrdata));
return (ISC_R_SUCCESS);
}
ISC_LIST_APPEND(knode->dslist->rdata, dsrdata, 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;
return (ISC_R_SUCCESS);
}
static isc_result_t
delete_ds(dns_keynode_t *knode, dns_rdata_ds_t *ds, isc_mem_t *mctx) {
isc_result_t result;
dns_rdata_t dsrdata = DNS_RDATA_INIT;
dns_rdata_t *rdata = NULL;
unsigned char data[DNS_DS_BUFFERSIZE];
bool found = false;
isc_buffer_t b;
if (knode->dslist == NULL) {
return (ISC_R_SUCCESS);
}
isc_buffer_init(&b, data, DNS_DS_BUFFERSIZE);
result = dns_rdata_fromstruct(&dsrdata, dns_rdataclass_in,
dns_rdatatype_ds, ds, &b);
if (result != ISC_R_SUCCESS) {
return (result);
}
for (rdata = ISC_LIST_HEAD(knode->dslist->rdata);
rdata != NULL;
rdata = ISC_LIST_NEXT(rdata, link))
{
if (dns_rdata_compare(rdata, &dsrdata) == 0) {
ISC_LIST_UNLINK(knode->dslist->rdata, rdata, link);
isc_mem_put(mctx, rdata->data, DNS_DS_BUFFERSIZE);
isc_mem_put(mctx, rdata, sizeof(*rdata));
found = true;
break;
}
}
if (found) {
return (ISC_R_SUCCESS);
} else {
/*
* The keyname must have matched or we wouldn't be here,
* so we use DNS_R_PARTIALMATCH instead of ISC_R_NOTFOUND.
*/
return (DNS_R_PARTIALMATCH);
}
}
/*%
* Create a keynode for "ds" (or a null key node if "ds" is NULL), set
* "managed" and "initial" as requested and attach the keynode to
* to "node" in "keytable".
*/
static isc_result_t
new_keynode(dns_rdata_ds_t *ds, dns_rbtnode_t *node,
dns_keytable_t *keytable, bool managed, bool initial)
{
dns_keynode_t *knode = NULL;
isc_result_t result;
REQUIRE(VALID_KEYTABLE(keytable));
REQUIRE(!initial || managed);
knode = isc_mem_get(keytable->mctx, sizeof(dns_keynode_t));
*knode = (dns_keynode_t) {
.magic = KEYNODE_MAGIC
};
dns_rdataset_init(&knode->dsset);
isc_refcount_init(&knode->refcount, 1);
/*
* 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).
* If a DS was supplied, initialize an rdatalist.
*/
if (keyp != NULL) {
if (knode->dslist != NULL) {
free_dslist(keytable->mctx, knode);
}
knode->key = *keyp;
*keyp = NULL;
} 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 (ds != NULL) {
result = add_ds(knode, ds, keytable->mctx);
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;
}
knode->managed = managed;
knode->initial = initial;
knode->next = node->data;
node->data = knode;
return (ISC_R_SUCCESS);
}
/*%
* 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.
* Add key trust anchor "ds" at "keyname" in "keytable". If an anchor
* already exists at the requested name does not contain "ds", update it.
* If "ds" 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
insert(dns_keytable_t *keytable, bool managed, bool initial,
const dns_name_t *keyname, dst_key_t **keyp, dns_rdata_ds_t *ds)
const dns_name_t *keyname, dns_rdata_ds_t *ds)
{
dns_rbtnode_t *node = NULL;
isc_result_t result;
@ -312,16 +339,15 @@ insert(dns_keytable_t *keytable, bool managed, bool initial,
/*
* There was no node for "keyname" in "keytable" yet, so one
* 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.
* trust anchor (or a null key node if "ds" is NULL)
* and attach it to the created node.
*/
result = prepend_keynode(keyp, ds, node, keytable,
managed, initial);
result = new_keynode(ds, node, keytable, managed, initial);
} else if (result == ISC_R_EXISTS) {
/*
* A node already exists for "keyname" in "keytable".
*/
if (keyp == NULL && ds == NULL) {
if (ds == NULL) {
/*
* We were told to add a null key at "keyname", which
* means there is nothing left to do as there is either
@ -331,29 +357,14 @@ insert(dns_keytable_t *keytable, bool managed, bool initial,
* "keyname" is already marked as secure.
*/
result = ISC_R_SUCCESS;
} else if (keyp != NULL) {
/*
* 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.
*/
result = update_keynode(keytable, node, keyp, initial);
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.
*/
result = prepend_keynode(keyp, NULL,
node, keytable,
managed, initial);
} else {
dns_keynode_t *knode = node->data;
if (knode == NULL) {
result = new_keynode(ds, node, keytable,
managed, initial);
} else {
result = add_ds(knode, ds, keytable->mctx);
}
} else if (ds != NULL) {
result = prepend_keynode(NULL, ds, node, keytable,
managed, initial);
}
}
@ -363,19 +374,18 @@ insert(dns_keytable_t *keytable, bool managed, bool initial,
}
isc_result_t
dns_keytable_add(dns_keytable_t *keytable,
bool managed, bool initial,
dns_name_t *name, dst_key_t **keyp, dns_rdata_ds_t *ds)
dns_keytable_add(dns_keytable_t *keytable, bool managed, bool initial,
dns_name_t *name, dns_rdata_ds_t *ds)
{
REQUIRE(keyp == NULL || *keyp != NULL);
REQUIRE(keyp != NULL || ds != NULL);
REQUIRE(ds != NULL);
REQUIRE(!initial || managed);
return (insert(keytable, managed, initial, name, keyp, ds));
return (insert(keytable, managed, initial, name, ds));
}
isc_result_t
dns_keytable_marksecure(dns_keytable_t *keytable, const dns_name_t *name) {
return (insert(keytable, true, false, name, NULL, NULL));
return (insert(keytable, true, false, name, NULL));
}
isc_result_t
@ -390,38 +400,49 @@ dns_keytable_delete(dns_keytable_t *keytable, const dns_name_t *keyname) {
result = dns_rbt_findnode(keytable->table, keyname, NULL, &node, NULL,
DNS_RBTFIND_NOOPTIONS, NULL, NULL);
if (result == ISC_R_SUCCESS) {
if (node->data != NULL)
if (node->data != NULL) {
result = dns_rbt_deletenode(keytable->table,
node, false);
else
} else {
result = ISC_R_NOTFOUND;
} else if (result == DNS_R_PARTIALMATCH)
}
} 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) {
dns_keytable_deletekey(dns_keytable_t *keytable, const dns_name_t *keyname,
dns_rdata_dnskey_t *dnskey)
{
isc_result_t result;
dns_name_t *keyname;
dns_rbtnode_t *node = NULL;
dns_keynode_t *knode = NULL, **kprev = NULL;
dns_keynode_t *knode = NULL;
dns_rdata_t rdata = DNS_RDATA_INIT;
unsigned char data[4096], digest[DNS_DS_BUFFERSIZE];
dns_rdata_ds_t ds;
isc_buffer_t b;
REQUIRE(VALID_KEYTABLE(keytable));
REQUIRE(dstkey != NULL);
REQUIRE(dnskey != NULL);
keyname = dst_key_name(dstkey);
isc_buffer_init(&b, data, sizeof(data));
dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
dns_rdatatype_dnskey, dnskey, &b);
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)
if (result == DNS_R_PARTIALMATCH) {
result = ISC_R_NOTFOUND;
if (result != ISC_R_SUCCESS)
}
if (result != ISC_R_SUCCESS) {
goto finish;
}
if (node->data == NULL) {
result = ISC_R_NOTFOUND;
@ -429,38 +450,21 @@ dns_keytable_deletekeynode(dns_keytable_t *keytable, dst_key_t *dstkey) {
}
knode = node->data;
if (knode->next == NULL && knode->key != NULL &&
dst_key_compare(knode->key, dstkey) == true)
{
result = dns_rbt_deletenode(keytable->table, node, false);
if (knode->dslist == NULL) {
result = DNS_R_PARTIALMATCH;
goto finish;
}
kprev = (dns_keynode_t **) &node->data;
while (knode != NULL) {
if (knode->key != NULL &&
dst_key_compare(knode->key, dstkey) == true)
break;
kprev = &knode->next;
knode = knode->next;
result = dns_ds_fromkeyrdata(keyname, &rdata, DNS_DSDIGEST_SHA256,
digest, &ds);
if (result != ISC_R_SUCCESS) {
goto finish;
}
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:
result = delete_ds(knode, &ds, keytable->mctx);
finish:
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
return (result);
}
@ -481,8 +485,7 @@ dns_keytable_find(dns_keytable_t *keytable, const dns_name_t *keyname,
DNS_RBTFIND_NOOPTIONS, NULL, NULL);
if (result == ISC_R_SUCCESS) {
if (node->data != NULL) {
dns_keytable_attachkeynode(keytable, node->data,
keynodep);
keynode_attach(node->data, keynodep);
} else {
result = ISC_R_NOTFOUND;
}
@ -494,123 +497,6 @@ dns_keytable_find(dns_keytable_t *keytable, const dns_name_t *keyname,
return (result);
}
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);
if (keynode->next == NULL) {
return (ISC_R_NOTFOUND);
}
dns_keytable_attachkeynode(keytable, keynode->next, nextnodep);
return (ISC_R_SUCCESS);
}
isc_result_t
dns_keytable_findkeynode(dns_keytable_t *keytable, const dns_name_t *name,
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);
/*
* 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.
*/
knode = NULL;
data = NULL;
result = dns_rbt_findname(keytable->table, name, 0, NULL, &data);
if (result == ISC_R_SUCCESS) {
INSIST(data != NULL);
for (knode = data; knode != NULL; knode = knode->next) {
if (knode->key == NULL) {
knode = NULL;
break;
}
if (algorithm == dst_key_alg(knode->key) &&
tag == dst_key_id(knode->key))
{
break;
}
}
if (knode != NULL) {
dns_keytable_attachkeynode(keytable, knode, keynodep);
} else {
result = DNS_R_PARTIALMATCH;
}
} else if (result == DNS_R_PARTIALMATCH) {
result = ISC_R_NOTFOUND;
}
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
return (result);
}
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) {
if (knode->key == NULL) {
knode = NULL;
break;
}
if (dst_key_alg(keynode->key) == dst_key_alg(knode->key) &&
dst_key_id(keynode->key) == dst_key_id(knode->key))
{
break;
}
}
if (knode != NULL) {
dns_keytable_attachkeynode(keytable, knode, nextnodep);
result = ISC_R_SUCCESS;
} else {
result = ISC_R_NOTFOUND;
}
return (result);
}
isc_result_t
dns_keytable_finddeepestmatch(dns_keytable_t *keytable, const dns_name_t *name,
dns_name_t *foundname)
@ -641,25 +527,7 @@ dns_keytable_finddeepestmatch(dns_keytable_t *keytable, const dns_name_t *name,
}
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);
REQUIRE(atomic_fetch_add_relaxed(&keytable->active_nodes, 1) < UINT32_MAX);
dns_keynode_attach(source, target);
}
void
dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep)
{
dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep) {
/*
* Give back a keynode found via dns_keytable_findkeynode().
*/
@ -667,9 +535,7 @@ dns_keytable_detachkeynode(dns_keytable_t *keytable, dns_keynode_t **keynodep)
REQUIRE(VALID_KEYTABLE(keytable));
REQUIRE(keynodep != NULL && VALID_KEYNODE(*keynodep));
REQUIRE(atomic_fetch_sub_release(&keytable->active_nodes, 1) > 0);
dns_keynode_detach(keytable->mctx, keynodep);
keynode_detach(keytable->mctx, keynodep);
}
isc_result_t
@ -775,7 +641,7 @@ keynode_dslist_totext(dns_name_t *name, dns_keynode_t *keynode,
dns_secalg_format(ds.algorithm, algbuf, sizeof(algbuf));
snprintf(obuf, sizeof(obuf), "%s/%s/%d ; %s%s (DS)\n",
snprintf(obuf, sizeof(obuf), "%s/%s/%d ; %s%s\n",
namebuf, algbuf, ds.key_tag,
keynode->initial ? "initializing " : "",
keynode->managed ? "managed" : "static");
@ -815,8 +681,6 @@ dns_keytable_totext(dns_keytable_t *keytable, isc_buffer_t **text) {
goto cleanup;
}
for (;;) {
char pbuf[DST_KEY_FORMATSIZE];
dns_rbtnodechain_current(&chain, foundname, origin, &node);
knode = node->data;
@ -828,24 +692,8 @@ dns_keytable_totext(dns_keytable_t *keytable, isc_buffer_t **text) {
}
result = keynode_dslist_totext(fullname, knode, text);
goto cleanup;
}
for (; knode != NULL; knode = knode->next) {
char obuf[DNS_NAME_FORMATSIZE + 200];
if (knode->key == NULL) {
continue;
}
dst_key_format(knode->key, pbuf, sizeof(pbuf));
snprintf(obuf, sizeof(obuf), "%s ; %s%s\n", pbuf,
knode->initial ? "initializing " : "",
knode->managed ? "managed" : "static");
result = putstr(text, obuf);
if (result != ISC_R_SUCCESS) {
break;
goto cleanup;
}
}
@ -858,7 +706,7 @@ dns_keytable_totext(dns_keytable_t *keytable, isc_buffer_t **text) {
}
}
cleanup:
cleanup:
dns_rbtnodechain_invalidate(&chain);
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
return (result);
@ -891,8 +739,7 @@ dns_keytable_forall(dns_keytable_t *keytable,
}
goto cleanup;
}
REQUIRE(atomic_fetch_add_relaxed(&keytable->active_nodes, 1)
< UINT32_MAX);
for (;;) {
dns_rbtnodechain_current(&chain, foundname, origin, &node);
if (node->data != NULL) {
@ -909,21 +756,13 @@ dns_keytable_forall(dns_keytable_t *keytable,
break;
}
}
REQUIRE(atomic_fetch_sub_release(&keytable->active_nodes, 1) > 0);
cleanup:
cleanup:
dns_rbtnodechain_invalidate(&chain);
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
return (result);
}
dst_key_t *
dns_keynode_key(dns_keynode_t *keynode) {
REQUIRE(VALID_KEYNODE(keynode));
return (keynode->key);
}
dns_rdataset_t *
dns_keynode_dsset(dns_keynode_t *keynode) {
REQUIRE(VALID_KEYNODE(keynode));
@ -955,65 +794,3 @@ dns_keynode_trust(dns_keynode_t *keynode) {
keynode->initial = false;
}
isc_result_t
dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target) {
dns_keynode_t *knode;
REQUIRE(target != NULL && *target == NULL);
knode = isc_mem_get(mctx, sizeof(dns_keynode_t));
knode->magic = KEYNODE_MAGIC;
knode->managed = false;
knode->initial = false;
knode->key = NULL;
knode->dslist = NULL;
dns_rdataset_init(&knode->dsset);
knode->next = NULL;
isc_refcount_init(&knode->refcount, 1);
*target = knode;
return (ISC_R_SUCCESS);
}
void
dns_keynode_attach(dns_keynode_t *source, dns_keynode_t **target) {
REQUIRE(VALID_KEYNODE(source));
isc_refcount_increment(&source->refcount);
*target = source;
}
void
dns_keynode_detach(isc_mem_t *mctx, dns_keynode_t **keynodep) {
REQUIRE(keynodep != NULL && VALID_KEYNODE(*keynodep));
dns_keynode_t *knode = *keynodep;
*keynodep = NULL;
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);
}
isc_mem_put(mctx, knode, sizeof(dns_keynode_t));
}
}
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;
}

View File

@ -27,11 +27,12 @@
#include <isc/base64.h>
#include <isc/buffer.h>
#include <isc/md.h>
#include <isc/util.h>
#include <dns/name.h>
#include <dns/fixedname.h>
#include <dns/keytable.h>
#include <dns/name.h>
#include <dns/nta.h>
#include <dns/rdataclass.h>
#include <dns/rdatastruct.h>
@ -67,7 +68,6 @@ dns_keytable_t *keytable = NULL;
dns_ntatable_t *ntatable = NULL;
static const char *keystr1 = "BQEAAAABok+vaUC9neRv8yeT/FEGgN7svR8s7VBUVSBd8NsAiV8AlaAg O5FHar3JQd95i/puZos6Vi6at9/JBbN8qVmO2AuiXxVqfxMKxIcy+LEB 0Vw4NaSJ3N3uaVREso6aTSs98H/25MjcwLOr7SFfXA7bGhZatLtYY/xu kp6Km5hMfkE=";
static const dns_keytag_t keytag1 = 30591;
static const char *keystr2 = "BQEAAAABwuHz9Cem0BJ0JQTO7C/a3McR6hMaufljs1dfG/inaJpYv7vH XTrAOm/MeKp+/x6eT4QLru0KoZkvZJnqTI8JyaFTw2OM/ItBfh/hL2lm Cft2O7n3MfeqYtvjPnY7dWghYW4sVfH7VVEGm958o9nfi79532Qeklxh x8pXWdeAaRU=";
@ -103,66 +103,94 @@ str2name(const char *namestr) {
}
static void
create_key(uint16_t flags, uint8_t proto, uint8_t alg,
const char *keynamestr, const char *keystr, dst_key_t **target)
create_keystruct(uint16_t flags, uint8_t proto, uint8_t alg,
const char *keystr, dns_rdata_dnskey_t *keystruct)
{
dns_rdata_dnskey_t keystruct;
unsigned char keydata[4096];
isc_buffer_t keydatabuf;
unsigned char rrdata[4096];
isc_buffer_t rrdatabuf;
isc_region_t r;
const dns_rdataclass_t rdclass = dns_rdataclass_in; /* for brevity */
const dns_rdataclass_t rdclass = dns_rdataclass_in;
keystruct.common.rdclass = rdclass;
keystruct.common.rdtype = dns_rdatatype_dnskey;
keystruct.mctx = NULL;
ISC_LINK_INIT(&keystruct.common, link);
keystruct.flags = flags;
keystruct.protocol = proto;
keystruct.algorithm = alg;
keystruct->common.rdclass = rdclass;
keystruct->common.rdtype = dns_rdatatype_dnskey;
keystruct->mctx = dt_mctx;
ISC_LINK_INIT(&keystruct->common, link);
keystruct->flags = flags;
keystruct->protocol = proto;
keystruct->algorithm = alg;
isc_buffer_init(&keydatabuf, keydata, sizeof(keydata));
isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
assert_int_equal(isc_base64_decodestring(keystr, &keydatabuf),
ISC_R_SUCCESS);
isc_buffer_usedregion(&keydatabuf, &r);
keystruct.datalen = r.length;
keystruct.data = r.base;
assert_int_equal(dns_rdata_fromstruct(NULL, keystruct.common.rdclass,
keystruct.common.rdtype,
&keystruct, &rrdatabuf),
ISC_R_SUCCESS);
keystruct->datalen = r.length;
keystruct->data = isc_mem_allocate(dt_mctx, r.length);
memmove(keystruct->data, r.base, r.length);
}
assert_int_equal(dst_key_fromdns(str2name(keynamestr), rdclass,
&rrdatabuf, dt_mctx, target),
ISC_R_SUCCESS);
static void
create_dsstruct(dns_name_t *name, uint16_t flags,
uint8_t proto, uint8_t alg, const char *keystr,
unsigned char *digest, dns_rdata_ds_t *dsstruct)
{
isc_result_t result;
unsigned char rrdata[4096];
isc_buffer_t rrdatabuf;
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_dnskey_t dnskey;
/*
* Populate DNSKEY rdata structure.
*/
create_keystruct(flags, proto, alg, keystr, &dnskey);
/*
* Convert to wire format.
*/
isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
result = dns_rdata_fromstruct(&rdata, dnskey.common.rdclass,
dnskey.common.rdtype,
&dnskey, &rrdatabuf);
assert_int_equal(result, ISC_R_SUCCESS);
/*
* Build DS rdata struct.
*/
result = dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256,
digest, dsstruct);
assert_int_equal(result, ISC_R_SUCCESS);
dns_rdata_freestruct(&dnskey);
}
/* Common setup: create a keytable and ntatable to test with a few keys */
static void
create_tables() {
isc_result_t result;
dst_key_t *key = NULL;
unsigned char digest[ISC_MAX_MD_SIZE];
dns_rdata_ds_t ds;
dns_fixedname_t fn;
dns_name_t *keyname = dns_fixedname_name(&fn);
isc_stdtime_t now;
result = dns_test_makeview("view", &view);
assert_int_equal(result, ISC_R_SUCCESS);
assert_int_equal(dns_keytable_create(dt_mctx, &keytable), ISC_R_SUCCESS);
assert_int_equal(dns_keytable_create(dt_mctx, &keytable),
ISC_R_SUCCESS);
assert_int_equal(dns_ntatable_create(view, taskmgr, timermgr,
&ntatable), ISC_R_SUCCESS);
/* Add a normal key */
create_key(257, 3, 5, "example.com", keystr1, &key);
assert_int_equal(dns_keytable_add(keytable, false, false,
dst_key_name(key), &key, NULL),
dns_test_namefromstring("example.com", &fn);
create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds);
assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds),
ISC_R_SUCCESS);
/* Add an initializing managed key */
create_key(257, 3, 5, "managed.com", keystr1, &key);
assert_int_equal(dns_keytable_add(keytable, true, true,
dst_key_name(key), &key, NULL),
dns_test_namefromstring("managed.com", &fn);
create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds);
assert_int_equal(dns_keytable_add(keytable, true, true, keyname, &ds),
ISC_R_SUCCESS);
/* Add a null key */
@ -193,65 +221,55 @@ destroy_tables() {
/* add keys to the keytable */
static void
add_test(void **state) {
dst_key_t *key = NULL;
dns_keynode_t *keynode = NULL;
dns_keynode_t *next_keynode = NULL;
dns_keynode_t *null_keynode = NULL;
unsigned char digest[ISC_MAX_MD_SIZE];
dns_rdata_ds_t ds;
dns_fixedname_t fn;
dns_name_t *keyname = dns_fixedname_name(&fn);
UNUSED(state);
create_tables();
/*
* Get the keynode for the example.com key. There's no other key for
* the name, so nextkeynode() should return NOTFOUND.
* Getting the keynode for the example.com key should succeed.
*/
assert_int_equal(dns_keytable_find(keytable, str2name("example.com"),
&keynode),
ISC_R_SUCCESS);
assert_int_equal(dns_keytable_nextkeynode(keytable, keynode,
&next_keynode),
ISC_R_NOTFOUND);
/*
* Try to add the same key. This should have no effect, so
* nextkeynode() should still return NOTFOUND.
* Try to add the same key. This should have no effect but
* report success.
*/
create_key(257, 3, 5, "example.com", keystr1, &key);
assert_int_equal(dns_keytable_add(keytable, false, false,
dst_key_name(key), &key, NULL),
dns_test_namefromstring("example.com", &fn);
create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds);
assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds),
ISC_R_SUCCESS);
dns_keytable_detachkeynode(keytable, &keynode);
assert_int_equal(dns_keytable_find(keytable, str2name("example.com"),
&keynode),
ISC_R_SUCCESS);
assert_int_equal(dns_keytable_nextkeynode(keytable, keynode,
&next_keynode),
ISC_R_NOTFOUND);
/* Add another key (different keydata) */
dns_keytable_detachkeynode(keytable, &keynode);
create_key(257, 3, 5, "example.com", keystr2, &key);
assert_int_equal(dns_keytable_add(keytable, false, false,
dst_key_name(key), &key, NULL),
create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds);
assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds),
ISC_R_SUCCESS);
assert_int_equal(dns_keytable_find(keytable, str2name("example.com"),
&keynode),
ISC_R_SUCCESS);
assert_int_equal(dns_keytable_nextkeynode(keytable, keynode,
&next_keynode),
ISC_R_SUCCESS);
dns_keytable_detachkeynode(keytable, &next_keynode);
dns_keytable_detachkeynode(keytable, &keynode);
/*
* Get the keynode for the managed.com key. There's no other key for
* the name, so nextkeynode() should return NOTFOUND. Ensure the
* Get the keynode for the managed.com key. Ensure the
* retrieved key is an initializing key, then mark it as trusted using
* dns_keynode_trust() and ensure the latter works as expected.
*/
assert_int_equal(dns_keytable_find(keytable, str2name("managed.com"),
&keynode),
ISC_R_SUCCESS);
assert_int_equal(dns_keytable_nextkeynode(keytable, keynode,
&next_keynode),
ISC_R_NOTFOUND);
assert_int_equal(dns_keynode_initial(keynode), true);
dns_keynode_trust(keynode);
assert_int_equal(dns_keynode_initial(keynode), false);
@ -259,21 +277,17 @@ add_test(void **state) {
/*
* Add a different managed key for managed.com, marking it as an
* initializing key. Ensure nextkeynode() no longer returns
* ISC_R_NOTFOUND and that the added key is an initializing key.
* initializing key. Since there is already a trusted key at the
* node, the node should *not* be marked as initializing.
*/
create_key(257, 3, 5, "managed.com", keystr2, &key);
assert_int_equal(dns_keytable_add(keytable, true, true,
dst_key_name(key), &key, NULL),
dns_test_namefromstring("managed.com", &fn);
create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds);
assert_int_equal(dns_keytable_add(keytable, true, true, keyname, &ds),
ISC_R_SUCCESS);
assert_int_equal(dns_keytable_find(keytable, str2name("managed.com"),
&keynode),
ISC_R_SUCCESS);
assert_int_equal(dns_keytable_nextkeynode(keytable, keynode,
&next_keynode),
ISC_R_SUCCESS);
assert_int_equal(dns_keynode_initial(keynode), true);
dns_keytable_detachkeynode(keytable, &next_keynode);
assert_int_equal(dns_keynode_initial(keynode), false);
dns_keytable_detachkeynode(keytable, &keynode);
/*
@ -282,86 +296,41 @@ add_test(void **state) {
* to a non-initializing key and make sure there are still two key
* nodes for managed.com, both containing non-initializing keys.
*/
create_key(257, 3, 5, "managed.com", keystr2, &key);
assert_int_equal(dns_keytable_add(keytable, true, false,
dst_key_name(key), &key, NULL),
assert_int_equal(dns_keytable_add(keytable, true, false, keyname, &ds),
ISC_R_SUCCESS);
assert_int_equal(dns_keytable_find(keytable, str2name("managed.com"),
&keynode),
ISC_R_SUCCESS);
assert_int_equal(dns_keynode_initial(keynode), false);
assert_int_equal(dns_keytable_nextkeynode(keytable, keynode,
&next_keynode),
ISC_R_SUCCESS);
dns_keytable_detachkeynode(keytable, &keynode);
keynode = next_keynode;
next_keynode = NULL;
assert_int_equal(dns_keynode_initial(keynode), false);
assert_int_equal(dns_keytable_nextkeynode(keytable, keynode,
&next_keynode),
ISC_R_NOTFOUND);
dns_keytable_detachkeynode(keytable, &keynode);
/*
* Add a managed key at a new node, two.com, marking it as an
* initializing key. Ensure nextkeynode() returns ISC_R_NOTFOUND and
* that the added key is an initializing key.
* initializing key.
*/
create_key(257, 3, 5, "two.com", keystr1, &key);
assert_int_equal(dns_keytable_add(keytable, true, true,
dst_key_name(key), &key, NULL),
dns_test_namefromstring("two.com", &fn);
create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds);
assert_int_equal(dns_keytable_add(keytable, true, true, keyname, &ds),
ISC_R_SUCCESS);
assert_int_equal(dns_keytable_find(keytable, str2name("two.com"),
&keynode),
ISC_R_SUCCESS);
assert_int_equal(dns_keytable_nextkeynode(keytable, keynode,
&next_keynode),
ISC_R_NOTFOUND);
assert_int_equal(dns_keynode_initial(keynode), true);
dns_keytable_detachkeynode(keytable, &keynode);
/*
* Add a different managed key for two.com, marking it as a
* non-initializing key. Ensure nextkeynode() no longer returns
* ISC_R_NOTFOUND and that the added key is not an initializing key.
* non-initializing key. Since there is already an iniitalizing
* trust anchor for two.com and we haven't run dns_keynode_trust(),
* the initialization status should not change.
*/
create_key(257, 3, 5, "two.com", keystr2, &key);
assert_int_equal(dns_keytable_add(keytable, true, false,
dst_key_name(key), &key, NULL),
create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds);
assert_int_equal(dns_keytable_add(keytable, true, false, keyname, &ds),
ISC_R_SUCCESS);
assert_int_equal(dns_keytable_find(keytable, str2name("two.com"),
&keynode),
ISC_R_SUCCESS);
assert_int_equal(dns_keytable_nextkeynode(keytable, keynode,
&next_keynode), ISC_R_SUCCESS);
assert_int_equal(dns_keynode_initial(keynode), false);
dns_keytable_detachkeynode(keytable, &next_keynode);
dns_keytable_detachkeynode(keytable, &keynode);
/*
* Add the first managed key again, but this time mark it as a
* non-initializing key. Ensure the previously added key is upgraded
* to a non-initializing key and make sure there are still two key
* nodes for two.com, both containing non-initializing keys.
*/
create_key(257, 3, 5, "two.com", keystr1, &key);
assert_int_equal(dns_keytable_add(keytable, true, false,
dst_key_name(key), &key, NULL),
ISC_R_SUCCESS);
assert_int_equal(dns_keytable_find(keytable, str2name("two.com"),
&keynode),
ISC_R_SUCCESS);
assert_int_equal(dns_keynode_initial(keynode), false);
assert_int_equal(dns_keytable_nextkeynode(keytable, keynode,
&next_keynode),
ISC_R_SUCCESS);
dns_keytable_detachkeynode(keytable, &keynode);
keynode = next_keynode;
next_keynode = NULL;
assert_int_equal(dns_keynode_initial(keynode), false);
assert_int_equal(dns_keytable_nextkeynode(keytable, keynode,
&next_keynode),
ISC_R_NOTFOUND);
assert_int_equal(dns_keynode_initial(keynode), true);
dns_keytable_detachkeynode(keytable, &keynode);
/*
@ -371,21 +340,19 @@ add_test(void **state) {
assert_int_equal(dns_keytable_find(keytable, str2name("null.example"),
&null_keynode),
ISC_R_SUCCESS);
create_key(257, 3, 5, "null.example", keystr2, &key);
assert_int_equal(dns_keytable_add(keytable, false, false,
dst_key_name(key), &key, NULL),
dns_test_namefromstring("null.example", &fn);
create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds);
assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds),
ISC_R_SUCCESS);
assert_int_equal(dns_keytable_find(keytable, str2name("null.example"),
&keynode),
ISC_R_SUCCESS);
assert_int_equal(keynode, null_keynode); /* should be the same node */
assert_non_null(dns_keynode_key(keynode)); /* now have a key */
dns_keytable_detachkeynode(keytable, &null_keynode);
/*
* Try to add a null key to a name that already has a key. It's
* effectively no-op, so the same key node is still there, with no
* no next node.
* effectively no-op, so the same key node is still there.
* (Note: this and above checks confirm that if a name has a null key
* that's the only key for the name).
*/
@ -396,10 +363,6 @@ add_test(void **state) {
&null_keynode),
ISC_R_SUCCESS);
assert_int_equal(keynode, null_keynode);
assert_non_null(dns_keynode_key(keynode));
assert_int_equal(dns_keytable_nextkeynode(keytable, keynode,
&next_keynode),
ISC_R_NOTFOUND);
dns_keytable_detachkeynode(keytable, &null_keynode);
dns_keytable_detachkeynode(keytable, &keynode);
@ -439,56 +402,68 @@ delete_test(void **state) {
/* delete key nodes from the keytable */
static void
deletekeynode_test(void **state) {
dst_key_t *key = NULL;
deletekey_test(void **state) {
dns_rdata_dnskey_t dnskey;
dns_fixedname_t fn;
dns_name_t *keyname = dns_fixedname_name(&fn);
UNUSED(state);
create_tables();
/* key name doesn't match */
create_key(257, 3, 5, "example.org", keystr1, &key);
assert_int_equal(dns_keytable_deletekeynode(keytable, key),
dns_test_namefromstring("example.org", &fn);
create_keystruct(257, 3, 5, keystr1, &dnskey);
assert_int_equal(dns_keytable_deletekey(keytable, keyname, &dnskey),
ISC_R_NOTFOUND);
dst_key_free(&key);
dns_rdata_freestruct(&dnskey);
/* subdomain match is the same as no match */
create_key(257, 3, 5, "sub.example.com", keystr1, &key);
assert_int_equal(dns_keytable_deletekeynode(keytable, key),
dns_test_namefromstring("sub.example.org", &fn);
create_keystruct(257, 3, 5, keystr1, &dnskey);
assert_int_equal(dns_keytable_deletekey(keytable, keyname, &dnskey),
ISC_R_NOTFOUND);
dst_key_free(&key);
dns_rdata_freestruct(&dnskey);
/* name matches but key doesn't match (resulting in PARTIALMATCH) */
create_key(257, 3, 5, "example.com", keystr2, &key);
assert_int_equal(dns_keytable_deletekeynode(keytable, key),
dns_test_namefromstring("example.com", &fn);
create_keystruct(257, 3, 5, keystr2, &dnskey);
assert_int_equal(dns_keytable_deletekey(keytable, keyname, &dnskey),
DNS_R_PARTIALMATCH);
dst_key_free(&key);
dns_rdata_freestruct(&dnskey);
/*
* exact match. after deleting the node the internal rbt node will be
* empty, and any delete or deletekeynode attempt should result in
* NOTFOUND.
* exact match: should return SUCCESS on the first try, then
* PARTIALMATCH on the second (because the name existed but
* not a matching key).
*/
create_key(257, 3, 5, "example.com", keystr1, &key);
assert_int_equal(dns_keytable_deletekeynode(keytable, key),
create_keystruct(257, 3, 5, keystr1, &dnskey);
assert_int_equal(dns_keytable_deletekey(keytable, keyname, &dnskey),
ISC_R_SUCCESS);
assert_int_equal(dns_keytable_deletekeynode(keytable, key),
assert_int_equal(dns_keytable_deletekey(keytable, keyname, &dnskey),
DNS_R_PARTIALMATCH);
/*
* after deleting the node, any deletekey or delete attempt should
* result in NOTFOUND.
*/
assert_int_equal(dns_keytable_delete(keytable, keyname),
ISC_R_SUCCESS);
assert_int_equal(dns_keytable_deletekey(keytable, keyname, &dnskey),
ISC_R_NOTFOUND);
assert_int_equal(dns_keytable_delete(keytable,
str2name("example.com")),
ISC_R_NOTFOUND);
dst_key_free(&key);
dns_rdata_freestruct(&dnskey);
/*
* A null key node for a name is not deleted when searched by key;
* it must be deleted by dns_keytable_delete()
*/
create_key(257, 3, 5, "null.example", keystr1, &key);
assert_int_equal(dns_keytable_deletekeynode(keytable, key),
dns_test_namefromstring("null.example", &fn);
create_keystruct(257, 3, 5, keystr1, &dnskey);
assert_int_equal(dns_keytable_deletekey(keytable, keyname, &dnskey),
DNS_R_PARTIALMATCH);
assert_int_equal(dns_keytable_delete(keytable, dst_key_name(key)),
assert_int_equal(dns_keytable_delete(keytable, keyname),
ISC_R_SUCCESS);
dst_key_free(&key);
dns_rdata_freestruct(&dnskey);
destroy_tables();
}
@ -524,7 +499,6 @@ find_test(void **state) {
str2name("null.example"),
&keynode),
ISC_R_SUCCESS);
assert_int_equal(dns_keynode_key(keynode), NULL);
dns_keytable_detachkeynode(keytable, &keynode);
/*
@ -552,37 +526,6 @@ find_test(void **state) {
ISC_R_SUCCESS);
assert_true(dns_name_equal(name, str2name("null.example")));
/*
* dns_keytable_findkeynode() requires exact name, algorithm, keytag
* match. If algorithm or keytag doesn't match, should result in
* PARTIALMATCH. Same for a node with a null key.
*/
assert_int_equal(dns_keytable_findkeynode(keytable,
str2name("example.org"),
5, keytag1, &keynode),
ISC_R_NOTFOUND);
assert_int_equal(dns_keytable_findkeynode(keytable,
str2name("sub.example.com"),
5, keytag1, &keynode),
ISC_R_NOTFOUND);
assert_int_equal(dns_keytable_findkeynode(keytable,
str2name("example.com"),
4, keytag1, &keynode),
DNS_R_PARTIALMATCH); /* different algorithm */
assert_int_equal(dns_keytable_findkeynode(keytable,
str2name("example.com"),
5, keytag1 + 1, &keynode),
DNS_R_PARTIALMATCH); /* different keytag */
assert_int_equal(dns_keytable_findkeynode(keytable,
str2name("null.example"),
5, 0, &keynode),
DNS_R_PARTIALMATCH); /* null key */
assert_int_equal(dns_keytable_findkeynode(keytable,
str2name("example.com"),
5, keytag1, &keynode),
ISC_R_SUCCESS); /* complete match */
dns_keytable_detachkeynode(keytable, &keynode);
destroy_tables();
}
@ -649,8 +592,11 @@ dump_test(void **state) {
static void
nta_test(void **state) {
isc_result_t result;
dst_key_t *key = NULL;
bool issecure, covered;
dns_fixedname_t fn;
dns_name_t *keyname = dns_fixedname_name(&fn);
unsigned char digest[ISC_MAX_MD_SIZE];
dns_rdata_ds_t ds;
dns_view_t *myview = NULL;
isc_stdtime_t now;
@ -672,14 +618,13 @@ nta_test(void **state) {
result = dns_view_getntatable(myview, &ntatable);
assert_int_equal(result, ISC_R_SUCCESS);
create_key(257, 3, 5, "example", keystr1, &key);
result = dns_keytable_add(keytable, false, false,
dst_key_name(key), &key, NULL),
dns_test_namefromstring("example", &fn);
create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds);
result = dns_keytable_add(keytable, false, false, keyname, &ds),
assert_int_equal(result, ISC_R_SUCCESS);
isc_stdtime_get(&now);
result = dns_ntatable_add(ntatable,
str2name("insecure.example"),
result = dns_ntatable_add(ntatable, str2name("insecure.example"),
false, now, 1);
assert_int_equal(result, ISC_R_SUCCESS);
@ -752,23 +697,16 @@ nta_test(void **state) {
int
main(void) {
const struct CMUnitTest tests[] = {
cmocka_unit_test_setup_teardown(add_test,
_setup, _teardown),
cmocka_unit_test_setup_teardown(delete_test,
_setup, _teardown),
cmocka_unit_test_setup_teardown(deletekeynode_test,
_setup, _teardown),
cmocka_unit_test_setup_teardown(find_test,
_setup, _teardown),
cmocka_unit_test_setup_teardown(issecuredomain_test,
_setup, _teardown),
cmocka_unit_test_setup_teardown(dump_test,
_setup, _teardown),
cmocka_unit_test_setup_teardown(nta_test,
_setup, _teardown),
cmocka_unit_test(add_test),
cmocka_unit_test(delete_test),
cmocka_unit_test(deletekey_test),
cmocka_unit_test(find_test),
cmocka_unit_test(issecuredomain_test),
cmocka_unit_test(dump_test),
cmocka_unit_test(nta_test),
};
return (cmocka_run_group_tests(tests, NULL, NULL));
return (cmocka_run_group_tests(tests, _setup, _teardown));
}
#else /* HAVE_CMOCKA */

View File

@ -533,6 +533,7 @@ fetch_callback_ds(isc_task_t *task, isc_event_t *event) {
"dsset with trust %s",
dns_trust_totext(rdataset->trust));
val->dsset = &val->frdataset;
INSIST(val->keynode == NULL);
result = validate_dnskey(val);
if (result != DNS_R_WAIT) {
validator_done(val, result);
@ -1356,23 +1357,13 @@ compute_keytag(dns_rdata_t *rdata) {
*/
static bool
selfsigned_dnskey(dns_validator_t *val) {
dns_rdataset_t *rdataset, *sigrdataset;
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_t sigrdata = DNS_RDATA_INIT;
dns_rdata_dnskey_t key;
dns_rdata_rrsig_t sig;
dns_keytag_t keytag;
dns_name_t *name;
dns_rdataset_t *rdataset = val->event->rdataset;
dns_rdataset_t *sigrdataset = val->event->sigrdataset;
dns_name_t *name = val->event->name;
isc_result_t result;
dst_key_t *dstkey;
isc_mem_t *mctx;
isc_mem_t *mctx = val->view->mctx;
bool answer = false;
rdataset = val->event->rdataset;
sigrdataset = val->event->sigrdataset;
name = val->event->name;
mctx = val->view->mctx;
if (rdataset->type != dns_rdatatype_dnskey) {
return (false);
}
@ -1381,15 +1372,24 @@ selfsigned_dnskey(dns_validator_t *val) {
result == ISC_R_SUCCESS;
result = dns_rdataset_next(rdataset))
{
dns_rdata_reset(&rdata);
dns_rdataset_current(rdataset, &rdata);
result = dns_rdata_tostruct(&rdata, &key, NULL);
dns_rdata_t keyrdata = DNS_RDATA_INIT;
dns_rdata_t sigrdata = DNS_RDATA_INIT;
dns_rdata_dnskey_t key;
dns_rdata_rrsig_t sig;
dns_keytag_t keytag;
dns_rdata_reset(&keyrdata);
dns_rdataset_current(rdataset, &keyrdata);
result = dns_rdata_tostruct(&keyrdata, &key, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
keytag = compute_keytag(&rdata);
keytag = compute_keytag(&keyrdata);
for (result = dns_rdataset_first(sigrdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(sigrdataset))
{
dst_key_t *dstkey = NULL;
dns_rdata_reset(&sigrdata);
dns_rdataset_current(sigrdataset, &sigrdata);
result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
@ -1402,8 +1402,7 @@ selfsigned_dnskey(dns_validator_t *val) {
continue;
}
dstkey = NULL;
result = dns_dnssec_keyfromrdata(name, &rdata, mctx,
result = dns_dnssec_keyfromrdata(name, &keyrdata, mctx,
&dstkey);
if (result != ISC_R_SUCCESS) {
continue;
@ -1417,11 +1416,13 @@ selfsigned_dnskey(dns_validator_t *val) {
if (result != ISC_R_SUCCESS) {
continue;
}
if ((key.flags & DNS_KEYFLAG_REVOKE) == 0) {
answer = true;
continue;
}
dns_view_untrust(val->view, name, &key, mctx);
dns_view_untrust(val->view, name, &key);
}
}
@ -1678,118 +1679,16 @@ check_signer(dns_validator_t *val, dns_rdata_t *keyrdata,
break;
}
}
if (dstkey != NULL) {
dst_key_free(&dstkey);
}
return (result);
}
static isc_result_t
anchor_signed(dns_validator_t *val, isc_result_t *resp) {
isc_result_t result;
bool atsep = false;
/*
* First, see if this key was signed by a trust anchor.
*/
for (result = dns_rdataset_first(val->event->sigrdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(val->event->sigrdataset))
{
dns_keynode_t *keynode = NULL;
dns_rdata_t sigrdata = DNS_RDATA_INIT;
dns_fixedname_t fixed;
dns_name_t *found;
dst_key_t *dstkey;
dns_rdata_rrsig_t sig;
found = dns_fixedname_initname(&fixed);
dns_rdata_reset(&sigrdata);
dns_rdataset_current(val->event->sigrdataset, &sigrdata);
result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
if (!dns_name_equal(val->event->name, &sig.signer)) {
continue;
}
result = dns_keytable_findkeynode(val->keytable,
val->event->name,
sig.algorithm, sig.keyid,
&keynode);
if (result == ISC_R_NOTFOUND) {
result = dns_keytable_finddeepestmatch(val->keytable,
val->event->name,
found);
if (result != ISC_R_SUCCESS) {
validator_log(val, ISC_LOG_DEBUG(3),
"not beneath secure root");
*resp = markanswer(val, "validate_dnskey (1)",
"not beneath secure root");
return (ISC_R_COMPLETE);
}
continue;
}
if (result == DNS_R_PARTIALMATCH || result == ISC_R_SUCCESS) {
atsep = true;
}
while (result == ISC_R_SUCCESS) {
dns_keynode_t *nextnode = NULL;
dstkey = dns_keynode_key(keynode);
if (dstkey == NULL) {
dns_keytable_detachkeynode(val->keytable,
&keynode);
break;
}
result = verify(val, dstkey, &sigrdata, sig.keyid);
if (result == ISC_R_SUCCESS) {
dns_keytable_detachkeynode(val->keytable,
&keynode);
break;
}
result = dns_keytable_findnextkeynode(val->keytable,
keynode,
&nextnode);
dns_keytable_detachkeynode(val->keytable, &keynode);
keynode = nextnode;
}
if (result == ISC_R_SUCCESS) {
marksecure(val->event);
validator_log(val, ISC_LOG_DEBUG(3),
"signed by trusted key; "
"marking as secure");
*resp = result;
return (ISC_R_COMPLETE);
}
}
if (atsep) {
/*
* We have not found a key to verify this DNSKEY
* RRset, but there is a trust anchor defined for this
* name, so we have to assume that the RRset is invalid.
*/
char namebuf[DNS_NAME_FORMATSIZE];
dns_name_format(val->event->name, namebuf, sizeof(namebuf));
validator_log(val, ISC_LOG_NOTICE,
"unable to find a DNSKEY which verifies "
"the DNSKEY RRset and also matches a "
"trusted key for '%s'", namebuf);
*resp = DNS_R_NOVALIDKEY;
return (ISC_R_COMPLETE);
}
return (result);
}
/*
* get_dsset is called to look up a DS RRset corresponding to the name
* get_dsset() is called to look up a DS RRset corresponding to the name
* of a DNSKEY record, either in the cache or, if necessary, by starting a
* fetch. This is done in the context of validating a zone key to build a
* trust chain.
@ -1812,6 +1711,7 @@ get_dsset(dns_validator_t *val, dns_name_t *tname, isc_result_t *resp) {
* We have a DS RRset.
*/
val->dsset = &val->frdataset;
INSIST(val->keynode == NULL);
if ((DNS_TRUST_PENDING(val->frdataset.trust) ||
DNS_TRUST_ANSWER(val->frdataset.trust)) &&
dns_rdataset_isassociated(&val->fsigrdataset))
@ -1918,43 +1818,42 @@ validate_dnskey(dns_validator_t *val) {
}
/*
* If that didn't work, see if there's a key-style trust anchor we
* can validate against. If not, look up the DS at the parent.
* No trust anchor for this name, so we look up the DS at the parent.
*/
if (val->dsset == NULL) {
isc_result_t tresult = ISC_R_SUCCESS;
/*
* First, check whether the key to be validated was
* signed by a trust anchor.
*/
result = anchor_signed(val, &tresult);
if (result == ISC_R_COMPLETE) {
return (tresult);
}
/*
* If this is the root name and there was no trusted key,
* If this is the root name and there was no trust anchor,
* we can give up now, since there's no DS at the root.
*/
if (dns_name_equal(val->event->name, dns_rootname)) {
if ((val->attributes & VALATTR_TRIEDVERIFY) != 0) {
validator_log(val, ISC_LOG_DEBUG(3),
"root key failed to validate");
return (DNS_R_NOVALIDSIG);
} else {
validator_log(val, ISC_LOG_DEBUG(3),
"no trusted root key");
return (DNS_R_NOVALIDDS);
}
result = DNS_R_NOVALIDSIG;
goto cleanup;
}
/*
* Otherwise, look up the DS RRset for this name.
* Look up the DS RRset for this name.
*/
result = get_dsset(val, val->event->name, &tresult);
if (result == ISC_R_COMPLETE) {
return (tresult);
if (tresult == DNS_R_WAIT) {
/*
* Keep the keynode attached so we don't
* lose val->dsset.
*/
val->keynode = keynode;
}
result = tresult;
goto cleanup;
}
}
@ -2048,8 +1947,7 @@ validate_dnskey(dns_validator_t *val) {
/*
* Find the DNSKEY matching the DS...
*/
result = dns_dnssec_matchdskey(val->event->name,
&dsrdata,
result = dns_dnssec_matchdskey(val->event->name, &dsrdata,
val->event->rdataset,
&keyrdata);
if (result != ISC_R_SUCCESS) {
@ -2069,25 +1967,27 @@ validate_dnskey(dns_validator_t *val) {
"no RRSIG matching DS key");
}
if (result == ISC_R_SUCCESS) {
marksecure(val->event);
validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (DS)");
} else if (result == ISC_R_NOMORE && !supported_algorithm) {
validator_log(val, ISC_LOG_DEBUG(3),
"no supported algorithm/digest (DS)");
result = markanswer(val, "validate_dnskey (3)",
"no supported algorithm/digest (DS)");
} else {
validator_log(val, ISC_LOG_INFO,
"no valid signature found (DS)");
result = DNS_R_NOVALIDSIG;
}
cleanup:
if (keynode != NULL) {
val->dsset = NULL;
dns_keytable_detachkeynode(val->keytable, &keynode);
}
if (result == ISC_R_SUCCESS) {
marksecure(val->event);
validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (DS)");
return (result);
} else if (result == ISC_R_NOMORE && !supported_algorithm) {
validator_log(val, ISC_LOG_DEBUG(3),
"no supported algorithm/digest (DS)");
return (markanswer(val, "validate_dnskey (3)",
"no supported algorithm/digest (DS)"));
} else {
validator_log(val, ISC_LOG_INFO,
"no valid signature found (DS)");
return (DNS_R_NOVALIDSIG);
}
return (result);
}
/*%
@ -3236,10 +3136,6 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
(rdataset == NULL && sigrdataset == NULL && message != NULL));
REQUIRE(validatorp != NULL && *validatorp == NULL);
val = isc_mem_get(view->mctx, sizeof(*val));
val->view = NULL;
dns_view_weakattach(view, &val->view);
event = (dns_validatorevent_t *)
isc_event_allocate(view->mctx, task,
DNS_EVENT_VALIDATORSTART,
@ -3247,7 +3143,6 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
sizeof(dns_validatorevent_t));
isc_task_attach(task, &tclone);
event->validator = val;
event->result = ISC_R_FAILURE;
event->name = name;
event->type = type;
@ -3258,32 +3153,23 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
event->optout = false;
event->secure = false;
val = isc_mem_get(view->mctx, sizeof(*val));
*val = (dns_validator_t) {
.event = event,
.options = options,
.task = task,
.action = action,
.arg = arg
};
dns_view_weakattach(view, &val->view);
isc_mutex_init(&val->lock);
val->event = event;
val->options = options;
val->attributes = 0;
val->fetch = NULL;
val->subvalidator = NULL;
val->parent = NULL;
val->keytable = NULL;
result = dns_view_getsecroots(val->view, &val->keytable);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
val->key = NULL;
val->siginfo = NULL;
val->task = task;
val->action = action;
val->arg = arg;
val->labels = 0;
val->currentset = NULL;
val->keyset = NULL;
val->dsset = NULL;
val->depth = 0;
val->authcount = 0;
val->authfail = 0;
val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name);
dns_rdataset_init(&val->frdataset);
dns_rdataset_init(&val->fsigrdataset);
@ -3293,6 +3179,8 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
ISC_LINK_INIT(val, link);
val->magic = VALIDATOR_MAGIC;
event->validator = val;
if ((options & DNS_VALIDATOR_DEFER) == 0) {
isc_task_send(task, ISC_EVENT_PTR(&event));
}
@ -3370,10 +3258,15 @@ destroy(dns_validator_t *val) {
REQUIRE(val->event == NULL);
REQUIRE(val->fetch == NULL);
val->magic = 0;
if (val->key != NULL) {
dst_key_free(&val->key);
}
if (val->keytable != NULL) {
if (val->keynode != NULL) {
dns_keytable_detachkeynode(val->keytable,
&val->keynode);
}
dns_keytable_detach(&val->keytable);
}
if (val->subvalidator != NULL) {
@ -3386,7 +3279,6 @@ destroy(dns_validator_t *val) {
}
isc_mutex_destroy(&val->lock);
dns_view_weakdetach(&val->view);
val->magic = 0;
isc_mem_put(mctx, val, sizeof(*val));
}

View File

@ -1864,34 +1864,28 @@ dns_view_issecuredomain(dns_view_t *view, const dns_name_t *name,
void
dns_view_untrust(dns_view_t *view, const dns_name_t *keyname,
dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx)
dns_rdata_dnskey_t *dnskey)
{
isc_result_t result;
unsigned char data[4096];
dns_rdata_t rdata = DNS_RDATA_INIT;
isc_buffer_t buffer;
dst_key_t *key = NULL;
dns_keytable_t *sr = NULL;
REQUIRE(DNS_VIEW_VALID(view));
REQUIRE(keyname != NULL);
REQUIRE(dnskey != NULL);
/*
* Clear the revoke bit, if set, so that the key will match what's
* in secroots now.
*/
dnskey->flags &= ~DNS_KEYFLAG_REVOKE;
/* Convert dnskey to DST key. */
isc_buffer_init(&buffer, data, sizeof(data));
dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
dns_rdatatype_dnskey, dnskey, &buffer);
result = dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &key);
if (result != ISC_R_SUCCESS)
return;
result = dns_view_getsecroots(view, &sr);
if (result == ISC_R_SUCCESS) {
result = dns_keytable_deletekeynode(sr, key);
if (result != ISC_R_SUCCESS) {
return;
}
result = dns_keytable_deletekey(sr, keyname, dnskey);
if (result == ISC_R_SUCCESS) {
/*
* If key was found in secroots, then it was a
* configured trust anchor, and we want to fail
@ -1899,14 +1893,10 @@ dns_view_untrust(dns_view_t *view, const dns_name_t *keyname,
* then leave a null key so that we can't validate
* anymore.
*/
if (result == ISC_R_SUCCESS)
dns_keytable_marksecure(sr, keyname);
dns_keytable_detach(&sr);
dns_keytable_marksecure(sr, keyname);
}
dst_key_free(&key);
dns_keytable_detach(&sr);
}
/*

View File

@ -336,6 +336,7 @@ dns_dnssecsignstats_create
dns_dnssecsignstats_dump
dns_dnssecsignstats_increment
dns_ds_buildrdata
dns_ds_fromkeyrdata
dns_dsdigest_format
dns_dsdigest_fromtext
dns_dsdigest_totext
@ -457,33 +458,24 @@ dns_keydata_fromdnskey
dns_keydata_todnskey
dns_keyflags_fromtext
dns_keymgr_run
dns_keynode_attach
dns_keynode_create
dns_keynode_detach
dns_keynode_detachall
dns_keynode_dsset
dns_keynode_initial
dns_keynode_key
dns_keynode_managed
dns_keynode_trust
dns_keyring_restore
dns_keytable_add
dns_keytable_attach
dns_keytable_attachkeynode
dns_keytable_create
dns_keytable_delete
dns_keytable_deletekeynode
dns_keytable_deletekey
dns_keytable_detach
dns_keytable_detachkeynode
dns_keytable_dump
dns_keytable_find
dns_keytable_finddeepestmatch
dns_keytable_findkeynode
dns_keytable_findnextkeynode
dns_keytable_forall
dns_keytable_issecuredomain
dns_keytable_marksecure
dns_keytable_nextkeynode
dns_keytable_totext
dns_lib_init
dns_lib_shutdown

View File

@ -18,6 +18,7 @@
#include <isc/atomic.h>
#include <isc/file.h>
#include <isc/hex.h>
#include <isc/md.h>
#include <isc/mutex.h>
#include <isc/pool.h>
#include <isc/print.h>
@ -3857,12 +3858,9 @@ create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
isc_stdtime_get(&now);
/*
* If the keynode has neither a key nor a DS RRset,
* we shouldn't be here.
* If the keynode has no trust anchor set, we shouldn't be here.
*/
if (dns_keynode_key(keynode) == NULL &&
dns_keynode_dsset(keynode) == NULL)
{
if (dns_keynode_dsset(keynode) == NULL) {
return (ISC_R_FAILURE);
}
@ -3945,35 +3943,34 @@ compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
*/
static void
trust_key(dns_zone_t *zone, dns_name_t *keyname,
dns_rdata_dnskey_t *dnskey, bool initial,
isc_mem_t *mctx)
dns_rdata_dnskey_t *dnskey, bool initial)
{
isc_result_t result;
dns_rdata_t rdata = DNS_RDATA_INIT;
unsigned char data[4096];
unsigned char data[4096], digest[ISC_MAX_MD_SIZE];
isc_buffer_t buffer;
dns_keytable_t *sr = NULL;
dst_key_t *dstkey = NULL;
dns_rdata_ds_t ds;
/* Convert dnskey to DST key. */
result = dns_view_getsecroots(zone->view, &sr);
if (result != ISC_R_SUCCESS) {
return;
}
/* Build DS record for key. */
isc_buffer_init(&buffer, data, sizeof(data));
dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
dns_rdatatype_dnskey, dnskey, &buffer);
CHECK(dns_ds_fromkeyrdata(keyname, &rdata, DNS_DSDIGEST_SHA256,
digest, &ds));
CHECK(dns_keytable_add(sr, true, initial, keyname, &ds));
result = dns_view_getsecroots(zone->view, &sr);
if (result != ISC_R_SUCCESS)
goto failure;
CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
CHECK(dns_keytable_add(sr, true, initial,
dst_key_name(dstkey), &dstkey, NULL));
dns_keytable_detach(&sr);
failure:
if (dstkey != NULL)
dst_key_free(&dstkey);
if (sr != NULL)
if (sr != NULL) {
dns_keytable_detach(&sr);
}
return;
}
@ -4003,7 +4000,6 @@ load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_keydata_t keydata;
dns_rdata_dnskey_t dnskey;
isc_mem_t *mctx = zone->mctx;
int trusted = 0, revoked = 0, pending = 0;
isc_stdtime_t now;
dns_keytable_t *sr = NULL;
@ -4054,7 +4050,7 @@ load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
/* Add to keytables. */
trusted++;
trust_key(zone, name, &dnskey, (keydata.addhd == 0), mctx);
trust_key(zone, name, &dnskey, (keydata.addhd == 0));
}
if (trusted == 0 && pending != 0) {
@ -4265,12 +4261,9 @@ addifmissing(dns_keytable_t *keytable, dns_keynode_t *keynode,
}
/*
* If the keynode has neither a key-style nor a DS-style
* trust anchor, return.
* If the keynode has no trust anchor set, return.
*/
if (dns_keynode_dsset(keynode) == NULL &&
dns_keynode_key(keynode) == NULL)
{
if (dns_keynode_dsset(keynode) == NULL) {
return;
}
@ -9823,8 +9816,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
}
/*
* If the first keynode has a DS trust anchor, use that for
* verification.
* If the keynode has a DS trust anchor, use it for verification.
*/
if ((dsset = dns_keynode_dsset(keynode)) != NULL) {
for (result = dns_rdataset_first(dnskeysigs);
@ -9897,74 +9889,6 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
break;
}
}
goto anchors_done;
} else {
dns_keytable_detachkeynode(secroots, &keynode);
}
/*
* Validate the DNSKEY set against using the key-style
* trust anchor(s).
*/
for (result = dns_rdataset_first(dnskeysigs);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(dnskeysigs))
{
result = dns_keytable_find(secroots, keyname, &keynode);
if (result != ISC_R_SUCCESS) {
goto anchors_done;
}
dns_rdata_reset(&sigrr);
dns_rdataset_current(dnskeysigs, &sigrr);
result = dns_rdata_tostruct(&sigrr, &sig, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
result = ISC_R_SUCCESS;
while (result == ISC_R_SUCCESS) {
dns_keynode_t *nextnode = NULL;
dstkey = dns_keynode_key(keynode);
if (dstkey == NULL) {
/* fail_secure() was called */
break;
}
if (dst_key_alg(dstkey) == sig.algorithm &&
dst_key_id(dstkey) == sig.keyid)
{
result = dns_dnssec_verify(keyname, dnskeys,
dstkey, false, 0,
mctx, &sigrr, NULL);
dnssec_log(zone, ISC_LOG_DEBUG(3),
"Verifying DNSKEY set "
"for zone '%s' "
"using key %d/%d: %s",
namebuf, sig.keyid,
sig.algorithm,
dns_result_totext(result));
if (result == ISC_R_SUCCESS) {
dnskeys->trust = dns_trust_secure;
dnskeysigs->trust = dns_trust_secure;
secure = true;
initial = dns_keynode_initial(keynode);
dns_keynode_trust(keynode);
break;
}
}
result = dns_keytable_nextkeynode(secroots, keynode,
&nextnode);
if (result == ISC_R_SUCCESS) {
dns_keytable_detachkeynode(secroots, &keynode);
keynode = nextnode;
}
}
dns_keytable_detachkeynode(secroots, &keynode);
if (secure) {
break;
}
}
anchors_done:
@ -10173,7 +10097,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
* Remove key from secroots.
*/
dns_view_untrust(zone->view, keyname,
&dnskey, mctx);
&dnskey);
/* If initializing, delete now */
if (keydata.addhd == 0) {
@ -10346,7 +10270,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
/* Trust this key. */
result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
trust_key(zone, keyname, &dnskey, false, mctx);
trust_key(zone, keyname, &dnskey, false);
}
if (secure && !deletekey) {

View File

@ -1614,39 +1614,6 @@ check_dnskey_sigs(vctx_t *vctx, const dns_rdata_dnskey_t *dnskey,
goto cleanup;
}
/*
* The keynode didn't have any DS trust anchors, so we now try to
* find a matching DNSKEY trust anchor.
*/
result = dns_keytable_findkeynode(vctx->secroots, vctx->origin,
dst_key_alg(key), dst_key_id(key),
&keynode);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
/*
* Walk the keynode list until we find a matching key or
* reach the end.
*/
while (result == ISC_R_SUCCESS) {
dns_keynode_t *nextnode = NULL;
if (dst_key_compare(key, dns_keynode_key(keynode))) {
dns_keytable_detachkeynode(vctx->secroots, &keynode);
dns_rdataset_settrust(&vctx->keyset, dns_trust_secure);
dns_rdataset_settrust(&vctx->keysigs, dns_trust_secure);
*goodkey = true;
goto cleanup;
}
result = dns_keytable_findnextkeynode(vctx->secroots,
keynode, &nextnode);
dns_keytable_detachkeynode(vctx->secroots, &keynode);
keynode = nextnode;
}
cleanup:
if (keynode != NULL) {
dns_keytable_detachkeynode(vctx->secroots, &keynode);

View File

@ -6634,23 +6634,12 @@ has_ta(query_ctx_t *qctx) {
}
}
while (result == ISC_R_SUCCESS) {
dns_keynode_t *nextnode = NULL;
dns_keytag_t keyid = dst_key_id(dns_keynode_key(keynode));
if (keyid == sentinel) {
dns_keytable_detachkeynode(keytable, &keynode);
dns_keytable_detach(&keytable);
return (true);
}
result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
dns_keytable_detachkeynode(keytable, &keynode);
keynode = nextnode;
}
if (keynode != NULL) {
dns_keytable_detachkeynode(keytable, &keynode);
}
dns_keytable_detach(&keytable);
return (false);
}