diff options
author | Casey Deccio <casey@deccio.net> | 2021-01-09 03:29:50 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-09 03:29:50 +0300 |
commit | bdaa08fb28b4821f11a3f82c775b26f11ac56b80 (patch) | |
tree | e03caa4a161530cc2dd9150460a62aef0d8ebd42 | |
parent | 2e3cb9b0893e16fc764cb45c0676dcd009d8cfc0 (diff) | |
parent | f0e697b1d837f63299aa79d6152742bfd2dc9926 (diff) |
Merge pull request #69 from dnsviz/obsoletealg
Obsoletealg
-rw-r--r-- | dnsviz/analysis/errors.py | 108 | ||||
-rw-r--r-- | dnsviz/analysis/offline.py | 49 | ||||
-rw-r--r-- | dnsviz/analysis/status.py | 120 | ||||
-rw-r--r-- | dnsviz/commands/graph.py | 6 | ||||
-rw-r--r-- | dnsviz/commands/grok.py | 6 | ||||
-rw-r--r-- | dnsviz/commands/print.py | 6 | ||||
-rw-r--r-- | doc/man/dnsviz-graph.1 | 8 | ||||
-rw-r--r-- | doc/man/dnsviz-grok.1 | 8 | ||||
-rw-r--r-- | doc/man/dnsviz-print.1 | 8 |
9 files changed, 268 insertions, 51 deletions
diff --git a/dnsviz/analysis/errors.py b/dnsviz/analysis/errors.py index c9da104..4ad5769 100644 --- a/dnsviz/analysis/errors.py +++ b/dnsviz/analysis/errors.py @@ -252,6 +252,63 @@ class AlgorithmNotSupported(RRSIGError): super(AlgorithmNotSupported, self).__init__(**kwargs) self.template_kwargs['algorithm_text'] = dns.dnssec.algorithm_to_text(self.template_kwargs['algorithm']) +class AlgorithmValidationProhibited(RRSIGError): + ''' + >>> e = AlgorithmValidationProhibited(algorithm=5) + >>> e.args + [5] + >>> e.description + 'DNSSEC specification prohibits validation of RRSIGs with DNSSEC algorithm 5 (RSASHA1).' + ''' + + _abstract = False + code = 'ALGORITHM_VALIDATION_PROHIBITED' + description_template = "DNSSEC specification prohibits validation of RRSIGs with DNSSEC algorithm %(algorithm)d (%(algorithm_text)s)." + references = ['RFC 8624, Sec. 3.1'] + required_params = ['algorithm'] + + def __init__(self, **kwargs): + super(AlgorithmValidationProhibited, self).__init__(**kwargs) + self.template_kwargs['algorithm_text'] = dns.dnssec.algorithm_to_text(self.template_kwargs['algorithm']) + +class AlgorithmProhibited(RRSIGError): + ''' + >>> e = AlgorithmProhibited(algorithm=5) + >>> e.args + [5] + >>> e.description + 'DNSSEC specification prohibits signing with DNSSEC algorithm 5 (RSASHA1).' + ''' + + _abstract = False + code = 'ALGORITHM_PROHIBITED' + description_template = "DNSSEC specification prohibits signing with DNSSEC algorithm %(algorithm)d (%(algorithm_text)s)." + references = ['RFC 8624, Sec. 3.1'] + required_params = ['algorithm'] + + def __init__(self, **kwargs): + super(AlgorithmProhibited, self).__init__(**kwargs) + self.template_kwargs['algorithm_text'] = dns.dnssec.algorithm_to_text(self.template_kwargs['algorithm']) + +class AlgorithmNotRecommended(RRSIGError): + ''' + >>> e = AlgorithmNotRecommended(algorithm=5) + >>> e.args + [5] + >>> e.description + 'DNSSEC specification recommends not signing with DNSSEC algorithm 5 (RSASHA1).' + ''' + + _abstract = False + code = 'ALGORITHM_NOT_RECOMMENDED' + description_template = "DNSSEC specification recommends not signing with DNSSEC algorithm %(algorithm)d (%(algorithm_text)s)." + references = ['RFC 8624, Sec. 3.1'] + required_params = ['algorithm'] + + def __init__(self, **kwargs): + super(AlgorithmNotRecommended, self).__init__(**kwargs) + self.template_kwargs['algorithm_text'] = dns.dnssec.algorithm_to_text(self.template_kwargs['algorithm']) + class DNSKEYRevokedRRSIG(RRSIGError): ''' >>> e = DNSKEYRevokedRRSIG() @@ -514,6 +571,57 @@ class DigestAlgorithmNotSupported(DSDigestError): super(DigestAlgorithmNotSupported, self).__init__(**kwargs) self.template_kwargs['algorithm_text'] = fmt.DS_DIGEST_TYPES.get(self.template_kwargs['algorithm'], self.template_kwargs['algorithm']) +class DigestAlgorithmValidationProhibited(DSDigestError): + ''' + >>> e = DigestAlgorithmValidationProhibited(algorithm=5) + >>> e.description + 'DNSSEC specification prohibits validation of DS records that use digest algorithm 5 (5).' + ''' + + _abstract = False + code = 'DIGEST_ALGORITHM_VALIDATION_PROHIBITED' + description_template = "DNSSEC specification prohibits validation of DS records that use digest algorithm %(algorithm)d (%(algorithm_text)s)." + references = ['RFC 8624, Sec. 3.2'] + required_params = ['algorithm'] + + def __init__(self, **kwargs): + super(DigestAlgorithmValidationProhibited, self).__init__(**kwargs) + self.template_kwargs['algorithm_text'] = fmt.DS_DIGEST_TYPES.get(self.template_kwargs['algorithm'], self.template_kwargs['algorithm']) + +class DigestAlgorithmProhibited(DSDigestError): + ''' + >>> e = DigestAlgorithmProhibited(algorithm=5) + >>> e.description + 'DNSSEC specification prohibits signing with DS records that use digest algorithm 5 (5).' + ''' + + _abstract = False + code = 'DIGEST_ALGORITHM_PROHIBITED' + description_template = "DNSSEC specification prohibits signing with DS records that use digest algorithm %(algorithm)d (%(algorithm_text)s)." + references = ['RFC 8624, Sec. 3.2'] + required_params = ['algorithm'] + + def __init__(self, **kwargs): + super(DigestAlgorithmProhibited, self).__init__(**kwargs) + self.template_kwargs['algorithm_text'] = fmt.DS_DIGEST_TYPES.get(self.template_kwargs['algorithm'], self.template_kwargs['algorithm']) + +class DigestAlgorithmNotRecommended(DSDigestError): + ''' + >>> e = DigestAlgorithmNotRecommended(algorithm=5) + >>> e.description + 'DNSSEC specification recommends not signing with DS records that use digest algorithm 5 (5).' + ''' + + _abstract = False + code = 'DIGEST_ALGORITHM_NOT_RECOMMENDED' + description_template = "DNSSEC specification recommends not signing with DS records that use digest algorithm %(algorithm)d (%(algorithm_text)s)." + references = ['RFC 8624, Sec. 3.2'] + required_params = ['algorithm'] + + def __init__(self, **kwargs): + super(DigestAlgorithmNotRecommended, self).__init__(**kwargs) + self.template_kwargs['algorithm_text'] = fmt.DS_DIGEST_TYPES.get(self.template_kwargs['algorithm'], self.template_kwargs['algorithm']) + class DNSKEYRevokedDS(DSDigestError): ''' >>> e = DNSKEYRevokedDS() diff --git a/dnsviz/analysis/offline.py b/dnsviz/analysis/offline.py index 7d08a83..dcfc58a 100644 --- a/dnsviz/analysis/offline.py +++ b/dnsviz/analysis/offline.py @@ -27,6 +27,7 @@ from __future__ import unicode_literals +import copy import errno import logging @@ -787,7 +788,7 @@ class OfflineDomainNameAnalysis(OnlineDomainNameAnalysis): (not x.effective_tcp and x.udp_responsive)) and \ (not require_valid or x.is_valid_response())) - def populate_status(self, trusted_keys, supported_algs=None, supported_digest_algs=None, is_dlv=False, trace=None, follow_mx=True): + def _populate_status(self, trusted_keys, supported_algs=None, supported_digest_algs=None, is_dlv=False, trace=None, follow_mx=True): if trace is None: trace = [] @@ -804,40 +805,29 @@ class OfflineDomainNameAnalysis(OnlineDomainNameAnalysis): if self.stub: return - # identify supported algorithms as intersection of explicitly supported - # and software supported - if supported_algs is not None: - supported_algs.intersection_update(crypto._supported_algs) - else: - supported_algs = crypto._supported_algs - if supported_digest_algs is not None: - supported_digest_algs.intersection_update(crypto._supported_digest_algs) - else: - supported_digest_algs = crypto._supported_digest_algs - # populate status of dependencies for cname in self.cname_targets: for target, cname_obj in self.cname_targets[cname].items(): if cname_obj is not None: - cname_obj.populate_status(trusted_keys, supported_algs, supported_digest_algs, trace=trace + [self]) + cname_obj._populate_status(trusted_keys, supported_algs, supported_digest_algs, trace=trace + [self]) if follow_mx: for target, mx_obj in self.mx_targets.items(): if mx_obj is not None: - mx_obj.populate_status(trusted_keys, supported_algs, supported_digest_algs, trace=trace + [self], follow_mx=False) + mx_obj._populate_status(trusted_keys, supported_algs, supported_digest_algs, trace=trace + [self], follow_mx=False) for signer, signer_obj in self.external_signers.items(): if signer_obj is not None: - signer_obj.populate_status(trusted_keys, supported_algs, supported_digest_algs, trace=trace + [self]) + signer_obj._populate_status(trusted_keys, supported_algs, supported_digest_algs, trace=trace + [self]) for target, ns_obj in self.ns_dependencies.items(): if ns_obj is not None: - ns_obj.populate_status(trusted_keys, supported_algs, supported_digest_algs, trace=trace + [self]) + ns_obj._populate_status(trusted_keys, supported_algs, supported_digest_algs, trace=trace + [self]) # populate status of ancestry if self.nxdomain_ancestor is not None: - self.nxdomain_ancestor.populate_status(trusted_keys, supported_algs, supported_digest_algs, trace=trace + [self]) + self.nxdomain_ancestor._populate_status(trusted_keys, supported_algs, supported_digest_algs, trace=trace + [self]) if self.parent is not None: - self.parent.populate_status(trusted_keys, supported_algs, supported_digest_algs, trace=trace + [self]) + self.parent._populate_status(trusted_keys, supported_algs, supported_digest_algs, trace=trace + [self]) if self.dlv_parent is not None: - self.dlv_parent.populate_status(trusted_keys, supported_algs, supported_digest_algs, is_dlv=True, trace=trace + [self]) + self.dlv_parent._populate_status(trusted_keys, supported_algs, supported_digest_algs, is_dlv=True, trace=trace + [self]) _logger.debug('Assessing status of %s...' % (fmt.humanize_name(self.name))) self._populate_name_status() @@ -853,6 +843,25 @@ class OfflineDomainNameAnalysis(OnlineDomainNameAnalysis): self._populate_ds_status(dns.rdatatype.DLV, supported_algs, supported_digest_algs) self._populate_dnskey_status(trusted_keys) + def populate_status(self, trusted_keys, supported_algs=None, supported_digest_algs=None, is_dlv=False, follow_mx=True, validate_prohibited_algs=False): + # identify supported algorithms as intersection of explicitly supported + # and software supported + if supported_algs is not None: + supported_algs.intersection_update(crypto._supported_algs) + else: + supported_algs = copy.copy(crypto._supported_algs) + if supported_digest_algs is not None: + supported_digest_algs.intersection_update(crypto._supported_digest_algs) + else: + supported_digest_algs = copy.copy(crypto._supported_digest_algs) + + # unless we are overriding, mark prohibited algorithms as not supported + if not validate_prohibited_algs: + supported_algs.difference_update(Status.DNSKEY_ALGS_VALIDATION_PROHIBITED) + supported_digest_algs.difference_update(Status.DS_DIGEST_ALGS_VALIDATION_PROHIBITED) + + self._populate_status(trusted_keys, supported_algs, supported_digest_algs, is_dlv, None, follow_mx) + def _populate_name_status(self, trace=None): # using trace allows _populate_name_status to be called independent of # populate_status @@ -2112,7 +2121,7 @@ class OfflineDomainNameAnalysis(OnlineDomainNameAnalysis): # is bogus because there should have been matching KSK. self.delegation_status[rdtype] = Status.DELEGATION_STATUS_BOGUS else: - # If no algorithsm are supported, then this is a + # If no algorithms are supported, then this is a # provably insecure delegation. self.delegation_status[rdtype] = Status.DELEGATION_STATUS_INSECURE else: diff --git a/dnsviz/analysis/status.py b/dnsviz/analysis/status.py index a2197a8..6a68af4 100644 --- a/dnsviz/analysis/status.py +++ b/dnsviz/analysis/status.py @@ -169,6 +169,16 @@ RRSIG_SIG_LENGTH_ERRORS = { DS_DIGEST_ALGS_STRONGER_THAN_SHA1 = (2, 4) DS_DIGEST_ALGS_IGNORING_SHA1 = (2,) +# RFC 8624 Section 3.1 +DNSKEY_ALGS_NOT_RECOMMENDED = (5, 7, 10) +DNSKEY_ALGS_PROHIBITED = (1, 3, 6, 12) +DNSKEY_ALGS_VALIDATION_PROHIBITED = (1, 3, 6) + +# RFC 8624 Section 3.2 +DS_DIGEST_ALGS_NOT_RECOMMENDED = () +DS_DIGEST_ALGS_PROHIBITED = (0, 1, 3) +DS_DIGEST_ALGS_VALIDATION_PROHIBITED = () + class RRSIGStatus(object): def __init__(self, rrset, rrsig, dnskey, zone_name, reference_ts, supported_algs): self.rrset = rrset @@ -186,13 +196,44 @@ class RRSIGStatus(object): self.validation_status = RRSIG_STATUS_VALID if self.signature_valid is None or self.dnskey.rdata.algorithm not in supported_algs: + # Either we can't validate the cryptographic signature, or we are + # explicitly directed to ignore the algorithm. if self.dnskey is None: + # In this case, there is no corresponding DNSKEY, so we make + # the status "INDETERMINATE". if self.validation_status == RRSIG_STATUS_VALID: self.validation_status = RRSIG_STATUS_INDETERMINATE_NO_DNSKEY + else: - if self.validation_status == RRSIG_STATUS_VALID: - self.validation_status = RRSIG_STATUS_INDETERMINATE_UNKNOWN_ALGORITHM - self.warnings.append(Errors.AlgorithmNotSupported(algorithm=self.rrsig.algorithm)) + # If there is a DNSKEY, then we look at *why* we are ignoring + # the cryptographic signature. + if self.dnskey.rdata.algorithm in DNSKEY_ALGS_VALIDATION_PROHIBITED: + # In this case, specification dictates that the algorithm + # MUST NOT be validated, so we mark it as ignored. + if self.validation_status == RRSIG_STATUS_VALID: + self.validation_status = RRSIG_STATUS_ALGORITHM_IGNORED + else: + # In this case, we can't validate this particular + # algorithm, either because the code doesn't support it, + # or because we have been explicitly directed to ignore it. + # In either case, mark it as "UNKNOWN", and warn that it is + # not supported. + if self.validation_status == RRSIG_STATUS_VALID: + self.validation_status = RRSIG_STATUS_INDETERMINATE_UNKNOWN_ALGORITHM + self.warnings.append(Errors.AlgorithmNotSupported(algorithm=self.rrsig.algorithm)) + + # Independent of whether or not we considered the cryptographic + # validation, issue a warning if we are using an algorithm for which + # validation or signing has been prohibited. + # + # Signing is prohibited + if self.dnskey.rdata.algorithm in DNSKEY_ALGS_VALIDATION_PROHIBITED: + self.warnings.append(Errors.AlgorithmValidationProhibited(algorithm=self.rrsig.algorithm)) + # Validation is prohibited or, at least, not recommended + if self.dnskey.rdata.algorithm in DNSKEY_ALGS_PROHIBITED: + self.warnings.append(Errors.AlgorithmProhibited(algorithm=self.rrsig.algorithm)) + elif self.dnskey.rdata.algorithm in DNSKEY_ALGS_NOT_RECOMMENDED: + self.warnings.append(Errors.AlgorithmNotRecommended(algorithm=self.rrsig.algorithm)) if self.rrset.ttl_cmp: if self.rrset.rrset.ttl != self.rrset.rrsig_info[self.rrsig].ttl: @@ -351,13 +392,43 @@ class DSStatus(object): self.validation_status = DS_STATUS_VALID if self.digest_valid is None or self.ds.digest_type not in supported_digest_algs: + # Either we cannot reproduce a digest with this type, or we are + # explicitly directed to ignore the digest type. if self.dnskey is None: + # In this case, there is no corresponding DNSKEY, so we make + # the status "INDETERMINATE". if self.validation_status == DS_STATUS_VALID: self.validation_status = DS_STATUS_INDETERMINATE_NO_DNSKEY else: - if self.validation_status == DS_STATUS_VALID: - self.validation_status = DS_STATUS_INDETERMINATE_UNKNOWN_ALGORITHM - self.warnings.append(Errors.DigestAlgorithmNotSupported(algorithm=ds.digest_type)) + # If there is a DNSKEY, then we look at *why* we are ignoring + # the digest of the DNSKEY. + if self.ds.digest_type in DS_DIGEST_ALGS_VALIDATION_PROHIBITED: + # In this case, specification dictates that the algorithm + # MUST NOT be validated, so we mark it as ignored. + if self.validation_status == DS_STATUS_VALID: + self.validation_status = DS_STATUS_ALGORITHM_IGNORED + else: + # In this case, we can't validate this particular + # digest type, either because the code doesn't support it, + # or because we have been explicitly directed to ignore it. + # In either case, mark it as "UNKNOWN", and warn that it is + # not supported. + if self.validation_status == DS_STATUS_VALID: + self.validation_status = DS_STATUS_INDETERMINATE_UNKNOWN_ALGORITHM + self.warnings.append(Errors.DigestAlgorithmNotSupported(algorithm=self.ds.digest_type)) + + # Independent of whether or not we considered the digest for + # validation, issue a warning if we are using a digest type for which + # validation or signing has been prohibited. + # + # Signing is prohibited + if self.ds.digest_type in DS_DIGEST_ALGS_VALIDATION_PROHIBITED: + self.warnings.append(Errors.DigestAlgorithmValidationProhibited(algorithm=self.ds.digest_type)) + # Validation is prohibited or, at least, not recommended + if self.ds.digest_type in DS_DIGEST_ALGS_PROHIBITED: + self.warnings.append(Errors.DigestAlgorithmProhibited(algorithm=self.ds.digest_type)) + elif self.ds.digest_type in DS_DIGEST_ALGS_NOT_RECOMMENDED: + self.warnings.append(Errors.DigestAlgorithmNotRecommended(algorithm=self.ds.digest_type)) if self.dnskey is not None and \ self.dnskey.rdata.flags & fmt.DNSKEY_FLAGS['revoke']: @@ -378,33 +449,26 @@ class DSStatus(object): # RFC 4509 if self.ds.digest_type == 1: - digest_algs = set() - my_digest_algs = {} + stronger_algs_all_ds = set() + # Cycle through all other DS records in the DS RRset, and + # create a list of digest types that are stronger than SHA1 + # and are being used by DS records across the *entire* DS. for ds_rdata in self.ds_meta.rrset: - digest_algs.add(ds_rdata.digest_type) - if (ds_rdata.algorithm, ds_rdata.key_tag) == (self.ds.algorithm, self.ds.key_tag): - # Here we produce a status of the DS with algorithm 2 with - # respect to the DNSKEY for comparison with the current DS - # with algorithm 1. It is possible that the DS with the - # different digest type matches a different DNSKEY than the - # present DNSKEY. If it does, there will be a warning, but - # it should be both rare and innocuous. - if ds_rdata.digest_type == self.ds.digest_type: - continue - elif ds_rdata.digest_type not in my_digest_algs or \ - my_digest_algs[ds_rdata.digest_type].validation_status != DS_STATUS_VALID: - my_digest_algs[ds_rdata.digest_type] = \ - DSStatus(ds_rdata, self.ds_meta, self.dnskey, supported_digest_algs) - - for digest_alg in DS_DIGEST_ALGS_STRONGER_THAN_SHA1: - if digest_alg in supported_digest_algs and digest_alg in digest_algs and \ - (digest_alg not in my_digest_algs or my_digest_algs[digest_alg].validation_status not in \ - (DS_STATUS_VALID, DS_STATUS_INDETERMINATE_NO_DNSKEY, DS_STATUS_INDETERMINATE_UNKNOWN_ALGORITHM, DS_STATUS_INDETERMINATE_MATCH_PRE_REVOKE)): + if ds_rdata.digest_type in DS_DIGEST_ALGS_STRONGER_THAN_SHA1: + stronger_algs_all_ds.add(ds_rdata.digest_type) + + # Consider only digest types that we actually support + stronger_algs_all_ds.intersection_update(supported_digest_algs) + if stronger_algs_all_ds: + # If there are DS records in the DS RRset with digest type + # stronger than SHA1, then this one MUST be ignored by + # validators (RFC 4509). + for digest_alg in stronger_algs_all_ds: if digest_alg in DS_DIGEST_ALGS_IGNORING_SHA1: - self.warnings.append(Errors.DSDigestAlgorithmIgnored(algorithm=1, new_algorithm=digest_alg)) if self.validation_status == DS_STATUS_VALID: self.validation_status = DS_STATUS_ALGORITHM_IGNORED + self.warnings.append(Errors.DSDigestAlgorithmIgnored(algorithm=1, new_algorithm=digest_alg)) else: self.warnings.append(Errors.DSDigestAlgorithmMaybeIgnored(algorithm=1, new_algorithm=digest_alg)) diff --git a/dnsviz/commands/graph.py b/dnsviz/commands/graph.py index 8beb188..13558e0 100644 --- a/dnsviz/commands/graph.py +++ b/dnsviz/commands/graph.py @@ -198,6 +198,10 @@ class GraphArgHelper: type=self.comma_separated_ints_set, action='store', metavar='<digest_alg>,[<digest_alg>...]', help='Support only the specified DNSSEC digest algorithm(s)') + self.parser.add_argument('-b', '--validate-prohibited-algs', + const=True, default=False, + action='store_const', + help='Validate algorithms for which validation is otherwise prohibited') self.parser.add_argument('-C', '--enforce-cookies', const=True, default=False, action='store_const', @@ -457,7 +461,7 @@ def main(argv): G = DNSAuthGraph() for name_obj in name_objs: - name_obj.populate_status(arghelper.trusted_keys, supported_algs=arghelper.args.algorithms, supported_digest_algs=arghelper.args.digest_algorithms) + name_obj.populate_status(arghelper.trusted_keys, supported_algs=arghelper.args.algorithms, supported_digest_algs=arghelper.args.digest_algorithms, validate_prohibited_algs=arghelper.args.validate_prohibited_algs) for qname, rdtype in name_obj.queries: if arghelper.args.rr_types is None: # if rdtypes was not specified, then graph all, with some diff --git a/dnsviz/commands/grok.py b/dnsviz/commands/grok.py index 37e612f..14fefc1 100644 --- a/dnsviz/commands/grok.py +++ b/dnsviz/commands/grok.py @@ -221,6 +221,10 @@ class GrokArgHelper: type=self.comma_separated_ints_set, action='store', metavar='<digest_alg>,[<digest_alg>...]', help='Support only the specified DNSSEC digest algorithm(s)') + self.parser.add_argument('-b', '--validate-prohibited-algs', + const=True, default=False, + action='store_const', + help='Validate algorithms for which validation is otherwise prohibited') self.parser.add_argument('-C', '--enforce-cookies', const=True, default=False, action='store_const', @@ -454,7 +458,7 @@ def main(argv): d = OrderedDict() for name_obj in name_objs: - name_obj.populate_status(arghelper.trusted_keys, supported_algs=arghelper.args.algorithms, supported_digest_algs=arghelper.args.digest_algorithms) + name_obj.populate_status(arghelper.trusted_keys, supported_algs=arghelper.args.algorithms, supported_digest_algs=arghelper.args.digest_algorithms, validate_prohibited_algs=arghelper.args.validate_prohibited_algs) if arghelper.trusted_keys: G = DNSAuthGraph() diff --git a/dnsviz/commands/print.py b/dnsviz/commands/print.py index d2e4524..ceffdfc 100644 --- a/dnsviz/commands/print.py +++ b/dnsviz/commands/print.py @@ -356,6 +356,10 @@ class PrintArgHelper: type=self.comma_separated_ints_set, action='store', metavar='<digest_alg>,[<digest_alg>...]', help='Support only the specified DNSSEC digest algorithm(s)') + self.parser.add_argument('-b', '--validate-prohibited-algs', + const=True, default=False, + action='store_const', + help='Validate algorithms for which validation is otherwise prohibited') self.parser.add_argument('-C', '--enforce-cookies', const=True, default=False, action='store_const', @@ -590,7 +594,7 @@ def main(argv): G = DNSAuthGraph() for name_obj in name_objs: - name_obj.populate_status(arghelper.trusted_keys, supported_algs=arghelper.args.algorithms, supported_digest_algs=arghelper.args.digest_algorithms) + name_obj.populate_status(arghelper.trusted_keys, supported_algs=arghelper.args.algorithms, supported_digest_algs=arghelper.args.digest_algorithms, validate_prohibited_algs=arghelper.args.validate_prohibited_algs) for qname, rdtype in name_obj.queries: if arghelper.args.rr_types is None: # if rdtypes was not specified, then graph all, with some diff --git a/doc/man/dnsviz-graph.1 b/doc/man/dnsviz-graph.1 index 2e49755..6971750 100644 --- a/doc/man/dnsviz-graph.1 +++ b/doc/man/dnsviz-graph.1 @@ -93,6 +93,14 @@ unknown. Additionally, when a zone has only DS records with unsupported digest algorithms, the zone is treated as "insecure", assuming the DS records are properly authenticated. .TP +.B -b, --validate-prohibited-algs +Validate algorithms for which validation is otherwise prohibited. Current +DNSSEC specification prohibits validators from validating older, weaker +algorithms associated with DNSKEY and DS records (see RFC 8624). If this +option is used, then a warning will be still be issued for DNSSEC records that +use these older algorithms, but the code will still assess their cryptographic +status, rather than ignoring them. +.TP .B -C, --enforce-cookies Enforce DNS cookies strictly. Require a server to return a "BADCOOKIE" response when a query contains a COOKIE option with no server cookie or with an invalid diff --git a/doc/man/dnsviz-grok.1 b/doc/man/dnsviz-grok.1 index c6773f7..c9a441d 100644 --- a/doc/man/dnsviz-grok.1 +++ b/doc/man/dnsviz-grok.1 @@ -89,6 +89,14 @@ unknown. Additionally, when a zone has only DS records with unsupported digest algorithms, the zone is treated as "insecure", assuming the DS records are properly authenticated. .TP +.B -b, --validate-prohibited-algs +Validate algorithms for which validation is otherwise prohibited. Current +DNSSEC specification prohibits validators from validating older, weaker +algorithms associated with DNSKEY and DS records (see RFC 8624). If this +option is used, then a warning will be still be issued for DNSSEC records that +use these older algorithms, but the code will still assess their cryptographic +status, rather than ignoring them. +.TP .B -C, --enforce-cookies Enforce DNS cookies strictly. Require a server to return a "BADCOOKIE" response when a query contains a COOKIE option with no server cookie or with an invalid diff --git a/doc/man/dnsviz-print.1 b/doc/man/dnsviz-print.1 index 0499e1d..6091405 100644 --- a/doc/man/dnsviz-print.1 +++ b/doc/man/dnsviz-print.1 @@ -93,6 +93,14 @@ unknown. Additionally, when a zone has only DS records with unsupported digest algorithms, the zone is treated as "insecure", assuming the DS records are properly authenticated. .TP +.B -b, --validate-prohibited-algs +Validate algorithms for which validation is otherwise prohibited. Current +DNSSEC specification prohibits validators from validating older, weaker +algorithms associated with DNSKEY and DS records (see RFC 8624). If this +option is used, then a warning will be still be issued for DNSSEC records that +use these older algorithms, but the code will still assess their cryptographic +status, rather than ignoring them. +.TP .B -C, --enforce-cookies Enforce DNS cookies strictly. Require a server to return a "BADCOOKIE" response when a query contains a COOKIE option with no server cookie or with an invalid |