Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dnsviz/dnsviz.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCasey Deccio <casey@deccio.net>2021-01-09 03:29:50 +0300
committerGitHub <noreply@github.com>2021-01-09 03:29:50 +0300
commitbdaa08fb28b4821f11a3f82c775b26f11ac56b80 (patch)
treee03caa4a161530cc2dd9150460a62aef0d8ebd42
parent2e3cb9b0893e16fc764cb45c0676dcd009d8cfc0 (diff)
parentf0e697b1d837f63299aa79d6152742bfd2dc9926 (diff)
Merge pull request #69 from dnsviz/obsoletealg
Obsoletealg
-rw-r--r--dnsviz/analysis/errors.py108
-rw-r--r--dnsviz/analysis/offline.py49
-rw-r--r--dnsviz/analysis/status.py120
-rw-r--r--dnsviz/commands/graph.py6
-rw-r--r--dnsviz/commands/grok.py6
-rw-r--r--dnsviz/commands/print.py6
-rw-r--r--doc/man/dnsviz-graph.18
-rw-r--r--doc/man/dnsviz-grok.18
-rw-r--r--doc/man/dnsviz-print.18
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