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:
commit
72b3b458d3
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
72
lib/dns/ds.c
72
lib/dns/ds.c
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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 *,
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
*/
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
122
lib/dns/zone.c
122
lib/dns/zone.c
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user