1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
From: =?utf-8?b?VmxhZGltw61yIMSMdW7DoXQ=?= <vladimir.cunat@nic.cz>
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. */
|