예제 #1
0
파일: SAPMS.py 프로젝트: pyq881120/pysap
class SAPMSProperty(PacketNoPadded):
    """SAP Message Server Property packet.

    Packet containing information about properties.
    """
    name = "SAP Message Server Property"
    fields_desc = [
        StrNullFixedLenField("client", None, 39),
        IntEnumField("id", 0x00, ms_property_id_values),

        # MS_PROPERTY_VHOST
        ConditionalField(ShortEnumKeysField("logon", 0, ms_logon_type_values), lambda pkt:pkt.id in [0x02]),

        # MS_PROPERTY_IPADR
        ConditionalField(IPField("address", "0.0.0.0"), lambda pkt:pkt.id in [0x03]),
        ConditionalField(IP6Field("address6", "::"), lambda pkt:pkt.id in [0x03]),

        # MS_PROPERTY_PARAM
        ConditionalField(StrNullField("param", ""), lambda pkt:pkt.id in [0x04]),
        ConditionalField(StrNullField("value", ""), lambda pkt:pkt.id in [0x04]),

        # MS_PROPERTY_SERVICE
        ConditionalField(ShortField("service", 0), lambda pkt:pkt.id in [0x05]),

        # Release Information fields
        ConditionalField(StrNullFixedLenField("release", "720", length=9), lambda pkt:pkt.id in [0x07]),
        ConditionalField(IntField("patchno", 0), lambda pkt:pkt.id in [0x07]),
        ConditionalField(IntField("supplvl", 0), lambda pkt:pkt.id in [0x07]),
        ConditionalField(IntField("platform", 0), lambda pkt:pkt.id in [0x07]),
    ]
예제 #2
0
class SAPCARArchiveFilev201Format(PacketNoPadded):
    """SAP CAR file information format

    This is used to parse files inside a SAP CAR archive.
    """
    name = "SAP CAR Archive File 2.01"

    fields_desc = [
        StrFixedLenField("type", SAPCAR_TYPE_FILE, 2),
        LEIntField("perm_mode", 0),
        LEIntField("file_length", 0),
        LEIntField("unknown1", 0),
        LEIntField("unknown2", 0),
        LEIntField("timestamp", 0),
        StrFixedLenField("unknown3", None, 10),
        FieldLenField("filename_length", None, length_of="filename", fmt="<H"),
        StrNullFixedLenField("filename",
                             None,
                             length_from=lambda x: x.filename_length - 1),
        ConditionalField(
            StrFixedLenField("mark", "ED", 2),
            lambda x: x.type == SAPCAR_TYPE_FILE and x.file_length > 0),
        ConditionalField(
            PacketField("compressed", None, SAPCARCompressedFileFormat),
            lambda x: x.type == SAPCAR_TYPE_FILE and x.file_length > 0),
        ConditionalField(
            LESignedIntField("checksum", 0),
            lambda x: x.type == SAPCAR_TYPE_FILE and x.file_length > 0),
    ]
예제 #3
0
class SAPDiagError(PacketNoPadded):
    """SAP Diag Error packet

    This packet holds Diag error packets.
    """
    name = "SAP Diag Error"
    # TODO: Need to figure out the meaning of the packets
    fields_desc = [
        StrNullFixedLenField("msg", "**DPTMMSG**", length=12),
        StrField("padd", None),
    ]
예제 #4
0
class SAPEnqueueTracePattern(PacketNoPadded):
    """SAP Enqueue Server Admin Trace Pattern
    """
    name = "SAP Enqueue Server Admin Trace Pattern"
    fields_desc = [
        FieldLenField("len", None, length_of="pattern", fmt="B"),
        StrNullFixedLenField("pattern",
                             "",
                             length_from=lambda pkt: pkt.len,
                             max_length=0xff),
    ]
