]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
3387. [func] Support for a DS digest can be disabled at
authorMark Andrews <marka@isc.org>
Wed, 3 Oct 2012 02:38:43 +0000 (12:38 +1000)
committerMark Andrews <marka@isc.org>
Wed, 3 Oct 2012 02:38:43 +0000 (12:38 +1000)
                        runtime with disable-ds-digests. [RT #21581]

22 files changed:
CHANGES
bin/named/named.conf.docbook
bin/named/server.c
bin/tests/system/conf.sh.in
configure.in
doc/arm/Bv9ARM-book.xml
doc/misc/options
lib/bind9/check.c
lib/dns/ds.c
lib/dns/dst_api.c
lib/dns/include/dns/ds.h
lib/dns/include/dns/resolver.h
lib/dns/include/dns/types.h
lib/dns/include/dst/dst.h
lib/dns/rcode.c
lib/dns/rdata.c
lib/dns/rdata/generic/dlv_32769.c
lib/dns/rdata/generic/ds_43.c
lib/dns/resolver.c
lib/dns/validator.c
lib/dns/win32/libdns.def
lib/isccfg/namedconf.c

diff --git a/CHANGES b/CHANGES
index 00c888c6dbc8aa42b7ffa12500747ce288aad656..e6ab1262d0be10d118f50bbfd439fa9ab225f99d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+3387.  [func]          Support for a DS digest can be disabled at
+                       runtime with disable-ds-digests. [RT #21581]
+
 3386.  [bug]           Address locking violation when generating new NSEC /
                        NSEC3 chains. [RT #31224]
 
index 338d80599397989eeb879a42b3c239a39c940767..1063ddf2d50e746adc234b2e2618cfc024036e8e 100644 (file)
@@ -284,6 +284,7 @@ options {
        max-udp-size <replaceable>integer</replaceable>;
        root-delegation-only <optional> exclude { <replaceable>quoted_string</replaceable>; ... } </optional>;
        disable-algorithms <replaceable>string</replaceable> { <replaceable>string</replaceable>; ... };
+       disable-ds-digests <replaceable>string</replaceable> { <replaceable>string</replaceable>; ... };
        dnssec-enable <replaceable>boolean</replaceable>;
        dnssec-validation <replaceable>boolean</replaceable>;
        dnssec-lookaside ( <replaceable>auto</replaceable> | <replaceable>no</replaceable> | <replaceable>domain</replaceable> trust-anchor <replaceable>domain</replaceable> );
@@ -472,6 +473,7 @@ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable>
        max-udp-size <replaceable>integer</replaceable>;
        root-delegation-only <optional> exclude { <replaceable>quoted_string</replaceable>; ... } </optional>;
        disable-algorithms <replaceable>string</replaceable> { <replaceable>string</replaceable>; ... };
+       disable-ds-digests <replaceable>string</replaceable> { <replaceable>string</replaceable>; ... };
        dnssec-enable <replaceable>boolean</replaceable>;
        dnssec-validation <replaceable>boolean</replaceable>;
        dnssec-lookaside ( <replaceable>auto</replaceable> | <replaceable>no</replaceable> | <replaceable>domain</replaceable> trust-anchor <replaceable>domain</replaceable> );
index 27e676489e0f5dca876d7300f22b88e0b3bf8374..5264042a4c2c5456e23aa03038bbc87248a7342c 100644 (file)
@@ -1216,6 +1216,48 @@ disable_algorithms(const cfg_obj_t *disabled, dns_resolver_t *resolver) {
        return (result);
 }
 
+static isc_result_t
+disable_ds_digests(const cfg_obj_t *disabled, dns_resolver_t *resolver) {
+       isc_result_t result;
+       const cfg_obj_t *digests;
+       const cfg_listelt_t *element;
+       const char *str;
+       dns_fixedname_t fixed;
+       dns_name_t *name;
+       isc_buffer_t b;
+
+       dns_fixedname_init(&fixed);
+       name = dns_fixedname_name(&fixed);
+       str = cfg_obj_asstring(cfg_tuple_get(disabled, "name"));
+       isc_buffer_init(&b, str, strlen(str));
+       isc_buffer_add(&b, strlen(str));
+       CHECK(dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
+
+       digests = cfg_tuple_get(disabled, "digests");
+       for (element = cfg_list_first(digests);
+            element != NULL;
+            element = cfg_list_next(element))
+       {
+               isc_textregion_t r;
+               dns_dsdigest_t digest;
+
+               DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base);
+               r.length = strlen(r.base);
+
+               /* disable_ds_digests handles numeric values. */
+               result = dns_dsdigest_fromtext(&digest, &r);
+               if (result != ISC_R_SUCCESS) {
+                       cfg_obj_log(cfg_listelt_value(element),
+                                   ns_g_lctx, ISC_LOG_ERROR,
+                                   "invalid algorithm");
+                       CHECK(result);
+               }
+               CHECK(dns_resolver_disable_ds_digest(resolver, name, digest));
+       }
+ cleanup:
+       return (result);
+}
+
 static isc_boolean_t
 on_disable_list(const cfg_obj_t *disablelist, dns_name_t *zonename) {
        const cfg_listelt_t *element;
@@ -2275,6 +2317,20 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
                                                 view->resolver));
        }
 
+       /*
+        * Set supported DS/DLV digest types.
+        */
+       dns_resolver_reset_ds_digests(view->resolver);
+       disabled = NULL;
+       (void)ns_config_get(maps, "disable-ds-digests", &disabled);
+       if (disabled != NULL) {
+               for (element = cfg_list_first(disabled);
+                    element != NULL;
+                    element = cfg_list_next(element))
+                       CHECK(disable_ds_digests(cfg_listelt_value(element),
+                                                view->resolver));
+       }
+
        /*
         * A global or view "forwarders" option, if present,
         * creates an entry for "." in the forwarding table.
index d67470800adb5e22ce43f65787ca0af3df45a1ce..c9a2fb26067858d8f5c7a9713d7079bb049b2249 100644 (file)
@@ -56,8 +56,8 @@ VERIFY=$TOP/bin/dnssec/dnssec-verify
 # v6synth
 SUBDIRS="acl allow_query addzone autosign builtin cacheclean checkconf
         @CHECKDS@ checknames checkzone database dlv dlvauto dlz dlzexternal
-         dname dns64 dnssec ecdsa forward glue gost ixfr inline limits
-        logfileconfig lwresd masterfile masterformat metadata notify
+        dname dns64 dnssec dsdigest ecdsa forward glue gost ixfr inline
+        limits logfileconfig lwresd masterfile masterformat metadata notify
         nsupdate pending pkcs11 redirect resolver rndc rpz rrsetorder
         rsabigexponent sortlist smartsign staticstub statistics stub
         tkey tsig tsiggss unknown upforwd verify views xfer xferquota
index 2b857bd4dcd17373a1d0263a24200b2f7a554738..69a84f14d0a75fd45a4a37ba680cd102d74ef87f 100644 (file)
@@ -3595,6 +3595,7 @@ AC_CONFIG_FILES([
        bin/tests/system/dlz/prereq.sh
        bin/tests/system/dlzexternal/Makefile
        bin/tests/system/dlzexternal/ns1/named.conf
+       bin/tests/system/dsdigest/prereq.sh
        bin/tests/system/ecdsa/prereq.sh
        bin/tests/system/filter-aaaa/Makefile
        bin/tests/system/gost/prereq.sh
index c3eb51aea8491ff0f4905689d83e78cde27d6a24..eae919fed5f5de1af735f018cb2ce86240bda2f3 100644 (file)
@@ -5340,6 +5340,8 @@ badresp:1,adberr:0,findfail:0,valfail:0]
     <optional> querylog <replaceable>yes_or_no</replaceable> ; </optional>
     <optional> disable-algorithms <replaceable>domain</replaceable> { <replaceable>algorithm</replaceable>;
                                 <optional> <replaceable>algorithm</replaceable>; </optional> }; </optional>
+    <optional> disable-ds-digests <replaceable>domain</replaceable> { <replaceable>digest_type</replaceable>;
+                                <optional> <replaceable>digest_type</replaceable>; </optional> }; </optional>
     <optional> acache-enable <replaceable>yes_or_no</replaceable> ; </optional>
     <optional> acache-cleaning-interval <replaceable>number</replaceable>; </optional>
     <optional> max-acache-size <replaceable>size_spec</replaceable> ; </optional>
@@ -5871,8 +5873,33 @@ options {
                 specified name.
                 Multiple <command>disable-algorithms</command>
                 statements are allowed.
-                Only the most specific will be applied.
+                Only the best match <command>disable-algorithms</command>
+               clause will be used to determine which algorithms are used.
               </para>
+              <para>
+               If all supported algorithms are disabled, the zones covered
+               by the <command>disable-algorithms</command> will be treated
+               as insecure.
+              </para>
+            </listitem>
+          </varlistentry>
+
+          <varlistentry>
+            <term><command>disable-ds-digests</command></term>
+            <listitem>
+              <para>
+                Disable the specified DS/DLV digest types at and below the
+                specified name.
+                Multiple <command>disable-ds-digests</command>
+                statements are allowed.
+                Only the best match <command>disable-ds-digests</command>
+               clause will be used to determine which digest types are used.
+              </para>
+             <para>
+               If all supported digest types are disabled, the zones covered
+               by the <command>disable-ds-digests</command> will be treated
+               as insecure.
+             </para>
             </listitem>
           </varlistentry>
 
index 57641e7c11b7d460386c148e8863f81a3f3ea2f3..e38357319a3ad6aa6892fe572ee90200e34db337 100644 (file)
@@ -101,6 +101,7 @@ options {
         dialup <dialuptype>;
         directory <quoted_string>;
         disable-algorithms <string> { <string>; ... };
+        disable-ds-digests <string> { <string>; ... };
         disable-empty-zone <string>;
         dns64 <netprefix> {
                 break-dnssec <boolean>;
index 9a14bfe86db5f2ca0bdad54f36d734266025da69..6c0407a6aab311b26c3cd7789c70b9038e8a5044 100644 (file)
@@ -286,12 +286,61 @@ disabled_algorithms(const cfg_obj_t *disabled, isc_log_t *logctx) {
                r.length = strlen(r.base);
 
                tresult = dns_secalg_fromtext(&alg, &r);
-               if (tresult != ISC_R_SUCCESS) {
+               if (tresult != ISC_R_SUCCESS) {
                        cfg_obj_log(cfg_listelt_value(element), logctx,
                                    ISC_LOG_ERROR, "invalid algorithm '%s'",
                                    r.base);
                        result = tresult;
-               }
+               }
+       }
+       return (result);
+}
+
+static isc_result_t
+disabled_ds_digests(const cfg_obj_t *disabled, isc_log_t *logctx) {
+       isc_result_t result = ISC_R_SUCCESS;
+       isc_result_t tresult;
+       const cfg_listelt_t *element;
+       const char *str;
+       isc_buffer_t b;
+       dns_fixedname_t fixed;
+       dns_name_t *name;
+       const cfg_obj_t *obj;
+
+       dns_fixedname_init(&fixed);
+       name = dns_fixedname_name(&fixed);
+       obj = cfg_tuple_get(disabled, "name");
+       str = cfg_obj_asstring(obj);
+       isc_buffer_init(&b, str, strlen(str));
+       isc_buffer_add(&b, strlen(str));
+       tresult = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
+       if (tresult != ISC_R_SUCCESS) {
+               cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+                           "bad domain name '%s'", str);
+               result = tresult;
+       }
+
+       obj = cfg_tuple_get(disabled, "digests");
+
+       for (element = cfg_list_first(obj);
+            element != NULL;
+            element = cfg_list_next(element))
+       {
+               isc_textregion_t r;
+               dns_dsdigest_t digest;
+               isc_result_t tresult;
+
+               DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base);
+               r.length = strlen(r.base);
+
+               /* works with a numeric argument too */
+               tresult = dns_dsdigest_fromtext(&digest, &r);
+               if (tresult != ISC_R_SUCCESS) {
+                       cfg_obj_log(cfg_listelt_value(element), logctx,
+                                   ISC_LOG_ERROR, "invalid digest type '%s'",
+                                   r.base);
+                       result = tresult;
+               }
        }
        return (result);
 }
