From: Evan Hunt Date: Fri, 20 Dec 2019 19:37:11 +0000 (-0800) Subject: disable adding keys to keytable; only DS trust anchors can now be added X-Git-Tag: v9.15.8~8^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b984a4b64733bb5924c7231ebdacb89f2d486577;p=thirdparty%2Fbind9.git disable adding keys to keytable; only DS trust anchors can now be added the internal keytable structure has not yet been changed, but insertion of DS anchors is the only method now available. NOTE: the keytable unit test is currently failing because of tests that expect individual keynode objects to contain single DST key objects. --- diff --git a/bin/named/server.c b/bin/named/server.c index 1b8ee399c4d..14088fb3c6e 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -700,11 +700,12 @@ configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config, } static isc_result_t -ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **keyp, - dns_rdata_ds_t **dsp, const char **namestrp, isc_mem_t *mctx) +ta_fromconfig(const cfg_obj_t *key, bool *initialp, const char **namestrp, + unsigned char *digest, dns_rdata_ds_t *ds) { + isc_result_t result; dns_rdata_dnskey_t keystruct; - dns_rdata_ds_t *ds = NULL; + dns_rdata_t rdata = DNS_RDATA_INIT; uint32_t rdata1, rdata2, rdata3; const char *datastr = NULL, *namestr = NULL; unsigned char data[4096]; @@ -715,8 +716,6 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **keyp, dns_fixedname_t fname; dns_name_t *name = NULL; isc_buffer_t namebuf; - isc_result_t result; - dst_key_t *dstkey = NULL; const char *atstr = NULL; enum { INIT_DNSKEY, @@ -726,9 +725,8 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **keyp, TRUSTED } anchortype; - REQUIRE(keyp != NULL && *keyp == NULL); - REQUIRE(dsp != NULL && *dsp == NULL); REQUIRE(namestrp != NULL && *namestrp == NULL); + REQUIRE(ds != NULL); /* if DNSKEY, flags; if DS, key tag */ rdata1 = cfg_obj_asuint32(cfg_tuple_get(key, "rdata1")); @@ -775,6 +773,13 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **keyp, isc_buffer_init(&databuf, data, sizeof(data)); isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); + *ds = (dns_rdata_ds_t){ + .common.rdclass = dns_rdataclass_in, + .common.rdtype = dns_rdatatype_ds + }; + + ISC_LINK_INIT(&ds->common, link); + switch(anchortype) { case INIT_DNSKEY: case STATIC_DNSKEY: @@ -802,7 +807,7 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **keyp, if (rdata2 > 0xff) { CHECKM(ISC_R_RANGE, "key protocol"); } - if (rdata3> 0xff) { + if (rdata3 > 0xff) { CHECKM(ISC_R_RANGE, "key algorithm"); } @@ -810,30 +815,25 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **keyp, keystruct.protocol = (uint8_t)rdata2; keystruct.algorithm = (uint8_t)rdata3; + if (!dst_algorithm_supported(keystruct.algorithm)) { + CHECK(DST_R_UNSUPPORTEDALG); + } + datastr = cfg_obj_asstring(cfg_tuple_get(key, "data")); CHECK(isc_base64_decodestring(datastr, &databuf)); isc_buffer_usedregion(&databuf, &r); keystruct.datalen = r.length; keystruct.data = r.base; - CHECK(dns_rdata_fromstruct(NULL, keystruct.common.rdclass, + CHECK(dns_rdata_fromstruct(&rdata, keystruct.common.rdclass, keystruct.common.rdtype, &keystruct, &rrdatabuf)); - CHECK(dst_key_fromdns(name, dns_rdataclass_in, - &rrdatabuf, mctx, &dstkey)); - - *keyp = dstkey; + CHECK(dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256, + digest, ds)); break; case INIT_DS: case STATIC_DS: - ds = isc_mem_get(mctx, sizeof(*ds)); - ds->common.rdclass = dns_rdataclass_in; - ds->common.rdtype = dns_rdatatype_ds; - ds->mctx = NULL; - - ISC_LINK_INIT(&ds->common, link); - if (rdata1 > 0xffff) { CHECKM(ISC_R_RANGE, "key tag"); } @@ -878,13 +878,10 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **keyp, break; } - ds->mctx = mctx; ds->length = r.length; - ds->digest = isc_mem_allocate(mctx, r.length); + ds->digest = digest; memmove(ds->digest, r.base, r.length); - *dsp = ds; - ds = NULL; break; default: @@ -895,15 +892,6 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **keyp, return (ISC_R_SUCCESS); cleanup: - if (dstkey != NULL) { - dst_key_free(&dstkey); - } - - if (ds != NULL) { - dns_rdata_freestruct(ds); - isc_mem_put(mctx, ds, sizeof(*ds)); - } - return (result); } @@ -921,46 +909,30 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **keyp, static isc_result_t process_key(const cfg_obj_t *key, dns_keytable_t *secroots, const dns_name_t *keyname_match, dns_resolver_t *resolver, - bool managed, isc_mem_t *mctx) + bool managed) { dns_fixedname_t fkeyname; dns_name_t *keyname = NULL; const char *namestr = NULL; - dst_key_t *dstkey = NULL; - dns_rdata_ds_t *ds = NULL; - unsigned int keyalg; + dns_rdata_ds_t ds; isc_result_t result; bool initializing = managed; + unsigned char digest[ISC_MAX_MD_SIZE]; + isc_buffer_t b; - result = ta_fromconfig(key, &initializing, &dstkey, &ds, - &namestr, mctx); + result = ta_fromconfig(key, &initializing, &namestr, digest, &ds); switch (result) { case ISC_R_SUCCESS: /* - * Trust anchor was parsed correctly. If dstkey is - * not NULL, then it was a key anchor, its algorithm - * is supported by the crypto library, and it is not - * revoked. If dstkey is NULL, then it was a DS - * trust anchor instead. + * Trust anchor was parsed correctly. */ - if (dstkey != NULL) { - keyname = dst_key_name(dstkey); - keyalg = dst_key_alg(dstkey); - } else { - isc_buffer_t b; - - INSIST(ds != NULL); - - isc_buffer_constinit(&b, namestr, strlen(namestr)); - isc_buffer_add(&b, strlen(namestr)); - keyname = dns_fixedname_initname(&fkeyname); - result = dns_name_fromtext(keyname, &b, - dns_rootname, 0, NULL); - if (result != ISC_R_SUCCESS) { - return (result); - } - keyalg = ds->algorithm; + isc_buffer_constinit(&b, namestr, strlen(namestr)); + isc_buffer_add(&b, strlen(namestr)); + keyname = dns_fixedname_initname(&fkeyname); + result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + return (result); } break; case DST_R_UNSUPPORTEDALG: @@ -1011,7 +983,8 @@ process_key(const cfg_obj_t *key, dns_keytable_t *secroots, * its owner name. If it does not, do not load the key and log a * warning, but do not prevent further keys from being processed. */ - if (!dns_resolver_algorithm_supported(resolver, keyname, keyalg)) { + if (!dns_resolver_algorithm_supported(resolver, keyname, ds.algorithm)) + { cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING, "ignoring %s for '%s': algorithm is disabled", initializing ? "initial-key" : "static-key", @@ -1026,29 +999,10 @@ process_key(const cfg_obj_t *key, dns_keytable_t *secroots, * managed, so we use 'initializing' twice here, for both the * 'managed' and 'initializing' arguments to dns_keytable_add(). */ - result = dns_keytable_add(secroots, initializing, - initializing, keyname, - dstkey != NULL ? &dstkey : NULL, - ds); + result = dns_keytable_add(secroots, initializing, initializing, + keyname, &ds); done: - /* - * Ensure 'dstkey' does not leak. Note that if dns_keytable_add() - * succeeds, ownership of the key structure is transferred to the key - * table, i.e. 'dstkey' is set to NULL. - */ - if (dstkey != NULL) { - dst_key_free(&dstkey); - } - - /* - * Free 'ds'. - */ - if (ds != NULL) { - dns_rdata_freestruct(ds); - isc_mem_put(mctx, ds, sizeof(*ds)); - } - return (result); } @@ -1059,7 +1013,7 @@ process_key(const cfg_obj_t *key, dns_keytable_t *secroots, */ static isc_result_t load_view_keys(const cfg_obj_t *keys, dns_view_t *view, bool managed, - const dns_name_t *keyname, isc_mem_t *mctx) + const dns_name_t *keyname) { const cfg_listelt_t *elt, *elt2; const cfg_obj_t *keylist; @@ -1078,9 +1032,8 @@ load_view_keys(const cfg_obj_t *keys, dns_view_t *view, bool managed, elt2 != NULL; elt2 = cfg_list_next(elt2)) { - CHECK(process_key(cfg_listelt_value(elt2), - secroots, keyname, view->resolver, - managed, mctx)); + CHECK(process_key(cfg_listelt_value(elt2), secroots, + keyname, view->resolver, managed)); } } @@ -1238,7 +1191,7 @@ configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig, if (builtin_keys != NULL) { CHECK(load_view_keys(builtin_keys, view, true, - dns_rootname, mctx)); + dns_rootname)); } if (!keyloaded(view, dns_rootname)) { @@ -1251,17 +1204,13 @@ configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig, } if (view->rdclass == dns_rdataclass_in) { - CHECK(load_view_keys(view_keys, view, false, NULL, mctx)); - CHECK(load_view_keys(view_trust_anchors, view, true, NULL, - mctx)); - CHECK(load_view_keys(view_managed_keys, view, true, NULL, - mctx)); - - CHECK(load_view_keys(global_keys, view, false, NULL, mctx)); - CHECK(load_view_keys(global_trust_anchors, view, true, - NULL, mctx)); - CHECK(load_view_keys(global_managed_keys, view, true, - NULL, mctx)); + CHECK(load_view_keys(view_keys, view, false, NULL)); + CHECK(load_view_keys(view_trust_anchors, view, true, NULL)); + CHECK(load_view_keys(view_managed_keys, view, true, NULL)); + + CHECK(load_view_keys(global_keys, view, false, NULL)); + CHECK(load_view_keys(global_trust_anchors, view, true, NULL)); + CHECK(load_view_keys(global_managed_keys, view, true, NULL)); } /* diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index e959412961b..0d14b737f79 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -3700,12 +3700,12 @@ status=$((status+ret)) # DNSSEC tests related to unsupported, disabled and revoked trust anchors. # -# This nameserver (ns8) is loaded with a bunch of trust anchors. Some of them -# are good (enabled.managed, enabled.trusted, secure.managed, secure.trusted), -# and some of them are bad (disabled.managed, revoked.managed, unsupported.managed, -# disabled.trusted, revoked.trusted, unsupported.trusted). Make sure that the bad -# trust anchors are ignored. This is tested by looking for the corresponding -# lines in the logfile. +# This nameserver (ns8) is loaded with a bunch of trust anchors. Some of +# them are good (enabled.managed, enabled.trusted, secure.managed, +# secure.trusted), and some of them are bad (disabled.managed, +# revoked.managed, unsupported.managed, disabled.trusted, revoked.trusted, +# unsupported.trusted). Make sure that the bad trust anchors are ignored. +# This is tested by looking for the corresponding lines in the logfile. echo_i "checking that keys with unsupported algorithms and disabled algorithms are ignored ($n)" ret=0 grep -q "ignoring static-key for 'disabled\.trusted\.': algorithm is disabled" ns8/named.run || ret=1 diff --git a/lib/dns/client.c b/lib/dns/client.c index 4ffbd6ff296..54e14ce1110 100644 --- a/lib/dns/client.c +++ b/lib/dns/client.c @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -1498,6 +1499,7 @@ dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass, dns_keytable_t *secroots = NULL; dns_name_t *name = NULL; char dsbuf[DNS_DS_BUFFERSIZE]; + unsigned char digest[ISC_MAX_MD_SIZE]; dns_rdata_ds_t ds; dns_decompress_t dctx; dns_rdata_t rdata; @@ -1515,33 +1517,28 @@ dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass, DE_CONST(keyname, name); - switch (rdtype) { - case dns_rdatatype_dnskey: - result = dst_key_fromdns(keyname, rdclass, databuf, - client->mctx, &dstkey); - if (result != ISC_R_SUCCESS) { - goto cleanup; - } - CHECK(dns_keytable_add(secroots, false, false, - name, &dstkey, NULL)); - break; - case dns_rdatatype_ds: - isc_buffer_init(&b, dsbuf, sizeof(dsbuf)); - dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE); - dns_rdata_init(&rdata); - isc_buffer_setactive(databuf, isc_buffer_usedlength(databuf)); - CHECK(dns_rdata_fromwire(&rdata, rdclass, rdtype, - databuf, &dctx, 0, &b)); - dns_decompress_invalidate(&dctx); - CHECK(dns_rdata_tostruct(&rdata, &ds, NULL)); - CHECK(dns_keytable_add(secroots, false, false, - name, NULL, &ds)); - break; - - default: + if (rdtype != dns_rdatatype_dnskey && rdtype != dns_rdatatype_ds) { result = ISC_R_NOTIMPLEMENTED; + goto cleanup; } + isc_buffer_init(&b, dsbuf, sizeof(dsbuf)); + dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE); + dns_rdata_init(&rdata); + isc_buffer_setactive(databuf, isc_buffer_usedlength(databuf)); + CHECK(dns_rdata_fromwire(&rdata, rdclass, rdtype, + databuf, &dctx, 0, &b)); + dns_decompress_invalidate(&dctx); + + if (rdtype == dns_rdatatype_ds) { + CHECK(dns_rdata_tostruct(&rdata, &ds, NULL)); + } else { + CHECK(dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256, + digest, &ds)); + } + + CHECK(dns_keytable_add(secroots, false, false, name, &ds)); + cleanup: if (dstkey != NULL) { dst_key_free(&dstkey); diff --git a/lib/dns/ds.c b/lib/dns/ds.c index 8958fb89cf2..7a9c911544e 100644 --- a/lib/dns/ds.c +++ b/lib/dns/ds.c @@ -29,20 +29,17 @@ #include isc_result_t -dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key, - dns_dsdigest_t digest_type, unsigned char *buffer, - dns_rdata_t *rdata) +dns_ds_fromkeyrdata(dns_name_t *owner, dns_rdata_t *key, + dns_dsdigest_t digest_type, unsigned char *digest, + dns_rdata_ds_t *dsrdata) { + isc_result_t result; dns_fixedname_t fname; dns_name_t *name; - unsigned char digest[ISC_MAX_MD_SIZE]; unsigned int digestlen; isc_region_t r; - isc_buffer_t b; - dns_rdata_ds_t ds; isc_md_t *md; isc_md_type_t md_type = 0; - isc_result_t ret; REQUIRE(key != NULL); REQUIRE(key->type == dns_rdatatype_dnskey || @@ -73,51 +70,68 @@ dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key, name = dns_fixedname_initname(&fname); (void)dns_name_downcase(owner, name, NULL); - memset(buffer, 0, DNS_DS_BUFFERSIZE); - isc_buffer_init(&b, buffer, DNS_DS_BUFFERSIZE); - md = isc_md_new(); if (md == NULL) { return (ISC_R_NOMEMORY); } - ret = isc_md_init(md, md_type); - if (ret != ISC_R_SUCCESS) { + result = isc_md_init(md, md_type); + if (result != ISC_R_SUCCESS) { goto end; } dns_name_toregion(name, &r); - ret = isc_md_update(md, r.base, r.length); - if (ret != ISC_R_SUCCESS) { + result = isc_md_update(md, r.base, r.length); + if (result != ISC_R_SUCCESS) { goto end; } dns_rdata_toregion(key, &r); INSIST(r.length >= 4); - ret = isc_md_update(md, r.base, r.length); - if (ret != ISC_R_SUCCESS) { + result = isc_md_update(md, r.base, r.length); + if (result != ISC_R_SUCCESS) { goto end; } - ret = isc_md_final(md, digest, &digestlen); - if (ret != ISC_R_SUCCESS) { + result = isc_md_final(md, digest, &digestlen); + if (result != ISC_R_SUCCESS) { goto end; } - ds.mctx = NULL; - ds.common.rdclass = key->rdclass; - ds.common.rdtype = dns_rdatatype_ds; - ds.algorithm = r.base[3]; - ds.key_tag = dst_region_computeid(&r); - ds.digest_type = digest_type; - ds.digest = digest; - ds.length = digestlen; - - ret = dns_rdata_fromstruct(rdata, key->rdclass, dns_rdatatype_ds, - &ds, &b); + dsrdata->mctx = NULL; + dsrdata->common.rdclass = key->rdclass; + dsrdata->common.rdtype = dns_rdatatype_ds; + dsrdata->algorithm = r.base[3]; + dsrdata->key_tag = dst_region_computeid(&r); + dsrdata->digest_type = digest_type; + dsrdata->digest = digest; + dsrdata->length = digestlen; + end: isc_md_free(md); - return (ret); + return (result); +} + +isc_result_t +dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key, + dns_dsdigest_t digest_type, unsigned char *buffer, + dns_rdata_t *rdata) +{ + isc_result_t result; + unsigned char digest[ISC_MAX_MD_SIZE]; + dns_rdata_ds_t ds; + isc_buffer_t b; + + result = dns_ds_fromkeyrdata(owner, key, digest_type, digest, &ds); + if (result != ISC_R_SUCCESS) { + return (result); + } + + memset(buffer, 0, DNS_DS_BUFFERSIZE); + isc_buffer_init(&b, buffer, DNS_DS_BUFFERSIZE); + result = dns_rdata_fromstruct(rdata, key->rdclass, dns_rdatatype_ds, + &ds, &b); + return (result); } diff --git a/lib/dns/include/dns/ds.h b/lib/dns/include/dns/ds.h index a1df4a5d576..ae610dae823 100644 --- a/lib/dns/include/dns/ds.h +++ b/lib/dns/include/dns/ds.h @@ -15,6 +15,7 @@ #include +#include #include #define DNS_DSDIGEST_SHA1 (1) @@ -29,16 +30,30 @@ ISC_LANG_BEGINDECLS +isc_result_t +dns_ds_fromkeyrdata(dns_name_t *owner, dns_rdata_t *key, + dns_dsdigest_t digest_type, unsigned char *digest, + dns_rdata_ds_t *dsrdata); +/*%< + * Build a DS rdata structure from a key. + * + * Requires: + *\li key Points to a valid DNSKEY or CDNSKEY record. + *\li buffer Points to a buffer of at least + * #ISC_MAX_MD_SIZE bytes. + */ + isc_result_t dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key, dns_dsdigest_t digest_type, unsigned char *buffer, dns_rdata_t *rdata); /*%< - * Build the rdata of a DS record. + * Similar to dns_ds_fromkeyrdata(), but copies the DS into a + * dns_rdata object. * * Requires: *\li key Points to a valid DNSKEY or CDNSKEY record. - *\li buffer Points to a temporary buffer of at least + *\li buffer Points to a buffer of at least * #DNS_DS_BUFFERSIZE bytes. *\li rdata Points to an initialized dns_rdata_t. * diff --git a/lib/dns/include/dns/keytable.h b/lib/dns/include/dns/keytable.h index 4edba81a5b4..bf4c414d72f 100644 --- a/lib/dns/include/dns/keytable.h +++ b/lib/dns/include/dns/keytable.h @@ -106,13 +106,11 @@ dns_keytable_detach(dns_keytable_t **keytablep); */ isc_result_t -dns_keytable_add(dns_keytable_t *keytable, - bool managed, bool initial, - dns_name_t *name, dst_key_t **keyp, dns_rdata_ds_t *ds); +dns_keytable_add(dns_keytable_t *keytable, bool managed, bool initial, + dns_name_t *name, dns_rdata_ds_t *ds); /*%< * Add a key to 'keytable'. The keynode associated with 'name' - * is updated with either the key referenced in '*keyp' - * or with the DS specified in 'ds'. + * is updated with the DS specified in 'ds'. * * The value of keynode->managed is set to 'managed', and the * value of keynode->initial is set to 'initial'. (Note: 'initial' @@ -123,28 +121,15 @@ dns_keytable_add(dns_keytable_t *keytable, * * Notes: * - *\li Ownership of *keyp is transferred to the keytable. - *\li If 'keyp' is not NULL and DS-style keys already exist - * in the table for this name, they are freed before adding - * the new key. - *\li If 'ds' is not NULL and key-style keys already exist - * in the table for this name, return ISC_R_EXISTS. DS keys - * can be updated to key-style, but not vice versa. - *\li If the key already exists in the table, ISC_R_EXISTS is - * returned and the new key is freed. + *\li If the key already exists in the table, adding it again + * has no effect and ISC_R_SUCCESS is returned. * * Requires: * *\li 'keytable' points to a valid keytable. - * + *\li 'ds' is not NULL. *\li if 'initial' is true then 'managed' must also be true. * - *\li keyp != NULL && *keyp is a valid dst_key_t *. - * - * Ensures: - * - *\li On success, *keyp == NULL - * * Returns: * *\li ISC_R_SUCCESS diff --git a/lib/dns/keytable.c b/lib/dns/keytable.c index 2a65c7caaba..91afb052ddc 100644 --- a/lib/dns/keytable.c +++ b/lib/dns/keytable.c @@ -364,14 +364,12 @@ insert(dns_keytable_t *keytable, bool managed, bool initial, } isc_result_t -dns_keytable_add(dns_keytable_t *keytable, - bool managed, bool initial, - dns_name_t *name, dst_key_t **keyp, dns_rdata_ds_t *ds) +dns_keytable_add(dns_keytable_t *keytable, bool managed, bool initial, + dns_name_t *name, dns_rdata_ds_t *ds) { - REQUIRE(keyp == NULL || *keyp != NULL); - REQUIRE(keyp != NULL || ds != NULL); + REQUIRE(ds != NULL); REQUIRE(!initial || managed); - return (insert(keytable, managed, initial, name, keyp, ds)); + return (insert(keytable, managed, initial, name, NULL, ds)); } isc_result_t diff --git a/lib/dns/tests/keytable_test.c b/lib/dns/tests/keytable_test.c index ac3066eafdb..3f5d2eb2102 100644 --- a/lib/dns/tests/keytable_test.c +++ b/lib/dns/tests/keytable_test.c @@ -27,11 +27,12 @@ #include #include +#include #include -#include #include #include +#include #include #include #include @@ -129,44 +130,48 @@ create_keystruct(uint16_t flags, uint8_t proto, uint8_t alg, } static void -create_key(uint16_t flags, uint8_t proto, uint8_t alg, - const char *keynamestr, const char *keystr, dst_key_t **target) +create_dsstruct(dns_name_t *name, uint16_t flags, + uint8_t proto, uint8_t alg, const char *keystr, + unsigned char *digest, dns_rdata_ds_t *dsstruct) { isc_result_t result; - dns_rdata_dnskey_t keystruct; unsigned char rrdata[4096]; isc_buffer_t rrdatabuf; - const dns_rdataclass_t rdclass = dns_rdataclass_in; + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_dnskey_t dnskey; /* * Populate DNSKEY rdata structure. */ - create_keystruct(flags, proto, alg, keystr, &keystruct); + create_keystruct(flags, proto, alg, keystr, &dnskey); /* * Convert to wire format. */ isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); - result = dns_rdata_fromstruct(NULL, keystruct.common.rdclass, - keystruct.common.rdtype, - &keystruct, &rrdatabuf), + result = dns_rdata_fromstruct(&rdata, dnskey.common.rdclass, + dnskey.common.rdtype, + &dnskey, &rrdatabuf); assert_int_equal(result, ISC_R_SUCCESS); /* - * Convert wire format to DST key. + * Build DS rdata struct. */ - result = dst_key_fromdns(str2name(keynamestr), rdclass, - &rrdatabuf, dt_mctx, target), + result = dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256, + digest, dsstruct); assert_int_equal(result, ISC_R_SUCCESS); - dns_rdata_freestruct(&keystruct); + dns_rdata_freestruct(&dnskey); } /* Common setup: create a keytable and ntatable to test with a few keys */ static void create_tables() { isc_result_t result; - dst_key_t *key = NULL; + unsigned char digest[ISC_MAX_MD_SIZE]; + dns_rdata_ds_t ds; + dns_fixedname_t fn; + dns_name_t *keyname = dns_fixedname_name(&fn); isc_stdtime_t now; result = dns_test_makeview("view", &view); @@ -178,15 +183,15 @@ create_tables() { &ntatable), ISC_R_SUCCESS); /* Add a normal key */ - create_key(257, 3, 5, "example.com", keystr1, &key); - assert_int_equal(dns_keytable_add(keytable, false, false, - dst_key_name(key), &key, NULL), + dns_test_namefromstring("example.com", &fn); + create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds); + assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds), ISC_R_SUCCESS); /* Add an initializing managed key */ - create_key(257, 3, 5, "managed.com", keystr1, &key); - assert_int_equal(dns_keytable_add(keytable, true, true, - dst_key_name(key), &key, NULL), + dns_test_namefromstring("managed.com", &fn); + create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds); + assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds), ISC_R_SUCCESS); /* Add a null key */ @@ -217,9 +222,12 @@ destroy_tables() { /* add keys to the keytable */ static void add_test(void **state) { - dst_key_t *key = NULL; dns_keynode_t *keynode = NULL; dns_keynode_t *null_keynode = NULL; + unsigned char digest[ISC_MAX_MD_SIZE]; + dns_rdata_ds_t ds; + dns_fixedname_t fn; + dns_name_t *keyname = dns_fixedname_name(&fn); UNUSED(state); @@ -236,9 +244,9 @@ add_test(void **state) { * Try to add the same key. This should have no effect but * report success. */ - create_key(257, 3, 5, "example.com", keystr1, &key); - assert_int_equal(dns_keytable_add(keytable, false, false, - dst_key_name(key), &key, NULL), + dns_test_namefromstring("example.com", &fn); + create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds); + assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds), ISC_R_SUCCESS); dns_keytable_detachkeynode(keytable, &keynode); assert_int_equal(dns_keytable_find(keytable, str2name("example.com"), @@ -247,9 +255,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, - dst_key_name(key), &key, NULL), + create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds); + assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds), ISC_R_SUCCESS); assert_int_equal(dns_keytable_find(keytable, str2name("example.com"), &keynode), @@ -273,9 +280,9 @@ add_test(void **state) { * Add a different managed key for managed.com, marking it as an * initializing key. */ - create_key(257, 3, 5, "managed.com", keystr2, &key); - assert_int_equal(dns_keytable_add(keytable, true, true, - dst_key_name(key), &key, NULL), + dns_test_namefromstring("managed.com", &fn); + create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds); + assert_int_equal(dns_keytable_add(keytable, true, true, keyname, &ds), ISC_R_SUCCESS); assert_int_equal(dns_keytable_find(keytable, str2name("managed.com"), &keynode), @@ -289,9 +296,7 @@ add_test(void **state) { * to a non-initializing key and make sure there are still two key * nodes for managed.com, both containing non-initializing keys. */ - create_key(257, 3, 5, "managed.com", keystr2, &key); - assert_int_equal(dns_keytable_add(keytable, true, false, - dst_key_name(key), &key, NULL), + assert_int_equal(dns_keytable_add(keytable, true, false, keyname, &ds), ISC_R_SUCCESS); assert_int_equal(dns_keytable_find(keytable, str2name("managed.com"), &keynode), @@ -303,9 +308,9 @@ add_test(void **state) { * Add a managed key at a new node, two.com, marking it as an * initializing key. */ - create_key(257, 3, 5, "two.com", keystr1, &key); - assert_int_equal(dns_keytable_add(keytable, true, true, - dst_key_name(key), &key, NULL), + dns_test_namefromstring("two.com", &fn); + create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds); + assert_int_equal(dns_keytable_add(keytable, true, true, keyname, &ds), ISC_R_SUCCESS); assert_int_equal(dns_keytable_find(keytable, str2name("two.com"), &keynode), @@ -317,9 +322,8 @@ add_test(void **state) { * Add a different managed key for two.com, marking it as a * non-initializing key. */ - create_key(257, 3, 5, "two.com", keystr2, &key); - assert_int_equal(dns_keytable_add(keytable, true, false, - dst_key_name(key), &key, NULL), + create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds); + assert_int_equal(dns_keytable_add(keytable, true, false, keyname, &ds), ISC_R_SUCCESS); assert_int_equal(dns_keytable_find(keytable, str2name("two.com"), &keynode), @@ -333,9 +337,8 @@ add_test(void **state) { * to a non-initializing key and make sure there are still two key * nodes for two.com, both containing non-initializing keys. */ - create_key(257, 3, 5, "two.com", keystr1, &key); - assert_int_equal(dns_keytable_add(keytable, true, false, - dst_key_name(key), &key, NULL), + create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds); + assert_int_equal(dns_keytable_add(keytable, true, false, keyname, &ds), ISC_R_SUCCESS); assert_int_equal(dns_keytable_find(keytable, str2name("two.com"), &keynode), @@ -350,9 +353,9 @@ add_test(void **state) { assert_int_equal(dns_keytable_find(keytable, str2name("null.example"), &null_keynode), ISC_R_SUCCESS); - create_key(257, 3, 5, "null.example", keystr2, &key); - assert_int_equal(dns_keytable_add(keytable, false, false, - dst_key_name(key), &key, NULL), + dns_test_namefromstring("null.example", &fn); + create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds); + assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds), ISC_R_SUCCESS); assert_int_equal(dns_keytable_find(keytable, str2name("null.example"), &keynode), @@ -595,8 +598,11 @@ dump_test(void **state) { static void nta_test(void **state) { isc_result_t result; - dst_key_t *key = NULL; bool issecure, covered; + dns_fixedname_t fn; + dns_name_t *keyname = dns_fixedname_name(&fn); + unsigned char digest[ISC_MAX_MD_SIZE]; + dns_rdata_ds_t ds; dns_view_t *myview = NULL; isc_stdtime_t now; @@ -618,14 +624,13 @@ nta_test(void **state) { result = dns_view_getntatable(myview, &ntatable); assert_int_equal(result, ISC_R_SUCCESS); - create_key(257, 3, 5, "example", keystr1, &key); - result = dns_keytable_add(keytable, false, false, - dst_key_name(key), &key, NULL), + dns_test_namefromstring("example", &fn); + create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds); + result = dns_keytable_add(keytable, false, false, keyname, &ds), assert_int_equal(result, ISC_R_SUCCESS); isc_stdtime_get(&now); - result = dns_ntatable_add(ntatable, - str2name("insecure.example"), + result = dns_ntatable_add(ntatable, str2name("insecure.example"), false, now, 1); assert_int_equal(result, ISC_R_SUCCESS); diff --git a/lib/dns/win32/libdns.def.in b/lib/dns/win32/libdns.def.in index 42e8ab222af..3de3985573a 100644 --- a/lib/dns/win32/libdns.def.in +++ b/lib/dns/win32/libdns.def.in @@ -336,6 +336,7 @@ dns_dnssecsignstats_create dns_dnssecsignstats_dump dns_dnssecsignstats_increment dns_ds_buildrdata +dns_ds_fromkeyrdata dns_dsdigest_format dns_dsdigest_fromtext dns_dsdigest_totext diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 80e3085a451..f7de8e7fdf7 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -3942,35 +3943,34 @@ compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx, */ static void trust_key(dns_zone_t *zone, dns_name_t *keyname, - dns_rdata_dnskey_t *dnskey, bool initial, - isc_mem_t *mctx) + dns_rdata_dnskey_t *dnskey, bool initial) { isc_result_t result; dns_rdata_t rdata = DNS_RDATA_INIT; - unsigned char data[4096]; + unsigned char data[4096], digest[ISC_MAX_MD_SIZE]; isc_buffer_t buffer; dns_keytable_t *sr = NULL; - dst_key_t *dstkey = NULL; + dns_rdata_ds_t ds; + + result = dns_view_getsecroots(zone->view, &sr); + if (result != ISC_R_SUCCESS) { + return; + } - /* Convert dnskey to DST key. */ + /* Build DS record for key. */ isc_buffer_init(&buffer, data, sizeof(data)); dns_rdata_fromstruct(&rdata, dnskey->common.rdclass, dns_rdatatype_dnskey, dnskey, &buffer); + CHECK(dns_ds_fromkeyrdata(keyname, &rdata, DNS_DSDIGEST_SHA256, + digest, &ds)); + CHECK(dns_keytable_add(sr, true, initial, keyname, &ds)); - result = dns_view_getsecroots(zone->view, &sr); - if (result != ISC_R_SUCCESS) - goto failure; - - CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey)); - CHECK(dns_keytable_add(sr, true, initial, - dst_key_name(dstkey), &dstkey, NULL)); dns_keytable_detach(&sr); failure: - if (dstkey != NULL) - dst_key_free(&dstkey); - if (sr != NULL) + if (sr != NULL) { dns_keytable_detach(&sr); + } return; } @@ -4000,7 +4000,6 @@ load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) { dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_keydata_t keydata; dns_rdata_dnskey_t dnskey; - isc_mem_t *mctx = zone->mctx; int trusted = 0, revoked = 0, pending = 0; isc_stdtime_t now; dns_keytable_t *sr = NULL; @@ -4051,7 +4050,7 @@ load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) { /* Add to keytables. */ trusted++; - trust_key(zone, name, &dnskey, (keydata.addhd == 0), mctx); + trust_key(zone, name, &dnskey, (keydata.addhd == 0)); } if (trusted == 0 && pending != 0) { @@ -10271,7 +10270,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { /* Trust this key. */ result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); - trust_key(zone, keyname, &dnskey, false, mctx); + trust_key(zone, keyname, &dnskey, false); } if (secure && !deletekey) {