From: Pieter Lexis Date: Wed, 27 Apr 2016 12:08:29 +0000 (+0200) Subject: Add basic NSEC and NSEC3 tests X-Git-Tag: rec-4.0.0-alpha3~38^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=11886ab917250ada978927ff5248aaeb0ba7afa8;p=pdns Add basic NSEC and NSEC3 tests Add a zone with NSEC3-optout for the NSEC3 tests --- diff --git a/regression-tests.recursor-dnssec/basicDNSSEC.py b/regression-tests.recursor-dnssec/basicDNSSEC.py new file mode 100644 index 000000000..b8b835a4a --- /dev/null +++ b/regression-tests.recursor-dnssec/basicDNSSEC.py @@ -0,0 +1,69 @@ +import dns +from recursortests import RecursorTest +import os + +class BasicDNSSEC(RecursorTest): + __test__ = False + _config_template = """dnssec=validate""" + + @classmethod + def setUp(cls): + confdir = os.path.join('configs', cls._confdir) + cls.wipeRecursorCache(confdir) + + @classmethod + def sendQuery(self, name, rdtype): + """Helper function that creates the query""" + msg = dns.message.make_query(name, rdtype, want_dnssec=True) + msg.flags |= dns.flags.AD + + return self.sendUDPQuery(msg) + + def testSecureAnswer(self): + res = self.sendQuery('ns.secure.example.', 'A') + expected = dns.rrset.from_text('ns.secure.example.', 0, dns.rdataclass.IN, 'A', '{prefix}.10'.format(prefix=self._PREFIX)) + + self.assertRcodeEqual(res, dns.rcode.NOERROR) + self.assertMatchingRRSIGInAnswer(res, expected) + self.assertMessageIsAuthenticated(res) + + def testInsecureAnswer(self): + res = self.sendQuery('node1.insecure.example.', 'A') + + self.assertNoRRSIGsInAnswer(res) + self.assertRcodeEqual(res, dns.rcode.NOERROR) + + def testBogusAnswer(self): + res = self.sendQuery('ted.bogus.example.', 'A') + + self.assertRcodeEqual(res, dns.rcode.SERVFAIL) + self.assertAnswerEmpty(res) + + def testSecureNXDOMAIN(self): + res = self.sendQuery('nxdomain.secure.example.', 'A') + + self.assertRcodeEqual(res, dns.rcode.NXDOMAIN) + + def testInsecureNXDOMAIN(self): + res = self.sendQuery('nxdomain.insecure.example.', 'A') + + self.assertRcodeEqual(res, dns.rcode.NXDOMAIN) + + def testBogusNXDOMAIN(self): + res = self.sendQuery('nxdomain.bogus.example.', 'A') + + self.assertRcodeEqual(res, dns.rcode.SERVFAIL) + + def testSecureOptoutAnswer(self): + res = self.sendQuery('node1.secure.optout.example.', 'A') + expected = dns.rrset.from_text('node1.secure.optout.example.', 0, dns.rdataclass.IN, 'A', '192.0.2.8') + + self.assertRcodeEqual(res, dns.rcode.NOERROR) + self.assertMatchingRRSIGInAnswer(res, expected) + self.assertMessageIsAuthenticated(res) + + def testInsecureOptoutAnswer(self): + res = self.sendQuery('node1.insecure.optout.example.', 'A') + + self.assertRcodeEqual(res, dns.rcode.NOERROR) + self.assertNoRRSIGsInAnswer(res) diff --git a/regression-tests.recursor-dnssec/recursortests.py b/regression-tests.recursor-dnssec/recursortests.py index 3292705c3..493e5b330 100644 --- a/regression-tests.recursor-dnssec/recursortests.py +++ b/regression-tests.recursor-dnssec/recursortests.py @@ -85,6 +85,10 @@ ns.bogus.example. 3600 IN A {prefix}.12 insecure.example. 3600 IN NS ns.insecure.example. ns.insecure.example. 3600 IN A {prefix}.13 + +optout.example. 3600 IN NS ns1.optout.example. +optout.example. 3600 IN DS 59332 13 1 e664f886ae1b5df03d918bc1217d22afc29925b9 +ns1.optout.example. 3600 IN A {prefix}.14 """, 'secure.example': """ secure.example. 3600 IN SOA {soa} @@ -106,6 +110,32 @@ insecure.example. 3600 IN NS ns1.insecure.example. ns1.insecure.example. 3600 IN A {prefix}.13 node1.insecure.example. 3600 IN A 192.0.2.6 + """, + 'optout.example': """ +optout.example. 3600 IN SOA {soa} +optout.example. 3600 IN NS ns1.optout.example. +ns1.optout.example. 3600 IN A {prefix}.14 + +insecure.optout.example. 3600 IN NS ns1.insecure.optout.example. +ns1.insecure.optout.example. 3600 IN A {prefix}.15 + +secure.optout.example. 3600 IN NS ns1.secure.optout.example. +secure.optout.example. 3600 IN DS 64215 13 1 b88284d7a8d8605c398e8942262f97b9a5a31787 +ns1.secure.optout.example. 3600 IN A {prefix}.15 + """, + 'insecure.optout.example': """ +insecure.optout.example. 3600 IN SOA {soa} +insecure.optout.example. 3600 IN NS ns1.insecure.optout.example. +ns1.insecure.optout.example. 3600 IN A {prefix}.15 + +node1.insecure.optout.example. 3600 IN A 192.0.2.7 + """, + 'secure.optout.example': """ +secure.optout.example. 3600 IN SOA {soa} +secure.optout.example. 3600 IN NS ns1.secure.optout.example. +ns1.secure.optout.example. 3600 IN A {prefix}.15 + +node1.secure.optout.example. 3600 IN A 192.0.2.8 """ } @@ -135,6 +165,18 @@ Private-key-format: v1.2 Algorithm: 13 (ECDSAP256SHA256) PrivateKey: f5jV7Q8kd5hDpMWObsuQ6SQda0ftf+JrO3uZwEg6nVw= """, + + 'optout.example': """ +Private-key-format: v1.2 +Algorithm: 13 (ECDSAP256SHA256) +PrivateKey: efmq9G+J4Y2iPnIBRwJiy6Z/nIHSzpsCy/7XHhlS19A= + """, + + 'secure.optout.example': """ +Private-key-format: v1.2 +Algorithm: 13 (ECDSAP256SHA256) +PrivateKey: xcNUxt1Knj14A00lKQFDboluiJyM2f7FxpgsQaQ3AQ4= + """ } # This dict is keyed with the suffix of the IP address and its value @@ -146,7 +188,9 @@ PrivateKey: f5jV7Q8kd5hDpMWObsuQ6SQda0ftf+JrO3uZwEg6nVw= '10': ['example'], '11': ['example'], '12': ['bogus.example'], - '13': ['insecure.example'] + '13': ['insecure.example'], + '14': ['optout.example'], + '15': ['insecure.optout.example', 'secure.optout.example'] } _auth_cmd = ['authbind', @@ -257,10 +301,12 @@ distributor-threads=1""".format(confdir=confdir, cls.generateAuthConfig(authconfdir) cls.generateAuthNamedConf(authconfdir, zones) - for zonename, content in cls._zones.items(): - cls.generateAuthZone(authconfdir, zonename, content) - if cls._zone_keys.get(zonename, None): - cls.secureZone(authconfdir, zonename, cls._zone_keys.get(zonename)) + for zone in zones: + cls.generateAuthZone(authconfdir, + zone, + cls._zones[zone]) + if cls._zone_keys.get(zone, None): + cls.secureZone(authconfdir, zone, cls._zone_keys.get(zone)) @classmethod def startAllAuth(cls, confdir): @@ -273,7 +319,7 @@ distributor-threads=1""".format(confdir=confdir, @classmethod def startAuth(cls, confdir, ipaddress): print("Launching pdns_server..") - authcmd = cls._auth_cmd + authcmd = list(cls._auth_cmd) authcmd.append('--config-dir=%s' % confdir) authcmd.append('--local-address=%s' % ipaddress) print(' '.join(authcmd)) diff --git a/regression-tests.recursor-dnssec/test_basicNSEC.py b/regression-tests.recursor-dnssec/test_basicNSEC.py new file mode 100644 index 000000000..9987776d8 --- /dev/null +++ b/regression-tests.recursor-dnssec/test_basicNSEC.py @@ -0,0 +1,6 @@ +from basicDNSSEC import BasicDNSSEC +import unittest + +class basicNSEC(BasicDNSSEC): + __test__ = True + _confdir = 'basicNSEC' diff --git a/regression-tests.recursor-dnssec/test_basicNSEC3.py b/regression-tests.recursor-dnssec/test_basicNSEC3.py new file mode 100644 index 000000000..5185f5f22 --- /dev/null +++ b/regression-tests.recursor-dnssec/test_basicNSEC3.py @@ -0,0 +1,53 @@ +from basicDNSSEC import BasicDNSSEC +import os +import subprocess + +class basicNSEC3(BasicDNSSEC): + __test__ = True + _confdir = 'basicNSEC3' + + @classmethod + def secureZone(cls, confdir, zonename, key=None): + zone = '.' if zonename == 'ROOT' else zonename + if not key: + pdnsutilCmd = [os.environ['PDNSUTIL'], + '--config-dir=%s' % confdir, + 'secure-zone', + zone] + else: + keyfile = os.path.join(confdir, 'dnssec.key') + with open(keyfile, 'w') as fdKeyfile: + fdKeyfile.write(key) + + pdnsutilCmd = [os.environ['PDNSUTIL'], + '--config-dir=%s' % confdir, + 'import-zone-key', + zone, + keyfile, + 'active', + 'ksk'] + + print ' '.join(pdnsutilCmd) + try: + subprocess.check_output(pdnsutilCmd, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + print e.output + raise + + params = "1 0 100 AABBCCDDEEFF112233" + + if zone == "optout.example": + params = "1 1 100 AABBCCDDEEFF112233" + + pdnsutilCmd = [os.environ['PDNSUTIL'], + '--config-dir=%s' % confdir, + 'set-nsec3', + zone, + params] + + print ' '.join(pdnsutilCmd) + try: + subprocess.check_output(pdnsutilCmd, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + print e.output + raise