1 # Copyright (C) Internet Systems Consortium, Inc. ("ISC") 2 # 3 # SPDX-License-Identifier: MPL-2.0 4 # 5 # This Source Code Form is subject to the terms of the Mozilla Public 6 # License, v. 2.0. If a copy of the MPL was not distributed with this 7 # file, you can obtain one at https://mozilla.org/MPL/2.0/. 8 # 9 # See the COPYRIGHT file distributed with this work for additional 10 # information regarding copyright ownership. 11 12 import os 13 import re 14 from re import compile as Re 15 16 import pytest 17 18 import isctest 19 20 pytestmark = pytest.mark.extra_artifacts( 21 [ 22 "verify.out.*", 23 "zones/K*", 24 "zones/dsset-*", 25 "zones/*.bad", 26 "zones/*.good", 27 "zones/*.out*", 28 "zones/*.tmp", 29 "zones/updated*", 30 ] 31 ) 32 33 VERIFY = os.environ.get("VERIFY") 34 35 36 @pytest.mark.parametrize( 37 "zone", 38 [ 39 "ksk-only.nsec3", 40 "ksk-only.nsec", 41 "ksk+zsk.nsec3.apex-dname", 42 "ksk+zsk.nsec3", 43 "ksk+zsk.nsec.apex-dname", 44 "ksk+zsk.nsec", 45 "ksk+zsk.optout", 46 "zsk-only.nsec3", 47 "zsk-only.nsec", 48 ], 49 ) 50 def test_verify_good_zone_files(zone): 51 isctest.run.cmd([VERIFY, "-z", "-o", zone, f"zones/{zone}.good"]) 52 53 54 def test_verify_good_zone_nsec_next_name_case_mismatch(): 55 isctest.run.cmd( 56 [ 57 VERIFY, 58 "-o", 59 "nsec-next-name-case-mismatch", 60 "zones/nsec-next-name-case-mismatch.good", 61 ], 62 ) 63 64 65 def verify_bad_zone(zone): 66 only_opt = ["-z"] if re.search(r"^[zk]sk-only", zone) else [] 67 cmd = isctest.run.cmd( 68 [VERIFY, *only_opt, "-o", zone, f"zones/{zone}.bad"], 69 raise_on_exception=False, 70 ) 71 assert cmd.rc != 0 72 return cmd 73 74 75 @pytest.mark.parametrize( 76 "zone", 77 [ 78 "ksk-only.dnskeyonly", 79 "ksk+zsk.dnskeyonly", 80 "zsk-only.dnskeyonly", 81 ], 82 ) 83 def test_verify_bad_zone_files_dnskeyonly(zone): 84 cmd = verify_bad_zone(zone) 85 assert "DNSKEY is not signed" in cmd.err 86 87 88 @pytest.mark.parametrize( 89 "zone", 90 [ 91 "ksk-only.nsec3.expired", 92 "ksk-only.nsec.expired", 93 "ksk+zsk.nsec3.expired", 94 "ksk+zsk.nsec.expired", 95 "ksk+zsk.nsec.ksk-expired", 96 "zsk-only.nsec3.expired", 97 "zsk-only.nsec.expired", 98 "ksk+zsk.nsec3.ksk-expired", 99 ], 100 ) 101 def test_verify_bad_zone_files_expired(zone): 102 cmd = verify_bad_zone(zone) 103 assert Re("signature has expired|No self-signed DNSKEY found") in cmd.err 104 105 106 @pytest.mark.parametrize( 107 "zone", 108 [ 109 "ksk+zsk.nsec.out-of-zone-nsec", 110 "ksk+zsk.nsec.below-bottom-of-zone-nsec", 111 "ksk+zsk.nsec.below-dname-nsec", 112 ], 113 ) 114 def test_verify_bad_zone_files_unexpected_nsec_rrset(zone): 115 cmd = verify_bad_zone(zone) 116 assert "unexpected NSEC RRset at" in cmd.err 117 118 119 def test_verify_bad_zone_files_bad_nsec_record(): 120 cmd = verify_bad_zone("ksk+zsk.nsec.broken-chain") 121 assert Re("Bad NSEC record for.*, next name mismatch") in cmd.err 122 123 124 def test_verify_bad_zone_files_bad_bitmap(): 125 cmd = verify_bad_zone("ksk+zsk.nsec.bad-bitmap") 126 assert "bit map mismatch" in cmd.err 127 128 129 def test_verify_bad_zone_files_missing_nsec3_record(): 130 cmd = verify_bad_zone("ksk+zsk.nsec3.missing-empty") 131 assert "Missing NSEC3 record for" in cmd.err 132 133 134 def test_verify_bad_zone_files_no_dnssec_keys(): 135 cmd = verify_bad_zone("unsigned") 136 assert "Zone contains no DNSSEC keys" in cmd.err 137 138 139 def test_verify_bad_zone_files_unequal_nsec3_chains(): 140 cmd = verify_bad_zone("ksk+zsk.nsec3.extra-nsec3") 141 assert "Expected and found NSEC3 chains not equal" in cmd.err 142 143 144 # checking error message when -o is not used 145 # and a SOA record not at top of zone is found 146 def test_verify_soa_not_at_top_error(): 147 # when -o is not used, origin is set to zone file name, 148 # which should cause an error in this case 149 cmd = isctest.run.cmd([VERIFY, "zones/ksk+zsk.nsec.good"], raise_on_exception=False) 150 assert "not at top of zone" in cmd.err 151 assert "use -o to specify a different zone origin" in cmd.err 152 153 154 # checking error message when an invalid -o is specified 155 # and a SOA record not at top of zone is found 156 def test_verify_invalid_o_option_soa_not_at_top_error(): 157 cmd = isctest.run.cmd( 158 [VERIFY, "-o", "invalid.origin", "zones/ksk+zsk.nsec.good"], 159 raise_on_exception=False, 160 ) 161 assert "not at top of zone" in cmd.err 162 assert "use -o to specify a different zone origin" not in cmd.err 163 164 165 # checking dnssec-verify -J reads journal file 166 def test_verify_j_reads_journal_file(): 167 cmd = isctest.run.cmd( 168 [ 169 VERIFY, 170 "-o", 171 "updated", 172 "-J", 173 "zones/updated.other.jnl", 174 "zones/updated.other", 175 ] 176 ) 177 assert "Loading zone 'updated' from file 'zones/updated.other'" in cmd.out 178