From: =?utf-8?b?VmxhZGltw61yIMSMdW7DoXQ=?= Date: Tue, 16 Jan 2024 07:35:20 +0100 Subject: mitigate KeyTrap DoS = CVE-2023-50387 Improve: don't retry in this case. --- lib/dnssec.c | 7 ++++--- lib/layer/validate.c | 4 ++++ lib/resolve.c | 4 +++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/dnssec.c b/lib/dnssec.c index 1e6eb58..262570c 100644 --- a/lib/dnssec.c +++ b/lib/dnssec.c @@ -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; } diff --git a/lib/layer/validate.c b/lib/layer/validate.c index 4882da8..1fdc57d 100644 --- a/lib/layer/validate.c +++ b/lib/layer/validate.c @@ -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 */ diff --git a/lib/resolve.c b/lib/resolve.c index 9e82e6f..456065b 100644 --- a/lib/resolve.c +++ b/lib/resolve.c @@ -880,7 +880,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. */