Exemplo n.º 1
0
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]),
    ]
Exemplo n.º 2
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
Exemplo n.º 3
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),
    ]
Exemplo n.º 4
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),
    ]
Exemplo n.º 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),
    ]
Exemplo n.º 6
0
class SAPMSProperty(Packet):
    """SAP Message Server Property packet.

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

        # MS_PROPERTY_VHOST
        ConditionalField(ShortEnumKeysField("logon", 0, ms_logon_type_values), lambda pkt:pkt.id in [0x02]),
        ConditionalField(StrFixedLenField("pad", None, 12), lambda pkt:pkt.id in [0x02]),
        ConditionalField(ShortField("len", 0), lambda pkt:pkt.id in [0x02]),
        ConditionalField(StrLenField("value", "", length_from=lambda pkt: pkt.len), lambda pkt:pkt.id in [0x02]),
        ConditionalField(ShortField("pad2", 0xffff), 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(FieldLenField("param_len", 0, length_of="param", fmt="I"), lambda pkt:pkt.id in [0x04]),
        ConditionalField(StrLenField("param", "", length_from=lambda pkt: pkt.param_len), lambda pkt:pkt.id in [0x04]),
        ConditionalField(StrLenField("param_padding", "", length_from=lambda pkt: 100 - pkt.param_len), lambda pkt:pkt.id in [0x04]),
        ConditionalField(ShortField("pad3", 0), lambda pkt:pkt.id in [0x04]),
        ConditionalField(FieldLenField("value_len", 0x0, length_of="value", fmt="H"), lambda pkt:pkt.id in [0x04]),
        ConditionalField(StrLenField("value", "", length_from=lambda pkt:pkt.value_len), lambda pkt:pkt.id in [0x04]),

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

        # Release Information fields
        ConditionalField(StrNullFixedLenField("release", "720", length=10), 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]),
    ]
Exemplo n.º 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
    """

    # Default router version to use
    SAPROUTER_DEFAULT_VERSION = 40

    # 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", 2),
            lambda pkt: router_is_known_type(pkt) and not router_is_pong(pkt)),

        # Route packets
        ConditionalField(
            ByteField("route_ni_version", SAPROUTER_DEFAULT_VERSION),
            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]),
        # 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]),

        # Cancel Route or Trace Connection fields
        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, 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 and pkt.err_text_length > 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])
    ]
Exemplo n.º 8
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),
        ConditionalField(ShortField("diag_port", 3200), lambda pkt:pkt.iflag == 0x08 and pkt.flag == 0x02),  # for MS_REQUEST+MS_LOGIN_2 it's the diag port
        ConditionalField(ShortField("padd", 0x0000), lambda pkt:pkt.iflag != 0x08 or pkt.flag != 0x02),

        # OpCode fields
        ConditionalField(ByteEnumKeysField("opcode", 0x01, ms_opcode_values), lambda pkt:pkt.iflag in [0x00, 0x01, 0x02, 0x07]),  # extending all those fields with MS_SEND_TYPE and MS_SEND_TYPE_ONCE packets
        ConditionalField(ByteEnumKeysField("opcode_error", 0x00, ms_opcode_error_values), lambda pkt:pkt.iflag in [0x00, 0x01, 0x02, 0x7]),
        ConditionalField(ByteField("opcode_version", 0x01), lambda pkt:pkt.iflag in [0x00, 0x01, 0x02, 0x07]),
        ConditionalField(ByteField("opcode_charset", 0x03), lambda pkt:pkt.iflag in [0x00, 0x01, 0x02, 0x07]),
        ConditionalField(StrField("opcode_value", ""), lambda pkt:pkt.iflag in [0x00, 0x01] and pkt.opcode not in [0x00, 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]),
        ConditionalField(StrField("opcode_trailer", ""), lambda pkt:pkt.iflag in [0x00, 0x01] and pkt.opcode not in [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x11, 0x1c, 0x1e, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2f, 0x43, 0x44, 0x45, 0x46, 0x47, 0x4a]),

        # Dispatcher info
        ConditionalField(ByteField("dp_version", 0x0), lambda pkt:pkt.opcode == 0x0 or (pkt.opcode_version == 0x00 and pkt.opcode_charset == 0x00)),
        ConditionalField(PacketLenField("dp_info1", SAPDPInfo1(), SAPDPInfo1, length_from=lambda x: 507), lambda pkt:(pkt.opcode == 0x0 or (pkt.opcode_version == 0x00 and pkt.opcode_charset == 0x00)) and pkt.dp_version == 0x0d),  # 745 kernel

        ConditionalField(PacketLenField("dp_info2", SAPDPInfo2(), SAPDPInfo2, length_from=lambda x: 203), lambda pkt:(pkt.opcode == 0x0 or (pkt.opcode_version == 0x00 and pkt.opcode_charset == 0x00)) and pkt.dp_version == 0x0b),  # 720 kernel

        ConditionalField(PacketLenField("dp_info3", SAPDPInfo3(), SAPDPInfo3, length_from=lambda x: 179), lambda pkt:(pkt.opcode == 0x0 or (pkt.opcode_version == 0x00 and pkt.opcode_charset == 0x00)) and pkt.dp_version == 0x0e),  # 749 kernel

        # MS ADM layer
        ConditionalField(StrFixedLenField("adm_eyecatcher", "AD-EYECATCH\x00", 12), lambda pkt: pkt.iflag in [0x00, 0x02, 0x05, 0x07] or pkt.opcode == 0x0),
        ConditionalField(ByteField("adm_version", 0x01), lambda pkt:pkt.iflag in [0x00, 0x02, 0x05, 0x07] or pkt.opcode == 0x0),
        ConditionalField(ByteEnumKeysField("adm_type", 0x01, ms_adm_type_values), lambda pkt:pkt.iflag in [0x00, 0x02, 0x05, 0x07] or pkt.opcode == 0x0),
        ConditionalField(IntToStrField("adm_recsize", 104, 11), lambda pkt:pkt.iflag in [0x00, 0x02, 0x05, 0x07] or pkt.opcode == 0x0),
        ConditionalField(IntToStrField("adm_recno", 1, 11), lambda pkt:pkt.iflag in [0x00, 0x02, 0x05, 0x07] or pkt.opcode == 0x0),
        ConditionalField(PacketListField("adm_records", None, SAPMSAdmRecord), lambda pkt:pkt.iflag in [0x00, 0x02, 0x05, 0x07] or pkt.opcode == 0x0),

        # 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_padding", "\x00\x00", 2), 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),
    ]
