]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
allow DS trust anchors to be set in keytable
authorEvan Hunt <each@isc.org>
Tue, 17 Sep 2019 04:06:23 +0000 (21:06 -0700)
committerEvan Hunt <each@isc.org>
Fri, 15 Nov 2019 23:47:56 +0000 (15:47 -0800)
note: this is a frankensteinian kluge which needs further refactoring.

the keytable started as an RBT where the node->data points to a list of
dns_keynode structures, each of which points to a single dst_key.
later it was modified so that the list could instead point to a single
"null" keynode structure, which does not reference a key; this means
a trust anchor has been configured but the RFC 5011 refresh failed.

in this branch it is further updated to allow the first keynode in
the list to point to an rdatalist of DS-style trust anchors.  these will
be used by the validator to populate 'val->dsset' when validating a zone
key.

a DS style trust anchor can be updated as a result of RFC 5011
processing to contain DST keys instead; this results in the DS list
being freed.  the reverse is not possible; attempting to add a DS-style
trust anchor if a key-style trust anchor is already in place results
in an error.

later, this should be refactored to use rdatalists for both DS-style
and key-style trust anchors, but we're keeping the existing code for
old-style trust anchors for now.

bin/named/server.c
lib/dns/client.c
lib/dns/include/dns/keytable.h
lib/dns/keytable.c
lib/dns/tests/keytable_test.c
lib/dns/win32/libdns.def.in
lib/dns/zone.c