@@ -869,6 +918,23 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx,
                }
        }
 
+       /*
+        * Set supported DS/DLV digest types.
+        */
+       obj = NULL;
+       (void)cfg_map_get(options, "disable-ds-digests", &obj);
+       if (obj != NULL) {
+               for (element = cfg_list_first(obj);
+                    element != NULL;
+                    element = cfg_list_next(element))
+               {
+                       obj = cfg_listelt_value(element);
+                       tresult = disabled_ds_digests(obj, logctx);
+                       if (tresult != ISC_R_SUCCESS)
+                               result = tresult;
+               }
+       }
+
        dns_fixedname_init(&fixed);
        name = dns_fixedname_name(&fixed);
 
index e72ecbb6cc2cf99faf34ecce0e56bda9b8199450..8eb31d30736a9f716d99fdacf3a49d61bb2883f6 100644 (file)
@@ -67,7 +67,7 @@ dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
        REQUIRE(key != NULL);
        REQUIRE(key->type == dns_rdatatype_dnskey);
 
-       if (!dns_ds_digest_supported(digest_type))
+       if (!dst_ds_digest_supported(digest_type))
                return (ISC_R_NOTIMPLEMENTED);
 
        dns_fixedname_init(&fname);
@@ -167,17 +167,3 @@ dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
        return (dns_rdata_fromstruct(rdata, key->rdclass, dns_rdatatype_ds,
                                     &ds, &b));
 }
