]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
read DS trust anchors in named.conf
authorEvan Hunt <each@isc.org>
Mon, 16 Sep 2019 06:14:51 +0000 (23:14 -0700)
committerEvan Hunt <each@isc.org>
Fri, 15 Nov 2019 23:47:17 +0000 (15:47 -0800)
(but they aren't used for anything yet)

bin/named/server.c
bin/tests/system/checkconf/bad-static-initial-1.conf [new file with mode: 0644]
bin/tests/system/checkconf/bad-static-initial-2.conf [new file with mode: 0644]
bin/tests/system/checkconf/bad-static-initial-3.conf [new file with mode: 0644]
bin/tests/system/checkconf/bad-static-initial-4.conf [new file with mode: 0644]
bin/tests/system/checkconf/check-root-static-ds.conf [new file with mode: 0644]
bin/tests/system/checkconf/good-initial-ds.conf [new file with mode: 0644]
bin/tests/system/checkconf/good-static-ds.conf [new file with mode: 0644]
bin/tests/system/checkconf/tests.sh
lib/bind9/check.c

index d68d01ae7e4edafe28688c10168c8d9c92836eb9..d6f912cbfbcbdac1ea64f80ae1cb7a0e211691c8 100644 (file)
@@ -698,19 +698,20 @@ 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 **target,
-             const char **keynamestrp, isc_mem_t *mctx)
+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)
 {
        dns_rdata_dnskey_t keystruct;
+       dns_rdata_ds_t *ds = NULL;
        uint32_t n1, n2, n3;
-       const char *datastr = NULL, *keynamestr = NULL;
+       const char *datastr = NULL, *namestr = NULL;
        unsigned char data[4096];
        isc_buffer_t databuf;
        unsigned char rrdata[4096];
        isc_buffer_t rrdatabuf;
        isc_region_t r;
-       dns_fixedname_t fkeyname;
-       dns_name_t *keyname = NULL;
+       dns_fixedname_t fname;
+       dns_name_t *name = NULL;
        isc_buffer_t namebuf;
        isc_result_t result;
        dst_key_t *dstkey = NULL;
@@ -723,8 +724,9 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **target,
                TRUSTED
        } anchortype;
 
-       REQUIRE(target != NULL && *target == NULL);
-       REQUIRE(keynamestrp != NULL && *keynamestrp == NULL);
+       REQUIRE(keyp != NULL && *keyp == NULL);
+       REQUIRE(dsp != NULL && *dsp == NULL);
+       REQUIRE(namestrp != NULL && *namestrp == NULL);
 
        /* if DNSKEY, flags; if DS, key tag */
        n1 = cfg_obj_asuint32(cfg_tuple_get(key, "n1"));
@@ -735,13 +737,13 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **target,
        /* if DNSKEY, algorithm; if DS, digest type */
        n3 = cfg_obj_asuint32(cfg_tuple_get(key, "n3"));
 
-       keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
-       *keynamestrp = keynamestr;
+       namestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
+       *namestrp = namestr;
 
-       keyname = dns_fixedname_initname(&fkeyname);
-       isc_buffer_constinit(&namebuf, keynamestr, strlen(keynamestr));
-       isc_buffer_add(&namebuf, strlen(keynamestr));
-       CHECK(dns_name_fromtext(keyname, &namebuf, dns_rootname, 0, NULL));
+       name = dns_fixedname_initname(&fname);
+       isc_buffer_constinit(&namebuf, namestr, strlen(namestr));
+       isc_buffer_add(&namebuf, strlen(namestr));
+       CHECK(dns_name_fromtext(name, &namebuf, dns_rootname, 0, NULL));
 
        if (*initialp) {
                atstr = cfg_obj_asstring(cfg_tuple_get(key, "anchortype"));
@@ -760,7 +762,7 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **target,
                        cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR,
                                    "key '%s': "
                                    "invalid initialization method '%s'",
-                                   keynamestr, atstr);
+                                   namestr, atstr);
                        result = ISC_R_FAILURE;
                        goto cleanup;
                }
