return len
end
+-- Fetch over HTTPS
+function kr_https_fetch (url, ca_file, file)
+ local http_ok, http_request = pcall(require, 'http.request')
+ local openssl_ok, openssl_ctx = pcall(require, 'openssl.ssl.context')
+
+ if not http_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.ctx:setVerify(openssl_ctx.VERIFY_PEER)
+ req.tls = true
+
+ local headers, stream = req:go()
+ assert(headers, 'HTTP client library error')
+ if headers:get(':status') ~= "200" then
+ return nil, headers:get(':status')
+ end
+
+ local err, errmsg = stream:save_body_to_file(file)
+ if err == nil then
+ return err, errmsg
+ end
+
+ file:seek ("set", 0)
+
+ return true
+end
+
end
-- TODO: Move bootstrap to a separate module or even its own binary
--- Fetch over HTTPS with peert cert checked
-local function https_fetch(url, ca)
- local http_ok, http_request = pcall(require, 'http.request')
- local openssl_ok, openssl_ctx = pcall(require, 'openssl.ssl.context')
-
- if not http_ok or not openssl_ok then
- return nil, 'error: lua-http and luaossl libraries are missing (but required) for root TA bootstrap'
- end
-
- local request = http_request.new_from_uri(url)
- request.ctx = openssl_ctx.new('TLSv1_2')
- local store = request.ctx:getStore()
- store:add(ca)
-
- request.ctx:setVerify(openssl_ctx.VERIFY_PEER)
- request.tls = true
-
- local headers, stream = request:go()
- if headers == nil then return nil, 'HTTP client library error' end
- if headers:get(':status') ~= "200" then return nil, headers:get(':status') end
-
- local resp, err = stream:get_body_as_string()
-
- return resp, err or ""
-end
-
-- remove UTC timezone specification if present or throw error
local function time2utc(orig_timespec)
local patterns = {'[+-]00:00$', 'Z$'}
-- Fetch root anchors in XML over HTTPS, returning a zone-file-style string
-- or false in case of error, and a message.
local function bootstrap(url, ca)
+ local kluautil = pcall(require, 'kluautil')
+ local file = io.tmpfile()
-- RFC 7958, sec. 2, but we don't do precise XML parsing.
-- @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 xml, err = https_fetch(url, ca)
- if not xml then
- return false, string.format('[ ta ] fetch of "%s" failed: %s', url, err)
+ local rcode, errmsg = kluautil.kr_https_fetch(url, ca, file)
+ if rcode == nil then
+ file:close()
+ return false, string.format('[ ta ] fetch of "%s" failed: %s', url, errmsg)
end
+ local xml = file:read("*a")
+ file:close()
+
-- we support only minimal subset of https://tools.ietf.org/html/rfc7958
assert_str_match(xml, '<?xml version="1%.0" encoding="UTF%-8"%?>', 1)
assert_str_match(xml, '<TrustAnchor ', 1)
-- Support for client sockets from inside policy actions
local socket_client = function ()
- return error("missing lua-cqueues library, can't create socket client")
+ return error("missing lua-cqueues library, can't create socket client")
end
local has_socket, socket = pcall(require, 'cqueues.socket')
if has_socket then
local prefill = {
}
-
--- Fetch over HTTPS
-local function https_fetch(url, ca_file, fname)
- local http_ok, http_request = pcall(require, 'http.request')
- local openssl_ok, openssl_ctx = pcall(require, 'openssl.ssl.context')
-
- if not http_ok or not openssl_ok then
- return nil, 'lua-http and luaossl needed for root TA bootstrap'
- 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.ctx:setVerify(openssl_ctx.VERIFY_PEER)
- req.tls = true
-
- local headers, stream = req:go()
- assert(headers, 'HTTP client library error')
- if headers:get(':status') ~= "200" then
- return nil, headers:get(':status')
- end
-
- local file, errmsg = io.open(fname, 'w')
- if not file then
- error(string.format("[prefill] unable to open file %s (%s)",
- fname, errmsg))
- end
-
- local err
- err, errmsg = stream:save_body_to_file(file)
- if err == nil then
- return err, errmsg
- end
-
- file:close()
-
- return file
-end
-
local function display_delay(time)
local days = math.floor(time / 86400)
local hours = math.floor((time % 86400) / 3600)
end
local function download(url, fname)
+ local kluautil = pcall(require, 'kluautil')
+ local file, rcode, errmsg
+ file, errmsg = io.open(fname, 'w')
+ if not file then
+ error(string.format("[prefill] unable to open file %s (%s)",
+ fname, errmsg))
+ end
+
log("[prefill] downloading root zone to file %s ...", fname)
- local rzone, err = https_fetch(url, rz_ca_file, fname)
- if rzone == nil then
- error(string.format("[prefill] fetch of `%s` failed: %s", url, err))
+ rcode, errmsg = kluautil.kr_https_fetch(url, rz_ca_file, file)
+ if rcode == nil then
+ error(string.format("[prefill] fetch of `%s` failed: %s", url, errmsg))
end
+
+ file:close()
end
local function import(fname)