예제 #5
0
class SAPRouterInfoClient(PacketNoPadded):
    """SAP Router Protocol Information Request Client info

    This packet is used to return the information of a connected client.
    """
    name = "SAP Router Client Info"
    fields_desc = [  # 137 bytes length
        IntField("id", 1),
        BitField("flag_XXX1", 0, 1),
        BitField("flag_XXX2", 0, 1),
        BitField("flag_XXX3", 0, 1),
        BitField("flag_XXX4", 0, 1),
        BitField("flag_XXX5", 0, 1),
        BitField("flag_traced", 0, 1),
        BitField("flag_connected", 0, 1),
        BitField("flag_routed", 0, 1),
        LongField("connected_on", 0),
        StrNullFixedLenField("address", None, length=45),
        StrNullFixedLenField("partner", None, length=45),
        StrNullFixedLenField("service", None, length=27),
        StrFixedLenField("XXX3", None, length=4),
    ]
예제 #6
0
class SAPMS(Packet):
    """SAP Message Server packet

    This packet is used for the Message Server protocol.
    """
    name = "SAP Message Server"
    fields_desc = [
        StrFixedLenField("eyecatcher", "**MESSAGE**\x00", 12),
        ByteField("version", 0x04),
        ByteEnumKeysField("errorno", 0x00, ms_errorno_values),
        StrFixedLenField("toname", "-" + " " * 39, 40),
        FlagsField("msgtype", 0, 8,
                   ["DIA", "UPD", "ENQ", "BTC", "SPO", "UP2", "ATP", "ICM"]),
        ByteField("reserved", 0x00),
        ByteEnumKeysField("domain", 0x00, ms_domain_values),
        ByteField("reserved", 0x00),
        StrFixedLenField("key", "\x00" * 8, 8),
        ByteEnumKeysField("flag", 0x01, ms_flag_values),
        ByteEnumKeysField("iflag", 0x01, ms_iflag_values),
        StrFixedLenField("fromname", "-" + " " * 39, 40),
        ShortField("padd", 0x0000),

        # OpCode fields
        ConditionalField(ByteEnumKeysField("opcode", 0x00, ms_opcode_values),
                         lambda pkt: pkt.iflag in [0x00, 0x01]),
        ConditionalField(
            ByteEnumKeysField("opcode_error", 0x00, ms_opcode_error_values),
            lambda pkt: pkt.iflag in [0x00, 0x01]),
        ConditionalField(ByteField("opcode_version", 0x01),
                         lambda pkt: pkt.iflag in [0x00, 0x01]),
        ConditionalField(ByteField("opcode_charset", 0x03),
                         lambda pkt: pkt.iflag in [0x00, 0x01]),
        ConditionalField(
            StrField("opcode_value", ""),
            lambda pkt: pkt.iflag in [0x00, 0x01] and pkt.opcode not in [
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
                0x11, 0x1c, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
                0x2a, 0x2b, 0x2c, 0x2d, 0x2f, 0x43, 0x44, 0x45, 0x46, 0x47,
                0x4a
            ]),

        # Adm OpCode fields
        ConditionalField(
            StrFixedLenField("adm_eyecatcher", "AD-EYECATCH\x00", 12),
            lambda pkt: pkt.iflag == 0x05),
        ConditionalField(ByteField("adm_version", 0x01),
                         lambda pkt: pkt.iflag == 0x05),
        ConditionalField(
            ByteEnumKeysField("adm_type", 0x01, ms_adm_type_values),
            lambda pkt: pkt.iflag == 0x05),
        ConditionalField(IntToStrField("adm_recsize", 104, 11),
                         lambda pkt: pkt.iflag == 0x05),
        ConditionalField(IntToStrField("adm_recno", 1, 11),
                         lambda pkt: pkt.iflag == 0x05),
        ConditionalField(PacketListField("adm_records", None, SAPMSAdmRecord),
                         lambda pkt: pkt.iflag == 0x05),

        # Server List fields
        ConditionalField(
            PacketListField("clients", None, SAPMSClient1), lambda pkt: pkt.
            opcode in [0x02, 0x03, 0x04, 0x05] and pkt.opcode_version == 0x01),
        ConditionalField(
            PacketListField("clients", None, SAPMSClient2), lambda pkt: pkt.
            opcode in [0x02, 0x03, 0x04, 0x05] and pkt.opcode_version == 0x02),
        ConditionalField(
            PacketListField("clients", None, SAPMSClient3), lambda pkt: pkt.
            opcode in [0x02, 0x03, 0x04, 0x05] and pkt.opcode_version == 0x03),
        ConditionalField(
            PacketListField("clients", None, SAPMSClient4), lambda pkt: pkt.
            opcode in [0x02, 0x03, 0x04, 0x05] and pkt.opcode_version == 0x04),

        # Change IP fields
        ConditionalField(IPField("change_ip_addressv4", "0.0.0.0"),
                         lambda pkt: pkt.opcode == 0x06),
        ConditionalField(
            IP6Field("change_ip_addressv6", "::"),
            lambda pkt: pkt.opcode == 0x06 and pkt.opcode_version == 0x02),

        # Get/Set Text fields
        ConditionalField(StrFixedLenField("text_name", "", 40),
                         lambda pkt: pkt.opcode in [0x22, 0x23]),
        ConditionalField(
            FieldLenField("text_length",
                          None,
                          length_of="text_value",
                          fmt="!I"), lambda pkt: pkt.opcode in [0x22, 0x23]),
        ConditionalField(
            StrFixedLenField("text_value",
                             "",
                             length_from=lambda pkt: pkt.text_length or 80),
            lambda pkt: pkt.opcode in [0x22, 0x23]),

        # Counter fields
        ConditionalField(
            PacketField("counter", None, SAPMSCounter),
            lambda pkt: pkt.opcode in [0x24, 0x25, 0x26, 0x27, 0x28, 0x29]),
        ConditionalField(PacketListField("counters", None, SAPMSCounter),
                         lambda pkt: pkt.opcode in [0x2a]),

        # Security Key 1 fields
        ConditionalField(StrFixedLenField("security_name", None, 40),
                         lambda pkt: pkt.opcode in [0x07, 0x08]),
        ConditionalField(StrFixedLenField("security_key", None, 256),
                         lambda pkt: pkt.opcode in [0x07, 0x08]),

        # Security Key 2 fields
        ConditionalField(IPField("security2_addressv4", "0.0.0.0"),
                         lambda pkt: pkt.opcode == 0x09),
        ConditionalField(ShortField("security2_port", 0),
                         lambda pkt: pkt.opcode == 0x09),
        ConditionalField(StrFixedLenField("security2_key", None, 256),
                         lambda pkt: pkt.opcode == 0x09),
        ConditionalField(IP6Field("security2_addressv6", "::"),
                         lambda pkt: pkt.opcode == 0x09),

        # Hardware ID field
        ConditionalField(StrNullFixedLenField("hwid", "", length=99),
                         lambda pkt: pkt.opcode == 0x0a),

        # Statistics
        ConditionalField(PacketField("stats", None, SAPMSStat3),
                         lambda pkt: pkt.opcode == 0x11 and pkt.flag == 0x03),

        # Codepage
        ConditionalField(IntField("codepage", 0),
                         lambda pkt: pkt.opcode == 0x1c and pkt.flag == 0x03),

        # Dump Info Request fields
        ConditionalField(ByteField("dump_dest", 0x02),
                         lambda pkt: pkt.opcode == 0x1E and pkt.flag == 0x02),
        ConditionalField(StrFixedLenField("dump_filler", "\x00\x00\x00", 3),
                         lambda pkt: pkt.opcode == 0x1E and pkt.flag == 0x02),
        ConditionalField(ShortField("dump_index", 0x00),
                         lambda pkt: pkt.opcode == 0x1E and pkt.flag == 0x02),
        ConditionalField(
            ShortEnumKeysField("dump_command", 0x01, ms_dump_command_values),
            lambda pkt: pkt.opcode == 0x1E and pkt.flag == 0x02),
        ConditionalField(StrFixedLenField("dump_name", "\x00" * 40, 40),
                         lambda pkt: pkt.opcode == 0x1E and pkt.flag == 0x02),

        # File Reload fields
        ConditionalField(
            ByteEnumKeysField("file_reload", 0, ms_file_reload_values),
            lambda pkt: pkt.opcode == 0x1f),
        ConditionalField(StrFixedLenField("file_filler", "\x00\x00\x00", 3),
                         lambda pkt: pkt.opcode == 0x1f),

        # Get/Set/Del Logon fields
        ConditionalField(PacketField("logon", None, SAPMSLogon),
                         lambda pkt: pkt.opcode in [0x2b, 0x2c, 0x2d]),

        # Server Disconnect/Shutdown fields
        ConditionalField(PacketField("shutdown_client", None, SAPMSClient3),
                         lambda pkt: pkt.opcode in [0x2e, 0x2f, 0x30, 0x4a]),
        ConditionalField(
            FieldLenField("shutdown_reason_length",
                          None,
                          length_of="shutdown_reason",
                          fmt="!H"),
            lambda pkt: pkt.opcode in [0x2e, 0x2f, 0x30, 0x4a]),
        ConditionalField(
            StrLenField("shutdown_reason",
                        "",
                        length_from=lambda pkt: pkt.shutdown_reason_length),
            lambda pkt: pkt.opcode in [0x2e, 0x2f, 0x30, 0x4a]),

        # Get/Set Property fields
        ConditionalField(PacketField("property", None, SAPMSProperty),
                         lambda pkt: pkt.opcode in [0x43, 0x44, 0x45]),

        # IP/Port to name fields
        ConditionalField(
            IPField("ip_to_name_address4", "0.0.0.0"),
            lambda pkt: pkt.opcode == 0x46 and pkt.opcode_version == 0x01),
        ConditionalField(
            IP6Field("ip_to_name_address6", "::"),
            lambda pkt: pkt.opcode == 0x46 and pkt.opcode_version == 0x02),
        ConditionalField(ShortField("ip_to_name_port", 0),
                         lambda pkt: pkt.opcode == 0x46),
        ConditionalField(
            FieldLenField("ip_to_name_length",
                          None,
                          length_of="ip_to_name",
                          fmt="!I"), lambda pkt: pkt.opcode == 0x46),
        ConditionalField(
            StrLenField("ip_to_name",
                        "",
                        length_from=lambda pkt: pkt.logonname_length),
            lambda pkt: pkt.opcode == 0x46),

        # Check ACL fields
        ConditionalField(ShortField("error_code", 0),
                         lambda pkt: pkt.opcode == 0x47),
        ConditionalField(StrFixedLenField("acl", "", 46),
                         lambda pkt: pkt.opcode == 0x47),
    ]