@@ -768,6 +770,9 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **target,
                anchortype = TRUSTED;
        }
 
+       isc_buffer_init(&databuf, data, sizeof(data));
+       isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
+
        switch(anchortype) {
        case INIT_DNSKEY:
        case STATIC_DNSKEY:
@@ -803,9 +808,6 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **target,
                keystruct.protocol = (uint8_t)n2;
                keystruct.algorithm = (uint8_t)n3;
 
-               isc_buffer_init(&databuf, data, sizeof(data));
-               isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
-
                datastr = cfg_obj_asstring(cfg_tuple_get(key, "data"));
                CHECK(isc_base64_decodestring(datastr, &databuf));
                isc_buffer_usedregion(&databuf, &r);
@@ -815,20 +817,65 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **target,
                CHECK(dns_rdata_fromstruct(NULL, keystruct.common.rdclass,
                                           keystruct.common.rdtype,
                                           &keystruct, &rrdatabuf));
-               CHECK(dst_key_fromdns(keyname, dns_rdataclass_in,
+               CHECK(dst_key_fromdns(name, dns_rdataclass_in,
                                      &rrdatabuf, mctx, &dstkey));
 
-               *target = dstkey;
+               *keyp = dstkey;
                break;
 
        case INIT_DS:
        case STATIC_DS:
-               cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR,
-                           "key '%s': "
-                           "initialization method '%s' is "
-                           "not yet supported", keynamestr, atstr);
-               result = ISC_R_FAILURE;
-               goto cleanup;
+               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 (n1 > 0xffff) {
+                       CHECKM(ISC_R_RANGE, "key tag");
+               }
+               if (n2 > 0xff) {
+                       CHECKM(ISC_R_RANGE, "key algorithm");
+               }
+               if (n3 > 0xff) {
+                       CHECKM(ISC_R_RANGE, "digest type");
+               }
+
+               ds->key_tag = (uint16_t)n1;
+               ds->algorithm = (uint8_t)n2;
+               ds->digest_type = (uint8_t)n3;
+
+               datastr = cfg_obj_asstring(cfg_tuple_get(key, "data"));
+               CHECK(isc_hex_decodestring(datastr, &databuf));
+               isc_buffer_usedregion(&databuf, &r);
+
+               switch (ds->digest_type) {
+               case DNS_DSDIGEST_SHA1:
+                       if (r.length != ISC_SHA1_DIGESTLENGTH) {
+                               CHECK(ISC_R_UNEXPECTEDEND);
+                       }
+                       break;
+               case DNS_DSDIGEST_SHA256:
+                       if (r.length != ISC_SHA256_DIGESTLENGTH) {
+                               CHECK(ISC_R_UNEXPECTEDEND);
+                       }
+                       break;
+               case DNS_DSDIGEST_SHA384:
+                       if (r.length != ISC_SHA384_DIGESTLENGTH) {
+                               CHECK(ISC_R_UNEXPECTEDEND);
+                       }
+                       break;
+               }
+
+               ds->mctx = mctx;
+               ds->length = r.length;
+               ds->digest = isc_mem_allocate(mctx, r.length);
+               memmove(ds->digest, r.base, r.length);
+
+               *dsp = ds;
+               ds = NULL;
+               break;
 
        default:
                INSIST(0);
@@ -842,6 +889,11 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **target,
                dst_key_free(&dstkey);
        }
 
+       if (ds != NULL) {
+               dns_rdata_freestruct(ds);
+               isc_mem_put(mctx, ds, sizeof(*ds));
+       }
+
        return (result);
 }
 
