]> git.ipfire.org Git - thirdparty/dnspython.git/commitdiff
Allow digest type 0 for CDS 713/head
authorPeter Thomassen <peter@desec.io>
Wed, 20 Oct 2021 14:55:36 +0000 (16:55 +0200)
committerPeter Thomassen <peter@desec.io>
Wed, 20 Oct 2021 14:56:36 +0000 (16:56 +0200)
dns/rdtypes/ANY/CDS.py
dns/rdtypes/dsbase.py
tests/test_dnssec.py

index 39e3556e7485f975ed0f3c3ef41f48627864a58f..094de12bfde888af4e618d47973a53a0b8082f07 100644 (file)
@@ -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)
+    }
index d125db21ef15492a11f3de882d568c050466e12a..403e9371a701404703de70456b368ebe60021c0c 100644 (file)
@@ -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()
index 6ea51dc859bb77dbc358c8156e509366775ddeee..b018b8623e2d6f053f077259c6f9bbe9a27c96bf 100644 (file)
@@ -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()