diff options
author | Marek Vavruša <marek.vavrusa@nic.cz> | 2015-09-23 09:37:24 +0200 |
---|---|---|
committer | Marek Vavruša <marek.vavrusa@nic.cz> | 2015-09-23 09:37:24 +0200 |
commit | 5700cec6729fd637cc23180b00ecdfb81f29d253 (patch) | |
tree | 88fcf5c875359cf857838088eecbc0665430b6df /lib/dnssec/ta.c | |
parent | lib/resolve: fixed missing txn abort introduced a few commits ago (diff) | |
download | knot-resolver-5700cec6729fd637cc23180b00ecdfb81f29d253.tar.xz knot-resolver-5700cec6729fd637cc23180b00ecdfb81f29d253.zip |
lib/dnssec: allow KSK DNSKEY records for TA
this allows the classic workflow, kdig for root DNSKEY
records to a key file and let it start
Diffstat (limited to 'lib/dnssec/ta.c')
-rw-r--r-- | lib/dnssec/ta.c | 79 |
1 files changed, 60 insertions, 19 deletions
diff --git a/lib/dnssec/ta.c b/lib/dnssec/ta.c index 2ecb1229..7e3daa2b 100644 --- a/lib/dnssec/ta.c +++ b/lib/dnssec/ta.c @@ -18,6 +18,8 @@ #include <libknot/rdataset.h> #include <libknot/rrset.h> #include <libknot/packet/wire.h> +#include <dnssec/key.h> +#include <dnssec/error.h> #include "lib/defines.h" #include "lib/dnssec/ta.h" @@ -27,28 +29,44 @@ knot_rrset_t *kr_ta_get(map_t *trust_anchors, const knot_dname_t *name) return map_get(trust_anchors, (const char *)name); } -int kr_ta_add(map_t *trust_anchors, const knot_dname_t *name, uint16_t type, - uint32_t ttl, const uint8_t *rdata, uint16_t rdlen) +/* @internal Create DS from DNSKEY, caller MUST free dst if successful. */ +static int dnskey2ds(dnssec_binary_t *dst, const knot_dname_t *owner, const uint8_t *rdata, uint16_t rdlen) { - if (!trust_anchors || !name) { - return kr_error(EINVAL); + dnssec_key_t *key = NULL; + int ret = dnssec_key_new(&key); + if (ret != DNSSEC_EOK) { + return kr_error(ENOMEM); } - - /* Convert DNSKEY records to DS */ - switch (type) { - case KNOT_RRTYPE_DS: break; /* OK */ - case KNOT_RRTYPE_DNSKEY: -#warning TODO: convert DNSKEY -> DS here - return kr_error(ENOSYS); - break; - default: return kr_error(EINVAL); + /* Create DS from DNSKEY and reinsert */ + const dnssec_binary_t key_data = { .size = rdlen, .data = (uint8_t *)rdata }; + ret = dnssec_key_set_rdata(key, &key_data); + if (ret == DNSSEC_EOK) { + /* Accept only KSK (257) to TA store */ + if (dnssec_key_get_flags(key) == 257) { + ret = dnssec_key_set_dname(key, owner); + } else { + ret = DNSSEC_EINVAL; + } + if (ret == DNSSEC_EOK) { + ret = dnssec_key_create_ds(key, DNSSEC_KEY_DIGEST_SHA256, dst); + } + } + dnssec_key_free(key); + /* Pick some sane error code */ + if (ret != DNSSEC_EOK) { + return kr_error(ENOMEM); } + return kr_ok(); +} - /* Create new RRSet or use existing */ +/* @internal Insert new TA to trust anchor set, rdata MUST be of DS type. */ +static int insert_ta(map_t *trust_anchors, const knot_dname_t *name, + uint32_t ttl, const uint8_t *rdata, uint16_t rdlen) +{ bool is_new_key = false; knot_rrset_t *ta_rr = kr_ta_get(trust_anchors, name); - if (!ta_rr) { - ta_rr = knot_rrset_new(name, type, KNOT_CLASS_IN, NULL); + if (!ta_rr) { + ta_rr = knot_rrset_new(name, KNOT_RRTYPE_DS, KNOT_CLASS_IN, NULL); is_new_key = true; } /* Merge-in new key data */ @@ -56,14 +74,37 @@ int kr_ta_add(map_t *trust_anchors, const knot_dname_t *name, uint16_t type, knot_rrset_free(&ta_rr, NULL); return kr_error(ENOMEM); } - /* Reinsert */ if (is_new_key) { - map_set(trust_anchors, (const char *)name, ta_rr); + return map_set(trust_anchors, (const char *)name, ta_rr); } - return kr_ok(); } +int kr_ta_add(map_t *trust_anchors, const knot_dname_t *name, uint16_t type, + uint32_t ttl, const uint8_t *rdata, uint16_t rdlen) +{ + if (!trust_anchors || !name) { + return kr_error(EINVAL); + } + + /* DS/DNSEY types are accepted, for DNSKEY we + * need to compute a DS digest. */ + if (type == KNOT_RRTYPE_DS) { + return insert_ta(trust_anchors, name, ttl, rdata, rdlen); + } else if (type == KNOT_RRTYPE_DNSKEY) { + dnssec_binary_t ds_rdata = { 0, }; + int ret = dnskey2ds(&ds_rdata, name, rdata, rdlen); + if (ret != 0) { + return ret; + } + ret = insert_ta(trust_anchors, name, ttl, ds_rdata.data, ds_rdata.size); + dnssec_binary_free(&ds_rdata); + return ret; + } else { /* Invalid type for TA */ + return kr_error(EINVAL); + } +} + int kr_ta_covers(map_t *trust_anchors, const knot_dname_t *name) { while(name) { |