unbound/backport-0001-CVE-2022-30698-and-CVE-2022-30699.patch
2022-08-04 16:01:44 +08:00

207 lines
8.1 KiB
Diff

From 55ba863440dc5b1266b79f26ed92bbbdde5a2ebb Mon Sep 17 00:00:00 2001
From: "W.C.A. Wijngaards" <wouter@nlnetlabs.nl>
Date: Tue, 13 Apr 2021 13:52:57 +0200
Subject: [PATCH] - Fix that nxdomain synthesis does not happen above the stub
or forward definition.
---
cachedb/cachedb.c | 8 +++++++-
edns-subnet/subnetmod.c | 2 +-
iterator/iter_utils.c | 15 ++++++++++++++-
iterator/iter_utils.h | 7 ++++++-
iterator/iterator.c | 12 +++++++-----
services/cache/dns.c | 5 ++++-
services/cache/dns.h | 4 +++-
7 files changed, 42 insertions(+), 11 deletions(-)
diff --git a/cachedb/cachedb.c b/cachedb/cachedb.c
index eed4d5f..1f3ff98 100644
--- a/cachedb/cachedb.c
+++ b/cachedb/cachedb.c
@@ -616,12 +616,18 @@ cachedb_extcache_store(struct module_qstate* qstate, struct cachedb_env* ie)
static int
cachedb_intcache_lookup(struct module_qstate* qstate)
{
+ uint8_t* dpname=NULL;
+ size_t dpnamelen=0;
struct dns_msg* msg;
+ if(iter_stub_fwd_no_cache(qstate, &qstate->qinfo,
+ &dpname, &dpnamelen))
+ return 0; /* no cache for these queries */
msg = dns_cache_lookup(qstate->env, qstate->qinfo.qname,
qstate->qinfo.qname_len, qstate->qinfo.qtype,
qstate->qinfo.qclass, qstate->query_flags,
qstate->region, qstate->env->scratch,
- 1 /* no partial messages with only a CNAME */
+ 1, /* no partial messages with only a CNAME */
+ dpname, dpnamelen
);
if(!msg && qstate->env->neg_cache &&
iter_qname_indicates_dnssec(qstate->env, &qstate->qinfo)) {
diff --git a/edns-subnet/subnetmod.c b/edns-subnet/subnetmod.c
index f1b401b..fcd6dc6 100644
--- a/edns-subnet/subnetmod.c
+++ b/edns-subnet/subnetmod.c
@@ -150,7 +150,7 @@ int ecs_whitelist_check(struct query_info* qinfo,
/* Cache by default, might be disabled after parsing EDNS option
* received from nameserver. */
- if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo)) {
+ if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL)) {
qstate->no_cache_store = 0;
}
diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c
index 7bc67da..260ebe6 100644
--- a/iterator/iter_utils.c
+++ b/iterator/iter_utils.c
@@ -1390,7 +1390,8 @@ int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp)
}
int
-iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf)
+iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
+ uint8_t** retdpname, size_t* retdpnamelen)
{
struct iter_hints_stub *stub;
struct delegpt *dp;
@@ -1419,6 +1420,10 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf)
dname_str(stub->dp->name, dpname);
verbose(VERB_ALGO, "stub for %s %s has no_cache", qname, dpname);
}
+ if(retdpname) {
+ *retdpname = stub->dp->name;
+ *retdpnamelen = stub->dp->namelen;
+ }
return (stub->dp->no_cache);
}
@@ -1431,7 +1436,15 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf)
dname_str(dp->name, dpname);
verbose(VERB_ALGO, "forward for %s %s has no_cache", qname, dpname);
}
+ if(retdpname) {
+ *retdpname = dp->name;
+ *retdpnamelen = dp->namelen;
+ }
return (dp->no_cache);
}
+ if(retdpname) {
+ *retdpname = NULL;
+ *retdpnamelen = 0;
+ }
return 0;
}
diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h
index f771930..6d4d152 100644
--- a/iterator/iter_utils.h
+++ b/iterator/iter_utils.h
@@ -380,9 +380,14 @@ int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp);
* Lookup if no_cache is set in stub or fwd.
* @param qstate: query state with env with hints and fwds.
* @param qinf: query name to lookup for.
+ * @param retdpname: returns NULL or the deepest enclosing name of fwd or stub.
+ * This is the name under which the closest lookup is going to happen.
+ * Used for NXDOMAIN checks, above that it is an nxdomain from a
+ * different server and zone. You can pass NULL to not get it.
+ * @param retdpnamelen: returns the length of the dpname.
* @return true if no_cache is set in stub or fwd.
*/
int iter_stub_fwd_no_cache(struct module_qstate *qstate,
- struct query_info *qinf);
+ struct query_info *qinf, uint8_t** retdpname, size_t* retdpnamelen);
#endif /* ITERATOR_ITER_UTILS_H */
diff --git a/iterator/iterator.c b/iterator/iterator.c
index 23b07ea..3772235 100644
--- a/iterator/iterator.c
+++ b/iterator/iterator.c
@@ -1228,8 +1228,8 @@ static int
processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
struct iter_env* ie, int id)
{
- uint8_t* delname;
- size_t delnamelen;
+ uint8_t* delname, *dpname=NULL;
+ size_t delnamelen, dpnamelen=0;
struct dns_msg* msg = NULL;
log_query_info(VERB_DETAIL, "resolving", &qstate->qinfo);
@@ -1283,7 +1283,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
/* This either results in a query restart (CNAME cache response), a
* terminating response (ANSWER), or a cache miss (null). */
- if (iter_stub_fwd_no_cache(qstate, &iq->qchase)) {
+ if (iter_stub_fwd_no_cache(qstate, &iq->qchase, &dpname, &dpnamelen)) {
/* Asked to not query cache. */
verbose(VERB_ALGO, "no-cache set, going to the network");
qstate->no_cache_lookup = 1;
@@ -1298,7 +1298,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
msg = dns_cache_lookup(qstate->env, iq->qchase.qname,
iq->qchase.qname_len, iq->qchase.qtype,
iq->qchase.qclass, qstate->query_flags,
- qstate->region, qstate->env->scratch, 0);
+ qstate->region, qstate->env->scratch, 0, dpname,
+ dpnamelen);
if(!msg && qstate->env->neg_cache &&
iter_qname_indicates_dnssec(qstate->env, &iq->qchase)) {
/* lookup in negative cache; may result in
@@ -2288,7 +2289,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
iq->qinfo_out.qname, iq->qinfo_out.qname_len,
iq->qinfo_out.qtype, iq->qinfo_out.qclass,
qstate->query_flags, qstate->region,
- qstate->env->scratch, 0);
+ qstate->env->scratch, 0, iq->dp->name,
+ iq->dp->namelen);
if(msg && FLAGS_GET_RCODE(msg->rep->flags) ==
LDNS_RCODE_NOERROR)
/* no need to send query if it is already
diff --git a/services/cache/dns.c b/services/cache/dns.c
index 7b6e142..8160b31 100644
--- a/services/cache/dns.c
+++ b/services/cache/dns.c
@@ -801,7 +801,7 @@ struct dns_msg*
dns_cache_lookup(struct module_env* env,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, struct regional* region, struct regional* scratch,
- int no_partial)
+ int no_partial, uint8_t* dpname, size_t dpnamelen)
{
struct lruhash_entry* e;
struct query_info k;
@@ -924,6 +924,9 @@ dns_cache_lookup(struct module_env* env,
* the same. We search upwards for NXDOMAINs. */
if(env->cfg->harden_below_nxdomain) {
while(!dname_is_root(k.qname)) {
+ if(dpname && dpnamelen
+ && !dname_subdomain_c(k.qname, dpname))
+ break; /* no synth nxdomain above the stub */
dname_remove_label(&k.qname, &k.qname_len);
h = query_info_hash(&k, flags);
e = slabhash_lookup(env->msg_cache, h, &k, 0);
diff --git a/services/cache/dns.h b/services/cache/dns.h
index f1b77fb..bece837 100644
--- a/services/cache/dns.h
+++ b/services/cache/dns.h
@@ -164,6 +164,8 @@ struct dns_msg* tomsg(struct module_env* env, struct query_info* q,
* @param scratch: where to allocate temporary data.
* @param no_partial: if true, only complete messages and not a partial
* one (with only the start of the CNAME chain and not the rest).
+ * @param dpname: if not NULL, do not return NXDOMAIN above this name.
+ * @param dpnamelen: length of dpname.
* @return new response message (alloced in region, rrsets do not have IDs).
* or NULL on error or if not found in cache.
* TTLs are made relative to the current time.
@@ -171,7 +173,7 @@ struct dns_msg* tomsg(struct module_env* env, struct query_info* q,
struct dns_msg* dns_cache_lookup(struct module_env* env,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, struct regional* region, struct regional* scratch,
- int no_partial);
+ int no_partial, uint8_t* dpname, size_t dpnamelen);
/**
* find and add A and AAAA records for missing nameservers in delegpt
--
2.33.0