somewhat woring evs decoding

This commit is contained in:
Istvan Ruzman
2022-02-21 18:24:43 +01:00
parent 2782b6950c
commit 0af5d95316
5 changed files with 76 additions and 53 deletions

View File

@@ -330,6 +330,8 @@ class Dictionary:
filename = self.filestack[-1] filename = self.filestack[-1]
tlength = self.cur_vendor.tlength tlength = self.cur_vendor.tlength
codes = evs.copy() codes = evs.copy()
if len(codes) > 0:
codes.append(self.cur_vendor.code)
for code in attr_code.split("."): for code in attr_code.split("."):
try: try:
code_num = _parse_number(code) code_num = _parse_number(code)
@@ -409,7 +411,7 @@ class Dictionary:
raise ParseError(filename, "evs must be a tlv", line_num) raise ParseError(filename, "evs must be a tlv", line_num)
self.evs[name.upper()] = list(attrcode) self.evs[name.upper()] = list(attrcode)
if self.cur_vendor != self.rfc_vendor: if self.cur_vendor != self.rfc_vendor and len(evs) == 0:
codes = [26, self.cur_vendor.code] + codes codes = [26, self.cur_vendor.code] + codes
LOG.info( LOG.info(
"Register Attribute %s for Vendor %s", "Register Attribute %s for Vendor %s",

View File

@@ -1,14 +1,13 @@
# Copyright 2020 Istvan Ruzman # Copyright 2020 Istvan Ruzman
# SPDX-License-Identifier: MIT OR Apache-2.0 # SPDX-License-Identifier: MIT OR Apache-2.0
"""Valid RADIUS codes (registered in IANA) """Valid RADIUS codes (registered in IANA)
Currently not all RADIUS codes are contained, because Currently not all RADIUS codes are contained, because
we don't support them (yet). we don't support them (yet).
""" """
from __future__ import annotations
from dataclasses import dataclass from dataclasses import dataclass, field
from enum import Enum, IntEnum, auto from enum import Enum, IntEnum, auto
from typing import Dict, List, Tuple, Union from typing import Dict, List, Tuple, Union
@@ -84,6 +83,7 @@ class Attribute: # pylint: disable=too-many-instance-attributes
has_tag: bool = False has_tag: bool = False
encrypt: Encrypt = Encrypt(0) encrypt: Encrypt = Encrypt(0)
is_sub_attr: bool = False is_sub_attr: bool = False
tlvs: Dict[str, Attribute] = field(default_factory=dict)
# vendor = Dictionary # vendor = Dictionary

View File

@@ -27,10 +27,10 @@ PACK_TABLE = {
class PacketError(Exception): class PacketError(Exception):
"""Exception for Invalid Packets""" """Exception for Invalid/Maleformed RADIUS Packets"""
Header = namedtuple("Header", ["code", "radius_id", "length", "authenticator"]) Header = namedtuple("Header", ["code", "identifier", "length", "authenticator"])
Attribute = namedtuple("Attribute", ["name", "pos", "type", "length", "tag", "value"]) Attribute = namedtuple("Attribute", ["name", "pos", "type", "length", "tag", "value"])
PreParsedAttributes = List[Tuple[Tuple[int, ...], bytes, int]] PreParsedAttributes = List[Tuple[Tuple[int, ...], bytes, int]]
@@ -70,6 +70,7 @@ def decode_attributes(rad_dict: Dictionary, raw_packet: bytes) -> List[Attribute
for key, value, offset in pre_decode_attributes(rad_dict, packet): for key, value, offset in pre_decode_attributes(rad_dict, packet):
attr_def = rad_dict.attrindex.get(key) attr_def = rad_dict.attrindex.get(key)
print(rad_dict.attrindex.keys())
dec_value: Any = value # to silence mypy dec_value: Any = value # to silence mypy
tag = 0 tag = 0
if attr_def is None: if attr_def is None:
@@ -129,8 +130,7 @@ def pre_decode_attributes( # pylint: disable=too-many-branches
elif attr_def.datatype == Datatype.CONCAT: elif attr_def.datatype == Datatype.CONCAT:
key, value, modifier = decode_concat(key, value, offset) key, value, modifier = decode_concat(key, value, offset)
else: else:
modifier = 2 modifier = 2 # Redundant in the "normal" case
# Redundant in the "normal" case
tmp_attributes = [(key, value, offset + modifier)] tmp_attributes = [(key, value, offset + modifier)]
except (KeyError, IndexError): except (KeyError, IndexError):
# We do not know the TLV, but the packet seems to be well-formed so far # We do not know the TLV, but the packet seems to be well-formed so far
@@ -143,6 +143,9 @@ def pre_decode_attributes( # pylint: disable=too-many-branches
if adef.datatype == Datatype.TLV: if adef.datatype == Datatype.TLV:
# TODO: deal with tagged tlvs # TODO: deal with tagged tlvs
attributes.extend(decode_tlv(rad_dict, list(key), value, offset)) attributes.extend(decode_tlv(rad_dict, list(key), value, offset))
elif adef.datatype == Datatype.EVS:
assert isinstance(key, tuple)
attributes.append(decode_evs(key, value))
else: else:
raise ValueError raise ValueError
except (ValueError, KeyError): except (ValueError, KeyError):
@@ -222,16 +225,16 @@ def decode_vsa(
def decode_extended(key: int, value: bytes) -> SpecialTlvDescription: def decode_extended(key: int, value: bytes) -> SpecialTlvDescription:
"""Decode an Attribute of type extended""" """Decode an Attribute of type extended"""
key = (key, value[0]) ext_key = (key, value[0])
value = value[1:] value = value[1:]
return (key, value, 3) return (ext_key, value, 3)
def decode_longextended(key: int, value: bytes) -> SpecialTlvDescription: def decode_longextended(key: int, value: bytes) -> SpecialTlvDescription:
"""Decode an Attribute of type long-extended""" """Decode an Attribute of type long-extended"""
key = (key, value[0]) ext_key = (key, value[0])
value = value[2:] value = value[2:]
return (key, value, 4) return (ext_key, value, 4)
def decode_concat(key: int, value: bytes, offset: int) -> SpecialTlvDescription: def decode_concat(key: int, value: bytes, offset: int) -> SpecialTlvDescription:
@@ -239,13 +242,13 @@ def decode_concat(key: int, value: bytes, offset: int) -> SpecialTlvDescription:
raise NotImplementedError raise NotImplementedError
def decode_evs(key: int, value: bytes, offset: int) -> PreParsedAttributes: def decode_evs(key: Tuple[int, int], value: bytes) -> SpecialTlvDescription:
"""Decode an Attribute of type EVS (Extended Vendor Specific)""" """Decode an Attribute of type EVS (Extended Vendor Specific)"""
vendor_id = int.from_bytes(value[:4], "big") vendor_id = int.from_bytes(value[:4], "big")
vendor_type = value[4] vendor_type = value[4]
key = tuple(list(key) + [vendor_id, vendor_type]) evs_key = (key[0], key[1], vendor_id, vendor_type)
value = value[5:] value = value[5:]
return (key, value, 5) return (evs_key, value, 5)
def decode_tlv( def decode_tlv(
@@ -268,6 +271,11 @@ def decode_tlv(
return ret return ret
def encode_attributes(rad_dict: Dictionary, attributes: List[Attribute]):
for attribute in attributes:
raise NotImplementedError
def calculate_authenticator( def calculate_authenticator(
secret: bytes, authenticator: bytes, raw_packet: bytes secret: bytes, authenticator: bytes, raw_packet: bytes
) -> bytes: ) -> bytes:

View File

@@ -81,44 +81,44 @@ ATTRIBUTE VENDOR10-TAGGED-ETHER 116 ether has_tag
END-VENDOR TEST10 END-VENDOR TEST10
BEGIN-VENDOR TEST10 format=RFC-SPACE-TYPE-EVS BEGIN-VENDOR TEST10 format=RFC-SPACE-TYPE-EVS
ATTRIBUTE VENDOR10-EVS-TYPE-STRING 19.21.1234.1 string ATTRIBUTE VENDOR10-EVS-TYPE-STRING 1 string
ATTRIBUTE VENDOR10-EVS-TYPE-OCTETS 19.21.1234.2 octets ATTRIBUTE VENDOR10-EVS-TYPE-OCTETS 2 octets
ATTRIBUTE VENDOR10-EVS-TYPE-DATE 19.21.1234.3 date ATTRIBUTE VENDOR10-EVS-TYPE-DATE 3 date
ATTRIBUTE VENDOR10-EVS-TYPE-ABINARY 19.21.1234.4 abinary ATTRIBUTE VENDOR10-EVS-TYPE-ABINARY 4 abinary
ATTRIBUTE VENDOR10-EVS-TYPE-BYTE 19.21.1234.5 byte ATTRIBUTE VENDOR10-EVS-TYPE-BYTE 5 byte
ATTRIBUTE VENDOR10-EVS-TYPE-SHORT 19.21.1234.6 short ATTRIBUTE VENDOR10-EVS-TYPE-SHORT 6 short
ATTRIBUTE VENDOR10-EVS-TYPE-INTEGER 19.21.1234.7 integer ATTRIBUTE VENDOR10-EVS-TYPE-INTEGER 7 integer
ATTRIBUTE VENDOR10-EVS-TYPE-SIGNED 19.21.1234.8 signed ATTRIBUTE VENDOR10-EVS-TYPE-SIGNED 8 signed
ATTRIBUTE VENDOR10-EVS-TYPE-INTEGER64 19.21.1234.9 integer64 ATTRIBUTE VENDOR10-EVS-TYPE-INTEGER64 9 integer64
ATTRIBUTE VENDOR10-EVS-TYPE-IPADDR 19.21.1234.10 ipaddr ATTRIBUTE VENDOR10-EVS-TYPE-IPADDR 10 ipaddr
ATTRIBUTE VENDOR10-EVS-TYPE-IPV4PREFIX 19.21.1234.11 ipv4prefix ATTRIBUTE VENDOR10-EVS-TYPE-IPV4PREFIX 11 ipv4prefix
ATTRIBUTE VENDOR10-EVS-TYPE-IPV6ADDR 19.21.1234.12 ipv6addr ATTRIBUTE VENDOR10-EVS-TYPE-IPV6ADDR 12 ipv6addr
ATTRIBUTE VENDOR10-EVS-TYPE-IPV6PREFIX 19.21.1234.13 ipv6prefix ATTRIBUTE VENDOR10-EVS-TYPE-IPV6PREFIX 13 ipv6prefix
ATTRIBUTE VENDOR10-EVS-TYPE-COMBOIP 19.21.1234.14 comboip ATTRIBUTE VENDOR10-EVS-TYPE-COMBOIP 14 comboip
ATTRIBUTE VENDOR10-EVS-TYPE-IFID 19.21.1234.15 ifid ATTRIBUTE VENDOR10-EVS-TYPE-IFID 15 ifid
ATTRIBUTE VENDOR10-EVS-TYPE-ETHER 19.21.1234.16 ether ATTRIBUTE VENDOR10-EVS-TYPE-ETHER 16 ether
ATTRIBUTE VENDOR10-EVS-TYPE-TLV 19.21.1234.18 tlv ATTRIBUTE VENDOR10-EVS-TYPE-TLV 18 tlv
END-VENDOR END-VENDOR TEST10
BEGIN-VENDOR TEST10 format=RFC-SPACE-TYPE-EVS BEGIN-VENDOR TEST10 format=RFC-SPACE-TYPE-LONG-EVS
ATTRIBUTE VENDOR10-LONG-EVS-TYPE-STRING 20.21.1234.1 string ATTRIBUTE VENDOR10-LONG-EVS-TYPE-STRING 1 string
ATTRIBUTE VENDOR10-LONG-EVS-TYPE-OCTETS 20.21.1234.2 octets ATTRIBUTE VENDOR10-LONG-EVS-TYPE-OCTETS 2 octets
ATTRIBUTE VENDOR10-LONG-EVS-TYPE-DATE 20.21.1234.3 date ATTRIBUTE VENDOR10-LONG-EVS-TYPE-DATE 3 date
ATTRIBUTE VENDOR10-LONG-EVS-TYPE-ABINARY 20.21.1234.4 abinary ATTRIBUTE VENDOR10-LONG-EVS-TYPE-ABINARY 4 abinary
ATTRIBUTE VENDOR10-LONG-EVS-TYPE-BYTE 20.21.1234.5 byte ATTRIBUTE VENDOR10-LONG-EVS-TYPE-BYTE 5 byte
ATTRIBUTE VENDOR10-LONG-EVS-TYPE-SHORT 20.21.1234.6 short ATTRIBUTE VENDOR10-LONG-EVS-TYPE-SHORT 6 short
ATTRIBUTE VENDOR10-LONG-EVS-TYPE-INTEGER 20.21.1234.7 integer ATTRIBUTE VENDOR10-LONG-EVS-TYPE-INTEGER 7 integer
ATTRIBUTE VENDOR10-LONG-EVS-TYPE-SIGNED 20.21.1234.8 signed ATTRIBUTE VENDOR10-LONG-EVS-TYPE-SIGNED 8 signed
ATTRIBUTE VENDOR10-LONG-EVS-TYPE-INTEGER64 20.21.1234.9 integer64 ATTRIBUTE VENDOR10-LONG-EVS-TYPE-INTEGER64 9 integer64
ATTRIBUTE VENDOR10-LONG-EVS-TYPE-IPADDR 20.21.1234.10 ipaddr ATTRIBUTE VENDOR10-LONG-EVS-TYPE-IPADDR 10 ipaddr
ATTRIBUTE VENDOR10-LONG-EVS-TYPE-IPV4PREFIX 20.21.1234.11 ipv4prefix ATTRIBUTE VENDOR10-LONG-EVS-TYPE-IPV4PREFIX 11 ipv4prefix
ATTRIBUTE VENDOR10-LONG-EVS-TYPE-IPV6ADDR 20.21.1234.12 ipv6addr ATTRIBUTE VENDOR10-LONG-EVS-TYPE-IPV6ADDR 12 ipv6addr
ATTRIBUTE VENDOR10-LONG-EVS-TYPE-IPV6PREFIX 20.21.1234.13 ipv6prefix ATTRIBUTE VENDOR10-LONG-EVS-TYPE-IPV6PREFIX 13 ipv6prefix
ATTRIBUTE VENDOR10-LONG-EVS-TYPE-COMBOIP 20.21.1234.14 comboip ATTRIBUTE VENDOR10-LONG-EVS-TYPE-COMBOIP 14 comboip
ATTRIBUTE VENDOR10-LONG-EVS-TYPE-IFID 20.21.1234.15 ifid ATTRIBUTE VENDOR10-LONG-EVS-TYPE-IFID 15 ifid
ATTRIBUTE VENDOR10-LONG-EVS-TYPE-ETHER 20.21.1234.16 ether ATTRIBUTE VENDOR10-LONG-EVS-TYPE-ETHER 16 ether
ATTRIBUTE VENDOR10-LONG-EVS-TYPE-TLV 20.21.1234.18 tlv ATTRIBUTE VENDOR10-LONG-EVS-TYPE-TLV 18 tlv
END-VENDOR END-VENDOR TEST10
VENDOR TEST11 1235 format=1,1 VENDOR TEST11 1235 format=1,1

View File

@@ -419,4 +419,17 @@ def test_extended_evs():
"END-VENDOR TEST-VENDOR" "END-VENDOR TEST-VENDOR"
) )
dd = Dictionary("", dictionary) dd = Dictionary("", dictionary)
assert dd["VENDOR-ATTRIBUTE"].code == [10, 20, 10] assert dd["VENDOR-ATTRIBUTE"].code == [10, 20, 1234, 10]
def test_long_extended_evs():
dictionary = StringIO(
"ATTRIBUTE RFC-LONGEXTENDED 10 extended\n"
"ATTRIBUTE RFC-LONGEXTENDED-EVS 10.20 evs\n"
"VENDOR TEST-VENDOR 1234\n"
"BEGIN-VENDOR TEST-VENDOR format=RFC-LONGEXTENDED-EVS\n"
"ATTRIBUTE VENDOR-ATTRIBUTE 10 integer\n"
"END-VENDOR TEST-VENDOR"
)
dd = Dictionary("", dictionary)
assert dd["VENDOR-ATTRIBUTE"].code == [10, 20, 1234, 10]