Commit 754746c5 authored by Karel Slaný's avatar Karel Slaný

lib/resolve: fetching missing first DNSKEY

parent b0c31a9d
......@@ -46,6 +46,39 @@ static int secure_query(knot_layer_t *ctx, knot_pkt_t *pkt)
return ctx->state;
}
if (query->zone_cut.key == NULL) {
/*
query->flags |= QUERY_AWAIT_TRUST;
DEBUG_MSG("%s() A002 '%s'\n", __func__, knot_pkt_qname(pkt));
struct knot_rrset *opt_rr = knot_rrset_copy(req->answer->opt_rr, &pkt->mm);
if (opt_rr == NULL) {
return KNOT_STATE_FAIL;
}
knot_pkt_clear(pkt);
int ret = knot_pkt_put_question(pkt, query->zone_cut.name, query->sclass, KNOT_RRTYPE_DNSKEY);
if (ret != KNOT_EOK) {
knot_rrset_free(&opt_rr, &pkt->mm);
return KNOT_STATE_FAIL;
}
knot_pkt_begin(pkt, KNOT_ADDITIONAL);
knot_pkt_put(pkt, KNOT_COMPR_HINT_NONE, opt_rr, KNOT_PF_FREE);
{
char name_str[KNOT_DNAME_MAXLEN], type_str[16];
knot_dname_to_str(name_str, knot_pkt_qname(pkt), sizeof(name_str));
knot_rrtype_to_string(knot_pkt_qtype(pkt), type_str, sizeof(type_str));
DEBUG_MSG("%s() A003 '%s %s'\n", __func__, name_str, type_str);
}
return KNOT_STATE_CONSUME;
*/
}
DEBUG_MSG("%s() A004\n", __func__);
#if 0
/* Copy query EDNS options and request DNSKEY for current cut. */
pkt->opt_rr = knot_rrset_copy(req->answer->opt_rr, &pkt->mm);
query->flags |= QUERY_AWAIT_TRUST;
......@@ -56,6 +89,8 @@ static int secure_query(knot_layer_t *ctx, knot_pkt_t *pkt)
knot_pkt_put(pkt, KNOT_COMPR_HINT_NONE, pkt->opt_rr, KNOT_PF_FREE);
return KNOT_STATE_CONSUME;
#endif
return ctx->state;
}
static int validate(knot_layer_t *ctx, knot_pkt_t *pkt)
......@@ -63,6 +98,8 @@ static int validate(knot_layer_t *ctx, knot_pkt_t *pkt)
#warning TODO: check if we have DNSKEY in qry->zone_cut and validate RRSIGS/proof, return FAIL if failed
#warning TODO: we must also validate incoming DNSKEY records against the current zone cut TA
#warning FLOW: first answer that comes here must have the DNSKEY that we can validate using TA
return ctx->state;
}
/** Module implementation. */
......
......@@ -49,7 +49,7 @@ static int invalidate_ns(struct kr_rplan *rplan, struct kr_query *qry)
}
}
static int ns_fetch_cut(struct kr_query *qry, struct kr_request *req)
static int ns_fetch_cut(struct kr_query *qry, struct kr_request *req, bool secured)
{
struct kr_cache_txn txn;
int ret = 0;
......@@ -63,7 +63,7 @@ static int ns_fetch_cut(struct kr_query *qry, struct kr_request *req)
if (kr_cache_txn_begin(&req->ctx->cache, &txn, NAMEDB_RDONLY) != 0) {
ret = kr_zonecut_set_sbelt(req->ctx, &qry->zone_cut);
} else {
ret = kr_zonecut_find_cached(req->ctx, &qry->zone_cut, qry->sname, &txn, qry->timestamp.tv_sec);
ret = kr_zonecut_find_cached(req->ctx, &qry->zone_cut, qry->sname, &txn, qry->timestamp.tv_sec, secured);
kr_cache_txn_abort(&txn);
}
return ret;
......@@ -424,6 +424,27 @@ int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *t
DEBUG_MSG("query '%s %s'\n", type_str, name_str);
#endif
/* The query wasn't resolved from cache,
* now it's the time to look up closest zone cut from cache.
*/
if (qry->flags & QUERY_AWAIT_CUT) {
int ret = ns_fetch_cut(qry, request, true);
if (ret != 0) {
return KNOT_STATE_FAIL;
}
if (!qry->zone_cut.key) {
/* Try to fetch missing DNSKEY. */
/* TODO -- Fetch all missing DNSKEYS and DS records. */
/* TODO -- Fetch DS at parent side of a zone cut. Fetch NS at the child side of the zone cut. */
/* TODO -- Handle holes (sequences with missing delegation). */
struct kr_query *next = kr_rplan_push(rplan, qry, qry->zone_cut.name, KNOT_CLASS_IN, KNOT_RRTYPE_DNSKEY);
if (!next) {
return kr_error(ENOMEM);
}
}
}
/* Resolve current query and produce dependent or finish */
int state = knot_overlay_produce(&request->overlay, packet);
if (state != KNOT_STATE_FAIL && knot_wire_get_qr(packet->wire)) {
......@@ -447,10 +468,6 @@ int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *t
* now it's the time to look up closest zone cut from cache.
*/
if (qry->flags & QUERY_AWAIT_CUT) {
int ret = ns_fetch_cut(qry, request);
if (ret != 0) {
return KNOT_STATE_FAIL;
}
qry->flags &= ~QUERY_AWAIT_CUT;
/* Update minimized QNAME if zone cut changed */
if (qry->zone_cut.name[0] != '\0' && !(qry->flags & QUERY_NO_MINIMIZE)) {
......@@ -497,7 +514,8 @@ int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *t
struct sockaddr *addr = &qry->ns.addr.ip;
inet_ntop(addr->sa_family, kr_nsrep_inaddr(qry->ns.addr), ns_str, sizeof(ns_str));
knot_dname_to_str(zonecut_str, qry->zone_cut.name, sizeof(zonecut_str));
DEBUG_MSG("=> querying: '%s' score: %u zone cut: '%s' m12n: '%s'\n", ns_str, qry->ns.score, zonecut_str, qname_str);
knot_rrtype_to_string(knot_pkt_qtype(packet), type_str, sizeof(type_str));
DEBUG_MSG("=> querying: '%s' score: %u zone cut: '%s' m12n: '%s' type: '%s'\n", ns_str, qry->ns.score, zonecut_str, qname_str, type_str);
#endif
/* Prepare additional query */
......
......@@ -321,8 +321,36 @@ static int fetch_ns(struct kr_context *ctx, struct kr_zonecut *cut, const knot_d
return kr_ok();
}
/** Fetch DNSKEY for zone cut. */
static int fetch_dnskey(struct kr_context *ctx, struct kr_zonecut *cut, const knot_dname_t *name, struct kr_cache_txn *txn, uint32_t timestamp)
{
uint32_t drift = timestamp;
knot_rrset_t cached_rr;
knot_rrset_free(&cut->key, cut->pool);
knot_rrset_init(&cached_rr, (knot_dname_t *)name, KNOT_RRTYPE_DNSKEY, KNOT_CLASS_IN);
int ret = kr_cache_peek_rr(txn, &cached_rr, &drift);
if (ret != 0) {
return ret;
}
cut->key = knot_rrset_new(name, KNOT_RRTYPE_DNSKEY, KNOT_CLASS_IN, cut->pool);
if (cut->key == NULL) {
return kr_error(ENOMEM);
}
ret = kr_cache_materialize(cut->key, &cached_rr, timestamp, cut->pool);
if (ret != 0) {
knot_rrset_free(&cut->key, cut->pool);
return ret;
}
return kr_ok();
}
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)
struct kr_cache_txn *txn, uint32_t timestamp, bool secured)
{
if (!ctx || !cut || !name) {
return kr_error(EINVAL);
......@@ -330,7 +358,8 @@ int kr_zonecut_find_cached(struct kr_context *ctx, struct kr_zonecut *cut, const
/* Start at QNAME parent. */
while (txn) {
if (fetch_ns(ctx, cut, name, txn, timestamp) == 0) {
bool has_key = !secured || fetch_dnskey(ctx, cut, name, txn, timestamp) == 0;
if (has_key && fetch_ns(ctx, cut, name, txn, timestamp) == 0) {
update_cut_name(cut, name);
return kr_ok();
}
......
......@@ -115,7 +115,8 @@ int kr_zonecut_set_sbelt(struct kr_context *ctx, struct kr_zonecut *cut);
* @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
* @return 0 or error code
*/
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);
struct kr_cache_txn *txn, uint32_t timestamp, bool secured);
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