diff options
-rw-r--r-- | dns/rdtypes/ANY/CDS.py | 5 | ||||
-rw-r--r-- | dns/rdtypes/dsbase.py | 24 | ||||
-rw-r--r-- | tests/test_dnssec.py | 23 |
3 files changed, 35 insertions, 17 deletions
diff --git a/dns/rdtypes/ANY/CDS.py b/dns/rdtypes/ANY/CDS.py index 39e3556..094de12 100644 --- a/dns/rdtypes/ANY/CDS.py +++ b/dns/rdtypes/ANY/CDS.py @@ -23,3 +23,8 @@ import dns.immutable class CDS(dns.rdtypes.dsbase.DSBase): """CDS record""" + + _digest_length_by_type = { + **dns.rdtypes.dsbase.DSBase._digest_length_by_type, + 0: 1, # delete, RFC 8078 Sec. 4 (including Errata ID 5049) + } diff --git a/dns/rdtypes/dsbase.py b/dns/rdtypes/dsbase.py index d125db2..403e937 100644 --- a/dns/rdtypes/dsbase.py +++ b/dns/rdtypes/dsbase.py @@ -24,15 +24,6 @@ import dns.rdata import dns.rdatatype -# Digest types registry: https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml -_digest_length_by_type = { - 1: 20, # SHA-1, RFC 3658 Sec. 2.4 - 2: 32, # SHA-256, RFC 4509 Sec. 2.2 - 3: 32, # GOST R 34.11-94, RFC 5933 Sec. 4 in conjunction with RFC 4490 Sec. 2.1 - 4: 48, # SHA-384, RFC 6605 Sec. 2 -} - - @dns.immutable.immutable class DSBase(dns.rdata.Rdata): @@ -40,6 +31,14 @@ class DSBase(dns.rdata.Rdata): __slots__ = ['key_tag', 'algorithm', 'digest_type', 'digest'] + # Digest types registry: https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml + _digest_length_by_type = { + 1: 20, # SHA-1, RFC 3658 Sec. 2.4 + 2: 32, # SHA-256, RFC 4509 Sec. 2.2 + 3: 32, # GOST R 34.11-94, RFC 5933 Sec. 4 in conjunction with RFC 4490 Sec. 2.1 + 4: 48, # SHA-384, RFC 6605 Sec. 2 + } + def __init__(self, rdclass, rdtype, key_tag, algorithm, digest_type, digest): super().__init__(rdclass, rdtype) @@ -49,13 +48,12 @@ class DSBase(dns.rdata.Rdata): self.digest = self._as_bytes(digest) try: + if len(self.digest) != self._digest_length_by_type[self.digest_type]: + raise ValueError('digest length inconsistent with digest type') + except KeyError: if self.digest_type == 0: # reserved, RFC 3658 Sec. 2.4 raise ValueError('digest type 0 is reserved') - expected_length = _digest_length_by_type[self.digest_type] - except KeyError: raise ValueError('unknown digest type') - if len(self.digest) != expected_length: - raise ValueError('digest length inconsistent with digest type') def to_text(self, origin=None, relativize=True, **kw): kw = kw.copy() diff --git a/tests/test_dnssec.py b/tests/test_dnssec.py index 6ea51dc..b018b86 100644 --- a/tests/test_dnssec.py +++ b/tests/test_dnssec.py @@ -499,13 +499,14 @@ class DNSSECMakeDSTestCase(unittest.TestCase): def testInvalidDigestType(self): # type: () -> None digest_type_errors = { - 0: 'digest type 0 is reserved', - 5: 'unknown digest type', + (dns.rdatatype.DS, 0): 'digest type 0 is reserved', + (dns.rdatatype.DS, 5): 'unknown digest type', + (dns.rdatatype.CDS, 5): 'unknown digest type', } - for digest_type, msg in digest_type_errors.items(): + for (rdtype, digest_type), msg in digest_type_errors.items(): with self.assertRaises(dns.exception.SyntaxError) as cm: dns.rdata.from_text(dns.rdataclass.IN, - dns.rdatatype.DS, + rdtype, f'18673 3 {digest_type} 71b71d4f3e11bbd71b4eff12cde69f7f9215bbe7') self.assertEqual(msg, str(cm.exception)) @@ -526,6 +527,20 @@ class DNSSECMakeDSTestCase(unittest.TestCase): self.assertEqual('digest length inconsistent with digest type', str(cm.exception)) + def testInvalidDigestLengthCDS0(self): # type: () -> None + # Make sure the construction is working + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CDS, f'0 0 0 00') + + test_records = { + 'digest length inconsistent with digest type': ['0 0 0', '0 0 0 0000'], + 'Odd-length string': ['0 0 0 0', '0 0 0 000'], + } + for msg, records in test_records.items(): + for record in records: + with self.assertRaises(dns.exception.SyntaxError) as cm: + dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.CDS, record) + self.assertEqual(msg, str(cm.exception)) + if __name__ == '__main__': unittest.main() |