]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
The dsset returned by dns_keynode_dsset needs to be thread safe.
authorMark Andrews <marka@isc.org>
Wed, 10 Jun 2020 07:07:52 +0000 (17:07 +1000)
committerMark Andrews <marka@isc.org>
Thu, 11 Jun 2020 06:02:09 +0000 (16:02 +1000)
- clone keynode->dsset rather than return a pointer so that thread
  use is independent of each other.
- hold a reference to the dsset (keynode) so it can't be deleted
  while in use.
- create a new keynode when removing DS records so that dangling
  pointers to the deleted records will not occur.
- use a rwlock when accessing the rdatalist to prevent instabilities
  when DS records are added.

bin/named/server.c
lib/dns/include/dns/keytable.h
lib/dns/include/dns/validator.h
lib/dns/keytable.c
lib/dns/validator.c
lib/dns/zone.c
lib/dns/zoneverify.c
lib/ns/query.c

index 892b497a0d7c2bdac3171be1369e733f864e1fdc..c6d8238ac6f58e433d67c06492f5d813ccfb9280 100644 (file)
@@ -6937,24 +6937,26 @@ struct dotat_arg {
  */
 static isc_result_t
 get_tat_qname(dns_name_t *target, dns_name_t *keyname, dns_keynode_t *keynode) {
-       dns_rdataset_t *dsset = NULL;
+       dns_rdataset_t dsset;
        unsigned int i, n = 0;
        uint16_t ids[12];
        isc_textregion_t r;
        char label[64];
        int m;
 
-       if ((dsset = dns_keynode_dsset(keynode)) != NULL) {
+       dns_rdataset_init(&dsset);
+       if (dns_keynode_dsset(keynode, &dsset)) {
                isc_result_t result;
 
-               for (result = dns_rdataset_first(dsset);
-                    result == ISC_R_SUCCESS; result = dns_rdataset_next(dsset))
+               for (result = dns_rdataset_first(&dsset);
+                    result == ISC_R_SUCCESS;
+                    result = dns_rdataset_next(&dsset))
                {
                        dns_rdata_t rdata = DNS_RDATA_INIT;
                        dns_rdata_ds_t ds;
 
                        dns_rdata_reset(&rdata);
-                       dns_rdataset_current(dsset, &rdata);
+                       dns_rdataset_current(&dsset, &rdata);
                        result = dns_rdata_tostruct(&rdata, &ds, NULL);
                        RUNTIME_CHECK(result == ISC_R_SUCCESS);
                        if (n < (sizeof(ids) / sizeof(ids[0]))) {
@@ -6962,6 +6964,7 @@ get_tat_qname(dns_name_t *target, dns_name_t *keyname, dns_keynode_t *keynode) {
                                n++;
                        }
                }
+               dns_rdataset_disassociate(&dsset);
        }
 
        if (n == 0) {
index c7ba60107794a5d7bfc40497909533a0177d869c..3798c0db3a664724d8cba72fd6d10b404b4183c2 100644 (file)
@@ -303,17 +303,20 @@ dns_keytable_totext(dns_keytable_t *keytable, isc_buffer_t **buf);
  * Dump the keytable to buffer at 'buf'
  */
 
-dns_rdataset_t *
-dns_keynode_dsset(dns_keynode_t *keynode);
+bool
+dns_keynode_dsset(dns_keynode_t *keynode, dns_rdataset_t *rdataset);
 /*%<
- * Return a pointer to the DS RRset associated with 'keynode'.
+ * Clone the DS RRset associated with 'keynode' into 'rdataset' if
+ * it exists.  'dns_rdataset_disassociate(rdataset)' needs to be
+ * called when done.
  *
  * Returns:
- *\li  ISC_R_SUCCESS
- *\li  ISC_R_FAILURE if the keynode does not contain a DS trust anchor.
+ *\li  true if there is a DS RRset.
+ *\li  false if there isn't DS RRset.
  *
  * Requires:
  *\li  'keynode' is valid.
+ *\li  'rdataset' is valid or NULL.
  */
 
 bool
index 5959e008db31cb1095a4532eb1c495e4e6f1eb41..9c743207bd3d5e0f7537a7d26acda3fd43a1eaab 100644 (file)
@@ -137,6 +137,7 @@ struct dns_validator {
        dns_rdataset_t *      currentset;
        dns_rdataset_t *      keyset;
        dns_rdataset_t *      dsset;
+       dns_rdataset_t        fdsset;
        dns_rdataset_t        frdataset;
        dns_rdataset_t        fsigrdataset;
        dns_fixedname_t       fname;
index 75654a7dc53fcc6c905e690b07cd78006b62c964..820261987e827986b59087092541919a24b22869 100644 (file)
@@ -48,13 +48,49 @@ struct dns_keytable {
 
 struct dns_keynode {
        unsigned int magic;
+       isc_mem_t *mctx;
        isc_refcount_t refcount;
+       isc_rwlock_t rwlock;
        dns_rdatalist_t *dslist;
        dns_rdataset_t dsset;
        bool managed;
        bool initial;
 };
 
+static dns_keynode_t *
+new_keynode(dns_rdata_ds_t *ds, dns_keytable_t *keytable, bool managed,
+           bool initial);
+
+static void
+keynode_disassociate(dns_rdataset_t *rdataset);
+static isc_result_t
+keynode_first(dns_rdataset_t *rdataset);
+static isc_result_t
+keynode_next(dns_rdataset_t *rdataset);
+static void
+keynode_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata);
+static void
+keynode_clone(dns_rdataset_t *source, dns_rdataset_t *target);
+
+static dns_rdatasetmethods_t methods = {
+       keynode_disassociate,
+       keynode_first,
+       keynode_next,
+       keynode_current,
+       keynode_clone,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL, /* settrust */
+       NULL, /* expire */
+       NULL, /* clearprefetch */
+       NULL,
+       NULL,
+       NULL /* addglue */
+};
+
 static void
 keynode_attach(dns_keynode_t *source, dns_keynode_t **target) {
        REQUIRE(VALID_KEYNODE(source));
@@ -71,11 +107,8 @@ keynode_detach(isc_mem_t *mctx, dns_keynode_t **keynodep) {
        if (isc_refcount_decrement(&knode->refcount) == 1) {
                dns_rdata_t *rdata = NULL;
                isc_refcount_destroy(&knode->refcount);
+               isc_rwlock_destroy(&knode->rwlock);
                if (knode->dslist != NULL) {
-                       if (dns_rdataset_isassociated(&knode->dsset)) {
-                               dns_rdataset_disassociate(&knode->dsset);
-                       }
-
                        for (rdata = ISC_LIST_HEAD(knode->dslist->rdata);
                             rdata != NULL;
                             rdata = ISC_LIST_HEAD(knode->dslist->rdata))
@@ -91,7 +124,8 @@ keynode_detach(isc_mem_t *mctx, dns_keynode_t **keynodep) {
                                    sizeof(*knode->dslist));
                        knode->dslist = NULL;
                }
-               isc_mem_put(mctx, knode, sizeof(dns_keynode_t));
+               isc_mem_putanddetach(&knode->mctx, knode,
+                                    sizeof(dns_keynode_t));
        }
 }
 
@@ -171,7 +205,7 @@ dns_keytable_detach(dns_keytable_t **keytablep) {
        }
 }
 
-static isc_result_t
+static void
 add_ds(dns_keynode_t *knode, dns_rdata_ds_t *ds, isc_mem_t *mctx) {
        isc_result_t result;
        dns_rdata_t *dsrdata = NULL, *rdata = NULL;
@@ -179,13 +213,6 @@ add_ds(dns_keynode_t *knode, dns_rdata_ds_t *ds, isc_mem_t *mctx) {
        bool exists = false;
        isc_buffer_t b;
 
-       if (knode->dslist == NULL) {
-               knode->dslist = isc_mem_get(mctx, sizeof(*knode->dslist));
-               dns_rdatalist_init(knode->dslist);
-               knode->dslist->rdclass = dns_rdataclass_in;
-               knode->dslist->type = dns_rdatatype_ds;
-       }
-
        dsrdata = isc_mem_get(mctx, sizeof(*dsrdata));
        dns_rdata_init(dsrdata);
 
@@ -194,8 +221,28 @@ add_ds(dns_keynode_t *knode, dns_rdata_ds_t *ds, isc_mem_t *mctx) {
 
        result = dns_rdata_fromstruct(dsrdata, dns_rdataclass_in,
                                      dns_rdatatype_ds, ds, &b);
-       if (result != ISC_R_SUCCESS) {
-               return (result);
+       RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+       RWLOCK(&knode->rwlock, isc_rwlocktype_write);
+
+       if (knode->dslist == NULL) {
+               knode->dslist = isc_mem_get(mctx, sizeof(*knode->dslist));
+               dns_rdatalist_init(knode->dslist);
+               knode->dslist->rdclass = dns_rdataclass_in;
+               knode->dslist->type = dns_rdatatype_ds;
+
+               INSIST(knode->dsset.methods == NULL);
+               knode->dsset.methods = &methods;
+               knode->dsset.rdclass = knode->dslist->rdclass;
+               knode->dsset.type = knode->dslist->type;
+               knode->dsset.covers = knode->dslist->covers;
+               knode->dsset.ttl = knode->dslist->ttl;
+               knode->dsset.private1 = knode;
+               knode->dsset.private2 = NULL;
+               knode->dsset.private3 = NULL;
+               knode->dsset.privateuint4 = 0;
+               knode->dsset.private5 = NULL;
+               knode->dsset.trust = dns_trust_ultimate;
        }
 
        for (rdata = ISC_LIST_HEAD(knode->dslist->rdata); rdata != NULL;
@@ -210,26 +257,16 @@ add_ds(dns_keynode_t *knode, dns_rdata_ds_t *ds, isc_mem_t *mctx) {
        if (exists) {
                isc_mem_put(mctx, dsrdata->data, DNS_DS_BUFFERSIZE);
                isc_mem_put(mctx, dsrdata, sizeof(*dsrdata));
-               return (ISC_R_SUCCESS);
-       }
-
-       ISC_LIST_APPEND(knode->dslist->rdata, dsrdata, link);
-
-       if (dns_rdataset_isassociated(&knode->dsset)) {
-               dns_rdataset_disassociate(&knode->dsset);
-       }
-
-       result = dns_rdatalist_tordataset(knode->dslist, &knode->dsset);
-       if (result != ISC_R_SUCCESS) {
-               return (result);
+       } else {
+               ISC_LIST_APPEND(knode->dslist->rdata, dsrdata, link);
        }
 
-       knode->dsset.trust = dns_trust_ultimate;
-       return (ISC_R_SUCCESS);
+       RWUNLOCK(&knode->rwlock, isc_rwlocktype_write);
 }
 
 static isc_result_t
-delete_ds(dns_keynode_t *knode, dns_rdata_ds_t *ds, isc_mem_t *mctx) {
+delete_ds(dns_keytable_t *keytable, dns_rbtnode_t *node, dns_rdata_ds_t *ds) {
+       dns_keynode_t *knode = node->data;
        isc_result_t result;
        dns_rdata_t dsrdata = DNS_RDATA_INIT;
        dns_rdata_t *rdata = NULL;
@@ -237,7 +274,9 @@ delete_ds(dns_keynode_t *knode, dns_rdata_ds_t *ds, isc_mem_t *mctx) {
        bool found = false;
        isc_buffer_t b;
 
+       RWLOCK(&knode->rwlock, isc_rwlocktype_read);
        if (knode->dslist == NULL) {
+               RWUNLOCK(&knode->rwlock, isc_rwlocktype_read);
                return (ISC_R_SUCCESS);
        }
 
@@ -246,6 +285,7 @@ delete_ds(dns_keynode_t *knode, dns_rdata_ds_t *ds, isc_mem_t *mctx) {
        result = dns_rdata_fromstruct(&dsrdata, dns_rdataclass_in,
                                      dns_rdatatype_ds, ds, &b);
        if (result != ISC_R_SUCCESS) {
+               RWUNLOCK(&knode->rwlock, isc_rwlocktype_write);
                return (result);
        }
 
@@ -253,23 +293,40 @@ delete_ds(dns_keynode_t *knode, dns_rdata_ds_t *ds, isc_mem_t *mctx) {
             rdata = ISC_LIST_NEXT(rdata, link))
        {
                if (dns_rdata_compare(rdata, &dsrdata) == 0) {
-                       ISC_LIST_UNLINK(knode->dslist->rdata, rdata, link);
-                       isc_mem_put(mctx, rdata->data, DNS_DS_BUFFERSIZE);
-                       isc_mem_put(mctx, rdata, sizeof(*rdata));
                        found = true;
                        break;
                }
        }
 
-       if (found) {
-               return (ISC_R_SUCCESS);
-       } else {
+       if (!found) {
+               RWUNLOCK(&knode->rwlock, isc_rwlocktype_read);
                /*
                 * The keyname must have matched or we wouldn't be here,
                 * so we use DNS_R_PARTIALMATCH instead of ISC_R_NOTFOUND.
                 */
                return (DNS_R_PARTIALMATCH);
        }
+
+       /*
+        * Replace knode with a new instance without the DS.
+        */
+       node->data = new_keynode(NULL, keytable, knode->managed,
+                                knode->initial);
+       for (rdata = ISC_LIST_HEAD(knode->dslist->rdata); rdata != NULL;
+            rdata = ISC_LIST_NEXT(rdata, link))
+       {
+               if (dns_rdata_compare(rdata, &dsrdata) != 0) {
+                       dns_rdata_ds_t ds0;
+                       result = dns_rdata_tostruct(rdata, &ds0, NULL);
+                       RUNTIME_CHECK(result == ISC_R_SUCCESS);
+                       add_ds(node->data, &ds0, keytable->mctx);
+               }
+       }
+       RWUNLOCK(&knode->rwlock, isc_rwlocktype_read);
+
+       keynode_detach(keytable->mctx, &knode);
+
+       return (ISC_R_SUCCESS);
 }
 
 /*%
@@ -277,9 +334,9 @@ delete_ds(dns_keynode_t *knode, dns_rdata_ds_t *ds, isc_mem_t *mctx) {
  * "managed" and "initial" as requested and attach the keynode to
  * to "node" in "keytable".
  */
-static isc_result_t
-new_keynode(dns_rdata_ds_t *ds, dns_rbtnode_t *node, dns_keytable_t *keytable,
-           bool managed, bool initial) {
+static dns_keynode_t *
+new_keynode(dns_rdata_ds_t *ds, dns_keytable_t *keytable, bool managed,
+           bool initial) {
        dns_keynode_t *knode = NULL;
        isc_result_t result;
 
@@ -291,23 +348,21 @@ new_keynode(dns_rdata_ds_t *ds, dns_rbtnode_t *node, dns_keytable_t *keytable,
 
        dns_rdataset_init(&knode->dsset);
        isc_refcount_init(&knode->refcount, 1);
+       result = isc_rwlock_init(&knode->rwlock, 0, 0);
+       RUNTIME_CHECK(result == ISC_R_SUCCESS);
 
        /*
         * If a DS was supplied, initialize an rdatalist.
         */
        if (ds != NULL) {
-               result = add_ds(knode, ds, keytable->mctx);
-               if (result != ISC_R_SUCCESS) {
-                       return (result);
-               }
+               add_ds(knode, ds, keytable->mctx);
        }
 
+       isc_mem_attach(keytable->mctx, &knode->mctx);
        knode->managed = managed;
        knode->initial = initial;
 
-       node->data = knode;
-
-       return (ISC_R_SUCCESS);
+       return (knode);
 }
 
 /*%
@@ -335,30 +390,21 @@ insert(dns_keytable_t *keytable, bool managed, bool initial,
                 * trust anchor (or a null key node if "ds" is NULL)
                 * and attach it to the created node.
                 */
-               result = new_keynode(ds, node, keytable, managed, initial);
+               node->data = new_keynode(ds, keytable, managed, initial);
        } else if (result == ISC_R_EXISTS) {
                /*
                 * A node already exists for "keyname" in "keytable".
                 */
-               if (ds == NULL) {
-                       /*
-                        * We were told to add a null key at "keyname", which
-                        * means there is nothing left to do as there is either
-                        * a null key at this node already or there is a
-                        * non-null key node which would not be affected.
-                        * Reset result to reflect the fact that the node for
-                        * "keyname" is already marked as secure.
-                        */
-                       result = ISC_R_SUCCESS;
-               } else {
+               if (ds != NULL) {
                        dns_keynode_t *knode = node->data;
                        if (knode == NULL) {
-                               result = new_keynode(ds, node, keytable,
-                                                    managed, initial);
+                               node->data = new_keynode(ds, keytable, managed,
+                                                        initial);
                        } else {
-                               result = add_ds(knode, ds, keytable->mctx);
+                               add_ds(knode, ds, keytable->mctx);
                        }
                }
+               result = ISC_R_SUCCESS;
        }
 
        RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
@@ -442,10 +488,13 @@ dns_keytable_deletekey(dns_keytable_t *keytable, const dns_name_t *keyname,
 
        knode = node->data;
 
+       RWLOCK(&knode->rwlock, isc_rwlocktype_read);
        if (knode->dslist == NULL) {
+               RWUNLOCK(&knode->rwlock, isc_rwlocktype_read);
                result = DNS_R_PARTIALMATCH;
                goto finish;
        }
+       RWUNLOCK(&knode->rwlock, isc_rwlocktype_read);
 
        result = dns_ds_fromkeyrdata(keyname, &rdata, DNS_DSDIGEST_SHA256,
                                     digest, &ds);
@@ -453,7 +502,7 @@ dns_keytable_deletekey(dns_keytable_t *keytable, const dns_name_t *keyname,
                goto finish;
        }
 
-       result = delete_ds(knode, &ds, keytable->mctx);
+       result = delete_ds(keytable, node, &ds);
 
 finish:
        RWUNLOCK(&keytable->rwlock, isc_rwlocktype_write);
@@ -606,20 +655,23 @@ keynode_dslist_totext(dns_name_t *name, dns_keynode_t *keynode,
        isc_result_t result;
        char namebuf[DNS_NAME_FORMATSIZE];
        char obuf[DNS_NAME_FORMATSIZE + 200];
-       dns_rdataset_t *dsset = NULL;
+       dns_rdataset_t dsset;
 
        dns_name_format(name, namebuf, sizeof(namebuf));
 
-       dsset = dns_keynode_dsset(keynode);
+       dns_rdataset_init(&dsset);
+       if (!dns_keynode_dsset(keynode, &dsset)) {
+               return (ISC_R_SUCCESS);
+       }
 
-       for (result = dns_rdataset_first(dsset); result == ISC_R_SUCCESS;
-            result = dns_rdataset_next(dsset))
+       for (result = dns_rdataset_first(&dsset); result == ISC_R_SUCCESS;
+            result = dns_rdataset_next(&dsset))
        {
                char algbuf[DNS_SECALG_FORMATSIZE];
                dns_rdata_t rdata = DNS_RDATA_INIT;
                dns_rdata_ds_t ds;
 
-               dns_rdataset_current(dsset, &rdata);
+               dns_rdataset_current(&dsset, &rdata);
                result = dns_rdata_tostruct(&rdata, &ds, NULL);
                RUNTIME_CHECK(result == ISC_R_SUCCESS);
 
@@ -632,9 +684,11 @@ keynode_dslist_totext(dns_name_t *name, dns_keynode_t *keynode,
 
                result = putstr(text, obuf);
                if (result != ISC_R_SUCCESS) {
+                       dns_rdataset_disassociate(&dsset);
                        return (result);
                }
        }
+       dns_rdataset_disassociate(&dsset);
 
        return (ISC_R_SUCCESS);
 }
@@ -746,15 +800,19 @@ cleanup:
        return (result);
 }
 
-dns_rdataset_t *
-dns_keynode_dsset(dns_keynode_t *keynode) {
+bool
+dns_keynode_dsset(dns_keynode_t *keynode, dns_rdataset_t *rdataset) {
        REQUIRE(VALID_KEYNODE(keynode));
+       REQUIRE(rdataset == NULL || DNS_RDATASET_VALID(rdataset));
 
        if (keynode->dslist != NULL) {
-               return (&keynode->dsset);
+               if (rdataset != NULL) {
+                       keynode_clone(&keynode->dsset, rdataset);
+               }
+               return (true);
        }
 
-       return (NULL);
+       return (false);
 }
 
 bool
@@ -777,3 +835,93 @@ dns_keynode_trust(dns_keynode_t *keynode) {
 
        keynode->initial = false;
 }
+
+static void
+keynode_disassociate(dns_rdataset_t *rdataset) {
+       dns_keynode_t *keynode;
+
+       REQUIRE(rdataset != NULL);
+       REQUIRE(rdataset->methods == &methods);
+
+       rdataset->methods = NULL;
+       keynode = rdataset->private1;
+       rdataset->private1 = NULL;
+
+       keynode_detach(keynode->mctx, &keynode);
+}
+
+static isc_result_t
+keynode_first(dns_rdataset_t *rdataset) {
+       dns_keynode_t *keynode;
+
+       REQUIRE(rdataset != NULL);
+       REQUIRE(rdataset->methods == &methods);
+
+       keynode = rdataset->private1;
+       RWLOCK(&keynode->rwlock, isc_rwlocktype_read);
+       rdataset->private2 = ISC_LIST_HEAD(keynode->dslist->rdata);
+       RWUNLOCK(&keynode->rwlock, isc_rwlocktype_read);
+
+       if (rdataset->private2 == NULL) {
+               return (ISC_R_NOMORE);
+       }
+
+       return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+keynode_next(dns_rdataset_t *rdataset) {
+       dns_keynode_t *keynode;
+       dns_rdata_t *rdata;
+
+       REQUIRE(rdataset != NULL);
+       REQUIRE(rdataset->methods == &methods);
+
+       rdata = rdataset->private2;
+       if (rdata == NULL) {
+               return (ISC_R_NOMORE);
+       }
+
+       keynode = rdataset->private1;
+       RWLOCK(&keynode->rwlock, isc_rwlocktype_read);
+       rdataset->private2 = ISC_LIST_NEXT(rdata, link);
+       RWUNLOCK(&keynode->rwlock, isc_rwlocktype_read);
+
+       if (rdataset->private2 == NULL) {
+               return (ISC_R_NOMORE);
+       }
+
+       return (ISC_R_SUCCESS);
+}
+
+static void
+keynode_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata) {
+       dns_rdata_t *list_rdata;
+
+       REQUIRE(rdataset != NULL);
+       REQUIRE(rdataset->methods == &methods);
+
+       list_rdata = rdataset->private2;
+       INSIST(list_rdata != NULL);
+
+       dns_rdata_clone(list_rdata, rdata);
+}
+
+static void
+keynode_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
+       dns_keynode_t *keynode;
+
+       REQUIRE(source != NULL);
+       REQUIRE(target != NULL);
+       REQUIRE(source->methods == &methods);
+
+       keynode = source->private1;
+       isc_refcount_increment(&keynode->refcount);
+
+       *target = *source;
+
+       /*
+        * Reset iterator state.
+        */
+       target->private2 = NULL;
+}
index 0c4860039757f3a69a01792ca0d29624a1da9f1b..fca2f4224b46304a5fdc1dcecffae56e2278ea28 100644 (file)
@@ -152,6 +152,9 @@ expire_rdatasets(dns_validator_t *val) {
  */
 static void
 disassociate_rdatasets(dns_validator_t *val) {
+       if (dns_rdataset_isassociated(&val->fdsset)) {
+               dns_rdataset_disassociate(&val->fdsset);
+       }
        if (dns_rdataset_isassociated(&val->frdataset)) {
                dns_rdataset_disassociate(&val->frdataset);
        }
@@ -1779,10 +1782,11 @@ validate_dnskey(dns_validator_t *val) {
                result = dns_keytable_find(val->keytable, val->event->name,
                                           &keynode);
                if (result == ISC_R_SUCCESS) {
-                       val->dsset = dns_keynode_dsset(keynode);
-                       if (val->dsset == NULL) {
+                       if (!dns_keynode_dsset(keynode, &val->fdsset)) {
                                dns_keytable_detachkeynode(val->keytable,
                                                           &keynode);
+                       } else {
+                               val->dsset = &val->fdsset;
                        }
                }
        }
@@ -1834,7 +1838,8 @@ validate_dnskey(dns_validator_t *val) {
 
        if (val->dsset->trust < dns_trust_secure) {
                INSIST(keynode == NULL);
-               return (markanswer(val, "validate_dnskey (2)", "insecure DS"));
+               result = markanswer(val, "validate_dnskey (2)", "insecure DS");
+               goto cleanup;
        }
 
        /*
@@ -1949,6 +1954,10 @@ validate_dnskey(dns_validator_t *val) {
        }
 
 cleanup:
+       if (val->dsset == &val->fdsset) {
+               val->dsset = NULL;
+               dns_rdataset_disassociate(&val->fdsset);
+       }
        if (keynode != NULL) {
                val->dsset = NULL;
                dns_keytable_detachkeynode(val->keytable, &keynode);
@@ -3113,6 +3122,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
        }
 
        val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name);
+       dns_rdataset_init(&val->fdsset);
        dns_rdataset_init(&val->frdataset);
        dns_rdataset_init(&val->fsigrdataset);
        dns_fixedname_init(&val->wild);
index 90a8ea44a32d8bafa49159bf9597fd8633d3a635..36bcacc6c8579d78f0d56deea03c4f7c6bd4382f 100644 (file)
@@ -4070,7 +4070,7 @@ create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
        /*
         * If the keynode has no trust anchor set, we shouldn't be here.
         */
-       if (dns_keynode_dsset(keynode) == NULL) {
+       if (!dns_keynode_dsset(keynode, NULL)) {
                return (ISC_R_FAILURE);
        }
 
@@ -4469,7 +4469,7 @@ addifmissing(dns_keytable_t *keytable, dns_keynode_t *keynode,
        /*
         * If the keynode has no trust anchor set, return.
         */
-       if (dns_keynode_dsset(keynode) == NULL) {
+       if (!dns_keynode_dsset(keynode, NULL)) {
                return;
        }
 
@@ -10017,7 +10017,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
        bool free_needed;
        dns_keynode_t *keynode = NULL;
        dns_rdataset_t *dnskeys = NULL, *dnskeysigs = NULL;
-       dns_rdataset_t *keydataset = NULL, *dsset = NULL;
+       dns_rdataset_t *keydataset = NULL, dsset;
 
        UNUSED(task);
        INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
@@ -10103,7 +10103,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
        /*
         * If the keynode has a DS trust anchor, use it for verification.
         */
-       if ((dsset = dns_keynode_dsset(keynode)) != NULL) {
+       dns_rdataset_init(&dsset);
+       if (dns_keynode_dsset(keynode, &dsset)) {
                for (result = dns_rdataset_first(dnskeysigs);
                     result == ISC_R_SUCCESS;
                     result = dns_rdataset_next(dnskeysigs))
@@ -10116,15 +10117,15 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
                        result = dns_rdata_tostruct(&sigrr, &sig, NULL);
                        RUNTIME_CHECK(result == ISC_R_SUCCESS);
 
-                       for (tresult = dns_rdataset_first(dsset);
+                       for (tresult = dns_rdataset_first(&dsset);
                             tresult == ISC_R_SUCCESS;
-                            tresult = dns_rdataset_next(dsset))
+                            tresult = dns_rdataset_next(&dsset))
                        {
                                dns_rdata_t dsrdata = DNS_RDATA_INIT;
                                dns_rdata_ds_t ds;
 
                                dns_rdata_reset(&dsrdata);
-                               dns_rdataset_current(dsset, &dsrdata);
+                               dns_rdataset_current(&dsset, &dsrdata);
                                tresult = dns_rdata_tostruct(&dsrdata, &ds,
                                                             NULL);
                                RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
@@ -10171,6 +10172,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
                                break;
                        }
                }
+               dns_rdataset_disassociate(&dsset);
        }
 
 anchors_done:
index 2d41a4cf313f12da8b9c5a3491b7b9cb6c0603c8..f6da8bab232adc84550912b883f8a884ac20b0bc 100644 (file)
@@ -1478,7 +1478,7 @@ check_dnskey_sigs(vctx_t *vctx, const dns_rdata_dnskey_t *dnskey,
        bool *goodkey = NULL;
        dst_key_t *key = NULL;
        isc_result_t result;
-       dns_rdataset_t *dsset = NULL;
+       dns_rdataset_t dsset;
 
        active_keys = (is_ksk ? vctx->ksk_algorithms : vctx->zsk_algorithms);
        standby_keys = (is_ksk ? vctx->standby_ksk : vctx->standby_zsk);
@@ -1543,9 +1543,11 @@ check_dnskey_sigs(vctx_t *vctx, const dns_rdata_dnskey_t *dnskey,
         * it doesn't have any DNSKEY ones. So, we can check for a DS
         * match and then stop.
         */
-       if ((dsset = dns_keynode_dsset(keynode)) != NULL) {
-               for (result = dns_rdataset_first(dsset);
-                    result == ISC_R_SUCCESS; result = dns_rdataset_next(dsset))
+       dns_rdataset_init(&dsset);
+       if (dns_keynode_dsset(keynode, &dsset)) {
+               for (result = dns_rdataset_first(&dsset);
+                    result == ISC_R_SUCCESS;
+                    result = dns_rdataset_next(&dsset))
                {
                        dns_rdata_t dsrdata = DNS_RDATA_INIT;
                        dns_rdata_t newdsrdata = DNS_RDATA_INIT;
@@ -1553,7 +1555,7 @@ check_dnskey_sigs(vctx_t *vctx, const dns_rdata_dnskey_t *dnskey,
                        dns_rdata_ds_t ds;
 
                        dns_rdata_reset(&dsrdata);
-                       dns_rdataset_current(dsset, &dsrdata);
+                       dns_rdataset_current(&dsset, &dsrdata);
                        result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
                        RUNTIME_CHECK(result == ISC_R_SUCCESS);
 
@@ -1578,6 +1580,7 @@ check_dnskey_sigs(vctx_t *vctx, const dns_rdata_dnskey_t *dnskey,
                                break;
                        }
                }
+               dns_rdataset_disassociate(&dsset);
 
                goto cleanup;
        }
index c25abd20e4231066fbc52d40c7ad8d62891aa4b3..d1fe194707aeb492350baa6ca1c538ab9a7be3c1 100644 (file)
@@ -6649,7 +6649,7 @@ static bool
 has_ta(query_ctx_t *qctx) {
        dns_keytable_t *keytable = NULL;
        dns_keynode_t *keynode = NULL;
-       dns_rdataset_t *dsset = NULL;
+       dns_rdataset_t dsset;
        dns_keytag_t sentinel = qctx->client->query.root_key_sentinel_keyid;
        isc_result_t result;
 
@@ -6667,23 +6667,27 @@ has_ta(query_ctx_t *qctx) {
                return (false);
        }
 
-       if ((dsset = dns_keynode_dsset(keynode)) != NULL) {
-               for (result = dns_rdataset_first(dsset);
-                    result == ISC_R_SUCCESS; result = dns_rdataset_next(dsset))
+       dns_rdataset_init(&dsset);
+       if (dns_keynode_dsset(keynode, &dsset)) {
+               for (result = dns_rdataset_first(&dsset);
+                    result == ISC_R_SUCCESS;
+                    result = dns_rdataset_next(&dsset))
                {
                        dns_rdata_t rdata = DNS_RDATA_INIT;
                        dns_rdata_ds_t ds;
 
                        dns_rdata_reset(&rdata);
-                       dns_rdataset_current(dsset, &rdata);
+                       dns_rdataset_current(&dsset, &rdata);
                        result = dns_rdata_tostruct(&rdata, &ds, NULL);
                        RUNTIME_CHECK(result == ISC_R_SUCCESS);
                        if (ds.key_tag == sentinel) {
                                dns_keytable_detachkeynode(keytable, &keynode);
                                dns_keytable_detach(&keytable);
+                               dns_rdataset_disassociate(&dsset);
                                return (true);
                        }
                }
+               dns_rdataset_disassociate(&dsset);
        }
 
        if (keynode != NULL) {