Merge branch '622-ds-anchor' into 'master'

support "initial-ds" in managed-keys

Closes #622

See merge request isc-projects/bind9!1762
This commit is contained in:
Evan Hunt 2019-11-16 02:32:12 +00:00
commit ac65f56774
62 changed files with 1954 additions and 802 deletions

View file

@ -1,3 +1,12 @@
5319. [func] Trust anchors can now be configured using DS
format to represent a key digest, by using the
new "initial-ds" or "static-ds" keywords in
the "dnssec-keys" statement.
Note: DNSKEY-format and DS-format trust anchors
cannot both be used for the same domain name.
[GL #622]
5318. [cleanup] The DNSSEC validation code has been refactored
for clarity and to reduce code duplication.
[GL #622]

View file

@ -33,8 +33,10 @@
#include <isc/app.h>
#include <isc/base64.h>
#include <isc/buffer.h>
#include <isc/hex.h>
#include <isc/lib.h>
#include <isc/log.h>
#include <isc/md.h>
#include <isc/mem.h>
#ifdef WIN32
#include <isc/ntpaths.h>
@ -608,11 +610,12 @@ convert_name(dns_fixedname_t *fn, dns_name_t **name, const char *text) {
static isc_result_t
key_fromconfig(const cfg_obj_t *key, dns_client_t *client) {
dns_rdata_dnskey_t keystruct;
uint32_t flags, proto, alg;
const char *keystr, *keynamestr;
unsigned char keydata[4096];
isc_buffer_t keydatabuf;
dns_rdata_dnskey_t dnskey;
dns_rdata_ds_t ds;
uint32_t n1, n2, n3;
const char *datastr = NULL, *keynamestr = NULL, *atstr = NULL;
unsigned char data[4096];
isc_buffer_t databuf;
unsigned char rrdata[4096];
isc_buffer_t rrdatabuf;
isc_region_t r;
@ -620,6 +623,13 @@ key_fromconfig(const cfg_obj_t *key, dns_client_t *client) {
dns_name_t *keyname;
isc_result_t result;
bool match_root = false;
enum {
INITIAL_KEY,
STATIC_KEY,
INITIAL_DS,
STATIC_DS,
TRUSTED
} anchortype;
keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
CHECK(convert_name(&fkeyname, &keyname, keynamestr));
@ -642,46 +652,118 @@ key_fromconfig(const cfg_obj_t *key, dns_client_t *client) {
delv_log(ISC_LOG_DEBUG(3), "adding trust anchor %s", trust_anchor);
flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags"));
proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol"));
alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm"));
/* if DNSKEY, flags; if DS, key tag */
n1 = cfg_obj_asuint32(cfg_tuple_get(key, "n1"));
keystruct.common.rdclass = dns_rdataclass_in;
keystruct.common.rdtype = dns_rdatatype_dnskey;
/*
* The key data in keystruct is not dynamically allocated.
*/
keystruct.mctx = NULL;
/* if DNSKEY, protocol; if DS, algorithm */
n2 = cfg_obj_asuint32(cfg_tuple_get(key, "n2"));
ISC_LINK_INIT(&keystruct.common, link);
/* if DNSKEY, algorithm; if DS, digest type */
n3 = cfg_obj_asuint32(cfg_tuple_get(key, "n3"));
if (flags > 0xffff)
CHECK(ISC_R_RANGE);
if (proto > 0xff)
CHECK(ISC_R_RANGE);
if (alg > 0xff)
CHECK(ISC_R_RANGE);
/* What type of trust anchor is this? */
atstr = cfg_obj_asstring(cfg_tuple_get(key, "anchortype"));
if (strcasecmp(atstr, "static-key") == 0) {
anchortype = STATIC_KEY;
} else if (strcasecmp(atstr, "static-ds") == 0) {
anchortype = STATIC_DS;
} else if (strcasecmp(atstr, "initial-key") == 0) {
anchortype = INITIAL_KEY;
} else if (strcasecmp(atstr, "initial-ds") == 0) {
anchortype = INITIAL_DS;
} else {
delv_log(ISC_LOG_ERROR,
"key '%s': invalid initialization method '%s'",
keynamestr, atstr);
result = ISC_R_FAILURE;
goto cleanup;
}
keystruct.flags = (uint16_t)flags;
keystruct.protocol = (uint8_t)proto;
keystruct.algorithm = (uint8_t)alg;
isc_buffer_init(&keydatabuf, keydata, sizeof(keydata));
isc_buffer_init(&databuf, data, sizeof(data));
isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
keystr = cfg_obj_asstring(cfg_tuple_get(key, "key"));
CHECK(isc_base64_decodestring(keystr, &keydatabuf));
isc_buffer_usedregion(&keydatabuf, &r);
keystruct.datalen = r.length;
keystruct.data = r.base;
if (n1 > 0xffff) {
CHECK(ISC_R_RANGE);
}
if (n2 > 0xff) {
CHECK(ISC_R_RANGE);
}
if (n3 > 0xff) {
CHECK(ISC_R_RANGE);
}
CHECK(dns_rdata_fromstruct(NULL,
keystruct.common.rdclass,
keystruct.common.rdtype,
&keystruct, &rrdatabuf));
switch (anchortype) {
case STATIC_KEY:
case INITIAL_KEY:
case TRUSTED:
dnskey.common.rdclass = dns_rdataclass_in;
dnskey.common.rdtype = dns_rdatatype_dnskey;
dnskey.mctx = NULL;
ISC_LINK_INIT(&dnskey.common, link);
dnskey.flags = (uint16_t)n1;
dnskey.protocol = (uint8_t)n2;
dnskey.algorithm = (uint8_t)n3;
datastr = cfg_obj_asstring(cfg_tuple_get(key, "data"));
CHECK(isc_base64_decodestring(datastr, &databuf));
isc_buffer_usedregion(&databuf, &r);
dnskey.datalen = r.length;
dnskey.data = r.base;
CHECK(dns_rdata_fromstruct(NULL, dnskey.common.rdclass,
dnskey.common.rdtype,
&dnskey, &rrdatabuf));
CHECK(dns_client_addtrustedkey(client, dns_rdataclass_in,
dns_rdatatype_dnskey,
keyname, &rrdatabuf));
break;
case INITIAL_DS:
case STATIC_DS:
ds.common.rdclass = dns_rdataclass_in;
ds.common.rdtype = dns_rdatatype_ds;
ds.mctx = NULL;
ISC_LINK_INIT(&ds.common, link);
ds.key_tag = (uint16_t)n1;
ds.algorithm = (uint8_t)n2;
ds.digest_type = (uint8_t)n3;
datastr = cfg_obj_asstring(cfg_tuple_get(key, "data"));
CHECK(isc_hex_decodestring(datastr, &databuf));
isc_buffer_usedregion(&databuf, &r);
switch (ds.digest_type) {
case DNS_DSDIGEST_SHA1:
if (r.length != ISC_SHA1_DIGESTLENGTH) {
CHECK(ISC_R_UNEXPECTEDEND);
}
break;
case DNS_DSDIGEST_SHA256:
if (r.length != ISC_SHA256_DIGESTLENGTH) {
CHECK(ISC_R_UNEXPECTEDEND);
}
break;
case DNS_DSDIGEST_SHA384:
if (r.length != ISC_SHA384_DIGESTLENGTH) {
CHECK(ISC_R_UNEXPECTEDEND);
}
break;
}
ds.length = r.length;
ds.digest = r.base;
CHECK(dns_rdata_fromstruct(NULL, ds.common.rdclass,
ds.common.rdtype,
&ds, &rrdatabuf));
CHECK(dns_client_addtrustedkey(client, dns_rdataclass_in,
dns_rdatatype_ds,
keyname, &rrdatabuf));
};
CHECK(dns_client_addtrustedkey(client, dns_rdataclass_in,
keyname, &rrdatabuf));
num_keys++;
cleanup:

View file

@ -13,7 +13,7 @@
<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.named.conf">
<info>
<date>2019-08-07</date>
<date>2019-08-12</date>
</info>
<refentryinfo>
<corpname>ISC</corpname>
@ -113,7 +113,8 @@ dlz <replaceable>string</replaceable> {
<refsection><info><title>DNSSEC-KEYS</title></info>
<literallayout class="normal">
dnssec-keys { <replaceable>string</replaceable> ( static-key |
initial-key ) <replaceable>integer</replaceable> <replaceable>integer</replaceable> <replaceable>integer</replaceable>
initial-key | static-ds | initial-ds )
<replaceable>integer</replaceable> <replaceable>integer</replaceable> <replaceable>integer</replaceable>
<replaceable>quoted_string</replaceable>; ... };
</literallayout>
</refsection>
@ -158,9 +159,9 @@ logging {
<para>Deprecated - see DNSSEC-KEYS.</para>
<literallayout class="normal">
managed-keys { <replaceable>string</replaceable> ( static-key
| initial-key ) <replaceable>integer</replaceable>
<replaceable>integer</replaceable> <replaceable>integer</replaceable>
<replaceable>quoted_string</replaceable>; ... }; deprecated
| initial-key | static-ds |
initial-ds ) <replaceable>integer</replaceable> <replaceable>integer</replaceable>
<replaceable>integer</replaceable> <replaceable>quoted_string</replaceable>; ... }; deprecated
</literallayout>
</refsection>
@ -607,8 +608,9 @@ view <replaceable>string</replaceable> [ <replaceable>class</replaceable> ] {
dnssec-accept-expired <replaceable>boolean</replaceable>;
dnssec-dnskey-kskonly <replaceable>boolean</replaceable>;
dnssec-keys { <replaceable>string</replaceable> ( static-key |
initial-key ) <replaceable>integer</replaceable> <replaceable>integer</replaceable>
<replaceable>integer</replaceable> <replaceable>quoted_string</replaceable>; ... };
initial-key | static-ds | initial-ds
) <replaceable>integer</replaceable> <replaceable>integer</replaceable> <replaceable>integer</replaceable>
<replaceable>quoted_string</replaceable>; ... };
dnssec-loadkeys-interval <replaceable>integer</replaceable>;
dnssec-must-be-secure <replaceable>string</replaceable> <replaceable>boolean</replaceable>;
dnssec-secure-to-insecure <replaceable>boolean</replaceable>;
@ -646,6 +648,7 @@ view <replaceable>string</replaceable> [ <replaceable>class</replaceable> ] {
lmdb-mapsize <replaceable>sizeval</replaceable>;
managed-keys { <replaceable>string</replaceable> (
static-key | initial-key
| static-ds | initial-ds
) <replaceable>integer</replaceable> <replaceable>integer</replaceable>
<replaceable>integer</replaceable>
<replaceable>quoted_string</replaceable>; ... }; deprecated

View file

@ -698,104 +698,190 @@ configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config,
}
static isc_result_t
dstkey_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **target,
const char **keynamestrp, isc_mem_t *mctx)
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)
{
dns_rdata_dnskey_t keystruct;
uint32_t flags, proto, alg;
const char *keystr, *keynamestr;
unsigned char keydata[4096];
isc_buffer_t keydatabuf;
dns_rdata_ds_t *ds = NULL;
uint32_t n1, n2, n3;
const char *datastr = NULL, *namestr = NULL;
unsigned char data[4096];
isc_buffer_t databuf;
unsigned char rrdata[4096];
isc_buffer_t rrdatabuf;
isc_region_t r;
dns_fixedname_t fkeyname;
dns_name_t *keyname;
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,
STATIC_DNSKEY,
INIT_DS,
STATIC_DS,
TRUSTED
} anchortype;
INSIST(target != NULL && *target == NULL);
INSIST(keynamestrp != NULL && *keynamestrp == NULL);
REQUIRE(keyp != NULL && *keyp == NULL);
REQUIRE(dsp != NULL && *dsp == NULL);
REQUIRE(namestrp != NULL && *namestrp == NULL);
flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags"));
proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol"));
alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm"));
keyname = dns_fixedname_name(&fkeyname);
keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
*keynamestrp = keynamestr;
/* if DNSKEY, flags; if DS, key tag */
n1 = cfg_obj_asuint32(cfg_tuple_get(key, "n1"));
/* if DNSKEY, protocol; if DS, algorithm */
n2 = cfg_obj_asuint32(cfg_tuple_get(key, "n2"));
/* if DNSKEY, algorithm; if DS, digest type */
n3 = cfg_obj_asuint32(cfg_tuple_get(key, "n3"));
namestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
*namestrp = namestr;
name = dns_fixedname_initname(&fname);
isc_buffer_constinit(&namebuf, namestr, strlen(namestr));
isc_buffer_add(&namebuf, strlen(namestr));
CHECK(dns_name_fromtext(name, &namebuf, dns_rootname, 0, NULL));
if (*initialp) {
const char *initmethod;
initmethod = cfg_obj_asstring(cfg_tuple_get(key, "init"));
atstr = cfg_obj_asstring(cfg_tuple_get(key, "anchortype"));
if (strcasecmp(initmethod, "static-key") == 0) {
if (strcasecmp(atstr, "static-key") == 0) {
*initialp = false;
} else if (strcasecmp(initmethod, "initial-key") != 0) {
anchortype = STATIC_DNSKEY;
} else if (strcasecmp(atstr, "static-ds") == 0) {
*initialp = false;
anchortype = STATIC_DS;
} else if (strcasecmp(atstr, "initial-key") == 0) {
anchortype = INIT_DNSKEY;
} else if (strcasecmp(atstr, "initial-ds") == 0) {
anchortype = INIT_DS;
} else {
cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR,
"key '%s': "
"invalid initialization method '%s'",
keynamestr, initmethod);
namestr, atstr);
result = ISC_R_FAILURE;
goto cleanup;
}
} else {
anchortype = TRUSTED;
}
/*
* This function should never be reached for non-IN classes.
*/
keystruct.common.rdclass = dns_rdataclass_in;
keystruct.common.rdtype = dns_rdatatype_dnskey;
/*
* The key data in keystruct is not dynamically allocated.
*/
keystruct.mctx = NULL;
ISC_LINK_INIT(&keystruct.common, link);
if (flags > 0xffff)
CHECKM(ISC_R_RANGE, "key flags");
if (flags & DNS_KEYFLAG_REVOKE)
CHECKM(DST_R_BADKEYTYPE, "key flags revoke bit set");
if (proto > 0xff)
CHECKM(ISC_R_RANGE, "key protocol");
if (alg > 0xff)
CHECKM(ISC_R_RANGE, "key algorithm");
keystruct.flags = (uint16_t)flags;
keystruct.protocol = (uint8_t)proto;
keystruct.algorithm = (uint8_t)alg;
isc_buffer_init(&keydatabuf, keydata, sizeof(keydata));
isc_buffer_init(&databuf, data, sizeof(data));
isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
keystr = cfg_obj_asstring(cfg_tuple_get(key, "key"));
CHECK(isc_base64_decodestring(keystr, &keydatabuf));
isc_buffer_usedregion(&keydatabuf, &r);
keystruct.datalen = r.length;
keystruct.data = r.base;
switch(anchortype) {
case INIT_DNSKEY:
case STATIC_DNSKEY:
case TRUSTED:
/*
* This function should never be reached for view
* class other than IN
*/
keystruct.common.rdclass = dns_rdataclass_in;
keystruct.common.rdtype = dns_rdatatype_dnskey;
if ((keystruct.algorithm == DST_ALG_RSASHA1) &&
r.length > 1 && r.base[0] == 1 && r.base[1] == 3)
{
cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING,
"%s '%s' has a weak exponent",
*initialp ? "initial-key" : "static-key",
keynamestr);
/*
* The key data in keystruct is not dynamically allocated.
*/
keystruct.mctx = NULL;
ISC_LINK_INIT(&keystruct.common, link);
if (n1 > 0xffff) {
CHECKM(ISC_R_RANGE, "key flags");
}
if (n1 & DNS_KEYFLAG_REVOKE) {
CHECKM(DST_R_BADKEYTYPE, "key flags revoke bit set");
}
if (n2 > 0xff) {
CHECKM(ISC_R_RANGE, "key protocol");
}
if (n3> 0xff) {
CHECKM(ISC_R_RANGE, "key algorithm");
}
keystruct.flags = (uint16_t)n1;
keystruct.protocol = (uint8_t)n2;
keystruct.algorithm = (uint8_t)n3;
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,
keystruct.common.rdtype,
&keystruct, &rrdatabuf));
CHECK(dst_key_fromdns(name, dns_rdataclass_in,
&rrdatabuf, mctx, &dstkey));
*keyp = dstkey;
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 (n1 > 0xffff) {
CHECKM(ISC_R_RANGE, "key tag");
}
if (n2 > 0xff) {
CHECKM(ISC_R_RANGE, "key algorithm");
}
if (n3 > 0xff) {
CHECKM(ISC_R_RANGE, "digest type");
}
ds->key_tag = (uint16_t)n1;
ds->algorithm = (uint8_t)n2;
ds->digest_type = (uint8_t)n3;
datastr = cfg_obj_asstring(cfg_tuple_get(key, "data"));
CHECK(isc_hex_decodestring(datastr, &databuf));
isc_buffer_usedregion(&databuf, &r);
switch (ds->digest_type) {
case DNS_DSDIGEST_SHA1:
if (r.length != ISC_SHA1_DIGESTLENGTH) {
CHECK(ISC_R_UNEXPECTEDEND);
}
break;
case DNS_DSDIGEST_SHA256:
if (r.length != ISC_SHA256_DIGESTLENGTH) {
CHECK(ISC_R_UNEXPECTEDEND);
}
break;
case DNS_DSDIGEST_SHA384:
if (r.length != ISC_SHA384_DIGESTLENGTH) {
CHECK(ISC_R_UNEXPECTEDEND);
}
break;
}
ds->mctx = mctx;
ds->length = r.length;
ds->digest = isc_mem_allocate(mctx, r.length);
memmove(ds->digest, r.base, r.length);
*dsp = ds;
ds = NULL;
break;
default:
INSIST(0);
ISC_UNREACHABLE();
}
CHECK(dns_rdata_fromstruct(NULL,
keystruct.common.rdclass,
keystruct.common.rdtype,
&keystruct, &rrdatabuf));
dns_fixedname_init(&fkeyname);
isc_buffer_constinit(&namebuf, keynamestr, strlen(keynamestr));
isc_buffer_add(&namebuf, strlen(keynamestr));
CHECK(dns_name_fromtext(keyname, &namebuf, dns_rootname, 0, NULL));
CHECK(dst_key_fromdns(keyname, dns_rdataclass_in, &rrdatabuf,
mctx, &dstkey));
*target = dstkey;
return (ISC_R_SUCCESS);
cleanup:
@ -803,6 +889,11 @@ dstkey_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **target,
dst_key_free(&dstkey);
}
if (ds != NULL) {
dns_rdata_freestruct(ds);
isc_mem_put(mctx, ds, sizeof(*ds));
}
return (result);
}
@ -822,24 +913,45 @@ 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)
{
const dns_name_t *keyname = NULL;
const char *keynamestr = NULL;
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;
isc_result_t result;
bool initializing = managed;
result = dstkey_fromconfig(key, &initializing,
&dstkey, &keynamestr, mctx);
result = ta_fromconfig(key, &initializing, &dstkey, &ds,
&namestr, mctx);
switch (result) {
case ISC_R_SUCCESS:
/*
* Key was parsed correctly, its algorithm is supported by the
* crypto library, and it is not revoked.
* 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.
*/
keyname = dst_key_name(dstkey);
keyalg = dst_key_alg(dstkey);
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;
}
break;
case DST_R_UNSUPPORTEDALG:
case DST_R_BADKEYTYPE:
@ -851,7 +963,7 @@ process_key(const cfg_obj_t *key, dns_keytable_t *secroots,
cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING,
"ignoring %s for '%s': %s",
initializing ? "initial-key" : "static-key",
keynamestr, isc_result_totext(result));
namestr, isc_result_totext(result));
return (ISC_R_SUCCESS);
case DST_R_NOCRYPTO:
/*
@ -860,7 +972,7 @@ process_key(const cfg_obj_t *key, dns_keytable_t *secroots,
cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR,
"ignoring %s for '%s': no crypto support",
initializing ? "initial-key" : "static-key",
keynamestr);
namestr);
return (result);
default:
/*
@ -871,7 +983,7 @@ process_key(const cfg_obj_t *key, dns_keytable_t *secroots,
cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR,
"configuring %s for '%s': %s",
initializing ? "initial-key" : "static-key",
keynamestr, isc_result_totext(result));
namestr, isc_result_totext(result));
return (ISC_R_FAILURE);
}
@ -893,7 +1005,7 @@ process_key(const cfg_obj_t *key, dns_keytable_t *secroots,
cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING,
"ignoring %s for '%s': algorithm is disabled",
initializing ? "initial-key" : "static-key",
keynamestr);
namestr);
goto done;
}
@ -905,7 +1017,9 @@ process_key(const cfg_obj_t *key, dns_keytable_t *secroots,
* 'managed' and 'initializing' arguments to dns_keytable_add().
*/
result = dns_keytable_add(secroots, initializing,
initializing, &dstkey);
initializing, keyname,
dstkey != NULL ? &dstkey : NULL,
ds);
done:
/*
@ -917,6 +1031,14 @@ process_key(const cfg_obj_t *key, dns_keytable_t *secroots,
dst_key_free(&dstkey);
}
/*
* Free 'ds'.
*/
if (ds != NULL) {
dns_rdata_freestruct(ds);
isc_mem_put(mctx, ds, sizeof(*ds));
}
return (result);
}
@ -1117,16 +1239,18 @@ configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig,
}
}
CHECK(load_view_keys(view_keys, view, false, NULL, mctx));
CHECK(load_view_keys(view_managed_keys, view, true, NULL, mctx));
CHECK(load_view_keys(view_dnssec_keys, view, true, NULL, mctx));
if (view->rdclass == dns_rdataclass_in) {
CHECK(load_view_keys(view_keys, view, false, NULL, mctx));
CHECK(load_view_keys(view_dnssec_keys, view, true, NULL,
mctx));
CHECK(load_view_keys(view_managed_keys, view, true, NULL,
mctx));
CHECK(load_view_keys(global_keys, view, false, NULL, mctx));
CHECK(load_view_keys(global_managed_keys, view, true,
NULL, mctx));
CHECK(load_view_keys(global_dnssec_keys, view, true,
NULL, mctx));
CHECK(load_view_keys(global_managed_keys, view, true,
NULL, mctx));
}
/*
@ -6700,35 +6824,55 @@ struct dotat_arg {
* reported in the TAT query.
*/
static isc_result_t
get_tat_qname(dns_name_t *dst, const dns_name_t **origin,
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;
dns_keynode_t *nextnode = NULL;
dns_rdataset_t *dsset = NULL;
unsigned int i, n = 0;
uint16_t ids[12];
isc_textregion_t r;
char label[64];
int m;
REQUIRE(origin != NULL && *origin == NULL);
if ((dsset = dns_keynode_dsset(keynode)) != NULL) {
isc_result_t result;
do {
dst_key_t *key = dns_keynode_key(keynode);
if (key != NULL) {
*origin = dst_key_name(key);
for (result = dns_rdataset_first(dsset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(dsset))
{
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_ds_t ds;
dns_rdata_reset(&rdata);
dns_rdataset_current(dsset, &rdata);
result = dns_rdata_tostruct(&rdata, &ds, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
if (n < (sizeof(ids)/sizeof(ids[0]))) {
ids[n] = dst_key_id(key);
ids[n] = ds.key_tag;
n++;
}
}
nextnode = NULL;
(void)dns_keytable_nextkeynode(keytable, keynode, &nextnode);
if (keynode != firstnode) {
dns_keytable_detachkeynode(keytable, &keynode);
}
keynode = nextnode;
} while (keynode != NULL);
} 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) {
return (DNS_R_EMPTYNAME);
@ -6758,14 +6902,15 @@ get_tat_qname(dns_name_t *dst, const dns_name_t **origin,
isc_textregion_consume(&r, m);
}
return (dns_name_fromstring2(dst, label, *origin, 0, NULL));
return (dns_name_fromstring2(target, label, keyname, 0, NULL));
}
static void
dotat(dns_keytable_t *keytable, dns_keynode_t *keynode, void *arg) {
dotat(dns_keytable_t *keytable, dns_keynode_t *keynode,
dns_name_t *keyname, void *arg)
{
struct dotat_arg *dotat_arg = arg;
char namebuf[DNS_NAME_FORMATSIZE];
const dns_name_t *origin = NULL;
dns_fixedname_t fixed, fdomain;
dns_name_t *tatname, *domain;
dns_rdataset_t nameservers;
@ -6782,7 +6927,7 @@ dotat(dns_keytable_t *keytable, dns_keynode_t *keynode, void *arg) {
task = dotat_arg->task;
tatname = dns_fixedname_initname(&fixed);
result = get_tat_qname(tatname, &origin, keytable, keynode);
result = get_tat_qname(tatname, keyname, keytable, keynode);
if (result != ISC_R_SUCCESS) {
return;
}
@ -6820,17 +6965,13 @@ dotat(dns_keytable_t *keytable, dns_keynode_t *keynode, void *arg) {
* order to eventually find the destination host to send the TAT query
* to.
*
* 'origin' holds the domain name at 'keynode', i.e. the domain name
* for which the trust anchors to be reported by this TAT query are
* defined.
*
* After the dns_view_findzonecut() call, 'domain' will hold the
* deepest zone cut we can find for 'origin' while 'nameservers' will
* deepest zone cut we can find for 'keyname' while 'nameservers' will
* hold the NS RRset at that zone cut.
*/
domain = dns_fixedname_initname(&fdomain);
dns_rdataset_init(&nameservers);
result = dns_view_findzonecut(view, origin, domain, NULL, 0, 0,
result = dns_view_findzonecut(view, keyname, domain, NULL, 0, 0,
true, true, &nameservers, NULL);
if (result == ISC_R_SUCCESS) {
result = dns_resolver_createfetch(view->resolver, tatname,

View file

@ -33,12 +33,12 @@ rm $zsknopriv.private
ksksby=`$KEYGEN -3 -a RSASHA1 -q -P now -A now+15s -fk $zone`
kskrev=`$KEYGEN -3 -a RSASHA1 -q -R now+15s -fk $zone`
keyfile_to_static_keys $ksksby > trusted.conf
keyfile_to_static_ds $ksksby > trusted.conf
cp trusted.conf ../ns2/trusted.conf
cp trusted.conf ../ns3/trusted.conf
cp trusted.conf ../ns4/trusted.conf
keyfile_to_static_keys $kskrev > trusted.conf
keyfile_to_static_ds $kskrev > trusted.conf
cp trusted.conf ../ns5/trusted.conf
echo $zskact > ../active.key

View file

@ -37,7 +37,7 @@ zonefile="${zone}.db"
infile="${zonefile}.in"
ksk=`$KEYGEN -a RSASHA1 -3 -q -fk $zone`
$KEYGEN -a RSASHA1 -3 -q $zone > /dev/null
keyfile_to_static_keys $ksk > private.conf
keyfile_to_static_ds $ksk > private.conf
cp private.conf ../ns4/private.conf
$SIGNER -S -3 beef -A -o $zone -f $zonefile $infile > /dev/null

View file

@ -0,0 +1,15 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
dnssec-keys {
example. initial-ds 60724 5 1 "D74CF845955A0DFE604AF215E948E67D2EA94FF3";
example. initial-key 257 3 5 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbody0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQYfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuwE60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn6zqCkwuMmrU=";
};

View file

@ -0,0 +1,15 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
dnssec-keys {
example. static-ds 60724 5 1 "D74CF845955A0DFE604AF215E948E67D2EA94FF3";
example. static-key 257 3 5 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbody0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQYfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuwE60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn6zqCkwuMmrU=";
};

View file

@ -0,0 +1,15 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
dnssec-keys {
example. initial-ds 60724 5 1 "D74CF845955A0DFE604AF215E948E67D2EA94FF3";
example. static-ds 60724 5 2 "29E79B9064EE1A11DF3BFF19581DDFED7952C22CC204ACE17B6007EB1437E9E6";
};

View file

@ -0,0 +1,15 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
dnssec-keys {
example. initial-ds 60724 5 1 "D74CF845955A0DFE604AF215E948E67D2EA94FF3";
example. static-key 257 3 5 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbody0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQYfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuwE60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn6zqCkwuMmrU=";
};

View file

@ -0,0 +1,15 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
dnssec-keys {
example. static-ds 60724 5 1 "D74CF845955A0DFE604AF215E948E67D2EA94FF3";
example. initial-key 257 3 5 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbody0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQYfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuwE60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn6zqCkwuMmrU=";
};

View file

@ -0,0 +1,15 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
dnssec-keys {
example. initial-key 257 3 5 "AwEAAawvFp8GlBx8Qt6yaIqXkDe+nMkSk2HkTAG7qlVBo++AQwZ1j3Xl25IN4jsw0VTMbKUbafw9DYsVzztIwx1sNkKRLo6qP9SSkBL8RicQaafGtURtsYI3oqte5qqLve1CUpRD8J06Pg1xkOxsDlz9sQAyiQrOyvMbykJYkYrFYGLzYAgl/JtMyVVYlBl9pqxQuAPKYPOuO1axaad/wLN3+wTy/hcJfpvJpqzXlDF9bI5RmpoX/7geZ06vpcYJEoT0xkkmPlEl0ZjEDrm/WIaSWG0/CEDpHcOXFz4OEczMVpY+lnuFfKybwF1WHFn2BwVEOS6cMM6ukIjINQyrszHhWUU=";
example. static-key 257 3 5 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbody0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQYfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuwE60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn6zqCkwuMmrU=";
};

View file

@ -0,0 +1,14 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
dnssec-keys {
. static-ds 20326 8 2 "E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D";
};

View file

@ -0,0 +1,14 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
dnssec-keys {
example. initial-ds 60724 5 2 "29E79B9064EE1A11DF3BFF19581DDFED7952C22CC204ACE17B6007EB1437E9E6";
};

View file

@ -0,0 +1,14 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
dnssec-keys {
example. static-ds 60724 5 2 "29E79B9064EE1A11DF3BFF19581DDFED7952C22CC204ACE17B6007EB1437E9E6";
};

View file

@ -437,7 +437,15 @@ n=`expr $n + 1`
echo_i "check that a static root key generates a warning ($n)"
ret=0
$CHECKCONF check-root-static-key.conf > checkconf.out$n 2>/dev/null || ret=1
grep "static-key entry for the root zone WILL FAIL" checkconf.out$n > /dev/null || ret=1
grep "static entry for the root zone WILL FAIL" checkconf.out$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo_i "check that a static root DS trust anchor generates a warning ($n)"
ret=0
$CHECKCONF check-root-static-ds.conf > checkconf.out$n 2>/dev/null || ret=1
grep "static entry for the root zone WILL FAIL" checkconf.out$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
status=`expr $status + $ret`

View file

@ -221,9 +221,9 @@ assert_int_equal() {
}
# keyfile_to_keys_section: helper function for keyfile_to_*_keys() which
# converts keyfile data into a configuration section using the supplied
# parameters
keyfile_to_keys_section() {
# converts keyfile data into a key-style trust anchor configuration
# section using the supplied parameters
keyfile_to_keys() {
section_name=$1
key_prefix=$2
shift
@ -241,18 +241,54 @@ keyfile_to_keys_section() {
echo "};"
}
# keyfile_to_dskeys_section: helper function for keyfile_to_*_dskeys()
# converts keyfile data into a DS-style trust anchor configuration
# section using the supplied parameters
keyfile_to_dskeys() {
section_name=$1
key_prefix=$2
shift
shift
echo "$section_name {"
for keyname in $*; do
$DSFROMKEY $keyname.key | \
awk '!/^; /{
printf "\t\""$1"\" "
printf "'"$key_prefix "'"
printf $4 " " $5 " " $6 " \""
for (i=7; i<=NF; i++) printf $i
printf "\";\n"
}'
done
echo "};"
}
# keyfile_to_static_keys: convert key data contained in the keyfile(s)
# provided to a *static* "dnssec-keys" section suitable for including in a
# provided to a *static-key* "dnssec-keys" section suitable for including in a
# resolver's configuration file
keyfile_to_static_keys() {
keyfile_to_keys_section "dnssec-keys" "static-key" $*
keyfile_to_keys "dnssec-keys" "static-key" $*
}
# keyfile_to_initial_keys: convert key data contained in the keyfile(s)
# provided to an *initialzing* "dnssec-keys" section suitable for including
# provided to an *initial-key* "dnssec-keys" section suitable for including
# in a resolver's configuration file
keyfile_to_initial_keys() {
keyfile_to_keys_section "dnssec-keys" "initial-key" $*
keyfile_to_keys "dnssec-keys" "initial-key" $*
}
# keyfile_to_static_ds_keys: convert key data contained in the keyfile(s)
# provided to a *static-ds* "dnssec-keys" section suitable for including in a
# resolver's configuration file
keyfile_to_static_ds() {
keyfile_to_dskeys "dnssec-keys" "static-ds" $*
}
# keyfile_to_initial_ds_keys: convert key data contained in the keyfile(s)
# provided to an *initial-ds* "dnssec-keys" section suitable for including
# in a resolver's configuration file
keyfile_to_initial_ds() {
keyfile_to_dskeys "dnssec-keys" "initial-ds" $*
}
# keyfile_to_key_id: convert a key file name to a key ID

View file

@ -30,14 +30,15 @@ cp "../ns2/dsset-in-addr.arpa$TP" .
grep "$DEFAULT_ALGORITHM_NUMBER [12] " "../ns2/dsset-algroll$TP" > "dsset-algroll$TP"
cp "../ns6/dsset-optout-tld$TP" .
keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
ksk=$("$KEYGEN" -q -fk -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
cat "$infile" "$keyname.key" > "$zonefile"
cat "$infile" "$ksk.key" "$zsk.key" > "$zonefile"
"$SIGNER" -P -g -o "$zone" "$zonefile" > /dev/null 2>&1
# Configure the resolving server with a staitc key.
keyfile_to_static_keys "$keyname" > trusted.conf
keyfile_to_static_ds "$ksk" > trusted.conf
cp trusted.conf ../ns2/trusted.conf
cp trusted.conf ../ns3/trusted.conf
cp trusted.conf ../ns4/trusted.conf
@ -46,11 +47,11 @@ cp trusted.conf ../ns7/trusted.conf
cp trusted.conf ../ns9/trusted.conf
# ...or with an initializing key.
keyfile_to_initial_keys "$keyname" > managed.conf
keyfile_to_initial_ds "$ksk" > managed.conf
cp managed.conf ../ns4/managed.conf
#
# Save keyid for managed key id test.
#
keyfile_to_key_id "$keyname" > managed.key.id
keyfile_to_key_id "$ksk" > managed.key.id

View file

@ -23,7 +23,7 @@ zonefile=root.db.signed
keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "$zone")
# copy the KSK out first, then revoke it
keyfile_to_initial_keys "$keyname" > revoked.conf
keyfile_to_initial_ds "$keyname" > revoked.conf
"$SETTIME" -R now "${keyname}.key" > /dev/null
@ -34,4 +34,4 @@ keyfile_to_initial_keys "$keyname" > revoked.conf
keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone ".")
keyfile_to_static_keys "$keyname" > trusted.conf
keyfile_to_static_ds "$keyname" > trusted.conf

View file

@ -20,7 +20,6 @@ options {
listen-on { 10.53.0.8; };
listen-on-v6 { none; };
recursion yes;
dnssec-enable yes;
dnssec-validation yes;
minimal-responses no;
disable-algorithms "disabled.managed." { @DISABLED_ALGORITHM@; };

View file

@ -20,7 +20,6 @@ options {
listen-on { 10.53.0.9; };
listen-on-v6 { none; };
recursion yes;
dnssec-enable yes;
dnssec-validation yes;
forward only;
forwarders { 10.53.0.4; };

View file

@ -29,7 +29,7 @@ cat $infile $key1.key $key2.key > $zonefile
$SIGNER -P -g -o $zone $zonefile > /dev/null
# Configure the resolving server with a static key.
keyfile_to_static_keys $key2 > trusted.conf
keyfile_to_static_ds $key2 > trusted.conf
cp trusted.conf ../ns2/trusted.conf
cp trusted.conf ../ns3/trusted.conf
cp trusted.conf ../ns4/trusted.conf

View file

@ -25,5 +25,5 @@ cat $infile $key1.key $key2.key > $zonefile
$SIGNER -P -g -o $zone $zonefile > /dev/null 2> signer.err || cat signer.err
# Configure the resolving server with a static key.
keyfile_to_static_keys $key1 > trusted.conf
keyfile_to_static_ds $key1 > trusted.conf
cp trusted.conf ../ns2/trusted.conf

View file

@ -26,7 +26,7 @@ cat $infile $key1.key $key2.key > $zonefile
$SIGNER -P -g -o $zone $zonefile > /dev/null 2> signer.err || cat signer.err
# Configure the resolving server with a static key.
keyfile_to_static_keys $key1 > trusted.conf
keyfile_to_static_ds $key1 > trusted.conf
cp trusted.conf ../ns2/trusted.conf
cd ../ns2 && $SHELL sign.sh

View file

@ -24,7 +24,7 @@ $KEYGEN -f KSK -a $DEFAULT_ALGORITHM $zone 2>&1 > keygen.out | cat_i
keyname=`cat keygen.out`
rm -f keygen.out
keyfile_to_static_keys $keyname > trusted.conf
keyfile_to_static_ds $keyname > trusted.conf
cp trusted.conf ../ns2/trusted.conf
cp trusted.conf ../ns3/trusted.conf
cp trusted.conf ../ns5/trusted.conf

View file

@ -20,5 +20,5 @@ keyname=`$KEYGEN -q -a RSASHA1 -b 1024 -n zone -f KSK $zone`
$SIGNER -S -x -T 1200 -o ${zone} root.db > signer.out
[ $? = 0 ] || cat signer.out
keyfile_to_static_keys $keyname > trusted.conf
keyfile_to_static_ds $keyname > trusted.conf
cp trusted.conf ../ns6/trusted.conf

View file

@ -28,5 +28,5 @@ cat $infile $keyname1.key $keyname2.key >$zonefile
$SIGNER -g -o $zone -f $outfile -e +30y $zonefile > /dev/null 2> signer.err || cat signer.err
keyfile_to_static_keys $keyname2 > trusted.conf
keyfile_to_static_ds $keyname2 > trusted.conf
cp trusted.conf ../ns1

View file

@ -21,13 +21,13 @@ zskkeyname=`$KEYGEN -a rsasha256 -q $zone`
$SIGNER -Sg -o $zone $zonefile > /dev/null 2>/dev/null
# Configure the resolving server with an initializing key.
keyfile_to_initial_keys $keyname > managed.conf
keyfile_to_initial_ds $keyname > managed.conf
cp managed.conf ../ns2/managed.conf
cp managed.conf ../ns4/managed.conf
cp managed.conf ../ns5/managed.conf
# Configure a static key to be used by delv.
keyfile_to_static_keys $keyname > trusted.conf
keyfile_to_static_ds $keyname > trusted.conf
# Prepare an unsupported algorithm key.
unsupportedkey=Kunknown.+255+00000

View file

@ -27,4 +27,6 @@ rootkey=`cat ../ns1/managed.key`
cp "../ns1/${rootkey}.key" .
# Configure the resolving server with an initializing key.
# (We use key-format trust anchors here because otherwise the
# unsupported algorithm test won't work.)
keyfile_to_initial_keys $unsupportedkey $rsakey $rootkey > managed.conf

View file

@ -301,7 +301,7 @@ status=`expr $status + $ret`
echo_i "reinitialize trust anchors, add second key to bind.keys"
$PERL $SYSTEMTESTTOP/stop.pl --use-rndc --port ${CONTROLPORT} mkeys ns2
rm -f ns2/managed-keys.bind*
keyfile_to_initial_keys ns1/$original ns1/$standby1 > ns2/managed.conf
keyfile_to_initial_ds ns1/$original ns1/$standby1 > ns2/managed.conf
nextpart ns2/named.run > /dev/null
$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} mkeys ns2

View file

@ -28,7 +28,7 @@ cat $infile $keyname1.key $keyname2.key > $zonefile
$SIGNER -g -o $zone $zonefile > /dev/null
# Configure the resolving server with a static key.
keyfile_to_static_keys $keyname2 > trusted.conf
keyfile_to_static_ds $keyname2 > trusted.conf
cp trusted.conf ../ns2/trusted.conf
cp trusted.conf ../ns3/trusted.conf
cp trusted.conf ../ns4/trusted.conf

View file

@ -31,4 +31,4 @@ cat $ksk.key $zsk.key dsset-ds.example.net$TP >> $zonefile
$SIGNER -P -o $zone $zonefile > /dev/null
# Configure a static key to be used by delv
keyfile_to_static_keys $ksk > ../ns5/trusted.conf
keyfile_to_static_ds $ksk > ../ns5/trusted.conf

View file

@ -28,7 +28,7 @@ cat $infile $keyname.key > $zonefile
$SIGNER -P -g -o $zone $zonefile > /dev/null
# Configure the resolving server with a static key.
keyfile_to_static_keys $keyname > trusted.conf
keyfile_to_static_ds $keyname > trusted.conf
cp trusted.conf ../ns2/trusted.conf
cp trusted.conf ../ns3/trusted.conf
cp trusted.conf ../ns4/trusted.conf

View file

@ -25,7 +25,7 @@ cat $infile $keyname.key > $zonefile
$SIGNER -P -g -o $zone $zonefile > /dev/null
# Configure the resolving server with a static key.
keyfile_to_static_keys $keyname > trusted.conf
keyfile_to_static_ds $keyname > trusted.conf
cp trusted.conf ../ns2/trusted.conf
cp trusted.conf ../ns3/trusted.conf

View file

@ -29,8 +29,8 @@ cat "$infile" "$keyname.key" > "$zonefile"
$SIGNER -P -g -o $zone $zonefile > /dev/null
# Configure the resolving server with a static key.
keyfile_to_static_keys "$keyname" > trusted.conf
keyfile_to_static_ds "$keyname" > trusted.conf
cp trusted.conf ../ns2/trusted.conf
# ...or with an initializing key.
keyfile_to_initial_keys "$keyname" > managed.conf
keyfile_to_initial_ds "$keyname" > managed.conf

View file

@ -16,4 +16,4 @@ set -e
keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone ".")
keyfile_to_static_keys "$keyname" > trusted.conf
keyfile_to_static_ds "$keyname" > trusted.conf

View file

@ -27,7 +27,7 @@ cat $infile $keyname1.key $keyname2.key > $zonefile
$SIGNER -g -o $zone $zonefile > /dev/null
# Configure the resolving server with a trusted key.
keyfile_to_static_keys $keyname2 > trusted.conf
keyfile_to_static_ds $keyname2 > trusted.conf
zone=undelegated
infile=undelegated.db.in
@ -38,5 +38,5 @@ cat $infile $keyname1.key $keyname2.key > $zonefile
$SIGNER -g -o $zone $zonefile > /dev/null
keyfile_to_static_keys $keyname2 >> trusted.conf
keyfile_to_static_ds $keyname2 >> trusted.conf
cp trusted.conf ../ns2/trusted.conf

View file

@ -40,4 +40,4 @@ cat "$infile" "$keyname.key" > "$zonefile"
$SIGNER -P -g -o $zone $zonefile > /dev/null
# Configure the resolving server with a static key.
keyfile_to_static_keys "$keyname" > trusted.conf
keyfile_to_static_ds "$keyname" > trusted.conf

View file

@ -43,7 +43,7 @@ cat $infile $keyname1.key $keyname2.key > $zonefile
$SIGNER -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
echo_i "signed $zone"
keyfile_to_static_keys $keyname2 > private.nsec.conf
keyfile_to_static_ds $keyname2 > private.nsec.conf
zone=nsec3
infile=nsec3.db.in
@ -72,7 +72,7 @@ cat $infile $keyname1.key $keyname2.key > $zonefile
$SIGNER -3 - -H 10 -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
echo_i "signed $zone"
keyfile_to_static_keys $keyname2 > private.nsec3.conf
keyfile_to_static_ds $keyname2 > private.nsec3.conf
zone=.
infile=root.db.in
@ -87,4 +87,4 @@ cat $infile $keyname1.key $keyname2.key $dssets >$zonefile
$SIGNER -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
echo_i "signed $zone"
keyfile_to_static_keys $keyname2 > trusted.conf
keyfile_to_static_ds $keyname2 > trusted.conf

View file

@ -2230,13 +2230,14 @@ allow-update { !{ !localnets; any; }; key host1-host2. ;};
The keys specified in <command>dnssec-keys</command>
copies of DNSKEY RRs for zones that are used to form the
first link in the cryptographic chain of trust. Keys configured
with the keyword <command>static-key</command> are loaded directly
with the keyword <command>static-key</command> or
<command>static-ds</command> are loaded directly
into the table of trust anchors, and can only be changed by
altering the configuration. Keys configured with
<command>initial-key</command> are used to initialize
RFC 5011 trust anchor maintenance, and will be kept up to
date automatically after the first time <command>named</command>
runs.
<command>initial-key</command> or <command>initial-ds</command>
are used to initialize RFC 5011 trust anchor maintenance, and
will be kept up to date automatically after the first time
<command>named</command> runs.
</para>
<para>
@ -2276,17 +2277,7 @@ dnssec-keys {
97S+LKUTpQcq27R7AT3/V5hRQxScINqwcz4jYqZD2fQ
dgxbcDTClU0CRBdiieyLMNzXG3";
/* Key for our organization's forward zone */
example.com. static-key 257 3 5 "AwEAAaxPMcR2x0HbQV4WeZB6oEDX+r0QM6
5KbhTjrW1ZaARmPhEZZe3Y9ifgEuq7vZ/z
GZUdEGNWy+JZzus0lUptwgjGwhUS1558Hb
4JKUbbOTcM8pwXlj0EiX3oDFVmjHO444gL
kBOUKUf/mC7HvfwYH/Be22GnClrinKJp1O
g4ywzO9WglMk7jbfW33gUKvirTHr25GL7S
TQUzBb5Usxt8lgnyTUHs1t3JwCY5hKZ6Cq
FxmAVZP20igTixin/1LcrgX/KMEGd/biuv
F4qJCyduieHukuY3H4XMAcR+xia2nIUPvm
/oyWR8BW/hWdzOvnSCThlHf3xiYleDbt/o
1OTQ09A0=";
example.com. static-ds 54135 5 2 "8EF922C97F1D07B23134440F19682E7519ADDAE180E20B1B1EC52E7F58B2831D"
/* Key for our reverse zone. */
2.0.192.IN-ADDRPA.NET. static-key 257 3 5 "AQOnS4xn/IgOUpBPJ3bogzwc
@ -3215,11 +3206,14 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
</entry>
<entry colname="2">
<para>
defines DNSSEC keys: if used with the
<command>initial-key</command> keyword,
keys are kept up to date using RFC 5011
trust anchor maintenance, and if used with
<command>static-key</command>, keys are permanent.
defines DNSSEC trust anchors: if used with
the <command>initial-key</command> or
<command>initial-ds</command> keyword,
trust anchors are kept up to date using RFC
5011 trust anchor maintenance, and if used with
<command>static-key</command> or
<command>static-ds</command>, trust anchors
are permanent.
</para>
</entry>
</row>
@ -4628,7 +4622,8 @@ badresp:1,adberr:0,findfail:0,valfail:0]
<para>
Specifies the directory in which to store the files that
track managed DNSSEC keys (i.e., those configured using
the <command>initial-key</command> keyword in a
the <command>initial-key</command> or
<command>initial-ds</command> keywords in a
<command>dnssec-keys</command> statement). By default,
this is the working directory. The directory
<emphasis>must</emphasis> be writable by the effective
@ -10864,12 +10859,12 @@ example.com CNAME rpz-tcp-only.
trust anchors. DNSSEC is described in <xref linkend="DNSSEC"/>.
</para>
<para>
A trust anchor is defined when the public key for
a non-authoritative zone is known, but cannot be securely
obtained through DNS, either because it is the DNS root zone
or because its parent zone is unsigned. Once a key has been
configured as a trust anchor, it is treated as if it had
been validated and proven secure.
A trust anchor is defined when the public key or public key
digest for a non-authoritative zone is known, but cannot be
securely obtained through DNS, either because it is the DNS
root zone or because its parent zone is unsigned. Once a key
or digest has been configured as a trust anchor, it is treated
as if it had been validated and proven secure.
</para>
<para>
The resolver attempts DNSSEC validation on all DNS data
@ -10881,19 +10876,9 @@ example.com CNAME rpz-tcp-only.
<para>
All keys listed in <command>dnssec-keys</command>, and
their corresponding zones, are deemed to exist regardless
of what parent zones say. Only keys configured as trust anchors
of what parent zones say. Only keys configured as trust anchors
are used to validate the DNSKEY RRset for the corresponding
name. The parent's DS RRset will not be used.
</para>
<para>
The <command>dnssec-keys</command> statement can contain
multiple key entries, each consisting of the key's
domain name, followed by the <command>static-key</command> or
<command>initial-key</command> keyword, then the key's flags,
protocol, algorithm, and the Base64 representation of the key
data. Spaces, tabs, newlines and carriage returns are ignored
in the key data, so the configuration may be split up into
multiple lines.
name. The parent's DS RRset will not be used.
</para>
<para>
<command>dnssec-keys</command> may be set at the top level
@ -10903,11 +10888,33 @@ example.com CNAME rpz-tcp-only.
defined in a view are only used within that view.
</para>
<para>
<command>dnssec-keys</command> entries can be configured with
two keywords: <command>static-key</command> or
<command>initial-key</command>. Keys configured with
<command>static-key</command> are immutable,
while keys configured with <command>initial-key</command>
The <command>dnssec-keys</command> statement can contain
multiple trust anchor entries, each consisting of a
domain name, followed by an "anchor type" keyword indicating
the trust anchor's format, followed by the key or digest data.
</para>
<para>
If the anchor type is <command>static-key</command> or
<command>initial-key</command>, then it is followed with the
key's flags, protocol, algorithm, and the Base64 representation
of the public key data. This is identical to the text
representation of a DNSKEY record. Spaces, tabs, newlines and
carriage returns are ignored in the key data, so the
configuration may be split up into multiple lines.
</para>
<para>
If the anchor type is <command>static-ds</command> or
<command>initial-ds</command>, then it is followed with the
key tag, algorithm, digest type, and the hexidecimal
representation of the key digest. This is identical to the
text representation of a DS record. Spaces, tabs, newlines
and carriage returns are ignored.
</para>
<para>
Trust anchors configured with the
<command>static-key</command> or <command>static-ds</command>
anchor types are immutable, while keys configured with
<command>initial-key</command> or <command>initial-ds</command>
can be kept up to date automatically, without intervention
from the resolver operator. (<command>static-key</command>
keys are identical to keys configured using the deprecated
@ -10917,45 +10924,55 @@ example.com CNAME rpz-tcp-only.
Suppose, for example, that a zone's key-signing
key was compromised, and the zone owner had to revoke and
replace the key. A resolver which had the original key
configured as a <command>static-key</command> would be
unable to validate this zone any longer; it would
reply with a SERVFAIL response code. This would
continue until the resolver operator had updated the
<command>dnssec-keys</command> statement with the new key.
configured using <command>static-key</command> or
<command>static-ds</command> would be unable to validate
this zone any longer; it would reply with a SERVFAIL response
code. This would continue until the resolver operator had
updated the <command>dnssec-keys</command> statement with
the new key.
</para>
<para>
If, however, the trust anchor had been configured with
<command>initial-key</command> instead, then the
zone owner could add a "stand-by" key to their zone in advance.
<command>named</command> would store the stand-by key, and
when the original key was revoked, <command>named</command>
would be able to transition smoothly to the new key. It would
also recognize that the old key had been revoked, and cease
using that key to validate answers, minimizing the damage that
the compromised key could do. This is the process used to
keep the ICANN root DNSSEC key up to date.
<command>initial-key</command> or <command>initial-ds</command>
instead, then the zone owner could add a "stand-by" key to
their zone in advance. <command>named</command> would store
the stand-by key, and when the original key was revoked,
<command>named</command> would be able to transition smoothly
to the new key. It would also recognize that the old key had
been revoked, and cease using that key to validate answers,
minimizing the damage that the compromised key could do.
This is the process used to keep the ICANN root DNSSEC key
up to date.
</para>
<para>
Whereas <command>static-key</command>
keys continue to be trusted until they are removed from
Whereas <command>static-key</command> and
<command>static-ds</command> trust anchors continue
to be trusted until they are removed from
<filename>named.conf</filename>, an
<command>initial-key</command> is only trusted
<emphasis>once</emphasis>: for as long as it
<command>initial-key</command> or <command>initial-ds</command>
is only trusted <emphasis>once</emphasis>: for as long as it
takes to load the managed key database and start the RFC 5011
key maintenance process.
</para>
<para>
It is not possible to mix static with initial trust anchors
for the same domain name. It is also not possible to mix
<command>key</command> with <command>ds</command> trust anchors.
</para>
<para>
The first time <command>named</command> runs with an
<command>initial-key</command> configured in
<filename>named.conf</filename>, it fetches the
<command>initial-key</command> or <command>initial-ds</command>
configured in <filename>named.conf</filename>, it fetches the
DNSKEY RRset directly from the zone apex, and validates it
using the key specified in <command>dnssec-keys</command>.
If the DNSKEY RRset is validly signed, then it is
used as the basis for a new managed keys database.
using the trust anchor specified in <command>dnssec-keys</command>.
If the DNSKEY RRset is validly signed by a key matching
the trust anchor, then it is used as the basis for a new
managed keys database.
</para>
<para>
From that point on, whenever <command>named</command> runs, it
sees the <command>initial-key</command> listed in
sees the <command>initial-key</command> or
<command>initial-ds</command> listed in
<command>dnssec-keys</command>, checks to
make sure RFC 5011 key maintenance has already been initialized
for the specified domain, and if so, it simply moves on. The
@ -10966,13 +10983,13 @@ example.com CNAME rpz-tcp-only.
</para>
<para>
The next time <command>named</command> runs after an
<command>initial-key</command> has been
<emphasis>removed</emphasis> from the
<command>initial-key</command> or <command>initial-ds</command>
trust anchor has been <emphasis>removed</emphasis> from the
<command>dnssec-keys</command> statement (or changed to
a <command>static-key</command>), the corresponding
zone will be removed from the managed keys database,
and RFC 5011 key maintenance will no longer be used for that
domain.
a <command>static-key</command> or <command>static-ds</command>),
the corresponding keys will be removed from the managed keys
database, and RFC 5011 key maintenance will no longer be used
for that domain.
</para>
<para>
In the current implementation, the managed keys database

View file

@ -13,6 +13,7 @@
<programlisting>
<command>dnssec-keys</command> { <replaceable>string</replaceable> ( static-key |
<command>initial-key</command> ) <replaceable>integer</replaceable> <replaceable>integer</replaceable> <replaceable>integer</replaceable>
<command>initial-key</command> | static-ds | initial-ds )
<replaceable>integer</replaceable> <replaceable>integer</replaceable> <replaceable>integer</replaceable>
<replaceable>quoted_string</replaceable>; ... };
</programlisting>

View file

@ -138,7 +138,8 @@ $ <userinput>make</userinput>
<filename>named.conf</filename>, except that all
<command>managed-keys</command> entries will be treated as
if they were configured with the <command>static-key</command>
keyword, even if they are configured with <command>initial-key</command>.
or <command>static-ds</command> keywords, even if they are configured
with <command>initial-key</command> or <command>iniital-ds</command>.
(See <xref linkend="managed-keys"/> for syntax details.)
</para>
</section>

View file

@ -13,7 +13,7 @@
<programlisting>
<command>managed-keys</command> { <replaceable>string</replaceable> ( static-key
| initial-key ) <replaceable>integer</replaceable>
<replaceable>integer</replaceable> <replaceable>integer</replaceable>
<replaceable>quoted_string</replaceable>; ... }; deprecated
| initial-key | static-ds |
<command>initial-ds</command> ) <replaceable>integer</replaceable> <replaceable>integer</replaceable>
<replaceable>integer</replaceable> <replaceable>quoted_string</replaceable>; ... }; deprecated
</programlisting>

View file

@ -25,8 +25,8 @@
<para>To configure a validating resolver to use RFC 5011 to
maintain a trust anchor, configure the trust anchor using a
<command>dnssec-keys</command> statement and the
<command>initial-key</command> keyword. Information about
this can be found in
<command>initial-key</command> or <command>initial-ds</command>
keyword. Information about this can be found in
<xref linkend="dnssec-keys"/>.</para>
</section>
<section><info><title>Authoritative Server</title></info>

View file

@ -33,6 +33,27 @@
policy used by <command>dnssec-keymgr</command>.) [GL #1134]
</para>
</listitem>
<listitem>
<para>
Two new keywords have been added to the
<command>dnssec-keys</command> statement:
<command>initial-ds</command> and <command>static-ds</command>.
These allow the use of trust anchors in DS format instead of
DNSKEY format. DS format allows trust anchors to be configured
for keys that have not yet been published; this is the format
used by IANA when announcing future root keys.
</para>
<para>
As with the <command>initial-key</command> and
<command>static-key</command> keywords, <command>initial-ds</command>
configures a dynamic trust anchor to be maintained via RFC 5011, and
<command>static-ds</command> configures a permanent trust anchor.
</para>
<para>
(Note: Currently, DNSKEY-format and DS-format trust anchors
cannot both be used for the same domain name.) [GL #6] [GL #622]
</para>
</listitem>
</itemizedlist>
</section>

View file

@ -22,7 +22,8 @@ dlz <string> {
}; // may occur multiple times
dnssec-keys { <string> ( static-key |
initial-key ) <integer> <integer> <integer>
initial-key | static-ds | initial-ds )
<integer> <integer> <integer>
<quoted_string>; ... }; // may occur multiple times
dnssec-policy <string> {
@ -68,9 +69,9 @@ logging {
lwres { <unspecified-text> }; // obsolete, may occur multiple times
managed-keys { <string> ( static-key
| initial-key ) <integer>
<integer> <integer>
<quoted_string>; ... }; // may occur multiple times, deprecated
| initial-key | static-ds |
initial-ds ) <integer> <integer>
<integer> <quoted_string>; ... }; // may occur multiple times, deprecated
masters <string> [ port <integer> ] [ dscp
<integer> ] { ( <masters> | <ipv4_address> [
@ -209,7 +210,7 @@ options {
fstrm-set-output-queue-model ( mpsc | spsc ); // not configured
fstrm-set-output-queue-size <integer>; // not configured
fstrm-set-reopen-interval <ttlval>; // not configured
geoip-directory ( <quoted_string> | none ); // not configured
geoip-directory ( <quoted_string> | none );
geoip-use-ecs <boolean>; // obsolete
glue-cache <boolean>;
has-old-clients <boolean>; // ancient
@ -230,7 +231,7 @@ options {
listen-on-v6 [ port <integer> ] [ dscp
<integer> ] {
<address_match_element>; ... }; // may occur multiple times
lmdb-mapsize <sizeval>; // non-operational
lmdb-mapsize <sizeval>;
lock-file ( <quoted_string> | none );
maintain-ixfr-base <boolean>; // ancient
managed-keys-directory <quoted_string>;
@ -538,8 +539,9 @@ view <string> [ <class> ] {
dnssec-dnskey-kskonly <boolean>;
dnssec-enable <boolean>; // obsolete
dnssec-keys { <string> ( static-key |
initial-key ) <integer> <integer>
<integer> <quoted_string>; ... }; // may occur multiple times
initial-key | static-ds | initial-ds
) <integer> <integer> <integer>
<quoted_string>; ... }; // may occur multiple times
dnssec-loadkeys-interval <integer>;
dnssec-lookaside ( <string>
trust-anchor <string> |
@ -581,10 +583,11 @@ view <string> [ <class> ] {
}; // may occur multiple times
key-directory <quoted_string>;
lame-ttl <ttlval>;
lmdb-mapsize <sizeval>; // non-operational
lmdb-mapsize <sizeval>;
maintain-ixfr-base <boolean>; // ancient
managed-keys { <string> (
static-key | initial-key
| static-ds | initial-ds
) <integer> <integer>
<integer>
<quoted_string>; ... }; // may occur multiple times, deprecated

View file

@ -22,7 +22,8 @@ dlz <string> {
}; // may occur multiple times
dnssec-keys { <string> ( static-key |
initial-key ) <integer> <integer> <integer>
initial-key | static-ds | initial-ds )
<integer> <integer> <integer>
<quoted_string>; ... }; // may occur multiple times
dyndb <string> <quoted_string> {
@ -50,9 +51,9 @@ logging {
};
managed-keys { <string> ( static-key
| initial-key ) <integer>
<integer> <integer>
<quoted_string>; ... }; // may occur multiple times, deprecated
| initial-key | static-ds |
initial-ds ) <integer> <integer>
<integer> <quoted_string>; ... }; // may occur multiple times, deprecated
masters <string> [ port <integer> ] [ dscp
<integer> ] { ( <masters> | <ipv4_address> [
@ -175,7 +176,7 @@ options {
fstrm-set-output-queue-model ( mpsc | spsc ); // not configured
fstrm-set-output-queue-size <integer>; // not configured
fstrm-set-reopen-interval <ttlval>; // not configured
geoip-directory ( <quoted_string> | none ); // not configured
geoip-directory ( <quoted_string> | none );
glue-cache <boolean>;
heartbeat-interval <integer>;
hostname ( <quoted_string> | none );
@ -192,7 +193,7 @@ options {
listen-on-v6 [ port <integer> ] [ dscp
<integer> ] {
<address_match_element>; ... }; // may occur multiple times
lmdb-mapsize <sizeval>; // non-operational
lmdb-mapsize <sizeval>;
lock-file ( <quoted_string> | none );
managed-keys-directory <quoted_string>;
masterfile-format ( map | raw | text );
@ -470,8 +471,9 @@ view <string> [ <class> ] {
dnssec-accept-expired <boolean>;
dnssec-dnskey-kskonly <boolean>;
dnssec-keys { <string> ( static-key |
initial-key ) <integer> <integer>
<integer> <quoted_string>; ... }; // may occur multiple times
initial-key | static-ds | initial-ds
) <integer> <integer> <integer>
<quoted_string>; ... }; // may occur multiple times
dnssec-loadkeys-interval <integer>;
dnssec-must-be-secure <string> <boolean>; // may occur multiple times
dnssec-secure-to-insecure <boolean>;
@ -506,9 +508,10 @@ view <string> [ <class> ] {
}; // may occur multiple times
key-directory <quoted_string>;
lame-ttl <ttlval>;
lmdb-mapsize <sizeval>; // non-operational
lmdb-mapsize <sizeval>;
managed-keys { <string> (
static-key | initial-key
| static-ds | initial-ds
) <integer> <integer>
<integer>
<quoted_string>; ... }; // may occur multiple times, deprecated

View file

@ -40,6 +40,7 @@
#include <dns/acl.h>
#include <dns/dnstap.h>
#include <dns/fixedname.h>
#include <dns/keyvalues.h>
#include <dns/rbt.h>
#include <dns/rdataclass.h>
#include <dns/rdatatype.h>
@ -48,6 +49,7 @@
#include <dns/ssu.h>
#include <dst/dst.h>
#include <dst/result.h>
#include <isccfg/aclconf.h>
#include <isccfg/cfg.h>
@ -3117,28 +3119,128 @@ check_servers(const cfg_obj_t *config, const cfg_obj_t *voptions,
#define ROOT_KSK_2017 0x08
static isc_result_t
check_trusted_key(const cfg_obj_t *key, bool managed,
unsigned int *keyflags, isc_log_t *logctx)
check_trust_anchor(const cfg_obj_t *key, bool managed,
unsigned int *flagsp, isc_log_t *logctx)
{
const char *keystr, *keynamestr;
const char *str = NULL, *namestr = NULL;
dns_fixedname_t fkeyname;
dns_name_t *keyname;
dns_name_t *keyname = NULL;
isc_buffer_t b;
isc_region_t r;
isc_result_t result = ISC_R_SUCCESS;
isc_result_t tresult;
uint32_t flags, proto, alg;
unsigned char keydata[4096];
uint32_t n1, n2, n3;
unsigned char data[4096];
const char *atstr = NULL;
enum {
INIT_DNSKEY,
STATIC_DNSKEY,
INIT_DS,
STATIC_DS,
TRUSTED
} anchortype;
flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags"));
proto = cfg_obj_asuint32(cfg_tuple_get(key, "protocol"));
alg = cfg_obj_asuint32(cfg_tuple_get(key, "algorithm"));
/*
* The 2010 and 2017 IANA root keys - these are used below
* to check the contents of trusted, initial and
* static trust anchor configurations.
*/
static const unsigned char root_ksk_2010[] = {
0x03, 0x01, 0x00, 0x01, 0xa8, 0x00, 0x20, 0xa9,
0x55, 0x66, 0xba, 0x42, 0xe8, 0x86, 0xbb, 0x80,
0x4c, 0xda, 0x84, 0xe4, 0x7e, 0xf5, 0x6d, 0xbd,
0x7a, 0xec, 0x61, 0x26, 0x15, 0x55, 0x2c, 0xec,
0x90, 0x6d, 0x21, 0x16, 0xd0, 0xef, 0x20, 0x70,
0x28, 0xc5, 0x15, 0x54, 0x14, 0x4d, 0xfe, 0xaf,
0xe7, 0xc7, 0xcb, 0x8f, 0x00, 0x5d, 0xd1, 0x82,
0x34, 0x13, 0x3a, 0xc0, 0x71, 0x0a, 0x81, 0x18,
0x2c, 0xe1, 0xfd, 0x14, 0xad, 0x22, 0x83, 0xbc,
0x83, 0x43, 0x5f, 0x9d, 0xf2, 0xf6, 0x31, 0x32,
0x51, 0x93, 0x1a, 0x17, 0x6d, 0xf0, 0xda, 0x51,
0xe5, 0x4f, 0x42, 0xe6, 0x04, 0x86, 0x0d, 0xfb,
0x35, 0x95, 0x80, 0x25, 0x0f, 0x55, 0x9c, 0xc5,
0x43, 0xc4, 0xff, 0xd5, 0x1c, 0xbe, 0x3d, 0xe8,
0xcf, 0xd0, 0x67, 0x19, 0x23, 0x7f, 0x9f, 0xc4,
0x7e, 0xe7, 0x29, 0xda, 0x06, 0x83, 0x5f, 0xa4,
0x52, 0xe8, 0x25, 0xe9, 0xa1, 0x8e, 0xbc, 0x2e,
0xcb, 0xcf, 0x56, 0x34, 0x74, 0x65, 0x2c, 0x33,
0xcf, 0x56, 0xa9, 0x03, 0x3b, 0xcd, 0xf5, 0xd9,
0x73, 0x12, 0x17, 0x97, 0xec, 0x80, 0x89, 0x04,
0x1b, 0x6e, 0x03, 0xa1, 0xb7, 0x2d, 0x0a, 0x73,
0x5b, 0x98, 0x4e, 0x03, 0x68, 0x73, 0x09, 0x33,
0x23, 0x24, 0xf2, 0x7c, 0x2d, 0xba, 0x85, 0xe9,
0xdb, 0x15, 0xe8, 0x3a, 0x01, 0x43, 0x38, 0x2e,
0x97, 0x4b, 0x06, 0x21, 0xc1, 0x8e, 0x62, 0x5e,
0xce, 0xc9, 0x07, 0x57, 0x7d, 0x9e, 0x7b, 0xad,
0xe9, 0x52, 0x41, 0xa8, 0x1e, 0xbb, 0xe8, 0xa9,
0x01, 0xd4, 0xd3, 0x27, 0x6e, 0x40, 0xb1, 0x14,
0xc0, 0xa2, 0xe6, 0xfc, 0x38, 0xd1, 0x9c, 0x2e,
0x6a, 0xab, 0x02, 0x64, 0x4b, 0x28, 0x13, 0xf5,
0x75, 0xfc, 0x21, 0x60, 0x1e, 0x0d, 0xee, 0x49,
0xcd, 0x9e, 0xe9, 0x6a, 0x43, 0x10, 0x3e, 0x52,
0x4d, 0x62, 0x87, 0x3d
};
static const unsigned char root_ksk_2017[] = {
0x03, 0x01, 0x00, 0x01, 0xac, 0xff, 0xb4, 0x09,
0xbc, 0xc9, 0x39, 0xf8, 0x31, 0xf7, 0xa1, 0xe5,
0xec, 0x88, 0xf7, 0xa5, 0x92, 0x55, 0xec, 0x53,
0x04, 0x0b, 0xe4, 0x32, 0x02, 0x73, 0x90, 0xa4,
0xce, 0x89, 0x6d, 0x6f, 0x90, 0x86, 0xf3, 0xc5,
0xe1, 0x77, 0xfb, 0xfe, 0x11, 0x81, 0x63, 0xaa,
0xec, 0x7a, 0xf1, 0x46, 0x2c, 0x47, 0x94, 0x59,
0x44, 0xc4, 0xe2, 0xc0, 0x26, 0xbe, 0x5e, 0x98,
0xbb, 0xcd, 0xed, 0x25, 0x97, 0x82, 0x72, 0xe1,
0xe3, 0xe0, 0x79, 0xc5, 0x09, 0x4d, 0x57, 0x3f,
0x0e, 0x83, 0xc9, 0x2f, 0x02, 0xb3, 0x2d, 0x35,
0x13, 0xb1, 0x55, 0x0b, 0x82, 0x69, 0x29, 0xc8,
0x0d, 0xd0, 0xf9, 0x2c, 0xac, 0x96, 0x6d, 0x17,
0x76, 0x9f, 0xd5, 0x86, 0x7b, 0x64, 0x7c, 0x3f,
0x38, 0x02, 0x9a, 0xbd, 0xc4, 0x81, 0x52, 0xeb,
0x8f, 0x20, 0x71, 0x59, 0xec, 0xc5, 0xd2, 0x32,
0xc7, 0xc1, 0x53, 0x7c, 0x79, 0xf4, 0xb7, 0xac,
0x28, 0xff, 0x11, 0x68, 0x2f, 0x21, 0x68, 0x1b,
0xf6, 0xd6, 0xab, 0xa5, 0x55, 0x03, 0x2b, 0xf6,
0xf9, 0xf0, 0x36, 0xbe, 0xb2, 0xaa, 0xa5, 0xb3,
0x77, 0x8d, 0x6e, 0xeb, 0xfb, 0xa6, 0xbf, 0x9e,
0xa1, 0x91, 0xbe, 0x4a, 0xb0, 0xca, 0xea, 0x75,
0x9e, 0x2f, 0x77, 0x3a, 0x1f, 0x90, 0x29, 0xc7,
0x3e, 0xcb, 0x8d, 0x57, 0x35, 0xb9, 0x32, 0x1d,
0xb0, 0x85, 0xf1, 0xb8, 0xe2, 0xd8, 0x03, 0x8f,
0xe2, 0x94, 0x19, 0x92, 0x54, 0x8c, 0xee, 0x0d,
0x67, 0xdd, 0x45, 0x47, 0xe1, 0x1d, 0xd6, 0x3a,
0xf9, 0xc9, 0xfc, 0x1c, 0x54, 0x66, 0xfb, 0x68,
0x4c, 0xf0, 0x09, 0xd7, 0x19, 0x7c, 0x2c, 0xf7,
0x9e, 0x79, 0x2a, 0xb5, 0x01, 0xe6, 0xa8, 0xa1,
0xca, 0x51, 0x9a, 0xf2, 0xcb, 0x9b, 0x5f, 0x63,
0x67, 0xe9, 0x4c, 0x0d, 0x47, 0x50, 0x24, 0x51,
0x35, 0x7b, 0xe1, 0xb5
};
static const unsigned char root_ds_1_2017[] = {
0xae, 0x1e, 0xa5, 0xb9, 0x74, 0xd4, 0xc8, 0x58,
0xb7, 0x40, 0xbd, 0x03, 0xe3, 0xce, 0xd7, 0xeb,
0xfc, 0xbd, 0x17, 0x24
};
static const unsigned char root_ds_2_2017[] = {
0xe0, 0x6d, 0x44, 0xb8, 0x0b, 0x8f, 0x1d, 0x39,
0xa9, 0x5c, 0x0b, 0x0d, 0x7c, 0x65, 0xd0, 0x84,
0x58, 0xe8, 0x80, 0x40, 0x9b, 0xbc, 0x68, 0x34,
0x57, 0x10, 0x42, 0x37, 0xc7, 0xf8, 0xec, 0x8D
};
/* if DNSKEY, flags; if DS, key tag */
n1 = cfg_obj_asuint32(cfg_tuple_get(key, "n1"));
/* if DNSKEY, protocol; if DS, algorithm */
n2 = cfg_obj_asuint32(cfg_tuple_get(key, "n2"));
/* if DNSKEY, algorithm; if DS, digest type */
n3 = cfg_obj_asuint32(cfg_tuple_get(key, "n3"));
namestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
keyname = dns_fixedname_initname(&fkeyname);
keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
isc_buffer_constinit(&b, keynamestr, strlen(keynamestr));
isc_buffer_add(&b, strlen(keynamestr));
isc_buffer_constinit(&b, namestr, strlen(namestr));
isc_buffer_add(&b, strlen(namestr));
result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL);
if (result != ISC_R_SUCCESS) {
cfg_obj_log(key, logctx, ISC_LOG_WARNING, "bad key name: %s\n",
@ -3146,151 +3248,169 @@ check_trusted_key(const cfg_obj_t *key, bool managed,
result = ISC_R_FAILURE;
}
if (flags > 0xffff) {
cfg_obj_log(key, logctx, ISC_LOG_WARNING,
"flags too big: %u\n", flags);
result = ISC_R_FAILURE;
}
if (proto > 0xff) {
cfg_obj_log(key, logctx, ISC_LOG_WARNING,
"protocol too big: %u\n", proto);
result = ISC_R_FAILURE;
}
if (alg > 0xff) {
cfg_obj_log(key, logctx, ISC_LOG_WARNING,
"algorithm too big: %u\n", alg);
result = ISC_R_FAILURE;
}
if (managed) {
const char *initmethod;
initmethod = cfg_obj_asstring(cfg_tuple_get(key, "init"));
atstr = cfg_obj_asstring(cfg_tuple_get(key, "anchortype"));
if (strcasecmp(initmethod, "static-key") == 0) {
if (strcasecmp(atstr, "static-key") == 0) {
managed = false;
} else if (strcasecmp(initmethod, "initial-key") != 0) {
anchortype = STATIC_DNSKEY;
} else if (strcasecmp(atstr, "static-ds") == 0) {
managed = false;
anchortype = STATIC_DS;
} else if (strcasecmp(atstr, "initial-key") == 0) {
anchortype = INIT_DNSKEY;
} else if (strcasecmp(atstr, "initial-ds") == 0) {
anchortype = INIT_DS;
} else {
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
"managed key '%s': "
"key '%s': "
"invalid initialization method '%s'",
keynamestr, initmethod);
namestr, atstr);
result = ISC_R_FAILURE;
/*
* We can't interpret the trust anchor, so
* we skip all other checks.
*/
goto cleanup;
}
} else {
atstr = "trusted-key";
anchortype = TRUSTED;
}
switch(anchortype) {
case INIT_DNSKEY:
case STATIC_DNSKEY:
case TRUSTED:
if (n1 > 0xffff) {
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
"flags too big: %u", n1);
result = ISC_R_RANGE;
}
if (n1 & DNS_KEYFLAG_REVOKE) {
cfg_obj_log(key, logctx, ISC_LOG_WARNING,
"key flags revoke bit set");
}
if (n2 > 0xff) {
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
"protocol too big: %u", n2);
result = ISC_R_RANGE;
}
if (n3 > 0xff) {
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
"algorithm too big: %u\n", n3);
result = ISC_R_RANGE;
}
isc_buffer_init(&b, data, sizeof(data));
str = cfg_obj_asstring(cfg_tuple_get(key, "data"));
tresult = isc_base64_decodestring(str, &b);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
"%s", isc_result_totext(tresult));
result = ISC_R_FAILURE;
} else {
isc_buffer_usedregion(&b, &r);
if ((n3 == DST_ALG_RSASHA1) &&
r.length > 1 && r.base[0] == 1 && r.base[1] == 3)
{
cfg_obj_log(key, logctx, ISC_LOG_WARNING,
"%s '%s' has a weak exponent",
atstr, namestr);
}
}
if (result == ISC_R_SUCCESS &&
dns_name_equal(keyname, dns_rootname)) {
/*
* Flag any use of a root key, regardless of content.
*/
*flagsp |=
(managed ? ROOT_KSK_MANAGED : ROOT_KSK_STATIC);
if (n1 == 257 && n2 == 3 && n3 == 8 &&
(isc_buffer_usedlength(&b) ==
sizeof(root_ksk_2010)) &&
memcmp(data, root_ksk_2010,
sizeof(root_ksk_2010)) == 0)
{
*flagsp |= ROOT_KSK_2010;
}
if (n1 == 257 && n2 == 3 && n3 == 8 &&
(isc_buffer_usedlength(&b) ==
sizeof(root_ksk_2017)) &&
memcmp(data, root_ksk_2017,
sizeof(root_ksk_2017)) == 0)
{
*flagsp |= ROOT_KSK_2017;
}
}
break;
case INIT_DS:
case STATIC_DS:
if (n1 > 0xffff) {
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
"key tag too big: %u", n1);
result = ISC_R_RANGE;
}
if (n2 > 0xff) {
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
"algorithm too big: %u\n", n2);
result = ISC_R_RANGE;
}
if (n3 > 0xff) {
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
"digest type too big: %u", 32);
result = ISC_R_RANGE;
}
isc_buffer_init(&b, data, sizeof(data));
str = cfg_obj_asstring(cfg_tuple_get(key, "data"));
tresult = isc_hex_decodestring(str, &b);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
"%s", isc_result_totext(tresult));
result = ISC_R_FAILURE;
}
if (result == ISC_R_SUCCESS &&
dns_name_equal(keyname, dns_rootname)) {
/*
* Flag any use of a root key, regardless of content.
*/
*flagsp |=
(managed ? ROOT_KSK_MANAGED : ROOT_KSK_STATIC);
if (n1 == 20326 && n2 == 8 && n3 == 1 &&
(isc_buffer_usedlength(&b) ==
sizeof(root_ds_1_2017)) &&
memcmp(data, root_ds_1_2017,
sizeof(root_ds_1_2017)) == 0)
{
*flagsp |= ROOT_KSK_2017;
}
if (n1 == 20326 && n2 == 8 && n3 == 2 &&
(isc_buffer_usedlength(&b) ==
sizeof(root_ds_2_2017)) &&
memcmp(data, root_ds_2_2017,
sizeof(root_ds_2_2017)) == 0)
{
*flagsp |= ROOT_KSK_2017;
}
}
break;
}
isc_buffer_init(&b, keydata, sizeof(keydata));
keystr = cfg_obj_asstring(cfg_tuple_get(key, "key"));
tresult = isc_base64_decodestring(keystr, &b);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(key, logctx, ISC_LOG_ERROR,
"%s", isc_result_totext(tresult));
result = ISC_R_FAILURE;
} else {
isc_buffer_usedregion(&b, &r);
if ((alg == DST_ALG_RSASHA1) &&
r.length > 1 && r.base[0] == 1 && r.base[1] == 3)
{
cfg_obj_log(key, logctx, ISC_LOG_WARNING,
"%s key '%s' has a weak exponent",
managed ? "initializing" : "static",
keynamestr);
}
}
if (result == ISC_R_SUCCESS && dns_name_equal(keyname, dns_rootname)) {
static const unsigned char root_ksk_2010[] = {
0x03, 0x01, 0x00, 0x01, 0xa8, 0x00, 0x20, 0xa9,
0x55, 0x66, 0xba, 0x42, 0xe8, 0x86, 0xbb, 0x80,
0x4c, 0xda, 0x84, 0xe4, 0x7e, 0xf5, 0x6d, 0xbd,
0x7a, 0xec, 0x61, 0x26, 0x15, 0x55, 0x2c, 0xec,
0x90, 0x6d, 0x21, 0x16, 0xd0, 0xef, 0x20, 0x70,
0x28, 0xc5, 0x15, 0x54, 0x14, 0x4d, 0xfe, 0xaf,
0xe7, 0xc7, 0xcb, 0x8f, 0x00, 0x5d, 0xd1, 0x82,
0x34, 0x13, 0x3a, 0xc0, 0x71, 0x0a, 0x81, 0x18,
0x2c, 0xe1, 0xfd, 0x14, 0xad, 0x22, 0x83, 0xbc,
0x83, 0x43, 0x5f, 0x9d, 0xf2, 0xf6, 0x31, 0x32,
0x51, 0x93, 0x1a, 0x17, 0x6d, 0xf0, 0xda, 0x51,
0xe5, 0x4f, 0x42, 0xe6, 0x04, 0x86, 0x0d, 0xfb,
0x35, 0x95, 0x80, 0x25, 0x0f, 0x55, 0x9c, 0xc5,
0x43, 0xc4, 0xff, 0xd5, 0x1c, 0xbe, 0x3d, 0xe8,
0xcf, 0xd0, 0x67, 0x19, 0x23, 0x7f, 0x9f, 0xc4,
0x7e, 0xe7, 0x29, 0xda, 0x06, 0x83, 0x5f, 0xa4,
0x52, 0xe8, 0x25, 0xe9, 0xa1, 0x8e, 0xbc, 0x2e,
0xcb, 0xcf, 0x56, 0x34, 0x74, 0x65, 0x2c, 0x33,
0xcf, 0x56, 0xa9, 0x03, 0x3b, 0xcd, 0xf5, 0xd9,
0x73, 0x12, 0x17, 0x97, 0xec, 0x80, 0x89, 0x04,
0x1b, 0x6e, 0x03, 0xa1, 0xb7, 0x2d, 0x0a, 0x73,
0x5b, 0x98, 0x4e, 0x03, 0x68, 0x73, 0x09, 0x33,
0x23, 0x24, 0xf2, 0x7c, 0x2d, 0xba, 0x85, 0xe9,
0xdb, 0x15, 0xe8, 0x3a, 0x01, 0x43, 0x38, 0x2e,
0x97, 0x4b, 0x06, 0x21, 0xc1, 0x8e, 0x62, 0x5e,
0xce, 0xc9, 0x07, 0x57, 0x7d, 0x9e, 0x7b, 0xad,
0xe9, 0x52, 0x41, 0xa8, 0x1e, 0xbb, 0xe8, 0xa9,
0x01, 0xd4, 0xd3, 0x27, 0x6e, 0x40, 0xb1, 0x14,
0xc0, 0xa2, 0xe6, 0xfc, 0x38, 0xd1, 0x9c, 0x2e,
0x6a, 0xab, 0x02, 0x64, 0x4b, 0x28, 0x13, 0xf5,
0x75, 0xfc, 0x21, 0x60, 0x1e, 0x0d, 0xee, 0x49,
0xcd, 0x9e, 0xe9, 0x6a, 0x43, 0x10, 0x3e, 0x52,
0x4d, 0x62, 0x87, 0x3d
};
static const unsigned char root_ksk_2017[] = {
0x03, 0x01, 0x00, 0x01, 0xac, 0xff, 0xb4, 0x09,
0xbc, 0xc9, 0x39, 0xf8, 0x31, 0xf7, 0xa1, 0xe5,
0xec, 0x88, 0xf7, 0xa5, 0x92, 0x55, 0xec, 0x53,
0x04, 0x0b, 0xe4, 0x32, 0x02, 0x73, 0x90, 0xa4,
0xce, 0x89, 0x6d, 0x6f, 0x90, 0x86, 0xf3, 0xc5,
0xe1, 0x77, 0xfb, 0xfe, 0x11, 0x81, 0x63, 0xaa,
0xec, 0x7a, 0xf1, 0x46, 0x2c, 0x47, 0x94, 0x59,
0x44, 0xc4, 0xe2, 0xc0, 0x26, 0xbe, 0x5e, 0x98,
0xbb, 0xcd, 0xed, 0x25, 0x97, 0x82, 0x72, 0xe1,
0xe3, 0xe0, 0x79, 0xc5, 0x09, 0x4d, 0x57, 0x3f,
0x0e, 0x83, 0xc9, 0x2f, 0x02, 0xb3, 0x2d, 0x35,
0x13, 0xb1, 0x55, 0x0b, 0x82, 0x69, 0x29, 0xc8,
0x0d, 0xd0, 0xf9, 0x2c, 0xac, 0x96, 0x6d, 0x17,
0x76, 0x9f, 0xd5, 0x86, 0x7b, 0x64, 0x7c, 0x3f,
0x38, 0x02, 0x9a, 0xbd, 0xc4, 0x81, 0x52, 0xeb,
0x8f, 0x20, 0x71, 0x59, 0xec, 0xc5, 0xd2, 0x32,
0xc7, 0xc1, 0x53, 0x7c, 0x79, 0xf4, 0xb7, 0xac,
0x28, 0xff, 0x11, 0x68, 0x2f, 0x21, 0x68, 0x1b,
0xf6, 0xd6, 0xab, 0xa5, 0x55, 0x03, 0x2b, 0xf6,
0xf9, 0xf0, 0x36, 0xbe, 0xb2, 0xaa, 0xa5, 0xb3,
0x77, 0x8d, 0x6e, 0xeb, 0xfb, 0xa6, 0xbf, 0x9e,
0xa1, 0x91, 0xbe, 0x4a, 0xb0, 0xca, 0xea, 0x75,
0x9e, 0x2f, 0x77, 0x3a, 0x1f, 0x90, 0x29, 0xc7,
0x3e, 0xcb, 0x8d, 0x57, 0x35, 0xb9, 0x32, 0x1d,
0xb0, 0x85, 0xf1, 0xb8, 0xe2, 0xd8, 0x03, 0x8f,
0xe2, 0x94, 0x19, 0x92, 0x54, 0x8c, 0xee, 0x0d,
0x67, 0xdd, 0x45, 0x47, 0xe1, 0x1d, 0xd6, 0x3a,
0xf9, 0xc9, 0xfc, 0x1c, 0x54, 0x66, 0xfb, 0x68,
0x4c, 0xf0, 0x09, 0xd7, 0x19, 0x7c, 0x2c, 0xf7,
0x9e, 0x79, 0x2a, 0xb5, 0x01, 0xe6, 0xa8, 0xa1,
0xca, 0x51, 0x9a, 0xf2, 0xcb, 0x9b, 0x5f, 0x63,
0x67, 0xe9, 0x4c, 0x0d, 0x47, 0x50, 0x24, 0x51,
0x35, 0x7b, 0xe1, 0xb5
};
/*
* Flag any use of a root key, regardless of content.
*/
*keyflags |= (managed ? ROOT_KSK_MANAGED : ROOT_KSK_STATIC);
if (flags == 257 && proto == 3 && alg == 8 &&
isc_buffer_usedlength(&b) == sizeof(root_ksk_2010) &&
!memcmp(keydata, root_ksk_2010, sizeof(root_ksk_2010)))
{
*keyflags |= ROOT_KSK_2010;
}
if (flags == 257 && proto == 3 && alg == 8 &&
isc_buffer_usedlength(&b) == sizeof(root_ksk_2017) &&
!memcmp(keydata, root_ksk_2017, sizeof(root_ksk_2017)))
{
*keyflags |= ROOT_KSK_2017;
}
}
cleanup:
return (result);
}
@ -3322,13 +3442,17 @@ record_static_keys(isc_symtab_t *symtab, isc_mem_t *mctx,
continue;
}
init = cfg_tuple_get(obj, "init");
init = cfg_tuple_get(obj, "anchortype");
if (!cfg_obj_isvoid(init)) {
initmethod = cfg_obj_asstring(init);
if (strcasecmp(initmethod, "initial-key") == 0) {
/* initializing key, skip it */
continue;
}
if (strcasecmp(initmethod, "initial-ds") == 0) {
/* initializing key, skip it */
continue;
}
}
dns_name_format(name, namebuf, sizeof(namebuf));
@ -3346,7 +3470,7 @@ record_static_keys(isc_symtab_t *symtab, isc_mem_t *mctx,
if (autovalidation && dns_name_equal(name, dns_rootname)) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"static key for root zone "
"static trust anchor for root zone "
"cannot be used with "
"'dnssec-validation auto'.");
ret = ISC_R_FAILURE;
@ -3378,9 +3502,10 @@ check_initializing_keys(isc_symtab_t *symtab, const cfg_obj_t *keylist,
const char *str;
isc_symvalue_t symvalue;
init = cfg_tuple_get(obj, "init");
init = cfg_tuple_get(obj, "anchortype");
if (cfg_obj_isvoid(init) ||
strcasecmp(cfg_obj_asstring(init), "static-key") == 0)
strcasecmp(cfg_obj_asstring(init), "static-key") == 0 ||
strcasecmp(cfg_obj_asstring(init), "static-ds") == 0)
{
/* static key, skip it */
continue;
@ -3414,6 +3539,118 @@ check_initializing_keys(isc_symtab_t *symtab, const cfg_obj_t *keylist,
return (ret);
}
static isc_result_t
record_ds_keys(isc_symtab_t *symtab, isc_mem_t *mctx, const cfg_obj_t *keylist)
{
isc_result_t result, ret = ISC_R_SUCCESS;
const cfg_listelt_t *elt;
dns_fixedname_t fixed;
dns_name_t *name;
char namebuf[DNS_NAME_FORMATSIZE], *p = NULL;
name = dns_fixedname_initname(&fixed);
for (elt = cfg_list_first(keylist);
elt != NULL;
elt = cfg_list_next(elt))
{
const char *initmethod;
const cfg_obj_t *init = NULL;
const cfg_obj_t *obj = cfg_listelt_value(elt);
const char *str = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
isc_symvalue_t symvalue;
result = dns_name_fromstring(name, str, 0, NULL);
if (result != ISC_R_SUCCESS) {
continue;
}
init = cfg_tuple_get(obj, "anchortype");
if (!cfg_obj_isvoid(init)) {
initmethod = cfg_obj_asstring(init);
if (strcasecmp(initmethod, "initial-key") == 0 ||
strcasecmp(initmethod, "static-key") == 0)
{
/* Key-style key, skip it */
continue;
}
}
dns_name_format(name, namebuf, sizeof(namebuf));
symvalue.as_cpointer = obj;
p = isc_mem_strdup(mctx, namebuf);
result = isc_symtab_define(symtab, p, 1, symvalue,
isc_symexists_reject);
if (result == ISC_R_EXISTS) {
isc_mem_free(mctx, p);
} else if (result != ISC_R_SUCCESS) {
isc_mem_free(mctx, p);
ret = result;
continue;
}
}
return (ret);
}
static isc_result_t
check_non_ds_keys(isc_symtab_t *symtab, const cfg_obj_t *keylist,
isc_log_t *logctx)
{
isc_result_t result, ret = ISC_R_SUCCESS;
const cfg_listelt_t *elt;
dns_fixedname_t fixed;
dns_name_t *name;
char namebuf[DNS_NAME_FORMATSIZE];
name = dns_fixedname_initname(&fixed);
for (elt = cfg_list_first(keylist);
elt != NULL;
elt = cfg_list_next(elt))
{
const cfg_obj_t *obj = cfg_listelt_value(elt);
const cfg_obj_t *init = NULL;
const char *str;
isc_symvalue_t symvalue;
init = cfg_tuple_get(obj, "anchortype");
if (cfg_obj_isvoid(init) ||
strcasecmp(cfg_obj_asstring(init), "static-ds") == 0 ||
strcasecmp(cfg_obj_asstring(init), "initial-ds") == 0)
{
/* DS-style entry, skip it */
continue;
}
str = cfg_obj_asstring(cfg_tuple_get(obj, "name"));
result = dns_name_fromstring(name, str, 0, NULL);
if (result != ISC_R_SUCCESS) {
continue;
}
dns_name_format(name, namebuf, sizeof(namebuf));
result = isc_symtab_lookup(symtab, namebuf, 1, &symvalue);
if (result == ISC_R_SUCCESS) {
const char *file = cfg_obj_file(symvalue.as_cpointer);
unsigned int line = cfg_obj_line(symvalue.as_cpointer);
if (file == NULL) {
file = "<unknown file>";
}
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"ds-style and key-style keys "
"cannot be used for the "
"same domain. "
"ds-style defined at "
"%s:%u", file, line);
ret = ISC_R_FAILURE;
}
}
return (ret);
}
/*
* Check for conflicts between static and initialiizing keys.
*/
@ -3425,27 +3662,38 @@ check_ta_conflicts(const cfg_obj_t *global_dkeys, const cfg_obj_t *view_dkeys,
isc_result_t result, tresult;
const cfg_listelt_t *elt = NULL;
const cfg_obj_t *keylist = NULL;
isc_symtab_t *symtab = NULL;
isc_symtab_t *statictab = NULL, *dstab = NULL;
result = isc_symtab_create(mctx, 100, freekey, mctx, false, &symtab);
result = isc_symtab_create(mctx, 100, freekey, mctx, false, &statictab);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
result = isc_symtab_create(mctx, 100, freekey, mctx, false, &dstab);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
/*
* First we record all the static keys (i.e., old-style
* trusted-keys and dnssec-keys configured with "static-key")
* trusted-keys and dnssec-keys configured with "static-key"),
* and all the DS-style trust anchors.
*/
for (elt = cfg_list_first(global_dkeys);
elt != NULL;
elt = cfg_list_next(elt))
{
keylist = cfg_listelt_value(elt);
tresult = record_static_keys(symtab, mctx, keylist,
tresult = record_static_keys(statictab, mctx, keylist,
logctx, autovalidation);
if (result == ISC_R_SUCCESS) {
result = tresult;
}
tresult = record_ds_keys(dstab, mctx, keylist);
if (result == ISC_R_SUCCESS) {
result = tresult;
}
}
for (elt = cfg_list_first(view_dkeys);
@ -3453,11 +3701,16 @@ check_ta_conflicts(const cfg_obj_t *global_dkeys, const cfg_obj_t *view_dkeys,
elt = cfg_list_next(elt))
{
keylist = cfg_listelt_value(elt);
tresult = record_static_keys(symtab, mctx, keylist,
tresult = record_static_keys(statictab, mctx, keylist,
logctx, autovalidation);
if (result == ISC_R_SUCCESS) {
result = tresult;
}
tresult = record_ds_keys(dstab, mctx, keylist);
if (result == ISC_R_SUCCESS) {
result = tresult;
}
}
for (elt = cfg_list_first(global_tkeys);
@ -3465,7 +3718,7 @@ check_ta_conflicts(const cfg_obj_t *global_dkeys, const cfg_obj_t *view_dkeys,
elt = cfg_list_next(elt))
{
keylist = cfg_listelt_value(elt);
tresult = record_static_keys(symtab, mctx, keylist,
tresult = record_static_keys(statictab, mctx, keylist,
logctx, autovalidation);
if (result == ISC_R_SUCCESS) {
result = tresult;
@ -3477,24 +3730,29 @@ check_ta_conflicts(const cfg_obj_t *global_dkeys, const cfg_obj_t *view_dkeys,
elt = cfg_list_next(elt))
{
keylist = cfg_listelt_value(elt);
tresult = record_static_keys(symtab, mctx, keylist,
tresult = record_static_keys(statictab, mctx, keylist,
logctx, autovalidation);
if (result == ISC_R_SUCCESS) {
result = tresult;
}
}
/*
* Next, ensure that there's no conflict between the
* static keys and the dnssec-keys configured with "initial-key"
* static keys and the dnssec-keys configured with "initial-key",
* or between DS-style and DNSKEY-style dnssec-keys.
*/
for (elt = cfg_list_first(global_dkeys);
elt != NULL;
elt = cfg_list_next(elt))
{
keylist = cfg_listelt_value(elt);
tresult = check_initializing_keys(symtab, keylist, logctx);
tresult = check_initializing_keys(statictab, keylist, logctx);
if (result == ISC_R_SUCCESS) {
result = tresult;
}
tresult = check_non_ds_keys(dstab, keylist, logctx);
if (result == ISC_R_SUCCESS) {
result = tresult;
}
@ -3505,15 +3763,23 @@ check_ta_conflicts(const cfg_obj_t *global_dkeys, const cfg_obj_t *view_dkeys,
elt = cfg_list_next(elt))
{
keylist = cfg_listelt_value(elt);
tresult = check_initializing_keys(symtab, keylist, logctx);
tresult = check_initializing_keys(statictab, keylist, logctx);
if (result == ISC_R_SUCCESS) {
result = tresult;
}
tresult = check_non_ds_keys(dstab, keylist, logctx);
if (result == ISC_R_SUCCESS) {
result = tresult;
}
}
cleanup:
if (symtab != NULL) {
isc_symtab_destroy(&symtab);
if (statictab != NULL) {
isc_symtab_destroy(&statictab);
}
if (dstab != NULL) {
isc_symtab_destroy(&dstab);
}
return (result);
}
@ -3898,8 +4164,7 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
element2 = cfg_list_next(element2))
{
obj = cfg_listelt_value(element2);
tresult = check_trusted_key(obj,
false,
tresult = check_trust_anchor(obj, false,
&flags,
logctx);
if (tresult != ISC_R_SUCCESS) {
@ -3914,7 +4179,8 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
"trusted-keys entry for the root "
"zone WILL FAIL after key "
"rollover - use dnssec-keys "
"with initial-key instead.");
"with initial-key "
"or initial-ds instead.");
}
tflags |= flags;
@ -3958,8 +4224,7 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
element2 = cfg_list_next(element2))
{
obj = cfg_listelt_value(element2);
tresult = check_trusted_key(obj,
true,
tresult = check_trust_anchor(obj, true,
&flags,
logctx);
if (tresult != ISC_R_SUCCESS) {
@ -3971,10 +4236,11 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
if ((flags & ROOT_KSK_STATIC) != 0) {
cfg_obj_log(check_keys[i], logctx,
ISC_LOG_WARNING,
"static-key entry for the root "
"static entry for the root "
"zone WILL FAIL after key "
"rollover - use dnssec-keys "
"with initial-key instead.");
"with initial-key "
"or initial-ds instead.");
}
if ((flags & ROOT_KSK_2010) != 0 &&
@ -4001,7 +4267,7 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
if ((dflags & ROOT_KSK_ANY) == ROOT_KSK_ANY) {
keys = (view_dkeys != NULL) ? view_dkeys : global_dkeys;
cfg_obj_log(keys, logctx, ISC_LOG_WARNING,
"both initial-key and static-key entries for the "
"both initial and static entries for the "
"root zone are present");
}

View file

@ -69,6 +69,13 @@
#define RESOLVER_NTASKS 31
#endif /* TUNE_LARGE */
#define CHECK(r) \
do { \
result = (r); \
if (result != ISC_R_SUCCESS) \
goto cleanup; \
} while (0)
/*%
* DNS client object
*/
@ -1482,12 +1489,19 @@ dns_client_destroyrestrans(dns_clientrestrans_t **transp) {
isc_result_t
dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass,
const dns_name_t *keyname, isc_buffer_t *keydatabuf)
dns_rdatatype_t rdtype, const dns_name_t *keyname,
isc_buffer_t *databuf)
{
isc_result_t result;
dns_view_t *view = NULL;
dst_key_t *dstkey = NULL;
dns_keytable_t *secroots = NULL;
dns_name_t *name = NULL;
char dsbuf[DNS_DS_BUFFERSIZE];
dns_rdata_ds_t ds;
dns_decompress_t dctx;
dns_rdata_t rdata;
isc_buffer_t b;
REQUIRE(DNS_CLIENT_VALID(client));
@ -1495,27 +1509,49 @@ dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass,
result = dns_viewlist_find(&client->viewlist, DNS_CLIENTVIEW_NAME,
rdclass, &view);
UNLOCK(&client->lock);
if (result != ISC_R_SUCCESS)
goto cleanup;
CHECK(result);
result = dns_view_getsecroots(view, &secroots);
if (result != ISC_R_SUCCESS)
goto cleanup;
CHECK(dns_view_getsecroots(view, &secroots));
result = dst_key_fromdns(keyname, rdclass, keydatabuf, client->mctx,
&dstkey);
if (result != ISC_R_SUCCESS)
goto cleanup;
DE_CONST(keyname, name);
result = dns_keytable_add(secroots, false, false, &dstkey);
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:
result = ISC_R_NOTIMPLEMENTED;
}
cleanup:
if (dstkey != NULL)
if (dstkey != NULL) {
dst_key_free(&dstkey);
if (view != NULL)
}
if (view != NULL) {
dns_view_detach(&view);
if (secroots != NULL)
}
if (secroots != NULL) {
dns_keytable_detach(&secroots);
}
return (result);
}

View file

@ -2270,3 +2270,53 @@ dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys,
failure:
return (result);
}
isc_result_t
dns_dnssec_matchdskey(dns_name_t *name, dns_rdata_t *dsrdata,
dns_rdataset_t *keyset, dns_rdata_t *keyrdata)
{
isc_result_t result;
unsigned char buf[DNS_DS_BUFFERSIZE];
dns_keytag_t keytag;
dns_rdata_dnskey_t key;
dns_rdata_ds_t ds;
isc_region_t r;
result = dns_rdata_tostruct(dsrdata, &ds, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
for (result = dns_rdataset_first(keyset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(keyset))
{
dns_rdata_t newdsrdata = DNS_RDATA_INIT;
dns_rdata_reset(keyrdata);
dns_rdataset_current(keyset, keyrdata);
result = dns_rdata_tostruct(keyrdata, &key, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
dns_rdata_toregion(keyrdata, &r);
keytag = dst_region_computeid(&r);
if (ds.key_tag != keytag || ds.algorithm != key.algorithm) {
continue;
}
result = dns_ds_buildrdata(name, keyrdata, ds.digest_type,
buf, &newdsrdata);
if (result != ISC_R_SUCCESS) {
continue;
}
if (dns_rdata_compare(dsrdata, &newdsrdata) == 0) {
break;
}
}
if (result == ISC_R_NOMORE) {
result = ISC_R_NOTFOUND;
}
return (result);
}

View file

@ -385,11 +385,13 @@ dns_client_freeresanswer(dns_client_t *client, dns_namelist_t *namelist);
isc_result_t
dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass,
const dns_name_t *keyname, isc_buffer_t *keydatabuf);
dns_rdatatype_t rdtype, const dns_name_t *keyname,
isc_buffer_t *keydatabuf);
/*%<
* Add a DNSSEC trusted key for the 'rdclass' class. A view for the 'rdclass'
* class must be created beforehand. 'keyname' is the DNS name of the key,
* and 'keydatabuf' stores the resource data of the key.
* class must be created beforehand. 'rdtype' is the type of the RR data
* for the key, either DNSKEY or DS. 'keyname' is the DNS name of the key,
* and 'keydatabuf' stores the RR data.
*
* Requires:
*

View file

@ -360,6 +360,18 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
* Update the CDS and CDNSKEY RRsets, adding and removing keys as needed.
*/
isc_result_t
dns_dnssec_matchdskey(dns_name_t *name, dns_rdata_t *dsrdata,
dns_rdataset_t *keyset, dns_rdata_t *keyrdata);
/*%<
* Given a DS rdata and a DNSKEY RRset, find the DNSKEY rdata that matches
* the DS, and place it in 'keyrdata'.
*
* Returns:
*\li ISC_R_SUCCESS
*\li ISC_R_NOTFOUND
*\li Other values indicate error
*/
ISC_LANG_ENDDECLS
#endif /* DNS_DNSSEC_H */

View file

@ -42,6 +42,7 @@
#include <isc/rwlock.h>
#include <isc/stdtime.h>
#include <dns/rdatastruct.h>
#include <dns/types.h>
#include <dst/dst.h>
@ -105,10 +106,14 @@ dns_keytable_detach(dns_keytable_t **keytablep);
*/
isc_result_t
dns_keytable_add(dns_keytable_t *keytable, bool managed,
bool initial, dst_key_t **keyp);
dns_keytable_add(dns_keytable_t *keytable,
bool managed, bool initial,
dns_name_t *name, dst_key_t **keyp, dns_rdata_ds_t *ds);
/*%<
* Add '*keyp' to 'keytable' (using the name in '*keyp').
* 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'.
*
* The value of keynode->managed is set to 'managed', and the
* value of keynode->initial is set to 'initial'. (Note: 'initial'
* should only be used when adding managed-keys from configuration.
@ -119,6 +124,12 @@ dns_keytable_add(dns_keytable_t *keytable, bool managed,
* 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.
*
@ -407,6 +418,19 @@ dns_keynode_key(dns_keynode_t *keynode);
* Get the DST key associated with keynode.
*/
dns_rdataset_t *
dns_keynode_dsset(dns_keynode_t *keynode);
/*%<
* Return a pointer to the DS RRset associated with 'keynode'.
*
* Returns:
*\li ISC_R_SUCCESS
*\li ISC_R_FAILURE if the keynode does not contain a DS trust anchor.
*
* Requires:
*\li 'keynode' is valid.
*/
bool
dns_keynode_managed(dns_keynode_t *keynode);
/*%<
@ -453,7 +477,8 @@ dns_keynode_detachall(isc_mem_t *mctx, dns_keynode_t **target);
isc_result_t
dns_keytable_forall(dns_keytable_t *keytable,
void (*func)(dns_keytable_t *, dns_keynode_t *, void *),
void (*func)(dns_keytable_t *, dns_keynode_t *,
dns_name_t *, void *),
void *arg);
ISC_LANG_ENDDECLS

View file

@ -24,6 +24,10 @@
#include <dns/keytable.h>
#include <dns/fixedname.h>
#include <dns/rbt.h>
#include <dns/rdata.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
#include <dns/rdatastruct.h>
#include <dns/result.h>
#define KEYTABLE_MAGIC ISC_MAGIC('K', 'T', 'b', 'l')
@ -46,10 +50,12 @@ struct dns_keytable {
struct dns_keynode {
unsigned int magic;
isc_refcount_t refcount;
dst_key_t * key;
dst_key_t *key;
dns_rdatalist_t *dslist;
dns_rdataset_t dsset;
bool managed;
bool initial;
struct dns_keynode * next;
struct dns_keynode *next;
};
static void
@ -135,12 +141,32 @@ 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 either a null key node or a key node for the exact same
* key as the one supplied in "keyp" and, if found, update it accordingly.
* 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(dst_key_t **keyp, dns_rbtnode_t *node, bool initial) {
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);
@ -149,13 +175,17 @@ update_keynode(dst_key_t **keyp, dns_rbtnode_t *node, bool initial) {
for (knode = node->data; knode != NULL; knode = knode->next) {
if (knode->key == NULL) {
/*
* Null key node found. Attach the supplied key to it,
* making it a non-null key node and transferring key
* 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;
return (ISC_R_SUCCESS);
} else if (dst_key_compare(knode->key, *keyp)) {
/*
* Key node found for the supplied key. Free the
@ -163,11 +193,15 @@ update_keynode(dst_key_t **keyp, dns_rbtnode_t *node, bool initial) {
* node's flags if necessary.
*/
dst_key_free(keyp);
if (!initial) {
dns_keynode_trust(knode);
}
return (ISC_R_SUCCESS);
} else {
continue;
}
if (!initial) {
dns_keynode_trust(knode);
}
return (ISC_R_SUCCESS);
}
return (ISC_R_NOTFOUND);
@ -179,9 +213,9 @@ update_keynode(dst_key_t **keyp, dns_rbtnode_t *node, bool initial) {
* one attached to "node" in "keytable".
*/
static isc_result_t
prepend_keynode(dst_key_t **keyp, dns_rbtnode_t *node,
dns_keytable_t *keytable, bool managed,
bool initial)
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;
isc_result_t result;
@ -196,15 +230,60 @@ prepend_keynode(dst_key_t **keyp, dns_rbtnode_t *node,
}
/*
* If a key was supplied, transfer its ownership to the keytable.
* 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 (keyp) {
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 (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;
@ -219,7 +298,7 @@ prepend_keynode(dst_key_t **keyp, dns_rbtnode_t *node,
*/
static isc_result_t
insert(dns_keytable_t *keytable, bool managed, bool initial,
const dns_name_t *keyname, dst_key_t **keyp)
const dns_name_t *keyname, dst_key_t **keyp, dns_rdata_ds_t *ds)
{
dns_rbtnode_t *node = NULL;
isc_result_t result;
@ -232,17 +311,17 @@ insert(dns_keytable_t *keytable, bool managed, bool initial,
if (result == ISC_R_SUCCESS) {
/*
* There was no node for "keyname" in "keytable" yet, so one
* was created. Create a new key node for the supplied key (or
* a null key node if "keyp" is NULL) and attach it to the
* created node.
* 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.
*/
result = prepend_keynode(keyp, node, keytable, managed,
initial);
result = prepend_keynode(keyp, ds, node, keytable,
managed, initial);
} else if (result == ISC_R_EXISTS) {
/*
* A node already exists for "keyname" in "keytable".
*/
if (keyp == NULL) {
if (keyp == NULL && ds == NULL) {
/*
* We were told to add a null key at "keyname", which
* means there is nothing left to do as there is either
@ -252,7 +331,7 @@ insert(dns_keytable_t *keytable, bool managed, bool initial,
* "keyname" is already marked as secure.
*/
result = ISC_R_SUCCESS;
} else {
} else if (keyp != NULL) {
/*
* We were told to add the key supplied in "keyp" at
* "keyname". Try to find an already existing key node
@ -260,7 +339,7 @@ insert(dns_keytable_t *keytable, bool managed, bool initial,
* node or a key node for the exact same key) and, if
* found, update it accordingly.
*/
result = update_keynode(keyp, node, initial);
result = update_keynode(keytable, node, keyp, initial);
if (result == ISC_R_NOTFOUND) {
/*
* The node for "keyname" only contains key
@ -268,9 +347,13 @@ insert(dns_keytable_t *keytable, bool managed, bool initial,
* one. Create a new key node for the supplied
* key and prepend it before the others.
*/
result = prepend_keynode(keyp, node, keytable,
result = prepend_keynode(keyp, NULL,
node, keytable,
managed, initial);
}
} else if (ds != NULL) {
result = prepend_keynode(NULL, ds, node, keytable,
managed, initial);
}
}
@ -280,17 +363,19 @@ insert(dns_keytable_t *keytable, bool managed, bool initial,
}
isc_result_t
dns_keytable_add(dns_keytable_t *keytable, bool managed,
bool initial, dst_key_t **keyp)
dns_keytable_add(dns_keytable_t *keytable,
bool managed, bool initial,
dns_name_t *name, dst_key_t **keyp, dns_rdata_ds_t *ds)
{
REQUIRE(keyp != NULL && *keyp != NULL);
REQUIRE(keyp == NULL || *keyp != NULL);
REQUIRE(keyp != NULL || ds != NULL);
REQUIRE(!initial || managed);
return (insert(keytable, managed, initial, dst_key_name(*keyp), keyp));
return (insert(keytable, managed, initial, name, keyp, ds));
}
isc_result_t
dns_keytable_marksecure(dns_keytable_t *keytable, const dns_name_t *name) {
return (insert(keytable, true, false, name, NULL));
return (insert(keytable, true, false, name, NULL, NULL));
}
isc_result_t
@ -420,8 +505,9 @@ dns_keytable_nextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
REQUIRE(VALID_KEYNODE(keynode));
REQUIRE(nextnodep != NULL && *nextnodep == NULL);
if (keynode->next == NULL)
if (keynode->next == NULL) {
return (ISC_R_NOTFOUND);
}
dns_keynode_attach(keynode->next, nextnodep);
isc_refcount_increment(&keytable->active_nodes);
@ -459,25 +545,29 @@ dns_keytable_findkeynode(dns_keytable_t *keytable, const dns_name_t *name,
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))
if (algorithm == dst_key_alg(knode->key) &&
tag == dst_key_id(knode->key))
{
break;
}
}
if (knode != NULL) {
isc_refcount_increment0(&keytable->active_nodes);
dns_keynode_attach(knode, keynodep);
} else
} else {
result = DNS_R_PARTIALMATCH;
} else if (result == DNS_R_PARTIALMATCH)
}
} else if (result == DNS_R_PARTIALMATCH) {
result = ISC_R_NOTFOUND;
}
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
@ -507,14 +597,17 @@ dns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
}
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) {
isc_refcount_increment(&keytable->active_nodes);
result = ISC_R_SUCCESS;
dns_keynode_attach(knode, nextnodep);
} else
} else {
result = ISC_R_NOTFOUND;
}
return (result);
}
@ -539,8 +632,9 @@ dns_keytable_finddeepestmatch(dns_keytable_t *keytable, const dns_name_t *name,
data = NULL;
result = dns_rbt_findname(keytable->table, name, 0, foundname, &data);
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
result = ISC_R_SUCCESS;
}
RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
@ -616,8 +710,9 @@ putstr(isc_buffer_t **b, const char *str) {
isc_result_t result;
result = isc_buffer_reserve(b, strlen(str));
if (result != ISC_R_SUCCESS)
if (result != ISC_R_SUCCESS) {
return (result);
}
isc_buffer_putstr(*b, str);
return (ISC_R_SUCCESS);
@ -639,9 +734,9 @@ dns_keytable_dump(dns_keytable_t *keytable, FILE *fp) {
if (isc_buffer_usedlength(text) != 0) {
(void) putstr(&text, "\n");
} else if (result == ISC_R_SUCCESS)
} else if (result == ISC_R_SUCCESS) {
(void) putstr(&text, "none");
else {
} else {
(void) putstr(&text, "could not dump key table: ");
(void) putstr(&text, isc_result_totext(result));
}
@ -653,44 +748,112 @@ dns_keytable_dump(dns_keytable_t *keytable, FILE *fp) {
return (result);
}
static isc_result_t
keynode_dslist_totext(dns_name_t *name, dns_keynode_t *keynode,
isc_buffer_t **text)
{
isc_result_t result;
char namebuf[DNS_NAME_FORMATSIZE];
char obuf[DNS_NAME_FORMATSIZE + 200];
dns_rdataset_t *dsset = NULL;
dns_name_format(name, namebuf, sizeof(namebuf));
dsset = dns_keynode_dsset(keynode);
for (result = dns_rdataset_first(dsset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(dsset))
{
char algbuf[DNS_SECALG_FORMATSIZE];
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_ds_t ds;
dns_rdataset_current(dsset, &rdata);
result = dns_rdata_tostruct(&rdata, &ds, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
dns_secalg_format(ds.algorithm, algbuf, sizeof(algbuf));
snprintf(obuf, sizeof(obuf), "%s/%s/%d ; %s%s (DS)\n",
namebuf, algbuf, ds.key_tag,
keynode->initial ? "initializing " : "",
keynode->managed ? "managed" : "static");
result = putstr(text, obuf);
if (result != ISC_R_SUCCESS) {
return (result);
}
}
return (ISC_R_SUCCESS);
}
isc_result_t
dns_keytable_totext(dns_keytable_t *keytable, isc_buffer_t **text) {
isc_result_t result;
dns_keynode_t *knode;
dns_rbtnode_t *node;
dns_rbtnodechain_t chain;
dns_name_t *foundname, *origin, *fullname;
dns_fixedname_t fixedfoundname, fixedorigin, fixedfullname;
REQUIRE(VALID_KEYTABLE(keytable));
REQUIRE(text != NULL && *text != NULL);
origin = dns_fixedname_initname(&fixedorigin);
fullname = dns_fixedname_initname(&fixedfullname);
foundname = dns_fixedname_initname(&fixedfoundname);
RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
dns_rbtnodechain_init(&chain);
result = dns_rbtnodechain_first(&chain, keytable->table, NULL, NULL);
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
if (result == ISC_R_NOTFOUND)
if (result == ISC_R_NOTFOUND) {
result = ISC_R_SUCCESS;
}
goto cleanup;
}
for (;;) {
char pbuf[DST_KEY_FORMATSIZE];
dns_rbtnodechain_current(&chain, NULL, NULL, &node);
for (knode = node->data; knode != NULL; knode = knode->next) {
dns_rbtnodechain_current(&chain, foundname, origin, &node);
knode = node->data;
if (knode != NULL && knode->dslist != NULL) {
result = dns_name_concatenate(foundname, origin,
fullname, NULL);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}
result = keynode_dslist_totext(fullname, knode, text);
goto cleanup;
}
for (; knode != NULL; knode = knode->next) {
char obuf[DNS_NAME_FORMATSIZE + 200];
if (knode->key == NULL)
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)
if (result != ISC_R_SUCCESS) {
break;
}
}
result = dns_rbtnodechain_next(&chain, NULL, NULL);
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
if (result == ISC_R_NOMORE)
if (result == ISC_R_NOMORE) {
result = ISC_R_SUCCESS;
}
break;
}
}
@ -703,32 +866,45 @@ dns_keytable_totext(dns_keytable_t *keytable, isc_buffer_t **text) {
isc_result_t
dns_keytable_forall(dns_keytable_t *keytable,
void (*func)(dns_keytable_t *, dns_keynode_t *, void *),
void (*func)(dns_keytable_t *, dns_keynode_t *,
dns_name_t *, void *),
void *arg)
{
isc_result_t result;
dns_rbtnode_t *node;
dns_rbtnodechain_t chain;
dns_fixedname_t fixedfoundname, fixedorigin, fixedfullname;
dns_name_t *foundname, *origin, *fullname;
REQUIRE(VALID_KEYTABLE(keytable));
origin = dns_fixedname_initname(&fixedorigin);
fullname = dns_fixedname_initname(&fixedfullname);
foundname = dns_fixedname_initname(&fixedfoundname);
RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
dns_rbtnodechain_init(&chain);
result = dns_rbtnodechain_first(&chain, keytable->table, NULL, NULL);
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
if (result == ISC_R_NOTFOUND)
if (result == ISC_R_NOTFOUND) {
result = ISC_R_SUCCESS;
}
goto cleanup;
}
isc_refcount_increment0(&keytable->active_nodes);
for (;;) {
dns_rbtnodechain_current(&chain, NULL, NULL, &node);
if (node->data != NULL)
(*func)(keytable, node->data, arg);
dns_rbtnodechain_current(&chain, foundname, origin, &node);
if (node->data != NULL) {
result = dns_name_concatenate(foundname, origin,
fullname, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
(*func)(keytable, node->data, fullname, arg);
}
result = dns_rbtnodechain_next(&chain, NULL, NULL);
if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
if (result == ISC_R_NOMORE)
if (result == ISC_R_NOMORE) {
result = ISC_R_SUCCESS;
}
break;
}
}
@ -747,6 +923,17 @@ dns_keynode_key(dns_keynode_t *keynode) {
return (keynode->key);
}
dns_rdataset_t *
dns_keynode_dsset(dns_keynode_t *keynode) {
REQUIRE(VALID_KEYNODE(keynode));
if (keynode->dslist != NULL) {
return (&keynode->dsset);
}
return (NULL);
}
bool
dns_keynode_managed(dns_keynode_t *keynode) {
REQUIRE(VALID_KEYNODE(keynode));
@ -780,6 +967,8 @@ dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target) {
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);
@ -796,17 +985,23 @@ dns_keynode_attach(dns_keynode_t *source, dns_keynode_t **target) {
}
void
dns_keynode_detach(isc_mem_t *mctx, dns_keynode_t **keynode) {
REQUIRE(keynode != NULL && VALID_KEYNODE(*keynode));
dns_keynode_t *node = *keynode;
*keynode = NULL;
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(&node->refcount) == 1) {
isc_refcount_destroy(&node->refcount);
if (node->key != NULL) {
dst_key_free(&node->key);
if (isc_refcount_decrement(&knode->refcount) == 1) {
isc_refcount_destroy(&knode->refcount);
if (knode->key != NULL) {
dst_key_free(&knode->key);
}
isc_mem_put(mctx, node, sizeof(dns_keynode_t));
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));
}
}

View file

@ -155,12 +155,14 @@ create_tables() {
/* Add a normal key */
create_key(257, 3, 5, "example.com", keystr1, &key);
assert_int_equal(dns_keytable_add(keytable, false, false, &key),
assert_int_equal(dns_keytable_add(keytable, false, false,
dst_key_name(key), &key, NULL),
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, &key),
assert_int_equal(dns_keytable_add(keytable, true, true,
dst_key_name(key), &key, NULL),
ISC_R_SUCCESS);
/* Add a null key */
@ -216,7 +218,8 @@ add_test(void **state) {
* nextkeynode() should still return NOTFOUND.
*/
create_key(257, 3, 5, "example.com", keystr1, &key);
assert_int_equal(dns_keytable_add(keytable, false, false, &key),
assert_int_equal(dns_keytable_add(keytable, false, false,
dst_key_name(key), &key, NULL),
ISC_R_SUCCESS);
assert_int_equal(dns_keytable_nextkeynode(keytable, keynode,
&next_keynode),
@ -225,7 +228,8 @@ add_test(void **state) {
/* 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, &key),
assert_int_equal(dns_keytable_add(keytable, false, false,
dst_key_name(key), &key, NULL),
ISC_R_SUCCESS);
assert_int_equal(dns_keytable_find(keytable, str2name("example.com"),
&keynode),
@ -259,7 +263,8 @@ add_test(void **state) {
* ISC_R_NOTFOUND and that the added key is an initializing key.
*/
create_key(257, 3, 5, "managed.com", keystr2, &key);
assert_int_equal(dns_keytable_add(keytable, true, true, &key),
assert_int_equal(dns_keytable_add(keytable, true, true,
dst_key_name(key), &key, NULL),
ISC_R_SUCCESS);
assert_int_equal(dns_keytable_find(keytable, str2name("managed.com"),
&keynode),
@ -278,7 +283,8 @@ add_test(void **state) {
* 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, &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("managed.com"),
&keynode),
@ -302,7 +308,8 @@ add_test(void **state) {
* that the added key is an initializing key.
*/
create_key(257, 3, 5, "two.com", keystr1, &key);
assert_int_equal(dns_keytable_add(keytable, true, true, &key),
assert_int_equal(dns_keytable_add(keytable, true, true,
dst_key_name(key), &key, NULL),
ISC_R_SUCCESS);
assert_int_equal(dns_keytable_find(keytable, str2name("two.com"),
&keynode),
@ -319,7 +326,8 @@ add_test(void **state) {
* ISC_R_NOTFOUND and that the added key is not an initializing key.
*/
create_key(257, 3, 5, "two.com", keystr2, &key);
assert_int_equal(dns_keytable_add(keytable, true, false, &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),
@ -337,7 +345,8 @@ add_test(void **state) {
* 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, &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),
@ -363,7 +372,8 @@ add_test(void **state) {
&null_keynode),
ISC_R_SUCCESS);
create_key(257, 3, 5, "null.example", keystr2, &key);
assert_int_equal(dns_keytable_add(keytable, false, false, &key),
assert_int_equal(dns_keytable_add(keytable, false, false,
dst_key_name(key), &key, NULL),
ISC_R_SUCCESS);
assert_int_equal(dns_keytable_find(keytable, str2name("null.example"),
&keynode),
@ -663,7 +673,8 @@ nta_test(void **state) {
assert_int_equal(result, ISC_R_SUCCESS);
create_key(257, 3, 5, "example", keystr1, &key);
result = dns_keytable_add(keytable, false, false, &key);
result = dns_keytable_add(keytable, false, false,
dst_key_name(key), &key, NULL),
assert_int_equal(result, ISC_R_SUCCESS);
isc_stdtime_get(&now);

View file

@ -1684,49 +1684,6 @@ check_signer(dns_validator_t *val, dns_rdata_t *keyrdata,
return (result);
}
/*%
* Find the DNSKEY that corresponds to the DS.
*/
static isc_result_t
dnskey_for_ds(dns_validator_t *val, dns_rdataset_t *rdataset,
dns_rdata_t *dsrdata, dns_rdata_ds_t *ds, dns_rdata_t *keyrdata)
{
dns_keytag_t keytag;
dns_rdata_dnskey_t key;
isc_result_t result;
unsigned char dsbuf[DNS_DS_BUFFERSIZE];
for (result = dns_rdataset_first(rdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(rdataset))
{
dns_rdata_t newdsrdata = DNS_RDATA_INIT;
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(keyrdata);
if (ds->key_tag != keytag || ds->algorithm != key.algorithm) {
continue;
}
dns_rdata_reset(&newdsrdata);
result = dns_ds_buildrdata(val->event->name, keyrdata,
ds->digest_type,
dsbuf, &newdsrdata);
if (result != ISC_R_SUCCESS) {
validator_log(val, ISC_LOG_DEBUG(3),
"dns_ds_buildrdata() -> %s",
dns_result_totext(result));
continue;
}
if (dns_rdata_compare(dsrdata, &newdsrdata) == 0) {
break;
}
}
return (result);
}
static isc_result_t
anchor_signed(dns_validator_t *val, isc_result_t *resp) {
isc_result_t result;
@ -1926,6 +1883,8 @@ get_dsset(dns_validator_t *val, dns_name_t *tname, isc_result_t *resp) {
* Attempts positive response validation of an RRset containing zone keys
* (i.e. a DNSKEY rrset).
*
* Caller must be holding the validator lock.
*
* Returns:
* \li ISC_R_SUCCESS Validation completed successfully
* \li DNS_R_WAIT Validation has started but is waiting
@ -1935,17 +1894,33 @@ get_dsset(dns_validator_t *val, dns_name_t *tname, isc_result_t *resp) {
static isc_result_t
validate_dnskey(dns_validator_t *val) {
isc_result_t result;
dns_rdataset_t trdataset;
dns_rdata_t dsrdata = DNS_RDATA_INIT;
dns_rdata_t keyrdata = DNS_RDATA_INIT;
dns_keynode_t *keynode = NULL;
dns_rdata_ds_t ds;
bool supported_algorithm;
char digest_types[256];
/*
* Caller must be holding the validator lock.
* If we don't already have a DS RRset, check to see if there's
* a DS style trust anchor configured for this key.
*/
if (val->dsset == NULL) {
result = dns_keytable_find(val->keytable,
val->event->name, &keynode);
if (result == ISC_R_SUCCESS) {
val->dsset = dns_keynode_dsset(keynode);
if (val->dsset == NULL) {
dns_keytable_detachkeynode(val->keytable,
&keynode);
}
}
}
/*
* 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.
*/
if (val->dsset == NULL) {
isc_result_t tresult = ISC_R_SUCCESS;
@ -1989,6 +1964,7 @@ validate_dnskey(dns_validator_t *val) {
INSIST(val->dsset != NULL);
if (val->dsset->trust < dns_trust_secure) {
INSIST(keynode == NULL);
return (markanswer(val, "validate_dnskey (2)", "insecure DS"));
}
@ -2069,16 +2045,14 @@ validate_dnskey(dns_validator_t *val) {
supported_algorithm = true;
dns_rdataset_init(&trdataset);
dns_rdataset_clone(val->event->rdataset, &trdataset);
/*
* Find the DNSKEY matching the DS...
*/
result = dnskey_for_ds(val, &trdataset, &dsrdata,
&ds, &keyrdata);
result = dns_dnssec_matchdskey(val->event->name,
&dsrdata,
val->event->rdataset,
&keyrdata);
if (result != ISC_R_SUCCESS) {
dns_rdataset_disassociate(&trdataset);
validator_log(val, ISC_LOG_DEBUG(3),
"no DNSKEY matching DS");
continue;
@ -2088,13 +2062,18 @@ validate_dnskey(dns_validator_t *val) {
* ... and check that it signed the DNSKEY RRset.
*/
result = check_signer(val, &keyrdata, ds.key_tag, ds.algorithm);
dns_rdataset_disassociate(&trdataset);
if (result == ISC_R_SUCCESS) {
break;
}
validator_log(val, ISC_LOG_DEBUG(3),
"no RRSIG matching DS key");
}
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)");

View file

@ -320,6 +320,7 @@ dns_dnssec_get_hints
dns_dnssec_keyactive
dns_dnssec_keyfromrdata
dns_dnssec_keylistfromrdataset
dns_dnssec_matchdskey
dns_dnssec_selfsigns
dns_dnssec_sign
dns_dnssec_signmessage
@ -462,6 +463,7 @@ dns_keynode_attach
dns_keynode_create
dns_keynode_detach
dns_keynode_detachall
dns_keynode_dsset
dns_keynode_initial
dns_keynode_key
dns_keynode_managed

View file

@ -3828,81 +3828,59 @@ set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
}
/*
* Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
* If keynode references a key or a DS rdataset, and if the key
* zone does not contain a KEYDATA record for the corresponding name,
* then create an empty KEYDATA and push it into the zone as a placeholder,
* then schedule a key refresh immediately. This new KEYDATA record will be
* updated during the refresh.
*
* If the key zone is changed, set '*changed' to true.
*/
static isc_result_t
create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
dns_diff_t *diff, dns_keytable_t *keytable,
dns_keynode_t **keynodep, bool *changed)
dns_diff_t *diff, dns_keynode_t *keynode,
dns_name_t *keyname, bool *changed)
{
const char me[] = "create_keydata";
isc_result_t result = ISC_R_SUCCESS;
isc_buffer_t keyb, dstb;
unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
dns_rdata_keydata_t keydata;
dns_rdata_dnskey_t dnskey;
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_keynode_t *keynode;
dns_rdata_keydata_t kd;
unsigned char rrdata[4096];
isc_buffer_t rrdatabuf;
isc_stdtime_t now;
isc_region_t r;
dst_key_t *key;
REQUIRE(keynodep != NULL);
keynode = *keynodep;
REQUIRE(keynode != NULL);
ENTER;
isc_stdtime_get(&now);
/* Loop in case there's more than one key. */
while (result == ISC_R_SUCCESS) {
dns_keynode_t *nextnode = NULL;
key = dns_keynode_key(keynode);
if (key == NULL)
goto skip;
isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
CHECK(dst_key_todns(key, &dstb));
/* Convert DST key to DNSKEY. */
dns_rdata_reset(&rdata);
isc_buffer_usedregion(&dstb, &r);
dns_rdata_fromregion(&rdata, dst_key_class(key),
dns_rdatatype_dnskey, &r);
/* DSTKEY to KEYDATA. */
CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0,
NULL));
/* KEYDATA to rdata. */
dns_rdata_reset(&rdata);
isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
CHECK(dns_rdata_fromstruct(&rdata,
zone->rdclass, dns_rdatatype_keydata,
&keydata, &keyb));
/* Add rdata to zone. */
CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
dst_key_name(key), 0, &rdata));
*changed = true;
/* Refresh new keys from the zone apex as soon as possible. */
set_refreshkeytimer(zone, &keydata, now, true);
skip:
result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
if (result != ISC_R_NOTFOUND) {
dns_keytable_detachkeynode(keytable, &keynode);
keynode = nextnode;
}
/*
* If the keynode has neither a key nor a DS RRset,
* we shouldn't be here.
*/
if (dns_keynode_key(keynode) == NULL &&
dns_keynode_dsset(keynode) == NULL)
{
return (ISC_R_FAILURE);
}
if (keynode != NULL)
dns_keytable_detachkeynode(keytable, &keynode);
*keynodep = NULL;
memset(&kd, 0, sizeof(kd));
kd.common.rdclass = zone->rdclass;
kd.common.rdtype = dns_rdatatype_keydata;
ISC_LINK_INIT(&kd.common, link);
isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass,
dns_rdatatype_keydata,
&kd, &rrdatabuf));
/* Add rdata to zone. */
CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
keyname, 0, &rdata));
*changed = true;
/* Refresh new keys from the zone apex as soon as possible. */
set_refreshkeytimer(zone, &kd, now, true);
return (ISC_R_SUCCESS);
failure:
@ -3985,7 +3963,8 @@ trust_key(dns_zone_t *zone, dns_name_t *keyname,
goto failure;
CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
CHECK(dns_keytable_add(sr, true, initial, &dstkey));
CHECK(dns_keytable_add(sr, true, initial,
dst_key_name(dstkey), &dstkey, NULL));
dns_keytable_detach(&sr);
failure:
@ -4262,51 +4241,69 @@ struct addifmissing_arg {
};
static void
addifmissing(dns_keytable_t *keytable, dns_keynode_t *keynode, void *arg) {
addifmissing(dns_keytable_t *keytable, dns_keynode_t *keynode,
dns_name_t *keyname, void *arg)
{
dns_db_t *db = ((struct addifmissing_arg *)arg)->db;
dns_dbversion_t *ver = ((struct addifmissing_arg *)arg)->ver;
dns_diff_t *diff = ((struct addifmissing_arg *)arg)->diff;
dns_zone_t *zone = ((struct addifmissing_arg *)arg)->zone;
bool *changed = ((struct addifmissing_arg *)arg)->changed;
isc_result_t result;
dns_keynode_t *dummy = NULL;
dns_fixedname_t fname;
if (((struct addifmissing_arg *)arg)->result != ISC_R_SUCCESS)
UNUSED(keytable);
if (((struct addifmissing_arg *)arg)->result != ISC_R_SUCCESS) {
return;
if (dns_keynode_managed(keynode)) {
dns_fixedname_t fname;
dns_name_t *keyname;
dst_key_t *key;
key = dns_keynode_key(keynode);
if (key == NULL)
return;
dns_fixedname_init(&fname);
keyname = dst_key_name(key);
result = dns_db_find(db, keyname, ver,
dns_rdatatype_keydata,
DNS_DBFIND_NOWILD, 0, NULL,
dns_fixedname_name(&fname),
NULL, NULL);
if (result == ISC_R_SUCCESS)
return;
dns_keytable_attachkeynode(keytable, keynode, &dummy);
result = create_keydata(zone, db, ver, diff, keytable,
&dummy, changed);
if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE)
((struct addifmissing_arg *)arg)->result = result;
}
};
if (!dns_keynode_managed(keynode)) {
return;
}
/*
* If the keynode has neither a key-style nor a DS-style
* trust anchor, return.
*/
if (dns_keynode_dsset(keynode) == NULL &&
dns_keynode_key(keynode) == NULL)
{
return;
}
/*
* Check whether there's already a KEYDATA entry for this name;
* if so, we don't need to add another.
*/
dns_fixedname_init(&fname);
result = dns_db_find(db, keyname, ver, dns_rdatatype_keydata,
DNS_DBFIND_NOWILD, 0, NULL,
dns_fixedname_name(&fname),
NULL, NULL);
if (result == ISC_R_SUCCESS) {
return;
}
/*
* Create the keydata.
*/
result = create_keydata(zone, db, ver, diff, keynode, keyname, changed);
if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) {
((struct addifmissing_arg *)arg)->result = result;
}
}
/*
* Synchronize the set of initializing keys found in managed-keys {}
* statements with the set of trust anchors found in the managed-keys.bind
* zone. If a domain is no longer named in managed-keys, delete all keys
* from that domain from the key zone. If a domain is mentioned in in
* managed-keys but there are no references to it in the key zone, load
* the key zone with the initializing key(s) for that domain.
* from that domain from the key zone. If a domain is configured as an
* initial-key in dnssec-keys, but there are no references to it in the
* key zone, load the key zone with the initializing key(s) for that
* domain and schedule a key refresh. If a domain is configured as
* an initial-ds in dnssec-keys, fetch the DNSKEY RRset, load the key
* zone with the matching key, and schedule a key refresh.
*/
static isc_result_t
sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
@ -4337,9 +4334,9 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
/*
* Walk the zone DB. If we find any keys whose names are no longer
* in managed-keys as initial-keys (or which are now configured as
* static keys, meaning they are permanent and not RFC5011-maintained),
* delete them from the zone. Otherwise call load_secroots(), which
* in dnssec-keys, or which have been changed from initial to static,
* (meaning they are permanent and not RFC5011-maintained), delete
* them from the zone. Otherwise call load_secroots(), which
* loads keys into secroots as appropriate.
*/
dns_rriterator_init(&rrit, db, ver, 0);
@ -4362,12 +4359,8 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
}
result = dns_keytable_find(sr, rrname, &keynode);
if ((result != ISC_R_SUCCESS &&
result != DNS_R_PARTIALMATCH) ||
dns_keynode_managed(keynode) == false)
{
CHECK(delete_keydata(db, ver, &diff,
rrname, rdataset));
if (result != ISC_R_SUCCESS || !dns_keynode_managed(keynode)) {
CHECK(delete_keydata(db, ver, &diff, rrname, rdataset));
changed = true;
} else {
load_secroots(zone, rrname, rdataset);
@ -4380,8 +4373,10 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
dns_rriterator_destroy(&rrit);
/*
* Now walk secroots to find any managed keys that aren't
* in the zone. If we find any, we add them to the zone.
* Walk secroots to find any initial keys that aren't in
* the zone. If we find any, add them to the zone directly.
* If any DS-style initial keys are found, refresh the key
* zone so that they'll be looked up.
*/
arg.db = db;
arg.ver = ver;
@ -9740,7 +9735,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
dns_diff_t diff;
bool alldone = false;
bool commit = false;
dns_name_t *keyname;
dns_name_t *keyname = NULL;
dns_rdata_t sigrr = DNS_RDATA_INIT;
dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
dns_rdata_t keydatarr = DNS_RDATA_INIT;
@ -9751,11 +9746,14 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
char namebuf[DNS_NAME_FORMATSIZE];
unsigned char key_buf[4096];
isc_buffer_t keyb;
dst_key_t *dstkey;
dst_key_t *dstkey = NULL;
isc_stdtime_t now;
int pending = 0;
bool secure = false, initial = false;
bool free_needed;
dns_keynode_t *keynode = NULL;
dns_rdataset_t *dnskeys = NULL, *dnskeysigs = NULL;
dns_rdataset_t *keydataset = NULL, *dsset = NULL;
UNUSED(task);
INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
@ -9765,6 +9763,9 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
zone = kfetch->zone;
isc_mem_attach(zone->mctx, &mctx);
keyname = dns_fixedname_name(&kfetch->name);
dnskeys = &kfetch->dnskeyset;
dnskeysigs = &kfetch->dnskeysigset;
keydataset = &kfetch->keydataset;
devent = (dns_fetchevent_t *) event;
eresult = devent->result;
@ -9806,9 +9807,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
namebuf, dns_result_totext(eresult));
/* Fetch failed */
if (eresult != ISC_R_SUCCESS ||
!dns_rdataset_isassociated(&kfetch->dnskeyset))
{
if (eresult != ISC_R_SUCCESS || !dns_rdataset_isassociated(dnskeys)) {
dnssec_log(zone, ISC_LOG_WARNING,
"Unable to fetch DNSKEY set '%s': %s",
namebuf, dns_result_totext(eresult));
@ -9817,7 +9816,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
}
/* No RRSIGs found */
if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
if (!dns_rdataset_isassociated(dnskeysigs)) {
dnssec_log(zone, ISC_LOG_WARNING,
"No DNSKEY RRSIGs found for '%s': %s",
namebuf, dns_result_totext(eresult));
@ -9829,27 +9828,110 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
* Clear any cached trust level, as we need to run validation
* over again; trusted keys might have changed.
*/
kfetch->dnskeyset.trust = kfetch->dnskeysigset.trust = dns_trust_none;
dnskeys->trust = dnskeysigs->trust = dns_trust_none;
/* Look up the trust anchor */
result = dns_keytable_find(secroots, keyname, &keynode);
if (result != ISC_R_SUCCESS) {
goto anchors_done;
}
/*
* Validate the dnskeyset against the current trusted keys.
* If the first keynode has a DS trust anchor, use that for
* verification.
*/
for (result = dns_rdataset_first(&kfetch->dnskeysigset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&kfetch->dnskeysigset))
{
dns_keynode_t *keynode = NULL;
if ((dsset = dns_keynode_dsset(keynode)) != NULL) {
for (result = dns_rdataset_first(dnskeysigs);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(dnskeysigs))
{
isc_result_t tresult;
dns_rdata_t keyrdata = DNS_RDATA_INIT;
dns_rdata_reset(&sigrr);
dns_rdataset_current(dnskeysigs, &sigrr);
result = dns_rdata_tostruct(&sigrr, &sig, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
for (tresult = dns_rdataset_first(dsset);
tresult == ISC_R_SUCCESS;
tresult = dns_rdataset_next(dsset))
{
dns_rdata_t dsrdata = DNS_RDATA_INIT;
dns_rdata_ds_t ds;
dns_rdata_reset(&dsrdata);
dns_rdataset_current(dsset, &dsrdata);
tresult = dns_rdata_tostruct(&dsrdata, &ds,
NULL);
RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
if (ds.key_tag != sig.keyid ||
ds.algorithm != sig.algorithm)
{
continue;
}
result = dns_dnssec_matchdskey(keyname,
&dsrdata,
dnskeys,
&keyrdata);
if (result == ISC_R_SUCCESS) {
break;
}
}
if (tresult == ISC_R_NOMORE) {
continue;
}
result = dns_dnssec_keyfromrdata(keyname, &keyrdata,
mctx, &dstkey);
if (result != ISC_R_SUCCESS) {
continue;
}
result = dns_dnssec_verify(keyname, dnskeys,
dstkey, false, 0,
mctx, &sigrr, NULL);
dst_key_free(&dstkey);
dnssec_log(zone, ISC_LOG_DEBUG(3),
"Verifying DNSKEY set for zone "
"'%s' using DS %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;
initial = dns_keynode_initial(keynode);
dns_keynode_trust(keynode);
secure = true;
break;
}
}
dns_keytable_detachkeynode(secroots, &keynode);
goto anchors_done;
}
/*
* 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))
{
dns_rdata_reset(&sigrr);
dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
dns_rdataset_current(dnskeysigs, &sigrr);
result = dns_rdata_tostruct(&sigrr, &sig, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
result = dns_keytable_find(secroots, keyname, &keynode);
result = ISC_R_SUCCESS;
while (result == ISC_R_SUCCESS) {
dns_keynode_t *nextnode = NULL;
dns_fixedname_t fixed;
dns_fixedname_init(&fixed);
dstkey = dns_keynode_key(keynode);
if (dstkey == NULL) {
@ -9860,26 +9942,21 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
if (dst_key_alg(dstkey) == sig.algorithm &&
dst_key_id(dstkey) == sig.keyid)
{
result = dns_dnssec_verify(keyname,
&kfetch->dnskeyset,
dstkey, false,
0,
zone->view->mctx,
&sigrr,
dns_fixedname_name(
&fixed));
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,
"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) {
kfetch->dnskeyset.trust =
dns_trust_secure;
kfetch->dnskeysigset.trust =
dns_trust_secure;
dnskeys->trust = dns_trust_secure;
dnskeysigs->trust = dns_trust_secure;
secure = true;
initial = dns_keynode_initial(keynode);
dns_keynode_trust(keynode);
@ -9887,14 +9964,12 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
}
}
result = dns_keytable_nextkeynode(secroots,
keynode, &nextnode);
dns_keytable_detachkeynode(secroots, &keynode);
keynode = nextnode;
}
if (keynode != NULL) {
dns_keytable_detachkeynode(secroots, &keynode);
result = dns_keytable_nextkeynode(secroots, keynode,
&nextnode);
if (result == ISC_R_SUCCESS) {
dns_keytable_detachkeynode(secroots, &keynode);
keynode = nextnode;
}
}
if (secure) {
@ -9902,6 +9977,12 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
}
}
anchors_done:
if (keynode != NULL) {
dns_keytable_detachkeynode(secroots, &keynode);
}
/*
* If we were not able to verify the answer using the current
* trusted keys then all we can do is look at any revoked keys.
@ -9926,14 +10007,14 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
* updated
*/
initializing = true;
for (result = dns_rdataset_first(&kfetch->keydataset);
for (result = dns_rdataset_first(keydataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&kfetch->keydataset))
result = dns_rdataset_next(keydataset))
{
dns_keytag_t keytag;
dns_rdata_reset(&keydatarr);
dns_rdataset_current(&kfetch->keydataset, &keydatarr);
dns_rdataset_current(keydataset, &keydatarr);
result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
@ -9960,7 +10041,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
*/
initializing = initializing && (keydata.addhd == 0);
if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
if (! matchkey(dnskeys, &keydatarr)) {
bool deletekey = false;
if (!secure) {
@ -10041,9 +10122,9 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
* - All keys not being removed have their refresh
* timers updated
*/
for (result = dns_rdataset_first(&kfetch->dnskeyset);
for (result = dns_rdataset_first(dnskeys);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(&kfetch->dnskeyset))
result = dns_rdataset_next(dnskeys))
{
bool revoked = false;
bool newkey = false;
@ -10053,7 +10134,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
dns_keytag_t keytag;
dns_rdata_reset(&dnskeyrr);
dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
dns_rdataset_current(dnskeys, &dnskeyrr);
result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
@ -10078,9 +10159,9 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
revoked = ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0);
if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
if (matchkey(keydataset, &dnskeyrr)) {
dns_rdata_reset(&keydatarr);
dns_rdataset_current(&kfetch->keydataset, &keydatarr);
dns_rdataset_current(keydataset, &keydatarr);
result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
@ -10339,14 +10420,14 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
zone->irefs--;
kfetch->zone = NULL;
if (dns_rdataset_isassociated(&kfetch->keydataset)) {
dns_rdataset_disassociate(&kfetch->keydataset);
if (dns_rdataset_isassociated(keydataset)) {
dns_rdataset_disassociate(keydataset);
}
if (dns_rdataset_isassociated(&kfetch->dnskeyset)) {
dns_rdataset_disassociate(&kfetch->dnskeyset);
if (dns_rdataset_isassociated(dnskeys)) {
dns_rdataset_disassociate(dnskeys);
}
if (dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
dns_rdataset_disassociate(&kfetch->dnskeysigset);
if (dns_rdataset_isassociated(dnskeysigs)) {
dns_rdataset_disassociate(dnskeysigs);
}
dns_name_free(keyname, mctx);
@ -10366,8 +10447,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
}
/*
* Refresh the data in the key zone. Initiate a fetch to get new DNSKEY
* records from the zone apex.
* Refresh the data in the key zone. Initiate a fetch to look up
* DNSKEY records at the trust anchor name.
*/
static void
zone_refreshkeys(dns_zone_t *zone) {

View file

@ -255,6 +255,7 @@ irs_context_create(irs_context_t **contextp) {
trustedkey != NULL;
trustedkey = ISC_LIST_NEXT(trustedkey, link)) {
result = dns_client_addtrustedkey(client, dns_rdataclass_in,
dns_rdatatype_dnskey,
trustedkey->keyname,
trustedkey->keydatabuf);
if (result != ISC_R_SUCCESS)

View file

@ -445,11 +445,11 @@ static cfg_type_t cfg_type_category = {
*/
static cfg_tuplefielddef_t dnsseckey_fields[] = {
{ "name", &cfg_type_astring, 0 },
{ "init", &cfg_type_void, 0 },
{ "flags", &cfg_type_uint32, 0 },
{ "protocol", &cfg_type_uint32, 0 },
{ "algorithm", &cfg_type_uint32, 0 },
{ "key", &cfg_type_qstring, 0 },
{ "anchortype", &cfg_type_void, 0 },
{ "n1", &cfg_type_uint32, 0 },
{ "n2", &cfg_type_uint32, 0 },
{ "n3", &cfg_type_uint32, 0 },
{ "data", &cfg_type_qstring, 0 },
{ NULL, NULL, 0 }
};
static cfg_type_t cfg_type_dnsseckey = {
@ -461,19 +461,20 @@ static cfg_type_t cfg_type_dnsseckey = {
* A key initialization specifier, as used in the
* "dnssec-keys" (or synonymous "managed-keys") statement.
*/
static const char *init_enums[] = { "static-key", "initial-key", NULL };
static cfg_type_t cfg_type_keyinit = {
"keyinit", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
&cfg_rep_string, &init_enums
static const char *anchortype_enums[] = {
"static-key", "initial-key", "static-ds", "initial-ds", NULL
};
static cfg_type_t cfg_type_anchortype = {
"anchortype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
&cfg_rep_string, anchortype_enums
};
static cfg_tuplefielddef_t managedkey_fields[] = {
{ "name", &cfg_type_astring, 0 },
{ "init", &cfg_type_keyinit, 0 },
{ "flags", &cfg_type_uint32, 0 },
{ "protocol", &cfg_type_uint32, 0 },
{ "algorithm", &cfg_type_uint32, 0 },
{ "key", &cfg_type_qstring, 0 },
{ "anchortype", &cfg_type_anchortype, 0 },
{ "n1", &cfg_type_uint32, 0 },
{ "n2", &cfg_type_uint32, 0 },
{ "n3", &cfg_type_uint32, 0 },
{ "data", &cfg_type_qstring, 0 },
{ NULL, NULL, 0 }
};
static cfg_type_t cfg_type_managedkey = {
@ -692,10 +693,9 @@ static cfg_type_t cfg_type_trustedkeys = {
};
/*%
* A list of key entries, as in "trusted-keys". This has a format similar
* to dnssec keys, except the keyname is followed by keyword, either
* "initial-key" or "static-key". If "initial-key", then the key is
* RFC 5011 managed; if "static-key", then the key never changes.
* A list of managed trust anchors. Each entry contains a name, a keyword
* ("static-key", initial-key", "static-ds" or "initial-ds"), and the
* fields associated with either a DNSKEY or a DS record.
*/
static cfg_type_t cfg_type_dnsseckeys = {
"dnsseckeys", cfg_parse_bracketed_list, cfg_print_bracketed_list,

View file

@ -6596,6 +6596,8 @@ static bool
has_ta(query_ctx_t *qctx) {
dns_keytable_t *keytable = NULL;
dns_keynode_t *keynode = NULL;
dns_rdataset_t *dsset = NULL;
dns_keytag_t sentinel = qctx->client->query.root_key_sentinel_keyid;
isc_result_t result;
result = dns_view_getsecroots(qctx->view, &keytable);
@ -6604,10 +6606,38 @@ has_ta(query_ctx_t *qctx) {
}
result = dns_keytable_find(keytable, dns_rootname, &keynode);
if (result != ISC_R_SUCCESS) {
if (keynode != NULL) {
dns_keytable_detachkeynode(keytable, &keynode);
}
dns_keytable_detach(&keytable);
return (false);
}
if ((dsset = dns_keynode_dsset(keynode)) != NULL) {
for (result = dns_rdataset_first(dsset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(dsset))
{
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_ds_t ds;
dns_rdata_reset(&rdata);
dns_rdataset_current(dsset, &rdata);
result = dns_rdata_tostruct(&rdata, &ds, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
if (ds.key_tag == sentinel) {
dns_keytable_detachkeynode(keytable, &keynode);
dns_keytable_detach(&keytable);
return (true);
}
}
}
while (result == ISC_R_SUCCESS) {
dns_keynode_t *nextnode = NULL;
dns_keytag_t keyid = dst_key_id(dns_keynode_key(keynode));
if (keyid == qctx->client->query.root_key_sentinel_keyid) {
if (keyid == sentinel) {
dns_keytable_detachkeynode(keytable, &keynode);
dns_keytable_detach(&keytable);
return (true);
@ -6616,8 +6646,11 @@ has_ta(query_ctx_t *qctx) {
dns_keytable_detachkeynode(keytable, &keynode);
keynode = nextnode;
}
dns_keytable_detach(&keytable);
if (keynode != NULL) {
dns_keytable_detachkeynode(keytable, &keynode);
}
dns_keytable_detach(&keytable);
return (false);
}

View file

@ -162,6 +162,7 @@ set_key(dns_client_t *client, char *keynamestr, char *keystr,
exit(1);
}
result = dns_client_addtrustedkey(client, dns_rdataclass_in,
dns_rdatatype_dnskey,
keyname, &rrdatabuf);
if (result != ISC_R_SUCCESS) {
fprintf(stderr, "failed to add key for %s\n",