From: Vladimír Čunát Date: Fri, 24 Sep 2021 10:00:15 +0000 (+0200) Subject: lib/dnssec: add a simple validator API X-Git-Tag: v5.4.3~13^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ce189de1269d10ff23ddac24ffe63fa1980618e4;p=thirdparty%2Fknot-resolver.git lib/dnssec: add a simple validator API --- diff --git a/lib/dnssec.c b/lib/dnssec.c index 50436c5f3..43ba20161 100644 --- a/lib/dnssec.c +++ b/lib/dnssec.c @@ -167,6 +167,11 @@ typedef struct { uint16_t tag; } kr_svldr_key_t; +struct kr_svldr_ctx { + kr_rrset_validation_ctx_t vctx; + array_t(kr_svldr_key_t) keys; // owned(malloc), also insides via svldr_key_* +}; + static int svldr_key_new(const knot_rdata_t *rdata, const knot_dname_t *owner, kr_svldr_key_t *result) { @@ -182,6 +187,48 @@ static inline void svldr_key_del(kr_svldr_key_t *skey) kr_dnssec_key_free(&skey->key); } +void kr_svldr_free_ctx(struct kr_svldr_ctx *ctx) +{ + if (!ctx) return; + for (ssize_t i = 0; i < ctx->keys.len; ++i) + svldr_key_del(&ctx->keys.at[i]); + array_clear(ctx->keys); + free_const(ctx->vctx.zone_name); + free(ctx); +} +struct kr_svldr_ctx * kr_svldr_new_ctx(const knot_rrset_t *ds, knot_rrset_t *dnskey, + const knot_rdataset_t *dnskey_sigs, uint32_t timestamp) +{ + // Basic init. + struct kr_svldr_ctx *ctx = calloc(1, sizeof(*ctx)); + if (unlikely(!ctx)) + return NULL; + ctx->vctx.timestamp = timestamp; + ctx->vctx.zone_name = knot_dname_copy(ds->owner, NULL); + if (unlikely(!ctx->vctx.zone_name)) + goto fail; + // Validate the DNSKEY set. + ctx->vctx.keys = dnskey; + if (kr_dnskeys_trusted(&ctx->vctx, dnskey_sigs, ds) != 0) + goto fail; + // Put usable DNSKEYs into ctx->keys. (Some duplication of work happens, but OK.) + array_init(ctx->keys); + array_reserve(ctx->keys, dnskey->rrs.count); + knot_rdata_t *krr = dnskey->rrs.rdata; + for (int i = 0; i < dnskey->rrs.count; ++i, krr = knot_rdataset_next(krr)) { + if (!kr_dnssec_key_zsk(krr->data) || kr_dnssec_key_revoked(krr->data)) + continue; // key not usable for this + kr_svldr_key_t key; + if (unlikely(svldr_key_new(krr, NULL/*seems OK here*/, &key) != 0)) + goto fail; + array_push(ctx->keys, key); + } + return ctx; +fail: + kr_svldr_free_ctx(ctx); + return NULL; +} + static int kr_svldr_rrset_with_key(knot_rrset_t *rrs, const knot_rdataset_t *rrsigs, kr_rrset_validation_ctx_t *vctx, const kr_svldr_key_t *key) { @@ -215,6 +262,20 @@ static int kr_svldr_rrset_with_key(knot_rrset_t *rrs, const knot_rdataset_t *rrs return vctx->result; } /* The implementation basically performs "parts of" kr_rrset_validate(). */ +int kr_svldr_rrset(knot_rrset_t *rrs, const knot_rdataset_t *rrsigs, + struct kr_svldr_ctx *ctx) +{ + if (knot_dname_in_bailiwick(rrs->owner, ctx->vctx.zone_name) < 0) { + ctx->vctx.result = kr_error(EAGAIN); + return ctx->vctx.result; + } + for (ssize_t i = 0; i < ctx->keys.len; ++i) { + kr_svldr_rrset_with_key(rrs, rrsigs, &ctx->vctx, &ctx->keys.at[i]); + if (ctx->vctx.result == 0) + break; + } + return ctx->vctx.result; +} /** diff --git a/lib/dnssec.h b/lib/dnssec.h index d69d88d0f..13ba176ab 100644 --- a/lib/dnssec.h +++ b/lib/dnssec.h @@ -147,3 +147,34 @@ void kr_dnssec_key_free(struct dnssec_key **key); */ int kr_dnssec_matches_name_and_type(const ranked_rr_array_t *rrs, uint32_t qry_uid, const knot_dname_t *name, uint16_t type); + + +/* Simple validator API. Main use case: prefill module, i.e. RRs from a zone file. */ + +/** Opaque context for simple validator. */ +struct kr_svldr_ctx; +/** + * Create new context for validating within a given zone. + * + * - `ds` is assumed to be trusted, and it's used to validate `dnskey+dnskey_sigs`. + * - The TTL of `dnskey` may get trimmed. + * - The insides are placed on malloc heap (use _free_ctx). + */ +KR_EXPORT +struct kr_svldr_ctx * kr_svldr_new_ctx(const knot_rrset_t *ds, knot_rrset_t *dnskey, + const knot_rdataset_t *dnskey_sigs, uint32_t timestamp); +/** Free the context. Passing NULL is OK. */ +KR_EXPORT +void kr_svldr_free_ctx(struct kr_svldr_ctx *ctx); +/** + * Validate an RRset with the associated signatures; assume no wildcard expansions. + * + * - It's caller's responsibility that rrsigs have matching owner, class and type. + * - The TTL of `rrs` may get trimmed. + * - If it's a wildcard other than in its simple `*.` form, it may fail to validate. + * - More generally, non-existence proofs are not supported. + */ +KR_EXPORT +int kr_svldr_rrset(knot_rrset_t *rrs, const knot_rdataset_t *rrsigs, + struct kr_svldr_ctx *ctx); +