Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • knot/knot-resolver
  • dkg/resolver
  • sbalazik/resolver
  • anb/knot-resolver
  • tkrizek/knot-resolver
  • jono/knot-resolver
  • analogic/knot-resolver
  • flokli/knot-resolver
  • hectorm/knot-resolver
  • aisha/knot-resolver
10 results
Show changes
Showing
with 1735 additions and 517 deletions
<?xml version="1.0" encoding="UTF-8"?>
<TrustAnchor id="1DECEB91-0591-44A1-95CF-1788337514B8" source="https://localhost/ok2.xml">
<Zone>.</Zone>
<KeyDigest id="K1" validFrom="2010-07-15T00:00:00+00:00">
<KeyTag>1</KeyTag>
<Algorithm>8</Algorithm>
<DigestType>2</DigestType>
<Digest>1111111111111111111111111111111111111111111111111111111111111111</Digest>
</KeyDigest>
<KeyDigest id="K2" validFrom="2011-02-02T00:00:00+00:00">
<KeyTag>2</KeyTag>
<Algorithm>8</Algorithm>
<DigestType>2</DigestType>
<Digest>2222222222222222222222222222222222222222222222222222222222222222</Digest>
</KeyDigest>
</TrustAnchor>
# SPDX-License-Identifier: GPL-3.0-or-later
for F in *.xml; do sed -i "s/TrustAnchor id=\"[^\"]*\"/TrustAnchor id=\"$(uuidgen | tr '[[:lower:]]' '[[:upper:]]')\"/" $F; done
for F in *.xml; do sed -i "s#source=\"[^\"]*\"#source=\"https://localhost/$F\"#" $F; done
. IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D
-- SPDX-License-Identifier: GPL-3.0-or-later
trust_anchors.remove('.')
local ffi = require('ffi')
-- count warning messages
warn_msg = {}
overriding_msg="warning: overriding previously set trust anchors for ."
warn_msg[overriding_msg] = 0
function log_warn(grp, fmt, ...) --luacheck: no unused args
msg = string.format(fmt, ...)
if warn_msg[msg] ~= nil then
warn_msg[msg] = warn_msg[msg] + 1
end
end
-- Test that adding a revoked DNSKEY is refused.
local function test_revoked_key()
local ta_c = kres.context().trust_anchors
same(ffi.C.kr_ta_del(ta_c, '\0'), 0, 'remove root TAs if any')
-- same() doesn't consider nil and typed NULL pointer equal, so we work around:
same(ffi.C.kr_ta_get(ta_c, '\0') == nil, true, 'no TA for root is used')
local key_crypto = 'AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjFFV'
.. 'QUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoXbfDaUeVPQuYEhg37'
.. 'NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaDX6RS6CXpoY68LsvPVjR0ZSwzz1apAz'
.. 'vN9dlzEheX7ICJBBtuA6G3LQpzW5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7O'
.. 'yQdXfZ57relSQageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulqQxA+Uk1ihz0='
boom(trust_anchors.add, { '. 3600 DNSKEY 385 3 8 ' .. key_crypto }, 'refuse revoked key')
same(ffi.C.kr_ta_get(ta_c, '\0') == nil, true, 'no TA for root is used')
-- Test that we don't have another problem in the key
trust_anchors.add('. 3600 DNSKEY 257 3 8 ' .. key_crypto)
local root_ta = ffi.C.kr_ta_get(ta_c, '\0')
same(root_ta == nil, false, 'we got non-NULL TA RRset')
same(root_ta.rrs.count, 1, 'the root TA set contains one RR')
end
local function test_remove()
-- uses root key from the previous test
assert(trust_anchors.keysets['\0'], 'root key must be there from previous test')
local ta_c = kres.context().trust_anchors
local root_ta = ffi.C.kr_ta_get(ta_c, '\0')
assert(root_ta ~= nil, 'we got non-NULL TA RRset')
assert(root_ta.rrs.count, 1, 'we have a root TA set to be deleted')
trust_anchors.remove('.')
same(trust_anchors.keysets['\0'], nil, 'Lua interface does not have the removed key')
root_ta = ffi.C.kr_ta_get(ta_c, '\0')
same(root_ta == nil, true, 'C interface does not have the removed key')
end
local function test_add_file()
boom(trust_anchors.add_file, {'nonwriteable/root.keys', false},
"Managed trust anchor in non-writeable directory")
boom(trust_anchors.add_file, {'nonexistent.keys', true},
"Nonexistent unmanaged trust anchor file")
is(warn_msg[overriding_msg], 0, "No override warning messages at start of test")
trust_anchors.add_file('root.keys', true)
trust_anchors.add_file('root.keys', true)
is(warn_msg[overriding_msg], 1, "Warning message when override trust anchors")
is(trust_anchors.keysets['\0'][1].key_tag, 20326,
"Loaded KeyTag from root.keys")
end
local function test_nta()
assert(trust_anchors.keysets['\0'], 'root key must be there from previous tests')
trust_anchors.set_insecure({'example.com'})
is(trust_anchors.insecure[1], 'example.com', 'Add example.com to NTA list')
boom(trust_anchors.set_insecure, {{'.'}}, 'Got error when adding TA . to NTA list')
is(#trust_anchors.insecure, 1, 'Check one item in NTA list')
is(trust_anchors.insecure[1], 'example.com', 'Check previous NTA list')
end
return {
test_revoked_key,
test_remove,
test_add_file,
test_nta,
}
<?xml version="1.0" encoding="UTF-8"?>
<TrustAnchor id="8449BFB8-FD6C-4082-B0FE-1A3E3399203B" source="https://localhost/unsupp_nonroot.xml">
<Zone>test.</Zone>
<KeyDigest id="2" validFrom="2000-02-02T00:00:00+00:00">
<KeyTag>2</KeyTag>
<Algorithm>8</Algorithm>
<DigestType>2</DigestType>
<Digest>1111111111111111111111111111111111111111111111111111111111111111</Digest>
</KeyDigest>
</TrustAnchor>
<?xml version="1.1" encoding="UTF-8"?>
<TrustAnchor id="3612AE1C-E8F3-4FD8-B8CD-96C7FDACC7A5" source="https://localhost/unsupp_xml_v11.xml">
<Zone>.</Zone>
<KeyDigest id="2" validFrom="2000-02-02T00:00:00+00:00">
<KeyTag>2</KeyTag>
<Algorithm>8</Algorithm>
<DigestType>2</DigestType>
<Digest>1111111111111111111111111111111111111111111111111111111111111111</Digest>
</KeyDigest>
</TrustAnchor>
-- SPDX-License-Identifier: GPL-3.0-or-later
-- This is a module that does the heavy lifting to provide an HTTP/2 enabled
-- server that supports TLS by default and provides endpoint for other modules
-- in order to enable them to export restful APIs and websocket streams.
-- One example is statistics module that can stream live metrics on the website,
-- or publish metrics on request for Prometheus scraper.
local http_server = require('http.server')
local http_headers = require('http.headers')
local http_websocket = require('http.websocket')
local http_util = require "http.util"
local x509, pkey = require('openssl.x509'), require('openssl.pkey')
-- Module declaration
local M = {}
-- Export HTTP service endpoints
M.endpoints = {
['/'] = {'text/html', 'test'},
}
-- Serve known requests, for methods other than GET
-- the endpoint must be a closure and not a preloaded string
local function serve(endpoints, h, stream)
local hsend = http_headers.new()
local path = h:get(':path')
local entry = endpoints[path]
if not entry then -- Accept top-level path match
entry = endpoints[path:match '^/[^/?]*']
end
-- Unpack MIME and data
local data, mime, ttl, err
if entry then
mime = entry[1]
data = entry[2]
ttl = entry[4]
end
-- Get string data out of service endpoint
if type(data) == 'function' then
local set_mime, set_ttl
data, err, set_mime, set_ttl = data(h, stream)
-- Override default endpoint mime/TTL
if set_mime then mime = set_mime end
if set_ttl then ttl = set_ttl end
-- Handler doesn't provide any data
if data == false then return end
if type(data) == 'number' then return tostring(data), err end
-- Methods other than GET require handler to be closure
elseif h:get(':method') ~= 'GET' then
return '501', ''
end
if not mime or type(data) ~= 'string' then
return '404', ''
else
-- Serve content type appropriately
hsend:append(':status', '200')
hsend:append('content-type', mime)
hsend:append('content-length', tostring(#data))
if ttl then
hsend:append('cache-control', string.format('max-age=%d', ttl))
end
assert(stream:write_headers(hsend, false))
assert(stream:write_chunk(data, true))
end
end
-- Web server service closure
local function route(endpoints)
return function (_, stream)
-- HTTP/2: We're only permitted to send in open/half-closed (remote)
local connection = stream.connection
if connection.version >= 2 then
if stream.state ~= 'open' and stream.state ~= 'half closed (remote)' then
return
end
end
-- Start reading headers
local h = assert(stream:get_headers())
local m = h:get(':method')
local path = h:get(':path')
-- Upgrade connection to WebSocket
local ws = http_websocket.new_from_stream(stream, h)
if ws then
assert(ws:accept { protocols = {'json'} })
-- Continue streaming results to client
local ep = endpoints[path]
local cb = ep[3]
if cb then
cb(h, ws)
end
ws:close()
return
else
local ok, err, reason = http_util.yieldable_pcall(serve, endpoints, h, stream)
if not ok or err then
print(string.format('%s err %s %s: %s (%s)', os.date(), m, path, err or '500', reason))
-- Method is not supported
local hsend = http_headers.new()
hsend:append(':status', err or '500')
if reason then
assert(stream:write_headers(hsend, false))
assert(stream:write_chunk(reason, true))
else
assert(stream:write_headers(hsend, true))
end
else
print(string.format('%s ok %s %s', os.date(), m, path))
end
end
end
end
-- @function Prefer HTTP/2 or HTTP/1.1
local function alpnselect(_, protos)
for _, proto in ipairs(protos) do
if proto == 'h2' or proto == 'http/1.1' then
return proto
end
end
return nil
end
-- @function Create TLS context
local function tlscontext(crt, key)
local http_tls = require('http.tls')
local ctx = http_tls.new_server_context()
if ctx.setAlpnSelect then
ctx:setAlpnSelect(alpnselect)
end
assert(ctx:setPrivateKey(key))
assert(ctx:setCertificate(crt))
return ctx
end
-- @function Listen on given HTTP(s) host
function M.add_interface(conf)
local crt, key
if conf.tls ~= false then
assert(conf.cert, 'cert missing')
assert(conf.key, 'private key missing')
-- Check if a cert file was specified
-- Read x509 certificate
local f = io.open(conf.cert, 'r')
if f then
crt = assert(x509.new(f:read('*all')))
f:close()
-- Continue reading key file
if crt then
f = io.open(conf.key, 'r')
key = assert(pkey.new(f:read('*all')))
f:close()
end
end
-- Check loaded certificate
assert(crt and key,
string.format('failed to load certificate "%s"', conf.cert))
end
-- Compose server handler
local routes = route(conf.endpoints or M.endpoints)
-- Check if UNIX socket path is used
local addr_str
if not conf.path then
conf.host = conf.host or 'localhost'
conf.port = conf.port or 8453
addr_str = string.format('%s@%d', conf.host, conf.port)
else
if conf.host or conf.port then
error('either "path", or "host" and "port" must be provided')
end
addr_str = conf.path
end
-- Create TLS context and start listening
local s, err = http_server.listen {
-- cq = worker.bg_worker.cq,
host = conf.host,
port = conf.port,
path = conf.path,
v6only = conf.v6only,
unlink = conf.unlink,
reuseaddr = conf.reuseaddr,
reuseport = conf.reuseport,
client_timeout = conf.client_timeout or 5,
ctx = crt and tlscontext(crt, key),
tls = conf.tls,
onstream = routes,
-- Log errors, but do not throw
onerror = function(myserver, context, op, err, errno) -- luacheck: ignore 212
local msg = '[http] ' .. op .. ' on ' .. tostring(context) .. ' failed'
if err then
msg = msg .. ': ' .. tostring(err)
end
print(msg)
end,
}
-- Manually call :listen() so that we are bound before calling :localname()
if s then
err = select(2, s:listen())
end
assert(not err, string.format('failed to listen on %s: %s', addr_str, err))
return s
end
-- init
local files = {
'ok0_badtimes.xml',
'ok1.xml',
'ok1_expired1.xml',
'ok1_notyet1.xml',
'ok2.xml',
'err_attr_validfrom_missing.xml',
'err_attr_validfrom_invalid.xml',
'err_attr_extra_attr.xml',
'err_elem_missing.xml',
'err_elem_extra.xml',
'err_multi_ta.xml',
'unsupp_nonroot.xml',
'unsupp_xml_v11.xml'
}
-- Export static pages specified at command line
for _, name in ipairs(files) do
local fd = io.open(name)
assert(fd, string.format('unable to open file "%s"', name))
M.endpoints['/' .. name] = { 'text/xml', fd:read('*a') }
fd:close()
end
local server = M.add_interface({
host = 'localhost',
port = 8080,
tls = true,
cert = 'x509/server.pem',
key = 'x509/server-key.pem'
})
server:loop()
Public Key Info:
Public Key Algorithm: RSA
Key Security Level: High (3072 bits)
modulus:
00:9e:ee:f2:d8:41:ae:2c:93:8a:01:1f:88:5b:d6:85
29:2f:91:9d:37:fc:35:88:7f:53:71:87:fc:17:71:e7
15:57:06:2d:54:fb:19:98:80:82:ec:1a:99:2d:57:cb
5f:dd:28:26:d8:95:fb:65:b2:be:e1:11:86:69:14:7e
32:5c:c0:02:0b:5d:11:78:69:50:20:25:3e:15:fb:8a
46:d1:83:f9:3b:84:46:9c:69:21:44:d5:09:1d:7a:04
cc:f3:6a:ea:4c:1b:da:7c:40:dd:1c:6f:f6:85:b4:ea
75:98:34:79:11:fb:cf:d3:18:70:64:25:33:8a:31:b6
93:67:d4:32:67:61:1c:d0:7b:85:61:54:c6:fb:51:b6
87:1d:d4:b8:58:40:a9:c5:32:ce:e0:b9:90:37:0d:58
e4:33:70:c5:c5:91:f2:18:f5:e0:08:ad:17:8b:cf:72
f1:26:6c:9c:88:d2:9e:06:4c:02:5d:4e:7c:93:af:8d
72:93:75:1d:60:0c:f7:34:09:a8:e6:f2:80:4a:14:81
24:40:4b:45:19:85:2e:ad:8e:97:4c:ff:ec:d0:9f:e6
a0:b7:c0:a9:a0:ad:d2:02:2d:13:55:f3:df:f8:f9:f1
f3:3e:35:e9:08:2b:db:11:93:57:13:55:c6:ba:c6:d7
ff:7d:e1:fa:8c:47:5d:da:bf:31:56:80:aa:34:97:43
bb:9e:ff:d3:e6:13:a9:c2:99:49:c2:1e:da:f2:c7:d2
d6:f7:5f:70:36:91:2f:ea:36:e9:88:44:08:a3:1a:0a
c0:e0:4b:48:82:9a:c9:72:29:9c:09:24:63:b3:c2:9f
2a:f6:e8:3a:c4:46:03:8d:70:ae:14:bb:3a:d6:c6:62
93:24:7f:bc:0a:c8:a2:20:53:3c:9f:5c:15:45:05:3d
1b:38:17:d4:fe:6b:6a:c2:16:f3:14:73:c2:c3:c7:36
e3:f1:f8:e5:28:84:4e:37:d4:68:e8:82:70:20:53:fc
01:
public exponent:
01:00:01:
private exponent:
44:4a:68:0e:84:2a:52:fd:12:4f:69:3d:2e:38:fe:fe
b3:71:de:1c:30:42:d0:63:e5:76:e2:f7:6f:1b:82:2f
a9:34:fe:45:85:9f:79:e7:be:59:b5:14:1c:67:9c:fb
94:0b:ac:a5:63:cc:a1:e6:2c:1e:89:69:37:bd:96:7c
0d:5e:73:82:6e:7b:13:42:2d:2b:a2:d5:0a:9d:0a:cd
63:39:51:de:40:f8:16:3d:16:0e:7d:7b:6d:2f:00:e1
0f:b6:e0:f5:d3:02:0e:61:d0:a0:67:7b:85:f8:36:c6
50:a0:3b:65:7e:cd:cd:e6:b2:64:55:97:cf:c9:8c:a9
c9:f3:63:b5:08:05:59:8f:b9:c0:18:ad:67:4f:b5:1e
59:b3:0d:82:de:46:14:75:c0:6e:cf:4d:28:5a:93:d7
7a:42:fa:b7:e9:fe:1c:bb:89:88:30:d7:ed:3b:36:28
68:5a:42:e8:87:97:5f:1d:49:e6:cd:d2:b9:a2:b5:23
d8:df:5d:cf:c6:98:9a:e0:99:7a:33:52:75:22:ce:ca
85:eb:d9:92:6a:d5:49:c0:cb:df:b1:a2:98:b5:6c:37
85:c2:e1:6a:13:48:22:72:02:a7:e2:e0:f3:f3:0c:ed
42:f6:83:ba:71:f0:ef:8f:ce:6a:59:30:be:9d:5f:23
06:c3:0e:49:5c:8f:6a:8d:c2:c3:c5:07:45:55:78:f0
bd:29:01:cb:ac:ec:b1:40:7d:78:cc:4d:cb:f9:60:a4
a2:f5:aa:21:0b:3e:da:1b:d9:f0:99:19:44:57:21:09
ba:0f:f9:05:8e:ee:59:4f:59:08:b1:67:51:02:80:4e
34:c7:5d:25:79:8c:84:f7:be:15:02:28:9c:f9:b9:ca
fc:6a:ed:d0:5f:df:be:ce:c4:96:63:23:2e:db:e1:85
1e:45:16:2c:24:b0:5e:7a:62:bf:36:00:8b:c8:90:61
c2:68:4b:95:b0:ce:41:77:a3:a0:5d:09:72:01:a0:01
prime1:
00:ca:fe:eb:14:07:13:a9:ef:b6:d5:6c:52:02:39:b6
6e:55:b6:dd:70:fc:c6:04:7c:07:81:9b:98:a4:da:db
f1:66:b8:33:91:fd:00:15:6e:72:0d:ab:0b:6f:be:34
c8:d9:82:58:7e:09:7f:e4:6f:c0:70:99:53:68:c7:53
d2:8f:97:22:f5:e8:e4:be:5f:e1:29:0f:27:a7:66:74
b2:cc:96:a1:d2:ca:2a:40:4b:70:cc:7a:16:4f:c9:4f
49:16:11:d5:f8:da:f6:92:06:1c:45:c3:f8:17:c4:1d
65:9a:2a:3f:33:be:33:f8:84:03:26:49:d8:52:25:f8
19:ce:31:00:c0:b6:55:71:74:03:53:e8:0c:ef:85:64
54:d4:8f:68:08:87:da:cb:9b:55:6a:2e:2b:c2:95:36
c4:dd:09:62:c0:6f:9e:e9:cc:ea:96:4e:e6:2d:6c:72
c1:54:92:11:29:91:af:4d:cd:08:7c:f8:6f:28:9d:ca
c5:
prime2:
00:c8:6e:b7:af:c3:c6:b9:df:49:ad:ea:b8:62:b7:43
e6:04:d9:5a:df:c3:f9:a3:0d:b5:e6:2d:9d:f7:c4:ff
38:c0:cb:03:9c:c1:d1:6f:b4:fb:cf:81:c4:9e:94:2a
d5:e2:a1:77:a8:7b:8f:d1:34:7a:c2:f5:38:ec:0d:35
a0:5e:3c:af:e9:2d:f4:f9:32:ae:da:c1:1e:62:74:e5
ab:3d:3b:3d:d0:88:fc:53:59:0f:21:30:ed:24:ac:a7
5a:a5:b7:f4:cc:5a:96:ad:79:a3:41:74:56:ad:39:14
0a:27:a4:10:18:19:33:f2:1a:aa:b4:36:9d:fa:3f:fc
71:42:1e:a0:96:8e:0f:de:46:87:ba:6c:38:17:d0:7e
c8:4a:cb:4a:29:1c:44:b9:88:29:c7:6f:b7:4f:3f:00
cd:0c:6b:0f:77:a1:5a:f1:80:21:91:b3:68:ca:0d:b5
c9:6d:04:f4:98:94:9f:09:f9:a8:58:ea:34:9c:d8:f0
0d:
coefficient:
00:bf:7b:93:68:64:ea:5e:b5:f4:b6:8c:91:49:aa:2b
b0:a5:74:40:73:45:23:b6:74:ae:7a:55:ae:9d:8a:bb
3b:6d:3a:7d:c4:7a:c0:82:7f:0e:ef:57:1c:86:e2:56
30:5b:0c:d9:d1:52:cf:df:10:4f:c8:4a:75:b1:b8:b1
59:9b:01:02:a2:4d:29:aa:63:e5:11:0a:17:ae:1e:79
ed:5d:10:fc:f0:8a:8d:f6:77:f8:78:17:1e:07:ee:d1
de:59:ed:d7:fb:94:bf:c9:7c:f7:f3:a0:8d:66:d3:94
9a:7f:d1:7a:89:87:71:17:96:90:4e:be:7b:54:5e:51
03:c6:35:af:5f:ea:5d:cc:31:ab:56:4b:75:6a:14:b6
c0:1a:bf:fb:e9:54:ba:ad:c3:52:e9:85:03:db:b2:e8
0b:18:60:37:19:f9:07:87:e7:b2:d8:3a:0d:c9:d5:f0
f0:73:60:fc:9e:e0:9e:b1:ea:52:71:c7:fd:27:0a:22
42:
exp1:
04:a5:69:04:00:55:76:e2:41:b1:08:d5:a7:af:62:79
8c:04:af:74:d2:94:45:ae:01:0d:fa:5d:b8:08:3a:58
80:1d:5f:30:cc:35:a0:47:f2:dc:55:39:e1:c8:dc:b4
6c:26:0b:98:76:e7:32:77:4c:54:47:6e:1d:4b:d2:a3
53:1e:06:72:d2:6d:c9:dd:af:ed:9c:a7:2f:b1:ac:a2
1b:04:a7:97:87:81:08:0f:b1:f9:3c:22:1e:99:60:f3
2f:4a:21:37:9c:eb:5f:d4:3b:f9:6c:ce:d4:dc:6c:3f
d3:13:7c:76:d6:b7:a1:cc:83:b5:f0:a2:be:de:97:9b
1f:99:07:87:61:a4:fa:ff:c8:c3:b6:df:f4:eb:7c:ac
64:61:13:e4:7e:17:87:e9:7a:3e:ff:e7:88:80:99:cc
4f:b2:d3:4b:cc:42:3a:df:b1:ce:d6:e7:75:ca:b1:a5
b3:25:d4:b6:ba:da:e4:50:f9:0c:c3:32:e8:1f:14:71
exp2:
00:9d:9d:bb:a3:63:b0:96:20:8a:5f:52:f2:b6:e6:69
65:ac:30:84:ee:ec:bd:16:45:44:e3:02:c2:73:c2:9d
f5:b2:5e:b3:b3:85:13:3e:e6:33:13:66:78:09:40:79
43:03:5a:78:af:ac:a3:57:20:0e:dd:db:5b:6c:fd:a2
4b:3f:70:37:e1:85:fb:5c:30:48:22:cc:b5:29:35:c6
1a:58:27:8b:1f:bf:69:b5:dd:96:31:42:b9:6a:1a:bf
ec:5f:df:7e:89:69:3f:8e:a1:d6:09:36:04:a7:69:f8
61:57:f5:03:96:ff:d2:c2:b3:c7:c3:ba:23:97:54:d4
1e:f8:a0:ff:26:06:07:62:83:52:5e:fe:95:49:dc:f2
a6:6d:72:da:19:e4:1a:03:50:99:92:35:3f:10:f9:79
96:c6:0a:36:fa:9b:8f:d9:d4:2a:11:da:e5:2f:e7:82
2a:29:2a:39:72:f7:84:ed:a2:3f:89:d4:7b:95:50:5f
cd:
Public Key PIN:
pin-sha256:u7TPTyh/innOijbJFG3Y4pWghApErLvhCQUZNXBlVFU=
Public Key ID:
sha256:bbb4cf4f287f8a79ce8a36c9146dd8e295a0840a44acbbe10905193570655455
sha1:92b7d0c4d107e2a73f827b87866aef9ff4379cc8
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIEGTCCAoGgAwIBAgIUXWsAXOOaZw+h37N9gUc/XLw3KHwwDQYJKoZIhvcNAQEL
BQAwIzEhMB8GA1UEAxMYS25vdCBSZXNvbHZlciB0ZXN0aW5nIENBMCAXDTIwMDEw
NzA5MzQwOVoYDzk5OTkxMjMxMjM1OTU5WjAjMSEwHwYDVQQDExhLbm90IFJlc29s
dmVyIHRlc3RpbmcgQ0EwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCe
7vLYQa4sk4oBH4hb1oUpL5GdN/w1iH9TcYf8F3HnFVcGLVT7GZiAguwamS1Xy1/d
KCbYlftlsr7hEYZpFH4yXMACC10ReGlQICU+FfuKRtGD+TuERpxpIUTVCR16BMzz
aupMG9p8QN0cb/aFtOp1mDR5EfvP0xhwZCUzijG2k2fUMmdhHNB7hWFUxvtRtocd
1LhYQKnFMs7guZA3DVjkM3DFxZHyGPXgCK0Xi89y8SZsnIjSngZMAl1OfJOvjXKT
dR1gDPc0Cajm8oBKFIEkQEtFGYUurY6XTP/s0J/moLfAqaCt0gItE1Xz3/j58fM+
NekIK9sRk1cTVca6xtf/feH6jEdd2r8xVoCqNJdDu57/0+YTqcKZScIe2vLH0tb3
X3A2kS/qNumIRAijGgrA4EtIgprJcimcCSRjs8KfKvboOsRGA41wrhS7OtbGYpMk
f7wKyKIgUzyfXBVFBT0bOBfU/mtqwhbzFHPCw8c24/H45SiETjfUaOiCcCBT/AEC
AwEAAaNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwQAMB0GA1Ud
DgQWBBSSt9DE0Qfipz+Ce4eGau+f9DecyDANBgkqhkiG9w0BAQsFAAOCAYEAA45p
Ak7ebzk2ss5FHhJDvHrhoTZG2/esNEQhtv70nuRPnm3j8UGDxYyydwjf4+W9DT1v
53QNfvbOIPcOUsGArAItmI7K6ltkBSS6ymO8T1ZY4vYw+77jJZ1EeYS6kjdan7dK
f2Zz23CVbuq8BOc/Ob6ChepEq/MIb3g/Y6FowuWqeC85s61GW9MKr5GeG0oSyYAO
UZdFnwa8QLCZ2IzQcwnolkAw2A/5TDxovINy9Lb5U3kyphC9vhjPqr8PJ5q/KVuK
vcHvEsrsSNPvW/WcxkziV1oJTnjvr/69mwAme8+xjjF90GhrNaQF1YOoijuZuQaS
Q+0qmwZbsMtcqAABKQALHfLGsGAA5MKip49khIQWuIAS8P2vb+hzbqQRLjq1uW7B
dEGvBHF0QebDZOXJeXEYK/b7btWa9kNedD2FvBx5c9QNiWwh7jZENkICKnhI7E+n
d5/gsKVa1glKwbMagZBSJgFtjZe/eo/LcoK82m4VuOUCJSe0Kd0McrSZ7XZX
-----END CERTIFICATE-----
cn = Knot Resolver testing CA
ca
cert_signing_key
expiration_days = -1
# SPDX-License-Identifier: GPL-3.0-or-later
# CA
certtool --generate-privkey > ca-key.pem
certtool --generate-self-signed --load-privkey ca-key.pem --template ca.tmpl --outfile ca.pem
# server cert signed by CA above
certtool --generate-privkey > server-key.pem
certtool --generate-certificate --load-privkey server-key.pem --load-ca-certificate ca.pem --load-ca-privkey ca-key.pem --template server.tmpl --outfile server.pem
# wrong CA - unrelated to others
certtool --generate-privkey > wrongca-key.pem
certtool --generate-self-signed --load-privkey wrongca-key.pem --template wrongca.tmpl --outfile wrongca.pem
Public Key Info:
Public Key Algorithm: RSA
Key Security Level: High (3072 bits)
modulus:
00:c3:46:2a:27:c8:39:e4:de:fa:24:45:6c:00:26:80
61:ca:dd:a1:24:34:1b:93:1c:13:c8:5a:cf:af:6a:ef
34:b9:89:83:02:76:51:ad:67:bf:ed:39:ee:0a:15:57
91:6e:fa:68:60:78:22:62:fa:0a:55:12:03:b3:0c:8e
b4:ca:cd:2b:9d:a2:43:b5:5a:48:a0:3d:4a:1f:77:a4
a6:d4:87:eb:79:99:df:d4:b4:a3:cf:91:03:a0:c5:82
39:f5:75:20:4b:90:b9:3b:72:65:a7:75:39:a6:62:58
65:b0:9c:40:5c:c7:c4:4c:d3:1e:cc:74:18:74:15:23
44:fd:51:59:b2:b7:70:95:6b:a0:be:d5:e4:72:59:2b
df:a5:a2:06:c8:e1:bd:17:80:25:b3:cf:8e:e8:ad:b2
f7:04:b1:9e:b8:72:0b:c5:dc:cd:a5:b6:f5:c9:1a:eb
63:78:75:9c:5d:c5:03:a9:4b:7b:d6:cd:5c:5f:8d:2e
d0:b4:0d:96:55:c7:1e:c7:ac:13:46:b8:ec:9c:36:b9
6a:1d:f0:7c:41:00:c6:bd:1f:81:7e:1d:48:1d:59:bc
e2:61:a6:d1:2d:52:10:3f:63:93:a9:14:d8:03:27:21
b0:d4:07:24:78:04:2b:86:c8:2b:0f:eb:a7:b3:3e:e2
81:62:2a:4a:07:d9:fd:f6:77:7f:50:88:ee:bb:7d:31
53:a8:97:bf:30:07:37:41:e9:52:16:15:74:a8:64:ed
93:46:38:56:b4:89:d9:0c:62:4b:64:a9:64:ff:fc:9a
d6:19:a7:84:98:28:04:b4:95:76:ac:4a:42:6a:fb:67
5b:b4:37:e6:e6:e2:52:d3:e9:38:8b:76:10:55:f1:e6
8e:d8:73:eb:17:d1:54:41:d4:5b:76:2d:70:7f:f5:0d
7d:d2:d6:f8:05:33:18:ab:dd:10:8a:5b:21:ee:3d:78
9d:cd:c9:c0:c6:98:4e:a6:0a:41:f0:97:91:83:c2:c8
4b:
public exponent:
01:00:01:
private exponent:
23:88:1f:e1:8f:40:61:91:e5:28:36:6d:99:75:68:04
e3:5a:02:99:48:d5:ff:a5:ab:3f:d8:ae:53:b7:fc:80
b6:85:fc:0d:b5:a3:d5:0e:bc:d0:98:aa:e4:b0:cf:77
4a:1f:4c:60:c9:5b:50:71:38:f2:13:ce:12:85:65:6e
26:3c:c1:03:f4:e3:a7:1b:1f:7d:f0:c9:0d:02:c3:36
0c:14:13:57:d4:14:f3:6a:4f:28:54:b5:b9:4a:57:10
de:c6:0a:33:55:c9:2e:b4:f9:24:48:63:4e:10:35:0f
83:dc:5a:a5:c7:3f:c3:ce:e2:9a:c7:41:2f:d6:2c:cd
bf:de:4e:99:03:61:fb:fe:52:88:86:f9:03:89:90:3f
28:af:5b:d6:af:a4:ad:a3:06:b9:3a:3a:41:c2:61:7f
2b:1e:7a:c8:0b:10:73:57:63:20:15:33:91:fd:50:f9
8f:90:ae:fc:2c:fe:26:8e:f2:a0:ba:4b:65:a3:95:f1
d8:30:d4:fa:8d:12:1b:8b:58:1d:66:10:cd:41:22:1e
b0:7a:f4:e6:0f:76:3f:0a:0f:9c:44:e2:19:cf:c6:4d
de:3a:f4:96:70:c7:e6:2d:98:27:0e:ac:3b:32:41:37
4e:05:b2:22:af:7b:38:92:16:40:fb:5c:96:b0:86:da
96:c6:77:c3:66:78:07:80:5c:2a:46:dc:9a:bf:fc:0c
2f:ee:f7:a1:b3:77:b4:50:75:a2:b7:36:9d:28:73:ee
7a:ab:a6:0c:f6:92:18:8f:ff:16:28:90:7f:16:4f:f1
6d:77:99:dd:a6:46:95:6a:6c:7a:15:48:53:b3:17:0b
30:aa:0d:c8:68:33:2b:4d:40:da:74:cf:9b:73:1b:cd
5d:f0:a9:d1:00:6f:db:de:55:ec:d4:24:96:bb:da:50
b4:d5:e1:87:35:5c:d4:50:c3:03:d5:d5:ee:03:65:4b
68:9c:07:5c:59:28:78:bd:d1:4b:cb:8d:85:8b:5b:c1
prime1:
00:cc:8d:55:38:2d:57:cb:d2:4b:57:5b:3f:a2:6d:91
4b:9c:54:29:98:9d:1d:bb:36:a6:e8:ba:e9:50:db:83
cf:c1:45:24:16:70:e5:51:40:eb:23:6b:fa:be:d5:d5
00:27:ed:99:c7:7c:6b:16:79:77:0b:f3:ff:58:35:4e
6c:58:68:51:d3:20:3c:57:b7:7d:bc:6b:fd:a7:c3:38
9a:f2:7a:8a:b6:71:a1:6e:5e:64:7e:a8:c5:7c:58:70
fb:8d:63:b3:27:cc:1a:97:1e:04:da:d5:34:b5:d1:aa
f1:96:39:89:5e:cb:e7:75:ab:7e:ac:8c:fe:62:3e:cc
93:66:88:d7:cd:c6:2d:db:9e:2f:f7:d1:6e:96:99:d2
32:61:f4:9b:f5:48:fe:e7:90:b7:a2:ab:89:90:c1:ae
67:5d:18:7a:c1:a3:84:97:09:47:13:df:d2:85:46:46
c7:77:3b:9f:b5:74:5c:f6:ec:a0:a7:66:0e:d1:d7:a4
e1:
prime2:
00:f4:63:70:fa:dd:7e:3d:1a:2b:5b:47:79:56:e9:c7
7f:6b:50:41:60:45:af:59:e0:77:b2:76:4e:40:ff:f8
55:9d:77:3b:c1:00:6a:c6:84:6a:09:a5:45:e6:fc:e6
e6:92:72:32:fc:93:8f:93:d9:db:fc:8c:43:d2:7a:ea
4b:0e:ee:1d:dc:e0:27:08:83:16:aa:de:37:59:39:c0
21:26:b5:34:49:f2:1f:7b:0c:d4:3c:0f:e5:06:ac:23
7b:85:b1:39:35:44:ec:70:48:c5:10:86:02:ea:36:4a
f1:20:a2:b2:c9:8d:d3:f6:5a:86:72:4b:8b:28:07:04
39:8d:01:fa:75:3a:35:40:c2:21:c3:ac:50:da:2f:3e
30:ee:ab:f7:7d:81:a3:77:5e:b7:03:be:52:fb:a4:70
92:5d:fd:09:ae:52:33:b8:7b:9c:e2:2a:77:f7:23:4d
c5:4b:82:f1:fb:0a:09:62:e6:5f:32:1e:7b:c7:c6:66
ab:
coefficient:
00:c3:2d:d8:18:32:30:a1:fa:2c:23:d0:ea:b4:60:0f
29:67:50:4a:5a:61:aa:6d:15:0e:4b:66:43:35:ee:39
4c:e7:8d:31:73:b0:bb:04:4d:e5:bc:28:ea:dc:77:81
35:bb:f7:80:13:96:04:4c:45:9c:43:6f:64:e0:a3:51
4b:7e:6c:b6:7d:c2:a6:e0:94:e6:6c:34:4e:62:71:ea
c0:c0:ab:30:30:c1:3a:39:0e:cd:f0:cc:0e:31:b5:fc
61:64:1e:29:1c:cd:fc:69:c0:02:7c:2a:fe:86:d5:e2
7b:8d:fe:ae:3d:3a:6c:1b:b3:b4:0d:b1:1b:d1:4d:37
36:ea:d7:15:f3:6e:02:b1:86:98:51:02:fc:62:df:30
f2:de:9f:03:6d:27:45:d7:c7:a8:04:ba:76:18:01:09
34:d2:57:f9:10:50:ea:ae:0e:ae:c6:a4:cd:f9:fd:b1
25:b2:45:20:bc:50:2d:9b:80:c1:39:08:97:d2:75:9b
f7:
exp1:
00:8a:b8:6a:8b:cf:8c:54:08:c8:d9:74:63:82:67:25
fb:0e:08:b1:b0:f3:14:7f:ab:3f:a4:63:65:e9:55:05
5e:36:a7:0a:23:41:ea:f2:a0:c1:16:63:9b:48:22:41
f2:7a:21:93:81:8a:ea:20:f2:bc:fe:59:39:d8:fb:45
b5:0a:7b:ac:ca:2e:79:5d:cf:6d:b1:03:d7:a1:17:2e
e3:3e:00:46:e4:15:c9:b1:cc:c8:00:71:ba:84:6a:82
2c:c6:a5:4f:91:74:c4:af:a9:47:07:95:41:ca:f0:67
2a:b1:83:51:9a:fd:53:7a:24:94:a2:b6:77:a9:ef:06
d4:0b:dc:4f:e6:18:39:6f:50:27:1d:bc:65:70:32:df
2f:15:e9:4a:7f:1d:42:e9:8d:e6:4b:a6:63:83:cd:25
d6:a9:76:f9:81:2a:c0:b7:a1:2e:17:d7:59:b0:d2:89
1b:aa:cb:bf:b2:d2:38:5d:a8:fa:06:ac:9a:ee:4a:7d
61:
exp2:
00:92:66:af:db:d8:ac:33:36:66:1a:bc:6a:78:22:7c
1c:5c:d1:2b:18:dd:25:fa:95:79:9f:33:38:15:c0:41
a8:28:38:b1:57:21:44:d5:bf:a5:36:3a:07:f2:24:36
be:91:a4:4f:de:f7:16:df:df:76:e5:87:b1:69:79:b0
b9:5e:2c:4f:3f:6e:18:74:04:f3:a3:50:93:9f:a3:f4
f0:e7:1b:4e:43:ae:04:25:d6:bd:9d:6d:78:29:d3:1d
3e:76:0c:80:d4:e4:81:2f:92:a8:5b:09:ac:dd:59:c0
f3:4a:35:ad:1d:09:15:9d:53:05:8f:9a:a9:b6:44:dd
c7:0c:2d:cf:38:42:b2:7c:24:cf:cd:44:80:fa:f3:aa
31:ee:08:9e:ae:54:e6:f4:2f:8d:3b:74:dc:89:5b:2d
04:c1:c1:3f:f7:69:cf:0a:09:23:26:69:82:8c:4e:5d
dc:7f:2b:e6:82:18:b5:1e:c6:1a:e9:0f:51:df:8f:7f
19:
Public Key PIN:
pin-sha256:pFSHHHovr50DJ04K3wEJcyxth+nszZdClOet/CRN9cU=
Public Key ID:
sha256:a454871c7a2faf9d03274e0adf0109732c6d87e9eccd974294e7adfc244df5c5
sha1:5137ef343399ccf38d6566803ddce123da640553
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIEfTCCAuWgAwIBAgIUIREQSLx52Sc9PFWI6Nwe3YzRp3MwDQYJKoZIhvcNAQEL
BQAwIzEhMB8GA1UEAxMYS25vdCBSZXNvbHZlciB0ZXN0aW5nIENBMCAXDTIwMDEw
NzA5MzQwOVoYDzk5OTkxMjMxMjM1OTU5WjA8MRIwEAYDVQQDEwlsb2NhbGhvc3Qx
JjAkBgNVBAoTHUZha2UgRE5TIHJvb3Qgb3JnIHRlc3Qgc2VydmVyMIIBojANBgkq
hkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAw0YqJ8g55N76JEVsACaAYcrdoSQ0G5Mc
E8haz69q7zS5iYMCdlGtZ7/tOe4KFVeRbvpoYHgiYvoKVRIDswyOtMrNK52iQ7Va
SKA9Sh93pKbUh+t5md/UtKPPkQOgxYI59XUgS5C5O3Jlp3U5pmJYZbCcQFzHxEzT
Hsx0GHQVI0T9UVmyt3CVa6C+1eRyWSvfpaIGyOG9F4Als8+O6K2y9wSxnrhyC8Xc
zaW29cka62N4dZxdxQOpS3vWzVxfjS7QtA2WVccex6wTRrjsnDa5ah3wfEEAxr0f
gX4dSB1ZvOJhptEtUhA/Y5OpFNgDJyGw1AckeAQrhsgrD+unsz7igWIqSgfZ/fZ3
f1CI7rt9MVOol78wBzdB6VIWFXSoZO2TRjhWtInZDGJLZKlk//ya1hmnhJgoBLSV
dqxKQmr7Z1u0N+bm4lLT6TiLdhBV8eaO2HPrF9FUQdRbdi1wf/UNfdLW+AUzGKvd
EIpbIe49eJ3NycDGmE6mCkHwl5GDwshLAgMBAAGjgY0wgYowDAYDVR0TAQH/BAIw
ADAUBgNVHREEDTALgglsb2NhbGhvc3QwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYD
VR0PAQH/BAUDAwegADAdBgNVHQ4EFgQUUTfvNDOZzPONZWaAPdzhI9pkBVMwHwYD
VR0jBBgwFoAUkrfQxNEH4qc/gnuHhmrvn/Q3nMgwDQYJKoZIhvcNAQELBQADggGB
AFfFgv5J1eb8h33tnvDJ/dLBSA7Soz1NXK8iha18CH1uxW2lo+6iJl7g191WD/3W
m/LdpRU3h5ewbD6An3FSA0I25cYQD1vlH7vdI+xu3hIuFhQVnkxGbwISzlM5vat8
1Ry7z/RpHmQA4V4z4R/PuYcQHQG5tINMPySmbfHBK/Ju+nnmSTJ/p3Z7sVaSCfNN
l37me0w197QU3ovNtA61xHa77VUSJeaAC+zOOXUBZ8Rc5PqhYOf6AJbIBk7tPNei
XH5Yyg3UT0i7V09vUViXK8EXbMX1VWsw59Et4Ro1YouS6TN34i2w8FtKg1+amQLr
UXmQW1lkzx23FdGG4T0fFPtWuJCL6ioc0J6vS7xt0xkbrri9U2thC7gvrKLGCJ6J
hWTGoKwjcBHpoLsT62XogHlctagkyXfjJ1Piik7k2JjqvmyteFlDDkOToLQmaCuI
LIBmOnO9mEig3y7T72cnL8QM+nb+c70cssfCW3LBTHb893J4QAOt5RN6LQUlFc49
sQ==
-----END CERTIFICATE-----
organization = Fake DNS root org test server
cn = localhost
tls_www_server
encryption_key
signing_key
dns_name = localhost
expiration_days = -1
Public Key Info:
Public Key Algorithm: RSA
Key Security Level: High (3072 bits)
modulus:
00:bb:d7:47:1f:55:ed:c0:08:af:1d:32:d2:69:ef:77
d2:f3:f6:86:7e:f3:97:e2:35:72:d4:0a:87:1e:75:76
bf:59:29:be:cd:e6:ad:6d:7d:62:47:19:fb:ed:24:94
7f:2b:d6:0c:68:cf:cd:ee:f3:5e:b2:db:11:44:4b:7f
30:ce:d2:a7:75:a7:37:83:c0:41:d6:a1:87:22:48:fa
ef:d1:15:ed:c9:d2:73:ab:e1:7c:94:4d:b2:96:80:cf
5a:5c:7e:96:f6:02:fa:a4:8b:b1:05:b0:27:f5:d7:38
bd:20:37:ed:12:c0:22:07:a9:a6:5e:47:bd:1d:33:27
a2:cd:4c:0c:70:ba:6e:d9:13:6f:7b:a1:72:e8:f4:be
e3:86:1b:a2:b3:a1:07:cf:93:e8:3a:26:51:3e:af:bc
da:80:b1:92:56:8b:21:e7:1d:d9:f9:0c:a9:68:b7:04
d8:6d:1f:6f:98:90:fb:fb:35:18:71:3c:50:73:b1:45
b1:e7:ee:7b:84:5d:57:95:33:37:b0:0f:eb:85:8f:8d
b0:7f:10:17:80:03:99:1b:62:0c:1d:72:6f:e5:77:38
c8:75:96:61:36:4b:28:ae:17:a4:f9:81:90:4d:4b:85
61:39:be:6c:ca:c0:a9:cd:4e:45:27:47:84:82:3d:7f
c6:a7:00:d7:90:64:7c:a5:e9:f8:f6:92:d2:72:54:a7
95:5f:fc:93:1d:c9:1a:78:6e:3a:1a:1f:8f:a2:41:d2
04:5c:19:32:54:16:f2:97:6f:7c:f9:24:d7:a6:e2:07
cf:9f:9e:64:27:81:5f:5a:77:65:4f:7b:b2:81:78:3f
a3:22:17:d3:ba:06:71:d5:09:6a:c2:85:ba:35:f7:71
01:b4:63:c7:70:62:98:58:80:a2:40:27:c0:e2:d5:fd
60:e0:5a:7a:9c:bf:7b:e6:34:78:f1:16:e8:28:d9:92
dc:e6:2e:b6:d7:1a:83:4b:86:92:d6:81:ce:8e:50:0a
d5:
public exponent:
01:00:01:
private exponent:
7a:27:5e:66:1f:60:54:60:91:58:80:a3:5b:26:d2:9a
89:f2:88:b6:68:3d:1e:6b:39:b8:70:fc:3b:af:91:c0
90:00:58:c7:d7:ba:72:98:76:5f:dc:a2:fb:2d:ad:b0
21:d6:ba:0d:33:0e:2d:d5:70:81:09:7b:6a:19:5a:a6
67:e9:8f:e3:30:12:27:08:d1:07:fd:d5:3e:53:8d:74
85:59:28:60:f6:0e:28:f9:a3:25:62:7d:bf:e8:16:70
21:f4:64:c1:a9:60:4b:bf:58:28:65:cd:26:cf:86:63
5f:5f:5f:39:b1:5e:af:f3:00:71:11:60:07:6c:2b:db
70:7c:83:1e:8f:ee:e4:16:02:8a:b8:8c:5c:b8:44:a6
fb:a0:5f:27:47:92:27:c8:7c:dd:cb:eb:4b:c3:c7:21
a5:4d:54:e8:18:e4:bc:42:aa:6c:8e:72:60:d9:9c:3a
0e:84:c1:f2:ca:5e:43:97:dc:c4:4e:bf:d6:ec:b2:70
08:41:13:01:48:bc:36:a2:eb:5e:67:b6:6a:a4:b6:4a
24:fa:fd:6d:ef:5b:77:bc:0c:7d:95:9a:84:ec:3f:97
aa:7c:07:76:80:f5:3a:49:f4:99:ee:cf:17:12:83:e8
db:ef:22:60:67:62:f8:3e:f9:bc:18:2b:84:fc:a9:82
95:8d:91:27:8e:ba:87:15:65:1e:9f:b3:95:5f:dc:40
2f:15:eb:7e:0a:d7:69:80:7b:8a:e2:29:89:3a:2e:eb
a9:05:c1:1e:5d:23:0d:a0:d7:c4:95:4d:09:85:8c:af
90:23:36:04:66:a9:16:d7:d4:e2:aa:5a:6d:44:5a:6c
c8:e8:a0:08:fa:de:19:20:5f:e3:06:17:e5:65:c6:55
ef:0f:0d:ff:3e:1c:c5:98:ee:34:d3:07:81:11:fe:e9
15:87:e6:9a:76:44:bd:cb:a0:38:63:9a:af:d1:7c:a7
db:26:e2:cd:4a:a2:8a:7f:b8:dc:7a:55:00:4c:20:c1
prime1:
00:c9:f5:14:59:49:3b:95:1f:15:b0:0c:83:cb:f4:6a
48:60:2a:af:8b:d5:83:16:aa:71:5a:af:11:63:c6:c1
0a:91:af:5b:bd:6e:9c:cb:d7:eb:bf:c7:31:9f:22:46
01:cf:3b:3c:cb:ba:7d:ad:e5:bb:d8:7c:d2:5d:52:20
14:ea:70:08:9e:29:98:31:20:78:9e:b6:3e:90:e8:ef
c8:2f:45:d4:35:04:71:a1:84:18:50:a9:a5:12:b7:14
4e:42:3e:93:50:9d:2f:c1:bd:45:f3:4e:86:61:0b:bc
3b:ed:78:c7:2b:ba:4b:a0:ef:e6:0e:a9:9a:f4:aa:73
23:b8:51:c7:d3:dd:fd:a7:1c:c1:69:32:ea:26:32:6d
40:b0:0a:cd:0d:fa:b4:f4:56:ed:e8:d4:96:08:80:fd
43:44:8c:fb:bb:af:81:d7:bb:71:c6:7c:3a:d2:a7:83
e6:28:2d:2f:00:05:82:d7:cc:59:db:d9:e5:4f:a4:67
05:
prime2:
00:ee:1b:2a:48:37:fa:7c:94:35:36:ac:83:5f:2c:98
e3:07:43:d1:2c:80:0e:a2:b8:7a:eb:e2:70:f6:49:77
b3:42:05:fe:06:cf:3f:ca:0f:0d:44:1c:74:0a:77:f7
31:9f:30:fb:d9:44:71:11:e6:4a:ff:ef:ae:77:98:3e
73:a0:77:21:a6:e0:66:9a:cf:5f:eb:3b:39:62:0b:ba
1b:9b:1a:a5:58:4c:7e:17:fc:64:61:93:89:f0:c0:0f
ce:55:18:7e:d4:33:87:32:0e:53:51:5f:03:b4:05:4a
5c:e7:5b:10:e5:b7:88:e5:04:b2:53:45:98:2f:9d:fb
32:f5:2f:d9:59:54:ce:91:83:4c:37:ee:ab:5a:05:40
85:05:03:ae:b4:3d:96:c2:67:6b:28:25:91:87:ed:d1
3a:0f:4b:38:a5:81:b3:5b:6f:3e:33:27:1e:9a:4a:e6
3c:7c:be:9f:45:72:5b:eb:e3:dd:6c:73:ae:0d:07:bd
91:
coefficient:
45:53:87:ab:71:9c:14:af:6c:00:44:bb:de:d5:72:ed
e9:21:f2:19:e5:4d:30:92:8e:9b:b7:f6:db:9e:ea:71
b3:c2:89:01:4a:49:1f:2e:f8:34:57:e0:36:9a:20:84
a8:b0:8a:0b:2a:d6:da:36:22:c2:ac:a2:85:99:f7:5d
3f:2e:71:ab:e5:f7:bd:b2:8c:6f:44:33:aa:2d:cf:38
8c:d6:77:c7:d5:68:88:f1:f9:80:c2:e2:b8:58:26:bd
de:d6:8d:d5:c9:43:dc:e2:af:2e:d3:c5:19:4e:d5:14
33:bc:15:58:6f:05:eb:8d:0d:fa:40:a3:b7:77:24:4b
30:a7:c2:8b:89:08:24:4d:fb:2e:3c:ad:ff:e3:d7:8b
9c:f2:07:0d:79:3c:5e:f5:83:94:32:e2:16:dc:a9:22
b4:f4:09:6a:f6:af:7d:9c:41:dc:be:23:7e:c4:6d:d6
f9:e6:8e:3c:2d:00:fa:ac:d2:c8:6e:c5:6d:52:74:cd
exp1:
4d:20:f9:2d:84:47:6a:13:1e:10:47:27:4a:8c:44:ce
f1:53:3c:09:d6:78:22:fe:e3:1d:b4:00:9b:2f:7b:e8
12:6d:7b:46:e4:68:a3:7d:09:ff:0b:0f:0b:6c:66:7a
28:6f:c2:2f:38:40:e9:59:f4:9c:a0:47:22:f6:cb:63
d1:89:09:f1:85:87:27:33:f4:7d:00:b2:f2:5a:d3:c0
8b:35:4a:ef:18:8c:61:17:f6:c5:4f:94:c8:89:fd:0a
4a:48:65:b0:82:e7:8b:41:42:e6:c2:15:96:18:8a:42
04:d6:7c:92:59:aa:aa:83:14:44:83:47:b7:ab:25:1f
fe:33:d5:72:37:b4:b8:ce:c5:9a:ec:a3:fa:04:86:2f
0f:4c:80:b5:97:0a:e6:ca:10:40:3c:78:34:35:37:04
2a:b9:01:26:d3:c7:6d:e1:9b:79:27:56:bb:be:d8:23
dd:32:2c:62:00:b8:d0:bb:ad:91:c6:2c:ca:76:ca:15
exp2:
30:d8:19:c0:5e:db:5f:9a:f7:9f:93:9c:0f:76:12:96
df:f2:a5:82:3f:72:c1:26:9e:f0:ac:af:07:96:e2:9b
3f:3c:03:74:5a:27:77:c7:c6:ac:e6:39:57:bc:6c:55
1d:96:ea:d3:13:1b:2e:d4:d3:25:d5:81:30:bf:66:70
49:c6:a6:7c:99:23:f3:35:ff:33:3e:1e:f3:61:fc:77
95:45:ce:0d:63:03:aa:df:f7:a7:9c:a0:7b:66:aa:d7
64:d5:75:8f:0a:52:fd:8d:ba:c1:c2:7f:fb:f9:e9:db
4d:0a:7d:58:e2:61:8e:b9:7b:eb:61:27:6a:fd:39:7e
a6:95:7e:3c:b9:0c:f7:04:bc:29:ed:27:f1:7b:8a:54
bf:46:96:1c:1b:56:45:e2:f9:34:6f:20:7f:85:e5:99
c7:71:62:d9:70:d5:de:37:df:c6:96:8b:cc:92:f8:d0
07:b7:02:ed:38:1c:6b:33:7f:44:b4:26:4c:3d:fe:41
Public Key PIN:
pin-sha256:UOonm3sEw21t/nC/tr24q9sX/HPV9mo0/M3Ya8rAwLs=
Public Key ID:
sha256:50ea279b7b04c36d6dfe70bfb6bdb8abdb17fc73d5f66a34fccdd86bcac0c0bb
sha1:b963cfb8eb202ccad2bb988dfa9e00cc52c1a4ba
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIEETCCAnmgAwIBAgIUNVTN+if8IQU0I1n4qyVF9qqhuo0wDQYJKoZIhvcNAQEL
BQAwHzEdMBsGA1UEAxMUQW5vdGhlciB1bnJlbGF0ZWQgQ0EwIBcNMjAwMTA3MDkz
NDA5WhgPOTk5OTEyMzEyMzU5NTlaMB8xHTAbBgNVBAMTFEFub3RoZXIgdW5yZWxh
dGVkIENBMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAu9dHH1XtwAiv
HTLSae930vP2hn7zl+I1ctQKhx51dr9ZKb7N5q1tfWJHGfvtJJR/K9YMaM/N7vNe
stsRREt/MM7Sp3WnN4PAQdahhyJI+u/RFe3J0nOr4XyUTbKWgM9aXH6W9gL6pIux
BbAn9dc4vSA37RLAIgeppl5HvR0zJ6LNTAxwum7ZE297oXLo9L7jhhuis6EHz5Po
OiZRPq+82oCxklaLIecd2fkMqWi3BNhtH2+YkPv7NRhxPFBzsUWx5+57hF1XlTM3
sA/rhY+NsH8QF4ADmRtiDB1yb+V3OMh1lmE2SyiuF6T5gZBNS4VhOb5sysCpzU5F
J0eEgj1/xqcA15BkfKXp+PaS0nJUp5Vf/JMdyRp4bjoaH4+iQdIEXBkyVBbyl298
+STXpuIHz5+eZCeBX1p3ZU97soF4P6MiF9O6BnHVCWrChbo193EBtGPHcGKYWICi
QCfA4tX9YOBaepy/e+Y0ePEW6CjZktzmLrbXGoNLhpLWgc6OUArVAgMBAAGjQzBB
MA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcEADAdBgNVHQ4EFgQUuWPP
uOsgLMrSu5iN+p4AzFLBpLowDQYJKoZIhvcNAQELBQADggGBAEobHXRbd6wfUmyf
P5v6qdJQMqtNGlU8eYzizEyuyovSlL+g9wgQ/91RAYK26FXzOuRz9Cg/ZWYVHqiG
rRWWwcfzY7qHo3HGkpDSIjD53TAoK46ICD4+EreG+JBvy1P3Ij/VX7M07swIg8Ff
6O4CnJpKAFaSr9wT8Ac3oCu+vymgLajMocNYV/UFVND+TLi6sx0zcMfCgW2vhSWk
PRulxL76xq97vjWoveqDiFS41cPOAghd4hUmzRFByX6XPBx6YZddSUF+QZt92K4Z
YEU4UbKqhbiBoZMGaQ8DzM2T44WPISrRZ0QpeS+pXwVjbDfoUbBWYAjFA8EHhPOi
oewIIYnarItI3z3iccErOeKPPVQh5QW3/CwO4XSnvTEBkhf2EjG25UAHZ8LZy0t8
Sw1raGJPYJV/qNVeIzLKd3tYmNpcmddYqS+ei2yBOoO5UPdbYaH1gTAZ4BbOhOml
BJKJWcekpJrZAVTBNRectxsMXB8fHYL65Wa+w3cRqsZRjTbTEg==
-----END CERTIFICATE-----
cn = Another unrelated CA
ca
cert_signing_key
expiration_days = -1
-- SPDX-License-Identifier: GPL-3.0-or-later
-- LuaJIT ffi bindings for zscanner, a DNS zone parser.
-- Author: Marek Vavrusa <marek.vavrusa@nic.cz>
--
local ffi = require('ffi')
local libzscanner = ffi.load(libzscanner_SONAME)
ffi.cdef[[
void free(void *ptr);
void *realloc(void *ptr, size_t size);
/*
* Data structures
*/
enum {
MAX_RDATA_LENGTH = 65535,
MAX_ITEM_LENGTH = 255,
MAX_DNAME_LENGTH = 255,
MAX_LABEL_LENGTH = 63,
MAX_RDATA_ITEMS = 64,
BITMAP_WINDOWS = 256,
INET4_ADDR_LENGTH = 4,
INET6_ADDR_LENGTH = 16,
RAGEL_STACK_SIZE = 16,
};
typedef struct {
uint8_t bitmap[32];
uint8_t length;
} window_t;
typedef struct {
uint8_t excl_flag;
uint16_t addr_family;
uint8_t prefix_length;
} apl_t;
typedef struct {
uint32_t d1, d2;
uint32_t m1, m2;
uint32_t s1, s2;
uint32_t alt;
uint64_t siz, hp, vp;
int8_t lat_sign, long_sign, alt_sign;
} loc_t;
typedef struct zs_state {
static const int NONE = 0;
static const int DATA = 1;
static const int ERROR = 2;
static const int INCLUDE = 3;
static const int EOF = 4;
static const int STOP = 5;
} zs_state_t;
typedef struct scanner {
int cs;
int top;
int stack[RAGEL_STACK_SIZE];
bool multiline;
uint64_t number64;
uint64_t number64_tmp;
uint32_t decimals;
uint32_t decimal_counter;
uint32_t item_length;
uint32_t item_length_position;
uint8_t *item_length_location;
uint32_t buffer_length;
uint8_t buffer[MAX_RDATA_LENGTH];
char include_filename[MAX_RDATA_LENGTH];
char *path;
window_t windows[BITMAP_WINDOWS];
int16_t last_window;
apl_t apl;
loc_t loc;
bool long_string;
uint8_t *dname;
uint32_t *dname_length;
uint32_t dname_tmp_length;
uint32_t r_data_tail;
uint32_t zone_origin_length;
uint8_t zone_origin[MAX_DNAME_LENGTH + MAX_LABEL_LENGTH];
uint16_t default_class;
uint32_t default_ttl;
int state;
struct {
bool automatic;
void (*record)(struct zs_scanner *);
void (*error)(struct zs_scanner *);
void *data;
} process;
struct {
const char *start;
const char *current;
const char *end;
bool eof;
} input;
struct {
char *name;
int descriptor;
} file;
struct {
int code;
uint64_t counter;
bool fatal;
} error;
uint64_t line_counter;
uint32_t r_owner_length;
uint8_t r_owner[MAX_DNAME_LENGTH + MAX_LABEL_LENGTH];
uint16_t r_class;
uint32_t r_ttl;
uint16_t r_type;
uint32_t r_data_length;
uint8_t r_data[MAX_RDATA_LENGTH];
} zs_scanner_t;
/*
* Function signatures
*/
int zs_init(zs_scanner_t *scanner, const char *origin, const uint16_t rclass, const uint32_t ttl);
void zs_deinit(zs_scanner_t *scanner);
int zs_set_input_string(zs_scanner_t *scanner, const char *input, size_t size);
int zs_set_input_file(zs_scanner_t *scanner, const char *file_name);
int zs_parse_record(zs_scanner_t *scanner);
const char* zs_strerror(const int code);
]]
-- Constant table
local zs_state = ffi.new('struct zs_state')
-- Wrap scanner context
local const_char_t = ffi.typeof('const char *')
local zs_scanner_t = ffi.typeof('struct scanner')
local zs_scanner_t = ffi.typeof('zs_scanner_t')
ffi.metatype( zs_scanner_t, {
__gc = function(zs) return libzscanner.zs_deinit(zs) end,
__new = function(ct, origin, class, ttl)
......@@ -148,30 +29,42 @@ ffi.metatype( zs_scanner_t, {
if input ~= nil then libzscanner.zs_set_input_string(zs, input, #input) end
local ret = libzscanner.zs_parse_record(zs)
-- Return current state only when parsed correctly, otherwise return error
if ret == 0 and zs.state ~= zs_state.ERROR then
return zs.state == zs_state.DATA
if ret == 0 and zs.state ~= "ZS_STATE_ERROR" then
return zs.state == "ZS_STATE_DATA"
else
return false, zs:strerr()
end
end,
current_rr = function(zs)
assert(ffi.istype(zs, zs_scanner_t))
return {owner = ffi.string(zs.r_owner, zs.r_owner_length),
ttl = tonumber(zs.r_ttl),
class = tonumber(zs.r_class),
type = tonumber(zs.r_type),
rdata = ffi.string(zs.r_data, zs.r_data_length)}
return {
owner = ffi.string(zs.r_owner, zs.r_owner_length),
ttl = tonumber(zs.r_ttl),
class = tonumber(zs.r_class),
type = tonumber(zs.r_type),
rdata = ffi.string(zs.r_data, zs.r_data_length),
comment = zs:current_comment(),
}
end,
strerr = function(zs)
assert(ffi.istype(zs, zs_scanner_t))
return ffi.string(libzscanner.zs_strerror(zs.error.code))
end,
current_comment = function(zs)
if zs.buffer_length > 0 then
return ffi.string(zs.buffer, zs.buffer_length - 1)
else
return nil
end
end
},
})
-- Module API
local rrparser = {
new = zs_scanner_t,
-- Parse a file into a list of RRs
file = function (path)
local zs = zs_scanner_t()
local ok, err = zs:open(path)
......@@ -184,6 +77,17 @@ local rrparser = {
end
return results
end,
state = zs_state,
-- Parse a string into a list of RRs.
string = function (input)
local zs = zs_scanner_t()
local results = {}
local ok = zs:parse(input)
while ok do
table.insert(results, zs:current_rr())
ok = zs:parse()
end
return results
end,
}
return rrparser
/* Copyright (C) 2014 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) CZ.NIC, z.s.p.o. <knot-resolver@labs.nic.cz>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
#include "kresconfig.h"
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
#include "contrib/ucw/mempool.h"
#include "daemon/engine.h"
#include "daemon/io.h"
#include "daemon/proxyv2.h"
#include "daemon/network.h"
#include "daemon/udp_queue.h"
#include "daemon/worker.h"
#include "daemon/ratelimiting.h"
#include "daemon/defer.h"
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "lib/defines.h"
#include "lib/dnssec.h"
#include "lib/log.h"
#include "lib/resolve.h"
#include "lib/rules/api.h"
#include <arpa/inet.h>
#include <getopt.h>
#include <libgen.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <uv.h>
#include <assert.h>
#include <contrib/cleanup.h>
#include <contrib/ucw/mempool.h>
#include <contrib/ccan/asprintf/asprintf.h>
#include <libknot/error.h>
#ifdef HAS_SYSTEMD
#include <systemd/sd-daemon.h>
#endif
#include <sys/resource.h>
#include <sys/wait.h>
#include <unistd.h>
#include "lib/defines.h"
#include "lib/resolve.h"
#include "lib/dnssec.h"
#include "daemon/network.h"
#include "daemon/worker.h"
#include "daemon/engine.h"
#include "daemon/bindings.h"
#include "daemon/tls.h"
/* We can fork early on Linux 3.9+ and do SO_REUSEPORT for better performance. */
#if defined(UV_VERSION_HEX) && defined(SO_REUSEPORT) && defined(__linux__)
#define CAN_FORK_EARLY 1
#if ENABLE_CAP_NG
#include <cap-ng.h>
#endif
/*
* Globals
*/
static bool g_quiet = false;
static bool g_interactive = true;
#include <lua.h>
#include <uv.h>
#if ENABLE_LIBSYSTEMD
#include <systemd/sd-daemon.h>
#else
static int notify_ready(const char *state);
#endif
#include <libknot/error.h>
/*
* TTY control
#if ENABLE_JEMALLOC
/* Make the jemalloc library needed.
*
* The problem is with --as-needed for linker which is added by default by meson.
* If we don't use any jemalloc-specific calls, linker will decide that
* it is not needed and won't link it. Making it needed seems better than
* trying to override the flag which might be useful in some other cases, etc.
*
* Exporting the function is a very easy way of ensuring that it's not optimized out.
*/
static void tty_read(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
#include <jemalloc/jemalloc.h>
KR_EXPORT void kr_jemalloc_unused(void)
{
/* Set output streams */
FILE *out = stdout, *outerr = stderr;
uv_os_fd_t stream_fd = 0;
if (uv_fileno((uv_handle_t *)stream, &stream_fd)) {
uv_close((uv_handle_t *)stream, (uv_close_cb) free);
if (buf) {
free(buf->base);
}
return;
}
if (stream_fd != STDIN_FILENO) {
if (nread <= 0) { /* Close if disconnected */
uv_close((uv_handle_t *)stream, (uv_close_cb) free);
if (buf) {
free(buf->base);
}
return;
}
uv_os_fd_t dup_fd = dup(stream_fd);
if (dup_fd >= 0) {
out = outerr = fdopen(dup_fd, "w");
}
}
/* Execute */
if (stream && buf && nread > 0) {
char *cmd = buf->base;
if (cmd[nread - 1] == '\n') {
cmd[nread - 1] = '\0';
}
struct engine *engine = stream->data;
lua_State *L = engine->L;
int ret = engine_cmd(L, cmd, false);
const char *message = "";
if (lua_gettop(L) > 0) {
message = lua_tostring(L, -1);
}
/* Log to remote socket if connected */
const char *delim = g_quiet ? "" : "> ";
if (stream_fd != STDIN_FILENO) {
fprintf(stdout, "%s\n", cmd); /* Duplicate command to logs */
if (message)
fprintf(out, "%s", message); /* Duplicate output to sender */
if (message || !g_quiet)
fprintf(out, "\n");
fprintf(out, "%s", delim);
}
/* Log to standard streams */
FILE *fp_out = ret ? stderr : stdout;
if (message)
fprintf(fp_out, "%s", message);
if (message || !g_quiet)
fprintf(fp_out, "\n");
fprintf(fp_out, "%s", delim);
lua_settop(L, 0);
}
fflush(out);
if (buf) {
free(buf->base);
}
/* Close if redirected */
if (stream_fd != STDIN_FILENO) {
fclose(out); /* outerr is the same */
}
malloc_stats_print(NULL, NULL, NULL);
}
/* We don't use threads (or rarely in some parts), so multiple arenas don't make sense.
https://jemalloc.net/jemalloc.3.html
*/
KR_EXPORT const char *malloc_conf = "narenas:1";
#endif
static void tty_alloc(uv_handle_t *handle, size_t suggested, uv_buf_t *buf) {
buf->len = suggested;
buf->base = malloc(suggested);
}
/**@internal Maximum number of incomplete TCP connections in queue.
* Default is from empirical testing - in our case, more isn't necessarily better.
* See https://gitlab.nic.cz/knot/knot-resolver/-/merge_requests/968
* */
#ifndef TCP_BACKLOG_DEFAULT
#define TCP_BACKLOG_DEFAULT 128
#endif
static void tty_accept(uv_stream_t *master, int status)
/** I don't know why linker is dropping these functions otherwise. TODO: revisit. */
KR_EXPORT void kr_misc_unused(void)
{
uv_tcp_t *client = malloc(sizeof(*client));
if (client) {
uv_tcp_init(master->loop, client);
if (uv_accept(master, (uv_stream_t *)client) != 0) {
free(client);
return;
}
client->data = master->data;
uv_read_start((uv_stream_t *)client, tty_alloc, tty_read);
/* Write command line */
if (!g_quiet) {
uv_buf_t buf = { "> ", 2 };
uv_try_write((uv_stream_t *)client, &buf, 1);
}
}
kr_rule_zonefile(NULL);
kr_rule_local_address(NULL, NULL, false, 0, 0);
}
static void ipc_close(uv_handle_t *handle)
{
free(handle);
}
struct args the_args_value; /** Static allocation for the_args singleton. */
/* @internal AF_LOCAL reads may still be interrupted, loop it. */
static bool ipc_readall(int fd, char *dst, size_t len)
static void signal_handler(uv_signal_t *handle, int signum)
{
while (len > 0) {
int rb = read(fd, dst, len);
if (rb > 0) {
dst += rb;
len -= rb;
} else if (errno != EAGAIN && errno != EINTR) {
return false;
}
switch (signum) {
case SIGINT: /* Fallthrough. */
case SIGTERM:
uv_stop(uv_default_loop());
uv_signal_stop(handle);
break;
case SIGCHLD:
/* Wait for all dead processes. */
while (waitpid(-1, NULL, WNOHANG) > 0);
break;
default:
kr_log_error(SYSTEM, "unhandled signal: %d\n", signum);
break;
}
return true;
}
static void ipc_activity(uv_poll_t* handle, int status, int events)
/** SIGBUS -> attempt to remove the overflowing cache file and abort. */
static void sigbus_handler(int sig, siginfo_t *siginfo, void *ptr)
{
struct engine *engine = handle->data;
if (status != 0) {
kr_log_error("[system] ipc: %s\n", uv_strerror(status));
ipc_close((uv_handle_t *)handle);
return;
/* We can't safely assume that printf-like functions work, but write() is OK.
* See POSIX for the safe functions, e.g. 2017 version just above this link:
* http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_04
*/
#define WRITE_ERR(err_charray) \
(void)write(STDERR_FILENO, err_charray, sizeof(err_charray))
/* Unfortunately, void-cast on the write isn't enough to avoid the warning. */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
const char msg_typical[] =
"\nSIGBUS received; this is most likely due to filling up the filesystem where cache resides.\n",
msg_unknown[] = "\nSIGBUS received, cause unknown.\n",
msg_deleted[] = "Cache file deleted.\n",
msg_del_fail[] = "Cache file deletion failed.\n",
msg_final[] = "kresd can not recover reliably by itself, exiting.\n";
if (siginfo->si_code != BUS_ADRERR) {
WRITE_ERR(msg_unknown);
goto end;
}
/* Get file descriptor from handle */
uv_os_fd_t fd = 0;
(void) uv_fileno((uv_handle_t *)(handle), &fd);
/* Read expression from IPC pipe */
uint32_t len = 0;
if (ipc_readall(fd, (char *)&len, sizeof(len))) {
auto_free char *rbuf = NULL;
if (len < UINT32_MAX) {
rbuf = malloc(len + 1);
} else {
errno = EINVAL;
}
if (!rbuf) {
kr_log_error("[system] ipc: %s\n", strerror(errno));
engine_stop(engine); /* Panic and stop this fork. */
return;
}
if (ipc_readall(fd, rbuf, len)) {
rbuf[len] = '\0';
/* Run expression */
const char *message = "";
int ret = engine_ipc(engine, rbuf);
if (ret > 0) {
message = lua_tostring(engine->L, -1);
}
/* Send response back */
len = strlen(message);
if (write(fd, &len, sizeof(len)) != sizeof(len) ||
write(fd, message, len) != len) {
kr_log_error("[system] ipc: %s\n", strerror(errno));
}
/* Clear the Lua stack */
lua_settop(engine->L, 0);
} else {
kr_log_error("[system] ipc: %s\n", strerror(errno));
}
WRITE_ERR(msg_typical);
if (!kr_cache_emergency_file_to_remove) goto end;
if (unlink(kr_cache_emergency_file_to_remove)) {
WRITE_ERR(msg_del_fail);
} else {
kr_log_error("[system] ipc: %s\n", strerror(errno));
}
}
static bool ipc_watch(uv_loop_t *loop, struct engine *engine, int fd)
{
uv_poll_t *poller = malloc(sizeof(*poller));
if (!poller) {
return false;
}
int ret = uv_poll_init(loop, poller, fd);
if (ret != 0) {
free(poller);
return false;
WRITE_ERR(msg_deleted);
}
poller->data = engine;
ret = uv_poll_start(poller, UV_READABLE, ipc_activity);
if (ret != 0) {
free(poller);
return false;
}
/* libuv sets O_NONBLOCK whether we want it or not */
(void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFL) & ~O_NONBLOCK);
return true;
}
static void signal_handler(uv_signal_t *handle, int signum)
{
uv_stop(uv_default_loop());
uv_signal_stop(handle);
end:
WRITE_ERR(msg_final);
_exit(128 - sig); /*< regular return from OS-raised SIGBUS can't work anyway */
#undef WRITE_ERR
#pragma GCC diagnostic pop
}
static const char *set_addr(char *addr, int *port)
{
char *p = strchr(addr, '#');
if (p) {
*port = atoi(p + 1);
*p = '\0';
}
return addr;
}
/*
* Server operation.
*/
static int fork_workers(fd_array_t *ipc_set, int forks)
{
/* Fork subprocesses if requested */
while (--forks > 0) {
int sv[2] = {-1, -1};
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sv) < 0) {
perror("[system] socketpair");
return kr_error(errno);
}
int pid = fork();
if (pid < 0) {
perror("[system] fork");
return kr_error(errno);
}
/* Forked process */
if (pid == 0) {
array_clear(*ipc_set);
array_push(*ipc_set, sv[0]);
close(sv[1]);
return forks;
/* Parent process */
} else {
array_push(*ipc_set, sv[1]);
/* Do not share parent-end with other forks. */
(void) fcntl(sv[1], F_SETFD, FD_CLOEXEC);
close(sv[0]);
}
}
return 0;
}
static void help(int argc, char *argv[])
{
printf("Usage: %s [parameters] [rundir]\n", argv[0]);
printf("\nParameters:\n"
" -a, --addr=[addr] Server address (default: localhost#53).\n"
" -t, --tls=[addr] Server address for TLS (default: off).\n"
" -S, --fd=[fd] Listen on given fd (handed out by supervisor).\n"
" -T, --tlsfd=[fd] Listen using TLS on given fd (handed out by supervisor).\n"
" -c, --config=[path] Config file path (relative to [rundir]) (default: config).\n"
" -k, --keyfile=[path] File containing trust anchors (DS or DNSKEY).\n"
" -f, --forks=N Start N forks sharing the configuration.\n"
" -q, --quiet Quiet output, no prompt in interactive mode.\n"
" -v, --verbose Run in verbose mode.\n"
" -a, --addr=[addr] Server address (default: localhost@53).\n"
" -t, --tls=[addr] Server address for TLS (default: off).\n"
" -S, --fd=[fd:kind] Listen on given fd (handed out by supervisor, :kind is optional).\n"
" -c, --config=[path] Config file path (relative to [rundir]) (default: config).\n"
" -n, --noninteractive Don't start the read-eval-print loop for stdin+stdout.\n"
" -q, --quiet No command prompt in interactive mode.\n"
" -v, --verbose Increase logging to debug level.\n"
" -V, --version Print version of the server.\n"
" -h, --help Print help and usage.\n"
"Options:\n"
" [rundir] Path to the working directory (default: .)\n");
}
static int run_worker(uv_loop_t *loop, struct engine *engine, fd_array_t *ipc_set, bool leader, int control_fd)
/** \return exit code for main() */
static int run_worker(uv_loop_t *loop, struct args *args)
{
/* Only some kinds of stdin work with uv_pipe_t.
* Otherwise we would abort() from libuv e.g. with </dev/null */
if (args->interactive) switch (uv_guess_handle(0)) {
case UV_TTY: /* standard terminal */
/* TODO: it has worked OK so far, but we'd better use uv_tty_*
* for this case instead of uv_pipe_*. */
case UV_NAMED_PIPE: /* echo 'quit()' | kresd ... */
break;
default:
kr_log_error(SYSTEM,
"error: standard input is not a terminal or pipe; "
"use '-n' if you want non-interactive mode. "
"Commands can be simply added to your configuration file or sent over the control socket.\n"
);
return EXIT_FAILURE;
}
/* Control sockets or TTY */
auto_free char *sock_file = NULL;
uv_pipe_t pipe;
uv_pipe_init(loop, &pipe, 0);
pipe.data = engine;
if (g_interactive) {
if (!g_quiet)
printf("[system] interactive mode\n> ");
fflush(stdout);
uv_pipe_open(&pipe, 0);
uv_read_start((uv_stream_t*) &pipe, tty_alloc, tty_read);
} else {
int pipe_ret = -1;
if (control_fd != -1) {
pipe_ret = uv_pipe_open(&pipe, control_fd);
} else {
(void) mkdir("tty", S_IRWXU|S_IRWXG);
sock_file = afmt("tty/%ld", getpid());
if (sock_file) {
pipe_ret = uv_pipe_bind(&pipe, sock_file);
}
}
if (!pipe_ret)
uv_listen((uv_stream_t *) &pipe, 16, tty_accept);
}
/* Watch IPC pipes (or just assign them if leading the pgroup). */
if (!leader) {
for (size_t i = 0; i < ipc_set->len; ++i) {
if (!ipc_watch(loop, engine, ipc_set->at[i])) {
kr_log_error("[system] failed to create poller: %s\n", strerror(errno));
close(ipc_set->at[i]);
}
}
uv_pipe_t *pipe = malloc(sizeof(*pipe));
if (!pipe)
return EXIT_FAILURE;
uv_pipe_init(loop, pipe, 0);
if (args->interactive) {
if (!args->quiet)
printf("Interactive mode:\n" "> ");
pipe->data = io_tty_alloc_data();
uv_pipe_open(pipe, 0);
uv_read_start((uv_stream_t*)pipe, io_tty_alloc, io_tty_process_input);
} else if (args->control_fd != -1 && uv_pipe_open(pipe, args->control_fd) == 0) {
uv_listen((uv_stream_t *)pipe, 16, io_tty_accept);
}
memcpy(&engine->ipc_set, ipc_set, sizeof(*ipc_set));
tls_setup_logging(kr_debug_status());
/* Notify supervisor. */
#ifdef HAS_SYSTEMD
#if ENABLE_LIBSYSTEMD
sd_notify(0, "READY=1");
#else
notify_ready("READY=1");
#endif
/* Run event loop */
uv_run(loop, UV_RUN_DEFAULT);
if (sock_file) {
unlink(sock_file);
/* Free pipe's data. Seems OK even on the stopped loop.
* In interactive case it may have been done in callbacks already (single leak). */
if (!args->interactive) {
uv_close((uv_handle_t *)pipe, NULL);
free(pipe);
}
return kr_ok();
return EXIT_SUCCESS;
}
void free_sd_socket_names(char **socket_names, int count)
static void args_init(struct args *args)
{
for (int i = 0; i < count; i++) {
free(socket_names[i]);
}
free(socket_names);
memset(args, 0, sizeof(struct args));
/* Zeroed arrays are OK. */
args->control_fd = -1;
args->interactive = true;
args->quiet = false;
}
int main(int argc, char **argv)
/* Free pointed-to resources. */
static void args_deinit(struct args *args)
{
int forks = 1;
array_t(char*) addr_set;
array_t(char*) tls_set;
array_init(addr_set);
array_init(tls_set);
array_t(int) fd_set;
array_init(fd_set);
array_t(int) tls_fd_set;
array_init(tls_fd_set);
char *keyfile = NULL;
const char *config = NULL;
char *keyfile_buf = NULL;
int control_fd = -1;
array_clear(args->addrs);
array_clear(args->addrs_tls);
for (int i = 0; i < args->fds.len; ++i)
free_const(args->fds.at[i].flags.kind);
array_clear(args->fds);
array_clear(args->config);
}
/** Process arguments into struct args.
* @return >=0 if main() should be exited immediately.
*/
static int parse_args(int argc, char **argv, struct args *args)
{
/* Long options. */
int c = 0, li = 0, ret = 0;
int c = 0, li = 0;
struct option opts[] = {
{"addr", required_argument, 0, 'a'},
{"tls", required_argument, 0, 't'},
{"fd", required_argument, 0, 'S'},
{"tlsfd", required_argument, 0, 'T'},
{"config", required_argument, 0, 'c'},
{"keyfile",required_argument, 0, 'k'},
{"forks",required_argument, 0, 'f'},
{"verbose", no_argument, 0, 'v'},
{"quiet", no_argument, 0, 'q'},
{"version", no_argument, 0, 'V'},
{"help", no_argument, 0, 'h'},
{"addr", required_argument, 0, 'a'},
{"tls", required_argument, 0, 't'},
{"config", required_argument, 0, 'c'},
{"noninteractive", no_argument, 0, 'n'},
{"verbose", no_argument, 0, 'v'},
{"quiet", no_argument, 0, 'q'},
{"version", no_argument, 0, 'V'},
{"help", no_argument, 0, 'h'},
{"fd", required_argument, 0, 'S'},
{0, 0, 0, 0}
};
while ((c = getopt_long(argc, argv, "a:t:S:T:c:f:k:vqVh", opts, &li)) != -1) {
while ((c = getopt_long(argc, argv, "a:t:c:f:nvqVhS:", opts, &li)) != -1) {
switch (c)
{
case 'a':
array_push(addr_set, optarg);
kr_require(optarg);
array_push(args->addrs, optarg);
break;
case 't':
array_push(tls_set, optarg);
break;
case 'S':
array_push(fd_set, atoi(optarg));
break;
case 'T':
array_push(tls_fd_set, atoi(optarg));
kr_require(optarg);
array_push(args->addrs_tls, optarg);
break;
case 'c':
config = optarg;
kr_require(optarg);
array_push(args->config, optarg);
break;
case 'f':
g_interactive = false;
forks = atoi(optarg);
if (forks <= 0) {
kr_log_error("[system] error '-f' requires a positive"
" number, not '%s'\n", optarg);
return EXIT_FAILURE;
}
break;
case 'k':
keyfile_buf = malloc(PATH_MAX);
if (!keyfile_buf) {
kr_log_error("[system] not enough memory\n");
return EXIT_FAILURE;
}
/* Check if the path is absolute */
if (optarg[0] == '/') {
keyfile = strdup(optarg);
} else {
/* Construct absolute path, the file may not exist */
keyfile = realpath(".", keyfile_buf);
if (keyfile) {
int len = strlen(keyfile);
int namelen = strlen(optarg);
if (len + namelen < PATH_MAX - 1) {
keyfile[len] = '/';
memcpy(keyfile + len + 1, optarg, namelen + 1);
keyfile = strdup(keyfile); /* Duplicate */
} else {
keyfile = NULL; /* Invalidate */
}
}
}
free(keyfile_buf);
if (!keyfile) {
kr_log_error("[system] keyfile '%s':"
"failed to construct absolute path\n", optarg);
return EXIT_FAILURE;
}
case 'n':
args->interactive = false;
break;
case 'v':
kr_debug_set(true);
kr_log_level_set(LOG_DEBUG);
break;
case 'q':
g_quiet = true;
args->quiet = true;
break;
case 'V':
kr_log_info("%s, version %s\n", "Knot DNS Resolver", PACKAGE_VERSION);
printf("Knot Resolver, version %s\n", PACKAGE_VERSION);
return EXIT_SUCCESS;
case 'h':
case '?':
......@@ -470,173 +282,396 @@ int main(int argc, char **argv)
default:
help(argc, argv);
return EXIT_FAILURE;
case 'S':
kr_require(optarg);
flagged_fd_t ffd = { 0 };
char *endptr;
ffd.fd = strtol(optarg, &endptr, 10);
if (endptr != optarg && endptr[0] == '\0') {
/* Plain DNS */
ffd.flags.tls = false;
} else if (endptr[0] == ':' && strcasecmp(endptr + 1, "tls") == 0) {
/* DoT */
ffd.flags.tls = true;
/* We know what .sock_type should be but it wouldn't help. */
} else if (endptr[0] == ':' && endptr[1] != '\0') {
/* Some other kind; no checks here. */
ffd.flags.kind = strdup(endptr + 1);
} else {
kr_log_error(SYSTEM, "incorrect value passed to '-S/--fd': %s\n",
optarg);
return EXIT_FAILURE;
}
array_push(args->fds, ffd);
break;
}
}
if (optind < argc) {
args->rundir = argv[optind];
}
return -1;
}
#ifdef HAS_SYSTEMD
/* Accept passed sockets from systemd supervisor. */
char **socket_names = NULL;
int sd_nsocks = sd_listen_fds_with_names(0, &socket_names);
for (int i = 0; i < sd_nsocks; ++i) {
int fd = SD_LISTEN_FDS_START + i;
/* when run under systemd supervision, do not use interactive mode */
g_interactive = false;
if (forks != 1) {
kr_log_error("[system] when run under systemd-style supervision, "
"use single-process only (bad: --fork=%d).\n", forks);
free_sd_socket_names(socket_names, sd_nsocks);
return EXIT_FAILURE;
/** Just convert addresses to file-descriptors; clear *addrs on success.
* @note AF_UNIX is supported (starting with '/').
* @return zero or exit code for main()
*/
static int bind_sockets(addr_array_t *addrs, bool tls, flagged_fd_array_t *fds)
{
bool has_error = false;
for (size_t i = 0; i < addrs->len; ++i) {
/* Get port and separate address string. */
uint16_t port = tls ? KR_DNS_TLS_PORT : KR_DNS_PORT;
char addr_buf[INET6_ADDRSTRLEN + 1];
int ret;
const char *addr_str;
const int family = kr_straddr_family(addrs->at[i]);
if (family == AF_UNIX) {
ret = 0;
addr_str = addrs->at[i];
} else { /* internet socket (or garbage) */
ret = kr_straddr_split(addrs->at[i], addr_buf, &port);
addr_str = addr_buf;
}
/* Get sockaddr. */
struct sockaddr *sa = NULL;
if (ret == 0) {
sa = kr_straddr_socket(addr_str, port, NULL);
if (!sa) ret = kr_error(EINVAL); /* could be ENOMEM but unlikely */
}
flagged_fd_t ffd = { .flags = { .tls = tls } };
if (ret == 0 && !tls && family != AF_UNIX) {
/* AF_UNIX can do SOCK_DGRAM, but let's not support that *here*. */
ffd.fd = io_bind(sa, SOCK_DGRAM, NULL);
if (ffd.fd < 0)
ret = ffd.fd;
else if (array_push(*fds, ffd) < 0)
ret = kr_error(ENOMEM);
}
if (!strcasecmp("control",socket_names[i])) {
control_fd = fd;
} else if (!strcasecmp("tls",socket_names[i])) {
array_push(tls_fd_set, fd);
if (ret == 0) { /* common for TCP and TLS, including AF_UNIX cases */
ffd.fd = io_bind(sa, SOCK_STREAM, NULL);
if (ffd.fd < 0)
ret = ffd.fd;
else if (array_push(*fds, ffd) < 0)
ret = kr_error(ENOMEM);
}
free(sa);
if (ret != 0) {
kr_log_error(NETWORK, "bind to '%s'%s: %s\n",
addrs->at[i], tls ? " (TLS)" : "", kr_strerror(ret));
has_error = true;
}
}
array_clear(*addrs);
return has_error ? EXIT_FAILURE : kr_ok();
}
static int start_listening(flagged_fd_array_t *fds) {
int some_bad_ret = 0;
for (size_t i = 0; i < fds->len; ++i) {
flagged_fd_t *ffd = &fds->at[i];
int ret = network_listen_fd(ffd->fd, ffd->flags);
if (ret != 0) {
some_bad_ret = ret;
/* TODO: try logging address@port. It's not too important,
* because typical problems happen during binding already.
* (invalid address, permission denied) */
kr_log_error(NETWORK, "listen on fd=%d: %s\n",
ffd->fd, kr_strerror(ret));
/* Continue printing all of these before exiting. */
} else {
array_push(fd_set, fd);
ffd->flags.kind = NULL; /* ownership transferred */
}
}
free_sd_socket_names(socket_names, sd_nsocks);
#endif
return some_bad_ret;
}
/* Switch to rundir. */
if (optind < argc) {
const char *rundir = argv[optind];
if (access(rundir, W_OK) != 0) {
kr_log_error("[system] rundir '%s': %s\n", rundir, strerror(errno));
return EXIT_FAILURE;
#if !ENABLE_LIBSYSTEMD
/* Notify supervisord about successful inicialization
* @note tested only on an abstract address in $NOTIFY_SOCKET*/
static int notify_ready(const char *state)
{
int sockfd;
struct sockaddr_un addr;
char *socket_path = getenv("NOTIFY_SOCKET");
if (!socket_path) {
kr_log_error(WORKER, "Failed retrieving env variable $NOTIFY_SOCKET\n");
return EXIT_FAILURE;
}
if ((sockfd = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) {
kr_log_error(WORKER, "Failed to create unix socket at $NOTIFY_SOCKET ('%s'): %s\n",
socket_path, strerror(errno));
return EXIT_FAILURE;
}
addr.sun_family = AF_UNIX;
int addrlen;
if (socket_path[0] == '@') {
addr.sun_path[0] = '\0';
strncpy(&addr.sun_path[1], socket_path + 1, sizeof(addr.sun_path) - 2);
addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path + 1) + 1;
} else {
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path) + 1;
}
if (sendto(sockfd, state, strlen(state), 0, &addr, addrlen) == -1) {
kr_log_error(WORKER, "Failed to send notify message to '%s': %s\n",
socket_path, strerror(errno));
close(sockfd);
return EXIT_FAILURE;
}
close(sockfd);
return kr_ok();
}
#endif /* if !ENABLE_LIBSYSTEMD */
/* Drop POSIX 1003.1e capabilities. */
static void drop_capabilities(void)
{
#if ENABLE_CAP_NG
/* Drop all capabilities when running under non-root user. */
if (geteuid() == 0) {
kr_log_debug(SYSTEM, "running as root, no capabilities dropped\n");
return;
}
if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) {
capng_clear(CAPNG_SELECT_BOTH);
/* Apply. */
if (capng_apply(CAPNG_SELECT_BOTH) < 0) {
kr_log_error(SYSTEM, "failed to set process capabilities: %s\n",
strerror(errno));
} else {
kr_log_debug(SYSTEM, "all capabilities dropped\n");
}
ret = chdir(rundir);
if (ret != 0) {
kr_log_error("[system] rundir '%s': %s\n", rundir, strerror(errno));
} else {
/* If user() was called, the capabilities were already dropped along with SETPCAP. */
kr_log_debug(SYSTEM, "process not allowed to set capabilities, skipping\n");
}
#endif /* ENABLE_CAP_NG */
}
int main(int argc, char **argv)
{
kr_log_group_reset();
if (setvbuf(stdout, NULL, _IONBF, 0) || setvbuf(stderr, NULL, _IONBF, 0)) {
kr_log_error(SYSTEM, "failed to set output buffering (ignored): %s\n",
strerror(errno));
(void)fflush(stderr);
}
if (strcmp("linux", OPERATING_SYSTEM) != 0)
kr_log_warning(SYSTEM, "Knot Resolver is tested on Linux, other platforms might exhibit bugs.\n"
"Please report issues to https://gitlab.nic.cz/knot/knot-resolver/issues/\n"
"Thank you for your time and interest!\n");
the_args = &the_args_value;
args_init(the_args);
int ret = parse_args(argc, argv, the_args);
if (ret >= 0) goto cleanup_args;
ret = bind_sockets(&the_args->addrs, false, &the_args->fds);
if (ret) goto cleanup_args;
ret = bind_sockets(&the_args->addrs_tls, true, &the_args->fds);
if (ret) goto cleanup_args;
/* Switch to rundir. */
if (the_args->rundir != NULL) {
/* FIXME: access isn't a good way if we start as root and drop privileges later */
if (access(the_args->rundir, W_OK) != 0
|| chdir(the_args->rundir) != 0) {
kr_log_error(SYSTEM, "rundir '%s': %s\n",
the_args->rundir, strerror(errno));
return EXIT_FAILURE;
}
if(config && strcmp(config, "-") != 0 && access(config, R_OK) != 0) {
kr_log_error("[system] rundir '%s'\n", rundir);
kr_log_error("[system] config '%s': %s\n", config, strerror(errno));
}
/* Select which config files to load and verify they are read-able. */
bool load_defaults = true;
size_t i = 0;
while (i < the_args->config.len) {
const char *config = the_args->config.at[i];
if (strcmp(config, "-") == 0) {
load_defaults = false;
array_del(the_args->config, i);
continue; /* don't increment i */
} else if (access(config, R_OK) != 0) {
char cwd[PATH_MAX];
get_workdir(cwd, sizeof(cwd));
kr_log_error(SYSTEM, "config '%s' (workdir '%s'): %s\n",
config, cwd, strerror(errno));
return EXIT_FAILURE;
}
i++;
}
#ifndef CAN_FORK_EARLY
/* Forking is currently broken with libuv. We need libuv to bind to
* sockets etc. before forking, but at the same time can't touch it before
* forking otherwise it crashes, so it's a chicken and egg problem.
* Disabling until https://github.com/libuv/libuv/pull/846 is done. */
if (forks > 1 && fd_set.len == 0 && tls_fd_set.len == 0) {
kr_log_error("[system] forking >1 workers supported only on Linux 3.9+ or with supervisor\n");
return EXIT_FAILURE;
}
#endif
/* Connect forks with local socket */
fd_array_t ipc_set;
array_init(ipc_set);
/* Fork subprocesses if requested */
int fork_id = fork_workers(&ipc_set, forks);
if (fork_id < 0) {
return EXIT_FAILURE;
if (the_args->config.len == 0 && access("config", R_OK) == 0)
array_push(the_args->config, "config");
if (load_defaults)
array_push(the_args->config, LIBDIR "/postconfig.lua");
/* File-descriptor count limit: soft->hard. */
struct rlimit rlim;
ret = getrlimit(RLIMIT_NOFILE, &rlim);
if (ret == 0 && rlim.rlim_cur != rlim.rlim_max) {
kr_log_debug(SYSTEM, "increasing file-descriptor limit: %ld -> %ld\n",
(long)rlim.rlim_cur, (long)rlim.rlim_max);
rlim.rlim_cur = rlim.rlim_max;
ret = setrlimit(RLIMIT_NOFILE, &rlim);
}
if (ret) {
kr_log_error(SYSTEM, "failed to get or set file-descriptor limit: %s\n",
strerror(errno));
} else if (rlim.rlim_cur < (rlim_t)512 * 1024) {
kr_log_warning(SYSTEM, "warning: hard limit for number of file-descriptors is only %ld but recommended value is 524288\n",
(long)rlim.rlim_cur);
}
kr_crypto_init();
network_init(uv_default_loop(), TCP_BACKLOG_DEFAULT);
/* Create a server engine. */
knot_mm_t pool = {
.ctx = mp_new (4096),
.alloc = (knot_mm_alloc_t) mp_alloc
};
struct engine engine;
ret = engine_init(&engine, &pool);
ret = engine_init();
if (ret != 0) {
kr_log_error("[system] failed to initialize engine: %s\n", kr_strerror(ret));
kr_log_error(SYSTEM, "failed to initialize engine: %s\n", kr_strerror(ret));
return EXIT_FAILURE;
}
/* Create worker */
struct worker_ctx *worker = worker_create(&engine, &pool, fork_id, forks);
if (!worker) {
kr_log_error("[system] not enough memory\n");
/* Create resolver context. */
ret = kr_resolver_init(&the_engine->modules, &the_engine->pool);
if (ret != 0) {
kr_log_error(SYSTEM, "failed to initialize resolver: %s\n", kr_strerror(ret));
return EXIT_FAILURE;
}
/* Bind to passed fds and run */
for (size_t i = 0; i < fd_set.len; ++i) {
ret = network_listen_fd(&engine.net, fd_set.at[i], false);
if (ret != 0) {
kr_log_error("[system] listen on fd=%d %s\n", fd_set.at[i], kr_strerror(ret));
ret = EXIT_FAILURE;
break;
}
/* Initialize the worker. */
ret = worker_init();
if (ret != 0) {
kr_log_error(SYSTEM, "failed to initialize worker: %s\n", kr_strerror(ret));
return EXIT_FAILURE;
}
/* Do the same for TLS */
for (size_t i = 0; i < tls_fd_set.len; ++i) {
ret = network_listen_fd(&engine.net, tls_fd_set.at[i], true);
if (ret != 0) {
kr_log_error("[system] TLS listen on fd=%d %s\n", tls_fd_set.at[i], kr_strerror(ret));
ret = EXIT_FAILURE;
break;
uv_loop_t *loop = uv_default_loop();
/* Catch some signals. */
uv_signal_t sigint, sigterm, sigchld;
if (true) ret = uv_signal_init(loop, &sigint);
if (!ret) ret = uv_signal_init(loop, &sigterm);
if (!ret) ret = uv_signal_init(loop, &sigchld);
if (!ret) ret = uv_signal_start(&sigint, signal_handler, SIGINT);
if (!ret) ret = uv_signal_start(&sigterm, signal_handler, SIGTERM);
if (!ret) ret = uv_signal_start(&sigchld, signal_handler, SIGCHLD);
/* Block SIGPIPE; see https://github.com/libuv/libuv/issues/45 */
if (!ret && signal(SIGPIPE, SIG_IGN) == SIG_ERR) ret = errno;
if (!ret) {
/* Catching SIGBUS via uv_signal_* can't work; see:
* https://github.com/libuv/libuv/pull/1987 */
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = sigbus_handler;
sa.sa_flags = SA_SIGINFO;
if (sigaction(SIGBUS, &sa, NULL)) {
ret = errno;
}
}
/* Bind to sockets and run */
if (ret == 0) {
for (size_t i = 0; i < addr_set.len; ++i) {
int port = 53;
const char *addr = set_addr(addr_set.at[i], &port);
ret = network_listen(&engine.net, addr, (uint16_t)port, NET_UDP|NET_TCP);
if (ret != 0) {
kr_log_error("[system] bind to '%s#%d' %s\n", addr, port, kr_strerror(ret));
ret = EXIT_FAILURE;
break;
}
}
if (ret) {
kr_log_error(SYSTEM, "failed to set up signal handlers: %s\n",
strerror(abs(errno)));
ret = EXIT_FAILURE;
goto cleanup;
}
/* Bind to TLS sockets */
if (ret == 0) {
for (size_t i = 0; i < tls_set.len; ++i) {
int port = KR_DNS_TLS_PORT;
const char *addr = set_addr(tls_set.at[i], &port);
ret = network_listen(&engine.net, addr, (uint16_t)port, NET_TCP|NET_TLS);
if (ret != 0) {
kr_log_error("[system] bind to '%s#%d' (TLS) %s\n", addr, port, kr_strerror(ret));
ret = EXIT_FAILURE;
break;
}
}
/* Profiling: avoid SIGPROF waking up the event loop. Otherwise the profiles
* (of the usual type) may skew results, e.g. epoll_pwait() taking lots of time. */
ret = uv_loop_configure(loop, UV_LOOP_BLOCK_SIGNAL, SIGPROF);
if (ret) {
kr_log_info(SYSTEM, "failed to block SIGPROF in event loop, ignoring: %s\n",
uv_strerror(ret));
}
/* Start listening, in the sense of network_listen_fd(). */
if (start_listening(&the_args->fds) != 0) {
ret = EXIT_FAILURE;
goto cleanup;
}
ret = udp_queue_init_global(loop);
if (ret) {
kr_log_error(SYSTEM, "failed to initialize UDP queue: %s\n",
kr_strerror(ret));
ret = EXIT_FAILURE;
goto cleanup;
}
/* Block signals. */
uv_loop_t *loop = uv_default_loop();
uv_signal_t sigint, sigterm;
uv_signal_init(loop, &sigint);
uv_signal_init(loop, &sigterm);
uv_signal_start(&sigint, signal_handler, SIGINT);
uv_signal_start(&sigterm, signal_handler, SIGTERM);
/* Start the scripting engine */
worker->loop = loop;
loop->data = worker;
if (ret == 0) {
ret = engine_start(&engine, config ? config : "config");
if (ret == 0) {
if (keyfile) {
auto_free char *cmd = afmt("trust_anchors.config('%s')", keyfile);
if (!cmd) {
kr_log_error("[system] not enough memory\n");
return EXIT_FAILURE;
}
engine_cmd(engine.L, cmd, false);
lua_settop(engine.L, 0);
}
/* Run the event loop */
ret = run_worker(loop, &engine, &ipc_set, fork_id == 0, control_fd);
if (engine_load_sandbox() != 0) {
ret = EXIT_FAILURE;
goto cleanup;
}
for (i = 0; i < the_args->config.len; ++i) {
const char *config = the_args->config.at[i];
if (engine_loadconf(config) != 0) {
ret = EXIT_FAILURE;
goto cleanup;
}
if (ret != 0) {
perror("[system] worker failed");
lua_settop(the_engine->L, 0);
}
if (!defer_initialized) {
kr_log_warning(SYSTEM, "Prioritization not initialized from Lua, using hardcoded default.\n");
ret = defer_init("defer", 1, 1);
if (ret) {
ret = EXIT_FAILURE;
goto cleanup;
}
}
/* Cleanup. */
free(keyfile);
engine_deinit(&engine);
worker_reclaim(worker);
mp_delete(pool.ctx);
array_clear(addr_set);
array_clear(tls_set);
if (defer_init_idle(loop) != 0) {
ret = EXIT_FAILURE;
goto cleanup;
}
ret = kr_rules_init_ensure();
if (ret) {
kr_log_error(RULES, "failed to initialize policy rule engine: %s\n",
kr_strerror(ret));
ret = EXIT_FAILURE;
goto cleanup;
}
drop_capabilities();
if (engine_start() != 0) {
ret = EXIT_FAILURE;
goto cleanup;
}
if (network_engage_endpoints()) {
ret = EXIT_FAILURE;
goto cleanup;
}
/* Starting everything succeeded, so commit rule DB changes. */
kr_rules_commit(true);
/* Run the event loop */
ret = run_worker(loop, the_args);
cleanup:/* Cleanup. */
network_unregister();
ratelimiting_deinit();
kr_resolver_deinit();
worker_deinit();
engine_deinit();
network_deinit();
defer_deinit();
kr_rules_commit(false);
kr_rules_deinit();
if (loop != NULL) {
uv_loop_close(loop);
}
cleanup_args:
args_deinit(the_args);
kr_crypto_cleanup();
return ret;
}
# SPDX-License-Identifier: GPL-3.0-or-later
# daemon
kresd_src = files([
'bindings/cache.c',
'bindings/event.c',
'bindings/impl.c',
'bindings/modules.c',
'bindings/net.c',
'bindings/worker.c',
'defer.c',
'engine.c',
'ffimodule.c',
'io.c',
'main.c',
'network.c',
'proxyv2.c',
'ratelimiting.c',
'session2.c',
'tls.c',
'tls_ephemeral_credentials.c',
'tls_session_ticket-srv.c',
'udp_queue.c',
'worker.c',
'zimport.c',
])
if nghttp2.found()
kresd_src += files(['http.c'])
endif
c_src_lint += kresd_src
unit_tests += [
['ratelimiting', files('ratelimiting.test/tests.c') + libkres_src ],
# parallel tests timeouts under valgrind; they checks mainly for race conditions, which is not needed there
['ratelimiting-parallel', files('ratelimiting.test/tests-parallel.c') + libkres_src, ['skip_valgrind']]
]
config_tests += [
['cache.clear', files('cache.test/clear.test.lua')],
['zimport', files('zimport.test/zimport.test.lua')],
]
integr_tests += [
['cache_insert_ns', meson.current_source_dir() / 'cache.test' / 'insert_ns.test.integr'],
['proxyv2', meson.current_source_dir() / 'proxyv2.test']
]
kresd_deps = [
contrib_dep,
kresconfig_dep,
libkres_dep,
libknot,
libzscanner,
libdnssec,
libuv,
luajit,
gnutls,
libsystemd,
capng,
nghttp2,
malloc,
libm
]
subdir('lua')
kresd = executable(
'kresd',
kresd_src,
dependencies: kresd_deps,
export_dynamic: true,
install: true,
install_dir: get_option('sbindir'),
install_rpath: rpath,
)