From: Matthijs Mekking Date: Fri, 31 Oct 2025 08:04:13 +0000 (+0100) Subject: A unified way to verify the zone fetch X-Git-Tag: v9.21.16~59^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6f70cb7a396e4be9dab24b2ff4e4eeb9f6e93ab5;p=thirdparty%2Fbind9.git A unified way to verify the zone fetch There is a lot of similarity when checking the completed fetch is legit. Create a new function to verify the fetch and to reduce code duplication. --- diff --git a/lib/dns/include/dns/zonefetch.h b/lib/dns/include/dns/zonefetch.h index 41dcb52b107..01f189b81d1 100644 --- a/lib/dns/include/dns/zonefetch.h +++ b/lib/dns/include/dns/zonefetch.h @@ -105,3 +105,21 @@ dns_zonefetch_done(void *arg); * Complete a zone fetch. This may trigger follow-up actions that depend on * the fetch type. */ + +isc_result_t +dns_zonefetch_verify(dns_zonefetch_t *fetch, isc_result_t eresult, + dns_trust_t trust); +/*%< + * Check a completed zone fetch. This checks the response result, + * if there are records and signatures available, and the level of trust. + * + * Requires: + * 'fetch' is not NULL. + * + * Returns: + * ISC_R_SUCCESS - if the completed zone fetch is verified. + * ISC_R_NOTFOUND - if no records are found. + * DNS_R_NOVALIDSIG - if no signatures are available, or the trust + * level is below 'trust'. + * eresult - error code in case the fetch failed. + */ diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 4b8b893e8d4..cf7b2bed684 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -10758,20 +10758,8 @@ keyfetch_done(dns_zonefetch_t *fetch, isc_result_t eresult) { "Returned from key fetch in keyfetch_done() for '%s': %s", namebuf, isc_result_totext(eresult)); - /* Fetch failed */ - if (eresult != ISC_R_SUCCESS || !dns_rdataset_isassociated(dnskeys)) { - dnssec_log(zone, ISC_LOG_WARNING, - "Unable to fetch DNSKEY set '%s': %s", namebuf, - isc_result_totext(eresult)); - CHECK(minimal_update(fetch, ver, &diff)); - goto done; - } - - /* No RRSIGs found */ - if (!dns_rdataset_isassociated(dnskeysigs)) { - dnssec_log(zone, ISC_LOG_WARNING, - "No DNSKEY RRSIGs found for '%s': %s", namebuf, - isc_result_totext(eresult)); + result = dns_zonefetch_verify(fetch, eresult, dns_trust_none); + if (result != ISC_R_SUCCESS) { CHECK(minimal_update(fetch, ver, &diff)); goto done; } @@ -21171,7 +21159,6 @@ nsfetch_done(dns_zonefetch_t *fetch, isc_result_t eresult) { dns_name_t *pname = NULL; char pnamebuf[DNS_NAME_FORMATSIZE]; dns_rdataset_t *nsrrset = NULL; - dns_rdataset_t *nssigset = NULL; REQUIRE(fetch != NULL); REQUIRE(fetch->fetchtype == ZONEFETCHTYPE_NS); @@ -21192,37 +21179,10 @@ nsfetch_done(dns_zonefetch_t *fetch, isc_result_t eresult) { dnssec_log(zone, ISC_LOG_DEBUG(3), "NODATA response for NS '%s', level up", pnamebuf); return DNS_R_CONTINUE; - - } else if (eresult != ISC_R_SUCCESS) { - dnssec_log(zone, ISC_LOG_WARNING, - "Unable to fetch NS set '%s': %s", pnamebuf, - isc_result_totext(eresult)); - result = eresult; - goto done; } - /* No NS records found */ - if (!dns_rdataset_isassociated(nsrrset)) { - dnssec_log(zone, ISC_LOG_WARNING, - "No NS records found for '%s'", pnamebuf); - result = ISC_R_NOTFOUND; - goto done; - } - - /* No RRSIGs found */ - if (!dns_rdataset_isassociated(nssigset)) { - dnssec_log(zone, ISC_LOG_WARNING, "No NS RRSIGs found for '%s'", - pnamebuf); - result = DNS_R_NOVALIDSIG; - goto done; - } - - /* Check trust level */ - if (nsrrset->trust < dns_trust_secure) { - dnssec_log(zone, ISC_LOG_WARNING, - "Invalid NS RRset for '%s' trust level %u", pnamebuf, - nsrrset->trust); - result = DNS_R_NOVALIDSIG; + result = dns_zonefetch_verify(fetch, eresult, dns_trust_secure); + if (result != ISC_R_SUCCESS) { goto done; } diff --git a/lib/dns/zonefetch.c b/lib/dns/zonefetch.c index 988f4a6bfad..ea3fa3099ce 100644 --- a/lib/dns/zonefetch.c +++ b/lib/dns/zonefetch.c @@ -187,3 +187,53 @@ cleanup: } } } + +isc_result_t +dns_zonefetch_verify(dns_zonefetch_t *fetch, isc_result_t eresult, + dns_trust_t trust) { + char namebuf[DNS_NAME_FORMATSIZE]; + char typebuf[DNS_RDATATYPE_FORMATSIZE]; + dns_rdataset_t *rrset = NULL; + dns_rdataset_t *sigset = NULL; + + REQUIRE(fetch != NULL); + + rrset = &fetch->rrset; + sigset = &fetch->sigset; + dns_name_format(fetch->qname, namebuf, sizeof(namebuf)); + dns_rdatatype_format(fetch->qtype, typebuf, sizeof(typebuf)); + + if (eresult != ISC_R_SUCCESS) { + dns_zone_logc(fetch->zone, DNS_LOGCATEGORY_DNSSEC, + ISC_LOG_WARNING, "Unable to fetch %s/%s: %s", + namebuf, typebuf, isc_result_totext(eresult)); + return eresult; + } + + /* No records found */ + if (!dns_rdataset_isassociated(rrset)) { + dns_zone_logc(fetch->zone, DNS_LOGCATEGORY_DNSSEC, + ISC_LOG_WARNING, "No %s records found for '%s'", + typebuf, namebuf); + return ISC_R_NOTFOUND; + } + + /* No RRSIGs found */ + if (!dns_rdataset_isassociated(sigset)) { + dns_zone_logc(fetch->zone, DNS_LOGCATEGORY_DNSSEC, + ISC_LOG_WARNING, "No %s RRSIGs found for '%s'", + typebuf, namebuf); + return DNS_R_NOVALIDSIG; + } + + /* Check trust level */ + if (rrset->trust < trust) { + dns_zone_logc(fetch->zone, DNS_LOGCATEGORY_DNSSEC, + ISC_LOG_WARNING, + "Invalid %s RRset for '%s' trust level %u", + typebuf, namebuf, rrset->trust); + return DNS_R_NOVALIDSIG; + } + + return ISC_R_SUCCESS; +}