]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
add support for DS trust anchors in delv
authorEvan Hunt <each@isc.org>
Thu, 19 Sep 2019 02:45:20 +0000 (19:45 -0700)
committerEvan Hunt <each@isc.org>
Fri, 15 Nov 2019 23:47:57 +0000 (15:47 -0800)
bin/delv/delv.c
lib/dns/client.c
lib/dns/include/dns/client.h
lib/irs/context.c
lib/samples/resolve.c

index c02dfb99055fe676b127dde3b47732daf27392ed..fb14aa05ba92addd7f00e71fe53f854d187e7314 100644 (file)
 #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;
-
-       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:
index 971c4e3af2670a4998eb564648cd6faf600752ab..58da8506e42fb2ae4f3f6838c3e8794cb0442a03 100644 (file)
 #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);
+
+       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);
 }
 
index d661e2deba65da8a137f1c37985beb5a504750b8..1740004892ebf2b7f46f8a1ddc73bf5292d9c657 100644 (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:
  *
index a359c1ee890b88e0f35e0d2289d268dff1a0c552..d1b71c420412546120115c40243eac47b38f9b4d 100644 (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)
index 1715c5c89eaf40e973f5b385d799ff4cfa2efe2a..587d159f4436e858116754c984a031ccde0891f4 100644 (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",