From: Vladimír Čunát Date: Thu, 8 Jun 2017 15:03:22 +0000 (+0200) Subject: validate: work around some SERVFAILs (iterating mode) X-Git-Tag: v1.3.0~3^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fe77cee9f262f610009381e82a0487059cbc7f0f;p=thirdparty%2Fknot-resolver.git validate: work around some SERVFAILs (iterating mode) - This affects the iterating mode only (except for a verbose message). - The problem was introduced when implementing forwarding in 651c5aad. - Example that was affected: *.org.ru. When the same server is authoritative for multiple consecutive zones, with a higher one being signed and a lower one being unsigned, we may get an unsigned answer even in case we *think* we're currently in a signed zone. In particular, DS (sub-)queries are important because of being used to prove the insecurity of zones - in that case the iterator can correctly determine the (unexpected) zone name from which the answer came, due to seeing the SOA record, but that is too late for zone_cut_check() to try getting a trust chain to it, so we need to YIELD for it to do it. --- diff --git a/lib/layer/validate.c b/lib/layer/validate.c index 308777f12..ad618321d 100644 --- a/lib/layer/validate.c +++ b/lib/layer/validate.c @@ -703,20 +703,23 @@ static int check_signer(kr_layer_t *ctx, knot_pkt_t *pkt) qry->flags |= QUERY_AWAIT_CUT; } qry->zone_cut.name = knot_dname_copy(signer, &req->pool); - } /* else zone cut matches, but DS/DNSKEY doesn't => refetch. */ - if (qry->stype != KNOT_RRTYPE_DS) { - /* zone cut matches, but DS/DNSKEY doesn't => refetch. */ - VERBOSE_MSG(qry, ">< cut changed, needs revalidation\n"); - if (qry->flags & QUERY_FORWARD) { - struct kr_rplan *rplan = &req->rplan; - struct kr_query *next = kr_rplan_push(rplan, qry, signer, qry->sclass, KNOT_RRTYPE_DS); - if (!next) { - return KR_STATE_FAIL; - } - kr_zonecut_set(&next->zone_cut, qry->zone_cut.name); - kr_zonecut_copy_trust(&next->zone_cut, &qry->zone_cut); - next->flags |= QUERY_DNSSEC_WANT; + } + + /* zone cut matches, but DS/DNSKEY doesn't => refetch. */ + VERBOSE_MSG(qry, ">< cut changed, needs revalidation\n"); + if ((qry->flags & QUERY_FORWARD) && qry->stype != KNOT_RRTYPE_DS) { + struct kr_rplan *rplan = &req->rplan; + struct kr_query *next = kr_rplan_push(rplan, qry, signer, + qry->sclass, KNOT_RRTYPE_DS); + if (!next) { + return KR_STATE_FAIL; } + kr_zonecut_set(&next->zone_cut, qry->zone_cut.name); + kr_zonecut_copy_trust(&next->zone_cut, &qry->zone_cut); + next->flags |= QUERY_DNSSEC_WANT; + return KR_STATE_YIELD; + } + if (!(qry->flags & QUERY_FORWARD)) { return KR_STATE_YIELD; } }