]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
mitigate KeyTrap DoS = CVE-2023-50387 security-backports-from-5.7.1_for-5.4.4
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>
Thu, 22 Feb 2024 13:29:36 +0000 (14:29 +0100)
Improve: don't retry in this case.
(cherry picked from commit cc5051b4441307d9b262fa382bc715391112ddbb)

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

index 78d71ce3a42ef7ba36e42966cc26bb445ebef800..7ce6e75af972dc174678340c5ad1311302338749 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;
                }
        }
@@ -292,7 +292,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;
@@ -378,6 +378,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) {
@@ -460,7 +461,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 c6b5ea02d33402db5853dba1010e74ff8d6e22cc..098aeee1d9a8ead1a17010da4c4f5de5c0fc4b16 100644 (file)
@@ -1142,6 +1142,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 1ffd07ec72c1ca3d455c414c36f5ef0902c7f50b..852566502790fd5488ef6e2d5bd475d780b58954 100644 (file)
@@ -881,7 +881,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. */