Exemplo n.º 1
0
 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
Exemplo n.º 2
0
    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)
Exemplo n.º 3
0
 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
Exemplo n.º 4
0
    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)
Exemplo n.º 5
0
 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