1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
|
-- SPDX-License-Identifier: GPL-3.0-or-later
-- Module interface
local ffi = require('ffi')
local mod = {}
local event_id = nil
-- Resolve callback
-- Check time validity of RRSIGs in priming query
-- luacheck: no unused args
local function check_time_callback(pkt, req)
if pkt == nil or pkt:rcode() ~= kres.rcode.NOERROR then
log_warn(ffi.C.LOG_GRP_DETECTTIMESKEW, "cannot resolve '.' NS")
return nil
end
local seen_rrsigs = 0
local valid_rrsigs = 0
local section = pkt:rrsets(kres.section.ANSWER)
local now = os.time()
local time_diff = 0
local inception = 0
local expiration = 0
for i = 1, #section do
local rr = section[i]
assert(rr.type)
if rr.type == kres.type.RRSIG then
for k = 0, rr.rrs.count - 1 do
seen_rrsigs = seen_rrsigs + 1
local rdata = rr:rdata_pt(k)
inception = ffi.C.kr_rrsig_sig_inception(rdata)
expiration = ffi.C.kr_rrsig_sig_expiration(rdata)
if now > expiration then
-- positive value = in the future
time_diff = now - expiration
elseif now < inception then
-- negative value = in the past
time_diff = now - inception
else
valid_rrsigs = valid_rrsigs + 1
end
end
end
end
if seen_rrsigs == 0 then
log_info(ffi.C.LOG_GRP_DETECTTIMESKEW, "No RRSIGs received! "..
"You really should configure DNSSEC trust anchor for the root.")
elseif valid_rrsigs == 0 then
log_warn(ffi.C.LOG_GRP_DETECTTIMESKEW, "Local system time %q seems to be at "..
"least %u seconds in the %s. DNSSEC signatures for '.' NS "..
"are not valid %s. Please check your system clock!",
os.date("%c", now),
math.abs(time_diff),
time_diff > 0 and "future" or "past",
time_diff > 0 and "anymore" or "yet")
else
log_info(ffi.C.LOG_GRP_DETECTTIMESKEW, "Local system time %q is within "..
"RRSIG validity interval <%q,%q>.", os.date("%c", now),
os.date("%c", inception), os.date("%c", expiration))
end
end
-- Do uncached priming query and check time validity of RRSIGs.
local function check_time()
resolve(".", kres.type.NS, kres.class.IN, {"DNSSEC_WANT", "DNSSEC_CD", "NO_CACHE"},
check_time_callback)
end
function mod.init()
if event_id then
error("Module is already loaded.")
else
event_id = event.after(0 , check_time)
end
end
function mod.deinit()
if event_id then
event.cancel(event_id)
event_id = nil
end
end
return mod
|