@@ -861,23 +913,45 @@ 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)
 {
-       const dns_name_t *keyname = NULL;
-       const char *keynamestr = NULL;
+       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;
        isc_result_t result;
        bool initializing = managed;
 
-       result = ta_fromconfig(key, &initializing, &dstkey, &keynamestr, mctx);
+       result = ta_fromconfig(key, &initializing, &dstkey, &ds,
+                              &namestr, mctx);
 
        switch (result) {
        case ISC_R_SUCCESS:
                /*
-                * Key was parsed correctly, its algorithm is supported by the
-                * crypto library, and it is not revoked.
+                * 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.
                 */
-               keyname = dst_key_name(dstkey);
-               keyalg = dst_key_alg(dstkey);
+               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;
+               }
                break;
        case DST_R_UNSUPPORTEDALG:
        case DST_R_BADKEYTYPE:
@@ -889,7 +963,7 @@ process_key(const cfg_obj_t *key, dns_keytable_t *secroots,
                cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING,
                            "ignoring %s for '%s': %s",
                            initializing ? "initial-key" : "static-key",
-                           keynamestr, isc_result_totext(result));
+                           namestr, isc_result_totext(result));
                return (ISC_R_SUCCESS);
        case DST_R_NOCRYPTO:
                /*
@@ -898,7 +972,7 @@ process_key(const cfg_obj_t *key, dns_keytable_t *secroots,
                cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR,
                            "ignoring %s for '%s': no crypto support",
                            initializing ? "initial-key" : "static-key",
-                           keynamestr);
+                           namestr);
                return (result);
        default:
                /*
@@ -909,7 +983,7 @@ process_key(const cfg_obj_t *key, dns_keytable_t *secroots,
                cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR,
                            "configuring %s for '%s': %s",
                            initializing ? "initial-key" : "static-key",
-                           keynamestr, isc_result_totext(result));
+                           namestr, isc_result_totext(result));
                return (ISC_R_FAILURE);
        }
 
@@ -931,7 +1005,7 @@ process_key(const cfg_obj_t *key, dns_keytable_t *secroots,
                cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING,
                            "ignoring %s for '%s': algorithm is disabled",
                            initializing ? "initial-key" : "static-key",
-                           keynamestr);
+                           namestr);
                goto done;
        }
 
@@ -955,6 +1029,14 @@ process_key(const cfg_obj_t *key, dns_keytable_t *secroots,
                dst_key_free(&dstkey);
        }
 
+       /*
+        * Ensure 'ds' does not leak.
+        */
+       if (ds != NULL) {
+               dns_rdata_freestruct(ds);
+               isc_mem_put(mctx, ds, sizeof(*ds));
+       }
+
        return (result);
 }
 
