From e64877b46ce690bdd59d10cbeaa7178bd85fbf26 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 2 Jul 2026 13:01:19 +0200 Subject: [PATCH] unbound: Make sure RRs match the queried or canonical name While `ub_resolve()` verifies the response is valid, only the `data` array provided in `ub_result` contains filtered results. The raw response packet we parse here could theoretically contain (validated) RRs for a different owner that would get accepted and returned in the provided `rr_set_t`. Fixes: 5a4126b49009 ("unbound: Implemented resolver_response_t as unbound_response_t") --- .../plugins/unbound/unbound_response.c | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/libstrongswan/plugins/unbound/unbound_response.c b/src/libstrongswan/plugins/unbound/unbound_response.c index 06bcc7b3c..36ec65722 100644 --- a/src/libstrongswan/plugins/unbound/unbound_response.c +++ b/src/libstrongswan/plugins/unbound/unbound_response.c @@ -113,6 +113,22 @@ METHOD(resolver_response_t, destroy, void, free(this); } +/** + * Check if the given RR's owner matches either the queried name or the resolved + * canonical name of the verified answer. + */ +static bool rr_owner_matches(const ldns_rr *rr, const ldns_rdf *qname, + const ldns_rdf *canonname) +{ + const ldns_rdf *owner = ldns_rr_owner(rr); + + if (ldns_dname_compare(owner, qname) != 0) + { + return canonname && ldns_dname_compare(owner, canonname) == 0; + } + return TRUE; +} + /* * Described in header. */ @@ -168,7 +184,7 @@ unbound_response_t *unbound_response_create_frm_libub_response( ldns_rr_list *orig_rr_list = NULL; size_t orig_rr_count; ldns_rr *orig_rr = NULL; - ldns_rdf *orig_rdf = NULL; + ldns_rdf *orig_rdf = NULL, *qname, *canonname = NULL; ldns_status status; linked_list_t *rr_list = NULL, *rrsig_list = NULL; unbound_rr_t *rr = NULL; @@ -193,10 +209,23 @@ unbound_response_t *unbound_response_create_frm_libub_response( orig_rr_list = ldns_pkt_answer(dns_pkt); orig_rr_count = ldns_rr_list_rr_count(orig_rr_list); + qname = ldns_dname_new_frm_str(libub_response->qname); + if (libub_response->canonname && + !strcaseeq(libub_response->qname, libub_response->canonname)) + { + canonname = ldns_dname_new_frm_str(libub_response->canonname); + } + for (i = 0; i < orig_rr_count; i++) { orig_rr = ldns_rr_list_rr(orig_rr_list, i); + if (!rr_owner_matches(orig_rr, qname, canonname)) + { + /* RR owner doesn't match queried or resolved canonical name */ + continue; + } + if (ldns_rr_get_type(orig_rr) == libub_response->qtype && ldns_rr_get_class(orig_rr) == libub_response->qclass) { @@ -253,6 +282,8 @@ unbound_response_t *unbound_response_create_frm_libub_response( */ this->rr_set = rr_set_create(rr_list, rrsig_list); + ldns_rdf_deep_free(canonname); + ldns_rdf_deep_free(qname); ldns_pkt_free(dns_pkt); } return &this->public;