Commit e436b6d9 authored by Grigorii Demidov's avatar Grigorii Demidov

lib/resolve: some additional zonecut checks

parent ee532be2
......@@ -584,17 +584,18 @@ static int validate(kr_layer_t *ctx, knot_pkt_t *pkt)
const bool referral = (an->count == 0 && !knot_wire_get_aa(pkt->wire));
const bool no_data = (an->count == 0 && knot_wire_get_aa(pkt->wire));
if (knot_wire_get_aa(pkt->wire) && qtype == KNOT_RRTYPE_DNSKEY) {
if (!(qry->flags & QUERY_CACHED) && knot_wire_get_aa(pkt->wire)) {
/* Track difference between current TA and signer name.
* This indicates that the NS is auth for both parent-child,
* and we must update DS/DNSKEY to validate it.
*/
if (!(qry->flags & QUERY_CACHED)) {
ret = check_signer(ctx, pkt);
if (ret != KR_STATE_DONE) {
return ret;
}
ret = check_signer(ctx, pkt);
if (ret != KR_STATE_DONE) {
return ret;
}
}
if (knot_wire_get_aa(pkt->wire) && qtype == KNOT_RRTYPE_DNSKEY) {
ret = validate_keyset(req, pkt, has_nsec3);
if (ret == kr_error(EAGAIN)) {
VERBOSE_MSG(qry, ">< cut changed, needs revalidation\n");
......@@ -606,14 +607,6 @@ static int validate(kr_layer_t *ctx, knot_pkt_t *pkt)
}
}
if (!(qry->flags & QUERY_CACHED) &&
knot_wire_get_aa(pkt->wire) && qtype == KNOT_RRTYPE_DS) {
ret = check_signer(ctx, pkt);
if (ret != KR_STATE_DONE) {
return ret;
}
}
/* Validate non-existence proof if not positive answer. */
if (!(qry->flags & QUERY_CACHED) && pkt_rcode == KNOT_RCODE_NXDOMAIN) {
/* @todo If knot_pkt_qname(pkt) is used instead of qry->sname then the tests crash. */
......@@ -648,6 +641,7 @@ static int validate(kr_layer_t *ctx, knot_pkt_t *pkt)
VERBOSE_MSG(qry, "<= can't prove NODATA due to optout, going insecure\n");
qry->flags &= ~QUERY_DNSSEC_WANT;
qry->flags |= QUERY_DNSSEC_INSECURE;
/* Could not return here, we must to update parent query */
} else {
VERBOSE_MSG(qry, "<= bad NODATA proof\n");
qry->flags |= QUERY_DNSSEC_BOGUS;
......@@ -659,7 +653,8 @@ static int validate(kr_layer_t *ctx, knot_pkt_t *pkt)
/* Validate all records, fail as bogus if it doesn't match.
* Do not revalidate data from cache, as it's already trusted. */
if (!(qry->flags & QUERY_CACHED)) {
if (!(qry->flags & QUERY_CACHED) &&
(qry->flags & QUERY_DNSSEC_WANT)) {
ret = validate_records(req, pkt, req->rplan.pool, has_nsec3);
if (ret != 0) {
/* something exceptional - no DNS key, empty pointers etc
......@@ -690,24 +685,26 @@ static int validate(kr_layer_t *ctx, knot_pkt_t *pkt)
}
/* Check and update current delegation point security status. */
ret = update_delegation(req, qry, pkt, has_nsec3);
if (ret == DNSSEC_NOT_FOUND && qry->stype != KNOT_RRTYPE_DS) {
if (ctx->state == KR_STATE_YIELD) {
VERBOSE_MSG(qry, "<= can't validate referral\n");
qry->flags |= QUERY_DNSSEC_BOGUS;
if (qry->flags & QUERY_DNSSEC_WANT) {
ret = update_delegation(req, qry, pkt, has_nsec3);
if (ret == DNSSEC_NOT_FOUND && qry->stype != KNOT_RRTYPE_DS) {
if (ctx->state == KR_STATE_YIELD) {
VERBOSE_MSG(qry, "<= can't validate referral\n");
qry->flags |= QUERY_DNSSEC_BOGUS;
return KR_STATE_FAIL;
} else {
/* Check the trust chain and query DS\DNSKEY if needed. */
VERBOSE_MSG(qry, "<= DS\\NSEC was not found, querying for DS\n");
return KR_STATE_YIELD;
}
} else if (ret != 0) {
return KR_STATE_FAIL;
} else {
/* Check the trust chain and query DS\DNSKEY if needed. */
VERBOSE_MSG(qry, "<= DS\\NSEC was not found, querying for DS\n");
return KR_STATE_YIELD;
} else if (pkt_rcode == KNOT_RCODE_NOERROR &&
referral &&
((qry->flags & (QUERY_DNSSEC_WANT | QUERY_DNSSEC_INSECURE)) == QUERY_DNSSEC_INSECURE)) {
/* referral with proven DS non-existance */
qtype = KNOT_RRTYPE_DS;
}
} else if (ret != 0) {
return KR_STATE_FAIL;
} else if (pkt_rcode == KNOT_RCODE_NOERROR &&
referral &&
((qry->flags & (QUERY_DNSSEC_WANT | QUERY_DNSSEC_INSECURE)) == QUERY_DNSSEC_INSECURE)) {
/* referral with proven DS non-existance */
qtype = KNOT_RRTYPE_DS;
}
/* Update parent query zone cut */
if (qry->parent) {
......
......@@ -182,19 +182,32 @@ static int ns_fetch_cut(struct kr_query *qry, const knot_dname_t *requested_name
{
map_t *trust_anchors = &req->ctx->trust_anchors;
map_t *negative_anchors = &req->ctx->negative_anchors;
/* It can occur that here parent query already have
* provably insecured zonecut which not in the cache yet. */
const bool is_insecured = ((qry->parent != NULL) &&
(qry->parent->flags & QUERY_DNSSEC_INSECURE) != 0);
/* Want DNSSEC if it's possible to secure this name
* (e.g. is covered by any TA) */
if (!kr_ta_covers(negative_anchors, qry->zone_cut.name) &&
kr_ta_covers(trust_anchors, qry->zone_cut.name)) {
if (is_insecured) {
/* If parent is unsecured we don't want DNSSEC
* even if cut name is covered by TA. */
qry->flags &= ~QUERY_DNSSEC_WANT;
qry->flags |= QUERY_DNSSEC_INSECURE;
} else if (!kr_ta_covers(negative_anchors, qry->zone_cut.name) &&
kr_ta_covers(trust_anchors, qry->zone_cut.name)) {
qry->flags |= QUERY_DNSSEC_WANT;
} else {
qry->flags &= ~QUERY_DNSSEC_WANT;
}
struct kr_zonecut cut_found = {0};
kr_zonecut_init(&cut_found, requested_name, req->rplan.pool);
/* Cut that has been found can differs from cut that has been requested
* So try to fetch ta & keys anyway */
bool secured = true;
/* Cut that has been found can differs from cut that has been requested.
* So if not already insecured,
* try to fetch ta & keys even if initial cut name not covered by TA */
bool secured = !is_insecured;
int ret = kr_zonecut_find_cached(req->ctx, &cut_found, requested_name,
qry->timestamp.tv_sec, &secured);
if (ret == kr_error(ENOENT)) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment