*
* For documentation of this protocol, see:
*
- * http://wiki.wireshark.org/SMB2
- * http://msdn.microsoft.com/en-us/library/cc246482(PROT.10).aspx
+ * https://wiki.wireshark.org/SMB2
+ * https://msdn.microsoft.com/en-us/library/cc246482.aspx
*
* If you edit this file, keep the wiki updated as well.
*
- * $Id$
- *
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
#include "config.h"
+
#include <epan/packet.h>
-#include <epan/conversation.h>
+#include <epan/prefs.h>
+#include <epan/expert.h>
#include <epan/tap.h>
-#include <epan/wmem/wmem.h>
+#include <epan/srt_table.h>
#include <epan/aftypes.h>
+#include <epan/to_str.h>
+#include <epan/asn1.h>
+#include <epan/reassemble.h>
#include "packet-smb2.h"
-#include "packet-dcerpc.h"
#include "packet-ntlmssp.h"
+#include "packet-kerberos.h"
#include "packet-windows-common.h"
#include "packet-smb-common.h"
-#include "packet-smb.h"
#include "packet-dcerpc-nt.h"
-#include <string.h>
-#include <epan/prefs.h>
-#include <glib.h>
-/* Use libgcrypt for cipher libraries. */
-#ifdef HAVE_LIBGCRYPT
#include <wsutil/wsgcrypt.h>
-#endif /* HAVE_LIBGCRYPT */
+
+#define NT_STATUS_PENDING 0x00000103
+
+void proto_register_smb2(void);
+void proto_reg_handoff_smb2(void);
static const char smb_header_label[] = "SMB2 Header";
static const char smb_transform_header_label[] = "SMB2 Transform Header";
static int hf_smb2_flags_chained = -1;
static int hf_smb2_flags_signature = -1;
static int hf_smb2_flags_replay_operation = -1;
+static int hf_smb2_flags_priority_mask = -1;
static int hf_smb2_chain_offset = -1;
static int hf_smb2_security_blob = -1;
static int hf_smb2_ioctl_in_data = -1;
static int hf_smb2_ioctl_out_data = -1;
static int hf_smb2_unknown = -1;
+static int hf_smb2_root_directory_mbz = -1;
static int hf_smb2_twrp_timestamp = -1;
static int hf_smb2_mxac_timestamp = -1;
static int hf_smb2_mxac_status = -1;
static int hf_smb2_boot_time = -1;
static int hf_smb2_filename = -1;
static int hf_smb2_filename_len = -1;
+static int hf_smb2_replace_if = -1;
static int hf_smb2_nlinks = -1;
static int hf_smb2_delete_pending = -1;
static int hf_smb2_is_directory = -1;
static int hf_smb2_infolevel_file_info = -1;
static int hf_smb2_infolevel_fs_info = -1;
static int hf_smb2_infolevel_sec_info = -1;
+static int hf_smb2_infolevel_posix_info = -1;
static int hf_smb2_max_response_size = -1;
static int hf_smb2_max_ioctl_in_size = -1;
static int hf_smb2_max_ioctl_out_size = -1;
static int hf_smb2_read_length = -1;
static int hf_smb2_read_remaining = -1;
static int hf_smb2_file_offset = -1;
+static int hf_smb2_qfr_length = -1;
+static int hf_smb2_qfr_usage = -1;
+static int hf_smb2_qfr_flags = -1;
+static int hf_smb2_qfr_total_region_entry_count = -1;
+static int hf_smb2_qfr_region_entry_count = -1;
static int hf_smb2_read_data = -1;
static int hf_smb2_disposition_delete_on_close = -1;
static int hf_smb2_create_disposition = -1;
static int hf_smb2_create_rep_flags = -1;
static int hf_smb2_create_rep_flags_reparse_point = -1;
static int hf_smb2_next_offset = -1;
+static int hf_smb2_negotiate_context_type = -1;
+static int hf_smb2_negotiate_context_data_length = -1;
+static int hf_smb2_negotiate_context_offset = -1;
+static int hf_smb2_negotiate_context_count = -1;
static int hf_smb2_ea_size = -1;
static int hf_smb2_ea_flags = -1;
static int hf_smb2_ea_name_len = -1;
static int hf_smb2_ioctl_function_device = -1;
static int hf_smb2_ioctl_function_access = -1;
static int hf_smb2_ioctl_function_function = -1;
+static int hf_smb2_fsctl_pipe_wait_timeout = -1;
+static int hf_smb2_fsctl_pipe_wait_name = -1;
+
+static int hf_smb2_fsctl_odx_token_type = -1;
+static int hf_smb2_fsctl_odx_token_idlen = -1;
+static int hf_smb2_fsctl_odx_token_idraw = -1;
+static int hf_smb2_fsctl_odx_token_ttl = -1;
+static int hf_smb2_fsctl_odx_size = -1;
+static int hf_smb2_fsctl_odx_flags = -1;
+static int hf_smb2_fsctl_odx_file_offset = -1;
+static int hf_smb2_fsctl_odx_copy_length = -1;
+static int hf_smb2_fsctl_odx_xfer_length = -1;
+static int hf_smb2_fsctl_odx_token_offset = -1;
+
+static int hf_smb2_fsctl_sparse_flag = -1;
+static int hf_smb2_fsctl_range_offset = -1;
+static int hf_smb2_fsctl_range_length = -1;
static int hf_smb2_ioctl_function_method = -1;
static int hf_smb2_ioctl_resiliency_timeout = -1;
static int hf_smb2_ioctl_resiliency_reserved = -1;
static int hf_smb2_ioctl_shadow_copy_count = -1;
static int hf_smb2_ioctl_shadow_copy_label = -1;
static int hf_smb2_compression_format = -1;
+static int hf_smb2_checksum_algorithm = -1;
+static int hf_smb2_integrity_reserved = -1;
+static int hf_smb2_integrity_flags = -1;
+static int hf_smb2_integrity_flags_enforcement_off = -1;
static int hf_smb2_FILE_OBJECTID_BUFFER = -1;
static int hf_smb2_lease_key = -1;
static int hf_smb2_lease_state = -1;
static int hf_smb2_lease_duration = -1;
static int hf_smb2_parent_lease_key = -1;
static int hf_smb2_lease_epoch = -1;
+static int hf_smb2_lease_reserved = -1;
static int hf_smb2_lease_break_reason = -1;
static int hf_smb2_lease_access_mask_hint = -1;
static int hf_smb2_lease_share_mask_hint = -1;
static int hf_smb2_max_read_size = -1;
static int hf_smb2_max_write_size = -1;
static int hf_smb2_channel = -1;
+static int hf_smb2_rdma_v1_offset = -1;
+static int hf_smb2_rdma_v1_token = -1;
+static int hf_smb2_rdma_v1_length = -1;
static int hf_smb2_session_flags = -1;
static int hf_smb2_ses_flags_guest = -1;
static int hf_smb2_ses_flags_null = -1;
static int hf_smb2_remaining_bytes = -1;
static int hf_smb2_channel_info_offset = -1;
static int hf_smb2_channel_info_length = -1;
+static int hf_smb2_channel_info_blob = -1;
static int hf_smb2_ioctl_flags = -1;
static int hf_smb2_ioctl_is_fsctl = -1;
static int hf_smb2_close_pq_attrib = -1;
static int hf_smb2_notify_watch_tree = -1;
static int hf_smb2_output_buffer_len = -1;
static int hf_smb2_notify_out_data = -1;
+static int hf_smb2_notify_info = -1;
+static int hf_smb2_notify_next_offset = -1;
+static int hf_smb2_notify_action = -1;
static int hf_smb2_find_flags = -1;
static int hf_smb2_find_flags_restart_scans = -1;
static int hf_smb2_find_flags_single_entry = -1;
static int hf_smb2_APP_INSTANCE_buffer_struct_size = -1;
static int hf_smb2_APP_INSTANCE_buffer_reserved = -1;
static int hf_smb2_APP_INSTANCE_buffer_app_guid = -1;
+static int hf_smb2_svhdx_open_device_context_version = -1;
+static int hf_smb2_svhdx_open_device_context_has_initiator_id = -1;
+static int hf_smb2_svhdx_open_device_context_reserved = -1;
+static int hf_smb2_svhdx_open_device_context_initiator_id = -1;
+static int hf_smb2_svhdx_open_device_context_flags = -1;
+static int hf_smb2_svhdx_open_device_context_originator_flags = -1;
+static int hf_smb2_svhdx_open_device_context_open_request_id = -1;
+static int hf_smb2_svhdx_open_device_context_initiator_host_name_len = -1;
+static int hf_smb2_svhdx_open_device_context_initiator_host_name = -1;
+static int hf_smb2_posix_v1_version = -1;
+static int hf_smb2_posix_v1_request = -1;
+static int hf_smb2_posix_v1_supported_features = -1;
+static int hf_smb2_posix_v1_posix_lock = -1;
+static int hf_smb2_posix_v1_posix_file_semantics = -1;
+static int hf_smb2_posix_v1_posix_utf8_paths = -1;
+static int hf_smb2_posix_v1_case_sensitive = -1;
+static int hf_smb2_posix_v1_posix_will_convert_nt_acls = -1;
+static int hf_smb2_posix_v1_posix_fileinfo = -1;
+static int hf_smb2_posix_v1_posix_acls = -1;
+static int hf_smb2_posix_v1_rich_acls = -1;
+static int hf_smb2_aapl_command_code = -1;
+static int hf_smb2_aapl_reserved = -1;
+static int hf_smb2_aapl_server_query_bitmask = -1;
+static int hf_smb2_aapl_server_query_bitmask_server_caps = -1;
+static int hf_smb2_aapl_server_query_bitmask_volume_caps = -1;
+static int hf_smb2_aapl_server_query_bitmask_model_info = -1;
+static int hf_smb2_aapl_server_query_caps = -1;
+static int hf_smb2_aapl_server_query_caps_supports_read_dir_attr = -1;
+static int hf_smb2_aapl_server_query_caps_supports_osx_copyfile = -1;
+static int hf_smb2_aapl_server_query_caps_unix_based = -1;
+static int hf_smb2_aapl_server_query_caps_supports_nfs_ace = -1;
+static int hf_smb2_aapl_server_query_volume_caps = -1;
+static int hf_smb2_aapl_server_query_volume_caps_support_resolve_id = -1;
+static int hf_smb2_aapl_server_query_volume_caps_case_sensitive = -1;
+static int hf_smb2_aapl_server_query_volume_caps_supports_full_sync = -1;
+static int hf_smb2_aapl_server_query_model_string = -1;
+static int hf_smb2_aapl_server_query_server_path = -1;
static int hf_smb2_error_byte_count = -1;
static int hf_smb2_error_data = -1;
static int hf_smb2_error_reserved = -1;
static int hf_smb2_reserved = -1;
+static int hf_smb2_reserved_random = -1;
static int hf_smb2_transform_signature = -1;
static int hf_smb2_transform_nonce = -1;
static int hf_smb2_transform_msg_size = -1;
static int hf_smb2_encryption_aes128_ccm = -1;
static int hf_smb2_transform_enc_alg = -1;
static int hf_smb2_transform_encrypted_data = -1;
+static int hf_smb2_server_component_smb2 = -1;
+static int hf_smb2_server_component_smb2_transform = -1;
+static int hf_smb2_truncated = -1;
+static int hf_smb2_pipe_fragments = -1;
+static int hf_smb2_pipe_fragment = -1;
+static int hf_smb2_pipe_fragment_overlap = -1;
+static int hf_smb2_pipe_fragment_overlap_conflict = -1;
+static int hf_smb2_pipe_fragment_multiple_tails = -1;
+static int hf_smb2_pipe_fragment_too_long_fragment = -1;
+static int hf_smb2_pipe_fragment_error = -1;
+static int hf_smb2_pipe_fragment_count = -1;
+static int hf_smb2_pipe_reassembled_in = -1;
+static int hf_smb2_pipe_reassembled_length = -1;
+static int hf_smb2_pipe_reassembled_data = -1;
+static int hf_smb2_cchunk_resume_key = -1;
+static int hf_smb2_cchunk_count = -1;
+static int hf_smb2_cchunk_src_offset = -1;
+static int hf_smb2_cchunk_dst_offset = -1;
+static int hf_smb2_cchunk_xfer_len = -1;
+static int hf_smb2_cchunk_chunks_written = -1;
+static int hf_smb2_cchunk_bytes_written = -1;
+static int hf_smb2_cchunk_total_written = -1;
static gint ett_smb2 = -1;
static gint ett_smb2_olb = -1;
static gint ett_smb2_encrypted = -1;
static gint ett_smb2_command = -1;
static gint ett_smb2_secblob = -1;
+static gint ett_smb2_negotiate_context_element = -1;
static gint ett_smb2_file_basic_info = -1;
static gint ett_smb2_file_standard_info = -1;
static gint ett_smb2_file_internal_info = -1;
static gint ett_smb2_share_caps = -1;
static gint ett_smb2_ioctl_flags = -1;
static gint ett_smb2_ioctl_network_interface = -1;
+static gint ett_smb2_fsctl_range_data = -1;
static gint ett_windows_sockaddr = -1;
static gint ett_smb2_close_flags = -1;
+static gint ett_smb2_notify_info = -1;
static gint ett_smb2_notify_flags = -1;
static gint ett_smb2_write_flags = -1;
+static gint ett_smb2_rdma_v1 = -1;
static gint ett_smb2_DH2Q_buffer = -1;
static gint ett_smb2_DH2C_buffer = -1;
static gint ett_smb2_dh2x_flags = -1;
static gint ett_smb2_APP_INSTANCE_buffer = -1;
+static gint ett_smb2_svhdx_open_device_context = -1;
+static gint ett_smb2_posix_v1_request = -1;
+static gint ett_smb2_posix_v1_response = -1;
+static gint ett_smb2_posix_v1_supported_features = -1;
+static gint ett_smb2_aapl_create_context_request = -1;
+static gint ett_smb2_aapl_server_query_bitmask = -1;
+static gint ett_smb2_aapl_server_query_caps = -1;
+static gint ett_smb2_aapl_create_context_response = -1;
+static gint ett_smb2_aapl_server_query_volume_caps = -1;
+static gint ett_smb2_integrity_flags = -1;
static gint ett_smb2_find_flags = -1;
static gint ett_smb2_file_directory_info = -1;
static gint ett_smb2_both_directory_info = -1;
static gint ett_smb2_lock_flags = -1;
static gint ett_smb2_transform_enc_alg = -1;
static gint ett_smb2_buffercode = -1;
+static gint ett_smb2_ioctl_network_interface_capabilities = -1;
+static gint ett_qfr_entry = -1;
+static gint ett_smb2_pipe_fragment = -1;
+static gint ett_smb2_pipe_fragments = -1;
+static gint ett_smb2_cchunk_entry = -1;
+static gint ett_smb2_fsctl_odx_token = -1;
+
+static expert_field ei_smb2_invalid_length = EI_INIT;
+static expert_field ei_smb2_bad_response = EI_INIT;
static int smb2_tap = -1;
static int smb2_eo_tap = -1;
static dissector_handle_t gssapi_handle = NULL;
static dissector_handle_t ntlmssp_handle = NULL;
-
-static heur_dissector_list_t smb2_heur_subdissector_list;
+static dissector_handle_t rsvd_handle = NULL;
+
+static heur_dissector_list_t smb2_pipe_subdissector_list;
+
+static const fragment_items smb2_pipe_frag_items = {
+ &ett_smb2_pipe_fragment,
+ &ett_smb2_pipe_fragments,
+ &hf_smb2_pipe_fragments,
+ &hf_smb2_pipe_fragment,
+ &hf_smb2_pipe_fragment_overlap,
+ &hf_smb2_pipe_fragment_overlap_conflict,
+ &hf_smb2_pipe_fragment_multiple_tails,
+ &hf_smb2_pipe_fragment_too_long_fragment,
+ &hf_smb2_pipe_fragment_error,
+ &hf_smb2_pipe_fragment_count,
+ &hf_smb2_pipe_reassembled_in,
+ &hf_smb2_pipe_reassembled_length,
+ &hf_smb2_pipe_reassembled_data,
+ "Fragments"
+};
#define SMB2_CLASS_FILE_INFO 0x01
#define SMB2_CLASS_FS_INFO 0x02
#define SMB2_CLASS_SEC_INFO 0x03
+#define SMB2_CLASS_POSIX_INFO 0x80
static const value_string smb2_class_vals[] = {
{ SMB2_CLASS_FILE_INFO, "FILE_INFO"},
{ SMB2_CLASS_FS_INFO, "FS_INFO"},
{ SMB2_CLASS_SEC_INFO, "SEC_INFO"},
+ { SMB2_CLASS_POSIX_INFO, "POSIX_INFO"},
{ 0, NULL }
};
-#define SMB2_FS_INFO_01 0x01
-#define SMB2_FS_INFO_03 0x03
-#define SMB2_FS_INFO_04 0x04
-#define SMB2_FS_INFO_05 0x05
-#define SMB2_FS_INFO_06 0x06
-#define SMB2_FS_INFO_07 0x07
-#define SMB2_FS_OBJECTID_INFO 0x08
+#define SMB2_FS_INFO_01 0x01
+#define SMB2_FS_LABEL_INFO 0x02
+#define SMB2_FS_INFO_03 0x03
+#define SMB2_FS_INFO_04 0x04
+#define SMB2_FS_INFO_05 0x05
+#define SMB2_FS_INFO_06 0x06
+#define SMB2_FS_INFO_07 0x07
+#define SMB2_FS_OBJECTID_INFO 0x08
+#define SMB2_FS_DRIVER_PATH_INFO 0x09
+#define SMB2_FS_VOLUME_FLAGS_INFO 0x0a
+#define SMB2_FS_SECTOR_SIZE_INFO 0x0b
static const value_string smb2_fs_info_levels[] = {
- {SMB2_FS_INFO_01, "SMB2_FS_INFO_01" },
- {SMB2_FS_INFO_03, "SMB2_FS_INFO_03" },
- {SMB2_FS_INFO_04, "SMB2_FS_INFO_04" },
- {SMB2_FS_INFO_05, "SMB2_FS_INFO_05" },
- {SMB2_FS_INFO_06, "SMB2_FS_INFO_06" },
- {SMB2_FS_INFO_07, "SMB2_FS_INFO_07" },
- {SMB2_FS_OBJECTID_INFO, "SMB2_FS_OBJECTID_INFO" },
+ {SMB2_FS_INFO_01, "FileFsVolumeInformation" },
+ {SMB2_FS_LABEL_INFO, "FileFsLabelInformation" },
+ {SMB2_FS_INFO_03, "FileFsSizeInformation" },
+ {SMB2_FS_INFO_04, "FileFsDeviceInformation" },
+ {SMB2_FS_INFO_05, "FileFsAttributeInformation" },
+ {SMB2_FS_INFO_06, "FileFsControlInformation" },
+ {SMB2_FS_INFO_07, "FileFsFullSizeInformation" },
+ {SMB2_FS_OBJECTID_INFO, "FileFsObjectIdInformation" },
+ {SMB2_FS_DRIVER_PATH_INFO, "FileFsDriverPathInformation" },
+ {SMB2_FS_VOLUME_FLAGS_INFO, "FileFsVolumeFlagsInformation" },
+ {SMB2_FS_SECTOR_SIZE_INFO, "FileFsSectorSizeInformation" },
{ 0, NULL }
};
static value_string_ext smb2_fs_info_levels_ext = VALUE_STRING_EXT_INIT(smb2_fs_info_levels);
};
static value_string_ext smb2_sec_info_levels_ext = VALUE_STRING_EXT_INIT(smb2_sec_info_levels);
+static const value_string smb2_posix_info_levels[] = {
+ { 0, "QueryFileUnixBasic" },
+ { 1, "QueryFileUnixLink" },
+ { 3, "QueryFileUnixHLink" },
+ { 5, "QueryFileUnixXAttr" },
+ { 0x0B, "QueryFileUnixInfo2" },
+ { 0, NULL }
+};
+
+static value_string_ext smb2_posix_info_levels_ext = VALUE_STRING_EXT_INIT(smb2_posix_info_levels);
+
#define SMB2_FIND_DIRECTORY_INFO 0x01
#define SMB2_FIND_FULL_DIRECTORY_INFO 0x02
#define SMB2_FIND_BOTH_DIRECTORY_INFO 0x03
{ 0, NULL }
};
+#define SMB2_PREAUTH_INTEGRITY_CAPABILITIES 0x0001
+#define SMB2_ENCRYPTION_CAPABILITIES 0x0002
+static const value_string smb2_negotiate_context_types[] = {
+ { SMB2_PREAUTH_INTEGRITY_CAPABILITIES, "SMB2_PREAUTH_INTEGRITY_CAPABILITIES" },
+ { SMB2_ENCRYPTION_CAPABILITIES, "SMB2_ENCRYPTION_CAPABILITIES" },
+ { 0, NULL }
+};
+
+#define SMB2_NUM_PROCEDURES 256
+
+static void
+smb2stat_init(struct register_srt* srt _U_, GArray* srt_array, srt_gui_init_cb gui_callback, void* gui_data)
+{
+ srt_stat_table *smb2_srt_table;
+ guint32 i;
+
+ smb2_srt_table = init_srt_table("SMB2", NULL, srt_array, SMB2_NUM_PROCEDURES, "Commands", "smb2.cmd", gui_callback, gui_data, NULL);
+ for (i = 0; i < SMB2_NUM_PROCEDURES; i++)
+ {
+ init_srt_table_row(smb2_srt_table, i, val_to_str_ext_const(i, &smb2_cmd_vals_ext, "<unknown>"));
+ }
+}
+
+static int
+smb2stat_packet(void *pss, packet_info *pinfo, epan_dissect_t *edt _U_, const void *prv)
+{
+ guint i = 0;
+ srt_stat_table *smb2_srt_table;
+ srt_data_t *data = (srt_data_t *)pss;
+ const smb2_info_t *si=(const smb2_info_t *)prv;
+
+ /* we are only interested in response packets */
+ if(!(si->flags&SMB2_FLAGS_RESPONSE)){
+ return 0;
+ }
+ /* if we haven't seen the request, just ignore it */
+ if(!si->saved){
+ return 0;
+ }
+
+ /* SMB2 SRT can be very inaccurate in the presence of retransmissions. Retransmitted responses
+ * not only add additional (bogus) transactions but also the latency associated with them.
+ * This can greatly inflate the maximum and average SRT stats especially in the case of
+ * retransmissions triggered by the expiry of the rexmit timer (RTOs). Only calculating SRT
+ * for the last received response accomplishes this goal without requiring the TCP pref
+ * "Do not call subdissectors for error packets" to be set. */
+ if ((si->saved->frame_req == 0) || (si->saved->frame_res != pinfo->num))
+ return 0;
+
+ smb2_srt_table = g_array_index(data->srt_array, srt_stat_table*, i);
+ add_srt_table_data(smb2_srt_table, si->opcode, &si->saved->req_time, pinfo);
+ return 1;
+}
+
+
static const gint8 zeros[NTLMSSP_KEY_LEN] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
/* ExportObject preferences variable */
tid.
qqq
We might need to refine this if it occurs that tids are reused on a single
- conversation. we dont worry about that yet for simplicity
+ conversation. we don't worry about that yet for simplicity
*/
static gint
smb2_tid_info_equal(gconstpointer k1, gconstpointer k2)
uid.
qqq
We might need to refine this if it occurs that uids are reused on a single
- conversation. we dont worry about that yet for simplicity
+ conversation. we don't worry about that yet for simplicity
*/
static gint
smb2_sesid_info_equal(gconstpointer k1, gconstpointer k2)
return hash;
}
+/*
+ * For File IDs of a specific conversation.
+ * This keeps track of fid to name mapping and application level conversations
+ * over named pipes.
+ *
+ * This handles implementation bugs, where the fid_persitent is 0 or
+ * the fid_persitent/fid_volative is not unique per conversation.
+ */
+static gint
+smb2_fid_info_equal(gconstpointer k1, gconstpointer k2)
+{
+ const smb2_fid_info_t *key1 = (const smb2_fid_info_t *)k1;
+ const smb2_fid_info_t *key2 = (const smb2_fid_info_t *)k2;
+
+ if (key1->fid_persistent != key2->fid_persistent) {
+ return 0;
+ };
+
+ if (key1->fid_volatile != key2->fid_volatile) {
+ return 0;
+ };
+
+ if (key1->sesid != key2->sesid) {
+ return 0;
+ };
+
+ if (key1->tid != key2->tid) {
+ return 0;
+ };
+
+ return 1;
+}
+
+static guint
+smb2_fid_info_hash(gconstpointer k)
+{
+ const smb2_fid_info_t *key = (const smb2_fid_info_t *)k;
+ guint32 hash;
+
+ if (key->fid_persistent != 0) {
+ hash = (guint32)( ((key->fid_persistent>>32)&0xffffffff)+((key->fid_persistent)&0xffffffff) );
+ } else {
+ hash = (guint32)( ((key->fid_volatile>>32)&0xffffffff)+((key->fid_volatile)&0xffffffff) );
+ }
+
+ return hash;
+}
+
/* Callback for destroying the glib hash tables associated with a conversation
* struct. */
static gboolean
g_hash_table_destroy(conv->matched);
g_hash_table_destroy(conv->unmatched);
+ g_hash_table_destroy(conv->fids);
g_hash_table_destroy(conv->sesids);
g_hash_table_destroy(conv->files);
gchar *file_id;
file_id = wmem_strdup_printf(wmem_packet_scope(),
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- hnd->uuid.Data1,
- hnd->uuid.Data2,
- hnd->uuid.Data3,
- hnd->uuid.Data4[0],
- hnd->uuid.Data4[1],
- hnd->uuid.Data4[2],
- hnd->uuid.Data4[3],
- hnd->uuid.Data4[4],
- hnd->uuid.Data4[5],
- hnd->uuid.Data4[6],
- hnd->uuid.Data4[7]);
+ hnd->uuid.data1,
+ hnd->uuid.data2,
+ hnd->uuid.data3,
+ hnd->uuid.data4[0],
+ hnd->uuid.data4[1],
+ hnd->uuid.data4[2],
+ hnd->uuid.data4[3],
+ hnd->uuid.data4[4],
+ hnd->uuid.data4[5],
+ hnd->uuid.data4[6],
+ hnd->uuid.data4[7]);
return file_id;
}
static guint smb2_eo_files_hash(gconstpointer k) {
const e_ctx_hnd *key1 = (const e_ctx_hnd *)k1;
const e_ctx_hnd *key2 = (const e_ctx_hnd *)k2;
- are_equal = (key1->uuid.Data1==key2->uuid.Data1 &&
- key1->uuid.Data2==key2->uuid.Data2 &&
- key1->uuid.Data3==key2->uuid.Data3 &&
- key1->uuid.Data4[0]==key2->uuid.Data4[0] &&
- key1->uuid.Data4[1]==key2->uuid.Data4[1] &&
- key1->uuid.Data4[2]==key2->uuid.Data4[2] &&
- key1->uuid.Data4[3]==key2->uuid.Data4[3] &&
- key1->uuid.Data4[4]==key2->uuid.Data4[4] &&
- key1->uuid.Data4[5]==key2->uuid.Data4[5] &&
- key1->uuid.Data4[6]==key2->uuid.Data4[6] &&
- key1->uuid.Data4[7]==key2->uuid.Data4[7]);
+ are_equal = (key1->uuid.data1==key2->uuid.data1 &&
+ key1->uuid.data2==key2->uuid.data2 &&
+ key1->uuid.data3==key2->uuid.data3 &&
+ key1->uuid.data4[0]==key2->uuid.data4[0] &&
+ key1->uuid.data4[1]==key2->uuid.data4[1] &&
+ key1->uuid.data4[2]==key2->uuid.data4[2] &&
+ key1->uuid.data4[3]==key2->uuid.data4[3] &&
+ key1->uuid.data4[4]==key2->uuid.data4[4] &&
+ key1->uuid.data4[5]==key2->uuid.data4[5] &&
+ key1->uuid.data4[6]==key2->uuid.data4[6] &&
+ key1->uuid.data4[7]==key2->uuid.data4[7]);
return are_equal;
}
gchar **aux_string_v;
/* Create a new tvb to point to the payload data */
- data_tvb = tvb_new_subset(tvb, dataoffset, length, length);
+ data_tvb = tvb_new_subset_length(tvb, dataoffset, length);
/* Create the eo_info to pass to the listener */
eo_info = wmem_new(wmem_packet_scope(), smb_eo_t);
/* Fill in eo_info */
/* Try to get file id and filename */
file_id=policy_hnd_to_file_id(&si->saved->policy_hnd);
- dcerpc_fetch_polhnd_data(&si->saved->policy_hnd, &fid_name, NULL, &open_frame, &close_frame, pinfo->fd->num);
+ dcerpc_fetch_polhnd_data(&si->saved->policy_hnd, &fid_name, NULL, &open_frame, &close_frame, pinfo->num);
if (fid_name && g_strcmp0(fid_name,"File: ")!=0) {
auxstring=fid_name;
/* Remove "File: " from filename */
}
/* packet number */
- eo_info->pkt_num = pinfo->fd->num;
+ eo_info->pkt_num = pinfo->num;
/* fid type */
if (si->eo_file_info->attr_mask & SMB2_FLAGS_ATTR_DIRECTORY) {
*
* This function is called twice, first to decode the offset/length and
* second time to dissect the actual string.
- * It is done this way since there is no guarantee that we have the full packet and we dont
+ * It is done this way since there is no guarantee that we have the full packet and we don't
* want to abort dissection too early if the packet ends somewhere between the
* length/offset and the actual buffer.
*
offset = olb->off;
len = olb->len;
off = olb->off;
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
/* sanity check */
tvb_ensure_bytes_exist(tvb, off, len);
if (((off+len)<off)
|| ((off+len)>(off+tvb_reported_length_remaining(tvb, off)))) {
- proto_tree_add_text(tree, tvb, offset, tvb_length_remaining(tvb, offset),
+ proto_tree_add_expert_format(tree, pinfo, &ei_smb2_invalid_length, tvb, offset, -1,
"Invalid offset/length. Malformed packet");
col_append_str(pinfo->cinfo, COL_INFO, " [Malformed packet]");
tvb_ensure_bytes_exist(tvb, off, len);
if (((off+len)<off)
|| ((off+len)>(off+tvb_reported_length_remaining(tvb, off)))) {
- proto_tree_add_text(parent_tree, tvb, offset, tvb_length_remaining(tvb, offset),
+ proto_tree_add_expert_format(parent_tree, pinfo, &ei_smb2_invalid_length, tvb, offset, -1,
"Invalid offset/length. Malformed packet");
col_append_str(pinfo->cinfo, COL_INFO, " [Malformed packet]");
return;
}
- /* if we dont want/need a subtree */
+ /* if we don't want/need a subtree */
if (olb->hfindex == -1) {
sub_item = parent_tree;
sub_tree = parent_tree;
return;
}
- sub_tvb = tvb_new_subset(tvb, off, MIN((int)len, tvb_length_remaining(tvb, off)), len);
+ sub_tvb = tvb_new_subset(tvb, off, MIN((int)len, tvb_captured_length_remaining(tvb, off)), len);
dissector(sub_tvb, pinfo, sub_tree, si);
}
int (*response)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si);
} smb2_function;
+static const true_false_string tfs_smb2_svhdx_has_initiator_id = {
+ "Has an initiator id",
+ "Does not have an initiator id"
+};
+
static const true_false_string tfs_flags_response = {
"This is a RESPONSE",
"This is a REQUEST"
"This is NOT a replay operation"
};
+static const true_false_string tfs_flags_priority_mask = {
+ "This pdu contains a PRIORITY",
+ "This pdu does NOT contain a PRIORITY1"
+};
+
static const true_false_string tfs_cap_dfs = {
"This host supports DFS",
"This host does NOT support DFS"
"This interface does not support RDMA"
};
+static const value_string file_region_usage_vals[] = {
+ { 0x00000001, "FILE_REGION_USAGE_VALID_CACHED_DATA" },
+ { 0, NULL }
+};
+
+static const value_string originator_flags_vals[] = {
+ { 1, "SVHDX_ORIGINATOR_PVHDPARSER" },
+ { 4, "SVHDX_ORIGINATOR_VHDMP" },
+ { 0, NULL }
+};
+
+static const value_string posix_locks_vals[] = {
+ { 1, "POSIX_V1_POSIX_LOCK" },
+ { 0, NULL }
+};
+
+static const value_string posix_utf8_paths_vals[] = {
+ { 1, "POSIX_V1_UTF8_PATHS" },
+ { 0, NULL }
+};
+
+static const value_string posix_file_semantics_vals[] = {
+ { 1, "POSIX_V1_POSIX_FILE_SEMANTICS" },
+ { 0, NULL }
+};
+
+static const value_string posix_case_sensitive_vals[] = {
+ { 1, "POSIX_V1_CASE_SENSITIVE" },
+ { 0, NULL }
+};
+
+static const value_string posix_will_convert_ntacls_vals[] = {
+ { 1, "POSIX_V1_WILL_CONVERT_NT_ACLS" },
+ { 0, NULL }
+};
+
+static const value_string posix_fileinfo_vals[] = {
+ { 1, "POSIX_V1_POSIX_FILEINFO" },
+ { 0, NULL }
+};
+
+static const value_string posix_acls_vals[] = {
+ { 1, "POSIX_V1_POSIX_ACLS" },
+ { 0, NULL }
+};
+
+static const value_string posix_rich_acls_vals[] = {
+ { 1, "POSIX_V1_RICH_ACLS" },
+ { 0, NULL }
+};
+
static const value_string compression_format_vals[] = {
{ 0, "COMPRESSION_FORMAT_NONE" },
{ 1, "COMPRESSION_FORMAT_DEFAULT" },
{ 0, NULL }
};
+static const value_string checksum_algorithm_vals[] = {
+ { 0x0000, "CHECKSUM_TYPE_NONE" },
+ { 0x0002, "CHECKSUM_TYPE_CRC64" },
+ { 0xFFFF, "CHECKSUM_TYPE_UNCHANGED" },
+ { 0, NULL }
+};
/* Note: All uncommented are "dissector not implemented" */
static const value_string smb2_ioctl_vals[] = {
{0x00060194, "FSCTL_DFS_GET_REFERRALS"}, /* dissector implemented */
+ {0x000601B0, "FSCTL_DFS_GET_REFERRALS_EX"},
{0x00090000, "FSCTL_REQUEST_OPLOCK_LEVEL_1"},
{0x00090004, "FSCTL_REQUEST_OPLOCK_LEVEL_2"},
{0x00090008, "FSCTL_REQUEST_BATCH_OPLOCK"},
{0x0009008F, "FSCTL_FIND_FILES_BY_SID"},
{0x00090097, "FSCTL_DUMP_PROPERTY_DATA"},
{0x0009009C, "FSCTL_GET_OBJECT_ID"}, /* dissector implemented */
+ {0x000900A4, "FSCTL_SET_REPARSE_POINT"},
{0x000900A8, "FSCTL_GET_REPARSE_POINT"},
{0x000900C0, "FSCTL_CREATE_OR_GET_OBJECT_ID"}, /* dissector implemented */
+ {0x000900C4, "FSCTL_SET_SPARSE"}, /* dissector implemented */
{0x000900D4, "FSCTL_SET_ENCRYPTION"},
{0x000900DB, "FSCTL_ENCRYPTION_FSCTL_IO"},
{0x000900DF, "FSCTL_WRITE_RAW_ENCRYPTED"},
{0x000900E3, "FSCTL_READ_RAW_ENCRYPTED"},
{0x000900F0, "FSCTL_EXTEND_VOLUME"},
+ {0x0009027C, "FSCTL_GET_INTEGRITY_INFORMATION"},
+ {0x00090284, "FSCTL_QUERY_FILE_REGIONS"},
+ {0x00090300, "FSCTL_QUERY_SHARED_VIRTUAL_DISK_SUPPORT"}, /* dissector implemented */
+ {0x00090304, "FSCTL_SVHDX_SYNC_TUNNEL_REQUEST"}, /* dissector implemented */
+ {0x00090308, "FSCTL_SVHDX_SET_INITIATOR_INFORMATION"},
+ {0x0009030C, "FSCTL_SET_EXTERNAL_BACKING"},
+ {0x00090310, "FSCTL_GET_EXTERNAL_BACKING"},
+ {0x00090314, "FSCTL_DELETE_EXTERNAL_BACKING"},
+ {0x00090318, "FSCTL_ENUM_EXTERNAL_BACKING"},
+ {0x0009031F, "FSCTL_ENUM_OVERLAY"},
{0x000940B3, "FSCTL_ENUM_USN_DATA"},
{0x000940B7, "FSCTL_SECURITY_ID_CHECK"},
{0x000940BB, "FSCTL_READ_USN_JOURNAL"},
- {0x000940CF, "FSCTL_QUERY_ALLOCATED_RANGES"},
+ {0x000940CF, "FSCTL_QUERY_ALLOCATED_RANGES"}, /* dissector implemented */
{0x000940E7, "FSCTL_CREATE_USN_JOURNAL"},
{0x000940EB, "FSCTL_READ_FILE_USN_DATA"},
{0x000940EF, "FSCTL_WRITE_USN_CLOSE_RECORD"},
+ {0x00094264, "FSCTL_OFFLOAD_READ"}, /* dissector implemented */
{0x00098098, "FSCTL_SET_OBJECT_ID"}, /* dissector implemented */
- {0x000980A0, "FSCTL_DELETE_OBJECT_ID"}, /* no data in/out */ /* dissector implemented */
+ {0x000980A0, "FSCTL_DELETE_OBJECT_ID"}, /* no data in/out */
{0x000980A4, "FSCTL_SET_REPARSE_POINT"},
{0x000980AC, "FSCTL_DELETE_REPARSE_POINT"},
{0x000980BC, "FSCTL_SET_OBJECT_ID_EXTENDED"}, /* dissector implemented */
- {0x000980C4, "FSCTL_SET_SPARSE"},
- {0x000980C8, "FSCTL_SET_ZERO_DATA"},
+ {0x000980C8, "FSCTL_SET_ZERO_DATA"}, /* dissector implemented */
{0x000980D0, "FSCTL_ENABLE_UPGRADE"},
+ {0x00098208, "FSCTL_FILE_LEVEL_TRIM"},
+ {0x00098268, "FSCTL_OFFLOAD_WRITE"}, /* dissector implemented */
{0x0009C040, "FSCTL_SET_COMPRESSION"}, /* dissector implemented */
+ {0x0009C280, "FSCTL_SET_INTEGRITY_INFORMATION"}, /* dissector implemented */
+ {0x00110018, "FSCTL_PIPE_WAIT"}, /* dissector implemented */
+ {0x0011400C, "FSCTL_PIPE_PEEK"},
{0x0011C017, "FSCTL_PIPE_TRANSCEIVE"}, /* dissector implemented */
{0x00140078, "FSCTL_SRV_REQUEST_RESUME_KEY"},
{0x001401D4, "FSCTL_LMR_REQUEST_RESILIENCY"}, /* dissector implemented */
{0x001401FC, "FSCTL_QUERY_NETWORK_INTERFACE_INFO"}, /* dissector implemented */
{0x00140200, "FSCTL_VALIDATE_NEGOTIATE_INFO_224"}, /* dissector implemented */
{0x00140204, "FSCTL_VALIDATE_NEGOTIATE_INFO"}, /* dissector implemented */
- {0x00144064, "FSCTL_GET_SHADOW_COPY_DATA"}, /* dissector implemented */
+ {0x00144064, "FSCTL_SRV_ENUMERATE_SNAPSHOTS"}, /* dissector implemented */
{0x001440F2, "FSCTL_SRV_COPYCHUNK"},
{0x001441bb, "FSCTL_SRV_READ_HASH"},
{0x001480F2, "FSCTL_SRV_COPYCHUNK_WRITE"},
char *fid_name;
guint32 open_frame = 0, close_frame = 0;
smb2_eo_file_info_t *eo_file_info;
+ smb2_fid_info_t sfi_key;
+ smb2_fid_info_t *sfi = NULL;
+
+ sfi_key.fid_persistent = tvb_get_letoh64(tvb, offset);
+ sfi_key.fid_volatile = tvb_get_letoh64(tvb, offset+8);
+ sfi_key.sesid = si->sesid;
+ sfi_key.tid = si->tid;
+ sfi_key.name = NULL;
di.conformant_run = 0;
/* we need di->call_data->flags.NDR64 == 0 */
di.call_data = &call_data;
- di.dcerpc_procedure_name = "";
switch (mode) {
case FID_MODE_OPEN:
offset = dissect_nt_guid_hnd(tvb, offset, pinfo, tree, &di, drep, hf_smb2_fid, &policy_hnd, &hnd_item, TRUE, FALSE);
if (!pinfo->fd->flags.visited) {
+ sfi = wmem_new(wmem_file_scope(), smb2_fid_info_t);
+ *sfi = sfi_key;
+ if (si->saved && si->saved->extra_info_type == SMB2_EI_FILENAME) {
+ sfi->name = wmem_strdup(wmem_file_scope(), (char *)si->saved->extra_info);
+ } else {
+ sfi->name = wmem_strdup_printf(wmem_file_scope(), "[unknown]");
+ }
+
if (si->saved && si->saved->extra_info_type == SMB2_EI_FILENAME) {
fid_name = wmem_strdup_printf(wmem_file_scope(), "File: %s", (char *)si->saved->extra_info);
} else {
dcerpc_store_polhnd_name(&policy_hnd, pinfo,
fid_name);
+ g_hash_table_insert(si->conv->fids, sfi, sfi);
+ si->file = sfi;
+
/* If needed, create the file entry and save the policy hnd */
- if (si->saved) { si->saved->policy_hnd = policy_hnd; }
+ if (si->saved) {
+ si->saved->file = sfi;
+ si->saved->policy_hnd = policy_hnd;
+ }
if (si->conv) {
eo_file_info = (smb2_eo_file_info_t *)g_hash_table_lookup(si->conv->files,&policy_hnd);
break;
}
- if (dcerpc_fetch_polhnd_data(&policy_hnd, &fid_name, NULL, &open_frame, &close_frame, pinfo->fd->num)) {
- /* put the filename in col_info */
- if (fid_name) {
+ si->file = (smb2_fid_info_t *)g_hash_table_lookup(si->conv->fids, &sfi_key);
+ if (si->file) {
+ if (si->saved) {
+ si->saved->file = si->file;
+ }
+ if (si->file->name) {
if (hnd_item) {
- proto_item_append_text(hnd_item, " %s", fid_name);
+ proto_item_append_text(hnd_item, " File: %s", si->file->name);
}
- col_append_fstr(pinfo->cinfo, COL_INFO, " %s", fid_name);
+ col_append_fstr(pinfo->cinfo, COL_INFO, " File: %s", si->file->name);
}
+ }
+ if (dcerpc_fetch_polhnd_data(&policy_hnd, &fid_name, NULL, &open_frame, &close_frame, pinfo->num)) {
/* look for the eo_file_info */
if (!si->eo_file_info) {
if (si->saved) { si->saved->policy_hnd = policy_hnd; }
/* file name length */
length = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(tree, hf_smb2_filename_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
-
- /* some unknown bytes */
- proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, 2, ENC_NA);
- offset += 2;
+ proto_tree_add_item(tree, hf_smb2_filename_len, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
/* file name */
if (length) {
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
name = get_unicode_or_ascii_string(tvb, &offset,
TRUE, &length, TRUE, TRUE, &bc);
if (name) {
}
offset += length;
-
return offset;
}
tree = proto_item_add_subtree(item, ett_smb2_file_allocation_info);
}
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
offset = dissect_qsfi_SMB_FILE_ALLOCATION_INFO(tvb, pinfo, tree, offset, &bc, &trunc);
return offset;
tree = proto_item_add_subtree(item, ett_smb2_file_endoffile_info);
}
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
offset = dissect_qsfi_SMB_FILE_ENDOFFILE_INFO(tvb, pinfo, tree, offset, &bc, &trunc);
return offset;
tree = proto_item_add_subtree(item, ett_smb2_file_alternate_name_info);
}
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
offset = dissect_qfi_SMB_FILE_NAME_INFO(tvb, pinfo, tree, offset, &bc, &trunc, /* XXX assumption hack */ TRUE);
return offset;
tree = proto_item_add_subtree(item, ett_smb2_file_standard_info);
}
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
offset = dissect_qfi_SMB_FILE_STANDARD_INFO(tvb, pinfo, tree, offset, &bc, &trunc);
return offset;
tree = proto_item_add_subtree(item, ett_smb2_file_internal_info);
}
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
offset = dissect_qfi_SMB_FILE_INTERNAL_INFO(tvb, pinfo, tree, offset, &bc, &trunc);
return offset;
tree = proto_item_add_subtree(item, ett_smb2_file_mode_info);
}
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
offset = dissect_qsfi_SMB_FILE_MODE_INFO(tvb, pinfo, tree, offset, &bc, &trunc);
return offset;
tree = proto_item_add_subtree(item, ett_smb2_file_alignment_info);
}
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
offset = dissect_qfi_SMB_FILE_ALIGNMENT_INFO(tvb, pinfo, tree, offset, &bc, &trunc);
return offset;
tree = proto_item_add_subtree(item, ett_smb2_file_position_info);
}
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
offset = dissect_qsfi_SMB_FILE_POSITION_INFO(tvb, pinfo, tree, offset, &bc, &trunc);
return offset;
tree = proto_item_add_subtree(item, ett_smb2_file_ea_info);
}
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
offset = dissect_qfi_SMB_FILE_EA_INFO(tvb, pinfo, tree, offset, &bc, &trunc);
return offset;
tree = proto_item_add_subtree(item, ett_smb2_file_stream_info);
}
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
offset = dissect_qfi_SMB_FILE_STREAM_INFO(tvb, pinfo, tree, offset, &bc, &trunc, TRUE);
return offset;
tree = proto_item_add_subtree(item, ett_smb2_file_pipe_info);
}
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
offset = dissect_sfi_SMB_FILE_PIPE_INFO(tvb, pinfo, tree, offset, &bc, &trunc);
return offset;
tree = proto_item_add_subtree(item, ett_smb2_file_compression_info);
}
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
offset = dissect_qfi_SMB_FILE_COMPRESSION_INFO(tvb, pinfo, tree, offset, &bc, &trunc);
return offset;
}
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
offset = dissect_qfi_SMB_FILE_NETWORK_OPEN_INFO(tvb, pinfo, tree, offset, &bc, &trunc);
return offset;
}
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
offset = dissect_qfi_SMB_FILE_ATTRIBUTE_TAG_INFO(tvb, pinfo, tree, offset, &bc, &trunc);
return offset;
const char *data = "";
guint16 bc;
int start_offset = offset;
- proto_item *ea_item = NULL;
- proto_tree *ea_tree = NULL;
+ proto_item *ea_item;
+ proto_tree *ea_tree;
- if (tree) {
- ea_item = proto_tree_add_text(tree, tvb, offset, -1, "EA:");
- ea_tree = proto_item_add_subtree(ea_item, ett_smb2_ea);
- }
+ ea_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_smb2_ea, &ea_item, "EA:");
/* next offset */
next_offset = tvb_get_letohl(tvb, offset);
/* ea name */
length = ea_name_len;
if (length) {
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
name = get_unicode_or_ascii_string(tvb, &offset,
FALSE, &length, TRUE, TRUE, &bc);
if (name) {
/* ea data */
length = ea_data_len;
if (length) {
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
data = get_unicode_or_ascii_string(tvb, &offset,
FALSE, &length, TRUE, TRUE, &bc);
/*
return offset;
}
+static const true_false_string tfs_replace_if_exists = {
+ "Replace the target if it exists",
+ "Fail if the target exists"
+};
+
static int
dissect_smb2_file_rename_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_)
{
tree = proto_item_add_subtree(item, ett_smb2_file_rename_info);
}
- /* some unknown bytes */
- proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, 16, ENC_NA);
- offset += 16;
+ /* ReplaceIfExists */
+ proto_tree_add_item(tree, hf_smb2_replace_if, tvb, offset, 1, ENC_NA);
+ offset += 1;
+
+ /* reserved */
+ proto_tree_add_item(tree, hf_smb2_reserved_random, tvb, offset, 7, ENC_NA);
+ offset += 7;
+
+ /* Root Directory Handle, MBZ */
+ proto_tree_add_item(tree, hf_smb2_root_directory_mbz, tvb, offset, 8, ENC_NA);
+ offset += 8;
/* file name length */
length = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(tree, hf_smb2_filename_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
-
- /* some unknown bytes */
- proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, 2, ENC_NA);
- offset += 2;
+ proto_tree_add_item(tree, hf_smb2_filename_len, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
/* file name */
if (length) {
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
name = get_unicode_or_ascii_string(tvb, &offset,
TRUE, &length, TRUE, TRUE, &bc);
if (name) {
}
offset += length;
- /* some unknown bytes */
- proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, 4, ENC_NA);
- offset += 4;
-
return offset;
}
}
/* security descriptor */
- offset = dissect_nt_sec_desc(tvb, offset, pinfo, tree, NULL, TRUE, tvb_length_remaining(tvb, offset), NULL);
+ offset = dissect_nt_sec_desc(tvb, offset, pinfo, tree, NULL, TRUE, tvb_captured_length_remaining(tvb, offset), NULL);
return offset;
}
tree = proto_item_add_subtree(item, ett_smb2_fs_info_05);
}
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
offset = dissect_qfsi_FS_ATTRIBUTE_INFO(tvb, pinfo, tree, offset, &bc, TRUE);
return offset;
tree = proto_item_add_subtree(item, ett_smb2_fs_info_06);
}
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
offset = dissect_nt_quota(tvb, tree, offset, &bc);
return offset;
tree = proto_item_add_subtree(item, ett_smb2_fs_info_07);
}
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
offset = dissect_qfsi_FS_FULL_SIZE_INFO(tvb, pinfo, tree, offset, &bc);
return offset;
}
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
offset = dissect_qfsi_FS_VOLUME_INFO(tvb, pinfo, tree, offset, &bc, TRUE);
return offset;
}
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
offset = dissect_qfsi_FS_SIZE_INFO(tvb, pinfo, tree, offset, &bc);
return offset;
}
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
offset = dissect_qfsi_FS_DEVICE_INFO(tvb, pinfo, tree, offset, &bc);
return offset;
buffer_code = tvb_get_letohs(tvb, offset);
item = proto_tree_add_uint(parent_tree, hf_smb2_buffer_code, tvb, offset, 2, buffer_code);
tree = proto_item_add_subtree(item, ett_smb2_buffercode);
- proto_tree_add_uint_format(tree, hf_smb2_buffer_code_len, tvb, offset, 2,
- buffer_code&0xfffe, "%s: %u",
- decode_numeric_bitfield(buffer_code, 0xfffe, 16, "Fixed Part Length"),
- buffer_code&0xfffe);
+ proto_tree_add_item(tree, hf_smb2_buffer_code_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_smb2_buffer_code_flags_dyn, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
if (length) {
- *length = buffer_code&0xfffe;
+ *length = buffer_code; /*&0xfffe don't mask it here, mask it on caller side */
}
return offset;
static int
dissect_smb2_capabilities(proto_tree *parent_tree, tvbuff_t *tvb, int offset)
{
- guint32 cap;
- proto_item *item = NULL;
- proto_tree *tree = NULL;
-
- cap = tvb_get_letohl(tvb, offset);
-
- item = proto_tree_add_item(parent_tree, hf_smb2_capabilities, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- tree = proto_item_add_subtree(item, ett_smb2_capabilities);
-
-
- proto_tree_add_boolean(tree, hf_smb2_cap_dfs, tvb, offset, 4, cap);
- proto_tree_add_boolean(tree, hf_smb2_cap_leasing, tvb, offset, 4, cap);
- proto_tree_add_boolean(tree, hf_smb2_cap_large_mtu, tvb, offset, 4, cap);
- proto_tree_add_boolean(tree, hf_smb2_cap_multi_channel, tvb, offset, 4, cap);
- proto_tree_add_boolean(tree, hf_smb2_cap_persistent_handles, tvb, offset, 4, cap);
- proto_tree_add_boolean(tree, hf_smb2_cap_directory_leasing, tvb, offset, 4, cap);
- proto_tree_add_boolean(tree, hf_smb2_cap_encryption, tvb, offset, 4, cap);
+ static const int * flags[] = {
+ &hf_smb2_cap_dfs,
+ &hf_smb2_cap_leasing,
+ &hf_smb2_cap_large_mtu,
+ &hf_smb2_cap_multi_channel,
+ &hf_smb2_cap_persistent_handles,
+ &hf_smb2_cap_directory_leasing,
+ &hf_smb2_cap_encryption,
+ NULL
+ };
+ proto_tree_add_bitmask(parent_tree, tvb, offset, hf_smb2_capabilities, ett_smb2_capabilities, flags, ENC_LITTLE_ENDIAN);
offset += 4;
return offset;
static int
dissect_smb2_secmode(proto_tree *parent_tree, tvbuff_t *tvb, int offset)
{
- guint8 sm;
- proto_item *item = NULL;
- proto_tree *tree = NULL;
-
- sm = tvb_get_guint8(tvb, offset);
-
- item = proto_tree_add_item(parent_tree, hf_smb2_security_mode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- tree = proto_item_add_subtree(item, ett_smb2_sec_mode);
-
- proto_tree_add_boolean(tree, hf_smb2_secmode_flags_sign_enabled, tvb, offset, 1, sm);
- proto_tree_add_boolean(tree, hf_smb2_secmode_flags_sign_required, tvb, offset, 1, sm);
+ static const int * flags[] = {
+ &hf_smb2_secmode_flags_sign_enabled,
+ &hf_smb2_secmode_flags_sign_required,
+ NULL
+ };
+ proto_tree_add_bitmask(parent_tree, tvb, offset, hf_smb2_security_mode, ett_smb2_sec_mode, flags, ENC_LITTLE_ENDIAN);
offset += 1;
return offset;
static int
dissect_smb2_ses_req_flags(proto_tree *parent_tree, tvbuff_t *tvb, int offset)
{
- guint8 sf;
- proto_item *item = NULL;
- proto_tree *tree = NULL;
-
- sf = tvb_get_guint8(tvb, offset);
-
- item = proto_tree_add_item(parent_tree, hf_smb2_ses_req_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
- tree = proto_item_add_subtree(item, ett_smb2_ses_req_flags);
-
- proto_tree_add_boolean(tree, hf_smb2_ses_req_flags_session_binding, tvb, offset, 1, sf);
+ static const int * flags[] = {
+ &hf_smb2_ses_req_flags_session_binding,
+ NULL
+ };
+ proto_tree_add_bitmask(parent_tree, tvb, offset, hf_smb2_ses_req_flags, ett_smb2_ses_req_flags, flags, ENC_LITTLE_ENDIAN);
offset += 1;
return offset;
static int
dissect_smb2_ses_flags(proto_tree *parent_tree, tvbuff_t *tvb, int offset)
{
- guint16 sf;
- proto_item *item = NULL;
- proto_tree *tree = NULL;
-
- sf = tvb_get_letohs(tvb, offset);
-
- item = proto_tree_add_item(parent_tree, hf_smb2_session_flags, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- tree = proto_item_add_subtree(item, ett_smb2_ses_flags);
-
- proto_tree_add_boolean(tree, hf_smb2_ses_flags_guest, tvb, offset, 2, sf);
- proto_tree_add_boolean(tree, hf_smb2_ses_flags_null, tvb, offset, 2, sf);
+ static const int * flags[] = {
+ &hf_smb2_ses_flags_guest,
+ &hf_smb2_ses_flags_null,
+ NULL
+ };
+ proto_tree_add_bitmask(parent_tree, tvb, offset, hf_smb2_session_flags, ett_smb2_ses_flags, flags, ENC_LITTLE_ENDIAN);
offset += 2;
return offset;
static void
dissect_smb2_secblob(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si _U_)
{
- if ((tvb_length(tvb)>=7)
+ if ((tvb_captured_length(tvb)>=7)
&& (!tvb_memeql(tvb, 0, "NTLMSSP", 7))) {
call_dissector(ntlmssp_handle, tvb, pinfo, tree);
} else {
if (!ntlmssp_tap_id) {
GString *error_string;
- /* We dont specify any callbacks at all.
+ /* We don't specify any callbacks at all.
* Instead we manually fetch the tapped data after the
* security blob has been fully dissected and before
* we exit from this dissector.
sizeof(sesid->client_decryption_key));
}
sesid->server_port = pinfo->destport;
- sesid->auth_frame = pinfo->fd->num;
+ sesid->auth_frame = pinfo->num;
sesid->tids = g_hash_table_new(smb2_tid_info_hash, smb2_tid_info_equal);
g_hash_table_insert(si->conv->sesids, sesid, sesid);
}
return offset;
}
+/* This needs more fixes for cases when the original header had also the constant value of 9.
+ This should be fixed on caller side where it decides if it has to call this or not.
+*/
static int
-dissect_smb2_error_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_)
+dissect_smb2_error_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_,
+ gboolean* continue_dissection)
{
gint byte_count;
+ guint16 length;
/* buffer code */
- offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
+ offset = dissect_smb2_buffercode(tree, tvb, offset, &length);
+ /* FIX: error response uses this constant, if not then it is not an error response */
+ if(length != 9)
+ {
+ if(continue_dissection)
+ *continue_dissection = TRUE;
+ } else {
+ if(continue_dissection)
+ *continue_dissection = FALSE;
- /* Reserved (2 bytes) */
- proto_tree_add_item(tree, hf_smb2_error_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
+ /* Reserved (2 bytes) */
+ proto_tree_add_item(tree, hf_smb2_error_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- /* ByteCount (4 bytes): The number of bytes of data contained in ErrorData[]. */
- byte_count = tvb_get_ntohl(tvb, offset);
- proto_tree_add_item(tree, hf_smb2_error_byte_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- offset += 4;
+ /* ByteCount (4 bytes): The number of bytes of data contained in ErrorData[]. */
+ byte_count = tvb_get_ntohl(tvb, offset);
+ proto_tree_add_item(tree, hf_smb2_error_byte_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
- /* If the ByteCount field is zero then the server MUST supply an ErrorData field
- that is one byte in length */
- if (byte_count == 0) byte_count = 1;
+ /* If the ByteCount field is zero then the server MUST supply an ErrorData field
+ that is one byte in length */
+ if (byte_count == 0) byte_count = 1;
- /* ErrorData (variable): A variable-length data field that contains extended
- error information.*/
- proto_tree_add_item(tree, hf_smb2_error_data, tvb, offset, byte_count, ENC_NA);
- offset += byte_count;
+ /* ErrorData (variable): A variable-length data field that contains extended
+ error information.*/
+ proto_tree_add_item(tree, hf_smb2_error_data, tvb, offset, byte_count, ENC_NA);
+ offset += byte_count;
+ }
return offset;
}
offset = dissect_smb2_olb_tvb_max_offset(offset, &s_olb);
+ /* If we have found a uid->acct_name mapping, store it */
+#ifdef HAVE_KERBEROS
+ if (!pinfo->fd->flags.visited && si->status == 0) {
+ enc_key_t *ek;
+
+ if (krb_decrypt) {
+ read_keytab_file_from_preferences();
+ }
+
+ for (ek=enc_key_list;ek;ek=ek->next) {
+ if (ek->fd_num == (int)pinfo->num) {
+ break;
+ }
+ }
+
+ if (ek != NULL) {
+ smb2_sesid_info_t *sesid;
+ guint8 session_key[16] = { 0, };
+
+ memcpy(session_key, ek->keyvalue, MIN(ek->keylength, 16));
+
+ sesid = wmem_new(wmem_file_scope(), smb2_sesid_info_t);
+ sesid->sesid = si->sesid;
+ /* TODO: fill in the correct information */
+ sesid->acct_name = NULL;
+ sesid->domain_name = NULL;
+ sesid->host_name = NULL;
+ smb2_key_derivation(session_key, sizeof(session_key),
+ "SMB2AESCCM", 11,
+ "ServerIn ", 10,
+ sesid->server_decryption_key);
+ smb2_key_derivation(session_key, sizeof(session_key),
+ "SMB2AESCCM", 11,
+ "ServerOut", 10,
+ sesid->client_decryption_key);
+ sesid->server_port = pinfo->srcport;
+ sesid->auth_frame = pinfo->num;
+ sesid->tids = g_hash_table_new(smb2_tid_info_hash, smb2_tid_info_equal);
+ g_hash_table_insert(si->conv->sesids, sesid, sesid);
+ }
+ }
+#endif
+
return offset;
}
dissect_smb2_tree_connect_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si _U_)
{
guint16 share_type;
+ gboolean continue_dissection;
switch (si->status) {
- case 0x00000000: break;
- default: return dissect_smb2_error_response(tvb, pinfo, tree, offset, si);
- }
-
/* buffer code */
- offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
+ case 0x00000000: offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); break;
+ default: offset = dissect_smb2_error_response(tvb, pinfo, tree, offset, si, &continue_dissection);
+ if (!continue_dissection) return offset;
+ }
/* share type */
share_type = tvb_get_letohs(tvb, offset);
tid = wmem_new(wmem_file_scope(), smb2_tid_info_t);
tid->tid = si->tid;
tid->name = (char *)si->saved->extra_info;
- tid->connect_frame = pinfo->fd->num;
+ tid->connect_frame = pinfo->num;
tid->share_type = share_type;
g_hash_table_insert(si->session->tids, tid, tid);
static int
dissect_smb2_tree_disconnect_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_)
{
- switch (si->status) {
- case 0x00000000: break;
- default: return dissect_smb2_error_response(tvb, pinfo, tree, offset, si);
- }
+ gboolean continue_dissection;
+ switch (si->status) {
/* buffer code */
- offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
+ case 0x00000000: offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); break;
+ default: offset = dissect_smb2_error_response(tvb, pinfo, tree, offset, si, &continue_dissection);
+ if (!continue_dissection) return offset;
+ }
/* reserved */
offset += 2;
static int
dissect_smb2_sessionlogoff_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_)
{
- switch (si->status) {
- case 0x00000000: break;
- default: return dissect_smb2_error_response(tvb, pinfo, tree, offset, si);
- }
+ gboolean continue_dissection;
+ switch (si->status) {
/* buffer code */
- offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
+ case 0x00000000: offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); break;
+ default: offset = dissect_smb2_error_response(tvb, pinfo, tree, offset, si, &continue_dissection);
+ if (!continue_dissection) return offset;
+ }
/* reserved bytes */
offset += 2;
static int
dissect_smb2_keepalive_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_)
{
- switch (si->status) {
- case 0x00000000: break;
- default: return dissect_smb2_error_response(tvb, pinfo, tree, offset, si);
- }
+ gboolean continue_dissection;
+ switch (si->status) {
/* buffer code */
- offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
+ case 0x00000000: offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); break;
+ default: offset = dissect_smb2_error_response(tvb, pinfo, tree, offset, si, &continue_dissection);
+ if (!continue_dissection) return offset;
+ }
/* some unknown bytes */
proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, 2, ENC_NA);
return offset;
}
+static const value_string notify_action_vals[] = {
+ {0x01, "FILE_ACTION_ADDED"},
+ {0x02, "FILE_ACTION_REMOVED"},
+ {0x03, "FILE_ACTION_MODIFIED"},
+ {0x04, "FILE_ACTION_RENAMED_OLD_NAME"},
+ {0x05, "FILE_ACTION_RENAMED_NEW_NAME"},
+ {0x06, "FILE_ACTION_ADDED_STREAM"},
+ {0x07, "FILE_ACTION_REMOVED_STREAM"},
+ {0x08, "FILE_ACTION_MODIFIED_STREAM"},
+ {0x09, "FILE_ACTION_REMOVED_BY_DELETE"},
+ {0, NULL}
+};
+
static void
-dissect_smb2_notify_data_out(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_)
+dissect_smb2_notify_data_out(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, smb2_info_t *si _U_)
{
- proto_tree_add_item(tree, hf_smb2_unknown, tvb, 0, tvb_length(tvb), ENC_NA);
+ proto_tree *tree = NULL;
+ proto_item *item = NULL;
+ int offset = 0;
+
+ while (tvb_reported_length_remaining(tvb, offset) > 4) {
+ guint32 start_offset = offset;
+ guint32 next_offset;
+ guint32 length;
+
+ if (parent_tree) {
+ item = proto_tree_add_item(parent_tree, hf_smb2_notify_info, tvb, offset, -1, ENC_NA);
+ tree = proto_item_add_subtree(item, ett_smb2_notify_info);
+ }
+
+ /* next offset */
+ proto_tree_add_item_ret_uint(tree, hf_smb2_notify_next_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN, &next_offset);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_smb2_notify_action, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ /* file name length */
+ proto_tree_add_item_ret_uint(tree, hf_smb2_filename_len, tvb, offset, 4, ENC_LITTLE_ENDIAN, &length);
+ offset += 4;
+
+ /* file name */
+ if (length) {
+ const guchar *name = "";
+ guint16 bc;
+
+ bc = tvb_reported_length_remaining(tvb, offset);
+ name = get_unicode_or_ascii_string(tvb, &offset,
+ TRUE, &length, TRUE, TRUE, &bc);
+ if (name) {
+ proto_tree_add_string(tree, hf_smb2_filename,
+ tvb, offset, length,
+ name);
+ }
+
+ offset += length;
+ }
+
+ if (!next_offset) {
+ break;
+ }
+
+ offset = start_offset+next_offset;
+ }
}
static int
dissect_smb2_notify_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si)
{
offset_length_buffer_t olb;
+ gboolean continue_dissection;
switch (si->status) {
- case 0x00000000: break;
- default: return dissect_smb2_error_response(tvb, pinfo, tree, offset, si);
+ /* MS-SMB2 3.3.4.4 says STATUS_NOTIFY_ENUM_DIR is not treated as an error */
+ case 0x0000010c: /* STATUS_NOTIFY_ENUM_DIR */
+ case 0x00000000: /* buffer code */
+ offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); break;
+ default: offset = dissect_smb2_error_response(tvb, pinfo, tree, offset, si, &continue_dissection);
+ if (!continue_dissection) return offset;
}
- /* buffer code */
- offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
-
/* out buffer offset/length */
offset = dissect_smb2_olb_length_offset(tvb, offset, &olb, OLB_O_UINT16_S_UINT32, hf_smb2_notify_out_data);
const char *name = NULL;
guint16 bc;
- while (tvb_length_remaining(tvb, offset) > 4) {
+ while (tvb_reported_length_remaining(tvb, offset) > 4) {
int old_offset = offset;
int next_offset;
int file_name_len;
offset = old_offset+next_offset;
if (offset < old_offset) {
- proto_tree_add_text(tree, tvb, offset, tvb_length_remaining(tvb, offset),
+ proto_tree_add_expert_format(tree, pinfo, &ei_smb2_invalid_length, tvb, offset, -1,
"Invalid offset/length. Malformed packet");
return;
}
const char *name = NULL;
guint16 bc;
- while (tvb_length_remaining(tvb, offset) > 4) {
+ while (tvb_reported_length_remaining(tvb, offset) > 4) {
int old_offset = offset;
int next_offset;
int file_name_len;
offset = old_offset+next_offset;
if (offset < old_offset) {
- proto_tree_add_text(tree, tvb, offset, tvb_length_remaining(tvb, offset),
+ proto_tree_add_expert_format(tree, pinfo, &ei_smb2_invalid_length, tvb, offset, -1,
"Invalid offset/length. Malformed packet");
return;
}
const char *name = NULL;
guint16 bc;
- while (tvb_length_remaining(tvb, offset) > 4) {
+ while (tvb_reported_length_remaining(tvb, offset) > 4) {
int old_offset = offset;
int next_offset;
int file_name_len;
offset = old_offset+next_offset;
if (offset < old_offset) {
- proto_tree_add_text(tree, tvb, offset, tvb_length_remaining(tvb, offset),
+ proto_tree_add_expert_format(tree, pinfo, &ei_smb2_invalid_length, tvb, offset, -1,
"Invalid offset/length. Malformed packet");
return;
}
const char *name = NULL;
guint16 bc;
- while (tvb_length_remaining(tvb, offset) > 4) {
+ while (tvb_reported_length_remaining(tvb, offset) > 4) {
int old_offset = offset;
int next_offset;
int file_name_len;
offset = old_offset+next_offset;
if (offset < old_offset) {
- proto_tree_add_text(tree, tvb, offset, tvb_length_remaining(tvb, offset),
+ proto_tree_add_expert_format(tree, pinfo, &ei_smb2_invalid_length, tvb, offset, -1,
"Invalid offset/length. Malformed packet");
return;
}
const char *name = NULL;
guint16 bc;
- while (tvb_length_remaining(tvb, offset) > 4) {
+ while (tvb_reported_length_remaining(tvb, offset) > 4) {
int old_offset = offset;
int next_offset;
int file_name_len;
offset = old_offset+next_offset;
if (offset < old_offset) {
- proto_tree_add_text(tree, tvb, offset, tvb_length_remaining(tvb, offset),
+ proto_tree_add_expert_format(tree, pinfo, &ei_smb2_invalid_length, tvb, offset, -1,
"Invalid offset/length. Malformed packet");
return;
}
smb2_find_dissector_t *dis = smb2_find_dissectors;
while (dis->dissector) {
- if (si && si->saved && si->saved) {
- if (dis->level ==si->saved->infolevel) {
+ if (si && si->saved) {
+ if (dis->level == si->saved->infolevel) {
dis->dissector(tvb, pinfo, tree, si);
return;
}
dis++;
}
- proto_tree_add_item(tree, hf_smb2_unknown, tvb, 0, tvb_length(tvb), ENC_NA);
+ proto_tree_add_item(tree, hf_smb2_unknown, tvb, 0, tvb_captured_length(tvb), ENC_NA);
}
static int
{
offset_length_buffer_t olb;
proto_item *item = NULL;
+ gboolean continue_dissection;
if (si->saved) {
/* infolevel */
}
switch (si->status) {
- case 0x00000000: break;
- default: return dissect_smb2_error_response(tvb, pinfo, tree, offset, si);
- }
-
/* buffer code */
- offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
+ case 0x00000000: offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); break;
+ default: offset = dissect_smb2_error_response(tvb, pinfo, tree, offset, si, &continue_dissection);
+ if (!continue_dissection) return offset;
+ }
/* findinfo offset */
offset = dissect_smb2_olb_length_offset(tvb, offset, &olb, OLB_O_UINT16_S_UINT32, hf_smb2_find_info_blob);
}
static int
-dissect_smb2_negotiate_protocol_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_)
-{
- guint16 dc;
-
- /* buffer code */
- offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
+dissect_smb2_negotiate_context(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_)
+{
+ int start_offset = offset;
+ guint16 type;
+ const gchar *type_str;
+ guint16 data_length;
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+ tvbuff_t *sub_tvb;
+
+ sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1, ett_smb2_negotiate_context_element, &sub_item, "Negotiate Context");
+
+ /* type */
+ type = tvb_get_letohl(tvb, offset);
+ type_str = val_to_str(type, smb2_negotiate_context_types, "Unknown Type: (0x%0x)");
+ proto_item_append_text(sub_item, ": %s ", type_str);
+ proto_tree_add_item(sub_tree, hf_smb2_negotiate_context_type, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
- /* dialect count */
- dc = tvb_get_letohs(tvb, offset);
- proto_tree_add_item(tree, hf_smb2_dialect_count, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ /* data length */
+ data_length = tvb_get_letohl(tvb, offset);
+ proto_tree_add_item(sub_tree, hf_smb2_negotiate_context_data_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
- /* security mode, skip second byte */
- offset = dissect_smb2_secmode(tree, tvb, offset);
- offset++;
+ /* reserved */
+ proto_tree_add_item(sub_tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA);
+ offset += 4;
+
+ /* data */
+ sub_tvb = tvb_new_subset_length(tvb, offset, data_length);
+ offset += data_length;
+
+ proto_item_set_len(sub_item, offset - start_offset);
+
+ /*
+ * TODO: disssect the context data
+ */
+ proto_tree_add_item(sub_tree, hf_smb2_unknown, sub_tvb, 0, data_length, ENC_NA);
+
+ return offset;
+}
+
+static int
+dissect_smb2_negotiate_protocol_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_)
+{
+ guint16 dc;
+ guint16 i;
+ gboolean supports_smb_3_10 = FALSE;
+ guint32 nco;
+ guint16 ncc;
+
+ /* buffer code */
+ offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
+
+ /* dialect count */
+ dc = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_smb2_dialect_count, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ /* security mode, skip second byte */
+ offset = dissect_smb2_secmode(tree, tvb, offset);
+ offset++;
/* reserved */
+ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 2, ENC_NA);
offset += 2;
/* capabilities */
proto_tree_add_item(tree, hf_smb2_client_guid, tvb, offset, 16, ENC_LITTLE_ENDIAN);
offset += 16;
- /* client boot time */
- dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_boot_time);
- offset += 8;
+ /* negotiate context offset */
+ nco = tvb_get_letohl(tvb, offset);
+ proto_tree_add_item(tree, hf_smb2_negotiate_context_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
- for ( ; dc>0; dc--) {
+ /* negotiate context count */
+ ncc = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_smb2_negotiate_context_count, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ /* reserved */
+ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 2, ENC_NA);
+ offset += 2;
+
+ for (i = 0 ; i < dc; i++) {
+ guint16 d = tvb_get_letohs(tvb, offset);
proto_tree_add_item(tree, hf_smb2_dialect, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
+
+ if (d >= 0x310) {
+ supports_smb_3_10 = TRUE;
+ }
+ }
+
+ if (!supports_smb_3_10) {
+ ncc = 0;
+ }
+
+ if (nco != 0) {
+ guint32 tmp = 0x40 + 36 + dc * 2;
+
+ if (nco >= tmp) {
+ offset += nco - tmp;
+ } else {
+ ncc = 0;
+ }
+ }
+
+ for (i = 0; i < ncc; i++) {
+ offset = (offset + 7) & ~7;
+ offset = dissect_smb2_negotiate_context(tvb, pinfo, tree, offset, si);
}
return offset;
dissect_smb2_negotiate_protocol_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si _U_)
{
offset_length_buffer_t s_olb;
+ guint16 d;
+ guint16 i;
+ guint32 nco;
+ guint16 ncc;
+ gboolean continue_dissection;
switch (si->status) {
- case 0x00000000: break;
- default: return dissect_smb2_error_response(tvb, pinfo, tree, offset, si);
- }
-
/* buffer code */
- offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
+ case 0x00000000: offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); break;
+ default: offset = dissect_smb2_error_response(tvb, pinfo, tree, offset, si, &continue_dissection);
+ if (!continue_dissection) return offset;
+ }
/* security mode, skip second byte */
offset = dissect_smb2_secmode(tree, tvb, offset);
offset++;
/* dialect picked */
+ d = tvb_get_letohs(tvb, offset);
proto_tree_add_item(tree, hf_smb2_dialect, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
- /* reserved */
+ /* negotiate context count */
+ ncc = tvb_get_letohs(tvb, offset);
+ proto_tree_add_item(tree, hf_smb2_negotiate_context_count, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
/* server GUID */
/* the security blob itself */
dissect_smb2_olb_buffer(pinfo, tree, tvb, &s_olb, si, dissect_smb2_secblob);
- /* reserved */
+ /* negotiate context offset */
+ nco = tvb_get_letohl(tvb, offset);
+ proto_tree_add_item(tree, hf_smb2_negotiate_context_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
offset += 4;
offset = dissect_smb2_olb_tvb_max_offset(offset, &s_olb);
+ if (d < 0x310) {
+ ncc = 0;
+ }
+
+ if (nco != 0) {
+ guint32 tmp = 0x40 + 64 + s_olb.len;
+
+ if (nco >= tmp) {
+ offset += nco - tmp;
+ } else {
+ ncc = 0;
+ }
+ }
+
+ for (i = 0; i < ncc; i++) {
+ offset = (offset + 7) & ~7;
+ offset = dissect_smb2_negotiate_context(tvb, pinfo, tree, offset, si);
+ }
+
return offset;
}
case SMB2_CLASS_FILE_INFO:
switch (si->saved->infolevel) {
default:
- /* we dont handle this infolevel yet */
+ /* we don't handle this infolevel yet */
proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, 16, ENC_NA);
- offset += tvb_length_remaining(tvb, offset);
+ offset += tvb_captured_length_remaining(tvb, offset);
}
break;
case SMB2_CLASS_FS_INFO:
switch (si->saved->infolevel) {
default:
- /* we dont handle this infolevel yet */
+ /* we don't handle this infolevel yet */
proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, 16, ENC_NA);
- offset += tvb_length_remaining(tvb, offset);
+ offset += tvb_captured_length_remaining(tvb, offset);
}
break;
case SMB2_CLASS_SEC_INFO:
dissect_security_information_mask(tvb, tree, offset+8);
break;
default:
- /* we dont handle this infolevel yet */
+ /* we don't handle this infolevel yet */
proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, 16, ENC_NA);
- offset += tvb_length_remaining(tvb, offset);
+ offset += tvb_captured_length_remaining(tvb, offset);
}
break;
default:
- /* we dont handle this class yet */
+ /* we don't handle this class yet */
proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, 16, ENC_NA);
- offset += tvb_length_remaining(tvb, offset);
+ offset += tvb_captured_length_remaining(tvb, offset);
}
return offset;
}
static int
dissect_smb2_class_infolevel(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree, smb2_info_t *si)
{
- char cl, il;
+ guint8 cl, il;
proto_item *item;
int hfindex;
value_string_ext *vsx;
hfindex = hf_smb2_infolevel_sec_info;
vsx = &smb2_sec_info_levels_ext;
break;
+ case SMB2_CLASS_POSIX_INFO:
+ hfindex = hf_smb2_infolevel_posix_info;
+ vsx = &smb2_posix_info_levels_ext;
+ break;
default:
hfindex = hf_smb2_infolevel;
vsx = NULL; /* allowed arg to val_to_str_ext() */
offset = dissect_smb2_file_attribute_tag_info(tvb, pinfo, tree, offset, si);
break;
default:
- /* we dont handle this infolevel yet */
- proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, tvb_length_remaining(tvb, offset), ENC_NA);
- offset += tvb_length_remaining(tvb, offset);
+ /* we don't handle this infolevel yet */
+ proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, tvb_captured_length_remaining(tvb, offset), ENC_NA);
+ offset += tvb_captured_length_remaining(tvb, offset);
}
break;
case SMB2_CLASS_FS_INFO:
offset = dissect_smb2_FS_OBJECTID_INFO(tvb, pinfo, tree, offset, si);
break;
default:
- /* we dont handle this infolevel yet */
- proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, tvb_length_remaining(tvb, offset), ENC_NA);
- offset += tvb_length_remaining(tvb, offset);
+ /* we don't handle this infolevel yet */
+ proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, tvb_captured_length_remaining(tvb, offset), ENC_NA);
+ offset += tvb_captured_length_remaining(tvb, offset);
}
break;
case SMB2_CLASS_SEC_INFO:
offset = dissect_smb2_sec_info_00(tvb, pinfo, tree, offset, si);
break;
default:
- /* we dont handle this infolevel yet */
- proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, tvb_length_remaining(tvb, offset), ENC_NA);
- offset += tvb_length_remaining(tvb, offset);
+ /* we don't handle this infolevel yet */
+ proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, tvb_captured_length_remaining(tvb, offset), ENC_NA);
+ offset += tvb_captured_length_remaining(tvb, offset);
}
break;
default:
- /* we dont handle this class yet */
- proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, tvb_length_remaining(tvb, offset), ENC_NA);
- offset += tvb_length_remaining(tvb, offset);
+ /* we don't handle this class yet */
+ proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, tvb_captured_length_remaining(tvb, offset), ENC_NA);
+ offset += tvb_captured_length_remaining(tvb, offset);
}
/* if we get BUFFER_OVERFLOW there will be truncated data */
if (si->status == 0x80000005) {
proto_item *item;
- item = proto_tree_add_text(tree, tvb, old_offset, 0, "Truncated...");
+ item = proto_tree_add_item(tree, hf_smb2_truncated, tvb, old_offset, 0, ENC_NA);
PROTO_ITEM_SET_GENERATED(item);
}
return offset;
dissect_smb2_infolevel(tvb, pinfo, tree, 0, si, si->saved->smb2_class, si->saved->infolevel);
} else {
/* some unknown bytes */
- proto_tree_add_item(tree, hf_smb2_unknown, tvb, 0, tvb_length(tvb), ENC_NA);
+ proto_tree_add_item(tree, hf_smb2_unknown, tvb, 0, tvb_captured_length(tvb), ENC_NA);
}
}
dissect_smb2_getinfo_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si)
{
offset_length_buffer_t olb;
+ gboolean continue_dissection;
/* class/infolevel */
dissect_smb2_class_infolevel(pinfo, tvb, offset, tree, si);
switch (si->status) {
- case 0x00000000: break;
+ case 0x00000000:
/* if we get BUFFER_OVERFLOW there will be truncated data */
- case 0x80000005: break;
+ case 0x80000005:
/* if we get BUFFER_TOO_SMALL there will not be any data there, only
* a guin32 specifying how big the buffer needs to be
*/
+ /* buffer code */
+ offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
+ break;
case 0xc0000023:
offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
offset = dissect_smb2_olb_length_offset(tvb, offset, &olb, OLB_O_UINT16_S_UINT32, -1);
offset += 4;
return offset;
- default: return dissect_smb2_error_response(tvb, pinfo, tree, offset, si);
+ default: offset = dissect_smb2_error_response(tvb, pinfo, tree, offset, si, &continue_dissection);
+ if (!continue_dissection) return offset;
}
-
- /* buffer code */
- offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
/* response buffer offset and size */
offset = dissect_smb2_olb_length_offset(tvb, offset, &olb, OLB_O_UINT16_S_UINT32, -1);
{
proto_tree *flags_tree = NULL;
proto_item *flags_item = NULL;
+ gboolean continue_dissection;
switch (si->status) {
- case 0x00000000: break;
- default: return dissect_smb2_error_response(tvb, pinfo, tree, offset, si);
- }
-
/* buffer code */
- offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
+ case 0x00000000: offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); break;
+ default: offset = dissect_smb2_error_response(tvb, pinfo, tree, offset, si, &continue_dissection);
+ if (!continue_dissection) return offset;
+ }
/* close flags */
if (tree) {
static int
dissect_smb2_flush_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_)
{
- switch (si->status) {
- case 0x00000000: break;
- default: return dissect_smb2_error_response(tvb, pinfo, tree, offset, si);
- }
+ gboolean continue_dissection;
+ switch (si->status) {
/* buffer code */
- offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
+ case 0x00000000: offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); break;
+ default: offset = dissect_smb2_error_response(tvb, pinfo, tree, offset, si, &continue_dissection);
+ if (!continue_dissection) return offset;
+ }
/* some unknown bytes */
proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, 2, ENC_NA);
static int
dissect_smb2_lock_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_)
{
- switch (si->status) {
- case 0x00000000: break;
- default: return dissect_smb2_error_response(tvb, pinfo, tree, offset, si);
- }
+ gboolean continue_dissection;
+ switch (si->status) {
/* buffer code */
- offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
+ case 0x00000000: offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); break;
+ default: offset = dissect_smb2_error_response(tvb, pinfo, tree, offset, si, &continue_dissection);
+ if (!continue_dissection) return offset;
+ }
/* some unknown bytes */
proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, 2, ENC_NA);
return offset;
}
+static const smb2_fid_info_t *
+smb2_pipe_get_fid_info(const smb2_info_t *si)
+{
+ smb2_fid_info_t *file = NULL;
+
+ if (si == NULL) {
+ return NULL;
+ }
+ if (si->file != NULL) {
+ file = si->file;
+ } else if (si->saved != NULL) {
+ file = si->saved->file;
+ }
+ if (file == NULL) {
+ return NULL;
+ }
+
+ return file;
+}
+
+static void
+smb2_pipe_set_file_id(packet_info *pinfo, smb2_info_t *si)
+{
+ guint64 persistent;
+ const smb2_fid_info_t *file = NULL;
+
+ file = smb2_pipe_get_fid_info(si);
+ if (file == NULL) {
+ return;
+ }
+
+ persistent = GPOINTER_TO_UINT(file);
+
+ dcerpc_set_transport_salt(persistent, pinfo);
+}
+
+static gboolean smb2_pipe_reassembly = TRUE;
+static reassembly_table smb2_pipe_reassembly_table;
+
+static void
+smb2_pipe_reassembly_init(void)
+{
+ /*
+ * XXX - addresses_ports_reassembly_table_functions?
+ * Probably correct for SMB-over-NBT and SMB-over-TCP,
+ * as stuff from two different connections should
+ * probably not be combined, but what about other
+ * transports for SMB, e.g. NBF or Netware?
+ */
+ reassembly_table_init(&smb2_pipe_reassembly_table,
+ &addresses_reassembly_table_functions);
+}
static int
-dissect_file_data_dcerpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, int offset, guint32 datalen, proto_tree *top_tree)
+dissect_file_data_smb2_pipe(tvbuff_t *raw_tvb, packet_info *pinfo, proto_tree *tree _U_, int offset, guint32 datalen, proto_tree *top_tree, void *data)
{
- tvbuff_t *dcerpc_tvb;
- dcerpc_tvb = tvb_new_subset(tvb, offset, MIN((int)datalen, tvb_length_remaining(tvb, offset)), datalen);
+ /*
+ * Note: si is NULL for some callers from packet-smb.c
+ */
+ const smb2_info_t *si = (const smb2_info_t *)data;
+ gboolean result=0;
+ gboolean save_fragmented;
+ gint remaining;
+ guint reported_len;
+ const smb2_fid_info_t *file = NULL;
+ guint32 id;
+ fragment_head *fd_head;
+ tvbuff_t *tvb;
+ tvbuff_t *new_tvb;
+ proto_item *frag_tree_item;
+ heur_dtbl_entry_t *hdtbl_entry;
+
+ file = smb2_pipe_get_fid_info(si);
+ id = (guint32)(GPOINTER_TO_UINT(file) & G_MAXUINT32);
+
+ remaining = tvb_captured_length_remaining(raw_tvb, offset);
+
+ tvb = tvb_new_subset(raw_tvb, offset,
+ MIN((int)datalen, remaining),
+ datalen);
+
+ /*
+ * Offer desegmentation service to Named Pipe subdissectors (e.g. DCERPC)
+ * if we have all the data. Otherwise, reassembly is (probably) impossible.
+ */
+ pinfo->can_desegment = 0;
+ pinfo->desegment_offset = 0;
+ pinfo->desegment_len = 0;
+ reported_len = tvb_reported_length(tvb);
+ if (smb2_pipe_reassembly && tvb_captured_length(tvb) >= reported_len) {
+ pinfo->can_desegment = 2;
+ }
+
+ save_fragmented = pinfo->fragmented;
+
+ /*
+ * if we are not offering desegmentation, just try the heuristics
+ *and bail out
+ */
+ if (!pinfo->can_desegment) {
+ result = dissector_try_heuristic(smb2_pipe_subdissector_list,
+ tvb, pinfo, top_tree,
+ &hdtbl_entry, data);
+ goto clean_up_and_exit;
+ }
+
+ /* below this line, we know we are doing reassembly */
+
+ /*
+ * this is a new packet, see if we are already reassembling this
+ * pdu and if not, check if the dissector wants us
+ * to reassemble it
+ */
+ if (!pinfo->fd->flags.visited) {
+ /*
+ * This is the first pass.
+ *
+ * Check if we are already reassembling this PDU or not;
+ * we check for an in-progress reassembly for this FID
+ * in this direction, by searching for its reassembly
+ * structure.
+ */
+ fd_head = fragment_get(&smb2_pipe_reassembly_table,
+ pinfo, id, NULL);
+ if (!fd_head) {
+ /*
+ * No reassembly, so this is a new pdu. check if the
+ * dissector wants us to reassemble it or if we
+ * already got the full pdu in this tvb.
+ */
+
+ /*
+ * Try the heuristic dissectors and see if we
+ * find someone that recognizes this payload.
+ */
+ result = dissector_try_heuristic(smb2_pipe_subdissector_list,
+ tvb, pinfo, top_tree,
+ &hdtbl_entry, data);
+
+ /* no this didn't look like something we know */
+ if (!result) {
+ goto clean_up_and_exit;
+ }
+
+ /* did the subdissector want us to reassemble any
+ more data ?
+ */
+ if (pinfo->desegment_len) {
+ fragment_add_check(&smb2_pipe_reassembly_table,
+ tvb, 0, pinfo, id, NULL,
+ 0, reported_len, TRUE);
+ fragment_set_tot_len(&smb2_pipe_reassembly_table,
+ pinfo, id, NULL,
+ pinfo->desegment_len+reported_len);
+ }
+ goto clean_up_and_exit;
+ }
+
+ /* OK, we're already doing a reassembly for this FID.
+ skip to last segment in the existing reassembly structure
+ and add this fragment there
+
+ XXX we might add code here to use any offset values
+ we might pick up from the Read/Write calls instead of
+ assuming we always get them in the correct order
+ */
+ while (fd_head->next) {
+ fd_head = fd_head->next;
+ }
+ fd_head = fragment_add_check(&smb2_pipe_reassembly_table,
+ tvb, 0, pinfo, id, NULL,
+ fd_head->offset+fd_head->len,
+ reported_len, TRUE);
+
+ /* if we completed reassembly */
+ if (fd_head) {
+ new_tvb = tvb_new_chain(tvb, fd_head->tvb_data);
+ add_new_data_source(pinfo, new_tvb,
+ "Named Pipe over SMB2");
+ pinfo->fragmented=FALSE;
+
+ tvb = new_tvb;
+
+ /* list what segments we have */
+ show_fragment_tree(fd_head, &smb2_pipe_frag_items,
+ tree, pinfo, tvb, &frag_tree_item);
+
+ /* dissect the full PDU */
+ result = dissector_try_heuristic(smb2_pipe_subdissector_list,
+ tvb, pinfo, top_tree,
+ &hdtbl_entry, data);
+ }
+ goto clean_up_and_exit;
+ }
+
+ /*
+ * This is not the first pass; see if it's in the table of
+ * reassembled packets.
+ *
+ * XXX - we know that several of the arguments aren't going to
+ * be used, so we pass bogus variables. Can we clean this
+ * up so that we don't have to distinguish between the first
+ * pass and subsequent passes?
+ */
+ fd_head = fragment_add_check(&smb2_pipe_reassembly_table,
+ tvb, 0, pinfo, id, NULL, 0, 0, TRUE);
+ if (!fd_head) {
+ /* we didn't find it, try any of the heuristic dissectors
+ and bail out
+ */
+ result = dissector_try_heuristic(smb2_pipe_subdissector_list,
+ tvb, pinfo, top_tree,
+ &hdtbl_entry, data);
+ goto clean_up_and_exit;
+ }
+ if (!(fd_head->flags&FD_DEFRAGMENTED)) {
+ /* we don't have a fully reassembled frame */
+ result = dissector_try_heuristic(smb2_pipe_subdissector_list,
+ tvb, pinfo, top_tree,
+ &hdtbl_entry, data);
+ goto clean_up_and_exit;
+ }
+
+ /* it is reassembled but it was reassembled in a different frame */
+ if (pinfo->num != fd_head->reassembled_in) {
+ proto_item *item;
+ item = proto_tree_add_uint(top_tree, hf_smb2_pipe_reassembled_in,
+ tvb, 0, 0, fd_head->reassembled_in);
+ PROTO_ITEM_SET_GENERATED(item);
+ goto clean_up_and_exit;
+ }
+
+ /* display the reassembled pdu */
+ new_tvb = tvb_new_chain(tvb, fd_head->tvb_data);
+ add_new_data_source(pinfo, new_tvb,
+ "Named Pipe over SMB2");
+ pinfo->fragmented = FALSE;
+
+ tvb = new_tvb;
+
+ /* list what segments we have */
+ show_fragment_tree(fd_head, &smb2_pipe_frag_items,
+ top_tree, pinfo, tvb, &frag_tree_item);
/* dissect the full PDU */
- dissector_try_heuristic(smb2_heur_subdissector_list, dcerpc_tvb, pinfo, top_tree, NULL);
+ result = dissector_try_heuristic(smb2_pipe_subdissector_list,
+ tvb, pinfo, top_tree,
+ &hdtbl_entry, data);
+clean_up_and_exit:
+ /* clear out the variables */
+ pinfo->can_desegment=0;
+ pinfo->desegment_offset = 0;
+ pinfo->desegment_len = 0;
- offset += datalen;
+ if (!result) {
+ call_data_dissector(tvb, pinfo, top_tree);
+ }
+
+ pinfo->fragmented = save_fragmented;
+ offset += datalen;
return offset;
}
+#define SMB2_CHANNEL_NONE 0x00000000
+#define SMB2_CHANNEL_RDMA_V1 0x00000001
+#define SMB2_CHANNEL_RDMA_V1_INVALIDATE 0x00000002
+
+static const value_string smb2_channel_vals[] = {
+ { SMB2_CHANNEL_NONE, "None" },
+ { SMB2_CHANNEL_RDMA_V1, "RDMA V1" },
+ { SMB2_CHANNEL_RDMA_V1_INVALIDATE, "RDMA V1_INVALIDATE" },
+ { 0, NULL }
+};
+
+static void
+dissect_smb2_rdma_v1_blob(tvbuff_t *tvb, packet_info *pinfo _U_,
+ proto_tree *parent_tree, smb2_info_t *si _U_)
+{
+ int offset = 0;
+ int len;
+ int i;
+ int num;
+ proto_tree *sub_tree;
+ proto_item *parent_item;
+
+ parent_item = proto_tree_get_parent(parent_tree);
+
+ len = tvb_reported_length(tvb);
+
+ num = len / 16;
+
+ if (parent_item) {
+ proto_item_append_text(parent_item, ": SMBDirect Buffer Descriptor V1: (%d elements)", num);
+ }
+
+ for (i = 0; i < num; i++) {
+ sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, 8, ett_smb2_rdma_v1, NULL, "RDMA V1");
+
+ proto_tree_add_item(sub_tree, hf_smb2_rdma_v1_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+
+ proto_tree_add_item(sub_tree, hf_smb2_rdma_v1_token, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(sub_tree, hf_smb2_rdma_v1_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+ }
+}
+
#define SMB2_WRITE_FLAG_WRITE_THROUGH 0x00000001
static int
{
guint16 dataoffset = 0;
guint32 data_tvb_len;
+ offset_length_buffer_t c_olb;
+ guint32 channel;
guint32 length;
guint64 off;
static const int *f_fields[] = {
offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
/* data offset */
- dataoffset=tvb_get_letohl(tvb,offset);
+ dataoffset=tvb_get_letohs(tvb,offset);
proto_tree_add_item(tree, hf_smb2_data_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
offset = dissect_smb2_fid(tvb, pinfo, tree, offset, si, FID_MODE_USE);
/* channel */
+ channel = tvb_get_letohl(tvb, offset);
proto_tree_add_item(tree, hf_smb2_channel, tvb, offset, 4, ENC_LITTLE_ENDIAN);
offset += 4;
proto_tree_add_item(tree, hf_smb2_remaining_bytes, tvb, offset, 4, ENC_LITTLE_ENDIAN);
offset += 4;
- /* write channel info offset */
- proto_tree_add_item(tree, hf_smb2_channel_info_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
-
- /* write channel info length */
- proto_tree_add_item(tree, hf_smb2_channel_info_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
+ /* write channel info blob offset/length */
+ offset = dissect_smb2_olb_length_offset(tvb, offset, &c_olb, OLB_O_UINT16_S_UINT16, hf_smb2_channel_info_blob);
/* flags */
proto_tree_add_bitmask(tree, tvb, offset, hf_smb2_write_flags, ett_smb2_write_flags, f_fields, ENC_LITTLE_ENDIAN);
offset += 4;
- /* data or dcerpc ?*/
- if (length && si->tree && si->tree->share_type == SMB2_SHARE_TYPE_PIPE) {
- offset = dissect_file_data_dcerpc(tvb, pinfo, tree, offset, length, si->top_tree);
- return offset;
+ /* the write channel info blob itself */
+ switch (channel) {
+ case SMB2_CHANNEL_RDMA_V1:
+ case SMB2_CHANNEL_RDMA_V1_INVALIDATE:
+ dissect_smb2_olb_buffer(pinfo, tree, tvb, &c_olb, si, dissect_smb2_rdma_v1_blob);
+ break;
+ case SMB2_CHANNEL_NONE:
+ default:
+ dissect_smb2_olb_buffer(pinfo, tree, tvb, &c_olb, si, NULL);
+ break;
+ }
+
+ /* data or namedpipe ?*/
+ if (length) {
+ int oldoffset = offset;
+ smb2_pipe_set_file_id(pinfo, si);
+ offset = dissect_file_data_smb2_pipe(tvb, pinfo, tree, offset, length, si->top_tree, si);
+ if (offset != oldoffset) {
+ /* managed to dissect pipe data */
+ return offset;
+ }
}
/* just ordinary data */
proto_tree_add_item(tree, hf_smb2_write_data, tvb, offset, length, ENC_NA);
- data_tvb_len=(guint32)tvb_length_remaining(tvb, offset);
+ data_tvb_len=(guint32)tvb_captured_length_remaining(tvb, offset);
- offset += MIN(length,(guint32)tvb_length_remaining(tvb, offset));
+ offset += MIN(length,(guint32)tvb_captured_length_remaining(tvb, offset));
+
+ offset = dissect_smb2_olb_tvb_max_offset(offset, &c_olb);
if (have_tap_listener(smb2_eo_tap) && (data_tvb_len == length)) {
if (si->saved && si->eo_file_info) { /* without this data we don't know wich file this belongs to */
static int
dissect_smb2_write_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_)
{
- switch (si->status) {
- case 0x00000000: break;
- default: return dissect_smb2_error_response(tvb, pinfo, tree, offset, si);
- }
+ gboolean continue_dissection;
+ switch (si->status) {
/* buffer code */
- offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
+ case 0x00000000: offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); break;
+ default: offset = dissect_smb2_error_response(tvb, pinfo, tree, offset, si, &continue_dissection);
+ if (!continue_dissection) return offset;
+ }
/* reserved */
proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 2, ENC_NA);
return offset;
}
-static void
-dissect_smb2_FSCTL_PIPE_TRANSCEIVE(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *top_tree, gboolean data_in _U_)
+/* The STORAGE_OFFLOAD_TOKEN is used for "Offload Data Transfer" (ODX) operations,
+ including FSCTL_OFFLOAD_READ, FSCTL_OFFLOAD_WRITE. Ref: MS-FSCC 2.3.79
+ Note: Unlike most of SMB2, the token fields are BIG-endian! */
+static int
+dissect_smb2_STORAGE_OFFLOAD_TOKEN(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
{
- dissect_file_data_dcerpc(tvb, pinfo, tree, offset, tvb_length_remaining(tvb, offset), top_tree);
-}
+ proto_tree *sub_tree;
+ proto_item *sub_item;
+ guint32 idlen = 0;
+ guint32 idtype = 0;
-static void
-dissect_smb2_FSCTL_LMR_REQUEST_RESILIENCY(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, gboolean data_in)
-{
- /* There is no out data */
- if (!data_in) {
- return;
- }
+ sub_tree = proto_tree_add_subtree(tree, tvb, offset, 512, ett_smb2_fsctl_odx_token, &sub_item, "Token");
- /* timeout */
- proto_tree_add_item(tree, hf_smb2_ioctl_resiliency_timeout, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item_ret_uint(sub_tree, hf_smb2_fsctl_odx_token_type, tvb, offset, 4, ENC_BIG_ENDIAN, &idtype);
offset += 4;
+ proto_item_append_text(sub_item, " (IdType 0x%x)", idtype);
+
/* reserved */
- proto_tree_add_item(tree, hf_smb2_ioctl_resiliency_reserved, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(sub_tree, hf_smb2_reserved, tvb, offset, 2, ENC_NA);
+ offset += 2;
+
+ /* TokenIdLength */
+ proto_tree_add_item_ret_uint(sub_tree, hf_smb2_fsctl_odx_token_idlen, tvb, offset, 2, ENC_BIG_ENDIAN, &idlen);
+ offset += 2;
+
+ /* idlen is what the server says is the "meaningful" part of the token.
+ However, token ID is always 504 bytes */
+ proto_tree_add_bytes_format_value(sub_tree, hf_smb2_fsctl_odx_token_idraw, tvb,
+ offset, idlen, NULL, "Opaque Data");
+ offset += 504;
+
+ return (offset);
}
+/* MS-FSCC 2.3.77, 2.3.78 */
static void
-dissect_windows_sockaddr_in(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, int len)
+dissect_smb2_FSCTL_OFFLOAD_READ(tvbuff_t *tvb,
+ packet_info *pinfo _U_,
+ proto_tree *tree,
+ int offset,
+ gboolean in)
{
- proto_item *sub_item = NULL;
- proto_tree *sub_tree = NULL;
- proto_item *parent_item = NULL;
- guint32 addr;
+ proto_tree_add_item(tree, hf_smb2_fsctl_odx_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
- if (len == -1) {
- len = 16;
- }
+ proto_tree_add_item(tree, hf_smb2_fsctl_odx_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
- if (parent_tree) {
- sub_item = proto_tree_add_text(parent_tree, tvb, offset, len, "Socket Address");
- sub_tree = proto_item_add_subtree(sub_item, ett_windows_sockaddr);
- parent_item = proto_tree_get_parent(parent_tree);
- }
+ if (in) {
+ proto_tree_add_item(tree, hf_smb2_fsctl_odx_token_ttl, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
- /* family */
- proto_tree_add_item(sub_tree, hf_windows_sockaddr_family, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
+ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA);
+ offset += 4;
- /* port */
- proto_tree_add_item(sub_tree, hf_windows_sockaddr_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
+ proto_tree_add_item(tree, hf_smb2_fsctl_odx_file_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
- /* IPv4 address */
- addr = tvb_get_ipv4(tvb, offset);
- proto_tree_add_ipv4(sub_tree, hf_windows_sockaddr_in_addr, tvb, offset, 4, addr);
- if (sub_item) {
- proto_item_append_text(sub_item, ", IPv4: %s", tvb_ip_to_str(tvb, offset));
- }
- if (parent_item) {
- proto_item_append_text(parent_item, ", IPv4: %s", tvb_ip_to_str(tvb, offset));
+ proto_tree_add_item(tree, hf_smb2_fsctl_odx_copy_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ /* offset += 8; */
+ } else {
+ proto_tree_add_item(tree, hf_smb2_fsctl_odx_xfer_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+
+ (void) dissect_smb2_STORAGE_OFFLOAD_TOKEN(tvb, pinfo, tree, offset);
}
}
+/* MS-FSCC 2.3.80, 2.3.81 */
static void
-dissect_windows_sockaddr_in6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, int len)
+dissect_smb2_FSCTL_OFFLOAD_WRITE(tvbuff_t *tvb,
+ packet_info *pinfo _U_,
+ proto_tree *tree,
+ int offset,
+ gboolean in)
{
- struct e_in6_addr addr;
- proto_item *sub_item = NULL;
- proto_tree *sub_tree = NULL;
- proto_item *parent_item = NULL;
+ proto_tree_add_item(tree, hf_smb2_fsctl_odx_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
- if (len == -1) {
- len = 16;
- }
+ proto_tree_add_item(tree, hf_smb2_fsctl_odx_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
- if (parent_tree) {
- sub_item = proto_tree_add_text(parent_tree, tvb, offset, len, "Socket Address");
- sub_tree = proto_item_add_subtree(sub_item, ett_windows_sockaddr);
- parent_item = proto_tree_get_parent(parent_tree);
- }
+ if (in) {
+ proto_tree_add_item(tree, hf_smb2_fsctl_odx_file_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+
+ proto_tree_add_item(tree, hf_smb2_fsctl_odx_copy_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+
+ proto_tree_add_item(tree, hf_smb2_fsctl_odx_token_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+
+ dissect_smb2_STORAGE_OFFLOAD_TOKEN(tvb, pinfo, tree, offset);
+
+ } else {
+ proto_tree_add_item(tree, hf_smb2_fsctl_odx_xfer_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ /* offset += 8; */
+ }
+}
+
+static void
+dissect_smb2_FSCTL_PIPE_TRANSCEIVE(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *top_tree, gboolean data_in _U_, void *data)
+{
+ dissect_file_data_smb2_pipe(tvb, pinfo, tree, offset, tvb_captured_length_remaining(tvb, offset), top_tree, data);
+}
+
+static void
+dissect_smb2_FSCTL_PIPE_WAIT(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, int offset, proto_tree *top_tree, gboolean data_in _U_)
+{
+ guint8 timeout_specified = tvb_get_guint8(tvb, offset + 12);
+ guint32 name_len = tvb_get_letohs(tvb, offset + 8);
+ const gchar *name;
+ int off = offset + 14;
+ guint16 bc = tvb_captured_length_remaining(tvb, off);
+ int len = name_len;
+
+ /* sanity check */
+ tvb_ensure_bytes_exist(tvb, off, name_len);
+
+ name = get_unicode_or_ascii_string(tvb, &off, TRUE, &len, TRUE, TRUE, &bc);
+ if (name == NULL) {
+ name = "";
+ }
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, " Pipe: %s", name);
+
+ if (top_tree) {
+ proto_tree_add_string(top_tree, hf_smb2_fsctl_pipe_wait_name, tvb, offset + 14, name_len, name);
+ if (timeout_specified) {
+ proto_tree_add_item(top_tree, hf_smb2_fsctl_pipe_wait_timeout, tvb, 0, 8, ENC_LITTLE_ENDIAN);
+ }
+ }
+}
+
+static int
+dissect_smb2_FSCTL_SET_SPARSE(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, gboolean data_in)
+{
+
+ /* There is no out data */
+ if (!data_in) {
+ return offset;
+ }
+
+ /* sparse flag (optional) */
+ if (tvb_reported_length_remaining(tvb, offset) >= 1) {
+ proto_tree_add_item(tree, hf_smb2_fsctl_sparse_flag, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ }
+
+ return offset;
+}
+
+static int
+dissect_smb2_FSCTL_SET_ZERO_DATA(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, gboolean data_in)
+{
+ proto_tree *sub_tree;
+ proto_item *sub_item;
+
+ /* There is no out data */
+ if (!data_in) {
+ return offset;
+ }
+
+ sub_tree = proto_tree_add_subtree(tree, tvb, offset, 16, ett_smb2_fsctl_range_data, &sub_item, "Range");
+
+ proto_tree_add_item(sub_tree, hf_smb2_fsctl_range_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+
+ proto_tree_add_item(sub_tree, hf_smb2_fsctl_range_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+
+ return offset;
+}
+
+static void
+dissect_smb2_FSCTL_QUERY_ALLOCATED_RANGES(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, int offset _U_, gboolean data_in)
+{
+ proto_tree *sub_tree;
+ proto_item *sub_item;
+
+ if (data_in) {
+ sub_tree = proto_tree_add_subtree(tree, tvb, offset, 16, ett_smb2_fsctl_range_data, &sub_item, "Range");
+
+ proto_tree_add_item(sub_tree, hf_smb2_fsctl_range_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+
+ proto_tree_add_item(sub_tree, hf_smb2_fsctl_range_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+ } else {
+ /* Zero or more allocated ranges may be reported. */
+ while (tvb_reported_length_remaining(tvb, offset) >= 16) {
+
+ sub_tree = proto_tree_add_subtree(tree, tvb, offset, 16, ett_smb2_fsctl_range_data, &sub_item, "Range");
+
+ proto_tree_add_item(sub_tree, hf_smb2_fsctl_range_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+
+ proto_tree_add_item(sub_tree, hf_smb2_fsctl_range_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+ }
+ }
+}
+
+
+static void
+dissect_smb2_FSCTL_QUERY_FILE_REGIONS(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, int offset _U_, gboolean data_in)
+{
+
+ if (data_in) {
+ proto_tree_add_item(tree, hf_smb2_file_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+
+ proto_tree_add_item(tree, hf_smb2_qfr_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+
+ proto_tree_add_item(tree, hf_smb2_qfr_usage, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA);
+ offset += 4;
+ } else {
+ guint32 entry_count = 0;
+
+ proto_tree_add_item(tree, hf_smb2_qfr_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_smb2_qfr_total_region_entry_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item_ret_uint(tree, hf_smb2_qfr_region_entry_count, tvb, offset, 4, ENC_LITTLE_ENDIAN, &entry_count);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA);
+ offset += 4;
+
+ while (entry_count && tvb_reported_length_remaining(tvb, offset)) {
+ proto_tree *sub_tree;
+ proto_item *sub_item;
+
+ sub_tree = proto_tree_add_subtree(tree, tvb, offset, 24, ett_qfr_entry, &sub_item, "Entry");
+
+ proto_tree_add_item(sub_tree, hf_smb2_file_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+
+ proto_tree_add_item(sub_tree, hf_smb2_qfr_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+
+ proto_tree_add_item(sub_tree, hf_smb2_qfr_usage, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(sub_tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA);
+ offset += 4;
+
+ entry_count--;
+ }
+ }
+}
+
+static void
+dissect_smb2_FSCTL_LMR_REQUEST_RESILIENCY(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, gboolean data_in)
+{
+ /* There is no out data */
+ if (!data_in) {
+ return;
+ }
+
+ /* timeout */
+ proto_tree_add_item(tree, hf_smb2_ioctl_resiliency_timeout, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ /* reserved */
+ proto_tree_add_item(tree, hf_smb2_ioctl_resiliency_reserved, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+}
+
+static void
+dissect_smb2_FSCTL_QUERY_SHARED_VIRTUAL_DISK_SUPPORT(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, int offset _U_, gboolean data_in _U_)
+{
+ /* There is no out data */
+ if (!data_in) {
+ return;
+ }
+
+ /* There is nothing to do here ... */
+}
+
+static void
+dissect_windows_sockaddr_in(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, int len)
+{
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+ proto_item *parent_item;
+
+ if (len == -1) {
+ len = 16;
+ }
+
+ sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, len, ett_windows_sockaddr, &sub_item, "Socket Address");
+ parent_item = proto_tree_get_parent(parent_tree);
+
+ /* family */
+ proto_tree_add_item(sub_tree, hf_windows_sockaddr_family, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ /* port */
+ proto_tree_add_item(sub_tree, hf_windows_sockaddr_port, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ /* IPv4 address */
+ proto_tree_add_item(sub_tree, hf_windows_sockaddr_in_addr, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+
+ proto_item_append_text(sub_item, ", IPv4: %s", tvb_ip_to_str(tvb, offset));
+ proto_item_append_text(parent_item, ", IPv4: %s", tvb_ip_to_str(tvb, offset));
+}
+
+static void
+dissect_windows_sockaddr_in6(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, int len)
+{
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+ proto_item *parent_item;
+
+ if (len == -1) {
+ len = 16;
+ }
+
+ sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, len, ett_windows_sockaddr, &sub_item, "Socket Address");
+ parent_item = proto_tree_get_parent(parent_tree);
/* family */
proto_tree_add_item(sub_tree, hf_windows_sockaddr_family, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 4;
/* IPv4 address */
- tvb_get_ipv6(tvb, offset, &addr);
- proto_tree_add_ipv6(sub_tree, hf_windows_sockaddr_in6_addr, tvb, offset, 16, (guint8 *)&addr);
- if (sub_item) {
- proto_item_append_text(sub_item, ", IPv6: %s", tvb_ip6_to_str(tvb, offset));
- }
- if (parent_item) {
- proto_item_append_text(parent_item, ", IPv6: %s", tvb_ip6_to_str(tvb, offset));
- }
+ proto_tree_add_item(sub_tree, hf_windows_sockaddr_in6_addr, tvb, offset, 16, ENC_NA);
+ proto_item_append_text(sub_item, ", IPv6: %s", tvb_ip6_to_str(tvb, offset));
+ proto_item_append_text(parent_item, ", IPv6: %s", tvb_ip6_to_str(tvb, offset));
offset += 16;
/* sin6_scope_id */
dissect_windows_sockaddr_storage(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
{
int len = 128;
- proto_item *sub_item = NULL;
- proto_tree *sub_tree = NULL;
- proto_item *parent_item = NULL;
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+ proto_item *parent_item;
guint16 family;
family = tvb_get_letohs(tvb, offset);
return;
}
- if (parent_tree) {
- sub_item = proto_tree_add_text(parent_tree, tvb, offset, len, "Socket Address");
- sub_tree = proto_item_add_subtree(sub_item, ett_windows_sockaddr);
- parent_item = proto_tree_get_parent(parent_tree);
- }
+ sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, len, ett_windows_sockaddr, &sub_item, "Socket Address");
+ parent_item = proto_tree_get_parent(parent_tree);
/* ss_family */
proto_tree_add_item(sub_tree, hf_windows_sockaddr_family, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- if (sub_item) {
- proto_item_append_text(sub_item, ", Family: %d (0x%04x)", family, family);
- }
- if (parent_item) {
- proto_item_append_text(sub_item, ", Family: %d (0x%04x)", family, family);
- }
+ proto_item_append_text(sub_item, ", Family: %d (0x%04x)", family, family);
+ proto_item_append_text(parent_item, ", Family: %d (0x%04x)", family, family);
/*offset += 2;*/
/* unknown */
guint32 next_offset;
int offset = 0;
int len = -1;
- proto_item *sub_item = NULL;
- proto_tree *sub_tree = NULL;
- proto_item *item = NULL;
+ proto_item *sub_item;
+ proto_tree *sub_tree;
+ proto_item *item;
guint32 capabilities;
guint64 link_speed;
gfloat val = 0;
const char *unit = NULL;
+ static const int * capability_flags[] = {
+ &hf_smb2_ioctl_network_interface_capability_rdma,
+ &hf_smb2_ioctl_network_interface_capability_rss,
+ NULL
+ };
next_offset = tvb_get_letohl(tvb, offset);
if (next_offset) {
len = next_offset;
}
- if (parent_tree) {
- sub_item = proto_tree_add_text(parent_tree, tvb, offset, len, "Network Interface");
- sub_tree = proto_item_add_subtree(sub_item, ett_smb2_ioctl_network_interface);
- }
+ sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, len, ett_smb2_ioctl_network_interface, &sub_item, "Network Interface");
+ item = proto_tree_get_parent(parent_tree);
/* next offset */
proto_tree_add_item(sub_tree, hf_smb2_ioctl_network_interface_next_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
/* capabilities */
capabilities = tvb_get_letohl(tvb, offset);
- proto_tree_add_item(sub_tree, hf_smb2_ioctl_network_interface_capabilities, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- proto_tree_add_boolean(sub_tree, hf_smb2_ioctl_network_interface_capability_rdma, tvb, offset, 4, capabilities);
- proto_tree_add_boolean(sub_tree, hf_smb2_ioctl_network_interface_capability_rss, tvb, offset, 4, capabilities);
+ proto_tree_add_bitmask(sub_tree, tvb, offset, hf_smb2_ioctl_network_interface_capabilities, ett_smb2_ioctl_network_interface_capabilities, capability_flags, ENC_LITTLE_ENDIAN);
+
if (capabilities != 0) {
proto_item_append_text(item, "%s%s",
(capabilities & NETWORK_INTERFACE_CAP_RDMA)?", RDMA":"",
(capabilities & NETWORK_INTERFACE_CAP_RSS)?", RSS":"");
- if (sub_item) {
- proto_item_append_text(sub_item, "%s%s",
+ proto_item_append_text(sub_item, "%s%s",
(capabilities & NETWORK_INTERFACE_CAP_RDMA)?", RDMA":"",
(capabilities & NETWORK_INTERFACE_CAP_RSS)?", RSS":"");
- }
}
offset += 4;
unit = "";
}
proto_item_append_text(item, ", %.1f %sBits/s", val, unit);
- if (sub_item) {
- proto_item_append_text(sub_item, ", %.1f %sBits/s", val, unit);
- }
+ proto_item_append_text(sub_item, ", %.1f %sBits/s", val, unit);
offset += 8;
}
static void
-dissect_smb2_FSCTL_GET_SHADOW_COPY_DATA(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, gboolean data_in)
+dissect_smb2_FSCTL_SRV_ENUMERATE_SNAPSHOTS(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, gboolean data_in)
{
guint32 num_volumes;
int len = 0;
int old_offset = offset;
- bc = tvb_length_remaining(tvb, offset);
+ bc = tvb_captured_length_remaining(tvb, offset);
name = get_unicode_or_ascii_string(tvb, &offset,
TRUE, &len, TRUE, FALSE, &bc);
proto_tree_add_string(tree, hf_smb2_ioctl_shadow_copy_label, tvb, old_offset, len, name);
return offset;
}
+
static int
dissect_smb2_FSCTL_SET_COMPRESSION(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, gboolean data_in)
{
return offset;
}
+static int
+dissect_smb2_FSCTL_SET_INTEGRITY_INFORMATION(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, gboolean data_in)
+{
+ const int *integrity_flags[] = {
+ &hf_smb2_integrity_flags_enforcement_off,
+ NULL
+ };
+
+ /* There is no out data */
+ if (!data_in) {
+ return offset;
+ }
+
+ proto_tree_add_item(tree, hf_smb2_checksum_algorithm, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_smb2_integrity_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_bitmask(tree, tvb, offset, hf_smb2_integrity_flags, ett_smb2_integrity_flags, integrity_flags, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ return offset;
+}
+
static int
dissect_smb2_FSCTL_SET_OBJECT_ID(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, gboolean data_in)
{
return offset;
}
+static int
+dissect_smb2_cchunk_RESUME_KEY(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
+{
+
+ proto_tree_add_bytes_format_value(tree, hf_smb2_cchunk_resume_key, tvb,
+ offset, 24, NULL, "Opaque Data");
+ offset += 24;
+
+ return (offset);
+}
+
+static void
+dissect_smb2_FSCTL_SRV_REQUEST_RESUME_KEY(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, gboolean data_in)
+{
+
+ /* There is no in data */
+ if (data_in) {
+ return;
+ }
+
+ offset = dissect_smb2_cchunk_RESUME_KEY(tvb, pinfo, tree, offset);
+
+ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA);
+ offset += 4;
+}
+
+static void
+dissect_smb2_FSCTL_SRV_COPYCHUNK(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, gboolean data_in)
+{
+ proto_tree *sub_tree;
+ proto_item *sub_item;
+ guint32 chunk_count = 0;
+
+ /* Output is simpler - handle that first. */
+ if (!data_in) {
+ proto_tree_add_item(tree, hf_smb2_cchunk_chunks_written, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(tree, hf_smb2_cchunk_bytes_written, tvb, offset+4, 4, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(tree, hf_smb2_cchunk_total_written, tvb, offset+8, 4, ENC_LITTLE_ENDIAN);
+ return;
+ }
+
+ /* Input data, fixed part */
+ offset = dissect_smb2_cchunk_RESUME_KEY(tvb, pinfo, tree, offset);
+ proto_tree_add_item_ret_uint(tree, hf_smb2_cchunk_count, tvb, offset, 4, ENC_LITTLE_ENDIAN, &chunk_count);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA);
+ offset += 4;
+
+ /* Zero or more allocated ranges may be reported. */
+ while (chunk_count && tvb_reported_length_remaining(tvb, offset) >= 24) {
+ sub_tree = proto_tree_add_subtree(tree, tvb, offset, 24, ett_smb2_cchunk_entry, &sub_item, "Chunk");
+
+ proto_tree_add_item(sub_tree, hf_smb2_cchunk_src_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+
+ proto_tree_add_item(sub_tree, hf_smb2_cchunk_dst_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+
+ proto_tree_add_item(sub_tree, hf_smb2_cchunk_xfer_len, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(sub_tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA);
+ offset += 4;
+
+ chunk_count--;
+ }
+}
+
void
-dissect_smb2_ioctl_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *top_tree, guint32 ioctl_function, gboolean data_in)
+dissect_smb2_ioctl_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *top_tree, guint32 ioctl_function, gboolean data_in, void *private_data _U_)
{
guint16 dc;
dissect_get_dfs_referral_data(tvb, pinfo, tree, 0, &dc, TRUE);
}
break;
- case 0x0011c017:
- dissect_smb2_FSCTL_PIPE_TRANSCEIVE(tvb, pinfo, tree, 0, top_tree, data_in);
+ case 0x000940CF: /* FSCTL_QUERY_ALLOCATED_RANGES */
+ dissect_smb2_FSCTL_QUERY_ALLOCATED_RANGES(tvb, pinfo, tree, 0, data_in);
+ break;
+ case 0x00094264: /* FSCTL_OFFLOAD_READ */
+ dissect_smb2_FSCTL_OFFLOAD_READ(tvb, pinfo, tree, 0, data_in);
+ break;
+ case 0x00098268: /* FSCTL_OFFLOAD_WRITE */
+ dissect_smb2_FSCTL_OFFLOAD_WRITE(tvb, pinfo, tree, 0, data_in);
+ break;
+ case 0x0011c017: /* FSCTL_PIPE_TRANSCEIVE */
+ dissect_smb2_FSCTL_PIPE_TRANSCEIVE(tvb, pinfo, tree, 0, top_tree, data_in, private_data);
+ break;
+ case 0x00110018: /* FSCTL_PIPE_WAIT */
+ dissect_smb2_FSCTL_PIPE_WAIT(tvb, pinfo, tree, 0, top_tree, data_in);
+ break;
+ case 0x00140078: /* FSCTL_SRV_REQUEST_RESUME_KEY */
+ dissect_smb2_FSCTL_SRV_REQUEST_RESUME_KEY(tvb, pinfo, tree, 0, data_in);
break;
case 0x001401D4: /* FSCTL_LMR_REQUEST_RESILIENCY */
dissect_smb2_FSCTL_LMR_REQUEST_RESILIENCY(tvb, pinfo, tree, 0, data_in);
case 0x00140204: /* FSCTL_VALIDATE_NEGOTIATE_INFO */
dissect_smb2_FSCTL_VALIDATE_NEGOTIATE_INFO(tvb, pinfo, tree, 0, data_in);
break;
- case 0x00144064: /* FSCTL_GET_SHADOW_COPY_DATA */
- dissect_smb2_FSCTL_GET_SHADOW_COPY_DATA(tvb, pinfo, tree, 0, data_in);
+ case 0x00144064: /* FSCTL_SRV_ENUMERATE_SNAPSHOTS */
+ dissect_smb2_FSCTL_SRV_ENUMERATE_SNAPSHOTS(tvb, pinfo, tree, 0, data_in);
+ break;
+ case 0x001440F2: /* FSCTL_SRV_COPYCHUNK */
+ case 0x001480F2: /* FSCTL_SRV_COPYCHUNK_WRITE */
+ dissect_smb2_FSCTL_SRV_COPYCHUNK(tvb, pinfo, tree, 0, data_in);
break;
case 0x0009009C: /* FSCTL_GET_OBJECT_ID */
case 0x000900c0: /* FSCTL_CREATE_OR_GET_OBJECT_ID */
dissect_smb2_FSCTL_CREATE_OR_GET_OBJECT_ID(tvb, pinfo, tree, 0, data_in);
break;
+ case 0x000900c4: /* FSCTL_SET_SPARSE */
+ dissect_smb2_FSCTL_SET_SPARSE(tvb, pinfo, tree, 0, data_in);
+ break;
case 0x00098098: /* FSCTL_SET_OBJECT_ID */
dissect_smb2_FSCTL_SET_OBJECT_ID(tvb, pinfo, tree, 0, data_in);
break;
case 0x000980BC: /* FSCTL_SET_OBJECT_ID_EXTENDED */
dissect_smb2_FSCTL_SET_OBJECT_ID_EXTENDED(tvb, pinfo, tree, 0, data_in);
break;
+ case 0x000980C8: /* FSCTL_SET_ZERO_DATA */
+ dissect_smb2_FSCTL_SET_ZERO_DATA(tvb, pinfo, tree, 0, data_in);
+ break;
case 0x0009003C: /* FSCTL_GET_COMPRESSION */
dissect_smb2_FSCTL_GET_COMPRESSION(tvb, pinfo, tree, 0, data_in);
break;
+ case 0x00090300: /* FSCTL_QUERY_SHARED_VIRTUAL_DISK_SUPPORT */
+ if (!data_in)
+ dissect_smb2_FSCTL_QUERY_SHARED_VIRTUAL_DISK_SUPPORT(tvb, pinfo, tree, 0, dc);
+ break;
+ case 0x00090304: /* FSCTL_SVHDX_SYNC_TUNNEL or response */
+ call_dissector_with_data(rsvd_handle, tvb, pinfo, top_tree, &data_in);
+ break;
case 0x0009C040: /* FSCTL_SET_COMPRESSION */
dissect_smb2_FSCTL_SET_COMPRESSION(tvb, pinfo, tree, 0, data_in);
break;
+ case 0x00090284: /* FSCTL_QUERY_FILE_REGIONS */
+ dissect_smb2_FSCTL_QUERY_FILE_REGIONS(tvb, pinfo, tree, 0, data_in);
+ break;
+ case 0x0009C280: /* FSCTL_SET_INTEGRITY_INFORMATION request or response */
+ dissect_smb2_FSCTL_SET_INTEGRITY_INFORMATION(tvb, pinfo, tree, 0, data_in);
+ break;
default:
- proto_tree_add_item(tree, hf_smb2_unknown, tvb, 0, tvb_length(tvb), ENC_NA);
+ proto_tree_add_item(tree, hf_smb2_unknown, tvb, 0, tvb_captured_length(tvb), ENC_NA);
}
}
static void
dissect_smb2_ioctl_data_in(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si)
{
- dissect_smb2_ioctl_data(tvb, pinfo, tree, si->top_tree, si->ioctl_function, TRUE);
+ smb2_pipe_set_file_id(pinfo, si);
+ dissect_smb2_ioctl_data(tvb, pinfo, tree, si->top_tree, si->ioctl_function, TRUE, si);
}
static void
dissect_smb2_ioctl_data_out(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si)
{
- dissect_smb2_ioctl_data(tvb, pinfo, tree, si->top_tree, si->ioctl_function, FALSE);
+ smb2_pipe_set_file_id(pinfo, si);
+ dissect_smb2_ioctl_data(tvb, pinfo, tree, si->top_tree, si->ioctl_function, FALSE, si);
}
static int
{
offset_length_buffer_t o_olb;
offset_length_buffer_t i_olb;
+ gboolean continue_dissection;
switch (si->status) {
- case 0x00000000: break;
- default: return dissect_smb2_error_response(tvb, pinfo, tree, offset, si);
- }
-
/* buffer code */
- offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
+ case 0x00000000: offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); break;
+ case 0x80000005: break;
+ default: offset = dissect_smb2_error_response(tvb, pinfo, tree, offset, si, &continue_dissection);
+ if (!continue_dissection) return offset;
+ }
/* some unknown bytes */
proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, 2, ENC_NA);
static int
dissect_smb2_read_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si)
{
+ offset_length_buffer_t c_olb;
+ guint32 channel;
guint32 len;
guint64 off;
offset += 4;
/* channel */
+ channel = tvb_get_letohl(tvb, offset);
proto_tree_add_item(tree, hf_smb2_channel, tvb, offset, 4, ENC_LITTLE_ENDIAN);
offset += 4;
proto_tree_add_item(tree, hf_smb2_remaining_bytes, tvb, offset, 4, ENC_LITTLE_ENDIAN);
offset += 4;
- /* channel info offset */
- proto_tree_add_item(tree, hf_smb2_channel_info_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
+ /* read channel info blob offset/length */
+ offset = dissect_smb2_olb_length_offset(tvb, offset, &c_olb, OLB_O_UINT16_S_UINT16, hf_smb2_channel_info_blob);
- /* channel info length */
- proto_tree_add_item(tree, hf_smb2_channel_info_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
+ /* the read channel info blob itself */
+ switch (channel) {
+ case SMB2_CHANNEL_RDMA_V1:
+ dissect_smb2_olb_buffer(pinfo, tree, tvb, &c_olb, si, dissect_smb2_rdma_v1_blob);
+ break;
+ case SMB2_CHANNEL_NONE:
+ default:
+ dissect_smb2_olb_buffer(pinfo, tree, tvb, &c_olb, si, NULL);
+ break;
+ }
- /* there is a buffer here but it is never used (yet) */
+ offset = dissect_smb2_olb_tvb_max_offset(offset, &c_olb);
/* Store len and offset */
if (si->saved) {
guint16 dataoffset = 0;
guint32 data_tvb_len;
guint32 length;
- switch (si->status) {
- case 0x00000000: break;
- default: return dissect_smb2_error_response(tvb, pinfo, tree, offset, si);
- }
+ gboolean continue_dissection;
+ switch (si->status) {
/* buffer code */
- offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
+ case 0x00000000: offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); break;
+ default: offset = dissect_smb2_error_response(tvb, pinfo, tree, offset, si, &continue_dissection);
+ if (!continue_dissection) return offset;
+ }
/* data offset */
dataoffset=tvb_get_letohl(tvb,offset);
/* reserved */
offset += 4;
- /* data or dcerpc ?
- * If the pidvalid flag is set we assume it is a deferred
- * STATUS_PENDING read and thus a named pipe (==dcerpc)
- */
- if (length && ( (si->tree && si->tree->share_type == SMB2_SHARE_TYPE_PIPE)||(si->flags & SMB2_FLAGS_ASYNC_CMD))) {
- offset = dissect_file_data_dcerpc(tvb, pinfo, tree, offset, length, si->top_tree);
- return offset;
+ /* data or namedpipe ?*/
+ if (length) {
+ int oldoffset = offset;
+ smb2_pipe_set_file_id(pinfo, si);
+ offset = dissect_file_data_smb2_pipe(tvb, pinfo, tree, offset, length, si->top_tree, si);
+ if (offset != oldoffset) {
+ /* managed to dissect pipe data */
+ return offset;
+ }
}
/* data */
proto_tree_add_item(tree, hf_smb2_read_data, tvb, offset, length, ENC_NA);
- data_tvb_len=(guint32)tvb_length_remaining(tvb, offset);
+ data_tvb_len=(guint32)tvb_captured_length_remaining(tvb, offset);
offset += MIN(length,data_tvb_len);
}
static void
-report_create_context_malformed_buffer(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, const char *buffer_desc)
+report_create_context_malformed_buffer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const char *buffer_desc)
{
- proto_tree_add_text(tree, tvb, 0, tvb_length_remaining(tvb, 0),
- "%s SHOULD NOT be generated. Malformed packet", buffer_desc);
+ proto_tree_add_expert_format(tree, pinfo, &ei_smb2_bad_response, tvb, 0, -1,
+ "%s SHOULD NOT be generated", buffer_desc);
}
static void
dissect_smb2_ExtA_buffer_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si)
}
if (item) {
- if (tvb_length(tvb) == 0) {
+ if (tvb_reported_length(tvb) == 0) {
proto_item_append_text(item, ": NO DATA");
} else {
proto_item_append_text(item, ": QFid request should have no data, malformed packet");
dissect_smb2_QFid_buffer_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_)
{
int offset = 0;
- proto_item *item = NULL;
- proto_item *sub_item = NULL;
- proto_item *sub_tree = NULL;
+ proto_item *item;
+ proto_item *sub_tree;
- if (tree) {
- item = proto_tree_get_parent(tree);
- }
+ item = proto_tree_get_parent(tree);
- if (item) {
- proto_item_append_text(item, ": QFid INFO");
- sub_item = proto_tree_add_text(tree, tvb, offset, -1, "QFid INFO");
- sub_tree = proto_item_add_subtree(sub_item, ett_smb2_QFid_buffer);
- }
+ proto_item_append_text(item, ": QFid INFO");
+ sub_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_smb2_QFid_buffer, NULL, "QFid INFO");
proto_tree_add_item(sub_tree, hf_smb2_qfid_fid, tvb, offset, 32, ENC_NA);
}
NULL
};
int offset = 0;
- proto_item *item = NULL;
- proto_item *sub_item = NULL;
- proto_item *sub_tree = NULL;
+ proto_item *item;
+ proto_item *sub_tree;
- if (tree) {
- item = proto_tree_get_parent(tree);
- }
+ item = proto_tree_get_parent(tree);
- if (item) {
- proto_item_append_text(item, ": DH2Q Request");
- sub_item = proto_tree_add_text(tree, tvb, offset, -1, "DH2Q Request");
- sub_tree = proto_item_add_subtree(sub_item, ett_smb2_DH2Q_buffer);
- }
+ proto_item_append_text(item, ": DH2Q Request");
+ sub_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_smb2_DH2Q_buffer, NULL, "DH2Q Request");
/* timeout */
proto_tree_add_item(sub_tree, hf_smb2_dh2x_buffer_timeout, tvb, offset, 4, ENC_LITTLE_ENDIAN);
dissect_smb2_DH2Q_buffer_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_)
{
int offset = 0;
- proto_item *item = NULL;
- proto_item *sub_item = NULL;
- proto_item *sub_tree = NULL;
+ proto_item *item;
+ proto_item *sub_tree;
- if (tree) {
- item = proto_tree_get_parent(tree);
- }
+ item = proto_tree_get_parent(tree);
- if (item) {
- proto_item_append_text(item, ": DH2Q Response");
- sub_item = proto_tree_add_text(tree, tvb, offset, -1, "DH2Q Response");
- sub_tree = proto_item_add_subtree(sub_item, ett_smb2_DH2Q_buffer);
- }
+ proto_item_append_text(item, ": DH2Q Response");
+ sub_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_smb2_DH2Q_buffer, NULL, "DH2Q Response");
/* timeout */
proto_tree_add_item(sub_tree, hf_smb2_dh2x_buffer_timeout, tvb, offset, 4, ENC_LITTLE_ENDIAN);
dissect_smb2_DH2C_buffer_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si)
{
int offset = 0;
- proto_item *item = NULL;
- proto_item *sub_item = NULL;
- proto_item *sub_tree = NULL;
+ proto_item *item;
+ proto_item *sub_tree;
- if (tree) {
- item = proto_tree_get_parent(tree);
- }
+ item = proto_tree_get_parent(tree);
- if (item) {
- proto_item_append_text(item, ": DH2C Request");
- sub_item = proto_tree_add_text(tree, tvb, offset, -1, "DH2C Request");
- sub_tree = proto_item_add_subtree(sub_item, ett_smb2_DH2C_buffer);
- }
+ proto_item_append_text(item, ": DH2C Request");
+ sub_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_smb2_DH2C_buffer, NULL, "DH2C Request");
/* file id */
dissect_smb2_fid(tvb, pinfo, sub_tree, offset, si, FID_MODE_DHNC);
item = proto_tree_get_parent(tree);
}
- if (tvb_length(tvb) == 0) {
+ if (tvb_reported_length(tvb) == 0) {
if (item) {
proto_item_append_text(item, ": NO DATA");
}
dissect_smb2_MxAc_buffer_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_)
{
int offset = 0;
- proto_item *item = NULL;
- proto_item *sub_item = NULL;
- proto_tree *sub_tree = NULL;
+ proto_item *item;
+ proto_tree *sub_tree;
- if (tree) {
- item = proto_tree_get_parent(tree);
- }
+ item = proto_tree_get_parent(tree);
- if (tvb_length(tvb) == 0) {
- if (item) {
- proto_item_append_text(item, ": NO DATA");
- }
+ if (tvb_reported_length(tvb) == 0) {
+ proto_item_append_text(item, ": NO DATA");
return;
}
- if (item) {
- proto_item_append_text(item, ": MxAc INFO");
- sub_item = proto_tree_add_text(tree, tvb, offset, -1, "MxAc INFO");
- sub_tree = proto_item_add_subtree(sub_item, ett_smb2_MxAc_buffer);
- }
+ proto_item_append_text(item, ": MxAc INFO");
+ sub_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_smb2_MxAc_buffer, NULL, "MxAc INFO");
proto_tree_add_item(sub_tree, hf_smb2_mxac_status, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
* 4 - lease state
* 4 - lease flags
* 8 - lease duration
- * 16 - pareant lease key
- * 4 - epoch
+ * 16 - parent lease key
+ * 2 - epoch
+ * 2 - reserved
*/
#define SMB2_LEASE_STATE_READ_CACHING 0x00000001
#define SMB2_LEASE_STATE_HANDLE_CACHING 0x00000002
{
int offset = 0;
int len;
- proto_item *sub_item = NULL;
proto_tree *sub_tree = NULL;
- proto_item *parent_item = NULL;
+ proto_item *parent_item;
- if (parent_tree) {
- parent_item = proto_tree_get_parent(parent_tree);
+ parent_item = proto_tree_get_parent(parent_tree);
+
+ len = tvb_reported_length(tvb);
+
+ switch (len) {
+ case 32: /* SMB2_CREATE_REQUEST/RESPONSE_LEASE */
+ proto_item_append_text(parent_item, ": LEASE_V1");
+ sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1, ett_smb2_RqLs_buffer, NULL, "LEASE_V1");
+ break;
+ case 52: /* SMB2_CREATE_REQUEST/RESPONSE_LEASE_V2 */
+ proto_item_append_text(parent_item, ": LEASE_V2");
+ sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1, ett_smb2_RqLs_buffer, NULL, "LEASE_V2");
+ break;
+ default:
+ report_create_context_malformed_buffer(tvb, pinfo, parent_tree, "RqLs");
+ break;
}
- len = tvb_length(tvb);
+ proto_tree_add_item(sub_tree, hf_smb2_lease_key, tvb, offset, 16, ENC_LITTLE_ENDIAN);
+ offset += 16;
+
+ proto_tree_add_bitmask(sub_tree, tvb, offset, hf_smb2_lease_state,
+ ett_smb2_lease_state, lease_state_fields, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_bitmask(sub_tree, tvb, offset, hf_smb2_lease_flags,
+ ett_smb2_lease_flags, lease_flags_fields, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(sub_tree, hf_smb2_lease_duration, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+
+ if (len < 52) {
+ return;
+ }
+
+ proto_tree_add_item(sub_tree, hf_smb2_parent_lease_key, tvb, offset, 16, ENC_LITTLE_ENDIAN);
+ offset += 16;
+
+ proto_tree_add_item(sub_tree, hf_smb2_lease_epoch, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(sub_tree, hf_smb2_lease_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+}
+
+static void
+dissect_smb2_RqLs_buffer_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_)
+{
+ dissect_SMB2_CREATE_LEASE_VX(tvb, pinfo, tree, si);
+}
+
+static void
+dissect_smb2_RqLs_buffer_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_)
+{
+ dissect_SMB2_CREATE_LEASE_VX(tvb, pinfo, tree, si);
+}
+
+/*
+ * SMB2_CREATE_APP_INSTANCE_ID
+ * 2 - structure size - 20
+ * 2 - reserved
+ * 16 - application guid
+ */
+
+static void
+dissect_smb2_APP_INSTANCE_buffer_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_)
+{
+ int offset = 0;
+ proto_item *item;
+ proto_item *sub_tree;
+
+ item = proto_tree_get_parent(tree);
+
+ proto_item_append_text(item, ": CREATE APP INSTANCE ID");
+ sub_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_smb2_APP_INSTANCE_buffer, NULL, "APP INSTANCE ID");
+
+ /* struct size */
+ proto_tree_add_item(sub_tree, hf_smb2_APP_INSTANCE_buffer_struct_size,
+ tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ /* reserved */
+ proto_tree_add_item(sub_tree, hf_smb2_APP_INSTANCE_buffer_reserved,
+ tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ /* create guid */
+ proto_tree_add_item(sub_tree, hf_smb2_APP_INSTANCE_buffer_app_guid, tvb, offset, 16, ENC_LITTLE_ENDIAN);
+}
+
+static void
+dissect_smb2_APP_INSTANCE_buffer_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_)
+{
+ report_create_context_malformed_buffer(tvb, pinfo, tree, "APP INSTANCE Response");
+}
+
+/*
+ * Dissect the MS-RSVD stuff that turns up when HyperV uses SMB3.x
+ */
+static void
+dissect_smb2_svhdx_open_device_context_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_)
+{
+ int offset = 0;
+ proto_item *item;
+ proto_item *sub_tree;
+
+ item = proto_tree_get_parent(tree);
+
+ proto_item_append_text(item, ": SVHDX OPEN DEVICE CONTEXT");
+ sub_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_smb2_svhdx_open_device_context, NULL, "SVHDX OPEN DEVICE CONTEXT");
+
+ /* Version */
+ proto_tree_add_item(sub_tree, hf_smb2_svhdx_open_device_context_version,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ /* HasInitiatorId */
+ proto_tree_add_item(sub_tree, hf_smb2_svhdx_open_device_context_has_initiator_id,
+ tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
+
+ /* Reserved */
+ proto_tree_add_item(sub_tree, hf_smb2_svhdx_open_device_context_reserved,
+ tvb, offset, 3, ENC_NA);
+ offset += 3;
+
+ /* InitiatorId */
+ proto_tree_add_item(sub_tree, hf_smb2_svhdx_open_device_context_initiator_id,
+ tvb, offset, 16, ENC_NA);
+ offset += 16;
+
+ /* Flags TODO: Dissect these*/
+ proto_tree_add_item(sub_tree, hf_smb2_svhdx_open_device_context_flags,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ /* OriginatorFlags */
+ proto_tree_add_item(sub_tree, hf_smb2_svhdx_open_device_context_originator_flags,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ /* OpenRequestId */
+ proto_tree_add_item(sub_tree, hf_smb2_svhdx_open_device_context_open_request_id,
+ tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+
+ /* InitiatorHostNameLength */
+ proto_tree_add_item(sub_tree, hf_smb2_svhdx_open_device_context_initiator_host_name_len,
+ tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
+
+ /* InitiatorHostName */
+ proto_tree_add_item(sub_tree, hf_smb2_svhdx_open_device_context_initiator_host_name,
+ tvb, offset, 126, ENC_ASCII | ENC_NA);
+}
+
+static void
+dissect_smb2_svhdx_open_device_context_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_)
+{
+ report_create_context_malformed_buffer(tvb, pinfo, tree, "SHVXD OPEN DEVICE CONTEXT Response");
+}
+
+static const int *posix_flags_fields[] = {
+ &hf_smb2_posix_v1_case_sensitive,
+ &hf_smb2_posix_v1_posix_lock,
+ &hf_smb2_posix_v1_posix_file_semantics,
+ &hf_smb2_posix_v1_posix_utf8_paths,
+ &hf_smb2_posix_v1_posix_will_convert_nt_acls,
+ &hf_smb2_posix_v1_posix_fileinfo,
+ &hf_smb2_posix_v1_posix_acls,
+ &hf_smb2_posix_v1_rich_acls,
+ NULL
+};
+
+static void
+dissect_smb2_posix_v1_caps_request(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_)
+{
+ int offset = 0;
+ proto_item *item;
+ proto_item *sub_tree;
+
+ item = proto_tree_get_parent(tree);
+
+ proto_item_append_text(item, ": POSIX V1 CAPS request");
+ sub_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_smb2_posix_v1_request, NULL, "POSIX_V1_REQUEST");
+
+ /* Version */
+ proto_tree_add_item(sub_tree, hf_smb2_posix_v1_version,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ /* Request */
+ proto_tree_add_item(sub_tree, hf_smb2_posix_v1_request,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+}
+
+static void
+dissect_smb2_posix_v1_caps_response(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_)
+{
+ int offset = 0;
+ proto_item *item;
+ proto_item *sub_tree;
+
+ item = proto_tree_get_parent(tree);
+
+ proto_item_append_text(item, ": POSIX V1 CAPS response");
+ sub_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_smb2_posix_v1_response, NULL, "POSIX_V1_RESPONSE");
+
+ /* Version */
+ proto_tree_add_item(sub_tree, hf_smb2_posix_v1_version,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ /* Supported Features */
+ proto_tree_add_bitmask(sub_tree, tvb, offset,
+ hf_smb2_posix_v1_supported_features,
+ ett_smb2_posix_v1_supported_features,
+ posix_flags_fields, ENC_LITTLE_ENDIAN);
+
+}
+
+#define SMB2_AAPL_SERVER_QUERY 1
+#define SMB2_AAPL_RESOLVE_ID 2
+
+static const value_string aapl_command_code_vals[] = {
+ { SMB2_AAPL_SERVER_QUERY, "Server query"},
+ { SMB2_AAPL_RESOLVE_ID, "Resolve ID"},
+ { 0, NULL }
+};
+
+#define SMB2_AAPL_SERVER_CAPS 0x00000001
+#define SMB2_AAPL_VOLUME_CAPS 0x00000002
+#define SMB2_AAPL_MODEL_INFO 0x00000004
+
+static const int *aapl_server_query_bitmap_fields[] = {
+ &hf_smb2_aapl_server_query_bitmask_server_caps,
+ &hf_smb2_aapl_server_query_bitmask_volume_caps,
+ &hf_smb2_aapl_server_query_bitmask_model_info,
+ NULL
+};
+
+#define SMB2_AAPL_SUPPORTS_READ_DIR_ATTR 0x00000001
+#define SMB2_AAPL_SUPPORTS_OSX_COPYFILE 0x00000002
+#define SMB2_AAPL_UNIX_BASED 0x00000004
+#define SMB2_AAPL_SUPPORTS_NFS_ACE 0x00000008
- switch (len) {
- case 32: /* SMB2_CREATE_REQUEST/RESPONSE_LEASE */
- if (parent_item) {
- proto_item_append_text(parent_item, ": LEASE_V1");
- sub_item = proto_tree_add_text(parent_tree, tvb, offset, len, "LEASE_V1");
- sub_tree = proto_item_add_subtree(sub_item, ett_smb2_RqLs_buffer);
- }
+static const int *aapl_server_query_caps_fields[] = {
+ &hf_smb2_aapl_server_query_caps_supports_read_dir_attr,
+ &hf_smb2_aapl_server_query_caps_supports_osx_copyfile,
+ &hf_smb2_aapl_server_query_caps_unix_based,
+ &hf_smb2_aapl_server_query_caps_supports_nfs_ace,
+ NULL
+};
- break;
- case 52: /* SMB2_CREATE_REQUEST/RESPONSE_LEASE_V2 */
- if (parent_item) {
- proto_item_append_text(parent_item, ": LEASE_V2");
- sub_item = proto_tree_add_text(parent_tree, tvb, offset, len, "LEASE_V2");
- sub_tree = proto_item_add_subtree(sub_item, ett_smb2_RqLs_buffer);
- }
+static void
+dissect_smb2_AAPL_buffer_request(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, smb2_info_t *si _U_)
+{
+ int offset = 0;
+ proto_item *item;
+ proto_item *sub_tree;
+ guint32 command_code;
- break;
- default:
- report_create_context_malformed_buffer(tvb, pinfo, parent_tree, "RqLs");
- break;
- }
+ item = proto_tree_get_parent(tree);
- proto_tree_add_item(sub_tree, hf_smb2_lease_key, tvb, offset, 16, ENC_LITTLE_ENDIAN);
- offset += 16;
+ proto_item_append_text(item, ": AAPL Create Context request");
+ sub_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_smb2_aapl_create_context_request, NULL, "AAPL Create Context request");
- proto_tree_add_bitmask(sub_tree, tvb, offset, hf_smb2_lease_state,
- ett_smb2_lease_state, lease_state_fields, ENC_LITTLE_ENDIAN);
+ /* Command code */
+ proto_tree_add_item_ret_uint(sub_tree, hf_smb2_aapl_command_code,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN, &command_code);
offset += 4;
- proto_tree_add_bitmask(sub_tree, tvb, offset, hf_smb2_lease_flags,
- ett_smb2_lease_flags, lease_flags_fields, ENC_LITTLE_ENDIAN);
+ /* Reserved */
+ proto_tree_add_item(sub_tree, hf_smb2_aapl_reserved,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
offset += 4;
- proto_tree_add_item(sub_tree, hf_smb2_lease_duration, tvb, offset, 8, ENC_LITTLE_ENDIAN);
- offset += 8;
+ switch (command_code) {
- if (len < 52) {
- return;
- }
+ case SMB2_AAPL_SERVER_QUERY:
+ /* Request bitmap */
+ proto_tree_add_bitmask(sub_tree, tvb, offset,
+ hf_smb2_aapl_server_query_bitmask,
+ ett_smb2_aapl_server_query_bitmask,
+ aapl_server_query_bitmap_fields,
+ ENC_LITTLE_ENDIAN);
+ offset += 8;
- proto_tree_add_item(sub_tree, hf_smb2_parent_lease_key, tvb, offset, 16, ENC_LITTLE_ENDIAN);
- offset += 16;
+ /* Client capabilities */
+ proto_tree_add_bitmask(sub_tree, tvb, offset,
+ hf_smb2_aapl_server_query_caps,
+ ett_smb2_aapl_server_query_caps,
+ aapl_server_query_caps_fields,
+ ENC_LITTLE_ENDIAN);
+ break;
- proto_tree_add_item(sub_tree, hf_smb2_lease_epoch, tvb, offset, 4, ENC_LITTLE_ENDIAN);
-}
+ case SMB2_AAPL_RESOLVE_ID:
+ /* file ID */
+ proto_tree_add_item(sub_tree, hf_smb2_file_id, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ break;
-static void
-dissect_smb2_RqLs_buffer_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_)
-{
- dissect_SMB2_CREATE_LEASE_VX(tvb, pinfo, tree, si);
+ default:
+ break;
+ }
}
-static void
-dissect_smb2_RqLs_buffer_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_)
-{
- dissect_SMB2_CREATE_LEASE_VX(tvb, pinfo, tree, si);
-}
+#define SMB2_AAPL_SUPPORTS_RESOLVE_ID 0x00000001
+#define SMB2_AAPL_CASE_SENSITIVE 0x00000002
+#define SMB2_AAPL_SUPPORTS_FULL_SYNC 0x00000004
-/*
- * SMB2_CREATE_APP_INSTANCE_ID
- * 2 - structure size - 20
- * 2 - reserved
- * 16 - application guid
- */
+static const int *aapl_server_query_volume_caps_fields[] = {
+ &hf_smb2_aapl_server_query_volume_caps_support_resolve_id,
+ &hf_smb2_aapl_server_query_volume_caps_case_sensitive,
+ &hf_smb2_aapl_server_query_volume_caps_supports_full_sync,
+ NULL
+};
static void
-dissect_smb2_APP_INSTANCE_buffer_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_)
+dissect_smb2_AAPL_buffer_response(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, smb2_info_t *si _U_)
{
int offset = 0;
- proto_item *item = NULL;
- proto_item *sub_item = NULL;
- proto_item *sub_tree = NULL;
+ proto_item *item;
+ proto_item *sub_tree;
+ guint32 command_code;
+ guint64 server_query_bitmask;
- if (tree) {
- item = proto_tree_get_parent(tree);
- }
+ item = proto_tree_get_parent(tree);
- if (item) {
- proto_item_append_text(item, ": APP INSTANCE ID");
- sub_item = proto_tree_add_text(tree, tvb, offset, -1, "APP INSTANCE ID");
- sub_tree = proto_item_add_subtree(sub_item, ett_smb2_APP_INSTANCE_buffer);
- }
+ proto_item_append_text(item, ": AAPL Create Context response");
+ sub_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_smb2_aapl_create_context_response, NULL, "AAPL Create Context response");
- /* struct size */
- proto_tree_add_item(sub_tree, hf_smb2_APP_INSTANCE_buffer_struct_size,
- tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
+ /* Command code */
+ proto_tree_add_item_ret_uint(sub_tree, hf_smb2_aapl_command_code,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN, &command_code);
+ offset += 4;
- /* reserved */
- proto_tree_add_item(sub_tree, hf_smb2_APP_INSTANCE_buffer_reserved,
- tvb, offset, 2, ENC_LITTLE_ENDIAN);
- offset += 2;
+ /* Reserved */
+ proto_tree_add_item(sub_tree, hf_smb2_aapl_reserved,
+ tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
- /* create guid */
- proto_tree_add_item(sub_tree, hf_smb2_APP_INSTANCE_buffer_app_guid, tvb, offset, 16, ENC_LITTLE_ENDIAN);
-}
+ switch (command_code) {
-static void
-dissect_smb2_APP_INSTANCE_buffer_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_)
-{
- report_create_context_malformed_buffer(tvb, pinfo, tree, "APP INSTANCE Response");
+ case SMB2_AAPL_SERVER_QUERY:
+ /* Reply bitmap */
+ proto_tree_add_bitmask_ret_uint64(sub_tree, tvb, offset,
+ hf_smb2_aapl_server_query_bitmask,
+ ett_smb2_aapl_server_query_bitmask,
+ aapl_server_query_bitmap_fields,
+ ENC_LITTLE_ENDIAN,
+ &server_query_bitmask);
+ offset += 8;
+
+ if (server_query_bitmask & SMB2_AAPL_SERVER_CAPS) {
+ /* Server capabilities */
+ proto_tree_add_bitmask(sub_tree, tvb, offset,
+ hf_smb2_aapl_server_query_caps,
+ ett_smb2_aapl_server_query_caps,
+ aapl_server_query_caps_fields,
+ ENC_LITTLE_ENDIAN);
+ offset += 8;
+ }
+ if (server_query_bitmask & SMB2_AAPL_VOLUME_CAPS) {
+ /* Volume capabilities */
+ proto_tree_add_bitmask(sub_tree, tvb, offset,
+ hf_smb2_aapl_server_query_volume_caps,
+ ett_smb2_aapl_server_query_volume_caps,
+ aapl_server_query_volume_caps_fields,
+ ENC_LITTLE_ENDIAN);
+ offset += 8;
+ }
+ if (server_query_bitmask & SMB2_AAPL_MODEL_INFO) {
+ /* Padding */
+ offset += 4;
+
+ /* Model string */
+ proto_tree_add_item(sub_tree, hf_smb2_aapl_server_query_model_string,
+ tvb, offset, 4,
+ ENC_UTF_16|ENC_LITTLE_ENDIAN);
+ }
+ break;
+
+ case SMB2_AAPL_RESOLVE_ID:
+ /* NT status */
+ proto_tree_add_item(sub_tree, hf_smb2_nt_status, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ /* Server path */
+ proto_tree_add_item(sub_tree, hf_smb2_aapl_server_query_server_path,
+ tvb, offset, 4,
+ ENC_UTF_16|ENC_LITTLE_ENDIAN);
+ break;
+
+ default:
+ break;
+ }
}
typedef void (*create_context_data_dissector_t)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si);
{ "RqLs", "SMB2_CREATE_REQUEST_LEASE",
{ dissect_smb2_RqLs_buffer_request, dissect_smb2_RqLs_buffer_response } },
{ "744D142E-46FA-0890-4AF7-A7EF6AA6BC45", "SMB2_CREATE_APP_INSTANCE_ID",
- { dissect_smb2_APP_INSTANCE_buffer_request,
- dissect_smb2_APP_INSTANCE_buffer_response } }
+ { dissect_smb2_APP_INSTANCE_buffer_request, dissect_smb2_APP_INSTANCE_buffer_response } },
+ { "6aa6bc45-a7ef-4af7-9008-fa462e144d74", "SMB2_CREATE_APP_INSTANCE_ID",
+ { dissect_smb2_APP_INSTANCE_buffer_request, dissect_smb2_APP_INSTANCE_buffer_response } },
+ { "9ecfcb9c-c104-43e6-980e-158da1f6ec83", "SVHDX_OPEN_DEVICE_CONTEXT",
+ { dissect_smb2_svhdx_open_device_context_request, dissect_smb2_svhdx_open_device_context_response} },
+ { "34263501-2921-4912-2586-447794114531", "SMB2_POSIX_V1_CAPS",
+ { dissect_smb2_posix_v1_caps_request, dissect_smb2_posix_v1_caps_response } },
+ { "AAPL", "SMB2_AAPL_CREATE_CONTEXT",
+ { dissect_smb2_AAPL_buffer_request, dissect_smb2_AAPL_buffer_response } },
};
static struct create_context_data_tag_dissectors*
};
size_t i;
+
for (i = 0; i<array_length(create_context_dissectors_array); i++) {
if (!strcmp(tag, create_context_dissectors_array[i].tag))
return &create_context_dissectors_array[i];
guint16 chain_offset;
int offset = 0;
int len = -1;
- proto_item *sub_item = NULL;
- proto_tree *sub_tree = NULL;
+ proto_item *sub_item;
+ proto_tree *sub_tree;
proto_item *parent_item = NULL;
create_context_data_dissectors_t *dissectors = NULL;
create_context_data_dissector_t dissector = NULL;
len = chain_offset;
}
- if (parent_tree) {
- sub_item = proto_tree_add_text(parent_tree, tvb, offset, len, "Chain Element");
- sub_tree = proto_item_add_subtree(sub_item, ett_smb2_create_chain_element);
- parent_item = proto_tree_get_parent(parent_tree);
- }
+ sub_tree = proto_tree_add_subtree(parent_tree, tvb, offset, len, ett_smb2_create_chain_element, &sub_item, "Chain Element");
+ parent_item = proto_tree_get_parent(parent_tree);
/* chain offset */
proto_tree_add_item(sub_tree, hf_smb2_create_chain_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
/* data offset/length */
dissect_smb2_olb_length_offset(tvb, offset, &data_olb, OLB_O_UINT16_S_UINT32, hf_smb2_create_chain_data);
- /* tag string */
- tag = dissect_smb2_olb_string(pinfo, sub_tree, tvb, &tag_olb, OLB_TYPE_ASCII_STRING);
+ /*
+ * These things are all either 4-char strings, like DH2C, or GUIDs,
+ * however, at least one of them appears to be a GUID as a string and
+ * one appears to be a binary guid. So, check if the the length is
+ * 16, and if so, pull the GUID and convert it to a string. Otherwise
+ * call dissect_smb2_olb_string.
+ */
+ if (tag_olb.len == 16) {
+ e_guid_t tag_guid;
+ proto_item *tag_item;
+ proto_tree *tag_tree;
+
+ tvb_get_letohguid(tvb, tag_olb.off, &tag_guid);
+ tag = guid_to_str(wmem_packet_scope(), &tag_guid);
+
+ tag_item = proto_tree_add_string(sub_tree, tag_olb.hfindex, tvb, tag_olb.off, tag_olb.len, tag);
+ tag_tree = proto_item_add_subtree(tag_item, ett_smb2_olb);
+ proto_tree_add_item(tag_tree, hf_smb2_olb_offset, tvb, tag_olb.off_offset, 2, ENC_LITTLE_ENDIAN);
+ proto_tree_add_item(tag_tree, hf_smb2_olb_length, tvb, tag_olb.len_offset, 2, ENC_LITTLE_ENDIAN);
+
+ } else {
+ /* tag string */
+ tag = dissect_smb2_olb_string(pinfo, sub_tree, tvb, &tag_olb, OLB_TYPE_ASCII_STRING);
+ }
tag_dissectors = get_create_context_data_tag_dissectors(tag);
- proto_item_append_text(parent_item, " %s", tag);
+ proto_item_append_text(parent_item, " %s", tag_dissectors->val);
proto_item_append_text(sub_item, ": %s \"%s\"", tag_dissectors->val, tag);
/* data */
&hf_smb2_create_rep_flags_reparse_point,
NULL
};
+ gboolean continue_dissection;
switch (si->status) {
- case 0x00000000: break;
- default: return dissect_smb2_error_response(tvb, pinfo, tree, offset, si);
- }
-
/* buffer code */
- offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
+ case 0x00000000: offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); break;
+ default: offset = dissect_smb2_error_response(tvb, pinfo, tree, offset, si, &continue_dissection);
+ if (!continue_dissection) return offset;
+ }
/* oplock */
offset = dissect_smb2_oplock(tree, tvb, offset);
offset = dissect_smb2_olb_tvb_max_offset(offset, &e_olb);
- /* free si->saved->extra_info we dont need it any more */
+ /* free si->saved->extra_info we don't need it any more */
if (si->saved && si->saved->extra_info_type == SMB2_EI_FILENAME) {
g_free(si->saved->extra_info);
si->saved->extra_info = NULL;
static int
dissect_smb2_setinfo_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si)
{
+ gboolean continue_dissection;
/* class/infolevel */
dissect_smb2_class_infolevel(pinfo, tvb, offset, tree, si);
switch (si->status) {
- case 0x00000000: break;
- default: return dissect_smb2_error_response(tvb, pinfo, tree, offset, si);
- }
-
/* buffer code */
- offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
+ case 0x00000000: offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); break;
+ default: offset = dissect_smb2_error_response(tvb, pinfo, tree, offset, si, &continue_dissection);
+ if (!continue_dissection) return offset;
+ }
return offset;
}
dissect_smb2_break_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si)
{
guint16 buffer_code;
-
- switch (si->status) {
- case 0x00000000: break;
- default: return dissect_smb2_error_response(tvb, pinfo, tree, offset, si);
- }
+ gboolean continue_dissection;
/* buffer code */
buffer_code = tvb_get_letohs(tvb, offset);
- offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
+ switch (si->status) {
+ case 0x00000000: offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); break;
+ default: offset = dissect_smb2_error_response(tvb, pinfo, tree, offset, si, &continue_dissection);
+ if (!continue_dissection) return offset;
+ }
if (buffer_code == 24) {
/* OPLOCK Break Notification */
/* Lease Break Notification */
- /* reserved */
- proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 2, ENC_NA);
- offset +=2;
+ /* new lease epoch */
+ proto_tree_add_item(tree, hf_smb2_lease_epoch, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ offset += 2;
/* lease flags */
proto_tree_add_bitmask(tree, tvb, offset, hf_smb2_lease_flags,
sesid_offset = offset;
sti->sesid = tvb_get_letoh64(tvb, offset);
sesid_item = proto_tree_add_item(tree, hf_smb2_sesid, tvb, offset, 8, ENC_LITTLE_ENDIAN);
- if (tree) {
- sesid_tree = proto_item_add_subtree(sesid_item, ett_smb2_sesid_tree);
- }
+ sesid_tree = proto_item_add_subtree(sesid_item, ett_smb2_sesid_tree);
offset += 8;
/* now we need to first lookup the uid session */
memcpy(&A_1[1], sti->nonce, 15 - 4);
- plain_data = (guint8 *)tvb_memdup(NULL, tvb, offset, sti->size);
+ plain_data = (guint8 *)tvb_memdup(pinfo->pool, tvb, offset, sti->size);
/* Open the cipher. */
if (gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0)) {
- g_free(plain_data);
+ wmem_free(pinfo->pool, plain_data);
plain_data = NULL;
goto done_decryption;
}
/* Set the key and initial value. */
if (gcry_cipher_setkey(cipher_hd, decryption_key, 16)) {
gcry_cipher_close(cipher_hd);
- g_free(plain_data);
+ wmem_free(pinfo->pool, plain_data);
plain_data = NULL;
goto done_decryption;
}
if (gcry_cipher_setctr(cipher_hd, A_1, 16)) {
gcry_cipher_close(cipher_hd);
- g_free(plain_data);
+ wmem_free(pinfo->pool, plain_data);
plain_data = NULL;
goto done_decryption;
}
if (gcry_cipher_encrypt(cipher_hd, plain_data, sti->size, NULL, 0)) {
gcry_cipher_close(cipher_hd);
- g_free(plain_data);
+ wmem_free(pinfo->pool, plain_data);
plain_data = NULL;
goto done_decryption;
}
}
done_decryption:
#endif
- *enc_tvb = tvb_new_subset(tvb, offset, sti->size, sti->size);
+ *enc_tvb = tvb_new_subset_length(tvb, offset, sti->size);
if (plain_data != NULL) {
*plain_tvb = tvb_new_child_real_data(*enc_tvb, plain_data, sti->size, sti->size);
- tvb_set_free_cb(*plain_tvb, g_free);
add_new_data_source(pinfo, *plain_tvb, "Decrypted SMB3");
}
proto_tree *cmd_tree;
int old_offset = offset;
- cmd_item = proto_tree_add_text(tree, tvb, offset, -1,
- "%s %s (0x%02x)",
+ cmd_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
+ ett_smb2_command, &cmd_item, "%s %s (0x%02x)",
decode_smb2_name(si->opcode),
(si->flags & SMB2_FLAGS_RESPONSE)?"Response":"Request",
si->opcode);
- cmd_tree = proto_item_add_subtree(cmd_item, ett_smb2_command);
-
cmd_dissector = (si->flags & SMB2_FLAGS_RESPONSE)?
smb2_dissector[si->opcode&0xff].response:
offset = (*cmd_dissector)(tvb, pinfo, cmd_tree, offset, si);
} else {
proto_tree_add_item(cmd_tree, hf_smb2_unknown, tvb, offset, -1, ENC_NA);
- offset = tvb_length(tvb);
+ offset = tvb_captured_length(tvb);
}
proto_item_set_len(cmd_item, offset-old_offset);
tid_offset = offset;
si->tid = tvb_get_letohl(tvb, offset);
tid_item = proto_tree_add_item(tree, hf_smb2_tid, tvb, offset, 4, ENC_LITTLE_ENDIAN);
- if (tree) {
- tid_tree = proto_item_add_subtree(tid_item, ett_smb2_tid_tree);
- }
+ tid_tree = proto_item_add_subtree(tid_item, ett_smb2_tid_tree);
offset += 4;
}
sesid_offset = offset;
si->sesid = tvb_get_letoh64(tvb, offset);
sesid_item = proto_tree_add_item(tree, hf_smb2_sesid, tvb, offset, 8, ENC_LITTLE_ENDIAN);
- if (tree) {
- sesid_tree = proto_item_add_subtree(sesid_item, ett_smb2_sesid_tree);
- }
+ sesid_tree = proto_item_add_subtree(sesid_item, ett_smb2_sesid_tree);
offset += 8;
/* now we need to first lookup the uid session */
* a tree connect, we create a dummy sessison, so we can hang the
* tree data on it
*/
- si->session = wmem_new(wmem_file_scope(), smb2_sesid_info_t);
- si->session->sesid = si->sesid;
- si->session->acct_name = NULL;
- si->session->domain_name = NULL;
- si->session->host_name = NULL;
- si->session->auth_frame = (guint32)-1;
- si->session->tids = g_hash_table_new(smb2_tid_info_hash, smb2_tid_info_equal);
+ si->session = wmem_new0(wmem_file_scope(), smb2_sesid_info_t);
+ si->session->sesid = si->sesid;
+ si->session->auth_frame = (guint32)-1;
+ si->session->tids = g_hash_table_new(smb2_tid_info_hash, smb2_tid_info_equal);
g_hash_table_insert(si->conv->sesids, si->session, si->session);
return offset;
proto_tree *tree = NULL;
proto_item *header_item = NULL;
proto_tree *header_tree = NULL;
- proto_item *flags_item = NULL;
- proto_tree *flags_tree = NULL;
int offset = 0;
int chain_offset = 0;
const char *label = smb_header_label;
e_ctx_hnd *policy_hnd_hashtablekey;
sti = wmem_new(wmem_packet_scope(), smb2_transform_info_t);
- si = wmem_new(wmem_packet_scope(), smb2_info_t);
- si->eo_file_info = NULL;
- si->conv = NULL;
- si->saved = NULL;
- si->tree = NULL;
- si->top_tree = parent_tree;
+ si = wmem_new0(wmem_packet_scope(), smb2_info_t);
+ si->top_tree = parent_tree;
if (tvb_get_guint8(tvb, 0) == 0xfd) {
smb2_transform_header = TRUE;
smb2_saved_info_equal_unmatched);
si->conv->sesids = g_hash_table_new(smb2_sesid_info_hash,
smb2_sesid_info_equal);
+ si->conv->fids = g_hash_table_new(smb2_fid_info_hash,
+ smb2_fid_info_equal);
si->conv->files = g_hash_table_new(smb2_eo_files_hash,smb2_eo_files_equal);
/* Bit of a hack to avoid leaking the hash tables - register a
col_append_str(pinfo->cinfo, COL_INFO, ";");
}
- if (parent_tree) {
- item = proto_tree_add_item(parent_tree, proto_smb2, tvb, offset,
- -1, ENC_NA);
- tree = proto_item_add_subtree(item, ett_smb2);
- }
+ item = proto_tree_add_item(parent_tree, proto_smb2, tvb, offset, -1, ENC_NA);
+ tree = proto_item_add_subtree(item, ett_smb2);
-
- if (tree) {
- header_item = proto_tree_add_text(tree, tvb, offset, -1, "%s", label);
- header_tree = proto_item_add_subtree(header_item, ett_smb2_header);
- }
+ header_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_smb2_header, &header_item, label);
/* Decode the header */
if (!smb2_transform_header) {
/* SMB2 marker */
- proto_tree_add_text(header_tree, tvb, offset, 4, "Server Component: SMB2");
+ proto_tree_add_item(header_tree, hf_smb2_server_component_smb2, tvb, offset, 4, ENC_NA);
offset += 4;
/* we need the flags before we know how to parse the credits field */
/* flags */
if (header_tree) {
- flags_item = proto_tree_add_uint_format(header_tree, hf_smb2_flags, tvb, offset, 4, si->flags,
- "Flags: 0x%08x", si->flags);
- flags_tree = proto_item_add_subtree(flags_item, ett_smb2_flags);
-
- proto_tree_add_boolean(flags_tree, hf_smb2_flags_response, tvb, offset, 4, si->flags);
- proto_tree_add_boolean(flags_tree, hf_smb2_flags_async_cmd, tvb, offset, 4, si->flags);
- proto_tree_add_boolean(flags_tree, hf_smb2_flags_chained, tvb, offset, 4, si->flags);
- proto_tree_add_boolean(flags_tree, hf_smb2_flags_signature, tvb, offset, 4, si->flags);
- proto_tree_add_boolean(flags_tree, hf_smb2_flags_dfs_op, tvb, offset, 4, si->flags);
- proto_tree_add_boolean(flags_tree, hf_smb2_flags_replay_operation, tvb, offset, 4, si->flags);
+ static const int * flags[] = {
+ &hf_smb2_flags_response,
+ &hf_smb2_flags_async_cmd,
+ &hf_smb2_flags_chained,
+ &hf_smb2_flags_signature,
+ &hf_smb2_flags_priority_mask,
+ &hf_smb2_flags_dfs_op,
+ &hf_smb2_flags_replay_operation,
+ NULL
+ };
+
+ proto_tree_add_bitmask(header_tree, tvb, offset, hf_smb2_flags,
+ ett_smb2_flags, flags, ENC_LITTLE_ENDIAN);
}
offset += 4;
}
if (!ssi) {
- /* no we couldnt find it, so just add it then
+ /* no we couldn't find it, so just add it then
* if was a request we are decoding
*/
ssi = wmem_new0(wmem_file_scope(), smb2_saved_info_t);
ssi->msg_id = ssi_key.msg_id;
- ssi->frame_req = pinfo->fd->num;
- ssi->req_time = pinfo->fd->abs_ts;
+ ssi->frame_req = pinfo->num;
+ ssi->req_time = pinfo->abs_ts;
ssi->extra_info_type = SMB2_EI_NONE;
g_hash_table_insert(si->conv->unmatched, ssi, ssi);
}
} else {
/* This is a response */
- if (ssi) {
+ if (!((si->flags & SMB2_FLAGS_ASYNC_CMD)
+ && si->status == NT_STATUS_PENDING)
+ && ssi) {
/* just set the response frame and move it to the matched table */
- ssi->frame_res = pinfo->fd->num;
+ ssi->frame_res = pinfo->num;
g_hash_table_remove(si->conv->unmatched, ssi);
g_hash_table_insert(si->conv->matched, ssi, ssi);
}
} else {
/* see if we can find this msg_id in the matched table */
ssi = (smb2_saved_info_t *)g_hash_table_lookup(si->conv->matched, &ssi_key);
- /* if we couldnt find it in the matched table, it might still
+ /* if we couldn't find it in the matched table, it might still
* be in the unmatched table
*/
if (!ssi) {
}
if (ssi) {
- if (dcerpc_fetch_polhnd_data(&ssi->policy_hnd, &fid_name, NULL, &open_frame, &close_frame, pinfo->fd->num)) {
+ if (dcerpc_fetch_polhnd_data(&ssi->policy_hnd, &fid_name, NULL, &open_frame, &close_frame, pinfo->num)) {
/* If needed, create the file entry and save the policy hnd */
if (!si->eo_file_info) {
if (si->conv) {
tmp_item = proto_tree_add_uint(header_tree, hf_smb2_response_to, tvb, 0, 0, ssi->frame_req);
PROTO_ITEM_SET_GENERATED(tmp_item);
- t = pinfo->fd->abs_ts;
+ t = pinfo->abs_ts;
nstime_delta(&deltat, &t, &ssi->req_time);
tmp_item = proto_tree_add_time(header_tree, hf_smb2_time, tvb,
0, 0, &deltat);
PROTO_ITEM_SET_GENERATED(tmp_item);
}
}
+ if (si->file != NULL) {
+ ssi->file = si->file;
+ } else {
+ si->file = ssi->file;
+ }
}
- /* if we dont have ssi yet we must fake it */
+ /* if we don't have ssi yet we must fake it */
/*qqq*/
si->saved = ssi;
/* Decode the payload */
offset = dissect_smb2_command(pinfo, tree, tvb, offset, si);
} else {
- proto_item *enc_item;
proto_tree *enc_tree;
tvbuff_t *enc_tvb = NULL;
tvbuff_t *plain_tvb = NULL;
/* SMB2_TRANSFORM marker */
- proto_tree_add_text(header_tree, tvb, offset, 4, "Server Component: SMB2_TRANSFORM");
+ proto_tree_add_item(header_tree, hf_smb2_server_component_smb2_transform, tvb, offset, 4, ENC_NA);
offset += 4;
offset = dissect_smb2_transform_header(pinfo, header_tree, tvb, offset, sti,
&enc_tvb, &plain_tvb);
- enc_item = proto_tree_add_text(tree, enc_tvb, 0, sti->size, "Encrypted SMB3 data");
- enc_tree = proto_item_add_subtree(enc_item, ett_smb2_encrypted);
+ enc_tree = proto_tree_add_subtree(tree, enc_tvb, 0, sti->size, ett_smb2_encrypted, NULL, "Encrypted SMB3 data");
if (plain_tvb != NULL) {
col_append_str(pinfo->cinfo, COL_INFO, "Decrypted SMB3");
dissect_smb2(plain_tvb, pinfo, enc_tree, FALSE);
{
/* must check that this really is a smb2 packet */
- if (tvb_length(tvb) < 4)
+ if (tvb_captured_length(tvb) < 4)
return FALSE;
if (((tvb_get_guint8(tvb, 0) != 0xfe) && (tvb_get_guint8(tvb, 0) != 0xfd))
&NT_errors_ext, 0, "NT Status code", HFILL }},
{ &hf_smb2_msg_id,
{ "Message ID", "smb2.msg_id", FT_INT64, BASE_DEC,
- NULL, 0, "SMB2 Messsage ID", HFILL }},
+ NULL, 0, "SMB2 Message ID", HFILL }},
{ &hf_smb2_tid,
{ "Tree Id", "smb2.tid", FT_UINT32, BASE_HEX,
NULL, 0, "SMB2 Tree Id", HFILL }},
{ &hf_smb2_flags_replay_operation,
{ "Replay operation", "smb2.flags.replay", FT_BOOLEAN, 32,
TFS(&tfs_flags_replay_operation), SMB2_FLAGS_REPLAY_OPERATION, "Whether this is a replay operation", HFILL }},
+ { &hf_smb2_flags_priority_mask,
+ { "Priority", "smb2.flags.priority_mask", FT_BOOLEAN, 32,
+ TFS(&tfs_flags_priority_mask), SMB2_FLAGS_PRIORITY_MASK, "Priority Mask", HFILL }},
{ &hf_smb2_tree,
{ "Tree", "smb2.tree", FT_STRING, BASE_NONE,
NULL, 0, "Name of the Tree/Share", HFILL }},
+
{ &hf_smb2_filename,
{ "Filename", "smb2.filename", FT_STRING, BASE_NONE,
NULL, 0, "Name of the file", HFILL }},
+
{ &hf_smb2_filename_len,
{ "Filename Length", "smb2.filename.len", FT_UINT32, BASE_DEC,
NULL, 0, "Length of the file name", HFILL }},
+ { &hf_smb2_replace_if,
+ { "Replace If", "smb2.rename.replace_if", FT_BOOLEAN, 8,
+ TFS(&tfs_replace_if_exists), 0xFF, "Whether to replace if the target exists", HFILL }},
+
{ &hf_smb2_data_offset,
{ "Data Offset", "smb2.data_offset", FT_UINT16, BASE_HEX,
NULL, 0, "Offset to data", HFILL }},
{ "InfoLevel", "smb2.sec_info.infolevel", FT_UINT8, BASE_HEX | BASE_EXT_STRING,
&smb2_sec_info_levels_ext, 0, "Sec_Info Infolevel", HFILL }},
+ { &hf_smb2_infolevel_posix_info,
+ { "InfoLevel", "smb2.posix_info.infolevel", FT_UINT8, BASE_HEX | BASE_EXT_STRING,
+ &smb2_posix_info_levels_ext, 0, "Posix_Info Infolevel", HFILL }},
+
{ &hf_smb2_write_length,
{ "Write Length", "smb2.write_length", FT_UINT32, BASE_DEC,
NULL, 0, "Amount of data to write", HFILL }},
{ "File Offset", "smb2.file_offset", FT_UINT64, BASE_DEC,
NULL, 0, NULL, HFILL }},
+ { &hf_smb2_fsctl_range_offset,
+ { "File Offset", "smb2.fsctl.range_offset", FT_UINT64, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_fsctl_range_length,
+ { "Length", "smb2.fsctl.range_length", FT_UINT64, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_qfr_length,
+ { "Length", "smb2.qfr_length", FT_UINT64, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_qfr_usage,
+ { "Desired Usage", "smb2.qfr_usage", FT_UINT32, BASE_HEX,
+ VALS(file_region_usage_vals), 0, NULL, HFILL }},
+
+ { &hf_smb2_qfr_flags,
+ { "Flags", "smb2.qfr_flags", FT_UINT32, BASE_HEX,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_qfr_total_region_entry_count,
+ { "Total Region Entry Count", "smb2.qfr_tot_region_entry_count", FT_UINT32, BASE_HEX,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_qfr_region_entry_count,
+ { "Region Entry Count", "smb2.qfr_region_entry_count", FT_UINT32, BASE_HEX,
+ NULL, 0, NULL, HFILL }},
+
{ &hf_smb2_security_blob,
{ "Security Blob", "smb2.security_blob", FT_BYTES, BASE_NONE,
NULL, 0, NULL, HFILL }},
NULL, 0, NULL, HFILL }},
{ &hf_smb2_lease_epoch,
- { "Lease Epoch", "smb2.lease.lease_oplock", FT_UINT32, BASE_HEX,
+ { "Lease Epoch", "smb2.lease.lease_oplock", FT_UINT16, BASE_HEX,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_lease_reserved,
+ { "Lease Reserved", "smb2.lease.lease_reserved", FT_UINT16, BASE_HEX,
NULL, 0, NULL, HFILL }},
{ &hf_smb2_lease_break_reason,
{ "Next Offset", "smb2.next_offset", FT_UINT32, BASE_DEC,
NULL, 0, "Offset to next buffer or 0", HFILL }},
+ { &hf_smb2_negotiate_context_type,
+ { "Type", "smb2.negotiate_context.type", FT_UINT16, BASE_HEX,
+ VALS(smb2_negotiate_context_types), 0, "NegotiateContext Type", HFILL }},
+
+ { &hf_smb2_negotiate_context_data_length,
+ { "DataLength", "smb2.negotiate_context.data_length", FT_UINT16, BASE_DEC,
+ NULL, 0, "NegotiateContext DataLength", HFILL }},
+
+ { &hf_smb2_negotiate_context_offset,
+ { "NegotiateContextOffset", "smb2.negotiate_context.offset", FT_UINT16, BASE_HEX,
+ NULL, 0, "NegotiateContext Offset", HFILL }},
+
+ { &hf_smb2_negotiate_context_count,
+ { "NegotiateContextCount", "smb2.negotiate_context.count", FT_UINT16, BASE_DEC,
+ NULL, 0, "NegotiateContext Count", HFILL }},
+
{ &hf_smb2_current_time,
{ "Current Time", "smb2.current_time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
NULL, 0, "Current Time at server", HFILL }},
{ &hf_smb2_buffer_code_len,
{ "Fixed Part Length", "smb2.buffer_code.length", FT_UINT16, BASE_DEC,
- NULL, 0, "Length of fixed portion of PDU", HFILL }},
+ NULL, 0xFFFE, "Length of fixed portion of PDU", HFILL }},
{ &hf_smb2_olb_length,
{ "Length", "smb2.olb.length", FT_UINT32, BASE_DEC,
{ "Method", "smb2.ioctl.function.method", FT_UINT32, BASE_HEX,
VALS(smb2_ioctl_method_vals), 0x00000003, "Method for Ioctl", HFILL }},
+ { &hf_smb2_fsctl_pipe_wait_timeout,
+ { "Timeout", "smb2.fsctl.wait.timeout", FT_INT64, BASE_DEC,
+ NULL, 0, "Wait timeout", HFILL }},
+
+ { &hf_smb2_fsctl_pipe_wait_name,
+ { "Name", "smb2.fsctl.wait.name", FT_STRING, BASE_NONE,
+ NULL, 0, "Pipe name", HFILL }},
+
+ { &hf_smb2_fsctl_odx_token_type,
+ { "TokenType", "smb2.fsctl.odx.token.type", FT_UINT32, BASE_HEX,
+ NULL, 0, "Token Type", HFILL }},
+
+ { &hf_smb2_fsctl_odx_token_idlen,
+ { "TokenIdLength", "smb2.fsctl.odx.token.idlen", FT_UINT16, BASE_DEC,
+ NULL, 0, "Token ID Length", HFILL }},
+
+ { &hf_smb2_fsctl_odx_token_idraw,
+ { "TokenId", "smb2.fsctl.odx.token.id", FT_BYTES, BASE_NONE,
+ NULL, 0, "Token ID (opaque)", HFILL }},
+
+ { &hf_smb2_fsctl_odx_token_ttl,
+ { "TokenTimeToLive", "smb2.fsctl.odx.token_ttl",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "TTL requested for the token (in milliseconds)", HFILL }},
+
+ { &hf_smb2_fsctl_odx_size,
+ { "Size", "smb2.fsctl.odx.size", FT_UINT32, BASE_DEC,
+ NULL, 0, "Size of this data element", HFILL }},
+
+ { &hf_smb2_fsctl_odx_flags,
+ { "Flags", "smb2.fsctl.odx.flags", FT_UINT32, BASE_HEX,
+ NULL, 0, "Flags for this operation", HFILL }},
+
+ { &hf_smb2_fsctl_odx_file_offset,
+ { "FileOffset", "smb2.fsctl.odx.file_offset",
+ FT_UINT64, BASE_DEC, NULL, 0,
+ "File offset", HFILL }},
+
+ { &hf_smb2_fsctl_odx_copy_length,
+ { "CopyLength", "smb2.fsctl.odx.copy_length",
+ FT_UINT64, BASE_DEC, NULL, 0,
+ "Copy length", HFILL }},
+
+ { &hf_smb2_fsctl_odx_xfer_length,
+ { "TransferLength", "smb2.fsctl.odx.xfer_length",
+ FT_UINT64, BASE_DEC, NULL, 0,
+ "Length Transfered", HFILL }},
+
+ { &hf_smb2_fsctl_odx_token_offset,
+ { "TokenOffset", "smb2.fsctl.odx.token_offset",
+ FT_UINT64, BASE_DEC, NULL, 0,
+ "Token Offset (relative to start of token)", HFILL }},
+
+ { &hf_smb2_fsctl_sparse_flag,
+ { "SetSparse", "smb2.fsctl.set_sparse", FT_BOOLEAN, 8,
+ NULL, 0xFF, NULL, HFILL }},
+
{ &hf_smb2_ioctl_resiliency_timeout,
{ "Timeout", "smb2.ioctl.resiliency.timeout", FT_UINT32, BASE_DEC,
NULL, 0, "Resiliency timeout", HFILL }},
{ "Compression Format", "smb2.compression_format", FT_UINT16, BASE_DEC,
VALS(compression_format_vals), 0, "Compression to use", HFILL }},
+ { &hf_smb2_checksum_algorithm,
+ { "Checksum Algorithm", "smb2.checksum_algorithm", FT_UINT16, BASE_HEX,
+ VALS(checksum_algorithm_vals), 0, "Checksum algorithm to use", HFILL}},
+
+ { &hf_smb2_integrity_reserved,
+ { "Reserved", "smb2.integrity_reserved", FT_UINT16, BASE_DEC,
+ NULL, 0, "Reserved Field", HFILL}},
+
+ { &hf_smb2_integrity_flags,
+ { "Flags", "smb2.integrity_flags", FT_UINT32, BASE_HEX,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_integrity_flags_enforcement_off,
+ { "FSCTL_INTEGRITY_FLAG_CHECKSUM_ENFORCEMENT_OFF", "smb2.integrity_flags_enforcement", FT_BOOLEAN, 32,
+ NULL, 0x1, "If checksum error enforcement is off", HFILL }},
+
{ &hf_smb2_share_type,
{ "Share Type", "smb2.share_type", FT_UINT8, BASE_HEX,
VALS(smb2_share_type_vals), 0, "Type of share", HFILL }},
NULL, 0, "Maximum size of a write", HFILL }},
{ &hf_smb2_channel,
- { "Channel", "smb2.channel", FT_UINT32, BASE_DEC,
+ { "Channel", "smb2.channel", FT_UINT32, BASE_HEX,
+ VALS(smb2_channel_vals), 0, NULL, HFILL }},
+
+ { &hf_smb2_rdma_v1_offset,
+ { "Offset", "smb2.buffer_descriptor.offset", FT_UINT64, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_rdma_v1_token,
+ { "Token", "smb2.buffer_descriptor.token", FT_UINT32, BASE_HEX,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_rdma_v1_length,
+ { "Length", "smb2.buffer_descriptor.length", FT_UINT32, BASE_DEC,
NULL, 0, NULL, HFILL }},
{ &hf_smb2_share_flags,
{ "Channel Info Length", "smb2.channel_info_length", FT_UINT16, BASE_DEC,
NULL, 0, NULL, HFILL }},
+ { &hf_smb2_channel_info_blob,
+ { "Channel Info Blob", "smb2.channel_info_blob", FT_NONE, BASE_NONE,
+ NULL, 0, NULL, HFILL }},
+
{ &hf_smb2_ioctl_is_fsctl,
{ "Is FSCTL", "smb2.ioctl.is_fsctl", FT_BOOLEAN, 32,
NULL, 0x00000001, NULL, HFILL }},
{ "Out Data", "smb2.notify.out", FT_NONE, BASE_NONE,
NULL, 0, NULL, HFILL }},
+ { &hf_smb2_notify_info,
+ { "Notify Info", "smb2.notify.info", FT_NONE, BASE_NONE,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_notify_next_offset,
+ { "Next Offset", "smb2.notify.next_offset", FT_UINT32, BASE_HEX,
+ NULL, 0, "Offset to next entry in chain or 0", HFILL }},
+
+ { &hf_smb2_notify_action,
+ { "Action", "smb2.notify.action", FT_UINT32, BASE_HEX,
+ VALS(notify_action_vals), 0, "Notify Action", HFILL }},
+
+
{ &hf_smb2_find_flags_restart_scans,
{ "Restart Scans", "smb2.find.restart_scans", FT_BOOLEAN, 8,
NULL, SMB2_FIND_FLAG_RESTART_SCANS, NULL, HFILL }},
{ "Reserved", "smb2.reserved", FT_BYTES, BASE_NONE,
NULL, 0, "Reserved bytes", HFILL }},
+ { &hf_smb2_reserved_random,
+ { "Reserved (Random)", "smb2.reserved.random", FT_BYTES, BASE_NONE,
+ NULL, 0, "Reserved bytes, random data", HFILL }},
+
+ { &hf_smb2_root_directory_mbz,
+ { "Root Dir Handle (MBZ)", "smb2.root_directory", FT_BYTES, BASE_NONE,
+ NULL, 0, "Root Directory Handle, mbz", HFILL }},
+
{ &hf_smb2_dhnq_buffer_reserved,
{ "Reserved", "smb2.dhnq_buffer_reserved", FT_UINT64, BASE_HEX,
NULL, 0, NULL, HFILL}},
{ "Application Guid", "smb2.app_instance.app_guid", FT_GUID, BASE_NONE,
NULL, 0, NULL, HFILL}},
+ { &hf_smb2_svhdx_open_device_context_version,
+ { "Version", "smb2.svhdx_open_device_context.version", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL}},
+
+ { &hf_smb2_svhdx_open_device_context_has_initiator_id,
+ { "HasInitiatorId", "smb2.svhdx_open_device_context.initiator_has_id", FT_BOOLEAN, 8,
+ TFS(&tfs_smb2_svhdx_has_initiator_id), 0, "Whether the host has an intiator", HFILL}},
+
+ { &hf_smb2_svhdx_open_device_context_reserved,
+ { "Reserved", "smb2.svhdx_open_device_context.reserved", FT_BYTES, BASE_NONE,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_svhdx_open_device_context_initiator_id,
+ { "InitiatorId", "smb2.svhdx_open_device_context.initiator_id", FT_BYTES, BASE_NONE,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_svhdx_open_device_context_flags,
+ { "Flags", "smb2.svhdx_open_device_context.flags", FT_UINT32, BASE_HEX,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_svhdx_open_device_context_originator_flags,
+ { "OriginatorFlags", "smb2.svhdx_open_device_context.originator_flags", FT_UINT32, BASE_HEX,
+ VALS(originator_flags_vals), 0, "Originator Flags", HFILL }},
+
+ { &hf_smb2_svhdx_open_device_context_open_request_id,
+ { "OpenRequestId","smb2.svhxd_open_device_context.open_request_id", FT_UINT64, BASE_HEX,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_svhdx_open_device_context_initiator_host_name_len,
+ { "HostNameLength", "smb2.svhxd_open_device_context.initiator_host_name_len", FT_UINT16, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_svhdx_open_device_context_initiator_host_name,
+ { "HostName", "smb2.svhdx_open_device_context.host_name", FT_STRING, BASE_NONE,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_posix_v1_version,
+ { "Version", "smb2.posix_v1_version", FT_UINT32, BASE_DEC,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_posix_v1_request,
+ { "Request", "smb2.posix_request", FT_UINT32, BASE_HEX,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_posix_v1_case_sensitive,
+ { "Posix Case Sensitive File Names", "smb2.posix_case_sensitive", FT_UINT32, BASE_HEX,
+ VALS(posix_case_sensitive_vals), 0x01, NULL, HFILL }},
+
+ { &hf_smb2_posix_v1_posix_lock,
+ { "Posix Byte-Range Locks", "smb2.posix_locks", FT_UINT32, BASE_HEX,
+ VALS(posix_locks_vals), 0x02, NULL, HFILL }},
+
+ { &hf_smb2_posix_v1_posix_file_semantics,
+ { "Posix File Semantics", "smb2.posix_file_semantics", FT_UINT32, BASE_HEX,
+ VALS(posix_file_semantics_vals), 0x04, NULL, HFILL }},
+
+ { &hf_smb2_posix_v1_posix_utf8_paths,
+ { "Posix UTF8 Paths", "smb2.posix_utf8_paths", FT_UINT32, BASE_HEX,
+ VALS(posix_utf8_paths_vals), 0x08, NULL, HFILL }},
+
+ { &hf_smb2_posix_v1_posix_will_convert_nt_acls,
+ { "Posix Will Convert NT ACLs", "smb2.will_convert_NTACLs", FT_UINT32, BASE_HEX,
+ VALS(posix_will_convert_ntacls_vals), 0x10, NULL, HFILL }},
+
+ { &hf_smb2_posix_v1_posix_fileinfo,
+ { "Posix Fileinfo", "smb2.posix_fileinfo", FT_UINT32, BASE_HEX,
+ VALS(posix_fileinfo_vals), 0x20, NULL, HFILL }},
+
+ { &hf_smb2_posix_v1_posix_acls,
+ { "Posix ACLs", "smb2.posix_acls", FT_UINT32, BASE_HEX,
+ VALS(posix_acls_vals), 0x40, NULL, HFILL }},
+
+ { &hf_smb2_posix_v1_rich_acls,
+ { "Rich ACLs", "smb2.rich_acls", FT_UINT32, BASE_HEX,
+ VALS(posix_rich_acls_vals), 0x80, NULL, HFILL }},
+
+ { &hf_smb2_posix_v1_supported_features,
+ { "Supported Features", "smb2.posix_supported_features", FT_UINT32, BASE_HEX,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_aapl_command_code,
+ { "Command code", "smb2.aapl.command_code", FT_UINT32, BASE_DEC,
+ VALS(aapl_command_code_vals), 0, NULL, HFILL }},
+
+ { &hf_smb2_aapl_reserved,
+ { "Reserved", "smb2.aapl.reserved", FT_UINT32, BASE_HEX,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_aapl_server_query_bitmask,
+ { "Query bitmask", "smb2.aapl.query_bitmask", FT_UINT64, BASE_HEX,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_aapl_server_query_bitmask_server_caps,
+ { "Server capabilities", "smb2.aapl.bitmask.server_caps", FT_BOOLEAN, 64,
+ NULL, SMB2_AAPL_SERVER_CAPS, NULL, HFILL }},
+
+ { &hf_smb2_aapl_server_query_bitmask_volume_caps,
+ { "Volume capabilities", "smb2.aapl.bitmask.volume_caps", FT_BOOLEAN, 64,
+ NULL, SMB2_AAPL_VOLUME_CAPS, NULL, HFILL }},
+
+ { &hf_smb2_aapl_server_query_bitmask_model_info,
+ { "Model information", "smb2.aapl.bitmask.model_info", FT_BOOLEAN, 64,
+ NULL, SMB2_AAPL_MODEL_INFO, NULL, HFILL }},
+
+ { &hf_smb2_aapl_server_query_caps,
+ { "Client/Server capabilities", "smb2.aapl.caps", FT_UINT64, BASE_HEX,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_aapl_server_query_caps_supports_read_dir_attr,
+ { "Supports READDIRATTR", "smb2.aapl.caps.supports_read_dir_addr", FT_BOOLEAN, 64,
+ NULL, SMB2_AAPL_SUPPORTS_READ_DIR_ATTR, NULL, HFILL }},
+
+ { &hf_smb2_aapl_server_query_caps_supports_osx_copyfile,
+ { "Supports OS X copyfile", "smb2.aapl.caps.supports_osx_copyfile", FT_BOOLEAN, 64,
+ NULL, SMB2_AAPL_SUPPORTS_OSX_COPYFILE, NULL, HFILL }},
+
+ { &hf_smb2_aapl_server_query_caps_unix_based,
+ { "UNIX-based", "smb2.aapl.caps.unix_based", FT_BOOLEAN, 64,
+ NULL, SMB2_AAPL_UNIX_BASED, NULL, HFILL }},
+
+ { &hf_smb2_aapl_server_query_caps_supports_nfs_ace,
+ { "Supports NFS ACE", "smb2.aapl.supports_nfs_ace", FT_BOOLEAN, 64,
+ NULL, SMB2_AAPL_SUPPORTS_NFS_ACE, NULL, HFILL }},
+
+ { &hf_smb2_aapl_server_query_volume_caps,
+ { "Volume capabilities", "smb2.aapl.volume_caps", FT_UINT64, BASE_HEX,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_aapl_server_query_volume_caps_support_resolve_id,
+ { "Supports Resolve ID", "smb2.aapl.volume_caps.supports_resolve_id", FT_BOOLEAN, 64,
+ NULL, SMB2_AAPL_SUPPORTS_RESOLVE_ID, NULL, HFILL }},
+
+ { &hf_smb2_aapl_server_query_volume_caps_case_sensitive,
+ { "Case sensitive", "smb2.aapl.volume_caps.case_sensitive", FT_BOOLEAN, 64,
+ NULL, SMB2_AAPL_CASE_SENSITIVE, NULL, HFILL }},
+
+ { &hf_smb2_aapl_server_query_volume_caps_supports_full_sync,
+ { "Supports full sync", "smb2.aapl.volume_caps.supports_full_sync", FT_BOOLEAN, 64,
+ NULL, SMB2_AAPL_SUPPORTS_FULL_SYNC, NULL, HFILL }},
+
+ { &hf_smb2_aapl_server_query_model_string,
+ { "Model string", "smb2.aapl.model_string", FT_UINT_STRING, STR_UNICODE,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_aapl_server_query_server_path,
+ { "Server path", "smb2.aapl.server_path", FT_UINT_STRING, STR_UNICODE,
+ NULL, 0, NULL, HFILL }},
+
{ &hf_smb2_transform_signature,
{ "Signature", "smb2.header.transform.signature", FT_BYTES, BASE_NONE,
NULL, 0, NULL, HFILL }},
{ "Data", "smb2.header.transform.enc_data", FT_BYTES, BASE_NONE,
NULL, 0, NULL, HFILL }},
+ { &hf_smb2_server_component_smb2,
+ { "Server Component: SMB2", "smb2.server_component_smb2", FT_NONE, BASE_NONE,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_server_component_smb2_transform,
+ { "Server Component: SMB2_TRANSFORM", "smb2.server_component_smb2_transform", FT_NONE, BASE_NONE,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_truncated,
+ { "Truncated...", "smb2.truncated", FT_NONE, BASE_NONE,
+ NULL, 0, NULL, HFILL }},
+
+ { &hf_smb2_pipe_fragment_overlap,
+ { "Fragment overlap", "smb2.pipe.fragment.overlap", FT_BOOLEAN, BASE_NONE,
+ NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
+ { &hf_smb2_pipe_fragment_overlap_conflict,
+ { "Conflicting data in fragment overlap", "smb2.pipe.fragment.overlap.conflict", FT_BOOLEAN,
+ BASE_NONE, NULL, 0x0, "Overlapping fragments contained conflicting data", HFILL }},
+ { &hf_smb2_pipe_fragment_multiple_tails,
+ { "Multiple tail fragments found", "smb2.pipe.fragment.multipletails", FT_BOOLEAN,
+ BASE_NONE, NULL, 0x0, "Several tails were found when defragmenting the packet", HFILL }},
+ { &hf_smb2_pipe_fragment_too_long_fragment,
+ { "Fragment too long", "smb2.pipe.fragment.toolongfragment", FT_BOOLEAN,
+ BASE_NONE, NULL, 0x0, "Fragment contained data past end of packet", HFILL }},
+ { &hf_smb2_pipe_fragment_error,
+ { "Defragmentation error", "smb2.pipe.fragment.error", FT_FRAMENUM,
+ BASE_NONE, NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }},
+ { &hf_smb2_pipe_fragment_count,
+ { "Fragment count", "smb2.pipe.fragment.count", FT_UINT32,
+ BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_smb2_pipe_fragment,
+ { "Fragment SMB2 Named Pipe", "smb2.pipe.fragment", FT_FRAMENUM,
+ BASE_NONE, NULL, 0x0, "SMB2 Named Pipe Fragment", HFILL }},
+ { &hf_smb2_pipe_fragments,
+ { "Reassembled SMB2 Named Pipe fragments", "smb2.pipe.fragments", FT_NONE,
+ BASE_NONE, NULL, 0x0, "SMB2 Named Pipe Fragments", HFILL }},
+ { &hf_smb2_pipe_reassembled_in,
+ { "This SMB2 Named Pipe payload is reassembled in frame", "smb2.pipe.reassembled_in", FT_FRAMENUM,
+ BASE_NONE, NULL, 0x0, "The Named Pipe PDU is completely reassembled in this frame", HFILL }},
+ { &hf_smb2_pipe_reassembled_length,
+ { "Reassembled SMB2 Named Pipe length", "smb2.pipe.reassembled.length", FT_UINT32,
+ BASE_DEC, NULL, 0x0, "The total length of the reassembled payload", HFILL }},
+ { &hf_smb2_pipe_reassembled_data,
+ { "Reassembled SMB2 Named Pipe Data", "smb2.pipe.reassembled.data", FT_BYTES,
+ BASE_NONE, NULL, 0x0, "The reassembled payload", HFILL }},
+ { &hf_smb2_cchunk_resume_key,
+ { "ResumeKey", "smb2.fsctl.cchunk.resume_key", FT_BYTES,
+ BASE_NONE, NULL, 0x0, "Opaque data representing source of copy", HFILL }},
+ { &hf_smb2_cchunk_count,
+ { "Chunk Count", "smb2.fsctl.cchunk.count", FT_UINT32,
+ BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_smb2_cchunk_src_offset,
+ { "Source Offset", "smb2.fsctl.cchunk.src_offset", FT_UINT64,
+ BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_smb2_cchunk_dst_offset,
+ { "Target Offset", "smb2.fsctl.cchunk.dst_offset", FT_UINT64,
+ BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_smb2_cchunk_xfer_len,
+ { "Transfer Length", "smb2.fsctl.cchunk.xfer_len", FT_UINT32,
+ BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_smb2_cchunk_chunks_written,
+ { "Chunks Written", "smb2.fsctl.cchunk.chunks_written", FT_UINT32,
+ BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_smb2_cchunk_bytes_written,
+ { "Chunk Bytes Written", "smb2.fsctl.cchunk.bytes_written", FT_UINT32,
+ BASE_DEC, NULL, 0x0, NULL, HFILL }},
+ { &hf_smb2_cchunk_total_written,
+ { "Total Bytes Written", "smb2.fsctl.cchunk.total_written", FT_UINT32,
+ BASE_DEC, NULL, 0x0, NULL, HFILL }},
};
static gint *ett[] = {
&ett_smb2_encrypted,
&ett_smb2_command,
&ett_smb2_secblob,
+ &ett_smb2_negotiate_context_element,
&ett_smb2_file_basic_info,
&ett_smb2_file_standard_info,
&ett_smb2_file_internal_info,
&ett_smb2_share_caps,
&ett_smb2_ioctl_flags,
&ett_smb2_ioctl_network_interface,
+ &ett_smb2_fsctl_range_data,
&ett_windows_sockaddr,
&ett_smb2_close_flags,
+ &ett_smb2_notify_info,
&ett_smb2_notify_flags,
+ &ett_smb2_rdma_v1,
&ett_smb2_write_flags,
&ett_smb2_find_flags,
&ett_smb2_file_directory_info,
&ett_smb2_DH2C_buffer,
&ett_smb2_dh2x_flags,
&ett_smb2_APP_INSTANCE_buffer,
+ &ett_smb2_svhdx_open_device_context,
+ &ett_smb2_posix_v1_request,
+ &ett_smb2_posix_v1_response,
+ &ett_smb2_posix_v1_supported_features,
+ &ett_smb2_aapl_create_context_request,
+ &ett_smb2_aapl_server_query_bitmask,
+ &ett_smb2_aapl_server_query_caps,
+ &ett_smb2_aapl_create_context_response,
+ &ett_smb2_aapl_server_query_volume_caps,
+ &ett_smb2_integrity_flags,
&ett_smb2_transform_enc_alg,
&ett_smb2_buffercode,
+ &ett_smb2_ioctl_network_interface_capabilities,
+ &ett_qfr_entry,
+ &ett_smb2_pipe_fragment,
+ &ett_smb2_pipe_fragments,
+ &ett_smb2_cchunk_entry,
+ &ett_smb2_fsctl_odx_token,
};
+ static ei_register_info ei[] = {
+ { &ei_smb2_invalid_length, { "smb2.invalid_length", PI_MALFORMED, PI_ERROR, "Invalid length", EXPFILL }},
+ { &ei_smb2_bad_response, { "smb2.bad_response", PI_MALFORMED, PI_ERROR, "Bad response", EXPFILL }},
+ };
+
+ expert_module_t* expert_smb2;
+
proto_smb2 = proto_register_protocol("SMB2 (Server Message Block Protocol version 2)",
"SMB2", "smb2");
proto_register_subtree_array(ett, array_length(ett));
proto_register_field_array(proto_smb2, hf, array_length(hf));
+ expert_smb2 = expert_register_protocol(proto_smb2);
+ expert_register_field_array(expert_smb2, ei, array_length(ei));
smb2_module = prefs_register_protocol(proto_smb2, NULL);
prefs_register_bool_preference(smb2_module, "eosmb2_take_name_as_fid",
"Whether the export object functionality will take the full path file name as file identifier",
&eosmb2_take_name_as_fid);
- register_heur_dissector_list("smb2_heur_subdissectors", &smb2_heur_subdissector_list);
+ prefs_register_bool_preference(smb2_module, "pipe_reassembly",
+ "Reassemble Named Pipes over SMB2",
+ "Whether the dissector should reassemble Named Pipes over SMB2 commands",
+ &smb2_pipe_reassembly);
+ smb2_pipe_subdissector_list = register_heur_dissector_list("smb2_pipe_subdissectors", proto_smb2);
+ register_init_routine(smb2_pipe_reassembly_init);
+
smb2_tap = register_tap("smb2");
smb2_eo_tap = register_tap("smb_eo"); /* SMB Export Object tap */
+ register_srt_table(proto_smb2, NULL, 1, smb2stat_packet, smb2stat_init, NULL);
}
void
proto_reg_handoff_smb2(void)
{
- gssapi_handle = find_dissector("gssapi");
- ntlmssp_handle = find_dissector("ntlmssp");
- heur_dissector_add("netbios", dissect_smb2_heur, proto_smb2);
+ gssapi_handle = find_dissector_add_dependency("gssapi", proto_smb2);
+ ntlmssp_handle = find_dissector_add_dependency("ntlmssp", proto_smb2);
+ rsvd_handle = find_dissector_add_dependency("rsvd", proto_smb2);
+ heur_dissector_add("netbios", dissect_smb2_heur, "SMB2 over Netbios", "smb2_netbios", proto_smb2, HEURISTIC_ENABLE);
+ heur_dissector_add("smb_direct", dissect_smb2_heur, "SMB2 over SMB Direct", "smb2_smb_direct", proto_smb2, HEURISTIC_ENABLE);
}
/*