From: Pieter Lexis Date: Fri, 12 Oct 2018 13:35:16 +0000 (+0200) Subject: rec: Add `ReadTrustAnchorsFromFile` function X-Git-Tag: dnsdist-1.3.3~23^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8f29eeaa8faa542cafccd14d08fda53730ac9c51;p=thirdparty%2Fpdns.git rec: Add `ReadTrustAnchorsFromFile` function This allows the recursor to read the output file from `unbound-anchor` and use these kind of files for trust anchors. This will enable distributions to ship DNSSEC anchors with their system and use them. --- diff --git a/pdns/rec-lua-conf.cc b/pdns/rec-lua-conf.cc index 3b5284dde1..76e1222836 100644 --- a/pdns/rec-lua-conf.cc +++ b/pdns/rec-lua-conf.cc @@ -15,6 +15,9 @@ #include "validate.hh" #include "validate-recursor.hh" #include "root-dnssec.hh" +#include "dnssecinfra.hh" +#include "dnsseckeeper.hh" +#include "zoneparser-tng.hh" GlobalStateHolder g_luaconfs; @@ -408,6 +411,39 @@ void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& de lci.negAnchors.clear(); }); + Lua.writeFunction("readTrustAnchorsFromFile", [&lci](const std::string& fname) { + warnIfDNSSECDisabled("Warning: reading Trust Anchors from file (readTrustAnchorsFromFile), but dnssec is set to 'off'!"); + auto zp = ZoneParserTNG(fname); + DNSResourceRecord rr; + DNSRecord dr; + try { + while(zp.get(rr)) { + dr = DNSRecord(rr); + if (rr.qtype == QType::DS) { + auto dsr = getRR(dr); + if (dsr == nullptr) { + throw PDNSException("Unable to parse DS record '" + rr.qname.toString() + " " + rr.getZoneRepresentation() + "'"); + } + lci.dsAnchors[rr.qname].insert(*dsr); + } + if (rr.qtype == QType::DNSKEY) { + auto dnskeyr = getRR(dr); + if (dnskeyr == nullptr) { + throw PDNSException("Unable to parse DNSKEY record '" + rr.qname.toString() + " " + rr.getZoneRepresentation() +"'"); + } + auto dsr = makeDSFromDNSKey(rr.qname, *dnskeyr, DNSSECKeeper::SHA256); + lci.dsAnchors[rr.qname].insert(dsr); + } + } + } + catch (const std::exception &e) { + throw PDNSException("Error while reading Trust Anchors from file (readTrustAnchorsFromFile) '" + fname + "': " + e.what()); + } + catch (...) { + throw PDNSException("Error while reading Trust Anchors from file (readTrustAnchorsFromFile) '" + fname + "'"); + } + }); + #if HAVE_PROTOBUF Lua.writeFunction("setProtobufMasks", [&lci](const uint8_t maskV4, uint8_t maskV6) { lci.protobufMaskV4 = maskV4; diff --git a/pdns/recursordist/docs/dnssec.rst b/pdns/recursordist/docs/dnssec.rst index 2e6d456c6f..b5bd5b9a41 100644 --- a/pdns/recursordist/docs/dnssec.rst +++ b/pdns/recursordist/docs/dnssec.rst @@ -100,6 +100,20 @@ For PowerDNS Recursor 4.1.x and below, use the :func:`addDS` function instead. Now (re)start the recursor to load these trust anchors. +Reading trust anchors from files +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Since version 4.2.0 of the PowerDNS Recursor, it is also possible to read the Trust Anchors from a BIND-style zonefile. +Only the DS and DNSKEY records from this file are read. +Debian and its derivatives ship the ``dns-root-data`` package that contains the DNSSEC root trust anchors in ``/usr/share/dns/root.key``. + +To only use the distribution-provided Trust Anchors, add the following to the :ref:`setting-lua-config-file`: + +.. sourcecode:: lua + + clearTA() -- Remove built-in trust-anchors + readTrustAnchorsFromFile("/usr/share/dns/root.key") -- Use these keys + Runtime Configuration of Trust Anchors ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To change or add trust anchors at runtime, use the :doc:`manpages/rec_control.1` tool. diff --git a/pdns/recursordist/docs/lua-config/dnssec.rst b/pdns/recursordist/docs/lua-config/dnssec.rst index 4061bde950..17b189d339 100644 --- a/pdns/recursordist/docs/lua-config/dnssec.rst +++ b/pdns/recursordist/docs/lua-config/dnssec.rst @@ -56,3 +56,12 @@ This page only documents the Lua functions for DNSSEC configuration not given, remove *all* negative trust anchors instead. :param str name: The name in the DNS tree from where this NTA should be removed + +.. function:: readTrustAnchorsFromFile(fname) + + .. versionadded:: 4.2.0 + + Reads all DS and DNSKEY records from ``fname`` (a BIND zone file) and adds these to the Trust Anchors. + This function can be used to read distribution provided trust anchors, as for instance ``/usr/share/dns/root.key`` from Debian's ``dns-root-data`` package. + + :param str fname: Path to a zone file with Trust Anchors diff --git a/regression-tests.recursor-dnssec/recursortests.py b/regression-tests.recursor-dnssec/recursortests.py index 8bfafa05db..d2a286858f 100644 --- a/regression-tests.recursor-dnssec/recursortests.py +++ b/regression-tests.recursor-dnssec/recursortests.py @@ -445,7 +445,7 @@ distributor-threads=1""".format(confdir=confdir, luaconfpath = os.path.join(confdir, 'conffile.lua') with open(luaconfpath, 'w') as luaconf: if cls._root_DS: - luaconf.write("addDS('.', '%s')\n" % cls._root_DS) + luaconf.write("addTA('.', '%s')\n" % cls._root_DS) if cls._lua_config_file: luaconf.write(cls._lua_config_file) conf.write("lua-config-file=%s\n" % luaconfpath) diff --git a/regression-tests.recursor-dnssec/root.keys b/regression-tests.recursor-dnssec/root.keys new file mode 100644 index 0000000000..16763f9970 --- /dev/null +++ b/regression-tests.recursor-dnssec/root.keys @@ -0,0 +1,3 @@ +. 300 IN DNSKEY 257 3 13 aPHAAOTdxA8XxiUo8YTOXPG7uRXPA4XFhcnJ/I13+f/0I/B0TobNDG0t aRjsp/rezR1o0DXh0fb4vvC+STbPog== ; Should be converted to DS +. 3600 IN DS 36914 13 2 C94ED457FF79AFE03804C26CE4FA832687DB92BC231AFF98617791FC 71A65870 ; Will be used as-is +. 1200 IN A 192.0.2.1 ; Should be ignored diff --git a/regression-tests.recursor-dnssec/test_NTA.py b/regression-tests.recursor-dnssec/test_NTA.py index b21d7f6b6b..9b4e18dfd2 100644 --- a/regression-tests.recursor-dnssec/test_NTA.py +++ b/regression-tests.recursor-dnssec/test_NTA.py @@ -7,7 +7,7 @@ class testSimple(RecursorTest): _config_template = """dnssec=validate""" _lua_config_file = """addNTA("bogus.example") addNTA('secure.optout.example', 'Should be Insecure, even with DS configured') -addDS('secure.optout.example', '64215 13 1 b88284d7a8d8605c398e8942262f97b9a5a31787')""" +addTA('secure.optout.example', '64215 13 1 b88284d7a8d8605c398e8942262f97b9a5a31787')""" def testDirectNTA(self): """Ensure a direct query to a bogus name with an NTA is Insecure""" diff --git a/regression-tests.recursor-dnssec/test_ReadTrustAnchorsFromFile.py b/regression-tests.recursor-dnssec/test_ReadTrustAnchorsFromFile.py new file mode 100644 index 0000000000..c150703ee9 --- /dev/null +++ b/regression-tests.recursor-dnssec/test_ReadTrustAnchorsFromFile.py @@ -0,0 +1,30 @@ +import os +import subprocess +from recursortests import RecursorTest + + +class testReadTrustAnchorsFronFile(RecursorTest): + _confdir = 'ReadTAsFromFile' + + _config_template = """dnssec=validate""" + _lua_config_file = """clearTA() +readTrustAnchorsFromFile('root.keys')""" + + def testCorrectFile(self): + """Ensure the file is read correctly""" + rec_controlCmd = [os.environ['RECCONTROL'], + '--config-dir=%s' % 'configs/' + self._confdir, + 'get-tas'] + expected = """Configured Trust Anchors: +. +\t\t36914 13 2 c94ed457ff79afe03804c26ce4fa832687db92bc231aff98617791fc71a65870 +\t\t42924 13 2 b49e0aafd6e147742afb9eab0e76af0546357dc6c61bf67d7c745cf6f43f460e +""" + try: + ret = subprocess.check_output(rec_controlCmd, stderr=subprocess.STDOUT) + self.assertEqual(ret, expected) + + except subprocess.CalledProcessError as e: + print e.output + raise +