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

daemon/trust_anchors: key state tracking (wip)

DS keys are injected into current set (unmanaged)
DNSKEY keys are in the managed set and their RFC5011 state is tracked

todo:
- implement timers and this AddTime/RemTime
- active refresh
- move to a separate module
parent 972ec3c3
......@@ -197,18 +197,24 @@ 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,
uint16_t rclass, uint16_t rtype, const uint8_t *rdata, uint16_t rdlen);
const char *kr_inaddr(const struct sockaddr *addr);
int kr_inaddr_len(const struct sockaddr *addr);
/* 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);
/* DNSSEC */
bool kr_dnssec_key_ksk(const uint8_t *dnskey_rdata);
bool kr_dnssec_key_revoked(const uint8_t *dnskey_rdata);
int kr_dnssec_key_tag(uint16_t rrtype, const uint8_t *rdata, size_t rdlen);
int kr_dnssec_key_match(const uint8_t *key_a_rdata, size_t key_a_rdlen,
const uint8_t *key_b_rdata, size_t key_b_rdlen);
]]
-- Metatype for sockaddr
......@@ -285,47 +291,118 @@ local kres = {
context = function () return kres_context end,
}
-- RFC5011 state table
local key_state = {
Start = 'Start', AddPend = 'AddPend', Valid = 'Valid',
Missing = 'Missing', Revoked = 'Revoked', Removed = 'Removed'
}
-- Find key in current keyset
local function ta_find(keyset, rr)
for i = 1, #keyset do
local ta = keyset[i]
-- Match key owner and content
if ta.owner == rr.owner and
C.kr_dnssec_key_match(ta.rdata, #ta.rdata, rr.rdata, #rr.rdata) then
return ta
end
end
return nil
end
-- Evaluate TA status according to RFC5011
local function evaluate_ta(keyset, ta)
-- @todo: check if KSK
-- @todo: get TA id
-- @todo: check key flags for revoked
-- @todo: build a state table
table.insert(keyset, ta)
local function ta_present(keyset, rr, force)
if not C.kr_dnssec_key_ksk(rr.rdata) then
return false -- Ignore
end
-- Find the key in current key set and check its status
local key_revoked = C.kr_dnssec_key_revoked(rr.rdata)
local key_tag = C.kr_dnssec_key_tag(rr.type, rr.rdata, #rr.rdata)
local ta = ta_find(keyset, rr)
if ta then
-- Key reappears (KeyPres)
if ta.state == key_state.Missing then ta.state = key_state.Valid end
-- Key is revoked (RevBit)
if ta.state == key_state.Valid or ta.state == key_state.Missing then
if key_revoked then
ta.state = key_state.Revoked
-- @todo: ta.time = ...
end
end
-- @todo RemTime
-- @todo AddTime
-- Preserve key (KeyPres)
print('[trust_anchors] key: '..key_tag..' state: '..ta.state)
return true
elseif not key_revoked then -- First time seen (NewKey)
rr.state = force and key_state.Valid or key_state.AddPend
-- rr.time = ...
print('[trust_anchors] key: '..key_tag..' state: '..rr.state)
table.insert(keyset, rr)
return true
end
return false
end
-- TA is missing in the new key set
local function ta_missing(keyset, ta)
-- Key is removed (KeyRem)
if ta.state == key_state.Valid then
ta.state = key_state.Missing
-- ta.time = ...
elseif ta.state == key_state.AddPend then
-- @todo: remove from the set (Start)
end
local key_tag = C.kr_dnssec_key_tag(ta.type, ta.rdata, #ta.rdata)
print('[trust_anchors] key: '..key_tag..' state: '..ta.state)
end
-- TA store management
kres.trust_anchors = {
keyset = {},
insecure = {},
-- Update existing keyset
update = function (new_keys)
-- Evaluate new TAs
update = function (new_keys, initial)
-- Flag keys missing in new set (KeyRem)
local keyset = kres.trust_anchors.keyset
for i = 1, #keyset do
local ta = keyset[i]
if not ta_find(new_keys, ta) then
ta_missing(keyset, ta)
end
end
-- Evaluate new TAs
if not new_keys then return false end
for i = 1, #new_keys do
local rr = new_keys[i]
if rr.type == kres.type.DS or rr.type == kres.type.DNSKEY then
evaluate_ta(keyset, rr)
if rr.type == kres.type.DNSKEY then
ta_present(keyset, rr, initial)
end
end
-- Publish active TAs
local store = kres_context.trust_anchors
C.kr_ta_clear(store)
for id, key in pairs(keyset) do
C.kr_ta_add(store, key.owner, key.type, key.ttl, key.rdata, #key.rdata)
for i = 1, #keyset do
local ta = keyset[i]
-- Key MAY be used as a TA only in these two states (RFC5011, 4.2)
if ta.state == key_state.Valid or ta.state == key_state.Missing then
C.kr_ta_add(store, ta.owner, ta.type, ta.ttl, ta.rdata, #ta.rdata)
end
end
return true
end,
-- Load keys from a file
-- Load keys from a file (managed)
config = function (path)
local new_keys = require('zonefile').parse_file(path)
kres.trust_anchors.update(new_keys)
return kres.trust_anchors.update(new_keys, true)
end,
-- Add DS/DNSKEY record(s)
add = function (rr)
local new_keys = {}
-- Add DS/DNSKEY record(s) (unmanaged)
add = function (keystr)
local store = kres_context.trust_anchors
require('zonefile').parser(function (p)
table.insert(new_keys, p:current_rr())
end):read(rr..'\n')
kres.trust_anchors.update(new_keys)
local rr = p:current_rr()
C.kr_ta_add(store, rr.owner, rr.type, rr.ttl, rr.rdata, #rr.rdata)
end):read(keystr..'\n')
end,
-- Negative TA management
set_insecure = function (list)
......@@ -334,6 +411,7 @@ kres.trust_anchors = {
local dname = kres.str2dname(list[i])
C.kr_ta_add(kres_context.negative_anchors, dname, kres.type.DS, 0, nil, 0)
end
kres.trust_anchors.insecure = list
end,
}
......
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