# Copyright (C) Internet Systems Consortium, Inc. ("ISC") # # SPDX-License-Identifier: MPL-2.0 # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, you can obtain one at https://mozilla.org/MPL/2.0/. # # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. import os import dns.message import dns.zone import pytest import isctest pytestmark = pytest.mark.extra_artifacts( [ "ns2/copied.db", "ns2/present.db", "ns2/alternate.db", "ns2/extra1.db", "ns2/extra2.db", ] ) def test_masterfile_include_semantics(): """Test master file $INCLUDE semantics""" msg_axfr = isctest.query.create("include.", "AXFR") res_axfr = isctest.query.tcp(msg_axfr, "10.53.0.1") axfr_include_semantics = """;ANSWER include. 300 IN SOA ns.include. hostmaster.include. 1 3600 1800 1814400 3600 include. 300 IN NS ns.include. a.include. 300 IN A 10.0.0.1 a.include. 300 IN A 10.0.0.99 a.a.include. 300 IN A 10.0.1.1 b.foo.a.include. 300 IN A 10.0.2.2 b.include. 300 IN A 10.0.0.2 a.b.include. 300 IN A 10.0.1.1 c.b.include. 300 IN A 10.0.0.3 b.foo.b.include. 300 IN A 10.0.2.2 ns.include. 300 IN A 127.0.0.1 """ expected = dns.message.from_text(axfr_include_semantics) isctest.check.rrsets_equal(res_axfr.answer, expected.answer, compare_ttl=True) def test_masterfile_bind_8_compat_semantics(): """Test master file BIND 8 TTL and $TTL semantics compatibility""" msg_axfr = isctest.query.create("ttl1.", "AXFR") res_axfr = isctest.query.tcp(msg_axfr, "10.53.0.1") axfr_ttl_semantics = """;ANSWER ttl1. 3 IN SOA ns.ttl1. hostmaster.ttl1. 1 3600 1800 1814400 3 ttl1. 3 IN NS ns.ttl1. a.ttl1. 3 IN TXT "soa minttl 3" b.ttl1. 2 IN TXT "explicit ttl 2" c.ttl1. 3 IN TXT "soa minttl 3" d.ttl1. 1 IN TXT "default ttl 1" e.ttl1. 4 IN TXT "explicit ttl 4" f.ttl1. 1 IN TXT "default ttl 1" ns.ttl1. 3 IN A 10.53.0.1 """ expected = dns.message.from_text(axfr_ttl_semantics) isctest.check.rrsets_equal(res_axfr.answer, expected.answer, compare_ttl=True) def test_masterfile_rfc_1035_semantics(): """Test master file RFC1035 TTL and $TTL semantics""" msg_axfr = isctest.query.create("ttl2.", "AXFR") res_axfr = isctest.query.tcp(msg_axfr, "10.53.0.1") axfr_ttl_semantics = """;ANSWER ttl2. 1 IN SOA ns.ttl2. hostmaster.ttl2. 1 3600 1800 1814400 3 ttl2. 1 IN NS ns.ttl2. a.ttl2. 1 IN TXT "inherited ttl 1" b.ttl2. 2 IN TXT "explicit ttl 2" c.ttl2. 2 IN TXT "inherited ttl 2" d.ttl2. 3 IN TXT "default ttl 3" e.ttl2. 2 IN TXT "explicit ttl 2" f.ttl2. 3 IN TXT "default ttl 3" ns.ttl2. 1 IN A 10.53.0.1 """ expected = dns.message.from_text(axfr_ttl_semantics) isctest.check.rrsets_equal(res_axfr.answer, expected.answer, compare_ttl=True) def test_masterfile_missing_master_file(): """Test nameserver running with a missing master file""" msg_soa = isctest.query.create("example.", "SOA") res_soa = isctest.query.tcp(msg_soa, "10.53.0.2") expected_soa_rr = """;ANSWER example. 300 IN SOA mname1. . 2010042407 20 20 1814400 3600 """ expected = dns.message.from_text(expected_soa_rr) isctest.check.rrsets_equal(res_soa.answer, expected.answer, compare_ttl=True) def test_masterfile_initial_file(): """Test zone configurations with initial template files""" # example inherited its configuration from the template, # make sure it works msg_soa = isctest.query.create("example.", "SOA") res_soa = isctest.query.tcp(msg_soa, "10.53.0.2") expected_soa_rr = """;ANSWER example. 300 IN SOA mname1. . 2010042407 20 20 1814400 3600 """ expected = dns.message.from_text(expected_soa_rr) isctest.check.rrsets_equal(res_soa.answer, expected.answer) # initial uses an initial-file option with the "file" # option set to "copied.db". make sure it works and that # copied.db has been populated. msg_soa = isctest.query.create("initial.", "SOA") res_soa = isctest.query.tcp(msg_soa, "10.53.0.2") expected_soa_rr = """;ANSWER initial. 300 IN SOA mname1. . 2010042407 20 20 1814400 3600 """ expected = dns.message.from_text(expected_soa_rr) isctest.check.rrsets_equal(res_soa.answer, expected.answer) isctest.check.file_contents_equal("ns2/example.db", "ns2/copied.db") # present uses an initial-file option, but the file 'present.db' # already exists and is empty, so the initial-file should not be # copied into place and the zone should not load. msg_soa = isctest.query.create("present.", "SOA") res_soa = isctest.query.tcp(msg_soa, "10.53.0.2") isctest.check.servfail(res_soa) isctest.check.file_empty("ns2/present.db") def test_masterfile_template_override(): """Test zone configurations with overridden template options""" # different inherited configuration from the template, but # overrides the "file" option to 'alternate.db'. msg_soa = isctest.query.create("different.", "SOA") res_soa = isctest.query.tcp(msg_soa, "10.53.0.2") expected_soa_rr = """;ANSWER different. 300 IN SOA mname1. . 2010042407 20 20 1814400 3600 """ expected = dns.message.from_text(expected_soa_rr) isctest.check.rrsets_equal(res_soa.answer, expected.answer) isctest.check.file_contents_equal("ns2/example.db", "ns2/alternate.db") assert not os.path.exists("ns2/different.db") def test_masterfile_missing_master_file_servfail(): """Test nameserver returning SERVFAIL for a missing master file""" msg_soa = isctest.query.create("missing.", "SOA") res_soa = isctest.query.tcp(msg_soa, "10.53.0.2") isctest.check.servfail(res_soa) def test_masterfile_owner_inheritance(): """Test owner inheritance after $INCLUDE""" cmd = isctest.run.cmd( [ os.environ["CHECKZONE"], "-D", "-q", "example", "zone/inheritownerafterinclude.db", ] ) owner_inheritance_zone = """ example. 0 IN SOA . . 0 0 0 0 0 example. 0 IN TXT "this should be at the zone apex" example. 0 IN NS . """ checker_zone = dns.zone.from_text(cmd.out, origin="example.") expected = dns.zone.from_text(owner_inheritance_zone, origin="example.") isctest.check.zones_equal(checker_zone, expected, compare_ttl=True)