]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Fail the DNSSEC validation if matching but invalid DNSKEY is found
authorOndřej Surý <ondrej@isc.org>
Tue, 22 Jul 2025 06:07:02 +0000 (08:07 +0200)
committerMichał Kępień <michal@isc.org>
Thu, 2 Oct 2025 10:32:06 +0000 (12:32 +0200)
If a matching but cryptographically invalid key was encountered during
the DNSSEC validation, the key would be just skipped and not counted
towards validation failures.  Treat such DNSSEC keys as hard failures
and fail the DNSSEC validation immediatelly instead of continuing the
DNSSEC validation with the next DNSKEYs in the RRset.

Co-authored-by: Matthijs Mekking <matthijs@isc.org>
(cherry picked from commit f00117a4226be90d1bc865aff19bddf114242914)

lib/dns/validator.c

index bcbe026f916c0f093a62d2060baff607747bd717..34934816b57ac14324ee8baa1b6e965c4ce7cb76 100644 (file)
@@ -378,6 +378,12 @@ trynsec3:
 static void
 resume_answer_with_key_done(void *arg);
 
+static bool
+over_max_fails(dns_validator_t *val);
+
+static void
+consume_validation_fail(dns_validator_t *val);
+
 static void
 resume_answer_with_key(void *arg) {
        dns_validator_t *val = arg;
@@ -386,6 +392,13 @@ resume_answer_with_key(void *arg) {
        isc_result_t result = select_signing_key(val, rdataset);
        if (result == ISC_R_SUCCESS) {
                val->keyset = &val->frdataset;
+       } else if (result != ISC_R_NOTFOUND) {
+               val->result = result;
+               if (over_max_fails(val)) {
+                       INSIST(val->key == NULL);
+                       val->result = ISC_R_QUOTA;
+               }
+               consume_validation_fail(val);
        }
 
        (void)validate_async_run(val, resume_answer_with_key_done);
@@ -395,6 +408,16 @@ static void
 resume_answer_with_key_done(void *arg) {
        dns_validator_t *val = arg;
 
+       switch (val->result) {
+       case ISC_R_CANCELED:     /* Validation was canceled */
+       case ISC_R_SHUTTINGDOWN: /* Server shutting down */
+       case ISC_R_QUOTA:        /* Validation fails quota reached */
+               dns_validator_cancel(val);
+               break;
+       default:
+               break;
+       }
+
        resume_answer(val);
 }
 
@@ -1070,6 +1093,8 @@ select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset) {
                                goto done;
                        }
                        dst_key_free(&val->key);
+               } else {
+                       break;
                }
                dns_rdata_reset(&rdata);
                result = dns_rdataset_next(rdataset);
@@ -1359,7 +1384,7 @@ selfsigned_dnskey(dns_validator_t *val) {
                        result = dns_dnssec_keyfromrdata(name, &keyrdata, mctx,
                                                         &dstkey);
                        if (result != ISC_R_SUCCESS) {
-                               continue;
+                               return result;
                        }
 
                        /*
@@ -1599,7 +1624,7 @@ validate_answer_signing_key_done(void *arg);
 static void
 validate_answer_signing_key(void *arg) {
        dns_validator_t *val = arg;
-       isc_result_t result = ISC_R_NOTFOUND;
+       isc_result_t result;
 
        if (CANCELED(val) || CANCELING(val)) {
                val->result = ISC_R_CANCELED;
@@ -1622,15 +1647,21 @@ validate_answer_signing_key(void *arg) {
        default:
                /* Select next signing key */
                result = select_signing_key(val, val->keyset);
+               if (result == ISC_R_SUCCESS) {
+                       INSIST(val->key != NULL);
+               } else if (result == ISC_R_NOTFOUND) {
+                       INSIST(val->key == NULL);
+               } else {
+                       val->result = result;
+                       if (over_max_fails(val)) {
+                               INSIST(val->key == NULL);
+                               val->result = ISC_R_QUOTA;
+                       }
+                       consume_validation_fail(val);
+               }
                break;
        }
 
-       if (result == ISC_R_SUCCESS) {
-               INSIST(val->key != NULL);
-       } else {
-               INSIST(val->key == NULL);
-       }
-
        (void)validate_async_run(val, validate_answer_signing_key_done);
 }
 
@@ -1894,10 +1925,7 @@ check_signer(dns_validator_t *val, dns_rdata_t *keyrdata, uint16_t keyid,
                        result = dns_dnssec_keyfromrdata(
                                val->name, keyrdata, val->view->mctx, &dstkey);
                        if (result != ISC_R_SUCCESS) {
-                               /*
-                                * This really shouldn't happen, but...
-                                */
-                               continue;
+                               return result;
                        }
                }
                result = verify(val, dstkey, &rdata, sig.keyid);