Esempio 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
Esempio 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)
Esempio 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
Esempio n. 4
0
    def parse(packed_message, secret, radius_lifecycle=None):
        """
        Args:
            packed_message:
            secret (str): Shared sceret between chewie and RADIUS server.
            radius_lifecycle: RadiusLifecycle object
        Returns:
            RadiusPacket - RadiusAccessChallenge/RadiusAccessRequest/
                            RadiusAccessAccept/RadiusAccessFailure
        Raises:
            MessageParseError: if packed_message cannot be parsed
        """
        try:
            code, packet_id, length, 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 = radius_lifecycle.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 parse Radius packet") \
                    from exception
        raise MessageParseError("Unable to parse radius code: %d" % code)
Esempio 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
Esempio n. 6
0
 def parse(cls, code, packet_id, packed_message):
     """
     Returns:
         EapIdentity.
     Raises:
         MessageParseError if packed message cannot be decoded.
     """
     try:
         identity = packed_message.decode()
     except UnicodeDecodeError as exception:
         raise MessageParseError("%s unable to decode identity" %
                                 cls.__name__) from exception
     return cls(code, packet_id, identity)
Esempio n. 7
0
    def parse(packed_message):
        """

        Args:
            packed_message:
        Returns:
            Eap*** object.
        Raises:
            MessageParseError if packed_message cannot be parsed.
        """
        try:
            code, packet_id, length = struct.unpack(
                "!BBH", packed_message[:EAP_HEADER_LENGTH])
        except struct.error as exception:
            raise MessageParseError(
                "unable to unpack EAP header (4 bytes)") from exception

        if code in (Eap.REQUEST, Eap.RESPONSE):
            try:
                packet_type, = struct.unpack(
                    "!B", packed_message[EAP_HEADER_LENGTH:EAP_HEADER_LENGTH +
                                         EAP_TYPE_LENGTH])
            except struct.error as exception:
                raise MessageParseError("EAP unable to unpack packet_type byte") \
                    from exception

            data = packed_message[EAP_HEADER_LENGTH + EAP_TYPE_LENGTH:length]
            try:
                return PARSERS[packet_type](code, packet_id, data)
            except KeyError as exception:
                raise MessageParseError("EAP packet_type: %s not supported" % packet_type) \
                    from exception
        elif code == Eap.SUCCESS:
            return EapSuccess(packet_id)
        elif code == Eap.FAILURE:
            return EapFailure(packet_id)
        raise MessageParseError("Got Eap packet with bad code: %s" %
                                packed_message)
Esempio n. 8
0
 def parse(cls, code, packet_id, packed_msg):
     """
     Returns:
         EapLegacyNak.
     Raises:
         MessageParseError if cannot unpack packed_message
     """
     value_len = len(packed_msg)
     try:
         desired_auth_types = struct.unpack("!%ds" % value_len, packed_msg)
     except struct.error as exception:
         raise MessageParseError("%s unable to unpack." %
                                 cls.__name__) from exception
     return cls(code, packet_id, desired_auth_types)
Esempio n. 9
0
 def parse(cls, code, packet_id, packed_message):
     """
     Returns:
         EapMd5Challenge.
     Raises:
         MessageParseError if cannot unpack packed_message
     """
     try:
         value_length, = struct.unpack("!B", packed_message[:1])
     except struct.error as exception:
         raise MessageParseError("%s unable to unpack first byte" % cls.__name__) \
             from exception
     challenge = packed_message[1:1 + value_length]
     extra_data = packed_message[1 + value_length:]
     return cls(code, packet_id, challenge, extra_data)
Esempio n. 10
0
    def ethernet_parse(packed_message):
        """Parses the ethernet header part, and payload
        Args:
            packed_message:
        Returns:
            ***Message & destination mac address.
        Raises:
            MessageParseError: the packed_message cannot be parsed."""
        ethernet_packet = EthernetPacket.parse(packed_message)
        if ethernet_packet.ethertype != 0x888e:
            raise MessageParseError(
                "Ethernet packet with bad ethertype received: %s" %
                ethernet_packet)

        return MessageParser.one_x_parse(ethernet_packet.data, ethernet_packet.src_mac), \
               ethernet_packet.dst_mac
