]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
lib: saner TA store, in Lua module ‘trust_anchors’
authorMarek Vavruša <marek.vavrusa@nic.cz>
Mon, 21 Sep 2015 07:17:21 +0000 (09:17 +0200)
committerMarek Vavruša <marek.vavrusa@nic.cz>
Mon, 21 Sep 2015 07:17:21 +0000 (09:17 +0200)
preparations for TA rotation and management
in config:
trust_anchors.file = ‘root.key’
trust_anchors.auto = true // NOTIMPL
trust_anchors.add(‘. IN DS …’) // Manual addition

daemon/engine.c
daemon/lua/kres.lua
daemon/lua/sandbox.lua
lib/dnssec/ta.c
lib/dnssec/ta.h
lib/layer/validate.c
lib/module.c
lib/resolve.c
lib/resolve.h
tests/kresd.j2

index 47de46590fc19b80deef3a2b16e7801f175c453d..b2e2bcd81aaa0c6b8b8c498a5412d8aeebe828dc 100644 (file)
@@ -27,6 +27,7 @@
 #include "lib/nsrep.h"
 #include "lib/cache.h"
 #include "lib/defines.h"
+#include "lib/dnssec/ta.h"
 
 /** @internal Compatibility wrapper for Lua < 5.2 */
 #if LUA_VERSION_NUM < 502
@@ -243,6 +244,7 @@ void *namedb_lmdb_mkopts(const char *conf, size_t maxsize)
 static int init_resolver(struct engine *engine)
 {
        /* Open resolution context */
+       engine->resolver.trust_anchors = map_make();
        engine->resolver.pool = engine->pool;
        engine->resolver.modules = &engine->modules;
        /* Create OPT RR */
@@ -363,6 +365,7 @@ void engine_deinit(struct engine *engine)
        }
        array_clear(engine->modules);
        array_clear(engine->storage_registry);
