From 89dc78e4a3e20632e098def65c7296541f5d7dcd Mon Sep 17 00:00:00 2001 From: Peter Thomassen Date: Mon, 24 Jan 2022 11:14:03 +0100 Subject: [PATCH] Require trailing field in rdata of TLSA and friends (cherry picked from commit 4c70268984d865f8b0e93ca019518807af5fd344) --- dns/rdata.py | 2 +- dns/rdtypes/ANY/TKEY.py | 2 +- dns/tokenizer.py | 7 ++++++- tests/test_dnssec.py | 3 ++- tests/test_rdata.py | 3 +++ 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/dns/rdata.py b/dns/rdata.py index 624063e0..6b5b5c5a 100644 --- a/dns/rdata.py +++ b/dns/rdata.py @@ -557,7 +557,7 @@ class GenericRdata(Rdata): raise dns.exception.SyntaxError( r'generic rdata does not start with \#') length = tok.get_int() - hex = tok.concatenate_remaining_identifiers().encode() + hex = tok.concatenate_remaining_identifiers(True).encode() data = binascii.unhexlify(hex) if len(data) != length: raise dns.exception.SyntaxError( diff --git a/dns/rdtypes/ANY/TKEY.py b/dns/rdtypes/ANY/TKEY.py index f8c47372..861fc4e3 100644 --- a/dns/rdtypes/ANY/TKEY.py +++ b/dns/rdtypes/ANY/TKEY.py @@ -63,7 +63,7 @@ class TKEY(dns.rdata.Rdata): error = tok.get_uint16() key_b64 = tok.get_string().encode() key = base64.b64decode(key_b64) - other_b64 = tok.concatenate_remaining_identifiers().encode() + other_b64 = tok.concatenate_remaining_identifiers(True).encode() other = base64.b64decode(other_b64) return cls(rdclass, rdtype, algorithm, inception, expiration, mode, diff --git a/dns/tokenizer.py b/dns/tokenizer.py index 7ddc7a96..cb6a6302 100644 --- a/dns/tokenizer.py +++ b/dns/tokenizer.py @@ -600,9 +600,12 @@ class Tokenizer: break return tokens - def concatenate_remaining_identifiers(self): + def concatenate_remaining_identifiers(self, allow_empty=False): """Read the remaining tokens on the line, which should be identifiers. + Raises dns.exception.SyntaxError if there are no remaining tokens, + unless `allow_empty=True` is given. + Raises dns.exception.SyntaxError if a token is seen that is not an identifier. @@ -618,6 +621,8 @@ class Tokenizer: if not token.is_identifier(): raise dns.exception.SyntaxError s += token.value + if not (allow_empty or s): + raise dns.exception.SyntaxError('expecting another identifier') return s def as_name(self, token, origin=None, relativize=False, relativize_to=None): diff --git a/tests/test_dnssec.py b/tests/test_dnssec.py index 12651d7d..d4d76275 100644 --- a/tests/test_dnssec.py +++ b/tests/test_dnssec.py @@ -533,7 +533,8 @@ class DNSSECMakeDSTestCase(unittest.TestCase): 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'], + 'expecting another identifier': ['0 0 0', '0 0 0 '], + 'digest length inconsistent with digest type': ['0 0 0 0000'], 'Odd-length string': ['0 0 0 0', '0 0 0 000'], } for msg, records in test_records.items(): diff --git a/tests/test_rdata.py b/tests/test_rdata.py index f87ff560..c002e7ab 100644 --- a/tests/test_rdata.py +++ b/tests/test_rdata.py @@ -539,6 +539,9 @@ class RdataTestCase(unittest.TestCase): with self.assertRaises(dns.exception.SyntaxError): dns.rdata.from_text('in', 'type45678', '\\# 6 000a03666f6f00') + def test_empty_generic(self): + dns.rdata.from_text('in', 'type45678', r'\# 0') + def test_covered_repr(self): text = 'NSEC 1 3 3600 20190101000000 20030101000000 ' + \ '2143 foo Ym9ndXM=' -- 2.47.3