static int validate_section(kr_rrset_validation_ctx_t *vctx, struct kr_query *qry,
knot_mm_t *pool)
{
+ struct kr_request *req = qry->request;
if (!vctx) {
return kr_error(EINVAL);
}
/* no RRSIGs found */
kr_rank_set(&entry->rank, KR_RANK_MISSING);
vctx->err_cnt += 1;
+ kr_request_set_extended_error(req, KNOT_EDNS_EDE_RRSIG_MISS, NULL); // TODO double-check EDE
log_bogus_rrsig(vctx, rr, "no valid RRSIGs found");
} else {
kr_rank_set(&entry->rank, KR_RANK_BOGUS);
vctx->err_cnt += 1;
+ req->extended_error.info_code = KNOT_EDNS_EDE_BOGUS;
+ req->extended_error.extra_text = "bogus signatures";
log_bogus_rrsig(vctx, rr, "bogus signatures");
}
}
}
} else if (ret != 0) {
VERBOSE_MSG(qry, "<= bogus proof of DS non-existence\n");
+ kr_request_set_extended_error(req, KNOT_EDNS_EDE_BOGUS, NULL);
qry->flags.DNSSEC_BOGUS = true;
} else if (proved_name[0] != '\0') { /* don't go to insecure for . DS */
qry->flags.DNSSEC_NODS = true;
if (!kr_rank_test(invalid_entry->rank, KR_RANK_SECURE) &&
(++(invalid_entry->revalidation_cnt) > MAX_REVALIDATION_CNT)) {
VERBOSE_MSG(qry, "<= continuous revalidation, fails\n");
+ kr_request_set_extended_error(req, KNOT_EDNS_EDE_OTHER, "continuous revalidation, fails");
qry->flags.DNSSEC_BOGUS = true;
return KR_STATE_FAIL;
}
} else if (kr_rank_test(invalid_entry->rank, KR_RANK_MISSING)) {
ret = rrsig_not_found(ctx, pkt, rr);
} else if (!kr_rank_test(invalid_entry->rank, KR_RANK_SECURE)) {
+ kr_request_set_extended_error(req, KNOT_EDNS_EDE_BOGUS, NULL);
qry->flags.DNSSEC_BOGUS = true;
ret = KR_STATE_FAIL;
}
bool use_signatures = (knot_pkt_qtype(pkt) != KNOT_RRTYPE_RRSIG);
if (!(qry->flags.CACHED) && !knot_pkt_has_dnssec(pkt) && !use_signatures) {
VERBOSE_MSG(qry, "<= got insecure response\n");
+ kr_request_set_extended_error(req, KNOT_EDNS_EDE_BOGUS, NULL);
qry->flags.DNSSEC_BOGUS = true;
return KR_STATE_FAIL;
}
* but iterator has not selected any records. */
if (!check_empty_answer(ctx, pkt)) {
VERBOSE_MSG(qry, "<= no useful RR in authoritative answer\n");
+ kr_request_set_extended_error(req, KNOT_EDNS_EDE_BOGUS, NULL);
qry->flags.DNSSEC_BOGUS = true;
return KR_STATE_FAIL;
}
if (ds && !kr_ds_algo_support(ds)) {
VERBOSE_MSG(qry, ">< all DS entries use unsupported algorithm pairs, going insecure\n");
/* ^ the message is a bit imprecise to avoid being too verbose */
+ kr_request_set_extended_error(req, KNOT_EDNS_EDE_OTHER, "unsupported digest/key");
qry->flags.DNSSEC_WANT = false;
qry->flags.DNSSEC_INSECURE = true;
rank_records(qry, true, KR_RANK_INSECURE, qry->zone_cut.name);
return KR_STATE_YIELD;
} else if (ret != 0) {
VERBOSE_MSG(qry, "<= bad keys, broken trust chain\n");
+ req->extended_error.info_code = KNOT_EDNS_EDE_BOGUS;
+ req->extended_error.extra_text = "bad keys, broken trust chain";
qry->flags.DNSSEC_BOGUS = true;
return KR_STATE_FAIL;
}
/* something exceptional - no DNS key, empty pointers etc
* normally it shouldn't happen */
VERBOSE_MSG(qry, "<= couldn't validate RRSIGs\n");
+ kr_request_set_extended_error(req, KNOT_EDNS_EDE_OTHER, "couldn't validate RRSIGs");
qry->flags.DNSSEC_BOGUS = true;
return KR_STATE_FAIL;
}
VERBOSE_MSG(qry, "<= can't prove NXDOMAIN due to optout, going insecure\n");
} else if (ret != 0) {
VERBOSE_MSG(qry, "<= bad NXDOMAIN proof\n");
+ kr_request_set_extended_error(req, KNOT_EDNS_EDE_NSEC_MISS, NULL);
qry->flags.DNSSEC_BOGUS = true;
return KR_STATE_FAIL;
}
* parent queries as insecure */
} else {
VERBOSE_MSG(qry, "<= bad NODATA proof\n");
+ kr_request_set_extended_error(req, KNOT_EDNS_EDE_NSEC_MISS, NULL);
qry->flags.DNSSEC_BOGUS = true;
return KR_STATE_FAIL;
}
if (ret == DNSSEC_NOT_FOUND && qry->stype != KNOT_RRTYPE_DS) {
if (ctx->state == KR_STATE_YIELD) {
VERBOSE_MSG(qry, "<= can't validate referral\n");
+ kr_request_set_extended_error(req, KNOT_EDNS_EDE_BOGUS, NULL);
qry->flags.DNSSEC_BOGUS = true;
return KR_STATE_FAIL;
} else {
struct kr_query *qry = req->current_query;
if (ret & KR_STATE_FAIL && qry->flags.DNSSEC_BOGUS)
qry->server_selection.error(qry, req->upstream.transport, KR_SELECTION_DNSSEC_ERROR);
+ if (ret & KR_STATE_DONE && !qry->flags.DNSSEC_BOGUS) {
+ /* Don't report extended DNS errors related to validation
+ * when it managed to succeed (e.g. by trying different auth). */
+ switch (req->extended_error.info_code) {
+ case KNOT_EDNS_EDE_BOGUS:
+ case KNOT_EDNS_EDE_NSEC_MISS:
+ kr_request_set_extended_error(req, KNOT_EDNS_EDE_NONE, NULL);
+ break;
+ case KNOT_EDNS_EDE_SIG_EXPIRED:
+ case KNOT_EDNS_EDE_SIG_NOTYET:
+ case KNOT_EDNS_EDE_DNSKEY_MISS:
+ case KNOT_EDNS_EDE_RRSIG_MISS:
+ case KNOT_EDNS_EDE_DNSKEY_BIT:
+ kr_assert(false); /* These EDE codes aren't used. */
+ break;
+ default: break;
+ }
+ }
return ret;
}