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