Commit 9829167a authored by Marek Vavruša's avatar Marek Vavruša

daemon: negative trust anchors

config:
trust_anchors.negative = { ‘bad.cz’, ‘here.com’ }

all names below these NTA will not be validated
(unless there is an island of trust below these anchors)
parent de71731d
......@@ -245,6 +245,7 @@ static int init_resolver(struct engine *engine)
{
/* 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 */
......@@ -359,18 +360,19 @@ void engine_deinit(struct engine *engine)
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)
......
......@@ -166,13 +166,21 @@ struct kr_context
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);
......@@ -181,9 +189,9 @@ uint16_t knot_pkt_qclass(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 */
......@@ -259,6 +267,24 @@ ffi.metatype( kr_request_t, {
},
})
-- 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)
......@@ -268,38 +294,26 @@ local function ta_parser(store)
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
......@@ -70,6 +70,7 @@ setmetatable(trust_anchors, {
__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,
})
......
......@@ -30,7 +30,7 @@ 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)
{
if (!trust_anchors || !name || !rdata) {
if (!trust_anchors || !name) {
return kr_error(EINVAL);
}
......@@ -52,7 +52,7 @@ int kr_ta_add(map_t *trust_anchors, const knot_dname_t *name, uint16_t type,
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);
}
......@@ -82,7 +82,9 @@ int kr_ta_covers(map_t *trust_anchors, const knot_dname_t *name)
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;
}
......
......@@ -357,12 +357,14 @@ static int zone_cut_check(struct kr_request *request, struct kr_query *qry, knot
{
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));
......@@ -377,6 +379,11 @@ static int zone_cut_check(struct kr_request *request, struct kr_query *qry, knot
}
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)) {
......@@ -388,7 +395,6 @@ static int zone_cut_check(struct kr_request *request, struct kr_query *qry, knot
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);
......
......@@ -86,6 +86,7 @@ struct kr_context
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;
......
......@@ -148,9 +148,7 @@ end
-- 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
......
......@@ -330,6 +330,7 @@ class Step:
# 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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment