]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Don't trust a placeholder KEYDATA record
authorAram Sargsyan <aram@isc.org>
Mon, 31 Oct 2022 12:49:05 +0000 (12:49 +0000)
committerAram Sargsyan <aram@isc.org>
Tue, 1 Nov 2022 10:55:38 +0000 (10:55 +0000)
When named starts it creates an empty KEYDATA record in the managed-keys
zone as a placeholder, then schedules a key refresh. If key refresh
fails for some reason (e.g. connectivity problems), named will load the
placeholder key into secroots as a trusted key during the next startup,
which will break the chain of trust, and named will never recover from
that state until managed-keys.bind and managed-keys.bind.jnl files are
manually deleted before (re)starting named again.

Before calling load_secroots(), check that we are not dealing with a
placeholder.

(cherry picked from commit 354ae2d7e3ad9e069d5104de5b454651829bdc88)

lib/dns/zone.c

index c25c055caae7e7003e32f48eed2f8f7f22476cea..9a248ff318767bdf4498615624410be013b60cae 100644 (file)
@@ -4645,9 +4645,15 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
             result = dns_rriterator_nextrrset(&rrit))
        {
                dns_rdataset_t *rdataset = NULL;
+               dns_rdata_t rdata = DNS_RDATA_INIT;
+               dns_rdata_keydata_t keydata;
+               isc_stdtime_t now;
+               bool load = true;
                dns_name_t *rrname = NULL;
                uint32_t ttl;
 
+               isc_stdtime_get(&now);
+
                dns_rriterator_current(&rrit, &rrname, &ttl, &rdataset, NULL);
                if (!dns_rdataset_isassociated(rdataset)) {
                        dns_rriterator_destroy(&rrit);
@@ -4657,6 +4663,31 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
                if (rdataset->type != dns_rdatatype_keydata) {
                        continue;
                }
+
+               /*
+                * The managed-keys zone can contain a placeholder instead of
+                * legitimate data, in which case we will not use it, and we
+                * will try to refresh it.
+                */
+               for (result = dns_rdataset_first(rdataset);
+                    result == ISC_R_SUCCESS;
+                    result = dns_rdataset_next(rdataset))
+               {
+                       isc_result_t iresult;
+
+                       dns_rdata_reset(&rdata);
+                       dns_rdataset_current(rdataset, &rdata);
+
+                       iresult = dns_rdata_tostruct(&rdata, &keydata, NULL);
+                       /* Do we have a valid placeholder KEYDATA record? */
+                       if (iresult == ISC_R_SUCCESS && keydata.flags == 0 &&
+                           keydata.protocol == 0 && keydata.algorithm == 0)
+                       {
+                               set_refreshkeytimer(zone, &keydata, now, true);
+                               load = false;
+                       }
+               }
+
                /*
                 * Release db wrlock to prevent LOR reports against
                 * dns_keytable_forall() call below.
@@ -4666,7 +4697,7 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
                if (result != ISC_R_SUCCESS || !dns_keynode_managed(keynode)) {
                        CHECK(delete_keydata(db, ver, &diff, rrname, rdataset));
                        changed = true;
-               } else {
+               } else if (load) {
                        load_secroots(zone, rrname, rdataset);
                }