+       kr_ta_clear(&engine->resolver.trust_anchors);
 
        if (engine->L) {
                lua_close(engine->L);
@@ -402,6 +405,12 @@ int engine_cmd(struct engine *engine, const char *str)
 
 static int engine_loadconf(struct engine *engine)
 {
+       /* Use module path for including Lua scripts */
+       static const char l_paths[] = "package.path = package.path..';" PREFIX MODULEDIR "/?.lua'";
+       int ret = l_dobytecode(engine->L, l_paths, sizeof(l_paths) - 1, "");
+       if (ret != 0) {
+               lua_pop(engine->L, 1);
+       }
        /* Init environment */
        static const char sandbox_bytecode[] = {
                #include "daemon/lua/sandbox.inc"
@@ -411,12 +420,6 @@ static int engine_loadconf(struct engine *engine)
                lua_pop(engine->L, 1);
                return kr_error(ENOEXEC);
        }
-       /* Use module path for including Lua scripts */
-       int ret = engine_cmd(engine, "package.path = package.path..';" PREFIX MODULEDIR "/?.lua'");
-       if (ret > 0) {
-               lua_pop(engine->L, 1);
-       }
-
        /* Load config file */
        if(access("config", F_OK ) != -1 ) {
                ret = l_dosandboxfile(engine->L, "config");
index e548ad239802b014576e135e78b5646b7a4d9dc6..649224a1fdc9b5aefb4dd754abf9628c89718454 100644 (file)
@@ -125,6 +125,16 @@ typedef struct {
        uint8_t _stub[]; /* Do not touch */
 } knot_pkt_t;
 
+/* generics */
+typedef void *(*map_alloc_f)(void *, size_t);
+typedef void (*map_free_f)(void *baton, void *ptr);
+typedef struct {
+       void *root;
+       map_alloc_f malloc;
+       map_free_f free;
+       void *baton;
+} map_t;
+
 /* libkres */
 struct kr_query {
        node_t _node;
@@ -141,16 +151,23 @@ struct kr_rplan {
        uint8_t _stub[]; /* Do not touch */
 };
 struct kr_request {
-       struct kr_context *_ctx;
+       struct kr_context *ctx;
        knot_pkt_t *answer;
-    struct {
-        const knot_rrset_t *key;
-        const struct sockaddr *addr;
-    } qsource;
+       struct {
+               const knot_rrset_t *key;
+               const struct sockaddr *addr;
+       } qsource;
        uint32_t options;
        int state;
        uint8_t _stub[]; /* Do not touch */
 };
+struct kr_context
+{      
+       uint32_t options;
+       knot_rrset_t *opt_rr;
+       map_t trust_anchors;
+       uint8_t _stub[]; /* Do not touch */
+};
 
 /* libknot API
  */
@@ -172,6 +189,12 @@ struct kr_rplan *kr_resolve_plan(struct kr_request *request);
 /* Resolution plan */
 struct kr_query *kr_rplan_current(struct kr_rplan *rplan);
 /* Query */
+/* Trust anchors */
+knot_rrset_t *kr_ta_get(map_t *trust_anchors, const knot_dname_t *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);
+int kr_ta_del(map_t *trust_anchors, const knot_dname_t *name);
+void kr_ta_clear(map_t *trust_anchors);
 /* Utils */
 unsigned kr_rand_uint(unsigned max);
 int kr_pkt_put(knot_pkt_t *pkt, const knot_dname_t *name, uint32_t ttl,
@@ -236,6 +259,33 @@ ffi.metatype( kr_request_t, {
        },
 })
 
+-- Return DS/DNSKEY parser that adds keys to TA store
+local function ta_parser(store)
+       local parser = require('zonefile').parser(function (p)
+               C.kr_ta_add(store, p.r_owner, p.r_type, p.r_ttl, p.r_data, p.r_data_length)
+       end)
+       return parser
+end
+
+-- TA store management
+local trust_anchors = {
+       current_file = "",
+       is_auto = false,
+       store = ffi.cast('struct kr_context *', __engine).trust_anchors,
+       -- Load keys from a file
+       config = function (path)
+               ta_parser(trust_anchors.store):parse_file(path)
+               trust_anchors.current_file = path
+       end,
+       -- Add DS/DNSKEY record
+       add = function (ds) ta_parser(trust_anchors.store):read(ds..'\n') end,
+       clear = function() C.kr_ta_clear(trust_anchors.store) end,
+       -- Set/disable RFC5011 TA management
+       set_auto = function (enable)
+               error("not supported")
+       end,
+}
+
 -- Module API
 local kres = {
        -- Constants
@@ -248,6 +298,8 @@ local kres = {
        pkt_t = function (udata) return ffi.cast('knot_pkt_t *', udata) end,
        request_t = function (udata) return ffi.cast('struct kr_request *', udata) end,
        -- Global API functions
+       context = function () return ffi.cast('struct kr_context *', __engine) end,
+       trust_anchors = trust_anchors,
 }
 
 return kres
\ No newline at end of file
index 53559156ea1007b30c511a4cec6c239551a02266..a918bf75ec89bc7fbe6cddf87afc5b173dff9219 100644 (file)
@@ -64,6 +64,16 @@ setmetatable(cache, {
        end
 })
 
+-- Syntactic sugar for TA store
+trust_anchors = require('kres').trust_anchors
+setmetatable(trust_anchors, {
+       __newindex = function (t,k,v)
+       if     k == 'file' then t.config(v)
+       elseif k == 'auto' then t.set_auto(v)
+       else   rawset(t, k, v) end
+       end,
+})
+
 -- Register module in Lua environment
 function modules_register(module)
        -- Syntactic sugar for get() and set() properties
@@ -85,7 +95,7 @@ end
 
 -- Make sandboxed environment
 local function make_sandbox(defined)
-       local __protected = { modules = true, cache = true, net = true }
+       local __protected = { modules = true, cache = true, net = true, trust_anchors = true }
        return setmetatable({}, {
                __index = defined,
                __newindex = function (t, k, v)
index f9fd2bd9630d26900cf64ecc09b0aaefda66e5d6..e39eef8045b6bb35cfc0512e666382f847cc679f 100644 (file)
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#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 <libknot/packet/wire.h>
 
 #include "lib/defines.h"
 #include "lib/dnssec/ta.h"
 
-static int dname_parse(knot_dname_t **dname, const char *dname_str, mm_ctx_t *pool)
-{
-       if (!dname) {
-               return kr_error(EINVAL);
-       }
-
-       knot_dname_t *owner = mm_alloc(pool, KNOT_DNAME_MAXLEN);
-       if (owner == NULL) {
-               return kr_error(ENOMEM);
-       }
-       knot_dname_t *aux = knot_dname_from_str(owner, dname_str, KNOT_DNAME_MAXLEN);
-       if (aux == NULL) {
-               mm_free(pool, owner);
-               return kr_error(ENOMEM);
-       }
-
-       assert(!*dname);
-       *dname = owner;
-       return 0;
-}
-
-static int uint_parse(const char *str, unsigned *u)
-{
-       char *err_pos;
-       long num = strtol(str, &err_pos, 10);
-       if ((*err_pos != '\0') || (num < 0)) {
-               return kr_error(EINVAL);
-       }
-       *u = (unsigned) num;
-       return 0;
-}
-
-static int strcicmp(char const *a, char const *b)
-{
-       if (!a && !b) {
-               return 0;
-       }
-       if (!a) {
-               return -1;
-       }
-       if (!b) {
-               return 1;
-       }
-       for ( ; ; ++a, ++b) {
-               int d = tolower(*a) - tolower(*b);
-               if ((d != 0) || (*a == '\0')) {
-                       return d;
-               }
-       }
-}
-
-static int algorithm_parse(const char *str, unsigned *u)
-{
-       int ret = uint_parse(str, u);
-       if (ret == 0) {
-               return 0;
-       }
-
-       const lookup_table_t *item = knot_dnssec_alg_names;
-       while (item->id) {
-               if (strcicmp(str, item->name) == 0) {
-                       break;
-               }
-               ++item;
-       }
-
-       if (!item->id) {
-               return kr_error(ENOENT);
-       }
-
-       *u = (unsigned) item->id;
-       return 0;
-}
-
-static int hex2value(const char hex)
-{
-       if ((hex >= '0') && (hex <= '9')) {
-               return hex - '0';
-       } else if ((hex >= 'a') && (hex <= 'f')) {
-               return hex - 'a' + 10;
-       } else if ((hex >= 'A') && (hex <= 'F')) {
-               return hex - 'A' + 10;
-       } else {
-               return -1;
-       }
-}
-
-static int hex2byte(const char hex[2], uint8_t *u)
-{
-       int d0, d1;
-       d0 = hex2value(hex[0]);
-       d1 = hex2value(hex[1]);
-
-       if ((d0 == -1) || (d1 == -1)) {
-               return kr_error(EINVAL);
-       }
-
-       *u = ((d0 & 0x0f) << 4) | (d1 & 0x0f);
-       return 0;
-}
-
-static int ta_ds_parse(uint8_t *rd, size_t *rd_written, size_t rd_maxsize, const char *seps, char **saveptr)
-{
-       if (!rd || !rd_written || !seps || !saveptr) {
-               return kr_error(EINVAL);
-       }
-
-       int ret = 0;
-       const char *token;
-       unsigned aux;
-
-       /* Key tag. */
-       token = strtok_r(NULL, seps, saveptr);
-       if (!token) {
-               return kr_error(EINVAL);
-       }
-       ret = uint_parse(token, &aux);
-       if (ret != 0) {
-               return ret;
-       }
-       uint16_t key_tag = aux;
-
-       /* Algorithm. */
-       token = strtok_r(NULL, seps, saveptr);
-       if (!token) {
-               return kr_error(EINVAL);
-       }
-       ret = algorithm_parse(token, &aux);
-       if (ret != 0) {
-               return ret;
-       }
-       uint8_t algorithm = aux;
-
-       /* Digest type. */
-       token = strtok_r(NULL, seps, saveptr);
-       if (!token) {
-               return kr_error(EINVAL);
-       }
-       ret = uint_parse(token, &aux);
-       if (ret != 0) {
-               return ret;
-       }
-       uint8_t digest_type = aux;
-
-       size_t rd_pos = 0;
-       if (rd_maxsize >= 4) {
-               * (uint16_t *) (rd + rd_pos) = htons(key_tag); rd_pos += 2;
-               *(rd + rd_pos++) = algorithm;
-               *(rd + rd_pos++) = digest_type;
-       } else {
-               return kr_error(EINVAL);
-       }
-
-       char hexbuf[2];
-       int i = 0;
-       while ((token = strtok_r(NULL, seps, saveptr)) != NULL) {
-               for (int j = 0; j < strlen(token); ++j) {
-                       hexbuf[i++] = token[j];
-                       if (i == 2) {
-                               uint8_t byte;
-                               ret = hex2byte(hexbuf, &byte);
-                               if (ret != 0) {
-                                       return ret;
-                               }
-                               i = 0;
-
-                               if (rd_pos < rd_maxsize) {
-                                       *(rd + rd_pos++) = byte;
-                               } else {
-                                       return kr_error(ENOMEM);
-                               }
-                       }
-               }
-       }
-
-       if (i != 0) {
-               return kr_error(EINVAL);
-       }
-
-       *rd_written = rd_pos;
-       return 0;
-}
-
-static int base2bytes(const uint8_t base[4], uint8_t bytes[3], unsigned *valid)
+knot_rrset_t *kr_ta_get(map_t *trust_anchors, const knot_dname_t *name)
 {
-       int32_t decoded = base64_decode(base, 4, bytes, 3);
-       if (decoded < 0) {
-               return kr_error(EINVAL);
-       }
-       *valid = decoded;
-       return 0;
+       return map_get(trust_anchors, (const char *)name);
 }
 
-static int ta_dnskey_parse(uint8_t *rd, size_t *rd_written, size_t rd_maxsize, const char *seps, char **saveptr)
+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)
 {
-       fprintf(stderr, "%s()\n", __func__);
-
-       if (!rd || !rd_written || !seps || !saveptr) {
-               return kr_error(EINVAL);
-       }
-
-       int ret = 0;
-       const char *token;
-       unsigned aux;
-
-       /* Flags. */
-       token = strtok_r(NULL, seps, saveptr);
-       if (!token) {
-               return kr_error(EINVAL);
-       }
-       ret = uint_parse(token, &aux);
-       if (ret != 0) {
-               return ret;
-       }
-       uint16_t flags = aux;
-
-       /* Protocol. */
-       token = strtok_r(NULL, seps, saveptr);
-       if (!token) {
-               return kr_error(EINVAL);
-       }
-       ret = uint_parse(token, &aux);
-       if (ret != 0) {
-               return ret;
-       }
-       uint8_t protocol = aux;
-       if (protocol != 3) {
-               return kr_error(EINVAL);
-       }
-
-       /* Algorithm. */
-       token = strtok_r(NULL, seps, saveptr);
-       if (!token) {
-               return kr_error(EINVAL);
-       }
-       ret = algorithm_parse(token, &aux);
-       if (ret != 0) {
-               return ret;
-       }
-       uint8_t algorithm = aux;
-
-       size_t rd_pos = 0;
-       if (rd_maxsize >= 4) {
-               * (uint16_t *) (rd + rd_pos) = htons(flags); rd_pos += 2;
-               *(rd + rd_pos++) = protocol;
-               *(rd + rd_pos++) = algorithm;
-       } else {
+       if (!trust_anchors || !name || !rdata) {
                return kr_error(EINVAL);
        }
 
-       uint8_t basebuf[4];
-       uint8_t databuf[3];
-       int i = 0;
-       while ((token = strtok_r(NULL, seps, saveptr)) != NULL) {
-               for (int j = 0; j < strlen(token); ++j) {
-                       basebuf[i++] = token[j];
-                       if (i == 4) {
-                               unsigned written;
-                               ret = base2bytes(basebuf, databuf, &written);
-                               if (ret != 0) {
-                                       return ret;
-                               }
-                               i = 0;
-
-                               if ((rd_pos + written) < rd_maxsize) {
-                                       memcpy(rd + rd_pos, databuf, written);
-                                       rd_pos += written;
-                               } else {
-                                       return kr_error(ENOMEM);
-                               }
-                       }
-               }
-       }
-
-       if (i != 0) {
-               return kr_error(EINVAL);
-       }
-
-       *rd_written = rd_pos;
-       return 0;
-}
-
-int kr_ta_parse(knot_rrset_t **rr, const char *ds_str, mm_ctx_t *pool)
-{
-#define SEPARATORS " \t\n\r"
-#define RDATA_MAXSIZE 640
-       int ret = 0;
-
-       if (!rr || !ds_str || !pool) {
-               ret = kr_error(EINVAL);
-               goto fail;
-       }
-
-       char *ds_cpy = NULL;
-       knot_dname_t *owner = NULL;
-       knot_rdata_t *rdata = NULL;
-       knot_rrset_t *ds_set = NULL;
-
-       size_t ds_len = strlen(ds_str) + 1;
-       ds_cpy = mm_alloc(pool, ds_len);
-       if (!ds_cpy) {
-               ret = kr_error(ENOMEM);
-               goto fail;
-       }
-       memcpy(ds_cpy, ds_str, ds_len);
-       char *saveptr = NULL, *token;
-
-       /* Owner name. */
-       token = strtok_r(ds_cpy, SEPARATORS, &saveptr);
-       if (!token) {
-               ret = kr_error(EINVAL);
-               goto fail;
-       }
-       ret = dname_parse(&owner, token, pool);
-       if (ret != 0) {
-               goto fail;
-       }
-
-       /* TTL may be missing. */
-       uint32_t ttl = 0;
-       token = strtok_r(NULL, SEPARATORS, &saveptr);
-       if (isdigit(token[0])) {
-               unsigned aux;
-               ret = uint_parse(token, &aux);
-               if (ret != 0) {
-                       goto fail;
-               }
-               ttl = aux;
-               /* Read class token. */
-               token = strtok_r(NULL, SEPARATORS, &saveptr);
-       }
-
-       /* Class. */
-       uint16_t class;
-       /* Token already read. */
-       if (!token) {
-               ret = kr_error(EINVAL);
-               goto fail;
-       }
-       ret = knot_rrclass_from_string(token, &class);
-       if (ret != 0) {
-               ret = kr_error(EINVAL);
-               goto fail;
-       }
-
-       /* Type. */
-       uint16_t type;
-       token = strtok_r(NULL, SEPARATORS, &saveptr);
-       if (!token) {
-               ret = kr_error(EINVAL);
-               goto fail;
-       }
-       ret = knot_rrtype_from_string(token, &type);
-       if ((ret != 0) ||
-           ((type != KNOT_RRTYPE_DS) && (type != KNOT_RRTYPE_DNSKEY))) {
-               ret = kr_error(EINVAL);
-               goto fail;
-       }
-
-       /* Construct RDATA. */
-       rdata = mm_alloc(pool, RDATA_MAXSIZE);
-       if (!rdata) {
-               ret = kr_error(ENOMEM);
-               goto fail;
-       }
-       size_t rd_written = 0;
-
+       /* Convert DNSKEY records to DS */
        switch (type) {
-       case KNOT_RRTYPE_DS:
-               ret = ta_ds_parse(rdata, &rd_written, RDATA_MAXSIZE, SEPARATORS, &saveptr);
-               break;
+       case KNOT_RRTYPE_DS: break; /* OK */
        case KNOT_RRTYPE_DNSKEY:
-               ret = ta_dnskey_parse(rdata, &rd_written, RDATA_MAXSIZE, SEPARATORS, &saveptr);
-               break;
-       default:
-               assert(0);
-               ret = kr_error(EINVAL);
+#warning TODO: convert DNSKEY -> DS here
+               return kr_error(ENOSYS);
                break;
+       default: return kr_error(EINVAL);
        }
-       if (ret != 0) {
-               goto fail;
-       }
-
-       ds_set = knot_rrset_new(owner, type, class, pool);
-       if (!ds_set) {
-               ret = kr_error(ENOMEM);
-               goto fail;
-       }
-
-       ret = knot_rrset_add_rdata(ds_set, rdata, rd_written, ttl, pool);
-       if (ret != 0) {
-               goto fail;
-       }
-
-       *rr = ds_set;
-       ds_set = NULL;
-
-fail:
-       knot_rrset_free(&ds_set, pool);
-       mm_free(pool, rdata);
-       knot_dname_free(&owner, pool);
-       mm_free(pool, ds_cpy);
-       return ret;
-#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;
-               }
+       /* Create new RRSet or use existing */
+       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);
+               is_new_key = true;
        }
-
-       return found;
-}
-
-static int ta_add(struct trust_anchors_nolock *tan, const char *ta_str)
-{
-       assert(tan && ta_str);
-
-       if (tan->used >= MAX_ANCHORS) {
+       /* Merge-in new key data */
+       if (!ta_rr || knot_rrset_add_rdata(ta_rr, rdata, rdlen, ttl, NULL) != 0) {
+               knot_rrset_free(&ta_rr, NULL);
                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();
+       /* Reinsert */
+       if (is_new_key) {
+               map_set(trust_anchors, (const char *)name, ta_rr);
        }
 
-       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();
+       return kr_ok(); 
 }
 
-int kr_ta_contains(struct trust_anchors *tas, const knot_dname_t *name)
-{
-       return ta_find(&tas->locked, name) != NULL;
-}
-
-int kr_ta_covers(struct trust_anchors *tas, const knot_dname_t *name)
+int kr_ta_covers(map_t *trust_anchors, const knot_dname_t *name)
 {
        while(name) {
-               if (kr_ta_contains(tas, name)) {
+               if (kr_ta_get(trust_anchors, name)) {
                        return true;
                }
                if (name[0] == '\0') {
@@ -656,63 +75,29 @@ int kr_ta_covers(struct trust_anchors *tas, const knot_dname_t *name)
                }
                name = knot_wire_next_label(name, NULL);
        }
-       return false;   
-}
-
-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;
-}
-
-int kr_ta_rdlock(struct trust_anchors *tas)
-{
-       if (!tas) {
-               return kr_error(EINVAL);
-       }
-
-       return pthread_rwlock_rdlock(&tas->rwlock);
+       return false;
 }
 
-int kr_ta_unlock(struct trust_anchors *tas)
+/* Delete record data */
+static int del_record(const char *k, void *v, void *ext)
 {
-       if (!tas) {
-               return kr_error(EINVAL);
-       }
-
-       return pthread_rwlock_unlock(&tas->rwlock);
+       knot_rrset_t *ta_rr = v;
+       knot_rrset_free(&ta_rr, NULL);
+       return 0;
 }
 
-int kr_ta_rrs_count_nolock(struct trust_anchors *tas)
+int kr_ta_del(map_t *trust_anchors, const knot_dname_t *name)
 {
-       if (!tas) {
-               return kr_error(EINVAL);
+       knot_rrset_t *ta_rr = kr_ta_get(trust_anchors, name);
+       if (ta_rr) {
+               del_record(NULL, ta_rr, NULL);
+               map_del(trust_anchors, (const char *)name);
        }
-
-       return tas->locked.used;
+       return kr_ok();
 }
 
-int kr_ta_rrs_at_nolock(const knot_rrset_t **ta, struct trust_anchors *tas, size_t pos)
+void kr_ta_clear(map_t *trust_anchors)
 {
-       if (!tas || !ta) {
-               return kr_error(EINVAL);
-       }
-
-       if (pos >= tas->locked.used) {
-               return kr_error(EINVAL);
-       }
-
-       *ta = tas->locked.anchors[pos];
-       return kr_ok();
+       map_walk(trust_anchors, del_record, NULL);
+       map_clear(trust_anchors);
 }
index 3900044373bc2a11c80ba6a216f86d1e9d07a135..6c712a0db162205b985d01c66d837ea8e77f8a4d 100644 (file)
 
 #pragma once
 
-#include <libknot/internal/mempattern.h>
+#include "lib/generic/map.h"
 #include <libknot/rrset.h>
 
-//#define ROOT_TA ". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5"
-#define ROOT_NAME ((const uint8_t *) "")
-#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="
-
 /**
- * Parses the supplied trust anchor string and creates a new RRSet.
- *
- * @param rr     created resource record
- * @param ds_str DS in presentation format
- * @param pool
- * @return       0 or an error code
+ * Find TA RRSet by name.
+ * @param  trust_anchors trust store
+ * @param  name          name of the TA
+ * @return non-empty RRSet or NULL
  */
-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_contains(struct trust_anchors *tas, const knot_dname_t *name);
+knot_rrset_t *kr_ta_get(map_t *trust_anchors, const knot_dname_t *name);
 
-int kr_ta_covers(struct trust_anchors *tas, const knot_dname_t *name);
+/**
+ * Add TA to trust store. DS or DNSKEY types are supported.
+ * @param  trust_anchors trust store
+ * @param  name          name of the TA
+ * @param  type          RR type of the TA (DS or DNSKEY)
+ * @param  ttl           
+ * @param  rdata         
+ * @param  rdlen         
+ * @return 0 or an error
+ */
+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);
 
-int kr_ta_get(knot_rrset_t **ta, struct trust_anchors *tas, const knot_dname_t *name, mm_ctx_t *pool);
+/**
+ * Return true if the name is below/at any TA in the store.
+ * This can be useful to check if it's possible to validate a name beforehand.
+ * @param  trust_anchors trust store
+ * @param  name          name of the TA
+ * @return boolean
+ */
+int kr_ta_covers(map_t *trust_anchors, const knot_dname_t *name);
 
-int kr_ta_rdlock(struct trust_anchors *tas);
-int kr_ta_unlock(struct trust_anchors *tas);
+/**
+ * Remove TA from trust store.
+ * @param  trust_anchors trust store
+ * @param  name          name of the TA
+ * @return 0 or an error
+ */
+int kr_ta_del(map_t *trust_anchors, const knot_dname_t *name);
 
-int kr_ta_rrs_count_nolock(struct trust_anchors *tas);
-int kr_ta_rrs_at_nolock(const knot_rrset_t **ta, struct trust_anchors *tas, size_t pos);
+/**
+ * Clear trust store.
+ * @param trust_anchors trust store
+ */
+void kr_ta_clear(map_t *trust_anchors);
index e09a67289aafc3bd0e11068fa77c258993bf57a7..31c8da944b9655f74f3555b4ba26797c451648eb 100644 (file)
 #include <stdio.h>
 #include <string.h>
 
-#include <ccan/json/json.h>
 #include <libknot/packet/wire.h>
-#include <libknot/rrset-dump.h>
 #include <libknot/rrtype/rdname.h>
 #include <libknot/rrtype/rrsig.h>
 
 #include "lib/dnssec/nsec.h"
 #include "lib/dnssec/nsec3.h"
 #include "lib/dnssec/packet/pkt.h"
-#include "lib/dnssec/ta.h"
 #include "lib/dnssec.h"
 #include "lib/layer.h"
 #include "lib/resolve.h"
 #include "lib/rplan.h"
 #include "lib/defines.h"
-#include "lib/nsrep.h"
 #include "lib/module.h"
 
 #define DEBUG_MSG(qry, fmt...) QRDEBUG(qry, "vldr", fmt)
 
-static knot_dump_style_t KNOT_DUMP_STYLE_TA = {
-       .wrap = false,
-       .show_class = true,
-       .show_ttl = false,
-       .verbose = false,
-       .empty_ttl = false,
-       .human_ttl = false,
-       .human_tmstamp = true,
-       .ascii_to_idn = NULL
-};
-
-/* Set resolution context and parameters. */
-static int begin(knot_layer_t *ctx, void *module_param)
-{
-       ctx->data = module_param;
-       return KNOT_STATE_PRODUCE;
-}
-
 struct rrset_ids {
        const knot_dname_t *owner;
        uint16_t type;
@@ -505,99 +483,10 @@ static int validate(knot_layer_t *ctx, knot_pkt_t *pkt)
        DEBUG_MSG(qry, "<= answer valid, OK\n");
        return ctx->state;
 }
-
-static int rrset_txt_dump_line(const knot_rrset_t *rrset, size_t pos,
-                               char *dst, const size_t maxlen, const knot_dump_style_t *style)
-{
-       assert(rrset && dst && maxlen && style);
-
-       int written = 0;
-       uint32_t ttl = knot_rdata_ttl(knot_rdataset_at(&rrset->rrs, 0));
-       int ret = knot_rrset_txt_dump_header(rrset, ttl, dst + written, maxlen - written, style);
-       if (ret <= 0) {
-               return ret;
-       }
-       written += ret;
-       ret = knot_rrset_txt_dump_data(rrset, pos, dst + written, maxlen - written, style);
-       if (ret <= 0) {
-               return ret;
-       }
-       written += ret;
-
-       return written;
-}
-
-static char *validate_trust_anchors(void *env, struct kr_module *module, const char *args)
-{
-#define MAX_BUF_LEN 1024
-       JsonNode *root = json_mkarray();
-
-       kr_ta_rdlock(&global_trust_anchors);
-
-       const knot_rrset_t *ta;
-       int count = kr_ta_rrs_count_nolock(&global_trust_anchors);
-       for (int i = 0; i < count; ++i) {
-               ta = NULL;
-               kr_ta_rrs_at_nolock(&ta, &global_trust_anchors, i);
-               assert(ta);
-               char buf[MAX_BUF_LEN];
-               for (uint16_t j = 0; j < ta->rrs.rr_count; ++j) {
-                       buf[0] = '\0';
-                       rrset_txt_dump_line(ta, j, buf, MAX_BUF_LEN, &KNOT_DUMP_STYLE_TA);
-                       json_append_element(root, json_mkstring(buf));
-               }
-       }
-
-       kr_ta_unlock(&global_trust_anchors);
-
-       char *result = json_encode(root);
-       json_delete(root);
-       return result;
-#undef MAX_BUF_LEN
-}
-
-static char *validate_trust_anchor_add(void *env, struct kr_module *module, const char *args)
-{
-       int ret = 0;
-       if (!args || (args[0] == '\0')) {
-               ret = kr_error(EINVAL);
-       } else {
-               ret = kr_ta_add(&global_trust_anchors, args);
-       }
-
-       char *result = NULL;
-       asprintf(&result, "{ \"result\": %s }", ret == 0 ? "true" : "false");
-       return result;
-}
-
-static int load(struct trust_anchors *tas, const char *path)
-{
-#define MAX_LINE_LEN 512
-       auto_fclose FILE *fp = fopen(path, "r");
-       if (fp == NULL) {
-               DEBUG_MSG(NULL, "reading '%s' failed: %s\n", path, strerror(errno));
-               return kr_error(errno);
-       } else {
-               DEBUG_MSG(NULL, "reading '%s'\n", path);
-       }
-
-       char line[MAX_LINE_LEN];
-       while (fgets(line, sizeof(line), fp) != NULL) {
-               int ret = kr_ta_add(tas, line);
-               if (ret != 0) {
-                       return ret;
-               }
-       }
-
-       return kr_ok();
-#undef MAX_LINE_LEN
-}
-
 /** Module implementation. */
 const knot_layer_api_t *validate_layer(struct kr_module *module)
 {
        static const knot_layer_api_t _layer = {
-               .begin = &begin,
                .consume = &validate,
        };
        /* Store module reference */
@@ -606,42 +495,7 @@ const knot_layer_api_t *validate_layer(struct kr_module *module)
 
 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();
-}
-
-int validate_config(struct kr_module *module, const char *conf)
-{
-       int ret = kr_ta_reset(&global_trust_anchors, NULL);
-       if (ret != 0) {
-               return ret;
-       }
-       return load(&global_trust_anchors, conf);
-}
-
-int validate_deinit(struct kr_module *module)
-{
-       kr_ta_deinit(&global_trust_anchors);
        return kr_ok();
 }
 
-const struct kr_prop validate_prop_list[] = {
-    { &validate_trust_anchors, "trust_anchors", "Retrieve trust anchors.", },
-    { &validate_trust_anchor_add, "trust_anchor_add", "Adds a trust anchor.", },
-    { NULL, NULL, NULL }
-};
-
-struct kr_prop *validate_props(void)
-{
-       return (struct kr_prop *) validate_prop_list;
-}
-
 KR_MODULE_EXPORT(validate)
index 53cfbe15c892e26e9f912369016c314f6ad3c8a0..071394940611722b5cb47b4441e181ed2a8e0097 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", validate_init, validate_deinit, validate_config, validate_layer, validate_prop_list, NULL, NULL },
+       { "validate", NULL, NULL, NULL, validate_layer, NULL, NULL, NULL },
        { "rrcache",  NULL, NULL, NULL, rrcache_layer, NULL, NULL, NULL },
        { "pktcache", NULL, NULL, NULL, pktcache_layer, NULL, NULL, NULL },
 };
index 6e6280e9fd3bbaaf3b80891e1b8d4900b8c6d646..074cbfe32d73853c6b96adde4be317026bb197de 100644 (file)
@@ -248,7 +248,9 @@ static int resolve_query(struct kr_request *request, const knot_pkt_t *packet)
 
        /* Deferred zone cut lookup for this query. */
        qry->flags |= QUERY_AWAIT_CUT;
-       if (knot_pkt_has_dnssec(packet)) {
+       /* Want DNSSEC if it's posible to secure this name (e.g. is covered by any TA) */
+       map_t *trust_anchors = &request->ctx->trust_anchors;
+       if (knot_pkt_has_dnssec(packet) && kr_ta_covers(trust_anchors, qname)) {
                qry->flags |= QUERY_DNSSEC_WANT;
        }
 
@@ -354,12 +356,13 @@ static int zone_cut_subreq(struct kr_rplan *rplan, struct kr_query *parent,
 static int zone_cut_check(struct kr_request *request, struct kr_query *qry, knot_pkt_t *packet)
 {
        struct kr_rplan *rplan = &request->rplan;
+       map_t *trust_anchors = &request->ctx->trust_anchors;
 
        /* The query wasn't resolved from cache,
         * now it's the time to look up closest zone cut from cache. */
        if (qry->flags & QUERY_AWAIT_CUT) {
                /* Want DNSSEC if it's posible to secure this name (e.g. is covered by any TA) */
-               if (kr_ta_covers(&global_trust_anchors, qry->zone_cut.name)) {
+               if (kr_ta_covers(trust_anchors, qry->zone_cut.name)) {
                        qry->flags |= QUERY_DNSSEC_WANT;
                }
                int ret = ns_fetch_cut(qry, request, (qry->flags & QUERY_DNSSEC_WANT));
@@ -376,7 +379,7 @@ static int zone_cut_check(struct kr_request *request, struct kr_query *qry, knot
        }
        /* Enable DNSSEC if enters a new island of trust. */
        bool want_secured = (qry->flags & QUERY_DNSSEC_WANT);
-       if (!want_secured && kr_ta_contains(&global_trust_anchors, qry->zone_cut.name)) {
+       if (!want_secured && kr_ta_get(trust_anchors, qry->zone_cut.name)) {
                qry->flags |= QUERY_DNSSEC_WANT;
                want_secured = true;
                WITH_DEBUG {
@@ -387,8 +390,8 @@ static int zone_cut_check(struct kr_request *request, struct kr_query *qry, knot
        }
        /* @todo Disable DNSSEC if it encounters NTA */
        if (want_secured && !qry->zone_cut.trust_anchor) {
-               kr_ta_get(&qry->zone_cut.trust_anchor, &global_trust_anchors,
-                         qry->zone_cut.name, qry->zone_cut.pool);
+               knot_rrset_t *ta_rr = kr_ta_get(trust_anchors, qry->zone_cut.name);
+               qry->zone_cut.trust_anchor = knot_rrset_copy(ta_rr, qry->zone_cut.pool);
        }
        /* Try to fetch missing DS. */
        if (want_secured && (qry->flags & QUERY_AWAIT_DS)) {
index c373819b7d9fa25c2e8ab7c2227bf3405487a3f9..d185fe48412a4b402f778573511036bacc9ca3a3 100644 (file)
@@ -20,6 +20,7 @@
 #include <libknot/processing/layer.h>
 #include <libknot/packet/pkt.h>
 
+#include "lib/generic/map.h"
 #include "lib/generic/array.h"
 #include "lib/nsrep.h"
 #include "lib/rplan.h"
@@ -81,15 +82,16 @@ typedef array_t(struct kr_module *) module_array_t;
  *       be shared between threads.
  */
 struct kr_context
-{
-       mm_ctx_t *pool;
+{      
+       uint32_t options;
+       knot_rrset_t *opt_rr;
+       map_t trust_anchors;
        struct kr_zonecut root_hints;
        struct kr_cache cache;
        kr_nsrep_lru_t *cache_rtt;
        kr_nsrep_lru_t *cache_rep;
        module_array_t *modules;
-       knot_rrset_t *opt_rr;
-       uint32_t options;
+       mm_ctx_t *pool;
 };
 
 /**
index 72b89cea37fe284d18a42fb498d52f8462ce46e3..2f787b5cf5da8a90ee5170d3391c6434430530f0 100644 (file)
@@ -1,10 +1,10 @@
-net.listen('{{SELF_ADDR}}',53)
-cache.size = 1*MB
+net = { '{{SELF_ADDR}}' }
 modules = {'stats', 'policy', 'hints'}
+cache.size = 1*MB
 hints.root({['k.root-servers.net'] = '{{ROOT_ADDR}}'})
 option('NO_MINIMIZE', {{NO_MINIMIZE}})
 option('ALLOW_LOCAL', true)
-validate.trust_anchor_add('{{TRUST_ANCHOR}}')
+trust_anchors.add('{{TRUST_ANCHOR}}')
 verbose(true)
 
 -- Self-checks on globals