def parse(cls, packed_value): try: cls.is_valid_length(packed_value) return cls(bytes_data=struct.unpack("!4s", packed_value)[0]) except (ValueError, struct.error) as exception: raise MessageParseError("%s unable to unpack." % cls.__name__) from exception
def extract_attributes(cls, attributes_data, attributes, attributes_to_concat): """ Extracts Radius Attributes from a packed payload. Keeps track of attribute ordering. Args: attributes_data (): data to extract from (input). attributes: attributes extracted (output variable). attributes_to_concat (dict): (output variable). Raises: MessageParseError: RadiusAttribute.parse will raise error if it cannot parse the attribute's data """ total_length = len(attributes_data) pos = 0 index = -1 last_attribute = -1 while pos < total_length: try: type_, attr_length = struct.unpack( "!BB", attributes_data[pos:pos + Attribute.HEADER_SIZE]) except struct.error as exception: raise MessageParseError('Unable to unpack first 2 bytes of attribute header') \ from exception data = attributes_data[pos + Attribute.HEADER_SIZE:pos + attr_length] pos += attr_length packed_value = data[:attr_length - Attribute.HEADER_SIZE] try: attribute = ATTRIBUTE_TYPES[type_].parse(packed_value) except KeyError as exception: raise MessageParseError( 'Cannot find parser for RADIUS attribute %s' % type_) from exception # keep track of where the concated AVP should be in the attributes list. # required so the hashing gives correct hash. if attribute.DATA_TYPE != Concat or last_attribute != attribute.TYPE: index += 1 last_attribute = attribute.TYPE if attribute.DATA_TYPE.DATA_TYPE_VALUE == Concat.DATA_TYPE_VALUE: if attribute.TYPE not in attributes_to_concat: attributes_to_concat[attribute.TYPE] = [] attributes_to_concat[attribute.TYPE].append((attribute, index)) attributes.append(attribute)
def parse(cls, packed_value): # TODO Vsa.parse does not currently separate the vendor-id from the vsa-data # we could do that at some point (e.g. if we wanted to use Vendor-Specific) try: cls.is_valid_length(packed_value) return cls(struct.unpack("!%ds" % len(packed_value), packed_value)[0]) except (ValueError, struct.error) as exception: raise MessageParseError("%s unable to unpack." % cls.__name__) from exception
def parse(packed_message, secret, packet_id_to_request_authenticator=None): """ Args: packed_message: secret (str): Shared sceret between chewie and RADIUS server. packet_id_to_request_authenticator: map to get authenticator for a packet_id Returns: RadiusPacket - RadiusAccessChallenge/RadiusAccessRequest/ RadiusAccessAccept/RadiusAccessFailure Raises: MessageParseError: if packed_message cannot be parsed """ try: code, packet_id, _, authenticator = struct.unpack( "!BBH16s", packed_message[:RADIUS_HEADER_LENGTH]) except struct.error as exception: raise MessageParseError('Unable to unpack first 20 bytes of RADIUS header') \ from exception if code in PACKET_TYPE_PARSERS.keys(): radius_packet = PACKET_TYPE_PARSERS[code]( packet_id, authenticator, RadiusAttributesList.parse( packed_message[RADIUS_HEADER_LENGTH:])) if code == Radius.ACCESS_REQUEST: request_authenticator = authenticator else: try: request_authenticator = packet_id_to_request_authenticator[ packet_id] except KeyError as exception: raise MessageParseError('Unknown RAIDUS packet_id: %s' % packet_id, ) \ from exception try: return radius_packet.validate_packet( secret, request_authenticator=request_authenticator, code=code) except (InvalidMessageAuthenticatorError, InvalidResponseAuthenticatorError) as exception: raise MessageParseError("Unable to validate Radius packet") \ from exception raise MessageParseError("Unable to parse radius code: %d" % code)
def parse(cls, packed_value): # TODO how do we want to do valid length checking here? # # Parsing is (generally) for packets coming from the radius server. # Packing is (generally) for packets going to the radius server. # # Therefore we error out if length is too long # (you are not allowed to have AVP that are too long) try: return cls(struct.unpack("!%ds" % len(packed_value), packed_value)[0]) except struct.error as exception: raise MessageParseError("%s unable to unpack." % cls.__name__) from exception