index d6f912cbfbcbdac1ea64f80ae1cb7a0e211691c8..1b63900bd9e665f37e866b06cb5543a64823bc35 100644 (file)
@@ -1017,7 +1017,9 @@ 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, &dstkey);
+                                 initializing, keyname,
+                                 dstkey != NULL ? &dstkey : NULL,
+                                 ds);
 
  done:
        /*
@@ -1030,7 +1032,7 @@ process_key(const cfg_obj_t *key, dns_keytable_t *secroots,
        }
 
        /*
-        * Ensure 'ds' does not leak.
+        * Free 'ds'.
         */
        if (ds != NULL) {
                dns_rdata_freestruct(ds);
index 48ed6aa88c90490f18b952b9625c56fa8ac79590..971c4e3af2670a4998eb564648cd6faf600752ab 100644 (file)
@@ -1507,7 +1507,8 @@ dns_client_addtrustedkey(dns_client_t *client, dns_rdataclass_t rdclass,
        if (result != ISC_R_SUCCESS)
                goto cleanup;
 
-       result = dns_keytable_add(secroots, false, false, &dstkey);
+       result = dns_keytable_add(secroots, false, false,
+                                 dst_key_name(dstkey), &dstkey, NULL);
 
  cleanup:
        if (dstkey != NULL)
index 66fc5c1a84ce3b666d00aab6480ce47dea567faf..0a68cb037c114b5a20938b21cc9efba20cc03a95 100644 (file)
@@ -42,6 +42,7 @@
 #include <isc/rwlock.h>
 #include <isc/stdtime.h>
 
+#include <dns/rdatastruct.h>
 #include <dns/types.h>
 
 #include <dst/dst.h>
@@ -105,10 +106,14 @@ dns_keytable_detach(dns_keytable_t **keytablep);
  */
 
 isc_result_t
-dns_keytable_add(dns_keytable_t *keytable, bool managed,
-                bool initial, dst_key_t **keyp);
+dns_keytable_add(dns_keytable_t *keytable,
+                bool managed, bool initial,
+                dns_name_t *name, dst_key_t **keyp, dns_rdata_ds_t *ds);
 /*%<
- * Add '*keyp' to 'keytable' (using the name in '*keyp').
+ * 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'.
+ *
  * The value of keynode->managed is set to 'managed', and the
  * value of keynode->initial is set to 'initial'. (Note: 'initial'
  * should only be used when adding managed-keys from configuration.
@@ -119,6 +124,12 @@ dns_keytable_add(dns_keytable_t *keytable, bool managed,
  * 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.
  *
@@ -407,6 +418,19 @@ dns_keynode_key(dns_keynode_t *keynode);
  * Get the DST key associated with keynode.
  */
 
+dns_rdataset_t *
+dns_keynode_dsset(dns_keynode_t *keynode);
+/*%<
+ * Return a pointer to the DS RRset associated with 'keynode'.
+ *
+ * Returns:
+ *\li  ISC_R_SUCCESS
+ *\li  ISC_R_FAILURE if the keynode does not contain a DS trust anchor.
+ *
+ * Requires:
+ *\li  'keynode' is valid.
+ */
+
 bool
 dns_keynode_managed(dns_keynode_t *keynode);
 /*%<
index a154699d452b6770f66d26110591959bfd31bf96..55aecc289260ed64261d3e671b62356b6c6ed6ed 100644 (file)
 #include <dns/keytable.h>
 #include <dns/fixedname.h>
 #include <dns/rbt.h>
+#include <dns/rdata.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
 #include <dns/result.h>
 
 #define KEYTABLE_MAGIC                  ISC_MAGIC('K', 'T', 'b', 'l')
@@ -46,10 +50,12 @@ struct dns_keytable {
 struct dns_keynode {
        unsigned int            magic;
        isc_refcount_t          refcount;
-       dst_key_t *             key;
+       dst_key_t               *key;
+       dns_rdatalist_t         *dslist;
+       dns_rdataset_t          dsset;
        bool                    managed;
        bool                    initial;
-       struct dns_keynode *    next;
+       struct dns_keynode      *next;
 };
 
 static void
@@ -135,12 +141,32 @@ dns_keytable_detach(dns_keytable_t **keytablep) {
        }
 }
 
+static void
+free_dslist(isc_mem_t *mctx, dns_keynode_t *knode) {
+       dns_rdata_t *rdata = NULL;
+
+       for (rdata = ISC_LIST_HEAD(knode->dslist->rdata);
+            rdata != NULL;
+            rdata = ISC_LIST_HEAD(knode->dslist->rdata))
+       {
+               ISC_LIST_UNLINK(knode->dslist->rdata, rdata, link);
+               isc_mem_put(mctx, rdata->data, DNS_DS_BUFFERSIZE);
+               isc_mem_put(mctx, rdata, sizeof(*rdata));
+       }
+
+       isc_mem_put(mctx, knode->dslist, sizeof(*knode->dslist));
+       knode->dslist = NULL;
+}
+
 /*%
- * Search "node" for either a null key node or a key node for the exact same
- * key as the one supplied in "keyp" and, if found, update it accordingly.
+ * Search "node" for an empty or DS-style keynode, or a keynode for the
+ * exact same key as the one supplied in "keyp" and, if found, update it
+ * accordingly.
  */
 static isc_result_t
-update_keynode(dst_key_t **keyp, dns_rbtnode_t *node, bool initial) {
+update_keynode(dns_keytable_t *keytable, dns_rbtnode_t *node,
+              dst_key_t **keyp, bool initial)
+{
        dns_keynode_t *knode;
 
        REQUIRE(keyp != NULL && *keyp != NULL);
@@ -149,13 +175,17 @@ update_keynode(dst_key_t **keyp, dns_rbtnode_t *node, bool initial) {
        for (knode = node->data; knode != NULL; knode = knode->next) {
                if (knode->key == NULL) {
                        /*
-                        * Null key node found.  Attach the supplied key to it,
-                        * making it a non-null key node and transferring key
+                        * Null or DS-style keynode found.  Detach
+                        * the DS rdatalist if present. Attach the
+                        * supplied key to it, transferring key
                         * ownership to the keytable.
                         */
+                       if (knode->dslist != NULL) {
+                               free_dslist(keytable->mctx, knode);
+                       }
+
                        knode->key = *keyp;
                        *keyp = NULL;
-                       return (ISC_R_SUCCESS);
                } else if (dst_key_compare(knode->key, *keyp)) {
                        /*
                         * Key node found for the supplied key.  Free the
@@ -163,11 +193,15 @@ update_keynode(dst_key_t **keyp, dns_rbtnode_t *node, bool initial) {
                         * node's flags if necessary.
                         */
                        dst_key_free(keyp);
-                       if (!initial) {
-                               dns_keynode_trust(knode);
-                       }
-                       return (ISC_R_SUCCESS);
+               } else {
+                       continue;
                }
+
+               if (!initial) {
+                       dns_keynode_trust(knode);
+               }
+
+               return (ISC_R_SUCCESS);
        }
 
        return (ISC_R_NOTFOUND);
@@ -179,9 +213,9 @@ update_keynode(dst_key_t **keyp, dns_rbtnode_t *node, bool initial) {
  * one attached to "node" in "keytable".
  */
 static isc_result_t
-prepend_keynode(dst_key_t **keyp, dns_rbtnode_t *node,
-               dns_keytable_t *keytable, bool managed,
-               bool initial)
+prepend_keynode(dst_key_t **keyp, dns_rdata_ds_t *ds,
+               dns_rbtnode_t *node, dns_keytable_t *keytable,
+               bool managed, bool initial)
 {
        dns_keynode_t *knode = NULL;
        isc_result_t result;
@@ -196,15 +230,60 @@ prepend_keynode(dst_key_t **keyp, dns_rbtnode_t *node,
        }
 
        /*
-        * If a key was supplied, transfer its ownership to the keytable.
+        * If a dst_key was supplied, transfer its ownership to the keytable.
+        * Otherwise, if a DS was supplied, append it to the rdatalist
+        * (initializing if necessary).
         */
-       if (keyp) {
+       if (keyp != NULL) {
+               if (knode->dslist != NULL) {
+                       free_dslist(keytable->mctx, knode);
+               }
                knode->key = *keyp;
                *keyp = NULL;
+       } else if (ds != NULL) {
+               dns_rdata_t *rdata = NULL;
+               void *data = NULL;
+               isc_buffer_t b;
+
+               if (knode->dslist == NULL) {
+                       knode->dslist = isc_mem_get(keytable->mctx,
+                                                   sizeof(*knode->dslist));
+                       dns_rdatalist_init(knode->dslist);
+                       knode->dslist->rdclass = dns_rdataclass_in;
+                       knode->dslist->type = dns_rdatatype_ds;
+                       knode->dslist->ttl = 0;
+               }
+
+               rdata = isc_mem_get(keytable->mctx, sizeof(*rdata));
+               dns_rdata_init(rdata);
+
+               data = isc_mem_get(keytable->mctx, DNS_DS_BUFFERSIZE);
+               isc_buffer_init(&b, data, DNS_DS_BUFFERSIZE);
+
+               result = dns_rdata_fromstruct(rdata, dns_rdataclass_in,
+                                             dns_rdatatype_ds, ds, &b);
+               if (result != ISC_R_SUCCESS) {
+                       return (result);
+               }
+
+               ISC_LIST_APPEND(knode->dslist->rdata, rdata, 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);
+               }
+
+               knode->dsset.trust = dns_trust_ultimate;
        }
 
        knode->managed = managed;
        knode->initial = initial;
+
        knode->next = node->data;
        node->data = knode;
 
@@ -219,7 +298,7 @@ prepend_keynode(dst_key_t **keyp, dns_rbtnode_t *node,
  */
 static isc_result_t
 insert(dns_keytable_t *keytable, bool managed, bool initial,
-       const dns_name_t *keyname, dst_key_t **keyp)
+       const dns_name_t *keyname, dst_key_t **keyp, dns_rdata_ds_t *ds)
 {
        dns_rbtnode_t *node = NULL;
        isc_result_t result;
@@ -232,17 +311,17 @@ insert(dns_keytable_t *keytable, bool managed, bool initial,
        if (result == ISC_R_SUCCESS) {
                /*
                 * There was no node for "keyname" in "keytable" yet, so one
-                * was created.  Create a new key node for the supplied key (or
-                * a null key node if "keyp" is NULL) and attach it to the
-                * created node.
+                * was created.  Create a new key node for the supplied
+                * trust anchor (or a null key node if both "keyp" and
+                * "ds" are NULL) and attach it to the created node.
                 */
-               result = prepend_keynode(keyp, node, keytable, managed,
-                                        initial);
+               result = prepend_keynode(keyp, ds, node, keytable,
+                                        managed, initial);
        } else if (result == ISC_R_EXISTS) {
                /*
                 * A node already exists for "keyname" in "keytable".
                 */
-               if (keyp == NULL) {
+               if (keyp == NULL && ds == NULL) {
                        /*
                         * We were told to add a null key at "keyname", which
                         * means there is nothing left to do as there is either
@@ -252,7 +331,7 @@ insert(dns_keytable_t *keytable, bool managed, bool initial,
                         * "keyname" is already marked as secure.
                         */
                        result = ISC_R_SUCCESS;
-               } else {
+               } else if (keyp != NULL) {
                        /*
                         * We were told to add the key supplied in "keyp" at
                         * "keyname".  Try to find an already existing key node
@@ -260,7 +339,7 @@ insert(dns_keytable_t *keytable, bool managed, bool initial,
                         * node or a key node for the exact same key) and, if
                         * found, update it accordingly.
                         */
-                       result = update_keynode(keyp, node, initial);
+                       result = update_keynode(keytable, node, keyp, initial);
                        if (result == ISC_R_NOTFOUND) {
                                /*
                                 * The node for "keyname" only contains key
@@ -268,9 +347,13 @@ insert(dns_keytable_t *keytable, bool managed, bool initial,
                                 * one.  Create a new key node for the supplied
                                 * key and prepend it before the others.
                                 */
-                               result = prepend_keynode(keyp, node, keytable,
+                               result = prepend_keynode(keyp, NULL,
+                                                        node, keytable,
                                                         managed, initial);
                        }
+               } else if (ds != NULL) {
+                       result = prepend_keynode(NULL, ds, node, keytable,
+                                                managed, initial);
                }
        }
 
@@ -280,17 +363,19 @@ insert(dns_keytable_t *keytable, bool managed, bool initial,
 }
 
 isc_result_t
-dns_keytable_add(dns_keytable_t *keytable, bool managed,
-                bool initial, dst_key_t **keyp)
+dns_keytable_add(dns_keytable_t *keytable,
+                bool managed, bool initial,
+                dns_name_t *name, dst_key_t **keyp, dns_rdata_ds_t *ds)
 {
-       REQUIRE(keyp != NULL && *keyp != NULL);
+       REQUIRE(keyp == NULL || *keyp != NULL);
+       REQUIRE(keyp != NULL || ds != NULL);
        REQUIRE(!initial || managed);
-       return (insert(keytable, managed, initial, dst_key_name(*keyp), keyp));
+       return (insert(keytable, managed, initial, name, keyp, ds));
 }
 
 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));
 }
 
 isc_result_t
@@ -420,8 +505,9 @@ dns_keytable_nextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
        REQUIRE(VALID_KEYNODE(keynode));
        REQUIRE(nextnodep != NULL && *nextnodep == NULL);
 
-       if (keynode->next == NULL)
+       if (keynode->next == NULL) {
                return (ISC_R_NOTFOUND);
+       }
 
        dns_keynode_attach(keynode->next, nextnodep);
        isc_refcount_increment(&keytable->active_nodes);
@@ -459,25 +545,29 @@ dns_keytable_findkeynode(dns_keytable_t *keytable, const dns_name_t *name,
        knode = NULL;
        data = NULL;
        result = dns_rbt_findname(keytable->table, name, 0, NULL, &data);
-
        if (result == ISC_R_SUCCESS) {
                INSIST(data != NULL);
+
                for (knode = data; knode != NULL; knode = knode->next) {
                        if (knode->key == NULL) {
                                knode = NULL;
                                break;
                        }
-                       if (algorithm == dst_key_alg(knode->key)
-                           && tag == dst_key_id(knode->key))
+                       if (algorithm == dst_key_alg(knode->key) &&
+                           tag == dst_key_id(knode->key))
+                       {
                                break;
+                       }
                }
                if (knode != NULL) {
                        isc_refcount_increment0(&keytable->active_nodes);
                        dns_keynode_attach(knode, keynodep);
-               } else
+               } else {
                        result = DNS_R_PARTIALMATCH;
-       } else if (result == DNS_R_PARTIALMATCH)
+               }
+       } else if (result == DNS_R_PARTIALMATCH) {
                result = ISC_R_NOTFOUND;
+       }
 
        RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
 
@@ -507,14 +597,17 @@ dns_keytable_findnextkeynode(dns_keytable_t *keytable, dns_keynode_t *keynode,
                }
                if (dst_key_alg(keynode->key) == dst_key_alg(knode->key) &&
                    dst_key_id(keynode->key) == dst_key_id(knode->key))
+               {
                        break;
+               }
        }
        if (knode != NULL) {
                isc_refcount_increment(&keytable->active_nodes);
                result = ISC_R_SUCCESS;
                dns_keynode_attach(knode, nextnodep);
-       } else
+       } else {
                result = ISC_R_NOTFOUND;
+       }
 
        return (result);
 }
@@ -539,8 +632,9 @@ dns_keytable_finddeepestmatch(dns_keytable_t *keytable, const dns_name_t *name,
        data = NULL;
        result = dns_rbt_findname(keytable->table, name, 0, foundname, &data);
 
-       if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
+       if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
                result = ISC_R_SUCCESS;
+       }
 
        RWUNLOCK(&keytable->rwlock, isc_rwlocktype_read);
 
@@ -616,8 +710,9 @@ putstr(isc_buffer_t **b, const char *str) {
        isc_result_t result;
 
        result = isc_buffer_reserve(b, strlen(str));
-       if (result != ISC_R_SUCCESS)
+       if (result != ISC_R_SUCCESS) {
                return (result);
+       }
 
        isc_buffer_putstr(*b, str);
        return (ISC_R_SUCCESS);
@@ -639,9 +734,9 @@ dns_keytable_dump(dns_keytable_t *keytable, FILE *fp) {
 
        if (isc_buffer_usedlength(text) != 0) {
                (void) putstr(&text, "\n");
-       } else if (result == ISC_R_SUCCESS)
+       } else if (result == ISC_R_SUCCESS) {
                (void) putstr(&text, "none");
-       else {
+       else {
                (void) putstr(&text, "could not dump key table: ");
                (void) putstr(&text, isc_result_totext(result));
        }
@@ -653,44 +748,112 @@ dns_keytable_dump(dns_keytable_t *keytable, FILE *fp) {
        return (result);
 }
 
+static isc_result_t
+keynode_dslist_totext(dns_name_t *name, dns_keynode_t *keynode,
+                     isc_buffer_t **text)
+{
+       isc_result_t result;
+       char namebuf[DNS_NAME_FORMATSIZE];
+       char obuf[DNS_NAME_FORMATSIZE + 200];
+       dns_rdataset_t *dsset = NULL;
+
+       dns_name_format(name, namebuf, sizeof(namebuf));
+
+       dsset = dns_keynode_dsset(keynode);
+
+       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);
+               result = dns_rdata_tostruct(&rdata, &ds, NULL);
+               RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+               dns_secalg_format(ds.algorithm, algbuf, sizeof(algbuf));
+
+               snprintf(obuf, sizeof(obuf), "%s/%s/%d ; %s%s (DS)\n",
+                        namebuf, algbuf, ds.key_tag,
+                        keynode->initial ? "initializing " : "",
+                        keynode->managed ? "managed" : "static");
+
+               result = putstr(text, obuf);
+               if (result != ISC_R_SUCCESS) {
+                       return (result);
+               }
+       }
+
+       return (ISC_R_SUCCESS);
+}
+
 isc_result_t
 dns_keytable_totext(dns_keytable_t *keytable, isc_buffer_t **text) {
        isc_result_t result;
        dns_keynode_t *knode;
        dns_rbtnode_t *node;
        dns_rbtnodechain_t chain;
+       dns_name_t *foundname, *origin, *fullname;
+       dns_fixedname_t fixedfoundname, fixedorigin, fixedfullname;
 
        REQUIRE(VALID_KEYTABLE(keytable));
        REQUIRE(text != NULL && *text != NULL);
 
+       origin = dns_fixedname_initname(&fixedorigin);
+       fullname = dns_fixedname_initname(&fixedfullname);
+       foundname = dns_fixedname_initname(&fixedfoundname);
+
        RWLOCK(&keytable->rwlock, isc_rwlocktype_read);
        dns_rbtnodechain_init(&chain);
        result = dns_rbtnodechain_first(&chain, keytable->table, NULL, NULL);
        if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
-               if (result == ISC_R_NOTFOUND)
+               if (result == ISC_R_NOTFOUND) {
                        result = ISC_R_SUCCESS;
+               }
                goto cleanup;
        }
        for (;;) {
                char pbuf[DST_KEY_FORMATSIZE];
 
-               dns_rbtnodechain_current(&chain, NULL, NULL, &node);
-               for (knode = node->data; knode != NULL; knode = knode->next) {
+               dns_rbtnodechain_current(&chain, foundname, origin, &node);
+
+               knode = node->data;
+               if (knode != NULL && knode->dslist != NULL) {
+                       result = dns_name_concatenate(foundname, origin,
+                                                     fullname, NULL);
+                       if (result != ISC_R_SUCCESS) {
+                               goto cleanup;
+                       }
+
+                       result = keynode_dslist_totext(fullname, knode, text);
+                       goto cleanup;
+               }
+
+               for (; knode != NULL; knode = knode->next) {
                        char obuf[DNS_NAME_FORMATSIZE + 200];
-                       if (knode->key == NULL)
+
+                       if (knode->key == NULL) {
                                continue;
+                       }
+
                        dst_key_format(knode->key, pbuf, sizeof(pbuf));
                        snprintf(obuf, sizeof(obuf), "%s ; %s%s\n", pbuf,
                                 knode->initial ? "initializing " : "",
                                 knode->managed ? "managed" : "static");
+
                        result = putstr(text, obuf);
-                       if (result != ISC_R_SUCCESS)
+                       if (result != ISC_R_SUCCESS) {
                                break;
+                       }
                }
+
                result = dns_rbtnodechain_next(&chain, NULL, NULL);
                if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
-                       if (result == ISC_R_NOMORE)
+                       if (result == ISC_R_NOMORE) {
                                result = ISC_R_SUCCESS;
+                       }
                        break;
                }
        }
@@ -716,19 +879,22 @@ dns_keytable_forall(dns_keytable_t *keytable,
        dns_rbtnodechain_init(&chain);
        result = dns_rbtnodechain_first(&chain, keytable->table, NULL, NULL);
        if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
-               if (result == ISC_R_NOTFOUND)
+               if (result == ISC_R_NOTFOUND) {
                        result = ISC_R_SUCCESS;
+               }
                goto cleanup;
        }
        isc_refcount_increment0(&keytable->active_nodes);
        for (;;) {
                dns_rbtnodechain_current(&chain, NULL, NULL, &node);
-               if (node->data != NULL)
+               if (node->data != NULL) {
                        (*func)(keytable, node->data, arg);
+               }
                result = dns_rbtnodechain_next(&chain, NULL, NULL);
                if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
-                       if (result == ISC_R_NOMORE)
+                       if (result == ISC_R_NOMORE) {
                                result = ISC_R_SUCCESS;
+                       }
                        break;
                }
        }
@@ -747,6 +913,17 @@ dns_keynode_key(dns_keynode_t *keynode) {
        return (keynode->key);
 }
 
+dns_rdataset_t *
+dns_keynode_dsset(dns_keynode_t *keynode) {
+       REQUIRE(VALID_KEYNODE(keynode));
+
+       if (keynode->dslist != NULL) {
+               return (&keynode->dsset);
+       }
+
+       return (NULL);
+}
+
 bool
 dns_keynode_managed(dns_keynode_t *keynode) {
        REQUIRE(VALID_KEYNODE(keynode));
@@ -780,6 +957,8 @@ dns_keynode_create(isc_mem_t *mctx, dns_keynode_t **target) {
        knode->managed = false;
        knode->initial = false;
        knode->key = NULL;
+       knode->dslist = NULL;
+       dns_rdataset_init(&knode->dsset);
        knode->next = NULL;
 
        isc_refcount_init(&knode->refcount, 1);
@@ -796,17 +975,23 @@ dns_keynode_attach(dns_keynode_t *source, dns_keynode_t **target) {
 }
 
 void
-dns_keynode_detach(isc_mem_t *mctx, dns_keynode_t **keynode) {
-       REQUIRE(keynode != NULL && VALID_KEYNODE(*keynode));
-       dns_keynode_t *node = *keynode;
-       *keynode = NULL;
+dns_keynode_detach(isc_mem_t *mctx, dns_keynode_t **keynodep) {
+       REQUIRE(keynodep != NULL && VALID_KEYNODE(*keynodep));
+       dns_keynode_t *knode = *keynodep;
+       *keynodep = NULL;
 
-       if (isc_refcount_decrement(&node->refcount) == 1) {
-               isc_refcount_destroy(&node->refcount);
-               if (node->key != NULL) {
-                       dst_key_free(&node->key);
+       if (isc_refcount_decrement(&knode->refcount) == 1) {
+               isc_refcount_destroy(&knode->refcount);
+               if (knode->key != NULL) {
+                       dst_key_free(&knode->key);
+               }
+               if (knode->dslist != NULL) {
+                       if (dns_rdataset_isassociated(&knode->dsset)) {
+                               dns_rdataset_disassociate(&knode->dsset);
+                       }
+                       free_dslist(mctx, knode);
                }
-               isc_mem_put(mctx, node, sizeof(dns_keynode_t));
+               isc_mem_put(mctx, knode, sizeof(dns_keynode_t));
        }
 }
 
index c6f777f03a8f547548c5c55cd9e468dc569d86b0..0ad5323ea77573ab786a20d548906fa26003809d 100644 (file)
@@ -155,12 +155,14 @@ create_tables() {
 
        /* Add a normal key */
        create_key(257, 3, 5, "example.com", keystr1, &key);
-       assert_int_equal(dns_keytable_add(keytable, false, false, &key),
+       assert_int_equal(dns_keytable_add(keytable, false, false,
+                                         dst_key_name(key), &key, NULL),
                         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, &key),
+       assert_int_equal(dns_keytable_add(keytable, true, true,
+                                         dst_key_name(key), &key, NULL),
                         ISC_R_SUCCESS);
 
        /* Add a null key */
@@ -216,7 +218,8 @@ add_test(void **state) {
         * nextkeynode() should still return NOTFOUND.
         */
        create_key(257, 3, 5, "example.com", keystr1, &key);
-       assert_int_equal(dns_keytable_add(keytable, false, false, &key),
+       assert_int_equal(dns_keytable_add(keytable, false, false,
+                                         dst_key_name(key), &key, NULL),
                         ISC_R_SUCCESS);
        assert_int_equal(dns_keytable_nextkeynode(keytable, keynode,
                                                  &next_keynode),
@@ -225,7 +228,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, &key),
+       assert_int_equal(dns_keytable_add(keytable, false, false,
+                                         dst_key_name(key), &key, NULL),
                         ISC_R_SUCCESS);
        assert_int_equal(dns_keytable_find(keytable, str2name("example.com"),
                                           &keynode),
@@ -259,7 +263,8 @@ add_test(void **state) {
         * ISC_R_NOTFOUND and that the added key is an initializing key.
         */
        create_key(257, 3, 5, "managed.com", keystr2, &key);
-       assert_int_equal(dns_keytable_add(keytable, true, true, &key),
+       assert_int_equal(dns_keytable_add(keytable, true, true,
+                                         dst_key_name(key), &key, NULL),
                         ISC_R_SUCCESS);
        assert_int_equal(dns_keytable_find(keytable, str2name("managed.com"),
                                           &keynode),
@@ -278,7 +283,8 @@ add_test(void **state) {
         * 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, &key),
+       assert_int_equal(dns_keytable_add(keytable, true, false,
+                                         dst_key_name(key), &key, NULL),
                         ISC_R_SUCCESS);
        assert_int_equal(dns_keytable_find(keytable, str2name("managed.com"),
                                           &keynode),
@@ -302,7 +308,8 @@ add_test(void **state) {
         * that the added key is an initializing key.
         */
        create_key(257, 3, 5, "two.com", keystr1, &key);
-       assert_int_equal(dns_keytable_add(keytable, true, true, &key),
+       assert_int_equal(dns_keytable_add(keytable, true, true,
+                                         dst_key_name(key), &key, NULL),
                         ISC_R_SUCCESS);
        assert_int_equal(dns_keytable_find(keytable, str2name("two.com"),
                                           &keynode),
@@ -319,7 +326,8 @@ add_test(void **state) {
         * ISC_R_NOTFOUND and that the added key is not an initializing key.
         */
        create_key(257, 3, 5, "two.com", keystr2, &key);
-       assert_int_equal(dns_keytable_add(keytable, true, false, &key),
+       assert_int_equal(dns_keytable_add(keytable, true, false,
+                                         dst_key_name(key), &key, NULL),
                         ISC_R_SUCCESS);
        assert_int_equal(dns_keytable_find(keytable, str2name("two.com"),
                                           &keynode),
@@ -337,7 +345,8 @@ add_test(void **state) {
         * 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, &key),
+       assert_int_equal(dns_keytable_add(keytable, true, false,
+                                         dst_key_name(key), &key, NULL),
                         ISC_R_SUCCESS);
        assert_int_equal(dns_keytable_find(keytable, str2name("two.com"),
                                           &keynode),
@@ -363,7 +372,8 @@ add_test(void **state) {
                                           &null_keynode),
                         ISC_R_SUCCESS);
        create_key(257, 3, 5, "null.example", keystr2, &key);
-       assert_int_equal(dns_keytable_add(keytable, false, false, &key),
+       assert_int_equal(dns_keytable_add(keytable, false, false,
+                                         dst_key_name(key), &key, NULL),
                         ISC_R_SUCCESS);
        assert_int_equal(dns_keytable_find(keytable, str2name("null.example"),
                                           &keynode),
@@ -663,7 +673,8 @@ nta_test(void **state) {
        assert_int_equal(result, ISC_R_SUCCESS);
 
        create_key(257, 3, 5, "example", keystr1, &key);
-       result = dns_keytable_add(keytable, false, false, &key);
+       result = dns_keytable_add(keytable, false, false,
+                                         dst_key_name(key), &key, NULL),
        assert_int_equal(result, ISC_R_SUCCESS);
 
        isc_stdtime_get(&now);
index 0988db5d2750a98080aae564e99827c07d3982fb..b1a02a0f68f09c7b2b14b94377f2398f34c03630 100644 (file)
@@ -463,6 +463,7 @@ dns_keynode_attach
 dns_keynode_create
 dns_keynode_detach
 dns_keynode_detachall
+dns_keynode_dsset
 dns_keynode_initial
 dns_keynode_key
 dns_keynode_managed
index 41af9487ac37d659cf1a25a91c3adf62a3785728..9e8591610475a7101093659c35281480a01e1273 100644 (file)
@@ -3985,7 +3985,8 @@ trust_key(dns_zone_t *zone, dns_name_t *keyname,
                goto failure;
 
        CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
-       CHECK(dns_keytable_add(sr, true, initial, &dstkey));
+       CHECK(dns_keytable_add(sr, true, initial,
+                              dst_key_name(dstkey), &dstkey, NULL));
        dns_keytable_detach(&sr);
 
   failure: