add support for DS trust anchors in delv

This commit is contained in:
Evan Hunt 2019-09-18 19:45:20 -07:00
parent edafbf1c0f
commit 342cc9b168
5 changed files with 158 additions and 44 deletions

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;
dns_rdata_dnskey_t dnskey;
dns_rdata_ds_t ds;
uint32_t n1, n2, n3;
const char *keystr, *keynamestr;
unsigned char keydata[4096];
isc_buffer_t keydatabuf;
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));
@ -651,14 +661,26 @@ key_fromconfig(const cfg_obj_t *key, dns_client_t *client) {
/* if DNSKEY, algorithm; if DS, digest type */
n3 = cfg_obj_asuint32(cfg_tuple_get(key, "n3"));
keystruct.common.rdclass = dns_rdataclass_in;
keystruct.common.rdtype = dns_rdatatype_dnskey;
/*
* The key data in keystruct is not dynamically allocated.
*/
keystruct.mctx = NULL;
/* 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;
}
ISC_LINK_INIT(&keystruct.common, link);
isc_buffer_init(&databuf, data, sizeof(data));
isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
if (n1 > 0xffff) {
CHECK(ISC_R_RANGE);
@ -670,25 +692,78 @@ key_fromconfig(const cfg_obj_t *key, dns_client_t *client) {
CHECK(ISC_R_RANGE);
}
keystruct.flags = (uint16_t)n1;
keystruct.protocol = (uint8_t)n2;
keystruct.algorithm = (uint8_t)n3;
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_buffer_init(&keydatabuf, keydata, sizeof(keydata));
isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
ISC_LINK_INIT(&dnskey.common, link);
keystr = cfg_obj_asstring(cfg_tuple_get(key, "data"));
CHECK(isc_base64_decodestring(keystr, &keydatabuf));
isc_buffer_usedregion(&keydatabuf, &r);
keystruct.datalen = r.length;
keystruct.data = r.base;
dnskey.flags = (uint16_t)n1;
dnskey.protocol = (uint8_t)n2;
dnskey.algorithm = (uint8_t)n3;
CHECK(dns_rdata_fromstruct(NULL, keystruct.common.rdclass,
keystruct.common.rdtype,
&keystruct, &rrdatabuf));
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

@ -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,28 +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,
dst_key_name(dstkey), &dstkey, NULL);
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

@ -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

@ -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

@ -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",