83 lines
2.3 KiB
Lua
83 lines
2.3 KiB
Lua
-- 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
|