-
-isc_boolean_t
-dns_ds_digest_supported(unsigned int digest_type) {
-#ifdef HAVE_OPENSSL_GOST
-       return  (ISC_TF(digest_type == DNS_DSDIGEST_SHA1 ||
-                       digest_type == DNS_DSDIGEST_SHA256 ||
-                       digest_type == DNS_DSDIGEST_GOST ||
-                       digest_type == DNS_DSDIGEST_SHA384));
-#else
-       return  (ISC_TF(digest_type == DNS_DSDIGEST_SHA1 ||
-                       digest_type == DNS_DSDIGEST_SHA256 ||
-                       digest_type == DNS_DSDIGEST_SHA384));
-#endif
-}
index 12822bedf218ebeb6f9603a358de582ecb6d6d4a..481601c6e29df224abdba0c08e37eb0a2a0c8ff8 100644 (file)
@@ -277,6 +277,20 @@ dst_algorithm_supported(unsigned int alg) {
        return (ISC_TRUE);
 }
 
+isc_boolean_t
+dst_ds_digest_supported(unsigned int digest_type) {
+#ifdef HAVE_OPENSSL_GOST
+       return  (ISC_TF(digest_type == DNS_DSDIGEST_SHA1 ||
+                       digest_type == DNS_DSDIGEST_SHA256 ||
+                       digest_type == DNS_DSDIGEST_GOST ||
+                       digest_type == DNS_DSDIGEST_SHA384));
+#else
+       return  (ISC_TF(digest_type == DNS_DSDIGEST_SHA1 ||
+                       digest_type == DNS_DSDIGEST_SHA256 ||
+                       digest_type == DNS_DSDIGEST_SHA384));
+#endif
+}
+
 isc_result_t
 dst_context_create(dst_key_t *key, isc_mem_t *mctx, dst_context_t **dctxp) {
        dst_context_t *dctx;
index 03ab0ed09da6ff6615a87038ace67a16a4d0809b..41cd2235bf5699797765c40117c3bf85a3d16d72 100644 (file)
@@ -58,12 +58,6 @@ dns_ds_buildrdata(dns_name_t *owner, dns_rdata_t *key,
  *             to 'buffer'.
  */
 
-isc_boolean_t
-dns_ds_digest_supported(unsigned int digest_type);
-/*%<
- * Is this digest algorithm supported by dns_ds_buildrdata()?
- */
-
 ISC_LANG_ENDDECLS
 
 #endif /* DNS_DS_H */
index 095269ea2dd295dacaf2744a8b670eb184fa7e4d..b96724fb75bc09760a0f026e85216c66c4976c38 100644 (file)
@@ -456,11 +456,17 @@ dns_resolver_reset_algorithms(dns_resolver_t *resolver);
  * Clear the disabled DNSSEC algorithms.
  */
 
+void
+dns_resolver_reset_ds_digests(dns_resolver_t *resolver);
+/*%<
+ * Clear the disabled DS/DLV digest types.
+ */
+
 isc_result_t
 dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
                               unsigned int alg);
 /*%<
- * Mark the give DNSSEC algorithm as disabled and below 'name'.
+ * Mark the given DNSSEC algorithm as disabled and below 'name'.
  * Valid algorithms are less than 256.
  *
  * Returns:
@@ -469,20 +475,37 @@ dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
  *\li  #ISC_R_NOMEMORY
  */
 
+isc_result_t
+dns_resolver_disable_ds_digest(dns_resolver_t *resolver, dns_name_t *name,
+                              unsigned int digest_type);
+/*%<
+ * Mark the given DS/DLV digest type as disabled and below 'name'.
+ * Valid types are less than 256.
+ *
+ * Returns:
+ *\li  #ISC_R_SUCCESS
+ *\li  #ISC_R_RANGE
+ *\li  #ISC_R_NOMEMORY
+ */
+
 isc_boolean_t
 dns_resolver_algorithm_supported(dns_resolver_t *resolver, dns_name_t *name,
                                 unsigned int alg);
 /*%<
  * Check if the given algorithm is supported by this resolver.
- * This checks if the algorithm has been disabled via
- * dns_resolver_disable_algorithm() then the underlying
- * crypto libraries if not specifically disabled.
+ * This checks whether the algorithm has been disabled via
+ * dns_resolver_disable_algorithm(), then checks the underlying
+ * crypto libraries if it was not specifically disabled.
  */
 
 isc_boolean_t
-dns_resolver_digest_supported(dns_resolver_t *resolver, unsigned int digest_type);
+dns_resolver_ds_digest_supported(dns_resolver_t *resolver, dns_name_t *name,
+                                unsigned int digest_type);
 /*%<
- * Is this digest type supported.
+ * Check if the given digest type is supported by this resolver.
+ * This checks whether the digest type has been disabled via
+ * dns_resolver_disable_ds_digest(), then checks the underlying
+ * crypto libraries if it was not specifically disabled.
  */
 
 void
index 62e79998f7087811bfcb862607353676759107eb..a163e3fa23408122433d79288ec1757b07f45e24 100644 (file)
@@ -74,6 +74,7 @@ typedef struct dns_dns64                      dns_dns64_t;
 typedef ISC_LIST(dns_dns64_t)                  dns_dns64list_t;
 typedef struct dns_dnsseckey                   dns_dnsseckey_t;
 typedef ISC_LIST(dns_dnsseckey_t)              dns_dnsseckeylist_t;
+typedef isc_uint8_t                            dns_dsdigest_t;
 typedef struct dns_dumpctx                     dns_dumpctx_t;
 typedef struct dns_fetch                       dns_fetch_t;
 typedef struct dns_fixedname                   dns_fixedname_t;
index 66501df4fc1cb28fccb1779bc44f8a535929bf44..d59ff7c32a42e82bd0e37b657a50659173b3d220 100644 (file)
@@ -28,6 +28,8 @@
 #include <dns/types.h>
 #include <dns/name.h>
 #include <dns/secalg.h>
+#include <dns/ds.h>
+#include <dns/dsdigest.h>
 
 #include <dst/gssapi.h>
 
@@ -167,6 +169,16 @@ dst_algorithm_supported(unsigned int alg);
  * \li ISC_FALSE
  */
 
+isc_boolean_t
+dst_ds_digest_supported(unsigned int digest_type);
+/*%<
+ * Checks that a given digest algorithm is supported by DST.
+ *
+ * Returns:
+ * \li ISC_TRUE
+ * \li ISC_FALSE
+ */
+
 isc_result_t
 dst_context_create(dst_key_t *key, isc_mem_t *mctx, dst_context_t **dctxp);
 /*%<
index 0b7fe8c28051d42a4ad821bb73d5a52332f4cc9a..b05100615cb99214a936cec53f11f9d2f1ed19d2 100644 (file)
@@ -32,6 +32,8 @@
 #include <isc/util.h>
 
 #include <dns/cert.h>
+#include <dns/ds.h>
+#include <dns/dsdigest.h>
 #include <dns/keyflags.h>
 #include <dns/keyvalues.h>
 #include <dns/rcode.h>
        { 1, "SHA-1", 0 }, \
        { 0, NULL, 0 }
 
+/* RFC3658, RFC4509, RFC5933, RFC6605 */
+
+#define DSDIGESTNAMES \
+       { DNS_DSDIGEST_SHA1, "SHA-1", 0 }, \
+       { DNS_DSDIGEST_SHA256, "SHA-256", 0 }, \
+       { DNS_DSDIGEST_GOST, "GOST", 0 }, \
+       { DNS_DSDIGEST_SHA384, "SHA-384", 0 }, \
+       { 0, NULL, 0}
+
 struct tbl {
        unsigned int    value;
        const char      *name;
@@ -142,6 +153,7 @@ static struct tbl certs[] = { CERTNAMES };
 static struct tbl secalgs[] = { SECALGNAMES };
 static struct tbl secprotos[] = { SECPROTONAMES };
 static struct tbl hashalgs[] = { HASHALGNAMES };
+static struct tbl dsdigests[] = { DSDIGESTNAMES };
 
 static struct keyflag {
        const char *name;
@@ -404,6 +416,34 @@ dns_keyflags_fromtext(dns_keyflags_t *flagsp, isc_textregion_t *source)
        return (ISC_R_SUCCESS);
 }
 
+isc_result_t
+dns_dsdigest_fromtext(dns_dsdigest_t *dsdigestp, isc_textregion_t *source) {
+       unsigned int value;
+       RETERR(dns_mnemonic_fromtext(&value, source, dsdigests, 0xff));
+       *dsdigestp = value;
+       return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+dns_dsdigest_totext(dns_dsdigest_t dsdigest, isc_buffer_t *target) {
+       return (dns_mnemonic_totext(dsdigest, target, dsdigests));
+}
+
+void
+dns_dsdigest_format(dns_dsdigest_t typ, char *cp, unsigned int size) {
+       isc_buffer_t b;
+       isc_region_t r;
+       isc_result_t result;
+
+       REQUIRE(cp != NULL && size > 0);
+       isc_buffer_init(&b, cp, size - 1);
+       result = dns_dsdigest_totext(typ, &b);
+       isc_buffer_usedregion(&b, &r);
+       r.base[r.length] = 0;
+       if (result != ISC_R_SUCCESS)
+               r.base[0] = 0;
+}
+
 /*
  * This uses lots of hard coded values, but how often do we actually
  * add classes?
index b6e715eff0b1314977b9ce6c1db940ef36ac2b56..6e7c8a229e833b7423dbf232c807626c2c2d6d50 100644 (file)
@@ -35,6 +35,7 @@
 #include <dns/callbacks.h>
 #include <dns/cert.h>
 #include <dns/compress.h>
+#include <dns/dsdigest.h>
 #include <dns/enumtype.h>
 #include <dns/keyflags.h>
 #include <dns/keyvalues.h>
index 474e9cb3bb3bc5188d81c840146c56c3a1608312..57970125915bbad544055eb9cccacfc54fdf50d1 100644 (file)
@@ -16,7 +16,7 @@
 
 /* $Id$ */
 
-/* draft-ietf-dnsext-delegation-signer-05.txt */
+/* RFC3658 */
 
 #ifndef RDATA_GENERIC_DLV_32769_C
 #define RDATA_GENERIC_DLV_32769_C
@@ -28,7 +28,6 @@
 
 #include <dns/ds.h>
 
-
 static inline isc_result_t
 fromtext_dlv(ARGS_FROMTEXT) {
        isc_token_t token;
index dd47c8d5e83ef1b43b8a54228274112b2933fa04..bbcadc43f4ec09e6ae26447a0f1e56f8c45448bd 100644 (file)
@@ -17,7 +17,7 @@
 
 /* $Id$ */
 
-/* draft-ietf-dnsext-delegation-signer-05.txt */
+/* RFC3658 */
 
 #ifndef RDATA_GENERIC_DS_43_C
 #define RDATA_GENERIC_DS_43_C
@@ -64,12 +64,10 @@ fromtext_ds(ARGS_FROMTEXT) {
        /*
         * Digest type.
         */
-       RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
+       RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
                                      ISC_FALSE));
-       if (token.value.as_ulong > 0xffU)
-               RETTOK(ISC_R_RANGE);
-       RETERR(uint8_tobuffer(token.value.as_ulong, target));
-       c = (unsigned char) token.value.as_ulong;
+       RETTOK(dns_dsdigest_fromtext(&c, &token.value.as_textregion));
+       RETERR(mem_tobuffer(target, &c, 1));
 
        /*
         * Digest.
index 46af973a84ee5415f971803fc9e9ccb4ab679c20..0659c6ca62db7745ff0524604a2362ed0b8b33df 100644 (file)
@@ -404,6 +404,7 @@ struct dns_resolver {
        isc_rwlock_t                    alglock;
 #endif
        dns_rbt_t *                     algorithms;
+       dns_rbt_t *                     digests;
 #if USE_MBSLOCK
        isc_rwlock_t                    mbslock;
 #endif
@@ -7352,6 +7353,7 @@ destroy(dns_resolver_t *res) {
                isc_mem_put(res->mctx, a, sizeof(*a));
        }
        dns_resolver_reset_algorithms(res);
+       dns_resolver_reset_ds_digests(res);
        destroy_badcache(res);
        dns_resolver_resetmustbesecure(res);
 #if USE_ALGLOCK
@@ -7478,6 +7480,7 @@ dns_resolver_create(dns_view_t *view,
        ISC_LIST_INIT(res->alternates);
        res->udpsize = RECV_BUFFER_SIZE;
        res->algorithms = NULL;
+       res->digests = NULL;
        res->badcache = NULL;
        res->badcount = 0;
        res->badhash = 0;
@@ -8667,11 +8670,118 @@ dns_resolver_algorithm_supported(dns_resolver_t *resolver, dns_name_t *name,
        return (dst_algorithm_supported(alg));
 }
 
+static void
+free_digest(void *node, void *arg) {
+       unsigned char *digests = node;
+       isc_mem_t *mctx = arg;
+
+       isc_mem_put(mctx, digests, *digests);
+}
+
+void
+dns_resolver_reset_ds_digests(dns_resolver_t *resolver) {
+
+       REQUIRE(VALID_RESOLVER(resolver));
+
+#if USE_ALGLOCK
+       RWLOCK(&resolver->alglock, isc_rwlocktype_write);
+#endif
+       if (resolver->digests != NULL)
+               dns_rbt_destroy(&resolver->digests);
+#if USE_ALGLOCK
+       RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
+#endif
+}
+
+isc_result_t
+dns_resolver_disable_ds_digest(dns_resolver_t *resolver, dns_name_t *name,
+                              unsigned int digest_type)
+{
+       unsigned int len, mask;
+       unsigned char *new;
+       unsigned char *digests;
+       isc_result_t result;
+       dns_rbtnode_t *node = NULL;
+
+       REQUIRE(VALID_RESOLVER(resolver));
+       if (digest_type > 255)
+               return (ISC_R_RANGE);
+
+#if USE_ALGLOCK
+       RWLOCK(&resolver->alglock, isc_rwlocktype_write);
+#endif
+       if (resolver->digests == NULL) {
+               result = dns_rbt_create(resolver->mctx, free_digest,
+                                       resolver->mctx, &resolver->digests);
+               if (result != ISC_R_SUCCESS)
+                       goto cleanup;
+       }
+
+       len = digest_type/8 + 2;
+       mask = 1 << (digest_type%8);
+
+       result = dns_rbt_addnode(resolver->digests, name, &node);
+
+       if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
+               digests = node->data;
+               if (digests == NULL || len > *digests) {
+                       new = isc_mem_get(resolver->mctx, len);
+                       if (new == NULL) {
+                               result = ISC_R_NOMEMORY;
+                               goto cleanup;
+                       }
+                       memset(new, 0, len);
+                       if (digests != NULL)
+                               memcpy(new, digests, *digests);
+                       new[len-1] |= mask;
+                       *new = len;
+                       node->data = new;
+                       if (digests != NULL)
+                               isc_mem_put(resolver->mctx, digests,
+                                           *digests);
+               } else
+                       digests[len-1] |= mask;
+       }
+       result = ISC_R_SUCCESS;
+ cleanup:
+#if USE_ALGLOCK
+       RWUNLOCK(&resolver->alglock, isc_rwlocktype_write);
+#endif
+       return (result);
+}
+
 isc_boolean_t
-dns_resolver_digest_supported(dns_resolver_t *resolver, unsigned int digest) {
+dns_resolver_ds_digest_supported(dns_resolver_t *resolver, dns_name_t *name,
+                                unsigned int digest_type)
+{
+       unsigned int len, mask;
+       unsigned char *digests;
+       void *data = NULL;
+       isc_result_t result;
+       isc_boolean_t found = ISC_FALSE;
+
+       REQUIRE(VALID_RESOLVER(resolver));
 
-       UNUSED(resolver);
-       return (dns_ds_digest_supported(digest));
+#if USE_ALGLOCK
+       RWLOCK(&resolver->alglock, isc_rwlocktype_read);
+#endif
+       if (resolver->digests == NULL)
+               goto unlock;
+       result = dns_rbt_findname(resolver->digests, name, 0, NULL, &data);
+       if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
+               len = digest_type/8 + 2;
+               mask = 1 << (digest_type%8);
+               digests = data;
+               if (len <= *digests && (digests[len-1] & mask) != 0)
+                       found = ISC_TRUE;
+       }
+ unlock:
+#if USE_ALGLOCK
+       RWUNLOCK(&resolver->alglock, isc_rwlocktype_read);
+#endif
+       if (found)
+               return (ISC_FALSE);
+       return (dst_ds_digest_supported(digest_type));
 }
 
 void
index 56639241b753dcb597cb6c1bc2ea23307060cb82..ebbda295175d75e7d66fc562887555648ad66020 100644 (file)
@@ -255,17 +255,10 @@ dlv_algorithm_supported(dns_validator_t *val) {
                                                      dlv.algorithm))
                        continue;
 
-#ifdef HAVE_OPENSSL_GOST
-               if (dlv.digest_type != DNS_DSDIGEST_SHA256 &&
-                   dlv.digest_type != DNS_DSDIGEST_SHA1 &&
-                   dlv.digest_type != DNS_DSDIGEST_GOST)
-                       continue;
-#else
-               if (dlv.digest_type != DNS_DSDIGEST_SHA256 &&
-                   dlv.digest_type != DNS_DSDIGEST_SHA1)
+               if (!dns_resolver_ds_digest_supported(val->view->resolver,
+                                                     val->event->name,
+                                                     dlv.digest_type))
                        continue;
-#endif
-
 
                return (ISC_TRUE);
        }
@@ -2275,11 +2268,12 @@ dlv_validatezonekey(dns_validator_t *val) {
                result = dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
                RUNTIME_CHECK(result == ISC_R_SUCCESS);
 
-               if (!dns_resolver_digest_supported(val->view->resolver,
-                                                  dlv.digest_type))
+               if (digest_types[dlv.digest_type] == 0)
                        continue;
 
-               if (digest_types[dlv.digest_type] == 0)
+               if (!dns_resolver_ds_digest_supported(val->view->resolver,
+                                                     val->event->name,
+                                                     dlv.digest_type))
                        continue;
 
                if (!dns_resolver_algorithm_supported(val->view->resolver,
@@ -2629,11 +2623,12 @@ validatezonekey(dns_validator_t *val) {
                result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
                RUNTIME_CHECK(result == ISC_R_SUCCESS);
 
-               if (!dns_resolver_digest_supported(val->view->resolver,
-                                                  ds.digest_type))
+               if (digest_types[ds.digest_type] == 0)
                        continue;
 
-               if (digest_types[ds.digest_type] == 0)
+               if (!dns_resolver_ds_digest_supported(val->view->resolver,
+                                                     val->event->name,
+                                                     ds.digest_type))
                        continue;
 
                if (!dns_resolver_algorithm_supported(val->view->resolver,
@@ -3299,8 +3294,8 @@ check_ds(dns_validator_t *val, dns_name_t *name, dns_rdataset_t *rdataset) {
                result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
                RUNTIME_CHECK(result == ISC_R_SUCCESS);
 
-               if (dns_resolver_digest_supported(val->view->resolver,
-                                                 ds.digest_type) &&
+               if (dns_resolver_ds_digest_supported(val->view->resolver,
+                                                    name, ds.digest_type) &&
                    dns_resolver_algorithm_supported(val->view->resolver,
                                                     name, ds.algorithm)) {
                        dns_rdata_reset(&dsrdata);
index 2a70292e96c250b2f7a922c4a3b228bfb0cb07f5..4895e01202e0e9b1f5c58f38871d8b4f0c45e728 100644 (file)
@@ -231,7 +231,6 @@ dns_dnssec_verifymessage
 dns_dnsseckey_create
 dns_dnsseckey_destroy
 dns_ds_buildrdata
-dns_ds_digest_supported
 dns_dumpctx_detach
 dns_fwdtable_add
 dns_fwdtable_create
@@ -616,9 +615,11 @@ dns_resolver_createfetch2
 dns_resolver_destroyfetch
 dns_resolver_detach
 dns_resolver_disable_algorithm
+dns_resolver_disable_ds_digest
 dns_resolver_dispatchmgr
 dns_resolver_dispatchv4
 dns_resolver_dispatchv6
+dns_resolver_ds_digest_supported
 dns_resolver_flushbadcache
 dns_resolver_freeze
 dns_resolver_getbadcache
@@ -631,6 +632,7 @@ dns_resolver_nrunning
 dns_resolver_prime
 dns_resolver_printbadcache
 dns_resolver_reset_algorithms
+dns_resolver_reset_ds_digests
 dns_resolver_resetmustbesecure
 dns_resolver_setclientsperquery
 dns_resolver_setlamettl
@@ -980,6 +982,7 @@ dst_context_create
 dst_context_destroy
 dst_context_sign
 dst_context_verify
+dst_ds_digest_supported
 dst_gssapi_acceptctx
 dst_gssapi_acquirecred
 dst_gssapi_initctx
index 9bd1ab4c28fe5ecb99cac4c06299df099d148188..264d1aa34707bfb03ee8c76f484a50d2b1f5c3c1 100644 (file)
@@ -1007,6 +1007,21 @@ static cfg_type_t cfg_type_disablealgorithm = {
        &cfg_rep_tuple, disablealgorithm_fields
 };
 
+static cfg_type_t cfg_type_dsdigestlist = {
+       "dsdigestlist", cfg_parse_bracketed_list, cfg_print_bracketed_list,
+       cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_astring };
+
+static cfg_tuplefielddef_t disabledsdigest_fields[] = {
+       { "name", &cfg_type_astring, 0 },
+       { "digests", &cfg_type_dsdigestlist, 0 },
+       { NULL, NULL, 0 }
+};
+
+static cfg_type_t cfg_type_disabledsdigest = {
+       "disabledsdigest", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+       &cfg_rep_tuple, disabledsdigest_fields
+};
+
 static cfg_tuplefielddef_t mustbesecure_fields[] = {
        { "name", &cfg_type_astring, 0 },
        { "value", &cfg_type_boolean, 0 },
@@ -1337,6 +1352,8 @@ view_clauses[] = {
        { "deny-answer-aliases", &cfg_type_denyaliases, 0 },
        { "disable-algorithms", &cfg_type_disablealgorithm,
          CFG_CLAUSEFLAG_MULTI },
+       { "disable-ds-digests", &cfg_type_disabledsdigest,
+         CFG_CLAUSEFLAG_MULTI },
        { "disable-empty-zone", &cfg_type_astring, CFG_CLAUSEFLAG_MULTI },
        { "dns64", &cfg_type_dns64, CFG_CLAUSEFLAG_MULTI },
        { "dns64-server", &cfg_type_astring, 0 },