From b2615b5ec34e028e28720914afb47e728c7f9cf5 Mon Sep 17 00:00:00 2001 From: Istvan Ruzman Date: Sat, 5 Sep 2020 15:35:53 +0200 Subject: [PATCH] support decoding for different vendor formats --- src/pyrad3/packet.py | 20 +- src/pyrad3/utils.py | 64 +++++- tests/dictionaries/dict | 394 +++++++++++++++++++++++++++++++++---- tests/test_parse_header.py | 89 +++++++-- 4 files changed, 496 insertions(+), 71 deletions(-) diff --git a/src/pyrad3/packet.py b/src/pyrad3/packet.py index 603ac2e..000d77e 100644 --- a/src/pyrad3/packet.py +++ b/src/pyrad3/packet.py @@ -15,8 +15,8 @@ from pyrad3.utils import ( Attribute, PacketError, calculate_authenticator, - parse_attributes, - parse_header, + decode_attributes, + decode_header, validate_chap_password, validate_pap_password, ) @@ -50,10 +50,10 @@ class Packet(OrderedDict): @staticmethod def from_raw(host: Host, raw_packet: bytearray) -> "Packet": - """Parse the given bytearray to a RADIUS Packet""" - (code, radius_id, _length, authenticator) = parse_header(raw_packet) + """Decode the given bytearray to a RADIUS Packet""" + (code, radius_id, _length, authenticator) = decode_header(raw_packet) - ordered_attrs = parse_attributes(host.dictionary, raw_packet) + ordered_attrs = decode_attributes(host.dictionary, raw_packet) # Can we do better than Any with type hinting? attrs: Dict[str, Any] = {} @@ -63,11 +63,11 @@ class Packet(OrderedDict): except KeyError: attrs[attr.name] = [attr.value] - parsed_packet = Packet(host, code, radius_id, **attrs) - parsed_packet.authenticator = authenticator - parsed_packet.raw_packet = raw_packet - parsed_packet.ordered_attributes = ordered_attrs - return parsed_packet + decoded_packet = Packet(host, code, radius_id, **attrs) + decoded_packet.authenticator = authenticator + decoded_packet.raw_packet = raw_packet + decoded_packet.ordered_attributes = ordered_attrs + return decoded_packet def from_raw_reply(self, raw_packet: bytearray) -> "Packet": """Parse a bytearray """ diff --git a/src/pyrad3/utils.py b/src/pyrad3/utils.py index 86961f2..be6bfcb 100644 --- a/src/pyrad3/utils.py +++ b/src/pyrad3/utils.py @@ -74,7 +74,6 @@ def decode_attributes( else: name = attr_def.name datatype = attr_def.datatype - print(attr_def) if attr_def.has_tag: tag = value[0] value = value[1:] @@ -116,7 +115,7 @@ def pre_decode_attributes( # pylint: disable=too-many-branches try: attr_def = rad_dict.attrindex[key] if attr_def.datatype == Datatype.vsa: - tmp_attributes = decode_vsa(key, value, offset) + tmp_attributes = decode_vsa(rad_dict, key, value, offset) else: if attr_def.datatype == Datatype.extended: key, value, modifier = decode_extended(key, value, offset) @@ -152,8 +151,42 @@ def pre_decode_attributes( # pylint: disable=too-many-branches return attributes -def decode_vsa(key: int, value: bytes, offset: int) -> PreParsedAttributes: +PACK_TABLE = { + 0: "", + 1: "B", + 2: "H", + 4: "I", +} + + +def get_vendor_format(rad_dict: Dictionary, vendor_id: int) -> Tuple[str, int]: + """Get the vendor format + + This functions returns a tuple with the unpack string for struct.unpack and + the slicesize + """ + try: + format_size = 0 + vendor = rad_dict.vendor[vendor_id] + format_size += vendor.tlength + format_size += vendor.llength + + type_pack = PACK_TABLE[vendor.tlength] + length_pack = PACK_TABLE[vendor.llength] + + unpack = f"!{type_pack}{length_pack}" + except KeyError: + # Assume "normal" one byte type one byte length + unpack = "BB" + format_size = 2 + return unpack, format_size + + +def decode_vsa( + rad_dict: Dictionary, key: int, value: bytes, offset: int +) -> PreParsedAttributes: """Decode a TLV of type VSA (Vendor-Specific-Attribute)""" + if len(value) < 4: raise PacketError vendor_id = int.from_bytes(value[:4], "big") @@ -162,16 +195,31 @@ def decode_vsa(key: int, value: bytes, offset: int) -> PreParsedAttributes: value = value[4:] offset += 4 + unpack, format_size = get_vendor_format(rad_dict, vendor_id) + while value: try: - (key, length) = struct.unpack("!BB", value[:2]) + unpacked = struct.unpack(unpack, value[:format_size]) + try: + (key, length) = unpacked + except ValueError: + # this does not have an length, so we use the "external" one + # it is not passed to this function but we can reconstruct it + # through the value length + # For vendor definitions which do not have a length value, there + # can be only a single attribute within a vsa, so it safe to use + # len(value) + length = len(value) + key = unpacked[0] except struct.error as exc: raise PacketError("VSA Attribute Header is corrupt") from exc - if length < 2: + if length < format_size: raise PacketError(f"Attribute length({length}) is too small") vendor_key = tuple(keystack + [key]) - vendor_attributes.append((vendor_key, value[2:length], offset + 2)) + vendor_attributes.append( + (vendor_key, value[format_size:length], offset + format_size) + ) offset += length value = value[length:] @@ -184,7 +232,7 @@ def decode_extended( ) -> SpecialTlvDescription: """Decode an Attribute of type extended""" key = (key, value[0]) - value = value[1:length-2] + value = value[1 : length - 2] return (key, value, 3) @@ -193,7 +241,7 @@ def decode_longextended( ) -> SpecialTlvDescription: """Decode an Attribute of type long-extended""" key = (key, value[0]) - value = value[2:length-3] + value = value[2 : length - 3] return (key, value, 4) diff --git a/tests/dictionaries/dict b/tests/dictionaries/dict index 22e66ad..7a61925 100644 --- a/tests/dictionaries/dict +++ b/tests/dictionaries/dict @@ -39,44 +39,366 @@ ATTRIBUTE RFC-SPACE-TAGGED-COMBOIP 114 comboip has_tag ATTRIBUTE RFC-SPACE-TAGGED-IFID 115 ifid has_tag ATTRIBUTE RFC-SPACE-TAGGED-ETHER 116 ether has_tag -VENDOR TEST 1234 +VENDOR TEST10 1234 format=1,0 -BEGIN-VENDOR TEST -ATTRIBUTE VENDOR-TYPE-STRING 1 string -ATTRIBUTE VENDOR-TYPE-OCTETS 2 octets -ATTRIBUTE VENDOR-TYPE-DATE 3 date -ATTRIBUTE VENDOR-TYPE-ABINARY 4 abinary -ATTRIBUTE VENDOR-TYPE-BYTE 5 byte -ATTRIBUTE VENDOR-TYPE-SHORT 6 short -ATTRIBUTE VENDOR-TYPE-INTEGER 7 integer -ATTRIBUTE VENDOR-TYPE-SIGNED 8 signed -ATTRIBUTE VENDOR-TYPE-INTEGER64 9 integer64 -ATTRIBUTE VENDOR-TYPE-IPADDR 10 ipaddr -ATTRIBUTE VENDOR-TYPE-IPV4PREFIX 11 ipv4prefix -ATTRIBUTE VENDOR-TYPE-IPV6ADDR 12 ipv6addr -ATTRIBUTE VENDOR-TYPE-IPV6PREFIX 13 ipv6prefix -ATTRIBUTE VENDOR-TYPE-COMBOIP 14 comboip -ATTRIBUTE VENDOR-TYPE-IFID 15 ifid -ATTRIBUTE VENDOR-TYPE-ETHER 16 ether -ATTRIBUTE VENDOR-TYPE-TLV 18 tlv +BEGIN-VENDOR TEST10 +ATTRIBUTE VENDOR10-TYPE-STRING 1 string +ATTRIBUTE VENDOR10-TYPE-OCTETS 2 octets +ATTRIBUTE VENDOR10-TYPE-DATE 3 date +ATTRIBUTE VENDOR10-TYPE-ABINARY 4 abinary +ATTRIBUTE VENDOR10-TYPE-BYTE 5 byte +ATTRIBUTE VENDOR10-TYPE-SHORT 6 short +ATTRIBUTE VENDOR10-TYPE-INTEGER 7 integer +ATTRIBUTE VENDOR10-TYPE-SIGNED 8 signed +ATTRIBUTE VENDOR10-TYPE-INTEGER64 9 integer64 +ATTRIBUTE VENDOR10-TYPE-IPADDR 10 ipaddr +ATTRIBUTE VENDOR10-TYPE-IPV4PREFIX 11 ipv4prefix +ATTRIBUTE VENDOR10-TYPE-IPV6ADDR 12 ipv6addr +ATTRIBUTE VENDOR10-TYPE-IPV6PREFIX 13 ipv6prefix +ATTRIBUTE VENDOR10-TYPE-COMBOIP 14 comboip +ATTRIBUTE VENDOR10-TYPE-IFID 15 ifid +ATTRIBUTE VENDOR10-TYPE-ETHER 16 ether +ATTRIBUTE VENDOR10-TYPE-TLV 18 tlv -ATTRIBUTE VENDOR-TAGGED-STRING 101 string has_tag -ATTRIBUTE VENDOR-TAGGED-OCTETS 102 octets has_tag -ATTRIBUTE VENDOR-TAGGED-DATE 103 date has_tag -ATTRIBUTE VENDOR-TAGGED-ABINARY 104 abinary has_tag -ATTRIBUTE VENDOR-TAGGED-BYTE 105 byte has_tag -ATTRIBUTE VENDOR-TAGGED-SHORT 106 short has_tag -ATTRIBUTE VENDOR-TAGGED-INTEGER 107 integer has_tag -ATTRIBUTE VENDOR-TAGGED-SIGNED 108 signed has_tag -ATTRIBUTE VENDOR-TAGGED-INTEGER64 109 integer64 has_tag -ATTRIBUTE VENDOR-TAGGED-IPADDR 110 ipaddr has_tag -ATTRIBUTE VENDOR-TAGGED-IPV4PREFIX 111 ipv4prefix has_tag -ATTRIBUTE VENDOR-TAGGED-IPV6ADDR 112 ipv6addr has_tag -ATTRIBUTE VENDOR-TAGGED-IPV6PREFIX 113 ipv6prefix has_tag -ATTRIBUTE VENDOR-TAGGED-COMBOIP 114 comboip has_tag -ATTRIBUTE VENDOR-TAGGED-IFID 115 ifid has_tag -ATTRIBUTE VENDOR-TAGGED-ETHER 116 ether has_tag +ATTRIBUTE VENDOR10-TAGGED-STRING 101 string has_tag +ATTRIBUTE VENDOR10-TAGGED-OCTETS 102 octets has_tag +ATTRIBUTE VENDOR10-TAGGED-DATE 103 date has_tag +ATTRIBUTE VENDOR10-TAGGED-ABINARY 104 abinary has_tag +ATTRIBUTE VENDOR10-TAGGED-BYTE 105 byte has_tag +ATTRIBUTE VENDOR10-TAGGED-SHORT 106 short has_tag +ATTRIBUTE VENDOR10-TAGGED-INTEGER 107 integer has_tag +ATTRIBUTE VENDOR10-TAGGED-SIGNED 108 signed has_tag +ATTRIBUTE VENDOR10-TAGGED-INTEGER64 109 integer64 has_tag +ATTRIBUTE VENDOR10-TAGGED-IPADDR 110 ipaddr has_tag +ATTRIBUTE VENDOR10-TAGGED-IPV4PREFIX 111 ipv4prefix has_tag +ATTRIBUTE VENDOR10-TAGGED-IPV6ADDR 112 ipv6addr has_tag +ATTRIBUTE VENDOR10-TAGGED-IPV6PREFIX 113 ipv6prefix has_tag +ATTRIBUTE VENDOR10-TAGGED-COMBOIP 114 comboip has_tag +ATTRIBUTE VENDOR10-TAGGED-IFID 115 ifid has_tag +ATTRIBUTE VENDOR10-TAGGED-ETHER 116 ether has_tag + +END-VENDOR TEST10 + +VENDOR TEST11 1235 format=1,1 + +BEGIN-VENDOR TEST11 +ATTRIBUTE VENDOR11-TYPE-STRING 1 string +ATTRIBUTE VENDOR11-TYPE-OCTETS 2 octets +ATTRIBUTE VENDOR11-TYPE-DATE 3 date +ATTRIBUTE VENDOR11-TYPE-ABINARY 4 abinary +ATTRIBUTE VENDOR11-TYPE-BYTE 5 byte +ATTRIBUTE VENDOR11-TYPE-SHORT 6 short +ATTRIBUTE VENDOR11-TYPE-INTEGER 7 integer +ATTRIBUTE VENDOR11-TYPE-SIGNED 8 signed +ATTRIBUTE VENDOR11-TYPE-INTEGER64 9 integer64 +ATTRIBUTE VENDOR11-TYPE-IPADDR 10 ipaddr +ATTRIBUTE VENDOR11-TYPE-IPV4PREFIX 11 ipv4prefix +ATTRIBUTE VENDOR11-TYPE-IPV6ADDR 12 ipv6addr +ATTRIBUTE VENDOR11-TYPE-IPV6PREFIX 13 ipv6prefix +ATTRIBUTE VENDOR11-TYPE-COMBOIP 14 comboip +ATTRIBUTE VENDOR11-TYPE-IFID 15 ifid +ATTRIBUTE VENDOR11-TYPE-ETHER 16 ether +ATTRIBUTE VENDOR11-TYPE-TLV 18 tlv + +ATTRIBUTE VENDOR11-TAGGED-STRING 101 string has_tag +ATTRIBUTE VENDOR11-TAGGED-OCTETS 102 octets has_tag +ATTRIBUTE VENDOR11-TAGGED-DATE 103 date has_tag +ATTRIBUTE VENDOR11-TAGGED-ABINARY 104 abinary has_tag +ATTRIBUTE VENDOR11-TAGGED-BYTE 105 byte has_tag +ATTRIBUTE VENDOR11-TAGGED-SHORT 106 short has_tag +ATTRIBUTE VENDOR11-TAGGED-INTEGER 107 integer has_tag +ATTRIBUTE VENDOR11-TAGGED-SIGNED 108 signed has_tag +ATTRIBUTE VENDOR11-TAGGED-INTEGER64 109 integer64 has_tag +ATTRIBUTE VENDOR11-TAGGED-IPADDR 110 ipaddr has_tag +ATTRIBUTE VENDOR11-TAGGED-IPV4PREFIX 111 ipv4prefix has_tag +ATTRIBUTE VENDOR11-TAGGED-IPV6ADDR 112 ipv6addr has_tag +ATTRIBUTE VENDOR11-TAGGED-IPV6PREFIX 113 ipv6prefix has_tag +ATTRIBUTE VENDOR11-TAGGED-COMBOIP 114 comboip has_tag +ATTRIBUTE VENDOR11-TAGGED-IFID 115 ifid has_tag +ATTRIBUTE VENDOR11-TAGGED-ETHER 116 ether has_tag + +END-VENDOR TEST11 -END-VENDOR TEST +VENDOR TEST12 1236 format=1,2 + +BEGIN-VENDOR TEST12 +ATTRIBUTE VENDOR12-TYPE-STRING 1 string +ATTRIBUTE VENDOR12-TYPE-OCTETS 2 octets +ATTRIBUTE VENDOR12-TYPE-DATE 3 date +ATTRIBUTE VENDOR12-TYPE-ABINARY 4 abinary +ATTRIBUTE VENDOR12-TYPE-BYTE 5 byte +ATTRIBUTE VENDOR12-TYPE-SHORT 6 short +ATTRIBUTE VENDOR12-TYPE-INTEGER 7 integer +ATTRIBUTE VENDOR12-TYPE-SIGNED 8 signed +ATTRIBUTE VENDOR12-TYPE-INTEGER64 9 integer64 +ATTRIBUTE VENDOR12-TYPE-IPADDR 10 ipaddr +ATTRIBUTE VENDOR12-TYPE-IPV4PREFIX 11 ipv4prefix +ATTRIBUTE VENDOR12-TYPE-IPV6ADDR 12 ipv6addr +ATTRIBUTE VENDOR12-TYPE-IPV6PREFIX 13 ipv6prefix +ATTRIBUTE VENDOR12-TYPE-COMBOIP 14 comboip +ATTRIBUTE VENDOR12-TYPE-IFID 15 ifid +ATTRIBUTE VENDOR12-TYPE-ETHER 16 ether +ATTRIBUTE VENDOR12-TYPE-TLV 18 tlv + +ATTRIBUTE VENDOR12-TAGGED-STRING 101 string has_tag +ATTRIBUTE VENDOR12-TAGGED-OCTETS 102 octets has_tag +ATTRIBUTE VENDOR12-TAGGED-DATE 103 date has_tag +ATTRIBUTE VENDOR12-TAGGED-ABINARY 104 abinary has_tag +ATTRIBUTE VENDOR12-TAGGED-BYTE 105 byte has_tag +ATTRIBUTE VENDOR12-TAGGED-SHORT 106 short has_tag +ATTRIBUTE VENDOR12-TAGGED-INTEGER 107 integer has_tag +ATTRIBUTE VENDOR12-TAGGED-SIGNED 108 signed has_tag +ATTRIBUTE VENDOR12-TAGGED-INTEGER64 109 integer64 has_tag +ATTRIBUTE VENDOR12-TAGGED-IPADDR 110 ipaddr has_tag +ATTRIBUTE VENDOR12-TAGGED-IPV4PREFIX 111 ipv4prefix has_tag +ATTRIBUTE VENDOR12-TAGGED-IPV6ADDR 112 ipv6addr has_tag +ATTRIBUTE VENDOR12-TAGGED-IPV6PREFIX 113 ipv6prefix has_tag +ATTRIBUTE VENDOR12-TAGGED-COMBOIP 114 comboip has_tag +ATTRIBUTE VENDOR12-TAGGED-IFID 115 ifid has_tag +ATTRIBUTE VENDOR12-TAGGED-ETHER 116 ether has_tag + +END-VENDOR TEST12 + +VENDOR TEST20 1237 format=2,0 + +BEGIN-VENDOR TEST20 +ATTRIBUTE VENDOR20-TYPE-STRING 1 string +ATTRIBUTE VENDOR20-TYPE-OCTETS 2 octets +ATTRIBUTE VENDOR20-TYPE-DATE 3 date +ATTRIBUTE VENDOR20-TYPE-ABINARY 4 abinary +ATTRIBUTE VENDOR20-TYPE-BYTE 5 byte +ATTRIBUTE VENDOR20-TYPE-SHORT 6 short +ATTRIBUTE VENDOR20-TYPE-INTEGER 7 integer +ATTRIBUTE VENDOR20-TYPE-SIGNED 8 signed +ATTRIBUTE VENDOR20-TYPE-INTEGER64 9 integer64 +ATTRIBUTE VENDOR20-TYPE-IPADDR 10 ipaddr +ATTRIBUTE VENDOR20-TYPE-IPV4PREFIX 11 ipv4prefix +ATTRIBUTE VENDOR20-TYPE-IPV6ADDR 12 ipv6addr +ATTRIBUTE VENDOR20-TYPE-IPV6PREFIX 13 ipv6prefix +ATTRIBUTE VENDOR20-TYPE-COMBOIP 14 comboip +ATTRIBUTE VENDOR20-TYPE-IFID 15 ifid +ATTRIBUTE VENDOR20-TYPE-ETHER 16 ether +ATTRIBUTE VENDOR20-TYPE-TLV 18 tlv + +ATTRIBUTE VENDOR20-TAGGED-STRING 101 string has_tag +ATTRIBUTE VENDOR20-TAGGED-OCTETS 102 octets has_tag +ATTRIBUTE VENDOR20-TAGGED-DATE 103 date has_tag +ATTRIBUTE VENDOR20-TAGGED-ABINARY 104 abinary has_tag +ATTRIBUTE VENDOR20-TAGGED-BYTE 105 byte has_tag +ATTRIBUTE VENDOR20-TAGGED-SHORT 106 short has_tag +ATTRIBUTE VENDOR20-TAGGED-INTEGER 107 integer has_tag +ATTRIBUTE VENDOR20-TAGGED-SIGNED 108 signed has_tag +ATTRIBUTE VENDOR20-TAGGED-INTEGER64 109 integer64 has_tag +ATTRIBUTE VENDOR20-TAGGED-IPADDR 110 ipaddr has_tag +ATTRIBUTE VENDOR20-TAGGED-IPV4PREFIX 111 ipv4prefix has_tag +ATTRIBUTE VENDOR20-TAGGED-IPV6ADDR 112 ipv6addr has_tag +ATTRIBUTE VENDOR20-TAGGED-IPV6PREFIX 113 ipv6prefix has_tag +ATTRIBUTE VENDOR20-TAGGED-COMBOIP 114 comboip has_tag +ATTRIBUTE VENDOR20-TAGGED-IFID 115 ifid has_tag +ATTRIBUTE VENDOR20-TAGGED-ETHER 116 ether has_tag + +END-VENDOR TEST20 + + +VENDOR TEST21 1238 format=2,1 + +BEGIN-VENDOR TEST21 +ATTRIBUTE VENDOR21-TYPE-STRING 1 string +ATTRIBUTE VENDOR21-TYPE-OCTETS 2 octets +ATTRIBUTE VENDOR21-TYPE-DATE 3 date +ATTRIBUTE VENDOR21-TYPE-ABINARY 4 abinary +ATTRIBUTE VENDOR21-TYPE-BYTE 5 byte +ATTRIBUTE VENDOR21-TYPE-SHORT 6 short +ATTRIBUTE VENDOR21-TYPE-INTEGER 7 integer +ATTRIBUTE VENDOR21-TYPE-SIGNED 8 signed +ATTRIBUTE VENDOR21-TYPE-INTEGER64 9 integer64 +ATTRIBUTE VENDOR21-TYPE-IPADDR 10 ipaddr +ATTRIBUTE VENDOR21-TYPE-IPV4PREFIX 11 ipv4prefix +ATTRIBUTE VENDOR21-TYPE-IPV6ADDR 12 ipv6addr +ATTRIBUTE VENDOR21-TYPE-IPV6PREFIX 13 ipv6prefix +ATTRIBUTE VENDOR21-TYPE-COMBOIP 14 comboip +ATTRIBUTE VENDOR21-TYPE-IFID 15 ifid +ATTRIBUTE VENDOR21-TYPE-ETHER 16 ether +ATTRIBUTE VENDOR21-TYPE-TLV 18 tlv + +ATTRIBUTE VENDOR21-TAGGED-STRING 101 string has_tag +ATTRIBUTE VENDOR21-TAGGED-OCTETS 102 octets has_tag +ATTRIBUTE VENDOR21-TAGGED-DATE 103 date has_tag +ATTRIBUTE VENDOR21-TAGGED-ABINARY 104 abinary has_tag +ATTRIBUTE VENDOR21-TAGGED-BYTE 105 byte has_tag +ATTRIBUTE VENDOR21-TAGGED-SHORT 106 short has_tag +ATTRIBUTE VENDOR21-TAGGED-INTEGER 107 integer has_tag +ATTRIBUTE VENDOR21-TAGGED-SIGNED 108 signed has_tag +ATTRIBUTE VENDOR21-TAGGED-INTEGER64 109 integer64 has_tag +ATTRIBUTE VENDOR21-TAGGED-IPADDR 110 ipaddr has_tag +ATTRIBUTE VENDOR21-TAGGED-IPV4PREFIX 111 ipv4prefix has_tag +ATTRIBUTE VENDOR21-TAGGED-IPV6ADDR 112 ipv6addr has_tag +ATTRIBUTE VENDOR21-TAGGED-IPV6PREFIX 113 ipv6prefix has_tag +ATTRIBUTE VENDOR21-TAGGED-COMBOIP 114 comboip has_tag +ATTRIBUTE VENDOR21-TAGGED-IFID 115 ifid has_tag +ATTRIBUTE VENDOR21-TAGGED-ETHER 116 ether has_tag + +END-VENDOR TEST21 + + +VENDOR TEST22 1239 format=2,2 + +BEGIN-VENDOR TEST22 +ATTRIBUTE VENDOR22-TYPE-STRING 1 string +ATTRIBUTE VENDOR22-TYPE-OCTETS 2 octets +ATTRIBUTE VENDOR22-TYPE-DATE 3 date +ATTRIBUTE VENDOR22-TYPE-ABINARY 4 abinary +ATTRIBUTE VENDOR22-TYPE-BYTE 5 byte +ATTRIBUTE VENDOR22-TYPE-SHORT 6 short +ATTRIBUTE VENDOR22-TYPE-INTEGER 7 integer +ATTRIBUTE VENDOR22-TYPE-SIGNED 8 signed +ATTRIBUTE VENDOR22-TYPE-INTEGER64 9 integer64 +ATTRIBUTE VENDOR22-TYPE-IPADDR 10 ipaddr +ATTRIBUTE VENDOR22-TYPE-IPV4PREFIX 11 ipv4prefix +ATTRIBUTE VENDOR22-TYPE-IPV6ADDR 12 ipv6addr +ATTRIBUTE VENDOR22-TYPE-IPV6PREFIX 13 ipv6prefix +ATTRIBUTE VENDOR22-TYPE-COMBOIP 14 comboip +ATTRIBUTE VENDOR22-TYPE-IFID 15 ifid +ATTRIBUTE VENDOR22-TYPE-ETHER 16 ether +ATTRIBUTE VENDOR22-TYPE-TLV 18 tlv + +ATTRIBUTE VENDOR22-TAGGED-STRING 101 string has_tag +ATTRIBUTE VENDOR22-TAGGED-OCTETS 102 octets has_tag +ATTRIBUTE VENDOR22-TAGGED-DATE 103 date has_tag +ATTRIBUTE VENDOR22-TAGGED-ABINARY 104 abinary has_tag +ATTRIBUTE VENDOR22-TAGGED-BYTE 105 byte has_tag +ATTRIBUTE VENDOR22-TAGGED-SHORT 106 short has_tag +ATTRIBUTE VENDOR22-TAGGED-INTEGER 107 integer has_tag +ATTRIBUTE VENDOR22-TAGGED-SIGNED 108 signed has_tag +ATTRIBUTE VENDOR22-TAGGED-INTEGER64 109 integer64 has_tag +ATTRIBUTE VENDOR22-TAGGED-IPADDR 110 ipaddr has_tag +ATTRIBUTE VENDOR22-TAGGED-IPV4PREFIX 111 ipv4prefix has_tag +ATTRIBUTE VENDOR22-TAGGED-IPV6ADDR 112 ipv6addr has_tag +ATTRIBUTE VENDOR22-TAGGED-IPV6PREFIX 113 ipv6prefix has_tag +ATTRIBUTE VENDOR22-TAGGED-COMBOIP 114 comboip has_tag +ATTRIBUTE VENDOR22-TAGGED-IFID 115 ifid has_tag +ATTRIBUTE VENDOR22-TAGGED-ETHER 116 ether has_tag + +END-VENDOR TEST22 + +VENDOR TEST40 1240 format=4,0 + +BEGIN-VENDOR TEST40 +ATTRIBUTE VENDOR40-TYPE-STRING 1 string +ATTRIBUTE VENDOR40-TYPE-OCTETS 2 octets +ATTRIBUTE VENDOR40-TYPE-DATE 3 date +ATTRIBUTE VENDOR40-TYPE-ABINARY 4 abinary +ATTRIBUTE VENDOR40-TYPE-BYTE 5 byte +ATTRIBUTE VENDOR40-TYPE-SHORT 6 short +ATTRIBUTE VENDOR40-TYPE-INTEGER 7 integer +ATTRIBUTE VENDOR40-TYPE-SIGNED 8 signed +ATTRIBUTE VENDOR40-TYPE-INTEGER64 9 integer64 +ATTRIBUTE VENDOR40-TYPE-IPADDR 10 ipaddr +ATTRIBUTE VENDOR40-TYPE-IPV4PREFIX 11 ipv4prefix +ATTRIBUTE VENDOR40-TYPE-IPV6ADDR 12 ipv6addr +ATTRIBUTE VENDOR40-TYPE-IPV6PREFIX 13 ipv6prefix +ATTRIBUTE VENDOR40-TYPE-COMBOIP 14 comboip +ATTRIBUTE VENDOR40-TYPE-IFID 15 ifid +ATTRIBUTE VENDOR40-TYPE-ETHER 16 ether +ATTRIBUTE VENDOR40-TYPE-TLV 18 tlv + +ATTRIBUTE VENDOR40-TAGGED-STRING 101 string has_tag +ATTRIBUTE VENDOR40-TAGGED-OCTETS 102 octets has_tag +ATTRIBUTE VENDOR40-TAGGED-DATE 103 date has_tag +ATTRIBUTE VENDOR40-TAGGED-ABINARY 104 abinary has_tag +ATTRIBUTE VENDOR40-TAGGED-BYTE 105 byte has_tag +ATTRIBUTE VENDOR40-TAGGED-SHORT 106 short has_tag +ATTRIBUTE VENDOR40-TAGGED-INTEGER 107 integer has_tag +ATTRIBUTE VENDOR40-TAGGED-SIGNED 108 signed has_tag +ATTRIBUTE VENDOR40-TAGGED-INTEGER64 109 integer64 has_tag +ATTRIBUTE VENDOR40-TAGGED-IPADDR 110 ipaddr has_tag +ATTRIBUTE VENDOR40-TAGGED-IPV4PREFIX 111 ipv4prefix has_tag +ATTRIBUTE VENDOR40-TAGGED-IPV6ADDR 112 ipv6addr has_tag +ATTRIBUTE VENDOR40-TAGGED-IPV6PREFIX 113 ipv6prefix has_tag +ATTRIBUTE VENDOR40-TAGGED-COMBOIP 114 comboip has_tag +ATTRIBUTE VENDOR40-TAGGED-IFID 115 ifid has_tag +ATTRIBUTE VENDOR40-TAGGED-ETHER 116 ether has_tag + +END-VENDOR TEST40 + +VENDOR TEST41 1241 format=4,1 + +BEGIN-VENDOR TEST41 +ATTRIBUTE VENDOR41-TYPE-STRING 1 string +ATTRIBUTE VENDOR41-TYPE-OCTETS 2 octets +ATTRIBUTE VENDOR41-TYPE-DATE 3 date +ATTRIBUTE VENDOR41-TYPE-ABINARY 4 abinary +ATTRIBUTE VENDOR41-TYPE-BYTE 5 byte +ATTRIBUTE VENDOR41-TYPE-SHORT 6 short +ATTRIBUTE VENDOR41-TYPE-INTEGER 7 integer +ATTRIBUTE VENDOR41-TYPE-SIGNED 8 signed +ATTRIBUTE VENDOR41-TYPE-INTEGER64 9 integer64 +ATTRIBUTE VENDOR41-TYPE-IPADDR 10 ipaddr +ATTRIBUTE VENDOR41-TYPE-IPV4PREFIX 11 ipv4prefix +ATTRIBUTE VENDOR41-TYPE-IPV6ADDR 12 ipv6addr +ATTRIBUTE VENDOR41-TYPE-IPV6PREFIX 13 ipv6prefix +ATTRIBUTE VENDOR41-TYPE-COMBOIP 14 comboip +ATTRIBUTE VENDOR41-TYPE-IFID 15 ifid +ATTRIBUTE VENDOR41-TYPE-ETHER 16 ether +ATTRIBUTE VENDOR41-TYPE-TLV 18 tlv + +ATTRIBUTE VENDOR41-TAGGED-STRING 101 string has_tag +ATTRIBUTE VENDOR41-TAGGED-OCTETS 102 octets has_tag +ATTRIBUTE VENDOR41-TAGGED-DATE 103 date has_tag +ATTRIBUTE VENDOR41-TAGGED-ABINARY 104 abinary has_tag +ATTRIBUTE VENDOR41-TAGGED-BYTE 105 byte has_tag +ATTRIBUTE VENDOR41-TAGGED-SHORT 106 short has_tag +ATTRIBUTE VENDOR41-TAGGED-INTEGER 107 integer has_tag +ATTRIBUTE VENDOR41-TAGGED-SIGNED 108 signed has_tag +ATTRIBUTE VENDOR41-TAGGED-INTEGER64 109 integer64 has_tag +ATTRIBUTE VENDOR41-TAGGED-IPADDR 110 ipaddr has_tag +ATTRIBUTE VENDOR41-TAGGED-IPV4PREFIX 111 ipv4prefix has_tag +ATTRIBUTE VENDOR41-TAGGED-IPV6ADDR 112 ipv6addr has_tag +ATTRIBUTE VENDOR41-TAGGED-IPV6PREFIX 113 ipv6prefix has_tag +ATTRIBUTE VENDOR41-TAGGED-COMBOIP 114 comboip has_tag +ATTRIBUTE VENDOR41-TAGGED-IFID 115 ifid has_tag +ATTRIBUTE VENDOR41-TAGGED-ETHER 116 ether has_tag + +END-VENDOR TEST41 + +VENDOR TEST42 1242 format=4,2 + +BEGIN-VENDOR TEST42 +ATTRIBUTE VENDOR42-TYPE-STRING 1 string +ATTRIBUTE VENDOR42-TYPE-OCTETS 2 octets +ATTRIBUTE VENDOR42-TYPE-DATE 3 date +ATTRIBUTE VENDOR42-TYPE-ABINARY 4 abinary +ATTRIBUTE VENDOR42-TYPE-BYTE 5 byte +ATTRIBUTE VENDOR42-TYPE-SHORT 6 short +ATTRIBUTE VENDOR42-TYPE-INTEGER 7 integer +ATTRIBUTE VENDOR42-TYPE-SIGNED 8 signed +ATTRIBUTE VENDOR42-TYPE-INTEGER64 9 integer64 +ATTRIBUTE VENDOR42-TYPE-IPADDR 10 ipaddr +ATTRIBUTE VENDOR42-TYPE-IPV4PREFIX 11 ipv4prefix +ATTRIBUTE VENDOR42-TYPE-IPV6ADDR 12 ipv6addr +ATTRIBUTE VENDOR42-TYPE-IPV6PREFIX 13 ipv6prefix +ATTRIBUTE VENDOR42-TYPE-COMBOIP 14 comboip +ATTRIBUTE VENDOR42-TYPE-IFID 15 ifid +ATTRIBUTE VENDOR42-TYPE-ETHER 16 ether +ATTRIBUTE VENDOR42-TYPE-TLV 18 tlv + +ATTRIBUTE VENDOR42-TAGGED-STRING 101 string has_tag +ATTRIBUTE VENDOR42-TAGGED-OCTETS 102 octets has_tag +ATTRIBUTE VENDOR42-TAGGED-DATE 103 date has_tag +ATTRIBUTE VENDOR42-TAGGED-ABINARY 104 abinary has_tag +ATTRIBUTE VENDOR42-TAGGED-BYTE 105 byte has_tag +ATTRIBUTE VENDOR42-TAGGED-SHORT 106 short has_tag +ATTRIBUTE VENDOR42-TAGGED-INTEGER 107 integer has_tag +ATTRIBUTE VENDOR42-TAGGED-SIGNED 108 signed has_tag +ATTRIBUTE VENDOR42-TAGGED-INTEGER64 109 integer64 has_tag +ATTRIBUTE VENDOR42-TAGGED-IPADDR 110 ipaddr has_tag +ATTRIBUTE VENDOR42-TAGGED-IPV4PREFIX 111 ipv4prefix has_tag +ATTRIBUTE VENDOR42-TAGGED-IPV6ADDR 112 ipv6addr has_tag +ATTRIBUTE VENDOR42-TAGGED-IPV6PREFIX 113 ipv6prefix has_tag +ATTRIBUTE VENDOR42-TAGGED-COMBOIP 114 comboip has_tag +ATTRIBUTE VENDOR42-TAGGED-IFID 115 ifid has_tag +ATTRIBUTE VENDOR42-TAGGED-ETHER 116 ether has_tag + +END-VENDOR TEST42 diff --git a/tests/test_parse_header.py b/tests/test_parse_header.py index 5549546..74ab005 100644 --- a/tests/test_parse_header.py +++ b/tests/test_parse_header.py @@ -3,6 +3,7 @@ import struct from ipaddress import IPv4Address, IPv4Network, IPv6Address, IPv6Network +from itertools import product import pytest @@ -114,6 +115,34 @@ TAGGED_ATTRIBUTES = [ (b"\x71\x07\x01\x00\x40\x20\x03", IPv6Network("2003::0/64")), ] +VENDOR_FORMAT_COMBINATIONS = [ + (1234, 1, 0), + (1235, 1, 1), + (1236, 1, 2), + (1237, 2, 0), + (1238, 2, 1), + (1239, 2, 2), + (1240, 4, 0), + (1241, 4, 1), + (1242, 4, 2), +] + + +def flattened_product(l1, l2): + result = [] + for combination in product(l1, l2): + left, right = combination + result.append(list(left) + list(right)) + return result + + +VENDOR_TEST_ATTRIBUTES = flattened_product( + VENDOR_FORMAT_COMBINATIONS, TEST_ATTRIBUTES +) +VENDOR_TAGGED_ATTRIBUTES = flattened_product( + VENDOR_FORMAT_COMBINATIONS, TAGGED_ATTRIBUTES +) + @pytest.fixture def radius_dictionary(): @@ -143,18 +172,6 @@ def test_decode_attribute_rfc(radius_dictionary, attr_bytes, expected): assert attrs[0].tag == 0 -@pytest.mark.parametrize("attr_bytes, expected", TEST_ATTRIBUTES) -def test_decode_attribute_vsa(radius_dictionary, attr_bytes, expected): - vsa_length = (6 + len(attr_bytes)).to_bytes(1, "big") - raw_packet = ( - bytes(20) + b"\x1a" + vsa_length + b"\x00\x00\x04\xd2" + attr_bytes - ) - attrs = utils.decode_attributes(radius_dictionary, raw_packet) - assert len(attrs) == 1 - assert attrs[0].value == expected - assert attrs[0].tag == 0 - - @pytest.mark.parametrize("attr_bytes, expected", TAGGED_ATTRIBUTES) def test_decode_attribute_rfc_tagged(radius_dictionary, attr_bytes, expected): raw_packet = bytes(20) + attr_bytes @@ -164,12 +181,50 @@ def test_decode_attribute_rfc_tagged(radius_dictionary, attr_bytes, expected): assert attrs[0].tag == 1 -@pytest.mark.parametrize("attr_bytes, expected", TAGGED_ATTRIBUTES) -def test_decode_attribute_vsa_tagged(radius_dictionary, attr_bytes, expected): - vsa_length = (6 + len(attr_bytes)).to_bytes(1, "big") - raw_packet = ( - bytes(20) + b"\x1a" + vsa_length + b"\x00\x00\x04\xd2" + attr_bytes +def generate_vendor_attribute(vendor_id, tlen, llen, attr_bytes): + vendor_id = vendor_id.to_bytes(4, "big") + vsa_length = (4 + tlen + llen + len(attr_bytes)).to_bytes(1, "big") + attr_type = attr_bytes[0].to_bytes(tlen, "big") + + attr_len = attr_bytes[1] + tlen + if llen == 0: + attr_len = b"" + else: + attr_len = attr_len.to_bytes(llen, "big") + + attr_bytes = attr_bytes[2:] + packet = ( + bytes(20) + + b"\x1a" + + vsa_length + + vendor_id + + attr_type + + attr_len + + attr_bytes ) + return packet + + +@pytest.mark.parametrize( + "vendor_id, tlen, llen, attr_bytes, expected", VENDOR_TEST_ATTRIBUTES +) +def test_decode_attribute_vsa( + radius_dictionary, vendor_id, tlen, llen, attr_bytes, expected +): + raw_packet = generate_vendor_attribute(vendor_id, tlen, llen, attr_bytes) + attrs = utils.decode_attributes(radius_dictionary, raw_packet) + assert len(attrs) == 1 + assert attrs[0].value == expected + assert attrs[0].tag == 0 + + +@pytest.mark.parametrize( + "vendor_id, tlen, llen, attr_bytes, expected", VENDOR_TAGGED_ATTRIBUTES +) +def test_decode_attribute_vsa_tagged( + radius_dictionary, vendor_id, tlen, llen, attr_bytes, expected +): + raw_packet = generate_vendor_attribute(vendor_id, tlen, llen, attr_bytes) attrs = utils.decode_attributes(radius_dictionary, raw_packet) assert len(attrs) == 1 assert attrs[0].value == expected