#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>
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;
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));
/* 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);
CHECK(ISC_R_RANGE);
}
- keystruct.flags = (uint16_t)n1;
- keystruct.protocol = (uint8_t)n2;
- keystruct.algorithm = (uint8_t)n3;
-
- isc_buffer_init(&keydatabuf, keydata, sizeof(keydata));
- isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
+ 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;
+ }
- 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;
+ ds.length = r.length;
+ ds.digest = r.base;
- CHECK(dns_rdata_fromstruct(NULL, keystruct.common.rdclass,
- keystruct.common.rdtype,
- &keystruct, &rrdatabuf));
+ 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:
#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
*/
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));
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);
+
+ 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;
- result = dns_keytable_add(secroots, false, false,
- dst_key_name(dstkey), &dstkey, NULL);
+ 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);
}