class SAPRFC(Packet): """SAP Remote Function Call packet This packet is used for the Remote Function Call (RFC) protocol. """ name = "SAP Remote Function Call" fields_desc = [ ByteField("version", 3), # If the version is 3, the packet has a size > 88h, versions 1 and 2 are 40h ByteEnumKeysField("req_type", 0, rfc_req_type_values), # Normal client fields (GW_NORMAL_CLIENT) ConditionalField(IPField("address", "0.0.0.0"), lambda pkt:pkt.req_type == 0x03), ConditionalField(IntField("padd1", 0), lambda pkt:pkt.req_type == 0x03), ConditionalField(StrFixedLenPaddedField("service", "", length=10), lambda pkt:pkt.req_type == 0x03), ConditionalField(StrFixedLenField("codepage", "1100", length=4), lambda pkt:pkt.req_type == 0x03), ConditionalField(StrFixedLenField("padd2", "\x00" * 6, length=6), lambda pkt:pkt.req_type == 0x03), ConditionalField(StrFixedLenPaddedField("lu", "", length=8), lambda pkt:pkt.req_type == 0x03), ConditionalField(StrFixedLenPaddedField("tp", "", length=8), lambda pkt:pkt.req_type == 0x03), ConditionalField(StrFixedLenPaddedField("conversation_id", "", length=8), lambda pkt:pkt.req_type == 0x03), ConditionalField(ByteField("appc_header_version", 6), lambda pkt:pkt.req_type == 0x03), ConditionalField(ByteField("accept_info", 0xcb), lambda pkt:pkt.req_type == 0x03), ConditionalField(SignedShortField("idx", -1), lambda pkt:pkt.req_type == 0x03), ConditionalField(IP6Field("address6", "::"), lambda pkt:pkt.req_type == 0x03 and pkt.version == 3), ConditionalField(IntField("rc", 0), lambda pkt:pkt.req_type == 0x03), ConditionalField(ByteField("echo_data", 0), lambda pkt:pkt.req_type == 0x03), ConditionalField(ByteField("filler", 0), lambda pkt:pkt.req_type == 0x03), # Monitor Command fields (GW_SEND_CMD) ConditionalField(ByteEnumKeysField("cmd", 0, rfc_monitor_cmd_values), lambda pkt:pkt.req_type == 0x09), ]
class SAPMSAdmRecord(PacketNoPadded): """SAP Message Server Administration Record packet Packet for Message Server administration records. Each administration package has a variable number of records, each one specifies an operation to execute. """ name = "SAP Message Server Adm Record" fields_desc = [ ByteEnumKeysField("opcode", 0x00, ms_adm_opcode_values), ByteField("serial_number", 0x00), ByteField("executed", 0x00), ByteField("errorno", 0x00), # TODO: Look for error names ConditionalField(StrFixedLenField("record", None, 100), lambda pkt:pkt.opcode not in [0x01, 0x15, 0x2e]), # TODO: Add more opcodes fields # AD_PROFILE and AD_SHARED_PARAMETER fields ConditionalField(StrNullFixedLenPaddedField("parameter", "", 100), lambda pkt:pkt.opcode in [0x01, 0x2e]), # AD_RZL_STRG opcode ConditionalField(ByteEnumKeysField("rzl_strg_type", 1, ms_adm_rzl_strg_type_values), lambda pkt:pkt.opcode in [0x15]), ConditionalField(ByteField("rzl_strg_name_length", 0), lambda pkt:pkt.opcode in [0x15]), ConditionalField(ByteField("rzl_strg_value_offset", 0), lambda pkt:pkt.opcode in [0x15]), ConditionalField(ByteField("rzl_strg_value_length", 0), lambda pkt:pkt.opcode in [0x15]), ConditionalField(StrFixedLenField("rzl_strg_name", None, 20), lambda pkt:pkt.opcode in [0x15]), ConditionalField(IntField("rzl_strg_integer0", 0), lambda pkt:pkt.opcode in [0x15] and pkt.rzl_strg_type in [11, 15, 21, 31, 41, 51]), ConditionalField(IntField("rzl_strg_integer1", 0), lambda pkt:pkt.opcode in [0x15] and pkt.rzl_strg_type in [11, 15, 21, 31, 41, 51]), ConditionalField(IntField("rzl_strg_integer2", 0), lambda pkt:pkt.opcode in [0x15] and pkt.rzl_strg_type in [11, 15, 21, 31, 41, 51]), ConditionalField(IntField("rzl_strg_integer3", 0), lambda pkt:pkt.opcode in [0x15] and pkt.rzl_strg_type in [11, 15, 21, 31, 41, 51]), ConditionalField(IntField("rzl_strg_integer4", 0), lambda pkt:pkt.opcode in [0x15] and pkt.rzl_strg_type in [11, 15, 21, 31, 41, 51]), ConditionalField(IntField("rzl_strg_integer5", 0), lambda pkt:pkt.opcode in [0x15] and pkt.rzl_strg_type in [11, 15, 21, 31, 41, 51]), ConditionalField(IntField("rzl_strg_integer6", 0), lambda pkt:pkt.opcode in [0x15] and pkt.rzl_strg_type in [11, 15, 21, 31, 41, 51]), ConditionalField(IntField("rzl_strg_integer7", 0), lambda pkt:pkt.opcode in [0x15] and pkt.rzl_strg_type in [11, 15, 21, 31, 41, 51]), ConditionalField(IntField("rzl_strg_integer8", 0), lambda pkt:pkt.opcode in [0x15] and pkt.rzl_strg_type in [11, 15, 21, 31, 41, 51]), ConditionalField(IntField("rzl_strg_integer9", 0), lambda pkt:pkt.opcode in [0x15] and pkt.rzl_strg_type in [11, 15, 21, 31, 41, 51]), ConditionalField(StrFixedLenField("rzl_strg_value", None, 40), lambda pkt:pkt.opcode in [0x15] and pkt.rzl_strg_type not in [11, 15, 21, 31, 41, 51]), ConditionalField(StrFixedLenField("rzl_strg_padd2", None, 36), lambda pkt:pkt.opcode in [0x15]), ]
class SAPDiagItem(PacketNoPadded): """SAP Diag Item packet This packet holds the different types of Diag items. The value field is interpreted according to the Type/ID/SID specified for the item. """ name = "SAP Diag Item" fields_desc = [ ByteEnumKeysField("item_type", 0, diag_item_types), ConditionalField(ByteEnumKeysField("item_id", 0, diag_appl_ids), diag_item_is_appl_appl4), ConditionalField( ByteMultiEnumKeysField("item_sid", 0, diag_appl_sids, depends_on=lambda item: item.item_id, fmt="B"), diag_item_is_appl_appl4), ConditionalField( FieldLenField("item_length", None, length_of="item_value", fmt="!H"), diag_item_is_short), ConditionalField( FieldLenField("item_length4", None, length_of="item_value", fmt="!I"), diag_item_is_long), MutablePacketField( "item_value", None, length_from=diag_item_get_length, get_class=diag_item_get_class, evaluators=[ lambda item: item.item_type, lambda item: item.item_id, lambda item: item.item_sid ], ) ]
class SAPMSClient3(Packet): """SAP Message Server Client packet version 3 Packet that contains information about a client of the Message Server service. This packet is for version 3. """ name = "SAP Message Server Client version 3" fields_desc = [ StrFixedLenField("client", None, 40), StrFixedLenField("host", None, 64), StrFixedLenField("service", None, 20), FlagsField("msgtype", 0, 8, ["ICM", "ATP", "UP2", "SPO", "BTC", "ENQ", "UPD", "DIA"]), IP6Field("hostaddrv6", "::1"), IPField("hostaddrv4", "0.0.0.0"), ShortField("servno", 0x00), ByteEnumKeysField("status", 0x00, ms_client_status_values), ByteField("nitrace", 0x00), ByteField("padd", 0), ]
class SAPMSClient2(PacketNoPadded): """SAP Message Server Client packet version 2 Packet that contains information about a client of the Message Server service. This packet is for version 2, which has been seen only on old releases (SAP NW 2004s). """ name = "SAP Message Server Client version 2" fields_desc = [ StrFixedLenField("client", None, 40), StrFixedLenField("host", None, 32), StrFixedLenField("service", None, 20), FlagsField("msgtype", 0, 8, ["ICM", "ATP", "UP2", "SPO", "BTC", "ENQ", "UPD", "DIA"]), IPField("hostaddrv4", "0.0.0.0"), ShortField("servno", 0x00), ByteEnumKeysField("status", 0x00, ms_client_status_values), ByteField("nitrace", 0x00), StrFixedLenField("padd", None, 14), ]
class SAPDiagUIEventSource(PacketNoPadded): name = "UI Event Source" fields_desc = [ BitField("valid_unused", 0, 4), BitField("valid_functionkey_data", 0, 1), BitField("valid_navigation_data", 0, 1), BitField("valid_control_pos", 0, 1), BitField("valid_menu_pos", 0, 1), ShortEnumKeysField("event_type", 0, diag_ui_event_type_values), ShortEnumKeysField("control_type", 0, diag_ui_event_control_values), ConditionalField( ByteEnumKeysField("navigation_data", 0, diag_ui_event_navigation_data_values), lambda pkt: pkt.valid_navigation_data), ConditionalField(ByteField("event_data", 0), lambda pkt: not pkt.valid_navigation_data), ShortField("control_row", 0), ShortField("control_col", 0), FieldLenField("container_nrs", None, count_of="containers"), FieldListField("containers", None, ByteField("container", 0), count_from=lambda x: x.container_nrs) ]
class SAPDiagDyntAtomItem(PacketNoPadded): name = "SAP Diag Dynt Atom item" fields_desc = [ ShortField("atom_length", 0), ByteField("dlg_flag_1", 0), ByteField("dlg_flag_2", 0), ByteEnumKeysField("etype", 0, diag_atom_etypes), ByteField("area", 0), ByteField("block", 0), ByteField("group", 0), ShortField("row", 0), ShortField("col", 0), # Attr flags BitField("attr_DIAG_BSD_COMBOSTYLE", 0, 1), # 80 BitField("attr_DIAG_BSD_YES3D", 0, 1), # 40 BitField("attr_DIAG_BSD_PROPFONT", 0, 1), # 20 BitField("attr_DIAG_BSD_MATCHCODE", 0, 1), # 10 BitField("attr_DIAG_BSD_JUSTRIGHT", 0, 1), # 08 BitField("attr_DIAG_BSD_INTENSIFY", 0, 1), # 04 BitField("attr_DIAG_BSD_INVISIBLE", 0, 1), # 02 BitField("attr_DIAG_BSD_PROTECTED", 0, 1), # 01 # DIAG_DGOTYP_FNAME ConditionalField( StrLenField("name_text", "", length_from=lambda pkt: pkt.atom_length - 13), lambda pkt: pkt.etype == 114), # DIAG_DGOTYP_PUSHBUTTON_2 */ ConditionalField(ByteField("pushbutton_v_length", 0), lambda pkt: pkt.etype in [115]), ConditionalField(ByteField("pushbutton_v_height", 0), lambda pkt: pkt.etype in [115]), ConditionalField(ShortField("pushbutton_function_code_offset", 0), lambda pkt: pkt.etype in [115]), ConditionalField(ShortField("pushbutton_text_offset", 0), lambda pkt: pkt.etype in [115]), ConditionalField(StrField("pushbutton_text", ""), lambda pkt: pkt.etype in [115]), ConditionalField(StrField("pushbutton_function_code", ""), lambda pkt: pkt.etype in [115]), # DIAG_DGOTYP_TABSTRIP_BUTTON ConditionalField(ByteField("tabstripbutton_v_length", 0), lambda pkt: pkt.etype in [116]), ConditionalField(ByteField("tabstripbutton_v_height", 0), lambda pkt: pkt.etype in [116]), ConditionalField(ByteField("tabstripbutton_page_id", 0), lambda pkt: pkt.etype in [116]), ConditionalField(ShortField("tabstripbutton_function_code_offset", 0), lambda pkt: pkt.etype in [116]), ConditionalField(ShortField("tabstripbutton_text_offset", 0), lambda pkt: pkt.etype in [116]), ConditionalField(ShortField("tabstripbutton_id_offset", 0), lambda pkt: pkt.etype in [116]), ConditionalField(StrNullField("tabstripbutton_text", ""), lambda pkt: pkt.etype in [116]), ConditionalField(StrNullField("tabstripbutton_function_code", ""), lambda pkt: pkt.etype in [116]), ConditionalField(StrNullField("tabstripbutton_id", ""), lambda pkt: pkt.etype in [116]), # DIAG_DGOTYP_XMLPROP ConditionalField( StrLenField("xmlprop_text", "", length_from=lambda pkt: pkt.atom_length - 13), lambda pkt: pkt.etype == 120), # DIAG_DGOTYP_EFIELD_1 or DIAG_DGOTYP_OFIELD_1 or DIAG_DGOTYP_KEYWORD_1 ConditionalField(ByteField("field1_flag1", 0), lambda pkt: pkt.etype in [121, 122, 123]), ConditionalField( FieldLenField("field1_dlen", None, fmt="B", length_of="field1_text"), lambda pkt: pkt.etype in [121, 122, 123]), ConditionalField(ByteField("field1_mlen", 0), lambda pkt: pkt.etype in [121, 122, 123]), ConditionalField(ShortField("field1_maxnrchars", 0), lambda pkt: pkt.etype in [121, 122, 123]), ConditionalField( StrLenField("field1_text", "", length_from=lambda pkt: pkt.field1_dlen), lambda pkt: pkt.etype in [121, 122, 123]), # DIAG_DGOTYP_FRAME_1 ConditionalField(ShortField("frame_drows", 0), lambda pkt: pkt.etype in [127]), ConditionalField(ShortField("frame_dcols", 0), lambda pkt: pkt.etype in [127]), ConditionalField( StrLenField("frame_text", "", length_from=lambda pkt: pkt.atom_length - 17), lambda pkt: pkt.etype in [127]), # DIAG_DGOTYP_RADIOBUTTON_3 ConditionalField(ByteField("radiobutton_button", 0), lambda pkt: pkt.etype in [129]), ConditionalField(ShortField("radiobutton_visible_label_length", 0), lambda pkt: pkt.etype in [129]), ConditionalField(ShortField("radiobutton_event_id_off", 0), lambda pkt: pkt.etype in [129]), ConditionalField(ByteField("radiobutton_event_id_len", 0), lambda pkt: pkt.etype in [129]), ConditionalField(ShortField("radiobutton_text_off", 0), lambda pkt: pkt.etype in [129]), ConditionalField(ShortField("radiobutton_text_length", 0), lambda pkt: pkt.etype in [129]), ConditionalField( StrLenField("radiobutton_text", "", length_from=lambda pkt: pkt.radiobutton_event_id_len + pkt.radiobutton_text_length), lambda pkt: pkt.etype in [129]), # DIAG_DGOTYP_EFIELD_2 or DIAG_DGOTYP_OFIELD_2 or DIAG_DGOTYP_KEYWORD_2 ConditionalField(ShortField("field2_flag1", 0), lambda pkt: pkt.etype in [130, 131, 132]), ConditionalField( FieldLenField("field2_dlen", None, fmt="B", length_of="field2_text"), lambda pkt: pkt.etype in [130, 131, 132]), ConditionalField(ByteField("field2_mlen", 0), lambda pkt: pkt.etype in [130, 131, 132]), ConditionalField(ShortField("field2_maxnrchars", 0), lambda pkt: pkt.etype in [130, 131, 132]), ConditionalField( StrLenField("field2_text", "", length_from=lambda pkt: pkt.field2_dlen), lambda pkt: pkt.etype in [130, 131, 132]), # Remaining types ConditionalField( StrLenField("value", "", length_from=lambda pkt: pkt.atom_length - 13), lambda pkt: pkt.etype not in [114, 115, 116, 120, 121, 122, 123, 127, 129, 130, 131, 132]), ] def post_build(self, p, pay): if pay is None: pay = '' # Update the atom_length field (first 2 bytes) with the packet length p = pack("!H", len(p)) + p[2:] return p + pay
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]) ]
class SAPDiag(PacketNoPadded): """SAP Diag packet This packet holds the Diag Header and serve as a container for L{SAPDiagItem} items. It handles compression/decompression, adding the appropriate Compression Header when necessary. """ name = "SAP Diag" fields_desc = [ ByteField("mode", 0), # Communication flags BitField("com_flag_TERM_GRA", 0, 1), BitField("com_flag_TERM_NNM", 0, 1), BitField("com_flag_TERM_CAS", 0, 1), BitField("com_flag_TERM_INI", 0, 1), BitField("com_flag_TERM_EOP", 0, 1), BitField("com_flag_TERM_NOP", 0, 1), BitField("com_flag_TERM_EOC", 0, 1), BitField("com_flag_TERM_EOS", 0, 1), ByteField("mode_stat", 0), ByteField("err_flag", 0), ByteField("msg_type", 0), ByteField("msg_info", 0), ByteField("msg_rc", 0), ByteEnumKeysField("compress", 0, diag_compress_values), # Compression Header ConditionalField(LEIntField("uncompress_length", None), lambda pkt: pkt.compress == 1), ConditionalField( ByteEnumField("algorithm", 0x12, { 0x12: "LZH", 0x10: "LZC" }), lambda pkt: pkt.compress == 1), ConditionalField(StrFixedLenField("magic_bytes", "\x1f\x9d", 2), lambda pkt: pkt.compress == 1), ConditionalField(ByteField("special", 2), lambda pkt: pkt.compress == 1), # SNC Frame ConditionalField(PacketField("snc_frame", None, SAPSNCFrame), lambda pkt: pkt.compress in [2, 3]), # Message info ConditionalField(StrEncodedPaddedField("info", None), lambda pkt: pkt.err_flag != 0), # Payload PacketListField("message", None, SAPDiagItem) ] def do_compress(self, s): """Compress a string using SAP compression C++ extension. @param s: string to compress @type s: C{string} @return: string compression header plus the compressed string @rtype: C{string} @raise pysapcompress.Error: when a compression error is raised """ if (len(s) > 0): # Compress the payload and return the output (_, _, outbuffer) = pysapcompress.compress(s, pysapcompress.ALG_LZH) return outbuffer def do_decompress(self, s, length): """Decompress a string using SAP compression C++ extension. @param s: compression header plus compressed string @type s: C{string} @param length: reported compressed length @type length: C{int} @return: decompressed string @rtype: C{string} @raise pysapcompress.Error: when a decompression error is raised """ if (len(s) > 0): # Decompress the payload and return the output (_, _, outbuffer) = pysapcompress.decompress(s, length) return outbuffer def pre_dissect(self, s): """Prepares the packet for dissection. If the compression flag is set, decompress the payload. """ # If the compression flag is set, decompress everything after the headers if s[7] == "\x01": # First need to get the reported decompressed length (reported_length, ) = unpack("<I", s[8:12]) # Then return the headers (Diag and Compression) and the payload (message field) try: return s[:16] + self.do_decompress(s[8:], reported_length) except DecompressError: return s # Uncompressed packet, just return them return s def post_build(self, p, pay): """Compress the payload. If the compression flag is set, compress both the message field and the payload. """ if pay is None: pay = '' if self.compress == 1: payload = "".join([str(item) for item in self.message]) + pay if (len(payload) > 0): try: return p[:8] + self.do_compress(payload) except CompressError: return p + pay return p + pay def get_item(self, item_type=None, item_id=None, item_sid=None): """Get an item from the packet's message. Returns None if the message is not found, or a list if the item is found multiple times. @param item_type: item type byte or string value @type item_type: C{int} or C{string} or C{list} @param item_id: item ID byte or string value @type item_id: C{int} or C{string} or C{list} @param item_sid: item SID byte or string value @type item_sid: C{int} or C{string} or C{list} @return: list of items found on the packet or None @rtype: C{list} of L{SAPDiagItem} """ # Expand list lookups items = [] if item_type is not None and type(item_type) == list: for itype in item_type: items.extend(self.get_item(itype, item_id, item_sid)) return items if item_id is not None and type(item_id) == list: for iid in item_id: items.extend(self.get_item(item_type, iid, item_sid)) return items if item_sid is not None and type(item_sid) == list: for isid in item_sid: items.extend(self.get_item(item_type, item_id, isid)) return items # Perform name lookups if item_type is not None and isinstance(item_type, str): item_type = list(diag_item_types.keys())[list( diag_item_types.values()).index(item_type)] if item_id is not None and isinstance(item_id, str): item_id = list(diag_appl_ids.keys())[list( diag_appl_ids.values()).index(item_id)] if item_sid is not None and isinstance(item_sid, str): item_sid = list(diag_appl_sids[item_id].keys())[list( diag_appl_sids[item_id].values()).index(item_sid)] # Filter and return items if item_sid is None and item_id is None: items = [ item for item in self.message if hasattr(item, "item_type") and item.item_type == item_type ] elif item_sid is None: items = [ item for item in self.message if hasattr(item, "item_type") and item.item_type == item_type and item.item_id == item_id ] else: items = [ item for item in self.message if hasattr(item, "item_type") and item.item_type == item_type and item.item_id == item_id and item.item_sid == item_sid ] return items
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
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", " " * 40, 40), FlagsField("msgtype", 0, 8, ["DIA", "UPD", "ENQ", "BTC", "SPO", "UP2", "ATP", "ICM"]), StrFixedLenField("reserved", "\x00" * 3, 3), StrFixedLenField("key", "\x00" * 8, 8), ByteEnumKeysField("flag", 0x01, ms_flag_values), ByteEnumKeysField("iflag", 0x01, ms_iflag_values), StrFixedLenField("fromname", " " * 40, 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), ]