diff --git a/bin/tests/system/checkconf/bad-static-initial-1.conf b/bin/tests/system/checkconf/bad-static-initial-1.conf
new file mode 100644 (file)
index 0000000..406b12b
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-keys {
+       example. initial-ds 60724 5 1 "D74CF845955A0DFE604AF215E948E67D2EA94FF3";
+       example. static-ds 60724 5 2 "29E79B9064EE1A11DF3BFF19581DDFED7952C22CC204ACE17B6007EB1437E9E6";
+};
diff --git a/bin/tests/system/checkconf/bad-static-initial-2.conf b/bin/tests/system/checkconf/bad-static-initial-2.conf
new file mode 100644 (file)
index 0000000..a8805b5
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-keys {
+       example. initial-ds 60724 5 1 "D74CF845955A0DFE604AF215E948E67D2EA94FF3";
+        example. static-key 257 3 5 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbody0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQYfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuwE60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn6zqCkwuMmrU=";
+};
diff --git a/bin/tests/system/checkconf/bad-static-initial-3.conf b/bin/tests/system/checkconf/bad-static-initial-3.conf
new file mode 100644 (file)
index 0000000..53bdc2c
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-keys {
+       example. static-ds 60724 5 1 "D74CF845955A0DFE604AF215E948E67D2EA94FF3";
+        example. initial-key 257 3 5 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbody0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQYfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuwE60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn6zqCkwuMmrU=";
+};
diff --git a/bin/tests/system/checkconf/bad-static-initial-4.conf b/bin/tests/system/checkconf/bad-static-initial-4.conf
new file mode 100644 (file)
index 0000000..bc29962
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-keys {
+        example. initial-key 257 3 5 "AwEAAawvFp8GlBx8Qt6yaIqXkDe+nMkSk2HkTAG7qlVBo++AQwZ1j3Xl25IN4jsw0VTMbKUbafw9DYsVzztIwx1sNkKRLo6qP9SSkBL8RicQaafGtURtsYI3oqte5qqLve1CUpRD8J06Pg1xkOxsDlz9sQAyiQrOyvMbykJYkYrFYGLzYAgl/JtMyVVYlBl9pqxQuAPKYPOuO1axaad/wLN3+wTy/hcJfpvJpqzXlDF9bI5RmpoX/7geZ06vpcYJEoT0xkkmPlEl0ZjEDrm/WIaSWG0/CEDpHcOXFz4OEczMVpY+lnuFfKybwF1WHFn2BwVEOS6cMM6ukIjINQyrszHhWUU=";
+        example. static-key 257 3 5 "AwEAAZtP9+RAA+W33A97e+HnnH8WTXzCWiEICyWj1B6rvZ9hd50ysbody0NLx7b3vZ1bzMLxLSRAr/n3Wi0TDZ1fvCKZhennfW8Wlc7ulCvHntSQYfKHUP0YWEo84sQAqIi850N1aiddj6CidwFo9JNW/HQ+8yarfrnGMFhX2STtkE0hNJ/R6JYKmD2EH7k1nyqJd08ibrEt55DuV4BiUjyyERdVbsuwE60jVqAwCKyVBYXb2sI+zv1yPNDBIANd6KTgnq6YWzx5ZodQP3W4K7Z/Bk3EKmVCvrTKZK/ADLAKaL0/6DD07+1jXA4BiNyoZTLTapkudkGad+Rn6zqCkwuMmrU=";
+};
diff --git a/bin/tests/system/checkconf/check-root-static-ds.conf b/bin/tests/system/checkconf/check-root-static-ds.conf
new file mode 100644 (file)
index 0000000..42af9ba
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-keys {
+        . static-ds 20326 8 2 "E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D";
+};
diff --git a/bin/tests/system/checkconf/good-initial-ds.conf b/bin/tests/system/checkconf/good-initial-ds.conf
new file mode 100644 (file)
index 0000000..31939c2
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-keys {
+       example. initial-ds 60724 5 2 "29E79B9064EE1A11DF3BFF19581DDFED7952C22CC204ACE17B6007EB1437E9E6";
+};
diff --git a/bin/tests/system/checkconf/good-static-ds.conf b/bin/tests/system/checkconf/good-static-ds.conf
new file mode 100644 (file)
index 0000000..fd5b393
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+dnssec-keys {
+       example. static-ds 60724 5 2 "29E79B9064EE1A11DF3BFF19581DDFED7952C22CC204ACE17B6007EB1437E9E6";
+};
index 45e6cefb4211c59273395ec8237ef9d07b5c7766..a25753e1bf2174ca4e779bbedccd0f16c736e9f9 100644 (file)
@@ -437,7 +437,15 @@ n=`expr $n + 1`
 echo_i "check that a static root key generates a warning ($n)"
 ret=0
 $CHECKCONF check-root-static-key.conf > checkconf.out$n 2>/dev/null || ret=1
-grep "static-key entry for the root zone WILL FAIL" checkconf.out$n > /dev/null || ret=1
+grep "static entry for the root zone WILL FAIL" checkconf.out$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo_i "check that a static root DS trust anchor generates a warning ($n)"
+ret=0
+$CHECKCONF check-root-static-ds.conf > checkconf.out$n 2>/dev/null || ret=1
+grep "static entry for the root zone WILL FAIL" checkconf.out$n > /dev/null || ret=1
 if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi
 status=`expr $status + $ret`
 
