From: Petr Špaček Date: Mon, 30 Dec 2019 11:16:52 +0000 (+0100) Subject: prefill: allow to use system-wide CA store X-Git-Tag: v5.0.0~13^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cebb8b18346b365efb2b73e66a95db1d0e4e7a7e;p=thirdparty%2Fknot-resolver.git prefill: allow to use system-wide CA store It also improves error reporting from store:add() call. Sometimes the error message from lua-ossl is incomplete. This is fixed by https://github.com/wahern/luaossl/pull/176. --- diff --git a/daemon/lua/kluautil.lua b/daemon/lua/kluautil.lua index 773738cf7..d0cca438f 100644 --- a/daemon/lua/kluautil.lua +++ b/daemon/lua/kluautil.lua @@ -10,24 +10,31 @@ function kluautil.kr_table_len(t) end -- Fetch over HTTPS -function kluautil.kr_https_fetch(url, ca_file, file) +function kluautil.kr_https_fetch(url, out_file, ca_file) local http_ok, http_request = pcall(require, 'http.request') + local httptls_ok, http_tls = pcall(require, 'http.tls') local openssl_ok, openssl_ctx = pcall(require, 'openssl.ssl.context') - if not http_ok or not openssl_ok then + if not http_ok or not httptls_ok or not openssl_ok then return nil, 'error: lua-http and luaossl libraries are missing (but required)' end assert(string.match(url, '^https://')) - assert(ca_file) local req = http_request.new_from_uri(url) - req.ctx = openssl_ctx.new() - local store = req.ctx:getStore() - store:add(ca_file) + req.tls = true + if ca_file then + req.ctx = openssl_ctx.new() + local store = req.ctx:getStore() + local load_ok, errmsg = pcall(store.add, store, ca_file) + if not load_ok then + return nil, errmsg + end + else -- use defaults + req.ctx = http_tls.new_client_context() + end req.ctx:setVerify(openssl_ctx.VERIFY_PEER) - req.tls = true local headers, stream, errmsg = req:go() if not headers then @@ -39,12 +46,12 @@ function kluautil.kr_https_fetch(url, ca_file, file) end local err - err, errmsg = stream:save_body_to_file(file) + err, errmsg = stream:save_body_to_file(out_file) if err == nil then return nil, errmsg end - file:seek ("set", 0) + out_file:seek("set", 0) return true end diff --git a/daemon/lua/trust_anchors.lua.in b/daemon/lua/trust_anchors.lua.in index 1d4cc1639..7652cd75c 100644 --- a/daemon/lua/trust_anchors.lua.in +++ b/daemon/lua/trust_anchors.lua.in @@ -124,7 +124,7 @@ local function bootstrap(url, ca) -- @todo ICANN certificate is verified against current CA -- this is not ideal, as it should rather verify .xml signature which -- is signed by ICANN long-lived cert, but luasec has no PKCS7 - local rcode, errmsg = kluautil.kr_https_fetch(url, ca, file) + local rcode, errmsg = kluautil.kr_https_fetch(url, file, ca) if rcode == nil then file:close() return false, string.format('[ ta ] fetch of "%s" failed: %s', url, errmsg) diff --git a/modules/prefill/README.rst b/modules/prefill/README.rst index 111378949..1211d141e 100644 --- a/modules/prefill/README.rst +++ b/modules/prefill/README.rst @@ -15,8 +15,8 @@ Example configuration is: prefill.config({ ['.'] = { url = 'https://www.internic.net/domain/root.zone', - ca_file = '/etc/pki/tls/certs/ca-bundle.crt', interval = 86400 -- seconds + ca_file = '/etc/pki/tls/certs/ca-bundle.crt', -- optional } }) @@ -27,7 +27,7 @@ Root zone to import must be signed using DNSSEC and the resolver must have valid .. csv-table:: :header: "Parameter", "Description" - "ca_file", "path to CA certificate bundle used to authenticate the HTTPS connection" + "ca_file", "path to CA certificate bundle used to authenticate the HTTPS connection (optional, system-wide store will be used if not specified)" "interval", "number of seconds between zone data refresh attempts" "url", "URL of a file in :rfc:`1035` zone file format" diff --git a/modules/prefill/prefill.lua b/modules/prefill/prefill.lua index 773162bd7..32079f519 100644 --- a/modules/prefill/prefill.lua +++ b/modules/prefill/prefill.lua @@ -77,7 +77,7 @@ local function download(url, fname) end log("[prefill] downloading root zone to file %s ...", fname) - rcode, errmsg = kluautil.kr_https_fetch(url, rz_ca_file, file) + rcode, errmsg = kluautil.kr_https_fetch(url, file, rz_ca_file) if rcode == nil then error(string.format("[prefill] fetch of `%s` failed: %s", url, errmsg)) end @@ -156,10 +156,6 @@ local function config_zone(zone_cfg) rz_cur_interval = zone_cfg.interval end - if not zone_cfg.ca_file then - error('[prefill] option ca_file must point ' - .. 'to a file with CA certificate(s) in PEM format') - end rz_ca_file = zone_cfg.ca_file if not zone_cfg.url or not string.match(zone_cfg.url, '^https://') then