예제 #7
0
class SAPRouter(Packet):
    """SAP Router packet

    This packet is used for general SAP Router packets. There are (at least)
    five types of SAP Router packets:

        1. Route packets. For requesting the routing of a connection to a
        remote hosts. The packet contains some general information and a
        connection string with a list of routing hops (:class:`SAPRouterRouteHop`).

        2. Administration packets. This packet is used for the SAP Router to
        send administrative commands. It's suppose to be used only from the
        hosts running the SAP Router or when an specific route is included in
        the routing table. Generally administration packets are not accepted
        from the external binding.

        3. Error Information packets. Packets sent when an error occurred.

        4. Control Message packets. Used to perform some control activities,
        like retrieving the current SAPRouter version or to perform the SNC
        handshake. They have the same structure that error information
        packets.

        5. Route accepted packet. Used to acknowledge a route request
        ("NI_PONG").


    Routed packets and some responses doesn't fill in these five packet
    types. For identifying those cases, you should check the type using the
    function :class:`router_is_known_type`.

    NI Versions found (unconfirmed):
        - 30: Release 40C
        - 36: Release <6.20
        - 38: Release 7.00/7.10
        - 39: Release 7.11
        - 40: Release 7.20/7.21
    """

    # Constants for router types
    SAPROUTER_ROUTE = "NI_ROUTE"
    """ :cvar: Constant for route packets
        :type: C{string} """

    SAPROUTER_ADMIN = "ROUTER_ADM"
    """ :cvar: Constant for administration packets
        :type: C{string} """

    SAPROUTER_ERROR = "NI_RTERR"
    """ :cvar: Constant for error information packets
        :type: C{string} """

    SAPROUTER_CONTROL = "NI_RTERR"
    """ :cvar: Constant for control messages packets
        :type: C{string} """

    SAPROUTER_PONG = "NI_PONG"
    """ :cvar: Constant for route accepted packets
        :type: C{string} """

    router_type_values = [
        SAPROUTER_ADMIN,
        SAPROUTER_ERROR,
        SAPROUTER_CONTROL,
        SAPROUTER_ROUTE,
        SAPROUTER_PONG,
    ]
    """ :cvar: List of known packet types
        :type: ``list`` of C{string} """

    name = "SAP Router"
    fields_desc = [
        # General fields present in all SAP Router packets
        StrNullField("type", SAPROUTER_ROUTE),

        ConditionalField(ByteField("version", 0x02), lambda pkt:router_is_known_type(pkt) and not router_is_pong(pkt)),

        # Route packets
        ConditionalField(ByteField("route_ni_version", 0x28), router_is_route),
        ConditionalField(ByteField("route_entries", 0), router_is_route),
        ConditionalField(ByteEnumKeysField("route_talk_mode", 0, router_ni_talk_mode_values), router_is_route),
        ConditionalField(ShortField("route_padd", 0), router_is_route),
        ConditionalField(ByteField("route_rest_nodes", 0), router_is_route),
        ConditionalField(FieldLenField("route_length", 0, length_of="route_string", fmt="I"), router_is_route),
        ConditionalField(IntField("route_offset", 0), router_is_route),
        ConditionalField(PacketListField("route_string", None, SAPRouterRouteHop,
                                         length_from=lambda pkt:pkt.route_length), router_is_route),

        # Admin packets
        ConditionalField(ByteEnumKeysField("adm_command", 0x02, router_adm_commands), router_is_admin),
        ConditionalField(ShortField("adm_unused", 0x00), lambda pkt:router_is_admin(pkt) and pkt.adm_command not in [10, 11, 12, 13]),

        # Info Request fields
        ConditionalField(StrNullFixedLenField("adm_password", "", 19), lambda pkt:router_is_admin(pkt) and pkt.adm_command in [2]),

        # Cancel Route fields
        ConditionalField(FieldLenField("adm_client_count", None, count_of="adm_client_ids", fmt="H"), lambda pkt:router_is_admin(pkt) and pkt.adm_command in [6]),
        ConditionalField(FieldListField("adm_client_ids", [0x00], IntField("", 0), count_from=lambda pkt:pkt.adm_client_count), lambda pkt:router_is_admin(pkt) and pkt.adm_command in [6]),

        # Trace Connection fields
        ConditionalField(FieldLenField("adm_client_count", None, count_of="adm_client_ids", fmt="I"), lambda pkt:router_is_admin(pkt) and pkt.adm_command in [12, 13]),
        ConditionalField(FieldListField("adm_client_ids", [0x00], IntField("", 0), count_from=lambda pkt:pkt.adm_client_count), lambda pkt:router_is_admin(pkt) and pkt.adm_command in [12, 13]),

        # Set/Clear Peer Trace fields  # TODO: Check whether this field should be a IPv6 address or another proper field
        ConditionalField(StrFixedLenField("adm_address_mask", "", 32), lambda pkt:router_is_admin(pkt) and pkt.adm_command in [10, 11]),

        # Error Information/Control Messages fields
        ConditionalField(ByteEnumKeysField("opcode", 0, router_control_opcodes), lambda pkt: router_is_error(pkt) or router_is_control(pkt)),
        ConditionalField(ByteField("opcode_padd", 0), lambda pkt: router_is_error(pkt) or router_is_control(pkt)),
        ConditionalField(SignedIntEnumField("return_code", 0, router_return_codes), lambda pkt: router_is_error(pkt) or router_is_control(pkt)),

        # Error Information fields
        ConditionalField(FieldLenField("err_text_length", None, length_of="err_text_value", fmt="!I"), lambda pkt: router_is_error(pkt) and pkt.opcode == 0),
        ConditionalField(PacketField("err_text_value", SAPRouterError(), SAPRouterError), lambda pkt: router_is_error(pkt) and pkt.opcode == 0),
        ConditionalField(IntField("err_text_unknown", 0), lambda pkt: router_is_error(pkt) and pkt.opcode == 0),

        # Control Message fields
        ConditionalField(IntField("control_text_length", 0), lambda pkt: router_is_control(pkt) and pkt.opcode != 0),
        ConditionalField(StrField("control_text_value", "*ERR"), lambda pkt: router_is_control(pkt) and pkt.opcode != 0),

        # SNC Frame fields
        ConditionalField(PacketField("snc_frame", None, SAPSNCFrame), lambda pkt: router_is_control(pkt) and pkt.opcode in [70, 71])
    ]