index 302c3dcc0079bdff0f200dc4a027bec027a79ddf..020d49982c92a0f486c4ae1fa82620b6317ea813 100644 (file)
@@ -3119,10 +3119,10 @@ check_servers(const cfg_obj_t *config, const cfg_obj_t *voptions,
 #define ROOT_KSK_2017          0x08
 
 static isc_result_t
-check_trusted_key(const cfg_obj_t *key, bool managed,
-                 unsigned int *keyflags, isc_log_t *logctx)
+check_trust_anchor(const cfg_obj_t *key, bool managed,
+                  unsigned int *flagsp, isc_log_t *logctx)
 {
-       const char *keystr = NULL, *keynamestr = NULL;
+       const char *str = NULL, *namestr = NULL;
        dns_fixedname_t fkeyname;
        dns_name_t *keyname = NULL;
        isc_buffer_t b;
@@ -3130,7 +3130,7 @@ check_trusted_key(const cfg_obj_t *key, bool managed,
        isc_result_t result = ISC_R_SUCCESS;
        isc_result_t tresult;
        uint32_t n1, n2, n3;
-       unsigned char keydata[4096];
+       unsigned char data[4096];
        const char *atstr = NULL;
        enum {
                INIT_DNSKEY,
@@ -3142,8 +3142,8 @@ check_trusted_key(const cfg_obj_t *key, bool managed,
 
        /*
         * The 2010 and 2017 IANA root keys - these are used below
-        * to check the contents of trusted-key, initial-key and
-        * static-key configurations.
+        * to check the contents of trusted, initial and
+        * static trust anchor configurations.
         */
        static const unsigned char root_ksk_2010[] = {
                0x03, 0x01, 0x00, 0x01, 0xa8, 0x00, 0x20, 0xa9,
@@ -3215,7 +3215,17 @@ check_trusted_key(const cfg_obj_t *key, bool managed,
                0x67, 0xe9, 0x4c, 0x0d, 0x47, 0x50, 0x24, 0x51,
                0x35, 0x7b, 0xe1, 0xb5
        };
-
+       static const unsigned char root_ds_1_2017[] = {
+               0xae, 0x1e, 0xa5, 0xb9, 0x74, 0xd4, 0xc8, 0x58,
+               0xb7, 0x40, 0xbd, 0x03, 0xe3, 0xce, 0xd7, 0xeb,
+               0xfc, 0xbd, 0x17, 0x24
+       };
+       static const unsigned char root_ds_2_2017[] = {
+               0xe0, 0x6d, 0x44, 0xb8, 0x0b, 0x8f, 0x1d, 0x39,
+               0xa9, 0x5c, 0x0b, 0x0d, 0x7c, 0x65, 0xd0, 0x84,
+               0x58, 0xe8, 0x80, 0x40, 0x9b, 0xbc, 0x68, 0x34,
+               0x57, 0x10, 0x42, 0x37, 0xc7, 0xf8, 0xec, 0x8D
+       };
 
        /* if DNSKEY, flags; if DS, key tag */
        n1 = cfg_obj_asuint32(cfg_tuple_get(key, "n1"));
@@ -3226,11 +3236,11 @@ check_trusted_key(const cfg_obj_t *key, bool managed,
        /* if DNSKEY, algorithm; if DS, digest type */
        n3 = cfg_obj_asuint32(cfg_tuple_get(key, "n3"));
 
-       keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
+       namestr = cfg_obj_asstring(cfg_tuple_get(key, "name"));
 
        keyname = dns_fixedname_initname(&fkeyname);
-       isc_buffer_constinit(&b, keynamestr, strlen(keynamestr));
-       isc_buffer_add(&b, strlen(keynamestr));
+       isc_buffer_constinit(&b, namestr, strlen(namestr));
+       isc_buffer_add(&b, strlen(namestr));
        result = dns_name_fromtext(keyname, &b, dns_rootname, 0, NULL);
        if (result != ISC_R_SUCCESS) {
                cfg_obj_log(key, logctx, ISC_LOG_WARNING, "bad key name: %s\n",
@@ -3255,7 +3265,7 @@ check_trusted_key(const cfg_obj_t *key, bool managed,
                        cfg_obj_log(key, logctx, ISC_LOG_ERROR,
                                    "key '%s': "
                                    "invalid initialization method '%s'",
-                                   keynamestr, atstr);
+                                   namestr, atstr);
                        result = ISC_R_FAILURE;
 
                        /*
@@ -3282,7 +3292,7 @@ check_trusted_key(const cfg_obj_t *key, bool managed,
                        cfg_obj_log(key, logctx, ISC_LOG_WARNING,
                                    "key flags revoke bit set");
                }
-               if (n2 > 0xff) {
+               if (n2 > 0xff)  {
                        cfg_obj_log(key, logctx, ISC_LOG_ERROR,
                                    "protocol too big: %u", n2);
                        result = ISC_R_RANGE;
@@ -3293,10 +3303,10 @@ check_trusted_key(const cfg_obj_t *key, bool managed,
                        result = ISC_R_RANGE;
                }
 
-               isc_buffer_init(&b, keydata, sizeof(keydata));
+               isc_buffer_init(&b, data, sizeof(data));
 
-               keystr = cfg_obj_asstring(cfg_tuple_get(key, "data"));
-               tresult = isc_base64_decodestring(keystr, &b);
+               str = cfg_obj_asstring(cfg_tuple_get(key, "data"));
+               tresult = isc_base64_decodestring(str, &b);
 
                if (tresult != ISC_R_SUCCESS) {
                        cfg_obj_log(key, logctx, ISC_LOG_ERROR,
@@ -3310,7 +3320,7 @@ check_trusted_key(const cfg_obj_t *key, bool managed,
                        {
                                cfg_obj_log(key, logctx, ISC_LOG_WARNING,
                                            "%s '%s' has a weak exponent",
-                                           atstr, keynamestr);
+                                           atstr, namestr);
                        }
                }
 
@@ -3319,36 +3329,85 @@ check_trusted_key(const cfg_obj_t *key, bool managed,
                        /*
                         * Flag any use of a root key, regardless of content.
                         */
-                       *keyflags |=
+                       *flagsp |=
                                (managed ? ROOT_KSK_MANAGED : ROOT_KSK_STATIC);
 
+
                        if (n1 == 257 && n2 == 3 && n3 == 8 &&
                            (isc_buffer_usedlength(&b) ==
                             sizeof(root_ksk_2010)) &&
-                           memcmp(keydata, root_ksk_2010,
+                           memcmp(data, root_ksk_2010,
                                   sizeof(root_ksk_2010)) == 0)
                        {
-                               *keyflags |= ROOT_KSK_2010;
+                               *flagsp |= ROOT_KSK_2010;
                        }
 
                        if (n1 == 257 && n2 == 3 && n3 == 8 &&
                            (isc_buffer_usedlength(&b) ==
                             sizeof(root_ksk_2017)) &&
-                           memcmp(keydata, root_ksk_2017,
+                           memcmp(data, root_ksk_2017,
                                   sizeof(root_ksk_2017)) == 0)
                        {
-                               *keyflags |= ROOT_KSK_2017;
+                               *flagsp |= ROOT_KSK_2017;
                        }
                }
                break;
 
        case INIT_DS:
        case STATIC_DS:
-               cfg_obj_log(key, logctx, ISC_LOG_ERROR,
-                           "key '%s': "
-                           "initialization method '%s' is "
-                           "not yet supported", keynamestr, atstr);
-               result = ISC_R_FAILURE;
+               if (n1 > 0xffff) {
+                       cfg_obj_log(key, logctx, ISC_LOG_ERROR,
+                                   "key tag too big: %u", n1);
+                       result = ISC_R_RANGE;
+               }
+               if (n2 > 0xff) {
+                       cfg_obj_log(key, logctx, ISC_LOG_ERROR,
+                                   "algorithm too big: %u\n", n2);
+                       result = ISC_R_RANGE;
+               }
+               if (n3 > 0xff) {
+                       cfg_obj_log(key, logctx, ISC_LOG_ERROR,
+                                   "digest type too big: %u", 32);
+                       result = ISC_R_RANGE;
+               }
+
+               isc_buffer_init(&b, data, sizeof(data));
+
+               str = cfg_obj_asstring(cfg_tuple_get(key, "data"));
+               tresult = isc_hex_decodestring(str, &b);
+
+               if (tresult != ISC_R_SUCCESS) {
+                       cfg_obj_log(key, logctx, ISC_LOG_ERROR,
+                                   "%s", isc_result_totext(tresult));
+                       result = ISC_R_FAILURE;
+               }
+               if (result == ISC_R_SUCCESS &&
+                   dns_name_equal(keyname, dns_rootname)) {
+                       /*
+                        * Flag any use of a root key, regardless of content.
+                        */
+                       *flagsp |=
+                               (managed ? ROOT_KSK_MANAGED : ROOT_KSK_STATIC);
+
+                       if (n1 == 20326 && n2 == 8 && n3 == 1 &&
+                           (isc_buffer_usedlength(&b) ==
+                            sizeof(root_ds_1_2017)) &&
+                           memcmp(data, root_ds_1_2017,
+                                  sizeof(root_ds_1_2017)) == 0)
+                       {
+                               *flagsp |= ROOT_KSK_2017;
+                       }
+
+                       if (n1 == 20326 && n2 == 8 && n3 == 2 &&
+                           (isc_buffer_usedlength(&b) ==
+                            sizeof(root_ds_2_2017)) &&
+                           memcmp(data, root_ds_2_2017,
+                                  sizeof(root_ds_2_2017)) == 0)
+                       {
+                               *flagsp |= ROOT_KSK_2017;
+                       }
+               }
+               break;
        }
 
  cleanup:
@@ -3964,8 +4023,7 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
                                     element2 = cfg_list_next(element2))
                                {
                                        obj = cfg_listelt_value(element2);
-                                       tresult = check_trusted_key(obj,
-                                                                   false,
+                                       tresult = check_trust_anchor(obj, false,
                                                                    &flags,
                                                                    logctx);
                                        if (tresult != ISC_R_SUCCESS) {
@@ -3980,7 +4038,8 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
                                            "trusted-keys entry for the root "
                                            "zone WILL FAIL after key "
                                            "rollover - use dnssec-keys "
-                                           "with initial-key instead.");
+                                           "with initial-key "
+                                           "or initial-ds instead.");
                        }
 
                        tflags |= flags;
@@ -4024,8 +4083,7 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
                                     element2 = cfg_list_next(element2))
                                {
                                        obj = cfg_listelt_value(element2);
-                                       tresult = check_trusted_key(obj,
-                                                                   true,
+                                       tresult = check_trust_anchor(obj, true,
                                                                    &flags,
                                                                    logctx);
                                        if (tresult != ISC_R_SUCCESS) {
@@ -4037,10 +4095,11 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
                        if ((flags & ROOT_KSK_STATIC) != 0) {
                                cfg_obj_log(check_keys[i], logctx,
                                            ISC_LOG_WARNING,
-                                           "static-key entry for the root "
+                                           "static entry for the root "
                                            "zone WILL FAIL after key "
                                            "rollover - use dnssec-keys "
-                                           "with initial-key instead.");
+                                           "with initial-key "
+                                           "or initial-ds instead.");
                        }
 
                        if ((flags & ROOT_KSK_2010) != 0 &&
@@ -4067,7 +4126,7 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
        if ((dflags & ROOT_KSK_ANY) == ROOT_KSK_ANY) {
                keys = (view_dkeys != NULL) ? view_dkeys : global_dkeys;
                cfg_obj_log(keys, logctx, ISC_LOG_WARNING,
-                           "both initial-key and static-key entries for the "
+                           "both initial and static entries for the "
                            "root zone are present");
        }