{
/* Open resolution context */
engine->resolver.trust_anchors = map_make();
+ engine->resolver.negative_anchors = map_make();
engine->resolver.pool = engine->pool;
engine->resolver.modules = &engine->modules;
/* Create OPT RR */
lru_deinit(engine->resolver.cache_rtt);
lru_deinit(engine->resolver.cache_rep);
- /* Unload modules. */
+ /* Unload modules and engine. */
for (size_t i = 0; i < engine->modules.len; ++i) {
engine_unload(engine, engine->modules.at[i]);
}
- array_clear(engine->modules);
- array_clear(engine->storage_registry);
- kr_ta_clear(&engine->resolver.trust_anchors);
-
if (engine->L) {
lua_close(engine->L);
}
+ /* Free data structures */
+ array_clear(engine->modules);
+ array_clear(engine->storage_registry);
+ kr_ta_clear(&engine->resolver.trust_anchors);
+ kr_ta_clear(&engine->resolver.negative_anchors);
}
int engine_pcall(lua_State *L, int argc)
uint32_t options;
knot_rrset_t *opt_rr;
map_t trust_anchors;
+ map_t negative_anchors;
uint8_t _stub[]; /* Do not touch */
};
-/* libknot API
+/*
+ * libc APIs
*/
+void free(void *ptr);
+/*
+ * libknot APIs
+ */
/* Domain names */
+knot_dname_t *knot_dname_from_str(uint8_t *dst, const char *name, size_t maxlen);
+char *knot_dname_to_str(char *dst, const knot_dname_t *name, size_t maxlen);
/* Resource records */
/* Packet */
const knot_dname_t *knot_pkt_qname(const knot_pkt_t *pkt);
int knot_pkt_begin(knot_pkt_t *pkt, int section_id);
int knot_pkt_put_question(knot_pkt_t *pkt, const knot_dname_t *qname, uint16_t qclass, uint16_t qtype);
-/* libkres API
+/*
+ * libkres API
*/
-
/* Resolution request */
struct kr_rplan *kr_resolve_plan(struct kr_request *request);
/* Resolution plan */
},
})
+-- Module API
+local kres_context = ffi.cast('struct kr_context *', __engine)
+local kres = {
+ -- Constants
+ class = ffi.new('struct rr_class'),
+ type = ffi.new('struct rr_type'),
+ section = ffi.new('struct pkt_section'),
+ rcode = ffi.new('struct pkt_rcode'),
+ NOOP = 0, CONSUME = 1, PRODUCE = 2, DONE = 4, FAIL = 8,
+ -- Metatypes
+ 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
+ str2dname = function(name) return ffi.string(ffi.gc(C.knot_dname_from_str(nil, name, 0), C.free)) end,
+ dname2str = function(dname) return ffi.string(ffi.gc(C.knot_dname_to_str(nil, dname, 0), C.free)) end,
+ context = function () return kres_context end,
+}
+
-- Return DS/DNSKEY parser that adds keys to TA store
local function ta_parser(store)
local parser = require('zonefile').parser(function (p)
end
-- TA store management
-local trust_anchors = {
- current_file = "",
- is_auto = false,
- store = ffi.cast('struct kr_context *', __engine).trust_anchors,
+kres.trust_anchors = {
-- Load keys from a file
config = function (path)
- ta_parser(trust_anchors.store):parse_file(path)
- trust_anchors.current_file = path
+ ta_parser(kres_context.trust_anchors):parse_file(path)
+ kres.trust_anchors.current_file = path
+ end,
+ -- Add DS/DNSKEY record(s)
+ add = function (ds) ta_parser(kres_context.trust_anchors):read(ds..'\n') end,
+ -- Negative TA management
+ set_insecure = function (list)
+ C.kr_ta_clear(kres_context.negative_anchors)
+ for i = 1, #list do
+ local dname = kres.str2dname(list[i])
+ C.kr_ta_add(kres_context.negative_anchors, dname, kres.type.DS, 0, nil, 0)
+ end
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
- class = ffi.new('struct rr_class'),
- type = ffi.new('struct rr_type'),
- section = ffi.new('struct pkt_section'),
- rcode = ffi.new('struct pkt_rcode'),
- NOOP = 0, CONSUME = 1, PRODUCE = 2, DONE = 4, FAIL = 8,
- -- Metatypes
- 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
__newindex = function (t,k,v)
if k == 'file' then t.config(v)
elseif k == 'auto' then t.set_auto(v)
+ elseif k == 'negative' then t.set_insecure(v)
else rawset(t, k, v) end
end,
})
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 || !rdata) {
+ if (!trust_anchors || !name) {
return kr_error(EINVAL);
}
is_new_key = true;
}
/* Merge-in new key data */
- if (!ta_rr || knot_rrset_add_rdata(ta_rr, rdata, rdlen, ttl, NULL) != 0) {
+ if (!ta_rr || (rdlen > 0 && knot_rrset_add_rdata(ta_rr, rdata, rdlen, ttl, NULL) != 0)) {
knot_rrset_free(&ta_rr, NULL);
return kr_error(ENOMEM);
}
static int del_record(const char *k, void *v, void *ext)
{
knot_rrset_t *ta_rr = v;
- knot_rrset_free(&ta_rr, NULL);
+ if (ta_rr) {
+ knot_rrset_free(&ta_rr, NULL);
+ }
return 0;
}
{
struct kr_rplan *rplan = &request->rplan;
map_t *trust_anchors = &request->ctx->trust_anchors;
+ map_t *negative_anchors = &request->ctx->negative_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(trust_anchors, qry->zone_cut.name)) {
+ if (!kr_ta_covers(negative_anchors, qry->zone_cut.name) &&
+ 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));
}
qry->flags &= ~QUERY_AWAIT_CUT;
}
+ /* Disable DNSSEC if it enters NTA. */
+ if (kr_ta_get(negative_anchors, qry->zone_cut.name)){
+ DEBUG_MSG(">< negative TA, going insecure\n");
+ qry->flags &= ~QUERY_DNSSEC_WANT;
+ }
/* Enable DNSSEC if enters a new island of trust. */
bool want_secured = (qry->flags & QUERY_DNSSEC_WANT);
if (!want_secured && kr_ta_get(trust_anchors, qry->zone_cut.name)) {
DEBUG_MSG(">< TA: using '%s'\n", qname_str);
}
}
- /* @todo Disable DNSSEC if it encounters NTA */
if (want_secured && !qry->zone_cut.trust_anchor) {
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);
uint32_t options;
knot_rrset_t *opt_rr;
map_t trust_anchors;
+ map_t negative_anchors;
struct kr_zonecut root_hints;
struct kr_cache cache;
kr_nsrep_lru_t *cache_rtt;
-- Convert list of string names to domain names
function policy.to_domains(names)
for i, v in ipairs(names) do
- names[i] = v:gsub('([^.]*%.)', function (x)
- return string.format('%s%s', string.char(x:len()-1), x:sub(1,-2))
- end)
+ names[i] = kres.str2dname(v)
end
end
# Wait for a response for a reasonable time
answer = None
if not self.data[0].is_raw_data_entry:
+ ctx.child_sock.settimeout(1)
answer, addr = ctx.child_sock.recvfrom(4096)
# Remember last answer for checking later
self.raw_answer = answer