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.
This commit is contained in:
Matthijs Mekking 2025-10-31 09:04:13 +01:00
parent 94a82c2ecb
commit 6f70cb7a39
3 changed files with 72 additions and 44 deletions

View file

@ -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.
*/

View file

@ -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;
}

View file

@ -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;
}