Exemplo n.º 9
0
class SAPCARArchiveFilev200Format(PacketNoPadded):
    """SAP CAR file information format

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

    version = SAPCAR_VERSION_200
    is_filename_null_terminated = False

    fields_desc = [
        StrFixedLenField("type", SAPCAR_TYPE_FILE, 2),
        LEIntField("perm_mode", 0),
        LELongField("file_length_low", 0),
        LEIntField("file_length_high", 0),
        LELongField("timestamp", 0),
        LEIntField("code_page", 0),
        FieldLenField("user_info_length", 0, length_of="user_info", fmt="<H"),
        FieldLenField("filename_length", 0, length_of="filename", fmt="<H"),
        StrNullFixedLenField("filename", None, length_from=lambda x: x.filename_length,
                             null_terminated=lambda x: x.is_filename_null_terminated),
        StrFixedLenField("user_info", None, length_from=lambda x: x.user_info_length),
        ConditionalField(PacketListStopField("blocks", None, SAPCARCompressedBlockFormat, stop=sapcar_is_last_block),
                         lambda x: x.type == SAPCAR_TYPE_FILE and x.file_length > 0),
    ]

    @property
    def file_length(self):
        """Getter for the file length fields. It converts the two length fields (low and high) as provided in the
        archive file into a long long integer.
        """
        return (self.file_length_high * SIZE_FOUR_GB) + self.file_length_low

    @file_length.setter
    def file_length(self, file_length):
        """Setter for the file length fields. It splits the long long integer int on the two length fields (low and
        high) as required by the archive file.
        """
        self.file_length_low = file_length & 0xffffffff
        self.file_length_high = file_length >> 32

    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 added to a buffer, skipping the length field, and decompression is performed after
        the block marked as end of data. Expected length and compression header is obtained from the first block and
        checksum from the end of data 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

        compressed = ""
        checksum = 0
        exp_length = None

        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)
            # Store compressed block types for later decompression
            elif block.type in [SAPCAR_BLOCK_TYPE_COMPRESSED, SAPCAR_BLOCK_TYPE_COMPRESSED_LAST]:
                # Add compressed block to a buffer, skipping the first 4 bytes of each block (uncompressed length)
                compressed += str(block.compressed)[4:]
                # If the expected length wasn't already set, do it
                if not exp_length:
                    exp_length = block.compressed.uncompress_length
            else:
                raise SAPCARInvalidFileException("Invalid block type found")

            # Check end of data block, performing decompression if needed
            if sapcar_is_last_block(block):
                checksum = block.checksum
                # If there was at least one compressed block that set the expected length, decompress it
                if exp_length:
                    (_, block_length, block_buffer) = decompress(str(compressed), exp_length)
                    if block_length != exp_length or not block_buffer:
                        raise DecompressError("Error decompressing block")
                    fd.write(block_buffer)
                break

        return checksum
Exemplo n.º 10
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