diff --git a/bin/named/server.c b/bin/named/server.c index 73dcdacbb1..552434379e 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -876,6 +876,13 @@ cleanup: return (result); } +static void +sfd_add(const dns_name_t *name, void *arg) { + if (arg != NULL) { + dns_view_sfd_add(arg, name); + } +} + /*% * Parse 'key' in the context of view configuration 'vconfig'. If successful, * add the key to 'secroots' if both of the following conditions are true: @@ -889,8 +896,7 @@ cleanup: */ 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) { + const dns_name_t *keyname_match, dns_view_t *view, bool managed) { dns_fixedname_t fkeyname; dns_name_t *keyname = NULL; const char *namestr = NULL; @@ -963,8 +969,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, ds.algorithm)) - { + if (!dns_resolver_algorithm_supported(view->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", @@ -980,7 +986,7 @@ 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, keyname, - &ds); + &ds, sfd_add, view); done: return (result); @@ -1008,7 +1014,7 @@ load_view_keys(const cfg_obj_t *keys, dns_view_t *view, bool managed, for (elt2 = cfg_list_first(keylist); elt2 != NULL; elt2 = cfg_list_next(elt2)) { CHECK(process_key(cfg_listelt_value(elt2), secroots, - keyname, view->resolver, managed)); + keyname, view, managed)); } } diff --git a/lib/dns/client.c b/lib/dns/client.c index 4385aa1db4..bf8d69c559 100644 --- a/lib/dns/client.c +++ b/lib/dns/client.c @@ -1311,7 +1311,7 @@ dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass, digest, &ds)); } - CHECK(dns_keytable_add(secroots, false, false, name, &ds)); + CHECK(dns_keytable_add(secroots, false, false, name, &ds, NULL, NULL)); cleanup: if (view != NULL) { diff --git a/lib/dns/include/dns/keytable.h b/lib/dns/include/dns/keytable.h index 94db94658c..6095a85e3f 100644 --- a/lib/dns/include/dns/keytable.h +++ b/lib/dns/include/dns/keytable.h @@ -49,6 +49,8 @@ ISC_LANG_BEGINDECLS +typedef void (*dns_keytable_callback_t)(const dns_name_t *name, void *fn_arg); + isc_result_t dns_keytable_create(isc_mem_t *mctx, dns_keytable_t **keytablep); /*%< @@ -106,7 +108,8 @@ 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, dns_rdata_ds_t *ds); + dns_name_t *name, dns_rdata_ds_t *ds, + dns_keytable_callback_t callback, void *callback_arg); /*%< * Add a key to 'keytable'. The keynode associated with 'name' * is updated with the DS specified in 'ds'. @@ -167,7 +170,8 @@ dns_keytable_marksecure(dns_keytable_t *keytable, const dns_name_t *name); */ isc_result_t -dns_keytable_delete(dns_keytable_t *keytable, const dns_name_t *keyname); +dns_keytable_delete(dns_keytable_t *keytable, const dns_name_t *keyname, + dns_keytable_callback_t callback, void *callback_arg); /*%< * Delete all trust anchors from 'keytable' matching name 'keyname' * diff --git a/lib/dns/keytable.c b/lib/dns/keytable.c index 324b4efc53..9172d51dd0 100644 --- a/lib/dns/keytable.c +++ b/lib/dns/keytable.c @@ -367,7 +367,8 @@ new_keynode(dns_rdata_ds_t *ds, dns_keytable_t *keytable, bool managed, */ static isc_result_t insert(dns_keytable_t *keytable, bool managed, bool initial, - const dns_name_t *keyname, dns_rdata_ds_t *ds) { + const dns_name_t *keyname, dns_rdata_ds_t *ds, + dns_keytable_callback_t callback, void *callback_arg) { dns_rbtnode_t *node = NULL; isc_result_t result; @@ -384,6 +385,9 @@ insert(dns_keytable_t *keytable, bool managed, bool initial, * and attach it to the created node. */ node->data = new_keynode(ds, keytable, managed, initial); + if (callback != NULL) { + (*callback)(keyname, callback_arg); + } } else if (result == ISC_R_EXISTS) { /* * A node already exists for "keyname" in "keytable". @@ -393,6 +397,9 @@ insert(dns_keytable_t *keytable, bool managed, bool initial, if (knode == NULL) { node->data = new_keynode(ds, keytable, managed, initial); + if (callback != NULL) { + (*callback)(keyname, callback_arg); + } } else { add_ds(knode, ds, keytable->mctx); } @@ -407,20 +414,23 @@ 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, dns_rdata_ds_t *ds) { + dns_name_t *name, dns_rdata_ds_t *ds, + dns_keytable_callback_t callback, void *callback_arg) { REQUIRE(ds != NULL); REQUIRE(!initial || managed); - return (insert(keytable, managed, initial, name, ds)); + return (insert(keytable, managed, initial, name, ds, callback, + callback_arg)); } 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, NULL)); } isc_result_t -dns_keytable_delete(dns_keytable_t *keytable, const dns_name_t *keyname) { +dns_keytable_delete(dns_keytable_t *keytable, const dns_name_t *keyname, + dns_keytable_callback_t callback, void *callback_arg) { isc_result_t result; dns_rbtnode_t *node = NULL; @@ -434,6 +444,9 @@ dns_keytable_delete(dns_keytable_t *keytable, const dns_name_t *keyname) { if (node->data != NULL) { result = dns_rbt_deletenode(keytable->table, node, false); + if (callback != NULL) { + (*callback)(keyname, callback_arg); + } } else { result = ISC_R_NOTFOUND; } diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 03b3e26d78..6796f8b499 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -4282,6 +4282,23 @@ compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx, return (result); } +/* + * Synth-from-dnssec callbacks to add/delete names from namespace tree. + */ +static void +sfd_add(const dns_name_t *name, void *arg) { + if (arg != NULL) { + dns_view_sfd_add(arg, name); + } +} + +static void +sfd_del(const dns_name_t *name, void *arg) { + if (arg != NULL) { + dns_view_sfd_del(arg, name); + } +} + /* * Add key to the security roots. */ @@ -4306,7 +4323,8 @@ trust_key(dns_zone_t *zone, dns_name_t *keyname, dns_rdata_dnskey_t *dnskey, 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)); + CHECK(dns_keytable_add(sr, true, initial, keyname, &ds, sfd_add, + zone->view)); dns_keytable_detach(&sr); @@ -4351,7 +4369,7 @@ load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) { result = dns_view_getsecroots(zone->view, &sr); if (result == ISC_R_SUCCESS) { - dns_keytable_delete(sr, name); + dns_keytable_delete(sr, name, sfd_del, zone->view); dns_keytable_detach(&sr); } diff --git a/tests/dns/keytable_test.c b/tests/dns/keytable_test.c index 0afb6bf68a..615f90eaab 100644 --- a/tests/dns/keytable_test.c +++ b/tests/dns/keytable_test.c @@ -152,15 +152,14 @@ create_dsstruct(dns_name_t *name, uint16_t flags, uint8_t proto, uint8_t alg, /* Common setup: create a keytable and ntatable to test with a few keys */ static void create_tables(void) { - isc_result_t result; 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", false, &view); - assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(dns_test_makeview("view", false, &view), + ISC_R_SUCCESS); assert_int_equal(dns_keytable_create(mctx, &keytable), ISC_R_SUCCESS); assert_int_equal( @@ -170,19 +169,21 @@ create_tables(void) { /* Add a normal key */ 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), + assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds, + NULL, NULL), ISC_R_SUCCESS); /* Add an initializing managed key */ dns_test_namefromstring("managed.com", &fn); create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds); - assert_int_equal(dns_keytable_add(keytable, true, true, keyname, &ds), + assert_int_equal(dns_keytable_add(keytable, true, true, keyname, &ds, + NULL, NULL), ISC_R_SUCCESS); /* Add a null key */ - assert_int_equal(dns_keytable_marksecure(keytable, str2name("null." - "example")), - ISC_R_SUCCESS); + assert_int_equal( + dns_keytable_marksecure(keytable, str2name("null.example")), + ISC_R_SUCCESS); /* Add a negative trust anchor, duration 1 hour */ isc_stdtime_get(&now); @@ -230,7 +231,8 @@ ISC_RUN_TEST_IMPL(dns_keytable_add) { */ 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), + assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds, + NULL, NULL), ISC_R_SUCCESS); dns_keytable_detachkeynode(keytable, &keynode); assert_int_equal( @@ -240,7 +242,8 @@ ISC_RUN_TEST_IMPL(dns_keytable_add) { /* Add another key (different keydata) */ dns_keytable_detachkeynode(keytable, &keynode); create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds); - assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds), + assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds, + NULL, NULL), ISC_R_SUCCESS); assert_int_equal( dns_keytable_find(keytable, str2name("example.com"), &keynode), @@ -267,7 +270,8 @@ ISC_RUN_TEST_IMPL(dns_keytable_add) { */ 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), + assert_int_equal(dns_keytable_add(keytable, true, true, keyname, &ds, + NULL, NULL), ISC_R_SUCCESS); assert_int_equal( dns_keytable_find(keytable, str2name("managed.com"), &keynode), @@ -281,7 +285,8 @@ ISC_RUN_TEST_IMPL(dns_keytable_add) { * to a non-initializing key and make sure there are still two key * nodes for managed.com, both containing non-initializing keys. */ - assert_int_equal(dns_keytable_add(keytable, true, false, keyname, &ds), + assert_int_equal(dns_keytable_add(keytable, true, false, keyname, &ds, + NULL, NULL), ISC_R_SUCCESS); assert_int_equal( dns_keytable_find(keytable, str2name("managed.com"), &keynode), @@ -295,7 +300,8 @@ ISC_RUN_TEST_IMPL(dns_keytable_add) { */ 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), + assert_int_equal(dns_keytable_add(keytable, true, true, keyname, &ds, + NULL, NULL), ISC_R_SUCCESS); assert_int_equal( dns_keytable_find(keytable, str2name("two.com"), &keynode), @@ -310,7 +316,8 @@ ISC_RUN_TEST_IMPL(dns_keytable_add) { * the initialization status should not change. */ create_dsstruct(keyname, 257, 3, 5, keystr2, digest, &ds); - assert_int_equal(dns_keytable_add(keytable, true, false, keyname, &ds), + assert_int_equal(dns_keytable_add(keytable, true, false, keyname, &ds, + NULL, NULL), ISC_R_SUCCESS); assert_int_equal( dns_keytable_find(keytable, str2name("two.com"), &keynode), @@ -327,7 +334,8 @@ ISC_RUN_TEST_IMPL(dns_keytable_add) { ISC_R_SUCCESS); 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), + assert_int_equal(dns_keytable_add(keytable, false, false, keyname, &ds, + NULL, NULL), ISC_R_SUCCESS); assert_int_equal( dns_keytable_find(keytable, str2name("null.example"), &keynode), @@ -341,9 +349,9 @@ ISC_RUN_TEST_IMPL(dns_keytable_add) { * (Note: this and above checks confirm that if a name has a null key * that's the only key for the name). */ - assert_int_equal(dns_keytable_marksecure(keytable, str2name("null." - "example")), - ISC_R_SUCCESS); + assert_int_equal( + dns_keytable_marksecure(keytable, str2name("null.example")), + ISC_R_SUCCESS); assert_int_equal(dns_keytable_find(keytable, str2name("null.example"), &null_keynode), ISC_R_SUCCESS); @@ -359,23 +367,26 @@ ISC_RUN_TEST_IMPL(dns_keytable_delete) { create_tables(); /* dns_keytable_delete requires exact match */ - assert_int_equal(dns_keytable_delete(keytable, str2name("example.org")), + assert_int_equal(dns_keytable_delete(keytable, str2name("example.org"), + NULL, NULL), ISC_R_NOTFOUND); - assert_int_equal(dns_keytable_delete(keytable, str2name("s.example." - "com")), + assert_int_equal(dns_keytable_delete(keytable, + str2name("s.example.com"), NULL, + NULL), ISC_R_NOTFOUND); - assert_int_equal(dns_keytable_delete(keytable, str2name("example.com")), + assert_int_equal(dns_keytable_delete(keytable, str2name("example.com"), + NULL, NULL), ISC_R_SUCCESS); /* works also for nodes with a null key */ - assert_int_equal(dns_keytable_delete(keytable, str2name("null." - "example")), + assert_int_equal(dns_keytable_delete(keytable, str2name("null.example"), + NULL, NULL), ISC_R_SUCCESS); /* or a negative trust anchor */ - assert_int_equal(dns_ntatable_delete(ntatable, str2name("insecure." - "example")), - ISC_R_SUCCESS); + assert_int_equal( + dns_ntatable_delete(ntatable, str2name("insecure.example")), + ISC_R_SUCCESS); destroy_tables(); } @@ -426,7 +437,8 @@ ISC_RUN_TEST_IMPL(dns_keytable_deletekey) { * after deleting the node, any deletekey or delete attempt should * result in NOTFOUND. */ - assert_int_equal(dns_keytable_delete(keytable, keyname), ISC_R_SUCCESS); + assert_int_equal(dns_keytable_delete(keytable, keyname, NULL, NULL), + ISC_R_SUCCESS); assert_int_equal(dns_keytable_deletekey(keytable, keyname, &dnskey), ISC_R_NOTFOUND); dns_rdata_freestruct(&dnskey); @@ -439,7 +451,8 @@ ISC_RUN_TEST_IMPL(dns_keytable_deletekey) { create_keystruct(257, 3, 5, keystr1, &dnskey); assert_int_equal(dns_keytable_deletekey(keytable, keyname, &dnskey), DNS_R_PARTIALMATCH); - assert_int_equal(dns_keytable_delete(keytable, keyname), ISC_R_SUCCESS); + assert_int_equal(dns_keytable_delete(keytable, keyname, NULL, NULL), + ISC_R_SUCCESS); dns_rdata_freestruct(&dnskey); destroy_tables(); @@ -585,7 +598,8 @@ ISC_RUN_TEST_IMPL(dns_keytable_nta) { dns_test_namefromstring("example", &fn); create_dsstruct(keyname, 257, 3, 5, keystr1, digest, &ds); - result = dns_keytable_add(keytable, false, false, keyname, &ds), + result = dns_keytable_add(keytable, false, false, keyname, &ds, NULL, + NULL), assert_int_equal(result, ISC_R_SUCCESS); isc_stdtime_get(&now);