예제 #8
0
class SAPEnqueue(PacketNoPadded):
    """SAP Enqueue Server packet

    This packet is used for general Enqueue packets.
    """

    name = "SAP Enqueue"
    fields_desc = [
        StrFixedLenField("magic_bytes", "\xab\xcd\xe1\x23", 4),
        IntField("id", 0),
        LenField("len", None, fmt="!I"),
        LenField("len_frag", None, fmt="!I"),
        ByteEnumKeysField("dest", 0x00, enqueue_dest_values),
        ByteEnumKeysField("opcode", 0x00, enqueue_conn_admin_opcode_values),
        ByteField("more_frags", 0),
        ByteEnumKeysField("type", 0x00, enqueue_type_values),

        # Server Admin fields
        ConditionalField(StrNullFixedLenField("adm_eyecatcher1", "ENC", 3),
                         lambda pkt: pkt.dest == 3),
        ConditionalField(ByteField("adm_version", 1),
                         lambda pkt: pkt.dest == 3),
        ConditionalField(ByteField("adm_padd1", 0), lambda pkt: pkt.dest == 3),
        ConditionalField(ByteField("adm_padd2", 0), lambda pkt: pkt.dest == 3),
        ConditionalField(ByteField("adm_padd3", 0), lambda pkt: pkt.dest == 3),
        ConditionalField(StrFixedLenField("adm_eyecatcher2", "#EAA", 4),
                         lambda pkt: pkt.dest == 3),
        ConditionalField(ByteField("adm_1", 1), lambda pkt: pkt.dest == 3),
        ConditionalField(IntField("adm_len", 0), lambda pkt: pkt.dest == 3),
        ConditionalField(
            ByteEnumKeysField("adm_opcode", 0,
                              enqueue_server_admin_opcode_values),
            lambda pkt: pkt.dest == 3),
        ConditionalField(ByteField("adm_flags", 0), lambda pkt: pkt.dest == 3),
        ConditionalField(IntField("adm_rc", 0), lambda pkt: pkt.dest == 3),
        ConditionalField(StrFixedLenField("adm_eyecatcher3", "#EAE", 4),
                         lambda pkt: pkt.dest == 3),

        # Server Admin Trace fields
        ConditionalField(
            ByteField("adm_trace_protocol_version", 1),
            lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]),
        ConditionalField(
            ByteEnumKeysField("adm_trace_action", 3,
                              enqueue_server_admin_trace_action_values),
            lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]),
        ConditionalField(
            ByteEnumKeysField("adm_trace_limit", 0,
                              enqueue_server_admin_trace_limit_values),
            lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]),
        ConditionalField(
            ByteEnumKeysField("adm_trace_thread", 0,
                              enqueue_server_admin_trace_thread_values),
            lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]),
        ConditionalField(
            IntField("adm_trace_unknown1", 0),
            lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]),
        ConditionalField(
            IntField("adm_trace_level", 1),
            lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]),
        ConditionalField(
            IntField("adm_trace_level1", 1),
            lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]),
        ConditionalField(
            ByteField("adm_trace_logging", 0),
            lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]),
        ConditionalField(
            IntField("adm_trace_max_file_size", 20 * 1024 * 1024),
            lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]),
        ConditionalField(
            FieldLenField("adm_trace_nopatterns",
                          0,
                          count_of="adm_trace_patterns",
                          fmt="!I"),
            lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]),
        ConditionalField(
            FieldLenField("adm_trace_nopatterns1",
                          0,
                          count_of="adm_trace_patterns",
                          fmt="!I"),
            lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]),
        ConditionalField(
            IntField("adm_trace_unknown3", 37),
            lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]),
        ConditionalField(
            StrFixedLenField("adm_trace_eyecatcher4", "#EAH", 4),
            lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]),
        ConditionalField(
            PacketListField("adm_trace_patterns",
                            None,
                            SAPEnqueueTracePattern,
                            count_from=lambda pkt: pkt.adm_trace_nopatterns),
            lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]),
        ConditionalField(
            StrFixedLenField("adm_trace_eyecatcher5", "#EAD", 4),
            lambda pkt: pkt.dest == 3 and pkt.adm_opcode in [0x06]),

        # Connection Admin fields
        ConditionalField(
            FieldLenField("params_count", None, count_of="params", fmt="!I"),
            lambda pkt: pkt.dest == 6 and pkt.opcode in [1, 2]),
        ConditionalField(
            PacketListField("params",
                            None,
                            SAPEnqueueParam,
                            count_from=lambda pkt: pkt.params_count),
            lambda pkt: pkt.dest == 6 and pkt.opcode in [1, 2]),
    ]

    def post_build(self, pkt, pay):
        """Adjust the len and len_frags fields after the build of the whole
        packet. """
        l = struct.pack("!I", len(pkt) + len(pay))
        pkt = pkt[:8] + l + l + pkt[16:]
        return pkt + pay
