diff --git a/lib/layer/validate.c b/lib/layer/validate.c index e17d228691603976162926a98341708b83b781ba..774088d710198ff9f09d00768e345c590d3db28b 100644 --- a/lib/layer/validate.c +++ b/lib/layer/validate.c @@ -628,14 +628,51 @@ static int validate_keyset(struct kr_query *qry, knot_pkt_t *answer) static int update_delegation(struct kr_query *qry, knot_pkt_t *answer) { + int ret = kr_ok(); + struct kr_zonecut *cut = &qry->zone_cut; + DEBUG_MSG("<= referral, checking DS\n"); -#warning TODO: delegation, check DS record presence - return kr_ok(); + + /* New trust anchor. */ + knot_rrset_t *new_ds = NULL; + const knot_pktsection_t *sec = knot_pkt_section(answer, KNOT_AUTHORITY); + for (unsigned i = 0; i < sec->count; ++i) { + const knot_rrset_t *rr = knot_pkt_rr(sec, i); + if ((rr->type != KNOT_RRTYPE_DS) || + (knot_dname_cmp(rr->owner, cut->name) != 0)) { + continue; + } + if (new_ds) { + ret = knot_rdataset_merge(&new_ds->rrs, &rr->rrs, cut->pool); + if (ret != 0) { + goto fail; + } + } else { + new_ds = knot_rrset_copy(rr, cut->pool); + if (!new_ds) { + ret = kr_error(ENOMEM); + goto fail; + } + } + } + + if (new_ds) { + knot_rrset_free(&cut->trust_anchor, cut->pool); + cut->trust_anchor = new_ds; + new_ds = NULL; + + /* It is very likely, that the keys don't match now. */ + knot_rrset_free(&cut->key, cut->pool); + } + +fail: + knot_rrset_free(&new_ds, cut->pool); + return ret; } static int validate(knot_layer_t *ctx, knot_pkt_t *pkt) { - int ret = 0; + int ret; struct kr_request *req = ctx->data; struct kr_query *qry = kr_rplan_current(&req->rplan); if (ctx->state & KNOT_STATE_FAIL) { @@ -674,9 +711,6 @@ static int validate(knot_layer_t *ctx, knot_pkt_t *pkt) qry->flags |= QUERY_DNSSEC_BOGUS; return KNOT_STATE_FAIL; } - /* Update trust anchor. */ - } else if (qtype == KNOT_RRTYPE_NS) { - update_delegation(qry, pkt); } /* Validate all records, fail as bogus if it doesn't match. */ @@ -687,6 +721,18 @@ static int validate(knot_layer_t *ctx, knot_pkt_t *pkt) return KNOT_STATE_FAIL; } + /* Update trust anchor. */ + if (qtype == KNOT_RRTYPE_NS) { + ret = update_delegation(qry, pkt); + if (ret != 0) { + return KNOT_STATE_FAIL; + } + + if (!qry->zone_cut.key) { + DEBUG_MSG("<= missing keys for new cut\n"); + } + } + DEBUG_MSG("<= answer valid, OK\n"); return ctx->state; }