]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
layer/validate: preliminary code enabling trust anchor configuration
authorKarel Slany <karel.slany@nic.cz>
Wed, 19 Aug 2015 16:27:32 +0000 (18:27 +0200)
committerKarel Slany <karel.slany@nic.cz>
Wed, 19 Aug 2015 16:27:32 +0000 (18:27 +0200)
lib/dnssec/ta.c
lib/dnssec/ta.h
lib/layer/validate.c
lib/module.c
lib/zonecut.c

index 61e64205c83f5486a11d3fd2bd085fa9ea3c5c43..59e696890f9b037b89592793e89e0767c1b42936 100644 (file)
 #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;
+}
index cf525059419723a18d55ed7a53816e81c2640d65..83d89d1f7751afdd90be67dc7397bd1935949f24 100644 (file)
@@ -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="
 
  * @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);
index d746390a057665bfc5e2b0c63b599ee25e24e750..80b32eaab5934eece8d83515f7103cef102b7ccd 100644 (file)
@@ -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)
index 071394940611722b5cb47b4441e181ed2a8e0097..53cfbe15c892e26e9f912369016c314f6ad3c8a0 100644 (file)
 
 /* 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 },
 };
index 5265936c1be2e2f0998c4eb93b4f01431d3c4ee6..c0bb394a99169954fa113e42d725af370749a4f1 100644 (file)
@@ -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;
        }