예제 #9
0
class SAPCARArchiveFilev201Format(PacketNoPadded):
    """SAP CAR file information format

    This is used to parse files inside a SAP CAR archive.
    """
    name = "SAP CAR Archive File 2.01"

    version = SAPCAR_VERSION_201

    fields_desc = [
        StrFixedLenField("type", SAPCAR_TYPE_FILE, 2),
        LEIntField("perm_mode", 0),
        LEIntField("file_length", 0),
        LEIntField("unknown1", 0),
        LEIntField("unknown2", 0),
        LEIntField("timestamp", 0),
        StrFixedLenField("unknown3", None, 10),
        FieldLenField("filename_length", None, length_of="filename", fmt="<H"),
        StrNullFixedLenField("filename", None, length_from=lambda x: x.filename_length - 1),
        ConditionalField(PacketListStopField("blocks", None, SAPCARCompressedBlockFormat, stop=sapcar_is_last_block),
                         lambda x: x.type == SAPCAR_TYPE_FILE and x.file_length > 0),
    ]

    def extract(self, fd):
        """Extracts the archive file and writes the extracted file to the provided file object. Returns the checksum
        obtained from the archive. If blocks are uncompressed, the file is directly extracted. If the blocks are
        compressed, each block is decompressed independently. Checksum is obtained from the last block.

        :param fd: file-like object to write the extracted file to
        :type fd: file

        :return: checksum
        :rtype: int

        :raise DecompressError: If there's a decompression error
        :raise SAPCARInvalidFileException: If the file is invalid
        """
        if self.file_length == 0:
            return 0

        checksum = 0

        remaining_length = self.file_length
        for block in self.blocks:
            # Process uncompressed block types
            if block.type in [SAPCAR_BLOCK_TYPE_UNCOMPRESSED, SAPCAR_BLOCK_TYPE_UNCOMPRESSED_LAST]:
                fd.write(block.compressed)
                remaining_length -= len(block.compressed)
            # Process compressed block types
            elif block.type in [SAPCAR_BLOCK_TYPE_COMPRESSED, SAPCAR_BLOCK_TYPE_COMPRESSED_LAST]:
                compressed = block.compressed
                exp_block_length = compressed.uncompress_length
                (_, block_length, block_buffer) = decompress(str(compressed)[4:], exp_block_length)
                if block_length != exp_block_length or not block_buffer:
                    raise DecompressError("Error decompressing block")
                fd.write(block_buffer)
                remaining_length -= block_length
            else:
                raise SAPCARInvalidFileException("Invalid block type found")

            # Check last block
            if sapcar_is_last_block(block):
                checksum = block.checksum
                break

        return checksum