]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Mark DNSSEC responses with NSEC3 records that exceed 150 as insecure
authorMark Andrews <marka@isc.org>
Wed, 17 Feb 2021 05:33:49 +0000 (16:33 +1100)
committerMatthijs Mekking <matthijs@isc.org>
Fri, 30 Apr 2021 07:36:45 +0000 (09:36 +0200)
(cherry picked from commit af02bbcdd6c4117a20092ed39533e7171e9a6771)

lib/dns/include/dns/nsec3.h
lib/dns/nsec3.c
lib/dns/validator.c

index 300efbe4e5cdaf4e00025b569d5d8fa8ee4dbbc1..f36ba99eac462f99f3d0ec86307a38cd5acbb461 100644 (file)
@@ -24,7 +24,8 @@
 #include <dns/rdatastruct.h>
 #include <dns/types.h>
 
-#define DNS_NSEC3_SALTSIZE 255
+#define DNS_NSEC3_SALTSIZE     255
+#define DNS_NSEC3_MAXITERATIONS 150U
 
 /*
  * hash = 1, flags =1, iterations = 2, salt length = 1, salt = 255 (max)
index 9be4f3fea6b4d1dc2c1b5161c0d84c9a347ae806..cdb824542c0d2dd5d356577798f36dc6c8d21b0f 100644 (file)
@@ -1777,7 +1777,7 @@ dns_nsec3_activex(dns_db_t *db, dns_dbversion_t *version,
 unsigned int
 dns_nsec3_maxiterations(void)
 {
-       return (150);
+       return (DNS_NSEC3_MAXITERATIONS);
 }
 
 isc_result_t
@@ -1912,6 +1912,13 @@ dns_nsec3_noexistnodata(dns_rdatatype_t type, dns_name_t* name,
        first = true;
 
        while (qlabels >= zlabels) {
+               /*
+                * If there are too many iterations reject the NSEC3 record.
+                */
+               if (nsec3.iterations > DNS_NSEC3_MAXITERATIONS) {
+                       return (DNS_R_NSEC3ITERRANGE);
+               }
+
                length = isc_iterated_hash(hash, nsec3.hash, nsec3.iterations,
                                           nsec3.salt, nsec3.salt_length,
                                           qname->ndata, qname->length);
index 9d966f7bb17669f53759eafdf933e6b0390d338b..2a5c3caa6ab51b9d69afd716591eed1341e0c87a 100644 (file)
@@ -2581,6 +2581,28 @@ findnsec3proofs(dns_validator_t *val) {
                                                 nearest, validator_log, val);
                if (unknown)
                        val->attributes |= VALATTR_FOUNDUNKNOWN;
+
+               if (result == DNS_R_NSEC3ITERRANGE) {
+                       /*
+                        * We don't really know which NSEC3 record provides
+                        * which proof.  Just populate them.
+                        */
+                       if (NEEDNOQNAME(val) &&
+                           proofs[DNS_VALIDATOR_NOQNAMEPROOF] == NULL) {
+                               proofs[DNS_VALIDATOR_NOQNAMEPROOF] = name;
+                       } else if (setclosest) {
+                               proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name;
+                       } else if (NEEDNODATA(val) &&
+                                  proofs[DNS_VALIDATOR_NODATAPROOF] == NULL) {
+                               proofs[DNS_VALIDATOR_NODATAPROOF] = name;
+                       } else if (NEEDNOWILDCARD(val) &&
+                                  proofs[DNS_VALIDATOR_NOWILDCARDPROOF] ==
+                                          NULL) {
+                               proofs[DNS_VALIDATOR_NOWILDCARDPROOF] = name;
+                       }
+                       return (result);
+               }
+
                if (result != ISC_R_SUCCESS)
                        continue;
                if (setclosest)
@@ -2825,8 +2847,16 @@ nsecvalidate(dns_validator_t *val, bool resume) {
         * had a secure wildcard answer.
         */
        if (!NEEDNODATA(val) && !NEEDNOWILDCARD(val) && NEEDNOQNAME(val)) {
-               if (!FOUNDNOQNAME(val))
-                       findnsec3proofs(val);
+               if (!FOUNDNOQNAME(val)) {
+                       result = findnsec3proofs(val);
+                       if (result == DNS_R_NSEC3ITERRANGE) {
+                               validator_log(val, ISC_LOG_DEBUG(3),
+                                             "too many iterations");
+                               markanswer(val, "validate_nx (3)");
+                               return (ISC_R_SUCCESS);
+                       }
+               }
+
                if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) &&
                    !FOUNDOPTOUT(val)) {
                        validator_log(val, ISC_LOG_DEBUG(3),
@@ -2852,8 +2882,15 @@ nsecvalidate(dns_validator_t *val, bool resume) {
                return (DNS_R_NOVALIDNSEC);
        }
 
-       if (!FOUNDNOQNAME(val) && !FOUNDNODATA(val))
-               findnsec3proofs(val);
+       if (!FOUNDNOQNAME(val) && !FOUNDNODATA(val)) {
+               result = findnsec3proofs(val);
+               if (result == DNS_R_NSEC3ITERRANGE) {
+                       validator_log(val, ISC_LOG_DEBUG(3),
+                                     "too many iterations");
+                       markanswer(val, "validate_nx (4)");
+                       return (ISC_R_SUCCESS);
+               }
+       }
 
        /*
         * Do we need to check for the wildcard?