end
local resp = {}
local r, c = https.request{
- url = url,
- cafile = ca,
- verify = {'peer', 'fail_if_no_peer_cert' },
- protocol = 'tlsv1_2',
- sink = ltn12.sink.table(resp),
+ url = url,
+ cafile = ca,
+ verify = {'peer', 'fail_if_no_peer_cert' },
+ protocol = 'tlsv1_2',
+ sink = ltn12.sink.table(resp),
}
if r == nil then return r, c end
return resp[1]
local err = ffi.C.kr_strptime_diff(
format, time_now, time2utc(valid_from), time_diff)
if (err ~= nil) then
- error(string.format('failed to process "validFrom" constraint: %s',
- ffi.string(err)))
+ error(string.format('failed to process "validFrom" constraint: %s',
+ ffi.string(err)))
end
local from_ok = time_diff[0] > 0
format, time_now, time2utc(valid_until), time_diff)
if (err ~= nil) then
error(string.format('failed to process "validUntil" constraint: %s',
- ffi.string(err)))
+ ffi.string(err)))
end
until_ok = time_diff[0] < 0
end
local valid_attrs = {id = true, validFrom = true, validUntil = true}
for key, _ in pairs(fields) do
assert(valid_attrs[key],
- string.format('unsupported KeyDigest attribute "%s" found in "%s"',
- key, attrs))
+ string.format('unsupported KeyDigest attribute "%s" found in "%s"',
+ key, attrs))
end
_, n = string.gsub(inside, "<([%w]+).->([^<]+)</[%w]+>", function (k, v) fields[k] = v end)
assert(n >= 1,
string.format('error parsing KeyDigest XML elements from "%s"',
- inside))
+ inside))
local mandatory_elements = {'KeyTag', 'Algorithm', 'DigestType', 'Digest'}
for _, key in ipairs(mandatory_elements) do
assert(fields[key],
string.format('mandatory element %s is missing in "%s"',
- key, inside))
+ key, inside))
end
assert(n == 4, string.format('found %d elements but expected 4 in %s', n, inside))
table.insert(output, fields) -- append to list of parsed keydigests
rrset = rrset .. '\n' .. rr
else
log('[ ta ] skipping trust anchor "%s" ' ..
- 'because it is outside of validity range', rr)
+ 'because it is outside of validity range', rr)
end
end
return rrset
count = count + 1
end
assert(count == expected,
- string.format('expected %d occurences of "%s" but got %d in "%s"',
- expected, pattern, count, str))
+ string.format('expected %d occurences of "%s" but got %d in "%s"',
+ expected, pattern, count, str))
end
-- Fetch root anchors in XML over HTTPS, returning a zone-file-style string
return false, string.format('[ ta ] no valid trust anchors found at "%s"', url)
end
local msg = '[ ta ] Root trust anchors bootstrapped over https with pinned certificate.\n'
- .. ' You SHOULD verify them manually against original source:\n'
- .. ' https://www.iana.org/dnssec/files\n'
- .. '[ ta ] Current root trust anchors are:'
- .. rrset
+ .. ' You SHOULD verify them manually against original source:\n'
+ .. ' https://www.iana.org/dnssec/files\n'
+ .. '[ ta ] Current root trust anchors are:'
+ .. rrset
return rrset, msg
end
for _, ta in ipairs(tas) do
if ta.owner ~= owner then
return nil, string.format("do not mix %s and %s TAs in single file/string",
- kres.dname2str(ta.owner), kres.dname2str(owner))
+ kres.dname2str(ta.owner), kres.dname2str(owner))
end
end
tas.owner = owner
end
if count == 0 then
warn('[ ta ] ERROR: no anchors are trusted for ' ..
- kres.dname2str(keyset.owner) .. ' !')
+ kres.dname2str(keyset.owner) .. ' !')
end
return count > 0 and not has_error
end
local refresh_plan = function(keyset, delay, is_initial)
- event.after(0, function()
- if ta_update ~= nil then
- ta_update.refresh_plan(keyset, delay, is_initial)
- end
- end)
+ event.after(0, function()
+ if ta_update ~= nil then
+ ta_update.refresh_plan(keyset, delay, is_initial)
+ end
+ end)
end
local function add_file(path, unmanaged)
-- Replace the TA store used for validation
if keyset_publish(keyset) and verbose() then
log('[ ta ] installed trust anchors for domain ' .. owner_str .. ' are:\n'
- .. trust_anchors.summary(owner))
+ .. trust_anchors.summary(owner))
end
-- TODO: if failed and for root, try to rebootstrap?
add_file = add_file,
config = add_file,
- keyset_write = keyset_write,
- keyset_publish = keyset_publish,
+ keyset_write = keyset_write,
+ keyset_publish = keyset_publish,
-- Add DS/DNSKEY record(s) (unmanaged)
add = function (keystr)
local function ta_find(keyset, rr)
local rr_tag = C.kr_dnssec_key_tag(rr.type, rr.rdata, #rr.rdata)
assert(rr_tag >= 0 and rr_tag <= 65535, string.format('invalid RR: %s: %s',
- kres.rr2str(rr), ffi.string(C.knot_strerror(rr_tag))))
+ kres.rr2str(rr), ffi.string(C.knot_strerror(rr_tag))))
for i, ta in ipairs(keyset) do
-- Match key owner and content
local ta_tag = C.kr_dnssec_key_tag(ta.type, ta.rdata, #ta.rdata)
assert(ta_tag >= 0 and ta_tag <= 65535, string.format('invalid RR: %s: %s',
- kres.rr2str(ta), ffi.string(C.knot_strerror(ta_tag))))
+ kres.rr2str(ta), ffi.string(C.knot_strerror(ta_tag))))
if ta.owner == rr.owner then
if ta.type == rr.type then
if rr.type == kres.type.DNSKEY then
-- Evaluate TA status of a RR according to RFC5011. The time is in seconds.
local function ta_present(keyset, rr, hold_down_time, force_valid)
if rr.type == kres.type.DNSKEY and not C.kr_dnssec_key_ksk(rr.rdata) then
- return false -- Ignore
+ return false -- Ignore
end
-- Attempt to extract key_tag
local key_tag = C.kr_dnssec_key_tag(rr.type, rr.rdata, #rr.rdata)
if key_tag < 0 or key_tag > 65535 then
- warn(string.format('[ ta_update ] ignoring invalid or unsupported RR: %s: %s',
- kres.rr2str(rr), ffi.string(C.knot_strerror(key_tag))))
- return false
+ warn(string.format('[ ta_update ] ignoring invalid or unsupported RR: %s: %s',
+ kres.rr2str(rr), ffi.string(C.knot_strerror(key_tag))))
+ return false
end
-- Find the key in current key set and check its status
local now = os.time()
local key_revoked = (rr.type == kres.type.DNSKEY) and C.kr_dnssec_key_revoked(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
- ta.timer = nil
- 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
- ta.timer = now + hold_down_time
- end
- end
- -- Remove hold-down timer expires (RemTime)
- if ta.state == key_state.Revoked and os.difftime(ta.timer, now) <= 0 then
- ta.state = key_state.Removed
- ta.timer = nil
- end
- -- Add hold-down timer expires (AddTime)
- if ta.state == key_state.AddPend and os.difftime(ta.timer, now) <= 0 then
- ta.state = key_state.Valid
- ta.timer = nil
- end
- if rr.state ~= key_state.Valid or verbose() then
- log('[ ta_update ] key: ' .. key_tag .. ' state: '..ta.state)
- end
- return true
+ -- Key reappears (KeyPres)
+ if ta.state == key_state.Missing then
+ ta.state = key_state.Valid
+ ta.timer = nil
+ 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
+ ta.timer = now + hold_down_time
+ end
+ end
+ -- Remove hold-down timer expires (RemTime)
+ if ta.state == key_state.Revoked and os.difftime(ta.timer, now) <= 0 then
+ ta.state = key_state.Removed
+ ta.timer = nil
+ end
+ -- Add hold-down timer expires (AddTime)
+ if ta.state == key_state.AddPend and os.difftime(ta.timer, now) <= 0 then
+ ta.state = key_state.Valid
+ ta.timer = nil
+ end
+ if rr.state ~= key_state.Valid or verbose() then
+ log('[ ta_update ] key: ' .. key_tag .. ' state: '..ta.state)
+ end
+ return true
elseif not key_revoked then -- First time seen (NewKey)
- rr.key_tag = key_tag
- if force_valid then
+ rr.key_tag = key_tag
+ if force_valid then
rr.state = key_state.Valid
else
rr.state = key_state.AddPend
local keep_ta = true
local key_tag = C.kr_dnssec_key_tag(ta.type, ta.rdata, #ta.rdata)
assert(key_tag >= 0 and key_tag <= 65535, string.format('invalid RR: %s: %s',
- kres.rr2str(ta), ffi.string(C.knot_strerror(key_tag))))
+ kres.rr2str(ta), ffi.string(C.knot_strerror(key_tag))))
if ta.state == key_state.Valid then
ta.state = key_state.Missing
ta.timer = os.time() + hold_down_time
return false
elseif verbose() then
log('[ ta_update ] refreshed trust anchors for domain ' .. kres.dname2str(keyset.owner) .. ' are:\n'
- .. trust_anchors.summary(keyset.owner))
+ .. trust_anchors.summary(keyset.owner))
end
return true
retry = false
else
warn('[ ta_update ] active refresh failed for ' .. kres.dname2str(keyset.owner)
- .. ' with rcode: ' .. pkt:rcode())
+ .. ' with rcode: ' .. pkt:rcode())
end
-- Calculate refresh/retry timer (RFC 5011, 2.3)
local min_ttl = retry and day or 15 * day
local delay_new = active_refresh(keyset, kres.pkt_t(pkt), is_initial)
delay_new = keyset.refresh_time or ta_update.refresh_time or delay_new
log('[ ta_update ] next refresh for ' .. owner_str .. ' in '
- .. delay_new/hour .. ' hours')
+ .. delay_new/hour .. ' hours')
refresh_plan(keyset, delay_new)
end)
end)
end
ta_update = {
- -- - [optional] overrides for global defaults of
- -- hold_down_time, refresh_time, keep_removed
- hold_down_time = 30 * day,
- refresh_time = nil,
- keep_removed = 0,
- refresh_plan = refresh_plan,
+ -- [optional] overrides for global defaults of
+ -- hold_down_time, refresh_time, keep_removed
+ hold_down_time = 30 * day,
+ refresh_time = nil,
+ keep_removed = 0,
+ refresh_plan = refresh_plan,
}
return ta_update