diff --git a/lib/dnssec/ta.c b/lib/dnssec/ta.c index 61e64205c83f5486a11d3fd2bd085fa9ea3c5c43..59e696890f9b037b89592793e89e0767c1b42936 100644 --- a/lib/dnssec/ta.c +++ b/lib/dnssec/ta.c @@ -17,9 +17,14 @@ #include <arpa/inet.h> #include <assert.h> #include <ctype.h> +#include <pthread.h> +#include <contrib/ucw/mempool.h> #include <libknot/descriptor.h> +#include <libknot/dname.h> #include <libknot/internal/base64.h> +#include <libknot/rdataset.h> +#include <libknot/rrset.h> #include <libknot/rrtype/rdname.h> #include "lib/defines.h" @@ -423,3 +428,222 @@ fail: #undef RDATA_MAXSIZE #undef SEPARATORS } + +#define MAX_ANCHORS 16 +struct trust_anchors_nolock { + mm_ctx_t pool; + knot_rrset_t *anchors[MAX_ANCHORS]; + int used; +}; + +struct trust_anchors { + struct trust_anchors_nolock locked; + pthread_rwlock_t rwlock; +}; + +struct trust_anchors global_trust_anchors = { + .locked.pool = {0, }, + .locked.anchors = {0, }, + .locked.used = 0, +}; + +static int ta_init(struct trust_anchors_nolock *tan) +{ + assert(tan); + + memset(tan, 0, sizeof(*tan)); + tan->pool.ctx = mp_new(4 * CPU_PAGE_SIZE); + tan->pool.alloc = (mm_alloc_t) mp_alloc; + tan->used = 0; + + return kr_ok(); +} + +static void ta_deinit(struct trust_anchors_nolock *tan) +{ + assert(tan); + + if (tan->pool.ctx) { + mp_delete(tan->pool.ctx); + tan->pool.ctx = NULL; + } +} + +int kr_ta_init(struct trust_anchors *tas) +{ + if (!tas) { + return kr_error(EINVAL); + } + + int ret = ta_init(&tas->locked); + if (ret != 0) { + return ret; + } + + ret = pthread_rwlock_init(&tas->rwlock, NULL); + if (ret != 0) { + ta_deinit(&tas->locked); + return kr_error(ret); + } + return kr_ok(); +} + +void kr_ta_deinit(struct trust_anchors *tas) +{ + if (!tas) { + return; + } + + while (pthread_rwlock_destroy(&tas->rwlock) == EBUSY); + + ta_deinit(&tas->locked); +} + +static int ta_reset(struct trust_anchors_nolock *tan, const char *ta_str) +{ + assert(tan); + + ta_deinit(tan); + int ret = ta_init(tan); + if (ret != 0) { + return ret; + } + + if (!ta_str || (ta_str[0] == '\0')) { + return kr_ok(); + } + + knot_rrset_t *ta = NULL; + ret = kr_ta_parse(&ta, ta_str, &tan->pool); + if (ret != 0) { + return ret; + } + + assert(ta); + + tan->anchors[tan->used++] = ta; + + return kr_ok(); +} + +int kr_ta_reset(struct trust_anchors *tas, const char *ta_str) +{ + if (!tas) { + return kr_error(ENOENT); + } + + int ret = pthread_rwlock_wrlock(&tas->rwlock); + if (ret != 0) { + return kr_error(ret); + } + + ret = ta_reset(&tas->locked, ta_str); + + pthread_rwlock_unlock(&tas->rwlock); + return ret; +} + +static knot_rrset_t *ta_find(struct trust_anchors_nolock *tan, const knot_dname_t *name) +{ + assert(tan && name); + + knot_rrset_t *found = NULL; + + int i; + for (i = 0; i < tan->used; ++i) { + if (knot_dname_is_equal(tan->anchors[i]->owner, name)) { + found = tan->anchors[i]; + break; + } + } + + return found; +} + +static int ta_add(struct trust_anchors_nolock *tan, const char *ta_str) +{ + assert(tan && ta_str); + + if (tan->used >= MAX_ANCHORS) { + return kr_error(ENOMEM); + } + + knot_rrset_t *ta = NULL; + int ret = kr_ta_parse(&ta, ta_str, &tan->pool); + if (ret != 0) { + return ret; + } + assert(ta); + + knot_rrset_t *found = ta_find(tan, ta->owner); + if (!found) { + tan->anchors[tan->used++] = ta; + return kr_ok(); + } + + if (found->type != ta->type) { + knot_rrset_free(&ta, &tan->pool); + return kr_error(EINVAL); + } + + ret = knot_rdataset_merge(&found->rrs, &ta->rrs, &tan->pool); + knot_rrset_free(&ta, &tan->pool); + if (ret != 0) { + return ret; + } + + return kr_ok(); +} + +int kr_ta_add(struct trust_anchors *tas, const char *ta_str) +{ + if (!tas || !ta_str) { + return kr_error(EINVAL); + } + + int ret = pthread_rwlock_wrlock(&tas->rwlock); + if (ret != 0) { + return kr_error(ret); + } + + ret = ta_add(&tas->locked, ta_str); + + pthread_rwlock_unlock(&tas->rwlock); + return ret; +} + +static int ta_get(knot_rrset_t **ta, struct trust_anchors_nolock *tan, const knot_dname_t *name, mm_ctx_t *pool) +{ + assert(ta && tan && name); + + knot_rrset_t *copy = ta_find(tan, name); + if (!copy) { + kr_error(ENOENT); + } + + copy = knot_rrset_copy(copy, pool); + if (!copy) { + kr_error(ENOMEM); + } + + *ta = copy; + + return kr_ok(); +} + +int kr_ta_get(knot_rrset_t **ta, struct trust_anchors *tas, const knot_dname_t *name, mm_ctx_t *pool) +{ + if (!ta || !tas || !name) { + return kr_error(EINVAL); + } + + int ret = pthread_rwlock_rdlock(&tas->rwlock); + if (ret != 0) { + return kr_error(ret); + } + + ret = ta_get(ta, &tas->locked, name, pool); + + pthread_rwlock_unlock(&tas->rwlock); + return ret; +} diff --git a/lib/dnssec/ta.h b/lib/dnssec/ta.h index cf525059419723a18d55ed7a53816e81c2640d65..83d89d1f7751afdd90be67dc7397bd1935949f24 100644 --- a/lib/dnssec/ta.h +++ b/lib/dnssec/ta.h @@ -20,6 +20,7 @@ #include <libknot/rrset.h> //#define ROOT_TA ". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5" +#define ROOT_NAME "" #define ROOT_TA ". IN DS 19036 RSASHA256 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5" //#define ROOT_TA ". IN DNSKEY 257 3 8 AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq QxA+Uk1ihz0=" @@ -32,3 +33,19 @@ * @return 0 or an error code */ int kr_ta_parse(knot_rrset_t **rr, const char *ds_str, mm_ctx_t *pool); + +/** Trust anchor container structure. */ +struct trust_anchors; + +/** Global trust anchor container. */ +extern struct trust_anchors global_trust_anchors; + +int kr_ta_init(struct trust_anchors *tas); + +void kr_ta_deinit(struct trust_anchors *tas); + +int kr_ta_reset(struct trust_anchors *tas, const char *ta_str); + +int kr_ta_add(struct trust_anchors *tas, const char *ta_str); + +int kr_ta_get(knot_rrset_t **ta, struct trust_anchors *tas, const knot_dname_t *name, mm_ctx_t *pool); diff --git a/lib/layer/validate.c b/lib/layer/validate.c index d746390a057665bfc5e2b0c63b599ee25e24e750..80b32eaab5934eece8d83515f7103cef102b7ccd 100644 --- a/lib/layer/validate.c +++ b/lib/layer/validate.c @@ -440,7 +440,43 @@ const knot_layer_api_t *validate_layer(struct kr_module *module) .begin = &begin, .consume = &validate, }; + /* Store module reference */ return &_layer; } +int validate_init(struct kr_module *module) +{ + int ret = kr_ta_init(&global_trust_anchors); + if (ret != 0) { + return ret; + } + /* Add root trust anchor. */ + ret = kr_ta_add(&global_trust_anchors, ROOT_TA); + if (ret != 0) { + return ret; + } + return kr_ok(); +} + +#warning TODO: set root trust anchor from config +int validate_config(struct kr_module *module, const char *conf) +{ + return kr_ok(); +} + +int validate_deinit(struct kr_module *module) +{ + kr_ta_deinit(&global_trust_anchors); + return kr_ok(); +} + +const struct kr_prop validate_prop_list[] = { + { NULL, NULL, NULL } +}; + +struct kr_prop *validate_props(void) +{ + return (struct kr_prop *) validate_prop_list; +} + KR_MODULE_EXPORT(validate) diff --git a/lib/module.c b/lib/module.c index 071394940611722b5cb47b4441e181ed2a8e0097..53cfbe15c892e26e9f912369016c314f6ad3c8a0 100644 --- a/lib/module.c +++ b/lib/module.c @@ -25,12 +25,16 @@ /* List of embedded modules */ const knot_layer_api_t *iterate_layer(struct kr_module *module); +int validate_init(struct kr_module *module); +int validate_deinit(struct kr_module *module); +int validate_config(struct kr_module *module, const char *conf); const knot_layer_api_t *validate_layer(struct kr_module *module); +extern struct kr_prop validate_prop_list[]; const knot_layer_api_t *rrcache_layer(struct kr_module *module); const knot_layer_api_t *pktcache_layer(struct kr_module *module); static const struct kr_module embedded_modules[] = { { "iterate", NULL, NULL, NULL, iterate_layer, NULL, NULL, NULL }, - { "validate", NULL, NULL, NULL, validate_layer, NULL, NULL, NULL }, + { "validate", validate_init, validate_deinit, validate_config, validate_layer, validate_prop_list, NULL, NULL }, { "rrcache", NULL, NULL, NULL, rrcache_layer, NULL, NULL, NULL }, { "pktcache", NULL, NULL, NULL, pktcache_layer, NULL, NULL, NULL }, }; diff --git a/lib/zonecut.c b/lib/zonecut.c index 5265936c1be2e2f0998c4eb93b4f01431d3c4ee6..c0bb394a99169954fa113e42d725af370749a4f1 100644 --- a/lib/zonecut.c +++ b/lib/zonecut.c @@ -289,10 +289,12 @@ int kr_zonecut_set_sbelt(struct kr_context *ctx, struct kr_zonecut *cut) } } -#warning TODO: set root trust anchor from config /* Set trust anchor. */ knot_rrset_free(&cut->trust_anchor, cut->pool); - int ret = kr_ta_parse(&cut->trust_anchor, ROOT_TA, cut->pool); + /* The root trust anchor can be changed via the validator layer + * (interactive) interface. + */ + int ret = kr_ta_get(&cut->trust_anchor, &global_trust_anchors, ROOT_NAME, cut->pool); if (ret != 0) { return ret; }