Skip to content

Commit

Permalink
fix(dnsrec/record)!: Handle private values of RRSIG type (#83)
Browse files Browse the repository at this point in the history
  • Loading branch information
c0r0n3r committed Mar 5, 2024
1 parent 4d88ec5 commit 83ba3b0
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 4 deletions.
28 changes: 24 additions & 4 deletions cryptoparser/dnsrec/record.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

from cryptodatahub.dnsrec.algorithm import DnsRrType, DnsSecAlgorithm, DnsSecDigestType

from cryptoparser.common.base import OneByteEnumParsable, Serializable, TwoByteEnumParsable
from cryptoparser.common.base import NumericRangeParsableBase, OneByteEnumParsable, Serializable, TwoByteEnumParsable
from cryptoparser.common.exception import NotEnoughData
from cryptoparser.common.parse import ByteOrder, ComposerBinary, ParsableBase, ParserBinary

Expand Down Expand Up @@ -318,6 +318,20 @@ def compose(self):
raise NotImplementedError()


class DnsRrTypePrivate(NumericRangeParsableBase):
@classmethod
def _get_value_min(cls):
return 0xff00

@classmethod
def _get_value_max(cls):
return 0xfffe

@classmethod
def _get_value_length(cls):
return 2


@attr.s
class DnsNameUncompressed(ParsableBase, Serializable):
labels = attr.ib(
Expand Down Expand Up @@ -373,7 +387,7 @@ def compose(self):
class DnsRecordRrsig(ParsableBase): # pylint: disable=too-many-instance-attributes
HEADER_SIZE = 24

type_covered = attr.ib(validator=attr.validators.instance_of(DnsRrType))
type_covered = attr.ib(validator=attr.validators.instance_of((DnsRrType, DnsRrTypePrivate)))
algorithm = attr.ib(validator=attr.validators.instance_of(DnsSecAlgorithm))
labels = attr.ib(validator=attr.validators.instance_of(six.integer_types))
original_ttl = attr.ib(
Expand All @@ -396,7 +410,10 @@ def _parse(cls, parsable):

parser = ParserBinary(parsable)

parser.parse_parsable('type_covered', DnsRrTypeFactory)
try:
parser.parse_parsable('type_covered', DnsRrTypeFactory)
except InvalidValue:
parser.parse_parsable('type_covered', DnsRrTypePrivate)
parser.parse_parsable('algorithm', DnsSecAlgorithmFactory)
parser.parse_numeric('labels', 1)
parser.parse_numeric('original_ttl', 4)
Expand All @@ -411,7 +428,10 @@ def _parse(cls, parsable):
def compose(self):
composer = ComposerBinary()

composer.compose_numeric_enum_coded(self.type_covered)
if isinstance(self.type_covered, DnsRrType):
composer.compose_numeric_enum_coded(self.type_covered)
else:
composer.compose_parsable(self.type_covered)
composer.compose_numeric_enum_coded(self.algorithm)
composer.compose_numeric(self.labels, 1)
composer.compose_numeric(self.original_ttl, 4)
Expand Down
27 changes: 27 additions & 0 deletions test/dnsrec/test_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
DnsRecordMx,
DnsRecordRrsig,
DnsRecordTxt,
DnsRrTypePrivate,
DnsSecFlag,
DnsSecProtocol,
)
Expand Down Expand Up @@ -447,6 +448,30 @@ def setUp(self):
signature=32 * b'\xff',
)

self.record_private_type_bytes = bytes(
b'\xff\xfe' + # type_covered: A
b'\x01' + # algorithm: RSAMD5
b'\x03' + # labels
b'\x00\x00\x0e\x10' + # original_ttl: 3600
b'\x00\x00\x00\x01' + # signature_expiration
b'\x00\x00\x00\x02' + # signature_inception
b'\xab\xcd' + # key_tag
b'\x06signer\x00' + # signers_name
32 * b'\xff' + # signature
b''
)
self.record_private_types = DnsRecordRrsig(
type_covered=DnsRrTypePrivate(0xfffe),
algorithm=DnsSecAlgorithm.RSAMD5,
labels=3,
original_ttl=3600,
signature_expiration=datetime.datetime(1970, 1, 1, 0, 0, 1, tzinfo=dateutil.tz.UTC),
signature_inception=datetime.datetime(1970, 1, 1, 0, 0, 2, tzinfo=dateutil.tz.UTC),
key_tag=0xabcd,
signers_name='signer',
signature=32 * b'\xff',
)

def test_error_not_enough_data(self):
with self.assertRaises(NotEnoughData) as context_manager:
DnsRecordRrsig.parse_exact_size(b'\x00')
Expand All @@ -458,9 +483,11 @@ def test_error_not_enough_data(self):

def test_parse(self):
self.assertEqual(DnsRecordRrsig.parse_exact_size(self.record_bytes), self.record)
self.assertEqual(DnsRecordRrsig.parse_exact_size(self.record_private_type_bytes), self.record_private_types)

def test_compose(self):
self.assertEqual(self.record.compose(), self.record_bytes)
self.assertEqual(self.record_private_types.compose(), self.record_private_type_bytes)


class TestDnsRecordMx(unittest.TestCase):
Expand Down

0 comments on commit 83ba3b0

Please sign in to comment.