summaryrefslogtreecommitdiffstats
path: root/debian/patches/0011-mitigate-KeyTrap-DoS-CVE-2023-50387.patch
blob: e074a940a875a759d584356677bd325aa8028301 (plain)
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. */