]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
mitigate KeyTrap DoS = CVE-2023-50387
authorVladimír Čunát <vladimir.cunat@nic.cz>
Tue, 16 Jan 2024 06:35:20 +0000 (07:35 +0100)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Tue, 13 Feb 2024 08:47:33 +0000 (09:47 +0100)
Improve: don't retry in this case.

lib/dnssec.c
lib/layer/validate.c
lib/resolve.c

index 1e6eb58c16eddc1bf8bf34576f1160a69101126b..262570c44f73f0ee99a0f2241ddec143874176f1 100644 (file)
@@ -134,7 +134,7 @@ int kr_rrset_validate(kr_rrset_validation_ctx_t *vctx, knot_rrset_t *covered)
        memset(&vctx->rrs_counters, 0, sizeof(vctx->rrs_counters));
        for (unsigned i = 0; i < vctx->keys->rrs.count; ++i) {
                int ret = kr_rrset_validate_with_key(vctx, covered, i, NULL);
-               if (ret == 0) {
+               if (ret == 0 || ret == kr_error(E2BIG)) {
                        return ret;
                }
        }
@@ -307,7 +307,7 @@ int kr_svldr_rrset(knot_rrset_t *rrs, const knot_rdataset_t *rrsigs,
        }
        for (ssize_t i = 0; i < ctx->keys.len; ++i) {
                kr_svldr_rrset_with_key(rrs, rrsigs, &ctx->vctx, &ctx->keys.at[i]);
-               if (ctx->vctx.result == 0)
+               if (ctx->vctx.result == 0 || ctx->vctx.result == kr_error(E2BIG))
                        break;
        }
        return ctx->vctx.result;
@@ -393,6 +393,7 @@ static int kr_rrset_validate_with_key(kr_rrset_validation_ctx_t *vctx,
                                }
                        }
                        if (!check_crypto_limit(vctx)) {
+                               vctx->result = kr_error(E2BIG);
                                goto finish;
                        }
                        if (kr_check_signature(rdata_j, key, covered, trim_labels) != 0) {
@@ -475,7 +476,7 @@ int kr_dnskeys_trusted(kr_rrset_validation_ctx_t *vctx, const knot_rdataset_t *s
                if (ret == 0)
                        ret = kr_svldr_rrset_with_key(keys, sigs, vctx, &key);
                svldr_key_del(&key);
-               if (ret == 0) {
+               if (ret == 0 || ret == kr_error(E2BIG)) {
                        kr_assert(vctx->result == 0);
                        return vctx->result;
                }
index 9b953940e346b2f0bf67767c99996e84a6063ea7..3bdb205c4520c12c7cc744b35df84bd6718dd7e4 100644 (file)
@@ -1177,6 +1177,10 @@ static int validate(kr_layer_t *ctx, knot_pkt_t *pkt)
                ret = validate_records(req, pkt, req->rplan.pool, has_nsec3);
                if (ret == KNOT_EDOWNGRADED) {
                        return KR_STATE_DONE;
+               } else if (ret == kr_error(E2BIG)) {
+                       qry->flags.DNSSEC_BOGUS = true;
+                       return KR_STATE_FAIL;
+
                } else if (ret != 0) {
                        /* something exceptional - no DNS key, empty pointers etc
                         * normally it shouldn't happen */
index 7ee1d1aa37a035259659aaaf65a218b341306671..e24a40b9cd6958b04095afe2f062401f2add2d44 100644 (file)
@@ -903,7 +903,9 @@ int kr_resolve_consume(struct kr_request *request, struct kr_transport **transpo
 
        /* Do not finish with bogus answer. */
        if (qry->flags.DNSSEC_BOGUS)  {
-               if (qry->flags.FORWARD || qry->flags.STUB) {
+               if (qry->flags.FORWARD || qry->flags.STUB
+                               /* Probably CPU exhaustion attempt, so do not retry. */
+                               || qry->vld_limit_crypto_remains <= 0) {
                        return KR_STATE_FAIL;
                }
                /* Other servers might not have broken DNSSEC. */