invalid_dsa.py 2.75 KB
Newer Older
1 2 3 4 5 6 7
"""Returns 1 if there is a DNSSEC DSA signature which is not 41 bytes long.\
0 otherwise.
"""

import os
import sys
import argparse
8
import dns
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
import pydnstest
import pydnstest.scenario
import pydnstest.augwrap


def parse(test):
    """ Parse the test"""
    _, config = pydnstest.scenario.parse_file(os.path.realpath(test))
    aug = pydnstest.augwrap.AugeasWrapper(
        confpath=os.path.realpath(test),
        lens='Deckard', loadpath="../pydnstest")
    node = aug.tree
    return config, node


def get_dsakeys(config, node):
    """ Make list of all DSA keys in the test"""
    dsakeys = []
    for conf in config:
        if conf[0] == "trust-anchor":
            conf[1] = conf[1][1:-1]
            trust_anchor = conf[1].split()
            for i, word in enumerate(trust_anchor):
                if word == "DS":
                    algorithm = trust_anchor[i + 2]
                    if algorithm == "3" or algorithm == "DSA":
                        dsakeys.append(trust_anchor[i + 1])

    for entry in node.match("/scenario/range/entry"):
        records = list(entry.match("/section/answer/record"))
        records.extend(list(entry.match("/section/authority/record")))
        records.extend(list(entry.match("/section/additional/record")))

        for record in records:
            if record["/type"].value == "DS":
                if record["/data"].value[1] in ["3", "DSA"]:
                    dsakeys.append(record["/data"].value[2])
    return dsakeys


def check_rrsig(node, dsakeys):
    """ Find records with wrong lenght of rrsig"""
51
    for key in dsakeys:  # pylint: disable=too-many-nested-blocks
52 53 54 55 56 57 58
        for entry in node.match("/scenario/range/entry"):
            records = list(entry.match("/section/answer/record"))
            records.extend(list(entry.match("/section/authority/record")))
            records.extend(list(entry.match("/section/additional/record")))

            for record in records:
                if record["/type"].value == "RRSIG":
59 60 61 62 63
                    rrset = dns.rrset.from_text(record["/domain"].value, 300,
                                                1, dns.rdatatype.RRSIG,
                                                record["/data"].value)
                    if rrset.items[0].key_tag == int(key):
                        if len(rrset.items[0].signature) != 41:
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
                            return True
    return False


def main():
    """Returns 1 if there is a DNSSEC DSA signature which is not 41 bytes long. \
    0 otherwise."""
    argparser = argparse.ArgumentParser()
    argparser.add_argument("file")
    args = argparser.parse_args()
    config, node = parse(args.file)
    dsakeys = get_dsakeys(config, node)
    bad_rrsig = check_rrsig(node, dsakeys)
    if bad_rrsig:
        sys.exit(1)
    else:
        sys.exit(0)

main()