}
}
-static int ns_fetch_cut(struct kr_query *qry, struct kr_request *req, knot_pkt_t *pkt, bool secured)
+static int ns_fetch_cut(struct kr_query *qry, struct kr_request *req, knot_pkt_t *pkt)
{
int ret = 0;
/* If at/subdomain of parent zone cut, start from its encloser.
* This is for case when we get to a dead end (and need glue from parent), or DS refetch. */
struct kr_query *parent = qry->parent;
+ bool secured = (qry->flags & QUERY_DNSSEC_WANT);
if (parent && parent->zone_cut.name[0] != '\0' && knot_dname_in(parent->zone_cut.name, qry->sname)) {
const knot_dname_t *encloser = knot_wire_next_label(parent->zone_cut.name, NULL);
- ret = kr_zonecut_find_cached(req->ctx, &qry->zone_cut, encloser, &txn, qry->timestamp.tv_sec, secured);
+ ret = kr_zonecut_find_cached(req->ctx, &qry->zone_cut, encloser, &txn, qry->timestamp.tv_sec, &secured);
} else {
- ret = kr_zonecut_find_cached(req->ctx, &qry->zone_cut, qry->sname, &txn, qry->timestamp.tv_sec, secured);
+ ret = kr_zonecut_find_cached(req->ctx, &qry->zone_cut, qry->sname, &txn, qry->timestamp.tv_sec, &secured);
}
/* Check if there's a non-terminal between target and current cut. */
if (ret == 0) {
check_empty_nonterms(qry, pkt, &txn, qry->timestamp.tv_sec);
+ /* Go insecure if the zone cut is provably insecure */
+ if ((qry->flags & QUERY_DNSSEC_WANT) && !secured) {
+ DEBUG_MSG(qry, "=> NS is provably without DS, going insecure\n");
+ qry->flags &= ~QUERY_DNSSEC_WANT;
+ qry->flags |= QUERY_DNSSEC_INSECURE;
+ }
}
kr_cache_txn_abort(&txn);
} else {
} else {
qry->flags &= ~QUERY_DNSSEC_WANT;
}
- int ret = ns_fetch_cut(qry, request, packet, (qry->flags & QUERY_DNSSEC_WANT));
+ int ret = ns_fetch_cut(qry, request, packet);
if (ret != 0) {
/* No cached cut found, start from SBELT and issue priming query. */
if (ret == kr_error(ENOENT)) {
}
/** Fetch best NS for zone cut. */
-static int fetch_ns(struct kr_context *ctx, struct kr_zonecut *cut, const knot_dname_t *name, struct kr_cache_txn *txn, uint32_t timestamp)
+static int fetch_ns(struct kr_context *ctx, struct kr_zonecut *cut, const knot_dname_t *name, struct kr_cache_txn *txn, uint32_t timestamp, uint16_t * restrict rank)
{
- uint16_t rank = 0;
uint32_t drift = timestamp;
knot_rrset_t cached_rr;
knot_rrset_init(&cached_rr, (knot_dname_t *)name, KNOT_RRTYPE_NS, KNOT_CLASS_IN);
- int ret = kr_cache_peek_rr(txn, &cached_rr, &rank, &drift);
+ int ret = kr_cache_peek_rr(txn, &cached_rr, rank, &drift);
if (ret != 0) {
return ret;
}
}
int kr_zonecut_find_cached(struct kr_context *ctx, struct kr_zonecut *cut, const knot_dname_t *name,
- struct kr_cache_txn *txn, uint32_t timestamp, bool secured)
+ struct kr_cache_txn *txn, uint32_t timestamp, bool * restrict secured)
{
if (!ctx || !cut || !name) {
return kr_error(EINVAL);
}
/* Start at QNAME parent. */
while (txn) {
+ /* Fetch NS first and see if it's insecure. */
+ uint16_t rank = 0;
const bool is_root = (label[0] == '\0');
- bool has_ta = !secured || is_root || fetch_ta(cut, label, txn, timestamp) == 0;
- if (has_ta && fetch_ns(ctx, cut, label, txn, timestamp) == 0) {
- if (secured) {
+ if (fetch_ns(ctx, cut, label, txn, timestamp, &rank) == 0) {
+ /* Flag as insecure if cached as this */
+ if (rank & KR_RANK_INSECURE)
+ *secured = false;
+ /* Fetch DS if caller wants secure zone cut */
+ if (*secured || is_root) {
+ fetch_ta(cut, label, txn, timestamp);
fetch_dnskey(cut, label, txn, timestamp);
}
update_cut_name(cut, label);
mm_free(cut->pool, qname);
return kr_ok();
- } else { /* Clear TA, as it is below any known NS. */
- knot_rrset_free(&cut->trust_anchor, cut->pool);
}
/* Subtract label from QNAME. */
if (!is_root) {
* @param name QNAME to start finding zone cut for
* @param txn cache transaction (read)
* @param timestamp transaction timestamp
- * @param secured search nearest containing a DNSKEY
+ * @param secured set to true if want secured zone cut, will return false if it is provably insecure
* @return 0 or error code (ENOENT if it doesn't find anything)
*/
int kr_zonecut_find_cached(struct kr_context *ctx, struct kr_zonecut *cut, const knot_dname_t *name,
- struct kr_cache_txn *txn, uint32_t timestamp, bool secured);
+ struct kr_cache_txn *txn, uint32_t timestamp, bool * restrict secured);