Esempio n. 11
0
 def one_x_parse(data, src_mac):
     """Parses the 1x header (version and packet type) part of the packet, and the payload.
     Args:
         data:
         src_mac (MacAddress): source mac address of the data packet.
     Raises:
         MessageParseError: the data cannot be parsed."""
     auth_8021x = Auth8021x.parse(data)
     if auth_8021x.packet_type == 0:
         return MessageParser.eap_parse(auth_8021x.data, src_mac)
     elif auth_8021x.packet_type == 1:
         return EapolStartMessage.build(src_mac)
     elif auth_8021x.packet_type == 2:
         return EapolLogoffMessage.build(src_mac)
     raise MessageParseError("802.1x has bad type, expected 0: %s" %
                             auth_8021x)
Esempio n. 12
0
 def parse(cls, packed_message):
     """construct an Auth8021x from a packed_message
     Args:
         packed_message (bytes):
     Returns:
         Auth8021x
     Raises:
         MessageParseException: if packed_message cannot be parsed successfully.
     """
     try:
         version, packet_type, length = struct.unpack("!BBH",
                                                      packed_message[:AUTH_8021X_HEADER_LENGTH])
     except struct.error as exception:
         raise MessageParseError("Auth8021x unable to parse first 4 bytes") from exception
     data = packed_message[AUTH_8021X_HEADER_LENGTH:AUTH_8021X_HEADER_LENGTH+length]
     return cls(version, packet_type, data)
Esempio n. 13
0
    def eap_parse(data, src_mac):
        """Parses the actual EAP payload
        Args:
            data:
            src_mac (MacAddress): source mac address of the data packet
        Raises:
            MessageParseError: the data cannot be parsed."""
        eap = Eap.parse(data)

        if isinstance(eap, tuple(PARSERS_TYPES.values())):
            return EAP_MESSAGES[eap.PACKET_TYPE].build(src_mac, eap)
        elif isinstance(eap, EapSuccess):
            return SuccessMessage.build(src_mac, eap)
        elif isinstance(eap, EapFailure):
            return FailureMessage.build(src_mac, eap)
        else:
            raise MessageParseError("Got bad Eap packet: %s" % eap)
Esempio n. 14
0
 def parse(cls, packed_message):
     """construct an EthernetPacket from a packed_message
     Args:
         packed_message (bytes):
     Returns:
         EthernetPacket
     Raises:
         MessageParseError: if packed_message cannot be successfully parsed.
     """
     try:
         dst_mac, src_mac, ethertype = struct.unpack(
             "!6s6sH", packed_message[:ETHERNET_HEADER_LENGTH])
     except struct.error as exception:
         raise MessageParseError(
             "Unable to parse Ethernet header (14bytes)") from exception
     data = packed_message[ETHERNET_HEADER_LENGTH:]
     return cls(MacAddress(dst_mac), MacAddress(src_mac), ethertype, data)
Esempio n. 15
0
    def parse(cls, code, packet_id, packed_msg):
        """
        Returns:
            A child of EapTLSBase e.g. EapTLS, EAPTTLS.
        Raises:
            MessageParseError if cannot unpack packed_message
        """
        value_len = len(packed_msg)
        fmt_str = "!B"
        if value_len > 1:
            fmt_str += "%ds" % (value_len - 1)
        try:
            unpacked = struct.unpack(fmt_str, packed_msg)
        except struct.error as exception:
            raise MessageParseError("%s unable to unpack" %
                                    cls.__name__) from exception
        extra_data = b""
        if value_len > 1:
            flags, extra_data = unpacked
        else:
            flags = unpacked[0]

        return cls(code, packet_id, flags, extra_data)