#include "packet-smb-common.h"
#include "packet-dcerpc-nt.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 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_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_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_offload_read_size = -1;
+static int hf_smb2_fsctl_offload_read_flags = -1;
+static int hf_smb2_fsctl_offload_read_token_ttl = -1;
+static int hf_smb2_fsctl_offload_reserved = -1;
+static int hf_smb2_fsctl_offload_read_file_offset = -1;
+static int hf_smb2_fsctl_offload_read_copy_length = -1;
+static int hf_smb2_fsctl_offload_read_transfer_length = -1;
+static int hf_smb2_fsctl_offload_token = -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_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_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_error_byte_count = -1;
static int hf_smb2_error_data = -1;
static int hf_smb2_error_reserved = -1;
static gint ett_smb2_ioctl_network_interface = -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_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_integrity_flags = -1;
static gint ett_smb2_find_flags = -1;
static gint ett_smb2_file_directory_info = -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 expert_field ei_smb2_invalid_length = EI_INIT;
static expert_field ei_smb2_bad_response = EI_INIT;
#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 }
};
};
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
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);
"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" },
{0x000900F0, "FSCTL_EXTEND_VOLUME"},
{0x0009027C, "FSCTL_GET_INTEGRITY_INFORMATION"},
{0x00090284, "FSCTL_QUERY_FILE_REGIONS"},
- {0x00090300, "FSCTL_QUERY_SHARED_VIRTUAL_DISK_SUPPORT"},
- {0x00090304, "FSCTL_SVHDX_SYNC_TUNNEL_REQUEST"},
+ {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"},
{0x000940E7, "FSCTL_CREATE_USN_JOURNAL"},
{0x000940EB, "FSCTL_READ_FILE_USN_DATA"},
{0x000940EF, "FSCTL_WRITE_USN_CLOSE_RECORD"},
+ {0x00094264, "FSCTL_OFFLOAD_READ"},
{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 */
{0x000980C8, "FSCTL_SET_ZERO_DATA"},
{0x000980D0, "FSCTL_ENABLE_UPGRADE"},
{0x0009C040, "FSCTL_SET_COMPRESSION"}, /* dissector implemented */
- {0x0009C280, "FSCTL_SET_INTEGRITY_INFORMATION"},
- {0x00110018, "FSCTL_PIPE_WAIT"},
-<<<<<<< HEAD
+ {0x0009C280, "FSCTL_SET_INTEGRITY_INFORMATION"}, /* dissector implemented */
+ {0x00110018, "FSCTL_PIPE_WAIT"}, /* dissector implemented */
{0x0011C017, "FSCTL_PIPE_TRANSCEIVE"}, /* dissector implemented */
{0x00140078, "FSCTL_SRV_REQUEST_RESUME_KEY"},
-=======
- {0x0011C017, "FSCTL_PIPE_TRANSCEIVE" }, /* dissector implemented */
- {0x00140078, "FSCTL_SRV_REQUEST_RESUME_KEY" },
->>>>>>> 24a7720... SMB2 - An out-of-order entry in smb2_ioctl_vals[] causes run-time error.
{0x001401D4, "FSCTL_LMR_REQUEST_RESILIENCY"}, /* dissector implemented */
{0x001401FC, "FSCTL_QUERY_NETWORK_INTERFACE_INFO"}, /* dissector implemented */
{0x00140200, "FSCTL_VALIDATE_NEGOTIATE_INFO_224"}, /* dissector implemented */
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]");
+ }
+ sfi->open_frame = pinfo->fd->num;
+
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->fd->num)) {
/* look for the eo_file_info */
if (!si->eo_file_info) {
if (si->saved) { si->saved->policy_hnd = policy_hnd; }
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_captured_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
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() */
if (si == NULL) {
return;
}
- if (si->saved == NULL) {
+ if (si->file == NULL) {
return;
}
- /*
- * the first 8 bytes are the persistent part of the file handle
- */
- persistent = si->saved->policy_hnd.uuid.data1;
- persistent |= ((guint64)si->saved->policy_hnd.uuid.data2) << 32;
- persistent |= ((guint64)si->saved->policy_hnd.uuid.data3) << 48;
+ persistent = GPOINTER_TO_UINT(si->file);
dcerpc_set_transport_salt(persistent, pinfo);
}
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_dcerpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, int offset, guint32 datalen, proto_tree *top_tree, void *data)
{
tvbuff_t *dcerpc_tvb;
heur_dtbl_entry_t *hdtbl_entry;
dcerpc_tvb = tvb_new_subset(tvb, offset, MIN((int)datalen, tvb_captured_length_remaining(tvb, offset)), datalen);
/* dissect the full PDU */
- dissector_try_heuristic(smb2_heur_subdissector_list, dcerpc_tvb, pinfo, top_tree, &hdtbl_entry, NULL);
+ if (dissector_try_heuristic(smb2_heur_subdissector_list, dcerpc_tvb, pinfo, top_tree, &hdtbl_entry, data)) {
- offset += datalen;
-
+ offset += datalen;
+ }
return offset;
}
}
/* data or dcerpc ?*/
- if (length && si->tree && si->tree->share_type == SMB2_SHARE_TYPE_PIPE) {
+ if (length) {
+ int oldoffset = offset;
smb2_set_dcerpc_file_id(pinfo, si);
- offset = dissect_file_data_dcerpc(tvb, pinfo, tree, offset, length, si->top_tree);
- return offset;
+ offset = dissect_file_data_dcerpc(tvb, pinfo, tree, offset, length, si->top_tree, si);
+ if (offset != oldoffset) {
+ /* managed to dissect pipe data */
+ return offset;
+ }
}
/* just ordinary data */
}
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_)
+dissect_smb2_FSCTL_OFFLOAD_READ(tvbuff_t *tvb,
+ packet_info *pinfo _U_,
+ proto_tree *tree,
+ int offset,
+ proto_tree *top_tree _U_,
+ gboolean in)
+{
+ proto_tree_add_item(tree, hf_smb2_fsctl_offload_read_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_smb2_fsctl_offload_read_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ if (in) {
+ proto_tree_add_item(tree, hf_smb2_fsctl_offload_read_token_ttl, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_smb2_fsctl_offload_reserved, tvb, offset, 4, ENC_NA);
+ offset += 4;
+
+ proto_tree_add_item(tree, hf_smb2_fsctl_offload_read_file_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+
+ proto_tree_add_item(tree, hf_smb2_fsctl_offload_read_copy_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ /* offset += 8; */
+ } else {
+ proto_tree_add_item(tree, hf_smb2_fsctl_offload_read_transfer_length, tvb, offset, 8, ENC_LITTLE_ENDIAN);
+ offset += 8;
+
+ proto_tree_add_item(tree, hf_smb2_fsctl_offload_token, tvb, offset, 512, ENC_NA);
+ /* offset += 512; */
+ }
+}
+
+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_dcerpc(tvb, pinfo, tree, offset, tvb_captured_length_remaining(tvb, offset), top_tree);
+ dissect_file_data_dcerpc(tvb, pinfo, tree, offset, tvb_captured_length_remaining(tvb, offset), top_tree, data);
}
static void
if (name == NULL) {
name = "";
}
+
col_append_fstr(pinfo->cinfo, COL_INFO, " Pipe: %s", name);
if (top_tree) {
}
}
+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)
{
}
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 0x00094264: /* FSCTL_OFFLOAD_READ */
+ dissect_smb2_FSCTL_OFFLOAD_READ(tvb, pinfo, tree, 0, top_tree, data_in);
break;
- case 0x00110018:
+ 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 0x001401D4: /* FSCTL_LMR_REQUEST_RESILIENCY */
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;
dissect_smb2_ioctl_data_in(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si)
{
smb2_set_dcerpc_file_id(pinfo, si);
- dissect_smb2_ioctl_data(tvb, pinfo, tree, si->top_tree, si->ioctl_function, TRUE);
+ 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)
{
smb2_set_dcerpc_file_id(pinfo, si);
- dissect_smb2_ioctl_data(tvb, pinfo, tree, si->top_tree, si->ioctl_function, FALSE);
+ dissect_smb2_ioctl_data(tvb, pinfo, tree, si->top_tree, si->ioctl_function, FALSE, si);
}
static int
/* 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))) {
+ /* data or dcerpc ?*/
+ if (length) {
+ int oldoffset = offset;
smb2_set_dcerpc_file_id(pinfo, si);
- offset = dissect_file_data_dcerpc(tvb, pinfo, tree, offset, length, si->top_tree);
- return offset;
+ offset = dissect_file_data_dcerpc(tvb, pinfo, tree, offset, length, si->top_tree, si);
+ if (offset != oldoffset) {
+ /* managed to dissect pipe data */
+ return offset;
+ }
}
/* data */
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);
+
+}
+
typedef void (*create_context_data_dissector_t)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si);
typedef struct create_context_data_dissectors {
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} }
+ 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 } }
};
static struct create_context_data_tag_dissectors*
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
&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
}
} 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;
g_hash_table_remove(si->conv->unmatched, ssi);
{ &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,
{ "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_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 }},
{ "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_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_offload_read_size,
+ { "Size", "smb2.fsctl.offload.read", FT_UINT32, BASE_DEC,
+ NULL, 0, "Size of data element", HFILL }},
+
+ { &hf_smb2_fsctl_offload_read_flags,
+ { "Flags", "smb2.fsctl.offload.flags", FT_UINT32, BASE_HEX,
+ NULL, 0, "Flags for this operation", HFILL }},
+
+ { &hf_smb2_fsctl_offload_read_token_ttl,
+ { "TokenTimeToLive", "smb2.fsctl.offload.token_ttl",
+ FT_UINT32, BASE_DEC, NULL, 0,
+ "TTL for the generated token (in milliseconds)", HFILL }},
- { &hf_smb2_fsctl_pipe_wait_name,
- { "Name", "smb2.fsctl.wait.name", FT_STRING, BASE_NONE,
- NULL, 0, "Pipe name", HFILL }},
+ { &hf_smb2_fsctl_offload_reserved,
+ { "Reserved", "smb2.fsctl.offload.reserved",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ NULL, HFILL }},
+
+ { &hf_smb2_fsctl_offload_read_file_offset,
+ { "FileOffset", "smb2.fsctl.offload.file_offset",
+ FT_UINT64, BASE_DEC, NULL, 0,
+ "File offset", HFILL }},
+
+ { &hf_smb2_fsctl_offload_read_copy_length,
+ { "CopyLength", "smb2.fsctl.offload.copy_length",
+ FT_UINT64, BASE_DEC, NULL, 0,
+ "Copy length", HFILL }},
+
+ { &hf_smb2_fsctl_offload_read_transfer_length,
+ { "TransferLength", "smb2.fsctl.offload.transfer_length",
+ FT_UINT64, BASE_DEC, NULL, 0,
+ "Transfer length", HFILL }},
+
+ { &hf_smb2_fsctl_offload_token,
+ { "Token", "smb2.fsctl.offload.token",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ NULL, HFILL }},
{ &hf_smb2_ioctl_resiliency_timeout,
{ "Timeout", "smb2.ioctl.resiliency.timeout", FT_UINT32, BASE_DEC,
{ "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 }},
{ "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_transform_signature,
{ "Signature", "smb2.header.transform.signature", FT_BYTES, BASE_NONE,
NULL, 0, NULL, HFILL }},
&ett_smb2_ioctl_network_interface,
&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_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_integrity_flags,
&ett_smb2_transform_enc_alg,
&ett_smb2_buffercode,
&ett_smb2_ioctl_network_interface_capabilities,
+ &ett_qfr_entry,
};
static ei_register_info ei[] = {
gssapi_handle = find_dissector("gssapi");
ntlmssp_handle = find_dissector("ntlmssp");
rsvd_handle = find_dissector("rsvd");
- heur_dissector_add("netbios", dissect_smb2_heur, proto_smb2);
- heur_dissector_add("smb_direct", dissect_smb2_heur, 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);
}
/*