/* packet-smb2.c * Routines for smb2 packet dissection * Ronnie Sahlberg 2005 * * For documentation of this protocol, see: * * 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. * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "packet-smb2.h" #include "packet-ntlmssp.h" #include "packet-kerberos.h" #include "packet-windows-common.h" #include "packet-smb-common.h" #include "packet-dcerpc-nt.h" #include "read_keytab_file.h" #include #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 proto_smb2 = -1; static int hf_smb2_cmd = -1; static int hf_smb2_nt_status = -1; static int hf_smb2_response_to = -1; static int hf_smb2_response_in = -1; static int hf_smb2_time = -1; static int hf_smb2_header_len = -1; static int hf_smb2_msg_id = -1; static int hf_smb2_pid = -1; static int hf_smb2_tid = -1; static int hf_smb2_aid = -1; static int hf_smb2_sesid = -1; static int hf_smb2_previous_sesid = -1; static int hf_smb2_flags_response = -1; static int hf_smb2_flags_async_cmd = -1; static int hf_smb2_flags_dfs_op = -1; 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_qfid_fid = -1; static int hf_smb2_create_timestamp = -1; static int hf_smb2_oplock = -1; static int hf_smb2_close_flags = -1; static int hf_smb2_notify_flags = -1; static int hf_smb2_last_access_timestamp = -1; static int hf_smb2_last_write_timestamp = -1; static int hf_smb2_last_change_timestamp = -1; static int hf_smb2_current_time = -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_file_id = -1; static int hf_smb2_allocation_size = -1; static int hf_smb2_end_of_file = -1; static int hf_smb2_tree = -1; static int hf_smb2_find_pattern = -1; static int hf_smb2_find_info_level = -1; static int hf_smb2_find_info_blob = -1; static int hf_smb2_client_guid = -1; static int hf_smb2_server_guid = -1; static int hf_smb2_object_id = -1; static int hf_smb2_birth_volume_id = -1; static int hf_smb2_birth_object_id = -1; static int hf_smb2_domain_id = -1; static int hf_smb2_class = -1; static int hf_smb2_infolevel = -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_flags = -1; static int hf_smb2_required_buffer_size = -1; static int hf_smb2_getinfo_input_size = -1; static int hf_smb2_getinfo_input_offset = -1; static int hf_smb2_getinfo_additional = -1; static int hf_smb2_getinfo_flags = -1; static int hf_smb2_setinfo_size = -1; static int hf_smb2_setinfo_offset = -1; static int hf_smb2_file_basic_info = -1; static int hf_smb2_file_standard_info = -1; static int hf_smb2_file_internal_info = -1; static int hf_smb2_file_ea_info = -1; static int hf_smb2_file_access_info = -1; static int hf_smb2_file_rename_info = -1; static int hf_smb2_file_disposition_info = -1; static int hf_smb2_file_position_info = -1; static int hf_smb2_file_full_ea_info = -1; static int hf_smb2_file_mode_info = -1; static int hf_smb2_file_alignment_info = -1; static int hf_smb2_file_all_info = -1; static int hf_smb2_file_allocation_info = -1; static int hf_smb2_file_endoffile_info = -1; static int hf_smb2_file_alternate_name_info = -1; static int hf_smb2_file_stream_info = -1; static int hf_smb2_file_pipe_info = -1; static int hf_smb2_file_compression_info = -1; static int hf_smb2_file_network_open_info = -1; static int hf_smb2_file_attribute_tag_info = -1; static int hf_smb2_fs_info_01 = -1; static int hf_smb2_fs_info_03 = -1; static int hf_smb2_fs_info_04 = -1; static int hf_smb2_fs_info_05 = -1; static int hf_smb2_fs_info_06 = -1; static int hf_smb2_fs_info_07 = -1; static int hf_smb2_fs_objectid_info = -1; static int hf_smb2_sec_info_00 = -1; static int hf_smb2_quota_info = -1; static int hf_smb2_query_quota_info = -1; static int hf_smb2_qq_single = -1; static int hf_smb2_qq_restart = -1; static int hf_smb2_qq_sidlist_len = -1; static int hf_smb2_qq_start_sid_len = -1; static int hf_smb2_qq_start_sid_offset = -1; static int hf_smb2_fid = -1; static int hf_smb2_write_length = -1; static int hf_smb2_write_data = -1; static int hf_smb2_write_flags = -1; static int hf_smb2_write_flags_write_through = -1; static int hf_smb2_write_count = -1; static int hf_smb2_write_remaining = -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_chain_offset = -1; static int hf_smb2_create_chain_data = -1; static int hf_smb2_data_offset = -1; static int hf_smb2_extrainfo = -1; static int hf_smb2_create_action = -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_hash_alg_count = -1; static int hf_smb2_hash_algorithm = -1; static int hf_smb2_salt_length = -1; static int hf_smb2_salt = -1; static int hf_smb2_cipher_count = -1; static int hf_smb2_cipher_id = -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_ea_data_len = -1; static int hf_smb2_ea_name = -1; static int hf_smb2_ea_data = -1; static int hf_smb2_position_information = -1; static int hf_smb2_mode_information = -1; static int hf_smb2_mode_file_write_through = -1; static int hf_smb2_mode_file_sequential_only = -1; static int hf_smb2_mode_file_no_intermediate_buffering = -1; static int hf_smb2_mode_file_synchronous_io_alert = -1; static int hf_smb2_mode_file_synchronous_io_nonalert = -1; static int hf_smb2_mode_file_delete_on_close = -1; static int hf_smb2_alignment_information = -1; static int hf_smb2_buffer_code = -1; static int hf_smb2_buffer_code_len = -1; static int hf_smb2_buffer_code_flags_dyn = -1; static int hf_smb2_olb_offset = -1; static int hf_smb2_olb_length = -1; static int hf_smb2_tag = -1; static int hf_smb2_impersonation_level = -1; static int hf_smb2_ioctl_function = -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_shared_virtual_disk_support = -1; static int hf_smb2_ioctl_shared_virtual_disk_handle_state = -1; static int hf_smb2_ioctl_sqos_protocol_version = -1; static int hf_smb2_ioctl_sqos_reserved = -1; static int hf_smb2_ioctl_sqos_options = -1; static int hf_smb2_ioctl_sqos_op_set_logical_flow_id = -1; static int hf_smb2_ioctl_sqos_op_set_policy = -1; static int hf_smb2_ioctl_sqos_op_probe_policy = -1; static int hf_smb2_ioctl_sqos_op_get_status = -1; static int hf_smb2_ioctl_sqos_op_update_counters = -1; static int hf_smb2_ioctl_sqos_logical_flow_id = -1; static int hf_smb2_ioctl_sqos_policy_id = -1; static int hf_smb2_ioctl_sqos_initiator_id = -1; static int hf_smb2_ioctl_sqos_limit = -1; static int hf_smb2_ioctl_sqos_reservation = -1; static int hf_smb2_ioctl_sqos_initiator_name = -1; static int hf_smb2_ioctl_sqos_initiator_node_name = -1; static int hf_smb2_ioctl_sqos_io_count_increment = -1; static int hf_smb2_ioctl_sqos_normalized_io_count_increment = -1; static int hf_smb2_ioctl_sqos_latency_increment = -1; static int hf_smb2_ioctl_sqos_lower_latency_increment = -1; static int hf_smb2_ioctl_sqos_bandwidth_limit = -1; static int hf_smb2_ioctl_sqos_kilobyte_count_increment = -1; static int hf_smb2_ioctl_sqos_time_to_live = -1; static int hf_smb2_ioctl_sqos_status = -1; static int hf_smb2_ioctl_sqos_maximum_io_rate = -1; static int hf_smb2_ioctl_sqos_minimum_io_rate = -1; static int hf_smb2_ioctl_sqos_base_io_size = -1; static int hf_smb2_ioctl_sqos_reserved2 = -1; static int hf_smb2_ioctl_sqos_maximum_bandwidth = -1; static int hf_windows_sockaddr_family = -1; static int hf_windows_sockaddr_port = -1; static int hf_windows_sockaddr_in_addr = -1; static int hf_windows_sockaddr_in6_flowinfo = -1; static int hf_windows_sockaddr_in6_addr = -1; static int hf_windows_sockaddr_in6_scope_id = -1; static int hf_smb2_ioctl_network_interface_next_offset = -1; static int hf_smb2_ioctl_network_interface_index = -1; static int hf_smb2_ioctl_network_interface_rss_queue_count = -1; static int hf_smb2_ioctl_network_interface_capabilities = -1; static int hf_smb2_ioctl_network_interface_capability_rss = -1; static int hf_smb2_ioctl_network_interface_capability_rdma = -1; static int hf_smb2_ioctl_network_interface_link_speed = -1; static int hf_smb2_ioctl_shadow_copy_num_volumes = -1; static int hf_smb2_ioctl_shadow_copy_num_labels = -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_state_read_caching = -1; static int hf_smb2_lease_state_handle_caching = -1; static int hf_smb2_lease_state_write_caching = -1; static int hf_smb2_lease_flags = -1; static int hf_smb2_lease_flags_break_ack_required = -1; static int hf_smb2_lease_flags_parent_lease_key_set = -1; static int hf_smb2_lease_flags_break_in_progress = -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_acct_name = -1; static int hf_smb2_domain_name = -1; static int hf_smb2_host_name = -1; static int hf_smb2_auth_frame = -1; static int hf_smb2_tcon_frame = -1; static int hf_smb2_share_type = -1; static int hf_smb2_signature = -1; static int hf_smb2_credit_charge = -1; static int hf_smb2_credits_requested = -1; static int hf_smb2_credits_granted = -1; static int hf_smb2_channel_sequence = -1; static int hf_smb2_dialect_count = -1; static int hf_smb2_security_mode = -1; static int hf_smb2_secmode_flags_sign_required = -1; static int hf_smb2_secmode_flags_sign_enabled = -1; static int hf_smb2_ses_req_flags = -1; static int hf_smb2_ses_req_flags_session_binding = -1; static int hf_smb2_capabilities = -1; static int hf_smb2_cap_dfs = -1; static int hf_smb2_cap_leasing = -1; static int hf_smb2_cap_large_mtu = -1; static int hf_smb2_cap_multi_channel = -1; static int hf_smb2_cap_persistent_handles = -1; static int hf_smb2_cap_directory_leasing = -1; static int hf_smb2_cap_encryption = -1; static int hf_smb2_dialect = -1; static int hf_smb2_max_trans_size = -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_ses_flags_encrypt = -1; static int hf_smb2_share_flags = -1; static int hf_smb2_share_flags_dfs = -1; static int hf_smb2_share_flags_dfs_root = -1; static int hf_smb2_share_flags_restrict_exclusive_opens = -1; static int hf_smb2_share_flags_force_shared_delete = -1; static int hf_smb2_share_flags_allow_namespace_caching = -1; static int hf_smb2_share_flags_access_based_dir_enum = -1; static int hf_smb2_share_flags_force_levelii_oplock = -1; static int hf_smb2_share_flags_enable_hash_v1 = -1; static int hf_smb2_share_flags_enable_hash_v2 = -1; static int hf_smb2_share_flags_encrypt_data = -1; static int hf_smb2_share_caching = -1; static int hf_smb2_share_caps = -1; static int hf_smb2_share_caps_dfs = -1; static int hf_smb2_share_caps_continuous_availability = -1; static int hf_smb2_share_caps_scaleout = -1; static int hf_smb2_share_caps_cluster = -1; static int hf_smb2_create_flags = -1; static int hf_smb2_lock_count = -1; static int hf_smb2_min_count = -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_find_flags_index_specified = -1; static int hf_smb2_find_flags_reopen = -1; static int hf_smb2_file_index = -1; static int hf_smb2_file_directory_info = -1; static int hf_smb2_both_directory_info = -1; static int hf_smb2_short_name_len = -1; static int hf_smb2_short_name = -1; static int hf_smb2_id_both_directory_info = -1; static int hf_smb2_full_directory_info = -1; static int hf_smb2_lock_info = -1; static int hf_smb2_lock_length = -1; static int hf_smb2_lock_flags = -1; static int hf_smb2_lock_flags_shared = -1; static int hf_smb2_lock_flags_exclusive = -1; static int hf_smb2_lock_flags_unlock = -1; static int hf_smb2_lock_flags_fail_immediately = -1; static int hf_smb2_dhnq_buffer_reserved = -1; static int hf_smb2_dh2x_buffer_timeout = -1; static int hf_smb2_dh2x_buffer_flags = -1; static int hf_smb2_dh2x_buffer_flags_persistent_handle = -1; static int hf_smb2_dh2x_buffer_reserved = -1; static int hf_smb2_dh2x_buffer_create_guid = -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_svhdx_open_device_context_virtual_disk_properties_initialized = -1; static int hf_smb2_svhdx_open_device_context_server_service_version = -1; static int hf_smb2_svhdx_open_device_context_virtual_sector_size = -1; static int hf_smb2_svhdx_open_device_context_physical_sector_size = -1; static int hf_smb2_svhdx_open_device_context_virtual_size = -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_context_count = -1; static int hf_smb2_error_reserved = -1; static int hf_smb2_error_byte_count = -1; static int hf_smb2_error_data = -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_transform_reserved = -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 int hf_smb2_symlink_error_response = -1; static int hf_smb2_symlink_length = -1; static int hf_smb2_symlink_error_tag = -1; static int hf_smb2_SYMBOLIC_LINK_REPARSE_DATA_BUFFER = -1; static int hf_smb2_reparse_tag = -1; static int hf_smb2_reparse_data_length = -1; static int hf_smb2_unparsed_path_length = -1; static int hf_smb2_symlink_substitute_name = -1; static int hf_smb2_symlink_print_name = -1; static int hf_smb2_symlink_flags = -1; static gint ett_smb2 = -1; static gint ett_smb2_olb = -1; static gint ett_smb2_ea = -1; static gint ett_smb2_header = -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_file_ea_info = -1; static gint ett_smb2_file_access_info = -1; static gint ett_smb2_file_position_info = -1; static gint ett_smb2_file_mode_info = -1; static gint ett_smb2_file_alignment_info = -1; static gint ett_smb2_file_all_info = -1; static gint ett_smb2_file_allocation_info = -1; static gint ett_smb2_file_endoffile_info = -1; static gint ett_smb2_file_alternate_name_info = -1; static gint ett_smb2_file_stream_info = -1; static gint ett_smb2_file_pipe_info = -1; static gint ett_smb2_file_compression_info = -1; static gint ett_smb2_file_network_open_info = -1; static gint ett_smb2_file_attribute_tag_info = -1; static gint ett_smb2_file_rename_info = -1; static gint ett_smb2_file_disposition_info = -1; static gint ett_smb2_file_full_ea_info = -1; static gint ett_smb2_fs_info_01 = -1; static gint ett_smb2_fs_info_03 = -1; static gint ett_smb2_fs_info_04 = -1; static gint ett_smb2_fs_info_05 = -1; static gint ett_smb2_fs_info_06 = -1; static gint ett_smb2_fs_info_07 = -1; static gint ett_smb2_fs_objectid_info = -1; static gint ett_smb2_sec_info_00 = -1; static gint ett_smb2_quota_info = -1; static gint ett_smb2_query_quota_info = -1; static gint ett_smb2_tid_tree = -1; static gint ett_smb2_sesid_tree = -1; static gint ett_smb2_create_chain_element = -1; static gint ett_smb2_MxAc_buffer = -1; static gint ett_smb2_QFid_buffer = -1; static gint ett_smb2_RqLs_buffer = -1; static gint ett_smb2_ioctl_function = -1; static gint ett_smb2_FILE_OBJECTID_BUFFER = -1; static gint ett_smb2_flags = -1; static gint ett_smb2_sec_mode = -1; static gint ett_smb2_capabilities = -1; static gint ett_smb2_ses_req_flags = -1; static gint ett_smb2_ses_flags = -1; static gint ett_smb2_lease_state = -1; static gint ett_smb2_lease_flags = -1; static gint ett_smb2_share_flags = -1; static gint ett_smb2_create_rep_flags = -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_ioctl_sqos_opeations = -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_id_both_directory_info = -1; static gint ett_smb2_full_directory_info = -1; static gint ett_smb2_file_name_info = -1; static gint ett_smb2_lock_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 gint ett_smb2_symlink_error_response = -1; static gint ett_smb2_SYMBOLIC_LINK_REPARSE_DATA_BUFFER = -1; static gint ett_smb2_error_data = -1; static expert_field ei_smb2_invalid_length = EI_INIT; static expert_field ei_smb2_bad_response = EI_INIT; static expert_field ei_smb2_invalid_getinfo_offset = EI_INIT; static expert_field ei_smb2_invalid_getinfo_size = EI_INIT; static expert_field ei_smb2_empty_getinfo_buffer = 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 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 FILE_BYTE_ALIGNMENT 0x00 #define FILE_WORD_ALIGNMENT 0x01 #define FILE_LONG_ALIGNMENT 0x03 #define FILE_QUAD_ALIGNMENT 0x07 #define FILE_OCTA_ALIGNMENT 0x0f #define FILE_32_BYTE_ALIGNMENT 0x1f #define FILE_64_BYTE_ALIGNMENT 0x3f #define FILE_128_BYTE_ALIGNMENT 0x7f #define FILE_256_BYTE_ALIGNMENT 0xff #define FILE_512_BYTE_ALIGNMENT 0x1ff static const value_string smb2_alignment_vals[] = { { FILE_BYTE_ALIGNMENT, "FILE_BYTE_ALIGNMENT" }, { FILE_WORD_ALIGNMENT, "FILE_WORD_ALIGNMENT" }, { FILE_LONG_ALIGNMENT, "FILE_LONG_ALIGNMENT" }, { FILE_OCTA_ALIGNMENT, "FILE_OCTA_ALIGNMENT" }, { FILE_32_BYTE_ALIGNMENT, "FILE_32_BYTE_ALIGNMENT" }, { FILE_64_BYTE_ALIGNMENT, "FILE_64_BYTE_ALIGNMENT" }, { FILE_128_BYTE_ALIGNMENT, "FILE_128_BYTE_ALIGNMENT" }, { FILE_256_BYTE_ALIGNMENT, "FILE_256_BYTE_ALIGNMENT" }, { FILE_512_BYTE_ALIGNMENT, "FILE_512_BYTE_ALIGNMENT" }, { 0, NULL } }; #define SMB2_CLASS_FILE_INFO 0x01 #define SMB2_CLASS_FS_INFO 0x02 #define SMB2_CLASS_SEC_INFO 0x03 #define SMB2_CLASS_QUOTA_INFO 0x04 #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_QUOTA_INFO, "QUOTA_INFO"}, { SMB2_CLASS_POSIX_INFO, "POSIX_INFO"}, { 0, NULL } }; #define SMB2_SHARE_TYPE_DISK 0x01 #define SMB2_SHARE_TYPE_PIPE 0x02 #define SMB2_SHARE_TYPE_PRINT 0x03 static const value_string smb2_share_type_vals[] = { { SMB2_SHARE_TYPE_DISK, "Physical disk" }, { SMB2_SHARE_TYPE_PIPE, "Named pipe" }, { SMB2_SHARE_TYPE_PRINT, "Printer" }, { 0, NULL } }; #define SMB2_FILE_BASIC_INFO 0x04 #define SMB2_FILE_STANDARD_INFO 0x05 #define SMB2_FILE_INTERNAL_INFO 0x06 #define SMB2_FILE_EA_INFO 0x07 #define SMB2_FILE_ACCESS_INFO 0x08 #define SMB2_FILE_RENAME_INFO 0x0a #define SMB2_FILE_DISPOSITION_INFO 0x0d #define SMB2_FILE_POSITION_INFO 0x0e #define SMB2_FILE_FULL_EA_INFO 0x0f #define SMB2_FILE_MODE_INFO 0x10 #define SMB2_FILE_ALIGNMENT_INFO 0x11 #define SMB2_FILE_ALL_INFO 0x12 #define SMB2_FILE_ALLOCATION_INFO 0x13 #define SMB2_FILE_ENDOFFILE_INFO 0x14 #define SMB2_FILE_ALTERNATE_NAME_INFO 0x15 #define SMB2_FILE_STREAM_INFO 0x16 #define SMB2_FILE_PIPE_INFO 0x17 #define SMB2_FILE_COMPRESSION_INFO 0x1c #define SMB2_FILE_NETWORK_OPEN_INFO 0x22 #define SMB2_FILE_ATTRIBUTE_TAG_INFO 0x23 static const value_string smb2_file_info_levels[] = { {SMB2_FILE_BASIC_INFO, "SMB2_FILE_BASIC_INFO" }, {SMB2_FILE_STANDARD_INFO, "SMB2_FILE_STANDARD_INFO" }, {SMB2_FILE_INTERNAL_INFO, "SMB2_FILE_INTERNAL_INFO" }, {SMB2_FILE_EA_INFO, "SMB2_FILE_EA_INFO" }, {SMB2_FILE_ACCESS_INFO, "SMB2_FILE_ACCESS_INFO" }, {SMB2_FILE_RENAME_INFO, "SMB2_FILE_RENAME_INFO" }, {SMB2_FILE_DISPOSITION_INFO, "SMB2_FILE_DISPOSITION_INFO" }, {SMB2_FILE_POSITION_INFO, "SMB2_FILE_POSITION_INFO" }, {SMB2_FILE_FULL_EA_INFO, "SMB2_FILE_FULL_EA_INFO" }, {SMB2_FILE_MODE_INFO, "SMB2_FILE_MODE_INFO" }, {SMB2_FILE_ALIGNMENT_INFO, "SMB2_FILE_ALIGNMENT_INFO" }, {SMB2_FILE_ALL_INFO, "SMB2_FILE_ALL_INFO" }, {SMB2_FILE_ALLOCATION_INFO, "SMB2_FILE_ALLOCATION_INFO" }, {SMB2_FILE_ENDOFFILE_INFO, "SMB2_FILE_ENDOFFILE_INFO" }, {SMB2_FILE_ALTERNATE_NAME_INFO, "SMB2_FILE_ALTERNATE_NAME_INFO" }, {SMB2_FILE_STREAM_INFO, "SMB2_FILE_STREAM_INFO" }, {SMB2_FILE_PIPE_INFO, "SMB2_FILE_PIPE_INFO" }, {SMB2_FILE_COMPRESSION_INFO, "SMB2_FILE_COMPRESSION_INFO" }, {SMB2_FILE_NETWORK_OPEN_INFO, "SMB2_FILE_NETWORK_OPEN_INFO" }, {SMB2_FILE_ATTRIBUTE_TAG_INFO, "SMB2_FILE_ATTRIBUTE_TAG_INFO" }, { 0, NULL } }; static value_string_ext smb2_file_info_levels_ext = VALUE_STRING_EXT_INIT(smb2_file_info_levels); #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, "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); #define SMB2_SEC_INFO_00 0x00 static const value_string smb2_sec_info_levels[] = { {SMB2_SEC_INFO_00, "SMB2_SEC_INFO_00" }, { 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 #define SMB2_FIND_INDEX_SPECIFIED 0x04 #define SMB2_FIND_NAME_INFO 0x0C #define SMB2_FIND_ID_BOTH_DIRECTORY_INFO 0x25 #define SMB2_FIND_ID_FULL_DIRECTORY_INFO 0x26 static const value_string smb2_find_info_levels[] = { { SMB2_FIND_DIRECTORY_INFO, "SMB2_FIND_DIRECTORY_INFO" }, { SMB2_FIND_FULL_DIRECTORY_INFO, "SMB2_FIND_FULL_DIRECTORY_INFO" }, { SMB2_FIND_BOTH_DIRECTORY_INFO, "SMB2_FIND_BOTH_DIRECTORY_INFO" }, { SMB2_FIND_INDEX_SPECIFIED, "SMB2_FIND_INDEX_SPECIFIED" }, { SMB2_FIND_NAME_INFO, "SMB2_FIND_NAME_INFO" }, { SMB2_FIND_ID_BOTH_DIRECTORY_INFO, "SMB2_FIND_ID_BOTH_DIRECTORY_INFO" }, { SMB2_FIND_ID_FULL_DIRECTORY_INFO, "SMB2_FIND_ID_FULL_DIRECTORY_INFO" }, { 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_HASH_ALGORITHM_SHA_512 0x0001 static const value_string smb2_hash_algorithm_types[] = { { SMB2_HASH_ALGORITHM_SHA_512, "SHA-512" }, { 0, NULL } }; #define SMB2_CIPHER_AES_128_CCM 0x0001 #define SMB2_CIPHER_AES_128_GCM 0x0002 static const value_string smb2_cipher_types[] = { { SMB2_CIPHER_AES_128_CCM, "AES-128-CCM" }, { SMB2_CIPHER_AES_128_GCM, "AES-128-GCM" }, { 0, NULL } }; static const val64_string unique_unsolicited_response[] = { { 0xffffffffffffffff, "unsolicited response" }, { 0, NULL } }; #define SMB2_NUM_PROCEDURES 256 static void smb2stat_init(struct register_srt* srt _U_, GArray* srt_array) { srt_stat_table *smb2_srt_table; guint32 i; smb2_srt_table = init_srt_table("SMB2", NULL, srt_array, SMB2_NUM_PROCEDURES, "Commands", "smb2.cmd", 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, "")); } } static tap_packet_status 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 TAP_PACKET_DONT_REDRAW; } /* We should not include cancel and oplock break requests either */ if (si->opcode == SMB2_COM_CANCEL || si->opcode == SMB2_COM_BREAK) { return TAP_PACKET_DONT_REDRAW; } /* if we haven't seen the request, just ignore it */ if(!si->saved){ return TAP_PACKET_DONT_REDRAW; } /* 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 TAP_PACKET_DONT_REDRAW; 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 TAP_PACKET_REDRAW; } /* Structure for SessionID <=> SessionKey mapping for decryption. */ typedef struct _smb2_seskey_field_t { guchar *id; guint id_len; guchar *key; guint key_len; } smb2_seskey_field_t; static smb2_seskey_field_t *seskey_list = NULL; static guint num_seskey_list = 0; static const gint8 zeros[NTLMSSP_KEY_LEN] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* Callbacks for SessionID <=> SessionKey mapping. */ UAT_BUFFER_CB_DEF(seskey_list, id, smb2_seskey_field_t, id, id_len) UAT_BUFFER_CB_DEF(seskey_list, key, smb2_seskey_field_t, key, key_len) #define SMB_SESSION_ID_SIZE 8 static gboolean seskey_list_update_cb(void *r, char **err) { smb2_seskey_field_t *rec = (smb2_seskey_field_t *)r; *err = NULL; if (rec->id_len != SMB_SESSION_ID_SIZE) { *err = g_strdup("Session ID must be " G_STRINGIFY(SMB_SESSION_ID_SIZE) " bytes long and in hexadecimal"); return FALSE; } if (rec->key_len == 0 || rec->key_len > NTLMSSP_KEY_LEN) { *err = g_strdup("Session Key must be a non-empty hexadecimal string representing at most " G_STRINGIFY(NTLMSSP_KEY_LEN) " bytes"); return FALSE; } return TRUE; } static void* seskey_list_copy_cb(void *n, const void *o, size_t siz _U_) { smb2_seskey_field_t *new_rec = (smb2_seskey_field_t *)n; const smb2_seskey_field_t *old_rec = (const smb2_seskey_field_t *)o; new_rec->id_len = old_rec->id_len; new_rec->id = old_rec->id ? (guchar *)g_memdup(old_rec->id, old_rec->id_len) : NULL; new_rec->key_len = old_rec->key_len; new_rec->key = old_rec->key ? (guchar *)g_memdup(old_rec->key, old_rec->key_len) : NULL; return new_rec; } static void seskey_list_free_cb(void *r) { smb2_seskey_field_t *rec = (smb2_seskey_field_t *)r; g_free(rec->id); g_free(rec->key); } static gboolean seskey_find_sid_key(guint64 sesid, guint8 *out_key) { guint i; for (i = 0; i < num_seskey_list; i++) { const smb2_seskey_field_t *p = &seskey_list[i]; if (memcmp(&sesid, p->id, SMB_SESSION_ID_SIZE) == 0) { memset(out_key, 0, NTLMSSP_KEY_LEN); memcpy(out_key, p->key, p->key_len); return TRUE; } } return FALSE; } /* ExportObject preferences variable */ gboolean eosmb2_take_name_as_fid = FALSE ; /* unmatched smb_saved_info structures. For unmatched smb_saved_info structures we store the smb_saved_info structure using the msg_id field. */ static gint smb2_saved_info_equal_unmatched(gconstpointer k1, gconstpointer k2) { const smb2_saved_info_t *key1 = (const smb2_saved_info_t *)k1; const smb2_saved_info_t *key2 = (const smb2_saved_info_t *)k2; return key1->msg_id == key2->msg_id; } static guint smb2_saved_info_hash_unmatched(gconstpointer k) { const smb2_saved_info_t *key = (const smb2_saved_info_t *)k; guint32 hash; hash = (guint32) (key->msg_id&0xffffffff); return hash; } /* matched smb_saved_info structures. For matched smb_saved_info structures we store the smb_saved_info structure using the msg_id field. */ static gint smb2_saved_info_equal_matched(gconstpointer k1, gconstpointer k2) { const smb2_saved_info_t *key1 = (const smb2_saved_info_t *)k1; const smb2_saved_info_t *key2 = (const smb2_saved_info_t *)k2; return key1->msg_id == key2->msg_id; } static guint smb2_saved_info_hash_matched(gconstpointer k) { const smb2_saved_info_t *key = (const smb2_saved_info_t *)k; guint32 hash; hash = (guint32) (key->msg_id&0xffffffff); return hash; } /* For Tids of a specific conversation. This keeps track of tid->sharename mappings and other information about the tid. qqq We might need to refine this if it occurs that tids are reused on a single conversation. we don't worry about that yet for simplicity */ static gint smb2_tid_info_equal(gconstpointer k1, gconstpointer k2) { const smb2_tid_info_t *key1 = (const smb2_tid_info_t *)k1; const smb2_tid_info_t *key2 = (const smb2_tid_info_t *)k2; return key1->tid == key2->tid; } static guint smb2_tid_info_hash(gconstpointer k) { const smb2_tid_info_t *key = (const smb2_tid_info_t *)k; guint32 hash; hash = key->tid; return hash; } /* For Uids of a specific conversation. This keeps track of uid->acct_name mappings and other information about the uid. qqq We might need to refine this if it occurs that uids are reused on a single conversation. we don't worry about that yet for simplicity */ static gint smb2_sesid_info_equal(gconstpointer k1, gconstpointer k2) { const smb2_sesid_info_t *key1 = (const smb2_sesid_info_t *)k1; const smb2_sesid_info_t *key2 = (const smb2_sesid_info_t *)k2; return key1->sesid == key2->sesid; } static guint smb2_sesid_info_hash(gconstpointer k) { const smb2_sesid_info_t *key = (const smb2_sesid_info_t *)k; guint32 hash; hash = (guint32)( ((key->sesid>>32)&0xffffffff)+((key->sesid)&0xffffffff) ); 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 smb2_conv_destroy(wmem_allocator_t *allocator _U_, wmem_cb_event_t event _U_, void *user_data) { smb2_conv_info_t *conv = (smb2_conv_info_t *)user_data; 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 conversation is gone, return FALSE to indicate we don't * want to be called again for this conversation. */ return FALSE; } static void smb2_key_derivation(const guint8 *KI, guint32 KI_len, const guint8 *Label, guint32 Label_len, const guint8 *Context, guint32 Context_len, guint8 KO[16]) { gcry_md_hd_t hd = NULL; guint8 buf[4]; guint8 *digest = NULL; /* * a simplified version of * "NIST Special Publication 800-108" section 5.1 * using hmac-sha256. */ gcry_md_open(&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); gcry_md_setkey(hd, KI, KI_len); memset(buf, 0, sizeof(buf)); buf[3] = 1; gcry_md_write(hd, buf, sizeof(buf)); gcry_md_write(hd, Label, Label_len); gcry_md_write(hd, buf, 1); gcry_md_write(hd, Context, Context_len); buf[3] = 128; gcry_md_write(hd, buf, sizeof(buf)); digest = gcry_md_read(hd, GCRY_MD_SHA256); memcpy(KO, digest, 16); gcry_md_close(hd); } /* for export-object-smb2 */ static gchar *policy_hnd_to_file_id(const e_ctx_hnd *hnd) { 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]); return file_id; } static guint smb2_eo_files_hash(gconstpointer k) { return g_str_hash(policy_hnd_to_file_id((const e_ctx_hnd *)k)); } static gint smb2_eo_files_equal(gconstpointer k1, gconstpointer k2) { int are_equal; 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]); return are_equal; } static void feed_eo_smb2(tvbuff_t * tvb,packet_info *pinfo,smb2_info_t * si, guint16 dataoffset,guint32 length, guint64 file_offset) { char *fid_name = NULL; guint32 open_frame = 0, close_frame = 0; tvbuff_t *data_tvb = NULL; smb_eo_t *eo_info; gchar *file_id; gchar *auxstring; gchar **aux_string_v; /* Create a new tvb to point to the payload data */ 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 */ eo_info->smbversion=2; /* cmd == opcode */ eo_info->cmd=si->opcode; /* We don't keep track of uid in SMB v2 */ eo_info->uid=0; /* 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->num); if (fid_name && g_strcmp0(fid_name,"File: ")!=0) { auxstring=fid_name; /* Remove "File: " from filename */ if (g_str_has_prefix(auxstring, "File: ")) { aux_string_v = g_strsplit(auxstring, "File: ", -1); eo_info->filename = wmem_strdup_printf(wmem_packet_scope(), "\\%s",aux_string_v[g_strv_length(aux_string_v)-1]); g_strfreev(aux_string_v); } else { if (g_str_has_prefix(auxstring, "\\")) { eo_info->filename = wmem_strdup(wmem_packet_scope(), auxstring); } else { eo_info->filename = wmem_strdup_printf(wmem_packet_scope(), "\\%s",auxstring); } } } else { auxstring=wmem_strdup_printf(wmem_packet_scope(), "File_Id_%s", file_id); eo_info->filename=auxstring; } if (eosmb2_take_name_as_fid) { eo_info->fid = g_str_hash(eo_info->filename); } else { eo_info->fid = g_str_hash(file_id); } /* tid, hostname, tree_id */ if (si->tree) { eo_info->tid=si->tree->tid; if (strlen(si->tree->name)>0 && strlen(si->tree->name)<=256) { eo_info->hostname = wmem_strdup(wmem_packet_scope(), si->tree->name); } else { eo_info->hostname = wmem_strdup_printf(wmem_packet_scope(), "\\\\%s\\TREEID_%i",tree_ip_str(pinfo,si->opcode),si->tree->tid); } } else { eo_info->tid=0; eo_info->hostname = wmem_strdup_printf(wmem_packet_scope(), "\\\\%s\\TREEID_UNKNOWN",tree_ip_str(pinfo,si->opcode)); } /* packet number */ eo_info->pkt_num = pinfo->num; /* fid type */ if (si->eo_file_info->attr_mask & SMB2_FLAGS_ATTR_DIRECTORY) { eo_info->fid_type=SMB2_FID_TYPE_DIR; } else { if (si->eo_file_info->attr_mask & (SMB2_FLAGS_ATTR_ARCHIVE | SMB2_FLAGS_ATTR_NORMAL | SMB2_FLAGS_ATTR_HIDDEN | SMB2_FLAGS_ATTR_READONLY | SMB2_FLAGS_ATTR_SYSTEM) ) { eo_info->fid_type=SMB2_FID_TYPE_FILE; } else { eo_info->fid_type=SMB2_FID_TYPE_OTHER; } } /* end_of_file */ eo_info->end_of_file=si->eo_file_info->end_of_file; /* data offset and chunk length */ eo_info->smb_file_offset=file_offset; eo_info->smb_chunk_len=length; /* XXX is this right? */ if (lengthsaved->bytes_moved) { si->saved->file_offset=si->saved->file_offset+length; si->saved->bytes_moved=si->saved->bytes_moved-length; } /* Payload */ eo_info->payload_len = length; eo_info->payload_data = tvb_get_ptr(data_tvb, 0, length); tap_queue_packet(smb2_eo_tap, pinfo, eo_info); } static int dissect_smb2_file_full_ea_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, smb2_info_t *si); /* This is a helper to dissect the common string type * uint16 offset * uint16 length * ... * char *string * * 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 don't * want to abort dissection too early if the packet ends somewhere between the * length/offset and the actual buffer. * */ enum offset_length_buffer_offset_size { OLB_O_UINT16_S_UINT16, OLB_O_UINT16_S_UINT32, OLB_O_UINT32_S_UINT32, OLB_S_UINT32_O_UINT32 }; typedef struct _offset_length_buffer_t { guint32 off; guint32 len; int off_offset; int len_offset; enum offset_length_buffer_offset_size offset_size; int hfindex; } offset_length_buffer_t; static int dissect_smb2_olb_length_offset(tvbuff_t *tvb, int offset, offset_length_buffer_t *olb, enum offset_length_buffer_offset_size offset_size, int hfindex) { olb->hfindex = hfindex; olb->offset_size = offset_size; switch (offset_size) { case OLB_O_UINT16_S_UINT16: olb->off = tvb_get_letohs(tvb, offset); olb->off_offset = offset; offset += 2; olb->len = tvb_get_letohs(tvb, offset); olb->len_offset = offset; offset += 2; break; case OLB_O_UINT16_S_UINT32: olb->off = tvb_get_letohs(tvb, offset); olb->off_offset = offset; offset += 2; olb->len = tvb_get_letohl(tvb, offset); olb->len_offset = offset; offset += 4; break; case OLB_O_UINT32_S_UINT32: olb->off = tvb_get_letohl(tvb, offset); olb->off_offset = offset; offset += 4; olb->len = tvb_get_letohl(tvb, offset); olb->len_offset = offset; offset += 4; break; case OLB_S_UINT32_O_UINT32: olb->len = tvb_get_letohl(tvb, offset); olb->len_offset = offset; offset += 4; olb->off = tvb_get_letohl(tvb, offset); olb->off_offset = offset; offset += 4; break; } return offset; } #define OLB_TYPE_UNICODE_STRING 0x01 #define OLB_TYPE_ASCII_STRING 0x02 static const char * dissect_smb2_olb_off_string(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, offset_length_buffer_t *olb, int base, int type) { int len, off; proto_item *item = NULL; proto_tree *tree = NULL; const char *name = NULL; guint16 bc; int offset; olb->off += base; offset = olb->off; len = olb->len; off = olb->off; bc = tvb_captured_length_remaining(tvb, offset); /* sanity check */ tvb_ensure_bytes_exist(tvb, off, len); if (((off+len)(off+tvb_reported_length_remaining(tvb, off)))) { 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]"); return NULL; } switch (type) { case OLB_TYPE_UNICODE_STRING: name = get_unicode_or_ascii_string(tvb, &off, TRUE, &len, TRUE, TRUE, &bc); if (!name) { name = ""; } if (parent_tree) { item = proto_tree_add_string(parent_tree, olb->hfindex, tvb, offset, len, name); tree = proto_item_add_subtree(item, ett_smb2_olb); } break; case OLB_TYPE_ASCII_STRING: name = get_unicode_or_ascii_string(tvb, &off, FALSE, &len, TRUE, TRUE, &bc); if (!name) { name = ""; } if (parent_tree) { item = proto_tree_add_string(parent_tree, olb->hfindex, tvb, offset, len, name); tree = proto_item_add_subtree(item, ett_smb2_olb); } break; } switch (olb->offset_size) { case OLB_O_UINT16_S_UINT16: proto_tree_add_item(tree, hf_smb2_olb_offset, tvb, olb->off_offset, 2, ENC_LITTLE_ENDIAN); proto_tree_add_item(tree, hf_smb2_olb_length, tvb, olb->len_offset, 2, ENC_LITTLE_ENDIAN); break; case OLB_O_UINT16_S_UINT32: proto_tree_add_item(tree, hf_smb2_olb_offset, tvb, olb->off_offset, 2, ENC_LITTLE_ENDIAN); proto_tree_add_item(tree, hf_smb2_olb_length, tvb, olb->len_offset, 4, ENC_LITTLE_ENDIAN); break; case OLB_O_UINT32_S_UINT32: proto_tree_add_item(tree, hf_smb2_olb_offset, tvb, olb->off_offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(tree, hf_smb2_olb_length, tvb, olb->len_offset, 4, ENC_LITTLE_ENDIAN); break; case OLB_S_UINT32_O_UINT32: proto_tree_add_item(tree, hf_smb2_olb_length, tvb, olb->len_offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(tree, hf_smb2_olb_offset, tvb, olb->off_offset, 4, ENC_LITTLE_ENDIAN); break; } return name; } static const char * dissect_smb2_olb_string(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, offset_length_buffer_t *olb, int type) { return dissect_smb2_olb_off_string(pinfo, parent_tree, tvb, olb, 0, type); } static void dissect_smb2_olb_buffer(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, offset_length_buffer_t *olb, smb2_info_t *si, void (*dissector)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si)) { int len, off; proto_item *sub_item = NULL; proto_tree *sub_tree = NULL; tvbuff_t *sub_tvb = NULL; int offset; offset = olb->off; len = olb->len; off = olb->off; /* sanity check */ tvb_ensure_bytes_exist(tvb, off, len); if (((off+len)(off+tvb_reported_length_remaining(tvb, off)))) { 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; } switch (olb->offset_size) { case OLB_O_UINT16_S_UINT16: proto_tree_add_item(parent_tree, hf_smb2_olb_offset, tvb, olb->off_offset, 2, ENC_LITTLE_ENDIAN); proto_tree_add_item(parent_tree, hf_smb2_olb_length, tvb, olb->len_offset, 2, ENC_LITTLE_ENDIAN); break; case OLB_O_UINT16_S_UINT32: proto_tree_add_item(parent_tree, hf_smb2_olb_offset, tvb, olb->off_offset, 2, ENC_LITTLE_ENDIAN); proto_tree_add_item(parent_tree, hf_smb2_olb_length, tvb, olb->len_offset, 4, ENC_LITTLE_ENDIAN); break; case OLB_O_UINT32_S_UINT32: proto_tree_add_item(parent_tree, hf_smb2_olb_offset, tvb, olb->off_offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(parent_tree, hf_smb2_olb_length, tvb, olb->len_offset, 4, ENC_LITTLE_ENDIAN); break; case OLB_S_UINT32_O_UINT32: proto_tree_add_item(parent_tree, hf_smb2_olb_length, tvb, olb->len_offset, 4, ENC_LITTLE_ENDIAN); proto_tree_add_item(parent_tree, hf_smb2_olb_offset, tvb, olb->off_offset, 4, ENC_LITTLE_ENDIAN); break; } /* if we don't want/need a subtree */ if (olb->hfindex == -1) { sub_item = parent_tree; sub_tree = parent_tree; } else { if (parent_tree) { sub_item = proto_tree_add_item(parent_tree, olb->hfindex, tvb, offset, len, ENC_NA); sub_tree = proto_item_add_subtree(sub_item, ett_smb2_olb); } } if (off == 0 || len == 0) { proto_item_append_text(sub_item, ": NO DATA"); return; } if (!dissector) { return; } sub_tvb = tvb_new_subset_length_caplen(tvb, off, MIN((int)len, tvb_captured_length_remaining(tvb, off)), len); dissector(sub_tvb, pinfo, sub_tree, si); } static int dissect_smb2_olb_tvb_max_offset(int offset, offset_length_buffer_t *olb) { if (olb->off == 0) { return offset; } return MAX(offset, (int)(olb->off + olb->len)); } typedef struct _smb2_function { int (*request) (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *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" }; static const true_false_string tfs_flags_async_cmd = { "This is an ASYNC command", "This is a SYNC command" }; static const true_false_string tfs_flags_dfs_op = { "This is a DFS OPERATION", "This is a normal operation" }; static const true_false_string tfs_flags_chained = { "This pdu a CHAINED command", "This pdu is NOT a chained command" }; static const true_false_string tfs_flags_signature = { "This pdu is SIGNED", "This pdu is NOT signed" }; static const true_false_string tfs_flags_replay_operation = { "This is a REPLAY OPEARATION", "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" }; static const true_false_string tfs_cap_leasing = { "This host supports LEASING", "This host does NOT support LEASING" }; static const true_false_string tfs_cap_large_mtu = { "This host supports LARGE_MTU", "This host does NOT support LARGE_MTU" }; static const true_false_string tfs_cap_multi_channel = { "This host supports MULTI CHANNEL", "This host does NOT support MULTI CHANNEL" }; static const true_false_string tfs_cap_persistent_handles = { "This host supports PERSISTENT HANDLES", "This host does NOT support PERSISTENT HANDLES" }; static const true_false_string tfs_cap_directory_leasing = { "This host supports DIRECTORY LEASING", "This host does NOT support DIRECTORY LEASING" }; static const true_false_string tfs_cap_encryption = { "This host supports ENCRYPTION", "This host does NOT support ENCRYPTION" }; static const true_false_string tfs_smb2_ioctl_network_interface_capability_rss = { "This interface supports RSS", "This interface does not support RSS" }; static const true_false_string tfs_smb2_ioctl_network_interface_capability_rdma = { "This interface supports RDMA", "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" }, { 2, "COMPRESSION_FORMAT_LZNT1" }, { 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"}, {0x0009000C, "FSCTL_OPLOCK_BREAK_ACKNOWLEDGE"}, {0x00090010, "FSCTL_OPBATCH_ACK_CLOSE_PENDING"}, {0x00090014, "FSCTL_OPLOCK_BREAK_NOTIFY"}, {0x00090018, "FSCTL_LOCK_VOLUME"}, {0x0009001C, "FSCTL_UNLOCK_VOLUME"}, {0x00090020, "FSCTL_DISMOUNT_VOLUME"}, {0x00090028, "FSCTL_IS_VOLUME_MOUNTED"}, {0x0009002C, "FSCTL_IS_PATHNAME_VALID"}, {0x00090030, "FSCTL_MARK_VOLUME_DIRTY"}, {0x0009003B, "FSCTL_QUERY_RETRIEVAL_POINTERS"}, {0x0009003C, "FSCTL_GET_COMPRESSION"}, /* dissector implemented */ {0x0009004F, "FSCTL_MARK_AS_SYSTEM_HIVE"}, {0x00090050, "FSCTL_OPLOCK_BREAK_ACK_NO_2"}, {0x00090054, "FSCTL_INVALIDATE_VOLUMES"}, {0x00090058, "FSCTL_QUERY_FAT_BPB"}, {0x0009005C, "FSCTL_REQUEST_FILTER_OPLOCK"}, {0x00090060, "FSCTL_FILESYSTEM_GET_STATISTICS"}, {0x00090064, "FSCTL_GET_NTFS_VOLUME_DATA"}, {0x00090068, "FSCTL_GET_NTFS_FILE_RECORD"}, {0x0009006F, "FSCTL_GET_VOLUME_BITMAP"}, {0x00090073, "FSCTL_GET_RETRIEVAL_POINTERS"}, {0x00090074, "FSCTL_MOVE_FILE"}, {0x00090078, "FSCTL_IS_VOLUME_DIRTY"}, {0x0009007C, "FSCTL_GET_HFS_INFORMATION"}, {0x00090083, "FSCTL_ALLOW_EXTENDED_DASD_IO"}, {0x00090087, "FSCTL_READ_PROPERTY_DATA"}, {0x0009008B, "FSCTL_WRITE_PROPERTY_DATA"}, {0x0009008F, "FSCTL_FIND_FILES_BY_SID"}, {0x00090097, "FSCTL_DUMP_PROPERTY_DATA"}, {0x0009009C, "FSCTL_GET_OBJECT_ID"}, /* dissector implemented */ {0x000900A4, "FSCTL_SET_REPARSE_POINT"}, /* dissector implemented */ {0x000900A8, "FSCTL_GET_REPARSE_POINT"}, /* dissector implemented */ {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"}, {0x00090244, "FSCTL_CSV_TUNNEL_REQUEST"}, {0x0009027C, "FSCTL_GET_INTEGRITY_INFORMATION"}, {0x00090284, "FSCTL_QUERY_FILE_REGIONS"}, /* dissector implemented */ {0x000902c8, "FSCTL_CSV_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"}, {0x00090314, "FSCTL_DELETE_EXTERNAL_BACKING"}, {0x00090318, "FSCTL_ENUM_EXTERNAL_BACKING"}, {0x0009031F, "FSCTL_ENUM_OVERLAY"}, {0x00090350, "FSCTL_STORAGE_QOS_CONTROL"}, /* dissector implemented */ {0x00090364, "FSCTL_SVHDX_ASYNC_TUNNEL_REQUEST"}, /* dissector implemented */ {0x000940B3, "FSCTL_ENUM_USN_DATA"}, {0x000940B7, "FSCTL_SECURITY_ID_CHECK"}, {0x000940BB, "FSCTL_READ_USN_JOURNAL"}, {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 */ {0x000980A4, "FSCTL_SET_REPARSE_POINT"}, {0x000980AC, "FSCTL_DELETE_REPARSE_POINT"}, {0x000980BC, "FSCTL_SET_OBJECT_ID_EXTENDED"}, /* dissector implemented */ {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_SRV_ENUMERATE_SNAPSHOTS"}, /* dissector implemented */ {0x001440F2, "FSCTL_SRV_COPYCHUNK"}, {0x001441bb, "FSCTL_SRV_READ_HASH"}, {0x001480F2, "FSCTL_SRV_COPYCHUNK_WRITE"}, { 0, NULL } }; static value_string_ext smb2_ioctl_vals_ext = VALUE_STRING_EXT_INIT(smb2_ioctl_vals); static const value_string smb2_ioctl_device_vals[] = { { 0x0001, "BEEP" }, { 0x0002, "CD_ROM" }, { 0x0003, "CD_ROM_FILE_SYSTEM" }, { 0x0004, "CONTROLLER" }, { 0x0005, "DATALINK" }, { 0x0006, "DFS" }, { 0x0007, "DISK" }, { 0x0008, "DISK_FILE_SYSTEM" }, { 0x0009, "FILE_SYSTEM" }, { 0x000a, "INPORT_PORT" }, { 0x000b, "KEYBOARD" }, { 0x000c, "MAILSLOT" }, { 0x000d, "MIDI_IN" }, { 0x000e, "MIDI_OUT" }, { 0x000f, "MOUSE" }, { 0x0010, "MULTI_UNC_PROVIDER" }, { 0x0011, "NAMED_PIPE" }, { 0x0012, "NETWORK" }, { 0x0013, "NETWORK_BROWSER" }, { 0x0014, "NETWORK_FILE_SYSTEM" }, { 0x0015, "NULL" }, { 0x0016, "PARALLEL_PORT" }, { 0x0017, "PHYSICAL_NETCARD" }, { 0x0018, "PRINTER" }, { 0x0019, "SCANNER" }, { 0x001a, "SERIAL_MOUSE_PORT" }, { 0x001b, "SERIAL_PORT" }, { 0x001c, "SCREEN" }, { 0x001d, "SOUND" }, { 0x001e, "STREAMS" }, { 0x001f, "TAPE" }, { 0x0020, "TAPE_FILE_SYSTEM" }, { 0x0021, "TRANSPORT" }, { 0x0022, "UNKNOWN" }, { 0x0023, "VIDEO" }, { 0x0024, "VIRTUAL_DISK" }, { 0x0025, "WAVE_IN" }, { 0x0026, "WAVE_OUT" }, { 0x0027, "8042_PORT" }, { 0x0028, "NETWORK_REDIRECTOR" }, { 0x0029, "BATTERY" }, { 0x002a, "BUS_EXTENDER" }, { 0x002b, "MODEM" }, { 0x002c, "VDM" }, { 0x002d, "MASS_STORAGE" }, { 0x002e, "SMB" }, { 0x002f, "KS" }, { 0x0030, "CHANGER" }, { 0x0031, "SMARTCARD" }, { 0x0032, "ACPI" }, { 0x0033, "DVD" }, { 0x0034, "FULLSCREEN_VIDEO" }, { 0x0035, "DFS_FILE_SYSTEM" }, { 0x0036, "DFS_VOLUME" }, { 0x0037, "SERENUM" }, { 0x0038, "TERMSRV" }, { 0x0039, "KSEC" }, { 0, NULL } }; static value_string_ext smb2_ioctl_device_vals_ext = VALUE_STRING_EXT_INIT(smb2_ioctl_device_vals); static const value_string smb2_ioctl_access_vals[] = { { 0x00, "FILE_ANY_ACCESS" }, { 0x01, "FILE_READ_ACCESS" }, { 0x02, "FILE_WRITE_ACCESS" }, { 0x03, "FILE_READ_WRITE_ACCESS" }, { 0, NULL } }; static const value_string smb2_ioctl_method_vals[] = { { 0x00, "METHOD_BUFFERED" }, { 0x01, "METHOD_IN_DIRECT" }, { 0x02, "METHOD_OUT_DIRECT" }, { 0x03, "METHOD_NEITHER" }, { 0, NULL } }; static const value_string smb2_ioctl_shared_virtual_disk_vals[] = { { 0x01, "SharedVirtualDisksSupported" }, { 0x07, "SharedVirtualDiskCDPSnapshotsSupported" }, { 0, NULL } }; static const value_string smb2_ioctl_shared_virtual_disk_hstate_vals[] = { { 0x00, "HandleStateNone" }, { 0x01, "HandleStateFileShared" }, { 0x03, "HandleStateShared" }, { 0, NULL } }; /* this is called from both smb and smb2. */ int dissect_smb2_ioctl_function(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, guint32 *ioctlfunc) { proto_item *item = NULL; proto_tree *tree = NULL; guint32 ioctl_function; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_ioctl_function, tvb, offset, 4, ENC_LITTLE_ENDIAN); tree = proto_item_add_subtree(item, ett_smb2_ioctl_function); } ioctl_function = tvb_get_letohl(tvb, offset); if (ioctlfunc) *ioctlfunc = ioctl_function; if (ioctl_function) { const gchar *unknown = "unknown"; const gchar *ioctl_name = val_to_str_ext_const(ioctl_function, &smb2_ioctl_vals_ext, unknown); /* * val_to_str_const() doesn't work with a unknown == NULL */ if (ioctl_name == unknown) { ioctl_name = NULL; } if (ioctl_name != NULL) { col_append_fstr( pinfo->cinfo, COL_INFO, " %s", ioctl_name); } /* device */ proto_tree_add_item(tree, hf_smb2_ioctl_function_device, tvb, offset, 4, ENC_LITTLE_ENDIAN); if (ioctl_name == NULL) { col_append_fstr( pinfo->cinfo, COL_INFO, " %s", val_to_str_ext((ioctl_function>>16)&0xffff, &smb2_ioctl_device_vals_ext, "Unknown (0x%08X)")); } /* access */ proto_tree_add_item(tree, hf_smb2_ioctl_function_access, tvb, offset, 4, ENC_LITTLE_ENDIAN); /* function */ proto_tree_add_item(tree, hf_smb2_ioctl_function_function, tvb, offset, 4, ENC_LITTLE_ENDIAN); if (ioctl_name == NULL) { col_append_fstr( pinfo->cinfo, COL_INFO, " Function:0x%04x", (ioctl_function>>2)&0x0fff); } /* method */ proto_tree_add_item(tree, hf_smb2_ioctl_function_method, tvb, offset, 4, ENC_LITTLE_ENDIAN); } offset += 4; return offset; } /* fake the dce/rpc support structures so we can piggy back on * dissect_nt_policy_hnd() since this will allow us * a cheap way to track where FIDs are opened, closed * and fid->filename mappings * if we want to do those things in the future. */ #define FID_MODE_OPEN 0 #define FID_MODE_CLOSE 1 #define FID_MODE_USE 2 #define FID_MODE_DHNQ 3 #define FID_MODE_DHNC 4 static int dissect_smb2_fid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si, int mode) { guint8 drep[4] = { 0x10, 0x00, 0x00, 0x00}; /* fake DREP struct */ static dcerpc_info di; /* fake dcerpc_info struct */ static dcerpc_call_value call_data; e_ctx_hnd policy_hnd; e_ctx_hnd *policy_hnd_hashtablekey; proto_item *hnd_item = NULL; 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; 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->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 { fid_name = wmem_strdup_printf(wmem_file_scope(), "File: "); } 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->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); if (!eo_file_info) { eo_file_info = wmem_new(wmem_file_scope(), smb2_eo_file_info_t); policy_hnd_hashtablekey = wmem_new(wmem_file_scope(), e_ctx_hnd); memcpy(policy_hnd_hashtablekey, &policy_hnd, sizeof(e_ctx_hnd)); eo_file_info->end_of_file=0; g_hash_table_insert(si->conv->files,policy_hnd_hashtablekey,eo_file_info); } si->eo_file_info=eo_file_info; } } break; case FID_MODE_CLOSE: offset = dissect_nt_guid_hnd(tvb, offset, pinfo, tree, &di, drep, hf_smb2_fid, &policy_hnd, &hnd_item, FALSE, TRUE); break; case FID_MODE_USE: case FID_MODE_DHNQ: case FID_MODE_DHNC: offset = dissect_nt_guid_hnd(tvb, offset, pinfo, tree, &di, drep, hf_smb2_fid, &policy_hnd, &hnd_item, FALSE, FALSE); break; } 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, " File: %s", si->file->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; } if (si->conv) { eo_file_info = (smb2_eo_file_info_t *)g_hash_table_lookup(si->conv->files,&policy_hnd); if (eo_file_info) { si->eo_file_info=eo_file_info; } else { /* XXX This should never happen */ eo_file_info = wmem_new(wmem_file_scope(), smb2_eo_file_info_t); policy_hnd_hashtablekey = wmem_new(wmem_file_scope(), e_ctx_hnd); memcpy(policy_hnd_hashtablekey, &policy_hnd, sizeof(e_ctx_hnd)); eo_file_info->end_of_file=0; g_hash_table_insert(si->conv->files,policy_hnd_hashtablekey,eo_file_info); } } } } return offset; } /* this info level is unique to SMB2 and differst from the corresponding * SMB_FILE_ALL_INFO in SMB */ static int dissect_smb2_file_all_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; int length; const char *name = ""; guint16 bc; static const int *mode_fields[] = { &hf_smb2_mode_file_write_through, &hf_smb2_mode_file_sequential_only, &hf_smb2_mode_file_no_intermediate_buffering, &hf_smb2_mode_file_synchronous_io_alert, &hf_smb2_mode_file_synchronous_io_nonalert, &hf_smb2_mode_file_delete_on_close, NULL, }; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_file_all_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_file_all_info); } /* create time */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_create_timestamp); /* last access */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_access_timestamp); /* last write */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_write_timestamp); /* last change */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_change_timestamp); /* File Attributes */ offset = dissect_file_ext_attr(tvb, tree, offset); /* some unknown bytes */ proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, 4, ENC_NA); offset += 4; /* allocation size */ proto_tree_add_item(tree, hf_smb2_allocation_size, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* end of file */ proto_tree_add_item(tree, hf_smb2_end_of_file, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* number of links */ proto_tree_add_item(tree, hf_smb2_nlinks, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* delete pending */ proto_tree_add_item(tree, hf_smb2_delete_pending, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* is directory */ proto_tree_add_item(tree, hf_smb2_is_directory, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* padding */ offset += 2; /* file id */ proto_tree_add_item(tree, hf_smb2_file_id, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* ea size */ proto_tree_add_item(tree, hf_smb2_ea_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* access mask */ offset = dissect_smb_access_mask(tvb, tree, offset); /* Position Information */ proto_tree_add_item(tree, hf_smb2_position_information, tvb, offset, 8, ENC_NA); offset += 8; /* Mode Information */ proto_tree_add_bitmask(tree, tvb, offset, hf_smb2_mode_information, ett_smb2_file_mode_info, mode_fields, ENC_LITTLE_ENDIAN); offset += 4; /* Alignment Information */ proto_tree_add_item(tree, hf_smb2_alignment_information, tvb, offset, 4, ENC_NA); offset +=4; /* file name length */ length = tvb_get_letohs(tvb, offset); proto_tree_add_item(tree, hf_smb2_filename_len, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* file name */ if (length) { bc = tvb_captured_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; return offset; } static int dissect_smb2_file_allocation_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint16 bc; gboolean trunc; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_file_allocation_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_file_allocation_info); } bc = tvb_captured_length_remaining(tvb, offset); offset = dissect_qsfi_SMB_FILE_ALLOCATION_INFO(tvb, pinfo, tree, offset, &bc, &trunc); return offset; } static int dissect_smb2_file_endoffile_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint16 bc; gboolean trunc; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_file_endoffile_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_file_endoffile_info); } bc = tvb_captured_length_remaining(tvb, offset); offset = dissect_qsfi_SMB_FILE_ENDOFFILE_INFO(tvb, pinfo, tree, offset, &bc, &trunc); return offset; } static int dissect_smb2_file_alternate_name_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint16 bc; gboolean trunc; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_file_alternate_name_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_file_alternate_name_info); } 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; } static int dissect_smb2_file_basic_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_file_basic_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_file_basic_info); } /* create time */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_create_timestamp); /* last access */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_access_timestamp); /* last write */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_write_timestamp); /* last change */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_change_timestamp); /* File Attributes */ offset = dissect_file_ext_attr(tvb, tree, offset); /* some unknown bytes */ proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, 4, ENC_NA); offset += 4; return offset; } static int dissect_smb2_file_standard_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint16 bc; gboolean trunc; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_file_standard_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_file_standard_info); } bc = tvb_captured_length_remaining(tvb, offset); offset = dissect_qfi_SMB_FILE_STANDARD_INFO(tvb, pinfo, tree, offset, &bc, &trunc); return offset; } static int dissect_smb2_file_internal_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint16 bc; gboolean trunc; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_file_internal_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_file_internal_info); } bc = tvb_captured_length_remaining(tvb, offset); offset = dissect_qfi_SMB_FILE_INTERNAL_INFO(tvb, pinfo, tree, offset, &bc, &trunc); return offset; } static int dissect_smb2_file_mode_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint16 bc; gboolean trunc; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_file_mode_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_file_mode_info); } bc = tvb_captured_length_remaining(tvb, offset); offset = dissect_qsfi_SMB_FILE_MODE_INFO(tvb, pinfo, tree, offset, &bc, &trunc); return offset; } static int dissect_smb2_file_alignment_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint16 bc; gboolean trunc; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_file_alignment_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_file_alignment_info); } bc = tvb_captured_length_remaining(tvb, offset); offset = dissect_qfi_SMB_FILE_ALIGNMENT_INFO(tvb, pinfo, tree, offset, &bc, &trunc); return offset; } static int dissect_smb2_file_position_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint16 bc; gboolean trunc; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_file_position_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_file_position_info); } bc = tvb_captured_length_remaining(tvb, offset); offset = dissect_qsfi_SMB_FILE_POSITION_INFO(tvb, pinfo, tree, offset, &bc, &trunc); return offset; } static int dissect_smb2_file_access_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_file_access_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_file_access_info); } /* access mask */ offset = dissect_smb_access_mask(tvb, tree, offset); return offset; } static int dissect_smb2_file_ea_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint16 bc; gboolean trunc; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_file_ea_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_file_ea_info); } bc = tvb_captured_length_remaining(tvb, offset); offset = dissect_qfi_SMB_FILE_EA_INFO(tvb, pinfo, tree, offset, &bc, &trunc); return offset; } static int dissect_smb2_file_stream_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint16 bc; gboolean trunc; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_file_stream_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_file_stream_info); } bc = tvb_captured_length_remaining(tvb, offset); offset = dissect_qfi_SMB_FILE_STREAM_INFO(tvb, pinfo, tree, offset, &bc, &trunc, TRUE); return offset; } static int dissect_smb2_file_pipe_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint16 bc; gboolean trunc; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_file_pipe_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_file_pipe_info); } bc = tvb_captured_length_remaining(tvb, offset); offset = dissect_sfi_SMB_FILE_PIPE_INFO(tvb, pinfo, tree, offset, &bc, &trunc); return offset; } static int dissect_smb2_file_compression_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint16 bc; gboolean trunc; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_file_compression_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_file_compression_info); } bc = tvb_captured_length_remaining(tvb, offset); offset = dissect_qfi_SMB_FILE_COMPRESSION_INFO(tvb, pinfo, tree, offset, &bc, &trunc); return offset; } static int dissect_smb2_file_network_open_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint16 bc; gboolean trunc; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_file_network_open_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_file_network_open_info); } bc = tvb_captured_length_remaining(tvb, offset); offset = dissect_qfi_SMB_FILE_NETWORK_OPEN_INFO(tvb, pinfo, tree, offset, &bc, &trunc); return offset; } static int dissect_smb2_file_attribute_tag_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint16 bc; gboolean trunc; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_file_attribute_tag_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_file_attribute_tag_info); } bc = tvb_captured_length_remaining(tvb, offset); offset = dissect_qfi_SMB_FILE_ATTRIBUTE_TAG_INFO(tvb, pinfo, tree, offset, &bc, &trunc); return offset; } static const true_false_string tfs_disposition_delete_on_close = { "DELETE this file when closed", "Normal access, do not delete on close" }; static int dissect_smb2_file_disposition_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_file_disposition_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_file_disposition_info); } /* file disposition */ proto_tree_add_item(tree, hf_smb2_disposition_delete_on_close, tvb, offset, 1, ENC_LITTLE_ENDIAN); return offset; } static int dissect_smb2_file_full_ea_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint32 next_offset; guint8 ea_name_len; guint16 ea_data_len; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_file_full_ea_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_file_full_ea_info); } while (1) { int length; const char *name = ""; const char *data = ""; guint16 bc; int start_offset = offset; proto_item *ea_item; proto_tree *ea_tree; 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); proto_tree_add_item(ea_tree, hf_smb2_next_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* EA flags */ proto_tree_add_item(ea_tree, hf_smb2_ea_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* EA Name Length */ ea_name_len = tvb_get_guint8(tvb, offset); proto_tree_add_item(ea_tree, hf_smb2_ea_name_len, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* EA Data Length */ ea_data_len = tvb_get_letohs(tvb, offset); proto_tree_add_item(ea_tree, hf_smb2_ea_data_len, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* ea name */ length = ea_name_len; if (length) { bc = tvb_captured_length_remaining(tvb, offset); name = get_unicode_or_ascii_string(tvb, &offset, FALSE, &length, TRUE, TRUE, &bc); if (name) { proto_tree_add_string(ea_tree, hf_smb2_ea_name, tvb, offset, length + 1, name); } } /* The name is terminated with a NULL */ offset += ea_name_len + 1; /* ea data */ length = ea_data_len; if (length) { bc = tvb_captured_length_remaining(tvb, offset); data = get_unicode_or_ascii_string(tvb, &offset, FALSE, &length, TRUE, TRUE, &bc); /* * We put the data here ... */ proto_tree_add_item(ea_tree, hf_smb2_ea_data, tvb, offset, length, ENC_NA); } offset += ea_data_len; if (ea_item) { proto_item_append_text(ea_item, " %s := %s", name, data); } proto_item_set_len(ea_item, offset-start_offset); if (!next_offset) { break; } offset = start_offset+next_offset; } 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_) { proto_item *item = NULL; proto_tree *tree = NULL; int length; const char *name = ""; guint16 bc; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_file_rename_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_file_rename_info); } /* 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, 4, ENC_LITTLE_ENDIAN); offset += 4; /* file name */ if (length) { bc = tvb_captured_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); } col_append_fstr(pinfo->cinfo, COL_INFO, " NewName:%s", name); } offset += length; return offset; } static int dissect_smb2_sec_info_00(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_sec_info_00, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_sec_info_00); } /* security descriptor */ offset = dissect_nt_sec_desc(tvb, offset, pinfo, tree, NULL, TRUE, tvb_captured_length_remaining(tvb, offset), NULL); return offset; } static int dissect_smb2_quota_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint16 bcp; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_quota_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_quota_info); } bcp = tvb_captured_length_remaining(tvb, offset); offset = dissect_nt_user_quota(tvb, tree, offset, &bcp); return offset; } static int dissect_smb2_fs_info_05(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint16 bc; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_fs_info_05, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_fs_info_05); } bc = tvb_captured_length_remaining(tvb, offset); offset = dissect_qfsi_FS_ATTRIBUTE_INFO(tvb, pinfo, tree, offset, &bc, TRUE); return offset; } static int dissect_smb2_fs_info_06(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint16 bc; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_fs_info_06, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_fs_info_06); } bc = tvb_captured_length_remaining(tvb, offset); offset = dissect_nt_quota(tvb, tree, offset, &bc); return offset; } static int dissect_smb2_FS_OBJECTID_INFO(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_fs_objectid_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_fs_objectid_info); } /* FILE_OBJECTID_BUFFER */ offset = dissect_smb2_FILE_OBJECTID_BUFFER(tvb, pinfo, tree, offset); return offset; } static int dissect_smb2_fs_info_07(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint16 bc; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_fs_info_07, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_fs_info_07); } bc = tvb_captured_length_remaining(tvb, offset); offset = dissect_qfsi_FS_FULL_SIZE_INFO(tvb, pinfo, tree, offset, &bc); return offset; } static int dissect_smb2_fs_info_01(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint16 bc; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_fs_info_01, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_fs_info_01); } bc = tvb_captured_length_remaining(tvb, offset); offset = dissect_qfsi_FS_VOLUME_INFO(tvb, pinfo, tree, offset, &bc, TRUE); return offset; } static int dissect_smb2_fs_info_03(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint16 bc; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_fs_info_03, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_fs_info_03); } bc = tvb_captured_length_remaining(tvb, offset); offset = dissect_qfsi_FS_SIZE_INFO(tvb, pinfo, tree, offset, &bc); return offset; } static int dissect_smb2_fs_info_04(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_item *item = NULL; proto_tree *tree = NULL; guint16 bc; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_fs_info_04, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_fs_info_04); } bc = tvb_captured_length_remaining(tvb, offset); offset = dissect_qfsi_FS_DEVICE_INFO(tvb, pinfo, tree, offset, &bc); return offset; } static const value_string oplock_vals[] = { { 0x00, "No oplock" }, { 0x01, "Level2 oplock" }, { 0x08, "Exclusive oplock" }, { 0x09, "Batch oplock" }, { 0xff, "Lease" }, { 0, NULL } }; static int dissect_smb2_oplock(proto_tree *parent_tree, tvbuff_t *tvb, int offset) { proto_tree_add_item(parent_tree, hf_smb2_oplock, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; return offset; } static int dissect_smb2_buffercode(proto_tree *parent_tree, tvbuff_t *tvb, int offset, guint16 *length) { proto_tree *tree; proto_item *item; guint16 buffer_code; /* dissect the first 2 bytes of the command PDU */ 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_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 don't mask it here, mask it on caller side */ } return offset; } #define NEGPROT_CAP_DFS 0x00000001 #define NEGPROT_CAP_LEASING 0x00000002 #define NEGPROT_CAP_LARGE_MTU 0x00000004 #define NEGPROT_CAP_MULTI_CHANNEL 0x00000008 #define NEGPROT_CAP_PERSISTENT_HANDLES 0x00000010 #define NEGPROT_CAP_DIRECTORY_LEASING 0x00000020 #define NEGPROT_CAP_ENCRYPTION 0x00000040 static int dissect_smb2_capabilities(proto_tree *parent_tree, tvbuff_t *tvb, int offset) { 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; } #define NEGPROT_SIGN_REQ 0x0002 #define NEGPROT_SIGN_ENABLED 0x0001 static int dissect_smb2_secmode(proto_tree *parent_tree, tvbuff_t *tvb, int offset) { 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; } #define SES_REQ_FLAGS_SESSION_BINDING 0x01 static int dissect_smb2_ses_req_flags(proto_tree *parent_tree, tvbuff_t *tvb, int offset) { 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; } #define SES_FLAGS_GUEST 0x0001 #define SES_FLAGS_NULL 0x0002 #define SES_FLAGS_ENCRYPT 0x0004 static int dissect_smb2_ses_flags(proto_tree *parent_tree, tvbuff_t *tvb, int offset) { static const int * flags[] = { &hf_smb2_ses_flags_guest, &hf_smb2_ses_flags_null, &hf_smb2_ses_flags_encrypt, 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; } #define SHARE_FLAGS_manual_caching 0x00000000 #define SHARE_FLAGS_auto_caching 0x00000010 #define SHARE_FLAGS_vdo_caching 0x00000020 #define SHARE_FLAGS_no_caching 0x00000030 static const value_string share_cache_vals[] = { { SHARE_FLAGS_manual_caching, "Manual caching" }, { SHARE_FLAGS_auto_caching, "Auto caching" }, { SHARE_FLAGS_vdo_caching, "VDO caching" }, { SHARE_FLAGS_no_caching, "No caching" }, { 0, NULL } }; #define SHARE_FLAGS_dfs 0x00000001 #define SHARE_FLAGS_dfs_root 0x00000002 #define SHARE_FLAGS_restrict_exclusive_opens 0x00000100 #define SHARE_FLAGS_force_shared_delete 0x00000200 #define SHARE_FLAGS_allow_namespace_caching 0x00000400 #define SHARE_FLAGS_access_based_dir_enum 0x00000800 #define SHARE_FLAGS_force_levelii_oplock 0x00001000 #define SHARE_FLAGS_enable_hash_v1 0x00002000 #define SHARE_FLAGS_enable_hash_v2 0x00004000 #define SHARE_FLAGS_encryption_required 0x00008000 static int dissect_smb2_share_flags(proto_tree *tree, tvbuff_t *tvb, int offset) { static const int *sf_fields[] = { &hf_smb2_share_flags_dfs, &hf_smb2_share_flags_dfs_root, &hf_smb2_share_flags_restrict_exclusive_opens, &hf_smb2_share_flags_force_shared_delete, &hf_smb2_share_flags_allow_namespace_caching, &hf_smb2_share_flags_access_based_dir_enum, &hf_smb2_share_flags_force_levelii_oplock, &hf_smb2_share_flags_enable_hash_v1, &hf_smb2_share_flags_enable_hash_v2, &hf_smb2_share_flags_encrypt_data, NULL }; proto_item *item; guint32 cp; item = proto_tree_add_bitmask(tree, tvb, offset, hf_smb2_share_flags, ett_smb2_share_flags, sf_fields, ENC_LITTLE_ENDIAN); cp = tvb_get_letohl(tvb, offset); cp &= 0x00000030; proto_tree_add_uint_format(item, hf_smb2_share_caching, tvb, offset, 4, cp, "Caching policy: %s (%08x)", val_to_str(cp, share_cache_vals, "Unknown:%u"), cp); offset += 4; return offset; } #define SHARE_CAPS_DFS 0x00000008 #define SHARE_CAPS_CONTINUOUS_AVAILABILITY 0x00000010 #define SHARE_CAPS_SCALEOUT 0x00000020 #define SHARE_CAPS_CLUSTER 0x00000040 static int dissect_smb2_share_caps(proto_tree *tree, tvbuff_t *tvb, int offset) { static const int *sc_fields[] = { &hf_smb2_share_caps_dfs, &hf_smb2_share_caps_continuous_availability, &hf_smb2_share_caps_scaleout, &hf_smb2_share_caps_cluster, NULL }; proto_tree_add_bitmask(tree, tvb, offset, hf_smb2_share_caps, ett_smb2_share_caps, sc_fields, ENC_LITTLE_ENDIAN); offset += 4; return offset; } static void dissect_smb2_secblob(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si _U_) { if ((tvb_captured_length(tvb)>=7) && (!tvb_memeql(tvb, 0, "NTLMSSP", 7))) { call_dissector(ntlmssp_handle, tvb, pinfo, tree); } else { call_dissector(gssapi_handle, tvb, pinfo, tree); } } /* * Derive client and server decryption keys from the secret session key * and set them in the session object. */ static void smb2_set_session_keys(smb2_sesid_info_t *sesid, const guint8 *session_key) { if (memcmp(session_key, zeros, NTLMSSP_KEY_LEN) != 0) { smb2_key_derivation(session_key, NTLMSSP_KEY_LEN, "SMB2AESCCM", 11, "ServerIn ", 10, sesid->server_decryption_key); smb2_key_derivation(session_key, NTLMSSP_KEY_LEN, "SMB2AESCCM", 11, "ServerOut", 10, sesid->client_decryption_key); } else { memset(sesid->server_decryption_key, 0, sizeof(sesid->server_decryption_key)); memset(sesid->client_decryption_key, 0, sizeof(sesid->client_decryption_key)); } } static int dissect_smb2_session_setup_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si) { offset_length_buffer_t s_olb; const ntlmssp_header_t *ntlmssph; static int ntlmssp_tap_id = 0; int idx; if (!ntlmssp_tap_id) { GString *error_string; /* 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. */ error_string = register_tap_listener("ntlmssp", NULL, NULL, TL_IS_DISSECTOR_HELPER, NULL, NULL, NULL, NULL); if (!error_string) { ntlmssp_tap_id = find_tap_id("ntlmssp"); } else { g_string_free(error_string, TRUE); } } /* buffer code */ offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); /* some unknown bytes */ /* flags */ offset = dissect_smb2_ses_req_flags(tree, tvb, offset); /* security mode */ offset = dissect_smb2_secmode(tree, tvb, offset); /* capabilities */ offset = dissect_smb2_capabilities(tree, tvb, offset); /* channel */ proto_tree_add_item(tree, hf_smb2_channel, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* security blob offset/length */ offset = dissect_smb2_olb_length_offset(tvb, offset, &s_olb, OLB_O_UINT16_S_UINT16, hf_smb2_security_blob); /* previous session id */ proto_tree_add_item(tree, hf_smb2_previous_sesid, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* the security blob itself */ dissect_smb2_olb_buffer(pinfo, tree, tvb, &s_olb, si, dissect_smb2_secblob); offset = dissect_smb2_olb_tvb_max_offset(offset, &s_olb); /* If we have found a uid->acct_name mapping, store it */ if (!pinfo->fd->visited) { idx = 0; while ((ntlmssph = (const ntlmssp_header_t *)fetch_tapped_data(ntlmssp_tap_id, idx++)) != NULL) { if (ntlmssph && ntlmssph->type == NTLMSSP_AUTH) { smb2_sesid_info_t *sesid; guint8 custom_seskey[NTLMSSP_KEY_LEN]; const guint8 *session_key; sesid = wmem_new(wmem_file_scope(), smb2_sesid_info_t); sesid->sesid = si->sesid; sesid->acct_name = wmem_strdup(wmem_file_scope(), ntlmssph->acct_name); sesid->domain_name = wmem_strdup(wmem_file_scope(), ntlmssph->domain_name); sesid->host_name = wmem_strdup(wmem_file_scope(), ntlmssph->host_name); /* Try to see first if we have a * session key set in the pref for * this particular session id */ if (seskey_find_sid_key(si->sesid, custom_seskey)) { session_key = custom_seskey; } else { session_key = ntlmssph->session_key; } smb2_set_session_keys(sesid, session_key); sesid->server_port = pinfo->destport; 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; } static void dissect_smb2_STATUS_STOPPED_ON_SYMLINK(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_tree *tree; proto_item *item; offset_length_buffer_t s_olb, p_olb; item = proto_tree_add_item(parent_tree, hf_smb2_symlink_error_response, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_symlink_error_response); /* symlink length */ proto_tree_add_item(tree, hf_smb2_symlink_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* symlink error tag */ proto_tree_add_item(tree, hf_smb2_symlink_error_tag, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* reparse tag */ proto_tree_add_item(tree, hf_smb2_reparse_tag, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_smb2_reparse_data_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_smb2_unparsed_path_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* substitute name offset/length */ offset = dissect_smb2_olb_length_offset(tvb, offset, &s_olb, OLB_O_UINT16_S_UINT16, hf_smb2_symlink_substitute_name); /* print name offset/length */ offset = dissect_smb2_olb_length_offset(tvb, offset, &p_olb, OLB_O_UINT16_S_UINT16, hf_smb2_symlink_print_name); /* flags */ proto_tree_add_item(tree, hf_smb2_symlink_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* substitute name string */ dissect_smb2_olb_off_string(pinfo, tree, tvb, &s_olb, offset, OLB_TYPE_UNICODE_STRING); /* print name string */ dissect_smb2_olb_off_string(pinfo, tree, tvb, &p_olb, offset, OLB_TYPE_UNICODE_STRING); } static void dissect_smb2_error_data(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int error_context_count, smb2_info_t *si _U_) { proto_tree *tree; proto_item *item; int offset = 0; item = proto_tree_add_item(parent_tree, hf_smb2_error_data, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_error_data); if (error_context_count == 0) { switch (si->status) { case 0x8000002D: /* STATUS_STOPPED_ON_SYMLINK */ dissect_smb2_STATUS_STOPPED_ON_SYMLINK(tvb, pinfo, tree, offset, si); break; default: break; } } else { /* TODO SMB311 supports multiple error contexts */ } } /* 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, gboolean* continue_dissection) { gint byte_count; guint8 error_context_count; guint16 length; tvbuff_t *sub_tvb; /* buffer code */ 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; /* ErrorContextCount (1 bytes) */ error_context_count = tvb_get_guint8(tvb, offset); proto_tree_add_item(tree, hf_smb2_error_context_count, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* Reserved (1 bytes) */ proto_tree_add_item(tree, hf_smb2_error_reserved, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* ByteCount (4 bytes): The number of bytes of data contained in ErrorData[]. */ byte_count = tvb_get_letohl(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; /* ErrorData (variable): A variable-length data field that contains extended error information.*/ sub_tvb = tvb_new_subset_length(tvb, offset, byte_count); offset += byte_count; dissect_smb2_error_data(sub_tvb, pinfo, tree, error_context_count, si); } return offset; } static int dissect_smb2_session_setup_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si _U_) { offset_length_buffer_t s_olb; /* session_setup is special and we don't use dissect_smb2_error_response() here! */ /* buffer code */ offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); /* session flags */ offset = dissect_smb2_ses_flags(tree, tvb, offset); /* security blob offset/length */ offset = dissect_smb2_olb_length_offset(tvb, offset, &s_olb, OLB_O_UINT16_S_UINT16, hf_smb2_security_blob); /* the security blob itself */ dissect_smb2_olb_buffer(pinfo, tree, tvb, &s_olb, si, dissect_smb2_secblob); 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->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 custom_seskey[NTLMSSP_KEY_LEN] = { 0, }; const guint8 *session_key; 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; if (seskey_find_sid_key(si->sesid, custom_seskey)) { session_key = custom_seskey; } else { session_key = ek->keyvalue; } smb2_set_session_keys(sesid, session_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; } static int dissect_smb2_tree_connect_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si _U_) { offset_length_buffer_t olb; const char *buf; /* buffer code */ offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 2, ENC_NA); offset += 2; /* tree offset/length */ offset = dissect_smb2_olb_length_offset(tvb, offset, &olb, OLB_O_UINT16_S_UINT16, hf_smb2_tree); /* tree string */ buf = dissect_smb2_olb_string(pinfo, tree, tvb, &olb, OLB_TYPE_UNICODE_STRING); offset = dissect_smb2_olb_tvb_max_offset(offset, &olb); /* treelen +1 is overkill here if the string is unicode, * but who ever has more than a handful of TCON in a trace anyways */ if (!pinfo->fd->visited && si->saved && buf && olb.len) { si->saved->extra_info_type = SMB2_EI_TREENAME; si->saved->extra_info = wmem_alloc(wmem_file_scope(), olb.len+1); g_snprintf((char *)si->saved->extra_info,olb.len+1,"%s",buf); } col_append_fstr(pinfo->cinfo, COL_INFO, " Tree: %s", buf); return offset; } static int dissect_smb2_tree_connect_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si _U_) { guint8 share_type; gboolean continue_dissection; switch (si->status) { /* buffer code */ 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_guint8(tvb, offset); proto_tree_add_item(tree, hf_smb2_share_type, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* byte is reserved and must be set to zero */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 1, ENC_NA); offset += 1; if (!pinfo->fd->visited && si->saved && si->saved->extra_info_type == SMB2_EI_TREENAME && si->session) { smb2_tid_info_t *tid, tid_key; tid_key.tid = si->tid; tid = (smb2_tid_info_t *)g_hash_table_lookup(si->session->tids, &tid_key); if (tid) { g_hash_table_remove(si->session->tids, &tid_key); } 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->num; tid->share_type = share_type; g_hash_table_insert(si->session->tids, tid, tid); si->saved->extra_info_type = SMB2_EI_NONE; si->saved->extra_info = NULL; } /* share flags */ offset = dissect_smb2_share_flags(tree, tvb, offset); /* share capabilities */ offset = dissect_smb2_share_caps(tree, tvb, offset); /* this is some sort of access mask */ offset = dissect_smb_access_mask(tvb, tree, offset); return offset; } static int dissect_smb2_tree_disconnect_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_) { /* buffer code */ offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 2, ENC_NA); offset += 2; return offset; } static int dissect_smb2_tree_disconnect_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_) { gboolean continue_dissection; switch (si->status) { /* buffer code */ 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); offset += 2; return offset; } static int dissect_smb2_sessionlogoff_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_) { /* buffer code */ offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); /* reserved bytes */ offset += 2; return offset; } static int dissect_smb2_sessionlogoff_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_) { gboolean continue_dissection; switch (si->status) { /* buffer code */ 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 */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 2, ENC_NA); offset += 2; return offset; } static int dissect_smb2_keepalive_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_) { /* buffer code */ offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); /* some unknown bytes */ proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, 2, ENC_NA); offset += 2; return offset; } static int dissect_smb2_keepalive_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_) { gboolean continue_dissection; switch (si->status) { /* buffer code */ 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); offset += 2; return offset; } static int dissect_smb2_notify_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si) { proto_tree *flags_tree = NULL; proto_item *flags_item = NULL; /* buffer code */ offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); /* notify flags */ if (tree) { flags_item = proto_tree_add_item(tree, hf_smb2_notify_flags, tvb, offset, 2, ENC_LITTLE_ENDIAN); flags_tree = proto_item_add_subtree(flags_item, ett_smb2_notify_flags); } proto_tree_add_item(flags_tree, hf_smb2_notify_watch_tree, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* output buffer length */ proto_tree_add_item(tree, hf_smb2_output_buffer_len, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* fid */ offset = dissect_smb2_fid(tvb, pinfo, tree, offset, si, FID_MODE_USE); /* completion filter */ offset = dissect_nt_notify_completion_filter(tvb, tree, offset); /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA); offset += 4; 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 *parent_tree, smb2_info_t *si _U_) { 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) { /* 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; } /* out buffer offset/length */ offset = dissect_smb2_olb_length_offset(tvb, offset, &olb, OLB_O_UINT16_S_UINT32, hf_smb2_notify_out_data); /* out buffer */ dissect_smb2_olb_buffer(pinfo, tree, tvb, &olb, si, dissect_smb2_notify_data_out); offset = dissect_smb2_olb_tvb_max_offset(offset, &olb); return offset; } #define SMB2_FIND_FLAG_RESTART_SCANS 0x01 #define SMB2_FIND_FLAG_SINGLE_ENTRY 0x02 #define SMB2_FIND_FLAG_INDEX_SPECIFIED 0x04 #define SMB2_FIND_FLAG_REOPEN 0x10 static int dissect_smb2_find_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si) { offset_length_buffer_t olb; const char *buf; guint8 il; static const int *f_fields[] = { &hf_smb2_find_flags_restart_scans, &hf_smb2_find_flags_single_entry, &hf_smb2_find_flags_index_specified, &hf_smb2_find_flags_reopen, NULL }; /* buffer code */ offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); il = tvb_get_guint8(tvb, offset); if (si->saved) { si->saved->infolevel = il; } /* infolevel */ proto_tree_add_uint(tree, hf_smb2_find_info_level, tvb, offset, 1, il); offset += 1; /* find flags */ proto_tree_add_bitmask(tree, tvb, offset, hf_smb2_find_flags, ett_smb2_find_flags, f_fields, ENC_LITTLE_ENDIAN); offset += 1; /* file index */ proto_tree_add_item(tree, hf_smb2_file_index, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* fid */ offset = dissect_smb2_fid(tvb, pinfo, tree, offset, si, FID_MODE_USE); /* search pattern offset/length */ offset = dissect_smb2_olb_length_offset(tvb, offset, &olb, OLB_O_UINT16_S_UINT16, hf_smb2_find_pattern); /* output buffer length */ proto_tree_add_item(tree, hf_smb2_output_buffer_len, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* search pattern */ buf = dissect_smb2_olb_string(pinfo, tree, tvb, &olb, OLB_TYPE_UNICODE_STRING); offset = dissect_smb2_olb_tvb_max_offset(offset, &olb); if (!pinfo->fd->visited && si->saved && olb.len) { si->saved->extra_info_type = SMB2_EI_FINDPATTERN; si->saved->extra_info = wmem_alloc(wmem_file_scope(), olb.len+1); g_snprintf((char *)si->saved->extra_info,olb.len+1,"%s",buf); } col_append_fstr(pinfo->cinfo, COL_INFO, " %s Pattern: %s", val_to_str(il, smb2_find_info_levels, "(Level:0x%02x)"), buf); return offset; } static void dissect_smb2_file_directory_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, smb2_info_t *si _U_) { int offset = 0; proto_item *item = NULL; proto_tree *tree = NULL; const char *name = NULL; guint16 bc; while (tvb_reported_length_remaining(tvb, offset) > 4) { int old_offset = offset; int next_offset; int file_name_len; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_file_directory_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_file_directory_info); } /* next offset */ next_offset = tvb_get_letohl(tvb, offset); proto_tree_add_item(tree, hf_smb2_next_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* file index */ proto_tree_add_item(tree, hf_smb2_file_index, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* create time */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_create_timestamp); /* last access */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_access_timestamp); /* last write */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_write_timestamp); /* last change */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_change_timestamp); /* end of file */ proto_tree_add_item(tree, hf_smb2_end_of_file, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* allocation size */ proto_tree_add_item(tree, hf_smb2_allocation_size, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* File Attributes */ offset = dissect_file_ext_attr(tvb, tree, offset); /* file name length */ file_name_len = tvb_get_letohl(tvb, offset); proto_tree_add_item(tree, hf_smb2_filename_len, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* file name */ if (file_name_len) { bc = file_name_len; name = get_unicode_or_ascii_string(tvb, &offset, TRUE, &file_name_len, TRUE, TRUE, &bc); if (name) { proto_tree_add_string(tree, hf_smb2_filename, tvb, offset, file_name_len, name); proto_item_append_text(item, ": %s", name); } } proto_item_set_len(item, offset-old_offset); if (next_offset == 0) { return; } offset = old_offset+next_offset; if (offset < old_offset) { proto_tree_add_expert_format(tree, pinfo, &ei_smb2_invalid_length, tvb, offset, -1, "Invalid offset/length. Malformed packet"); return; } } } static void dissect_smb2_full_directory_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, smb2_info_t *si _U_) { int offset = 0; proto_item *item = NULL; proto_tree *tree = NULL; const char *name = NULL; guint16 bc; while (tvb_reported_length_remaining(tvb, offset) > 4) { int old_offset = offset; int next_offset; int file_name_len; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_full_directory_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_full_directory_info); } /* next offset */ next_offset = tvb_get_letohl(tvb, offset); proto_tree_add_item(tree, hf_smb2_next_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* file index */ proto_tree_add_item(tree, hf_smb2_file_index, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* create time */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_create_timestamp); /* last access */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_access_timestamp); /* last write */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_write_timestamp); /* last change */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_change_timestamp); /* end of file */ proto_tree_add_item(tree, hf_smb2_end_of_file, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* allocation size */ proto_tree_add_item(tree, hf_smb2_allocation_size, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* File Attributes */ offset = dissect_file_ext_attr(tvb, tree, offset); /* file name length */ file_name_len = tvb_get_letohl(tvb, offset); proto_tree_add_item(tree, hf_smb2_filename_len, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* ea size */ proto_tree_add_item(tree, hf_smb2_ea_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* file name */ if (file_name_len) { bc = file_name_len; name = get_unicode_or_ascii_string(tvb, &offset, TRUE, &file_name_len, TRUE, TRUE, &bc); if (name) { proto_tree_add_string(tree, hf_smb2_filename, tvb, offset, file_name_len, name); proto_item_append_text(item, ": %s", name); } } proto_item_set_len(item, offset-old_offset); if (next_offset == 0) { return; } offset = old_offset+next_offset; if (offset < old_offset) { proto_tree_add_expert_format(tree, pinfo, &ei_smb2_invalid_length, tvb, offset, -1, "Invalid offset/length. Malformed packet"); return; } } } static void dissect_smb2_both_directory_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, smb2_info_t *si _U_) { int offset = 0; proto_item *item = NULL; proto_tree *tree = NULL; const char *name = NULL; guint16 bc; while (tvb_reported_length_remaining(tvb, offset) > 4) { int old_offset = offset; int next_offset; int file_name_len; int short_name_len; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_both_directory_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_both_directory_info); } /* next offset */ next_offset = tvb_get_letohl(tvb, offset); proto_tree_add_item(tree, hf_smb2_next_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* file index */ proto_tree_add_item(tree, hf_smb2_file_index, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* create time */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_create_timestamp); /* last access */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_access_timestamp); /* last write */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_write_timestamp); /* last change */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_change_timestamp); /* end of file */ proto_tree_add_item(tree, hf_smb2_end_of_file, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* allocation size */ proto_tree_add_item(tree, hf_smb2_allocation_size, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* File Attributes */ offset = dissect_file_ext_attr(tvb, tree, offset); /* file name length */ file_name_len = tvb_get_letohl(tvb, offset); proto_tree_add_item(tree, hf_smb2_filename_len, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* ea size */ proto_tree_add_item(tree, hf_smb2_ea_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* short name length */ short_name_len = tvb_get_guint8(tvb, offset); proto_tree_add_item(tree, hf_smb2_short_name_len, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 1, ENC_NA); offset += 1; /* short name */ if (short_name_len) { bc = short_name_len; name = get_unicode_or_ascii_string(tvb, &offset, TRUE, &short_name_len, TRUE, TRUE, &bc); if (name) { proto_tree_add_string(tree, hf_smb2_short_name, tvb, offset, short_name_len, name); } } offset += 24; /* file name */ if (file_name_len) { bc = file_name_len; name = get_unicode_or_ascii_string(tvb, &offset, TRUE, &file_name_len, TRUE, TRUE, &bc); if (name) { proto_tree_add_string(tree, hf_smb2_filename, tvb, offset, file_name_len, name); proto_item_append_text(item, ": %s", name); } } proto_item_set_len(item, offset-old_offset); if (next_offset == 0) { return; } offset = old_offset+next_offset; if (offset < old_offset) { proto_tree_add_expert_format(tree, pinfo, &ei_smb2_invalid_length, tvb, offset, -1, "Invalid offset/length. Malformed packet"); return; } } } static void dissect_smb2_file_name_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, smb2_info_t *si _U_) { int offset = 0; proto_item *item = NULL; proto_tree *tree = NULL; const char *name = NULL; guint16 bc; while (tvb_reported_length_remaining(tvb, offset) > 4) { int old_offset = offset; int next_offset; int file_name_len; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_both_directory_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_both_directory_info); } /* next offset */ next_offset = tvb_get_letohl(tvb, offset); proto_tree_add_item(tree, hf_smb2_next_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* file index */ proto_tree_add_item(tree, hf_smb2_file_index, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* file name length */ file_name_len = tvb_get_letohl(tvb, offset); proto_tree_add_item(tree, hf_smb2_filename_len, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* file name */ if (file_name_len) { bc = file_name_len; name = get_unicode_or_ascii_string(tvb, &offset, TRUE, &file_name_len, TRUE, TRUE, &bc); if (name) { proto_tree_add_string(tree, hf_smb2_filename, tvb, offset, file_name_len, name); proto_item_append_text(item, ": %s", name); } } proto_item_set_len(item, offset-old_offset); if (next_offset == 0) { return; } offset = old_offset+next_offset; if (offset < old_offset) { proto_tree_add_expert_format(tree, pinfo, &ei_smb2_invalid_length, tvb, offset, -1, "Invalid offset/length. Malformed packet"); return; } } } static void dissect_smb2_id_both_directory_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, smb2_info_t *si _U_) { int offset = 0; proto_item *item = NULL; proto_tree *tree = NULL; const char *name = NULL; guint16 bc; while (tvb_reported_length_remaining(tvb, offset) > 4) { int old_offset = offset; int next_offset; int file_name_len; int short_name_len; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_id_both_directory_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_id_both_directory_info); } /* next offset */ next_offset = tvb_get_letohl(tvb, offset); proto_tree_add_item(tree, hf_smb2_next_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* file index */ proto_tree_add_item(tree, hf_smb2_file_index, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* create time */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_create_timestamp); /* last access */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_access_timestamp); /* last write */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_write_timestamp); /* last change */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_change_timestamp); /* end of file */ proto_tree_add_item(tree, hf_smb2_end_of_file, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* allocation size */ proto_tree_add_item(tree, hf_smb2_allocation_size, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* File Attributes */ offset = dissect_file_ext_attr(tvb, tree, offset); /* file name length */ file_name_len = tvb_get_letohl(tvb, offset); proto_tree_add_item(tree, hf_smb2_filename_len, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* ea size */ proto_tree_add_item(tree, hf_smb2_ea_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* short name length */ short_name_len = tvb_get_guint8(tvb, offset); proto_tree_add_item(tree, hf_smb2_short_name_len, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 1, ENC_NA); offset += 1; /* short name */ if (short_name_len) { bc = short_name_len; name = get_unicode_or_ascii_string(tvb, &offset, TRUE, &short_name_len, TRUE, TRUE, &bc); if (name) { proto_tree_add_string(tree, hf_smb2_short_name, tvb, offset, short_name_len, name); } } offset += 24; /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 2, ENC_NA); offset += 2; /* file id */ proto_tree_add_item(tree, hf_smb2_file_id, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* file name */ if (file_name_len) { bc = file_name_len; name = get_unicode_or_ascii_string(tvb, &offset, TRUE, &file_name_len, TRUE, TRUE, &bc); if (name) { proto_tree_add_string(tree, hf_smb2_filename, tvb, offset, file_name_len, name); proto_item_append_text(item, ": %s", name); } } proto_item_set_len(item, offset-old_offset); if (next_offset == 0) { return; } offset = old_offset+next_offset; if (offset < old_offset) { proto_tree_add_expert_format(tree, pinfo, &ei_smb2_invalid_length, tvb, offset, -1, "Invalid offset/length. Malformed packet"); return; } } } static void dissect_smb2_id_full_directory_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, smb2_info_t *si _U_) { int offset = 0; proto_item *item = NULL; proto_tree *tree = NULL; const char *name = NULL; guint16 bc; while (tvb_reported_length_remaining(tvb, offset) > 4) { int old_offset = offset; int next_offset; int file_name_len; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_id_both_directory_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_id_both_directory_info); } /* next offset */ next_offset = tvb_get_letohl(tvb, offset); proto_tree_add_item(tree, hf_smb2_next_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* file index */ proto_tree_add_item(tree, hf_smb2_file_index, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* create time */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_create_timestamp); /* last access */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_access_timestamp); /* last write */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_write_timestamp); /* last change */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_change_timestamp); /* end of file */ proto_tree_add_item(tree, hf_smb2_end_of_file, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* allocation size */ proto_tree_add_item(tree, hf_smb2_allocation_size, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* File Attributes */ offset = dissect_file_ext_attr(tvb, tree, offset); /* file name length */ file_name_len = tvb_get_letohl(tvb, offset); proto_tree_add_item(tree, hf_smb2_filename_len, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* ea size */ proto_tree_add_item(tree, hf_smb2_ea_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA); offset += 4; /* file id */ proto_tree_add_item(tree, hf_smb2_file_id, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* file name */ if (file_name_len) { bc = file_name_len; name = get_unicode_or_ascii_string(tvb, &offset, TRUE, &file_name_len, TRUE, TRUE, &bc); if (name) { proto_tree_add_string(tree, hf_smb2_filename, tvb, offset, file_name_len, name); proto_item_append_text(item, ": %s", name); } } proto_item_set_len(item, offset-old_offset); if (next_offset == 0) { return; } offset = old_offset+next_offset; if (offset < old_offset) { proto_tree_add_expert_format(tree, pinfo, &ei_smb2_invalid_length, tvb, offset, -1, "Invalid offset/length. Malformed packet"); return; } } } typedef struct _smb2_find_dissector_t { guint32 level; void (*dissector)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si); } smb2_find_dissector_t; smb2_find_dissector_t smb2_find_dissectors[] = { {SMB2_FIND_DIRECTORY_INFO, dissect_smb2_file_directory_info}, {SMB2_FIND_FULL_DIRECTORY_INFO, dissect_smb2_full_directory_info}, {SMB2_FIND_BOTH_DIRECTORY_INFO, dissect_smb2_both_directory_info}, {SMB2_FIND_NAME_INFO, dissect_smb2_file_name_info}, {SMB2_FIND_ID_BOTH_DIRECTORY_INFO,dissect_smb2_id_both_directory_info}, {SMB2_FIND_ID_FULL_DIRECTORY_INFO,dissect_smb2_id_full_directory_info}, {0, NULL} }; static void dissect_smb2_find_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si) { smb2_find_dissector_t *dis = smb2_find_dissectors; while (dis->dissector) { 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_captured_length(tvb), ENC_NA); } static int dissect_smb2_find_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_) { offset_length_buffer_t olb; proto_item *item = NULL; gboolean continue_dissection; if (si->saved) { /* infolevel */ item = proto_tree_add_uint(tree, hf_smb2_find_info_level, tvb, offset, 0, si->saved->infolevel); PROTO_ITEM_SET_GENERATED(item); } if (!pinfo->fd->visited && si->saved && si->saved->extra_info_type == SMB2_EI_FINDPATTERN) { col_append_fstr(pinfo->cinfo, COL_INFO, " %s Pattern: %s", val_to_str(si->saved->infolevel, smb2_find_info_levels, "(Level:0x%02x)"), (const char *)si->saved->extra_info); wmem_free(wmem_file_scope(), si->saved->extra_info); si->saved->extra_info_type = SMB2_EI_NONE; si->saved->extra_info = NULL; } switch (si->status) { /* buffer code */ 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); /* the buffer */ dissect_smb2_olb_buffer(pinfo, tree, tvb, &olb, si, dissect_smb2_find_data); offset = dissect_smb2_olb_tvb_max_offset(offset, &olb); return offset; } static int dissect_smb2_negotiate_context(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { guint16 type; const gchar *type_str; guint32 i, data_length, salt_length, hash_count, cipher_count; proto_item *sub_item; proto_tree *sub_tree; 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; /* data length */ proto_tree_add_item_ret_uint(sub_tree, hf_smb2_negotiate_context_data_length, tvb, offset, 2, ENC_LITTLE_ENDIAN, &data_length); offset += 2; /* reserved */ proto_tree_add_item(sub_tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA); offset += 4; switch (type) { case SMB2_PREAUTH_INTEGRITY_CAPABILITIES: proto_tree_add_item_ret_uint(sub_tree, hf_smb2_hash_alg_count, tvb, offset, 2, ENC_LITTLE_ENDIAN, &hash_count); offset += 2; proto_tree_add_item_ret_uint(sub_tree, hf_smb2_salt_length, tvb, offset, 2, ENC_LITTLE_ENDIAN, &salt_length); offset += 2; for (i = 0; i < hash_count; i++) { proto_tree_add_item(sub_tree, hf_smb2_hash_algorithm, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; } if (salt_length) { proto_tree_add_item(sub_tree, hf_smb2_salt, tvb, offset, salt_length, ENC_NA); offset += salt_length; } break; case SMB2_ENCRYPTION_CAPABILITIES: proto_tree_add_item_ret_uint(sub_tree, hf_smb2_cipher_count, tvb, offset, 2, ENC_LITTLE_ENDIAN, &cipher_count); offset += 2; for (i = 0; i < cipher_count; i ++) { proto_tree_add_item(sub_tree, hf_smb2_cipher_id, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; } break; default: proto_tree_add_item(sub_tree, hf_smb2_unknown, tvb, offset, data_length, ENC_NA); offset += data_length; break; } 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 */ offset = dissect_smb2_capabilities(tree, tvb, offset); /* client guid */ proto_tree_add_item(tree, hf_smb2_client_guid, tvb, offset, 16, ENC_LITTLE_ENDIAN); offset += 16; /* 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; /* 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; } static int 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) { /* buffer code */ 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; /* 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 */ proto_tree_add_item(tree, hf_smb2_server_guid, tvb, offset, 16, ENC_LITTLE_ENDIAN); offset += 16; /* capabilities */ offset = dissect_smb2_capabilities(tree, tvb, offset); /* max trans size */ proto_tree_add_item(tree, hf_smb2_max_trans_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* max read size */ proto_tree_add_item(tree, hf_smb2_max_read_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* max write size */ proto_tree_add_item(tree, hf_smb2_max_write_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* current time */ dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_current_time); offset += 8; /* boot time */ dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_boot_time); offset += 8; /* security blob offset/length */ offset = dissect_smb2_olb_length_offset(tvb, offset, &s_olb, OLB_O_UINT16_S_UINT16, hf_smb2_security_blob); /* the security blob itself */ dissect_smb2_olb_buffer(pinfo, tree, tvb, &s_olb, si, dissect_smb2_secblob); /* 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; } static int dissect_smb2_getinfo_parameters(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si) { /* Additional Info */ switch (si->saved->smb2_class) { case SMB2_CLASS_SEC_INFO: dissect_security_information_mask(tvb, tree, offset); break; default: proto_tree_add_item(tree, hf_smb2_getinfo_additional, tvb, offset, 4, ENC_LITTLE_ENDIAN); } offset += 4; /* Flags */ proto_tree_add_item(tree, hf_smb2_getinfo_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; return offset; } static int dissect_smb2_getinfo_buffer_quota(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { guint32 sidlist_len = 0; guint32 startsid_len = 0; guint32 startsid_offset = 0; proto_item *item = NULL; proto_tree *tree = NULL; if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_query_quota_info, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_query_quota_info); } proto_tree_add_item(tree, hf_smb2_qq_single, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(tree, hf_smb2_qq_restart, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 2, ENC_NA); offset += 2; proto_tree_add_item_ret_uint(tree, hf_smb2_qq_sidlist_len, tvb, offset, 4, ENC_LITTLE_ENDIAN, &sidlist_len); offset += 4; proto_tree_add_item_ret_uint(tree, hf_smb2_qq_start_sid_len, tvb, offset, 4, ENC_LITTLE_ENDIAN, &startsid_len); offset += 4; proto_tree_add_item_ret_uint(tree, hf_smb2_qq_start_sid_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN, &startsid_offset); offset += 4; if (sidlist_len != 0) { offset = dissect_nt_get_user_quota(tvb, tree, offset, &sidlist_len); } else if (startsid_len != 0) { offset = dissect_nt_sid(tvb, offset + startsid_offset, tree, "Start SID", NULL, -1); } return offset; } static int dissect_smb2_class_infolevel(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree *tree, smb2_info_t *si) { guint8 cl, il; proto_item *item; int hfindex; value_string_ext *vsx; if (si->flags & SMB2_FLAGS_RESPONSE) { if (!si->saved) { return offset; } cl = si->saved->smb2_class; il = si->saved->infolevel; } else { cl = tvb_get_guint8(tvb, offset); il = tvb_get_guint8(tvb, offset+1); if (si->saved) { si->saved->smb2_class = cl; si->saved->infolevel = il; } } switch (cl) { case SMB2_CLASS_FILE_INFO: hfindex = hf_smb2_infolevel_file_info; vsx = &smb2_file_info_levels_ext; break; case SMB2_CLASS_FS_INFO: hfindex = hf_smb2_infolevel_fs_info; vsx = &smb2_fs_info_levels_ext; break; case SMB2_CLASS_SEC_INFO: hfindex = hf_smb2_infolevel_sec_info; vsx = &smb2_sec_info_levels_ext; break; case SMB2_CLASS_QUOTA_INFO: /* infolevel is not being used for quota */ hfindex = hf_smb2_infolevel; vsx = NULL; 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() */ } /* class */ item = proto_tree_add_uint(tree, hf_smb2_class, tvb, offset, 1, cl); if (si->flags & SMB2_FLAGS_RESPONSE) { PROTO_ITEM_SET_GENERATED(item); } /* infolevel */ item = proto_tree_add_uint(tree, hfindex, tvb, offset+1, 1, il); if (si->flags & SMB2_FLAGS_RESPONSE) { PROTO_ITEM_SET_GENERATED(item); } offset += 2; if (!(si->flags & SMB2_FLAGS_RESPONSE)) { /* Only update COL_INFO for requests. It clutters the * display a bit too much if we do it for replies * as well. */ col_append_fstr(pinfo->cinfo, COL_INFO, " %s/%s", val_to_str(cl, smb2_class_vals, "(Class:0x%02x)"), val_to_str_ext(il, vsx, "(Level:0x%02x)")); } return offset; } static int dissect_smb2_getinfo_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si) { guint32 getinfo_size = 0; guint32 getinfo_offset = 0; proto_item *offset_item; /* buffer code */ offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); /* class and info level */ offset = dissect_smb2_class_infolevel(pinfo, tvb, offset, tree, si); /* max response size */ proto_tree_add_item(tree, hf_smb2_max_response_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* offset */ offset_item = proto_tree_add_item_ret_uint(tree, hf_smb2_getinfo_input_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN, &getinfo_offset); offset += 2; /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 2, ENC_NA); offset += 2; /* size */ proto_tree_add_item_ret_uint(tree, hf_smb2_getinfo_input_size, tvb, offset, 4, ENC_LITTLE_ENDIAN, &getinfo_size); offset += 4; /* parameters */ if (si->saved) { offset = dissect_smb2_getinfo_parameters(tvb, pinfo, tree, offset, si); } else { /* some unknown bytes */ proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, 8, ENC_NA); offset += 8; } /* fid */ offset = dissect_smb2_fid(tvb, pinfo, tree, offset, si, FID_MODE_USE); /* buffer */ if (si->saved) { if (getinfo_size != 0) { /* * 2.2.37 says "For quota requests, this MUST be * the length of the contained SMB2_QUERY_QUOTA_INFO * embedded in the request. For FileFullEaInformation * requests, this MUST be set to the length of the * user supplied EA list specified in [MS-FSCC] * section 2.4.15.1. For other information queries, * this field SHOULD be set to 0 and the server MUST * ignore it on receipt. * * This seems to imply that, for requests other * than those to types, we should either completely * ignore a non-zero getinfo_size or should, at * most, add a warning-level expert info at the * protocol level saying that it should be zero, * but not try and interpret it or check its * validity. */ if (si->saved->smb2_class == SMB2_CLASS_QUOTA_INFO || (si->saved->smb2_class == SMB2_CLASS_FILE_INFO && si->saved->infolevel == SMB2_FILE_FULL_EA_INFO)) { /* * According to 2.2.37 SMB2 QUERY_INFO * Request in the current MS-SMB2 spec, * these are the only info requests that * have an input buffer. */ /* * Make sure that the input buffer is after * the fixed-length part of the message. */ if (getinfo_offset < (guint)offset) { expert_add_info(pinfo, offset_item, &ei_smb2_invalid_getinfo_offset); return offset; } /* * Make sure the input buffer is within the * message, i.e. that it's within the tvbuff. * * We check for offset+length overflowing and * for offset+length being beyond the reported * length of the tvbuff. */ if (getinfo_offset + getinfo_size < getinfo_offset || getinfo_offset + getinfo_size > tvb_reported_length(tvb)) { expert_add_info(pinfo, offset_item, &ei_smb2_invalid_getinfo_size); return offset; } if (si->saved->smb2_class == SMB2_CLASS_QUOTA_INFO) { dissect_smb2_getinfo_buffer_quota(tvb, pinfo, tree, getinfo_offset, si); } else { /* * XXX - handle user supplied EA info. */ proto_tree_add_item(tree, hf_smb2_unknown, tvb, getinfo_offset, getinfo_size, ENC_NA); } offset = getinfo_offset + getinfo_size; } } else { /* * The buffer size is 0, meaning it's not present. * * 2.2.37 says "For FileFullEaInformation requests, * the input buffer MUST contain the user supplied * EA list with zero or more FILE_GET_EA_INFORMATION * structures, specified in [MS-FSCC] section * 2.4.15.1.", so it seems that, for a "get full * EA information" request, the size can be zero - * there's no other obvious way for the list to * have zero structures. * * 2.2.37 also says "For quota requests, the input * buffer MUST contain an SMB2_QUERY_QUOTA_INFO, * as specified in section 2.2.37.1."; that seems * to imply that the input buffer must not be empty * in that case. */ if (si->saved->smb2_class == SMB2_CLASS_QUOTA_INFO) expert_add_info(pinfo, offset_item, &ei_smb2_empty_getinfo_buffer); } } return offset; } static int dissect_smb2_infolevel(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si, guint8 smb2_class, guint8 infolevel) { int old_offset = offset; switch (smb2_class) { case SMB2_CLASS_FILE_INFO: switch (infolevel) { case SMB2_FILE_BASIC_INFO: offset = dissect_smb2_file_basic_info(tvb, pinfo, tree, offset, si); break; case SMB2_FILE_STANDARD_INFO: offset = dissect_smb2_file_standard_info(tvb, pinfo, tree, offset, si); break; case SMB2_FILE_INTERNAL_INFO: offset = dissect_smb2_file_internal_info(tvb, pinfo, tree, offset, si); break; case SMB2_FILE_EA_INFO: offset = dissect_smb2_file_ea_info(tvb, pinfo, tree, offset, si); break; case SMB2_FILE_ACCESS_INFO: offset = dissect_smb2_file_access_info(tvb, pinfo, tree, offset, si); break; case SMB2_FILE_RENAME_INFO: offset = dissect_smb2_file_rename_info(tvb, pinfo, tree, offset, si); break; case SMB2_FILE_DISPOSITION_INFO: offset = dissect_smb2_file_disposition_info(tvb, pinfo, tree, offset, si); break; case SMB2_FILE_POSITION_INFO: offset = dissect_smb2_file_position_info(tvb, pinfo, tree, offset, si); break; case SMB2_FILE_FULL_EA_INFO: offset = dissect_smb2_file_full_ea_info(tvb, pinfo, tree, offset, si); break; case SMB2_FILE_MODE_INFO: offset = dissect_smb2_file_mode_info(tvb, pinfo, tree, offset, si); break; case SMB2_FILE_ALIGNMENT_INFO: offset = dissect_smb2_file_alignment_info(tvb, pinfo, tree, offset, si); break; case SMB2_FILE_ALL_INFO: offset = dissect_smb2_file_all_info(tvb, pinfo, tree, offset, si); break; case SMB2_FILE_ALLOCATION_INFO: offset = dissect_smb2_file_allocation_info(tvb, pinfo, tree, offset, si); break; case SMB2_FILE_ENDOFFILE_INFO: dissect_smb2_file_endoffile_info(tvb, pinfo, tree, offset, si); break; case SMB2_FILE_ALTERNATE_NAME_INFO: offset = dissect_smb2_file_alternate_name_info(tvb, pinfo, tree, offset, si); break; case SMB2_FILE_STREAM_INFO: offset = dissect_smb2_file_stream_info(tvb, pinfo, tree, offset, si); break; case SMB2_FILE_PIPE_INFO: offset = dissect_smb2_file_pipe_info(tvb, pinfo, tree, offset, si); break; case SMB2_FILE_COMPRESSION_INFO: offset = dissect_smb2_file_compression_info(tvb, pinfo, tree, offset, si); break; case SMB2_FILE_NETWORK_OPEN_INFO: offset = dissect_smb2_file_network_open_info(tvb, pinfo, tree, offset, si); break; case SMB2_FILE_ATTRIBUTE_TAG_INFO: offset = dissect_smb2_file_attribute_tag_info(tvb, pinfo, tree, offset, si); break; default: /* 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: switch (infolevel) { case SMB2_FS_INFO_01: offset = dissect_smb2_fs_info_01(tvb, pinfo, tree, offset, si); break; case SMB2_FS_INFO_03: offset = dissect_smb2_fs_info_03(tvb, pinfo, tree, offset, si); break; case SMB2_FS_INFO_04: offset = dissect_smb2_fs_info_04(tvb, pinfo, tree, offset, si); break; case SMB2_FS_INFO_05: offset = dissect_smb2_fs_info_05(tvb, pinfo, tree, offset, si); break; case SMB2_FS_INFO_06: offset = dissect_smb2_fs_info_06(tvb, pinfo, tree, offset, si); break; case SMB2_FS_INFO_07: offset = dissect_smb2_fs_info_07(tvb, pinfo, tree, offset, si); break; case SMB2_FS_OBJECTID_INFO: offset = dissect_smb2_FS_OBJECTID_INFO(tvb, pinfo, tree, offset, si); break; default: /* 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: switch (infolevel) { case SMB2_SEC_INFO_00: offset = dissect_smb2_sec_info_00(tvb, pinfo, tree, offset, si); break; default: /* 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_QUOTA_INFO: offset = dissect_smb2_quota_info(tvb, pinfo, tree, offset, si); break; default: /* 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_item(tree, hf_smb2_truncated, tvb, old_offset, 0, ENC_NA); PROTO_ITEM_SET_GENERATED(item); } return offset; } static void dissect_smb2_getinfo_response_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si) { /* data */ if (si->saved) { 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_captured_length(tvb), ENC_NA); } } static int 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: /* if we get BUFFER_OVERFLOW there will be truncated data */ 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); proto_tree_add_item(tree, hf_smb2_required_buffer_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; return offset; default: offset = dissect_smb2_error_response(tvb, pinfo, tree, offset, si, &continue_dissection); if (!continue_dissection) return offset; } /* response buffer offset and size */ offset = dissect_smb2_olb_length_offset(tvb, offset, &olb, OLB_O_UINT16_S_UINT32, -1); /* response data*/ dissect_smb2_olb_buffer(pinfo, tree, tvb, &olb, si, dissect_smb2_getinfo_response_data); return offset; } static int dissect_smb2_close_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si) { proto_tree *flags_tree = NULL; proto_item *flags_item = NULL; /* buffer code */ offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); /* close flags */ if (tree) { flags_item = proto_tree_add_item(tree, hf_smb2_close_flags, tvb, offset, 2, ENC_LITTLE_ENDIAN); flags_tree = proto_item_add_subtree(flags_item, ett_smb2_close_flags); } proto_tree_add_item(flags_tree, hf_smb2_close_pq_attrib, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* padding */ offset += 4; /* fid */ offset = dissect_smb2_fid(tvb, pinfo, tree, offset, si, FID_MODE_CLOSE); return offset; } static int dissect_smb2_close_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_) { proto_tree *flags_tree = NULL; proto_item *flags_item = NULL; gboolean continue_dissection; switch (si->status) { /* buffer code */ 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) { flags_item = proto_tree_add_item(tree, hf_smb2_close_flags, tvb, offset, 2, ENC_LITTLE_ENDIAN); flags_tree = proto_item_add_subtree(flags_item, ett_smb2_close_flags); } proto_tree_add_item(flags_tree, hf_smb2_close_pq_attrib, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA); offset += 4; /* create time */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_create_timestamp); /* last access */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_access_timestamp); /* last write */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_write_timestamp); /* last change */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_change_timestamp); /* allocation size */ proto_tree_add_item(tree, hf_smb2_allocation_size, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* end of file */ proto_tree_add_item(tree, hf_smb2_end_of_file, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* File Attributes */ offset = dissect_file_ext_attr(tvb, tree, offset); return offset; } static int dissect_smb2_flush_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si) { /* buffer code */ offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); /* some unknown bytes */ proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, 6, ENC_NA); offset += 6; /* fid */ offset = dissect_smb2_fid(tvb, pinfo, tree, offset, si, FID_MODE_USE); return offset; } static int dissect_smb2_flush_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_) { gboolean continue_dissection; switch (si->status) { /* buffer code */ 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); offset += 2; return offset; } static int dissect_smb2_lock_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si) { guint16 lock_count; /* buffer code */ offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); /* lock count */ lock_count = tvb_get_letohs(tvb, offset); proto_tree_add_item(tree, hf_smb2_lock_count, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA); offset += 4; /* fid */ offset = dissect_smb2_fid(tvb, pinfo, tree, offset, si, FID_MODE_USE); while (lock_count--) { proto_item *lock_item = NULL; proto_tree *lock_tree = NULL; static const int *lf_fields[] = { &hf_smb2_lock_flags_shared, &hf_smb2_lock_flags_exclusive, &hf_smb2_lock_flags_unlock, &hf_smb2_lock_flags_fail_immediately, NULL }; if (tree) { lock_item = proto_tree_add_item(tree, hf_smb2_lock_info, tvb, offset, 24, ENC_NA); lock_tree = proto_item_add_subtree(lock_item, ett_smb2_lock_info); } /* offset */ proto_tree_add_item(tree, hf_smb2_file_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* count */ proto_tree_add_item(lock_tree, hf_smb2_lock_length, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* flags */ proto_tree_add_bitmask(lock_tree, tvb, offset, hf_smb2_lock_flags, ett_smb2_lock_flags, lf_fields, ENC_LITTLE_ENDIAN); offset += 4; /* reserved */ proto_tree_add_item(lock_tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA); offset += 4; } return offset; } static int dissect_smb2_lock_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_) { gboolean continue_dissection; switch (si->status) { /* buffer code */ 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); offset += 2; return offset; } static int dissect_smb2_cancel_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_) { /* buffer code */ offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); /* some unknown bytes */ proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, 2, ENC_NA); offset += 2; 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 int 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) { /* * 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_length_caplen(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->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 */ 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; 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 dissect_smb2_write_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si) { guint16 dataoffset = 0; guint32 data_tvb_len; offset_length_buffer_t c_olb; guint32 channel; guint32 length; guint64 off; static const int *f_fields[] = { &hf_smb2_write_flags_write_through, NULL }; /* buffer code */ offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); /* data offset */ dataoffset=tvb_get_letohs(tvb,offset); proto_tree_add_item(tree, hf_smb2_data_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* length */ length = tvb_get_letohl(tvb, offset); proto_tree_add_item(tree, hf_smb2_write_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* offset */ off = tvb_get_letoh64(tvb, offset); if (si->saved) si->saved->file_offset=off; proto_tree_add_item(tree, hf_smb2_file_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; col_append_fstr(pinfo->cinfo, COL_INFO, " Len:%d Off:%" G_GINT64_MODIFIER "u", length, off); /* fid */ 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; /* remaining bytes */ proto_tree_add_item(tree, hf_smb2_remaining_bytes, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* 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; /* 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_tvb_len=(guint32)tvb_captured_length_remaining(tvb, 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 */ goto out; } } /* just ordinary data */ proto_tree_add_item(tree, hf_smb2_write_data, tvb, offset, length, ENC_NA); offset += MIN(length,(guint32)tvb_captured_length_remaining(tvb, offset)); offset = dissect_smb2_olb_tvb_max_offset(offset, &c_olb); out: 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 */ feed_eo_smb2(tvb,pinfo,si,dataoffset,length,off); } } return offset; } static int dissect_smb2_write_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, smb2_info_t *si _U_) { gboolean continue_dissection; switch (si->status) { /* buffer code */ 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); offset += 2; /* count */ proto_tree_add_item(tree, hf_smb2_write_count, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* remaining, must be set to 0 */ proto_tree_add_item(tree, hf_smb2_write_remaining, 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; return offset; } /* 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) { proto_tree *sub_tree; proto_item *sub_item; guint32 idlen = 0; guint32 idtype = 0; sub_tree = proto_tree_add_subtree(tree, tvb, offset, 512, ett_smb2_fsctl_odx_token, &sub_item, "Token"); 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(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_smb2_FSCTL_OFFLOAD_READ(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, gboolean in) { proto_tree_add_item(tree, hf_smb2_fsctl_odx_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_smb2_fsctl_odx_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; if (in) { proto_tree_add_item(tree, hf_smb2_fsctl_odx_token_ttl, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA); offset += 4; 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; */ } 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_smb2_FSCTL_OFFLOAD_WRITE(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, gboolean in) { proto_tree_add_item(tree, hf_smb2_fsctl_odx_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_smb2_fsctl_odx_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; 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, packet_info *pinfo _U_, proto_tree *tree, int offset, gboolean data_in) { /* There is no in data */ if (data_in) { return; } proto_tree_add_item(tree, hf_smb2_ioctl_shared_virtual_disk_support, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_smb2_ioctl_shared_virtual_disk_handle_state, tvb, offset, 4, ENC_LITTLE_ENDIAN); } #define STORAGE_QOS_CONTROL_FLAG_SET_LOGICAL_FLOW_ID 0x00000001 #define STORAGE_QOS_CONTROL_FLAG_SET_POLICY 0x00000002 #define STORAGE_QOS_CONTROL_FLAG_PROBE_POLICY 0x00000004 #define STORAGE_QOS_CONTROL_FLAG_GET_STATUS 0x00000008 #define STORAGE_QOS_CONTROL_FLAG_UPDATE_COUNTERS 0x00000010 static const value_string smb2_ioctl_sqos_protocol_version_vals[] = { { 0x0100, "Storage QoS Protocol Version 1.0" }, { 0x0101, "Storage QoS Protocol Version 1.1" }, { 0, NULL } }; static const value_string smb2_ioctl_sqos_status_vals[] = { { 0x00, "StorageQoSStatusOk" }, { 0x01, "StorageQoSStatusInsufficientThroughput" }, { 0x02, "StorageQoSUnknownPolicyId" }, { 0x04, "StorageQoSStatusConfigurationMismatch" }, { 0x05, "StorageQoSStatusNotAvailable" }, { 0, NULL } }; static void dissect_smb2_FSCTL_STORAGE_QOS_CONTROL(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, gboolean data_in) { static const int * operations[] = { &hf_smb2_ioctl_sqos_op_set_logical_flow_id, &hf_smb2_ioctl_sqos_op_set_policy, &hf_smb2_ioctl_sqos_op_probe_policy, &hf_smb2_ioctl_sqos_op_get_status, &hf_smb2_ioctl_sqos_op_update_counters, NULL }; gint proto_ver; /* Both request and reply have the same common header */ proto_ver = tvb_get_letohs(tvb, offset); proto_tree_add_item(tree, hf_smb2_ioctl_sqos_protocol_version, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(tree, hf_smb2_ioctl_sqos_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_bitmask(tree, tvb, offset, hf_smb2_ioctl_sqos_options, ett_smb2_ioctl_sqos_opeations, operations, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_smb2_ioctl_sqos_logical_flow_id, tvb, offset, 16, ENC_LITTLE_ENDIAN); offset += 16; proto_tree_add_item(tree, hf_smb2_ioctl_sqos_policy_id, tvb, offset, 16, ENC_LITTLE_ENDIAN); offset += 16; proto_tree_add_item(tree, hf_smb2_ioctl_sqos_initiator_id, tvb, offset, 16, ENC_LITTLE_ENDIAN); offset += 16; if (data_in) { offset_length_buffer_t host_olb, node_olb; proto_tree_add_item(tree, hf_smb2_ioctl_sqos_limit, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; proto_tree_add_item(tree, hf_smb2_ioctl_sqos_reservation, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; offset = dissect_smb2_olb_length_offset(tvb, offset, &host_olb, OLB_O_UINT16_S_UINT16, hf_smb2_ioctl_sqos_initiator_name); offset = dissect_smb2_olb_length_offset(tvb, offset, &node_olb, OLB_O_UINT16_S_UINT16, hf_smb2_ioctl_sqos_initiator_node_name); proto_tree_add_item(tree, hf_smb2_ioctl_sqos_io_count_increment, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; proto_tree_add_item(tree, hf_smb2_ioctl_sqos_normalized_io_count_increment, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; proto_tree_add_item(tree, hf_smb2_ioctl_sqos_latency_increment, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; proto_tree_add_item(tree, hf_smb2_ioctl_sqos_lower_latency_increment, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; if (proto_ver > 0x0100) { proto_tree_add_item(tree, hf_smb2_ioctl_sqos_bandwidth_limit, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; proto_tree_add_item(tree, hf_smb2_ioctl_sqos_kilobyte_count_increment, tvb, offset, 8, ENC_LITTLE_ENDIAN); /*offset += 8;*/ } dissect_smb2_olb_string(pinfo, tree, tvb, &host_olb, OLB_TYPE_UNICODE_STRING); dissect_smb2_olb_string(pinfo, tree, tvb, &node_olb, OLB_TYPE_UNICODE_STRING); } else { proto_tree_add_item(tree, hf_smb2_ioctl_sqos_time_to_live, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_smb2_ioctl_sqos_status, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_smb2_ioctl_sqos_maximum_io_rate, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; proto_tree_add_item(tree, hf_smb2_ioctl_sqos_minimum_io_rate, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; proto_tree_add_item(tree, hf_smb2_ioctl_sqos_base_io_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_smb2_ioctl_sqos_reserved2, tvb, offset, 4, ENC_LITTLE_ENDIAN); if (proto_ver > 0x0100) { offset += 4; proto_tree_add_item(tree, hf_smb2_ioctl_sqos_maximum_bandwidth, tvb, offset, 8, ENC_LITTLE_ENDIAN); } } } 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 += 2; /* port */ proto_tree_add_item(sub_tree, hf_windows_sockaddr_port, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* sin6_flowinfo */ proto_tree_add_item(sub_tree, hf_windows_sockaddr_in6_flowinfo, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 4; /* IPv4 address */ 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 */ proto_tree_add_item(sub_tree, hf_windows_sockaddr_in6_scope_id, tvb, offset, 2, ENC_LITTLE_ENDIAN); } static void dissect_windows_sockaddr_storage(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset) { int len = 128; proto_item *sub_item; proto_tree *sub_tree; proto_item *parent_item; guint16 family; family = tvb_get_letohs(tvb, offset); switch (family) { case WINSOCK_AF_INET: dissect_windows_sockaddr_in(tvb, pinfo, parent_tree, offset, len); return; case WINSOCK_AF_INET6: dissect_windows_sockaddr_in6(tvb, pinfo, parent_tree, offset, len); return; } 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); 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 */ /*offset += 126;*/ } #define NETWORK_INTERFACE_CAP_RSS 0x00000001 #define NETWORK_INTERFACE_CAP_RDMA 0x00000002 static void dissect_smb2_NETWORK_INTERFACE_INFO(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) { guint32 next_offset; int offset = 0; int len = -1; 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; } 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); offset += 4; /* interface index */ proto_tree_add_item(sub_tree, hf_smb2_ioctl_network_interface_index, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* capabilities */ capabilities = tvb_get_letohl(tvb, offset); 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":""); proto_item_append_text(sub_item, "%s%s", (capabilities & NETWORK_INTERFACE_CAP_RDMA)?", RDMA":"", (capabilities & NETWORK_INTERFACE_CAP_RSS)?", RSS":""); } offset += 4; /* rss queue count */ proto_tree_add_item(sub_tree, hf_smb2_ioctl_network_interface_rss_queue_count, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* link speed */ link_speed = tvb_get_letoh64(tvb, offset); item = proto_tree_add_item(sub_tree, hf_smb2_ioctl_network_interface_link_speed, tvb, offset, 8, ENC_LITTLE_ENDIAN); if (link_speed >= (1000*1000*1000)) { val = (gfloat)(link_speed / (1000*1000*1000)); unit = "G"; } else if (link_speed >= (1000*1000)) { val = (gfloat)(link_speed / (1000*1000)); unit = "M"; } else if (link_speed >= (1000)) { val = (gfloat)(link_speed / (1000)); unit = "K"; } else { val = (gfloat)(link_speed); unit = ""; } proto_item_append_text(item, ", %.1f %sBits/s", val, unit); proto_item_append_text(sub_item, ", %.1f %sBits/s", val, unit); offset += 8; /* socket address */ dissect_windows_sockaddr_storage(tvb, pinfo, sub_tree, offset); if (next_offset) { tvbuff_t *next_tvb; next_tvb = tvb_new_subset_remaining(tvb, next_offset); /* next extra info */ dissect_smb2_NETWORK_INTERFACE_INFO(next_tvb, pinfo, parent_tree); } } static void dissect_smb2_FSCTL_QUERY_NETWORK_INTERFACE_INFO(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset _U_, gboolean data_in) { /* There is no in data */ if (data_in) { return; } dissect_smb2_NETWORK_INTERFACE_INFO(tvb, pinfo, tree); } static void dissect_smb2_FSCTL_VALIDATE_NEGOTIATE_INFO_224(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset _U_, gboolean data_in) { /* * This is only used by Windows 8 beta */ if (data_in) { /* capabilities */ offset = dissect_smb2_capabilities(tree, tvb, offset); /* client guid */ proto_tree_add_item(tree, hf_smb2_client_guid, tvb, offset, 16, ENC_LITTLE_ENDIAN); offset += 16; /* security mode, skip second byte */ offset = dissect_smb2_secmode(tree, tvb, offset); offset++; /* dialect */ proto_tree_add_item(tree, hf_smb2_dialect, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; } else { /* capabilities */ offset = dissect_smb2_capabilities(tree, tvb, offset); /* server guid */ proto_tree_add_item(tree, hf_smb2_server_guid, tvb, offset, 16, ENC_LITTLE_ENDIAN); offset += 16; /* security mode, skip second byte */ offset = dissect_smb2_secmode(tree, tvb, offset); offset++; /* dialect */ proto_tree_add_item(tree, hf_smb2_dialect, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; } } static void dissect_smb2_FSCTL_VALIDATE_NEGOTIATE_INFO(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset _U_, gboolean data_in) { if (data_in) { guint16 dc; /* capabilities */ offset = dissect_smb2_capabilities(tree, tvb, offset); /* client guid */ proto_tree_add_item(tree, hf_smb2_client_guid, tvb, offset, 16, ENC_LITTLE_ENDIAN); offset += 16; /* security mode, skip second byte */ offset = dissect_smb2_secmode(tree, tvb, offset); offset++; /* 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; for ( ; dc>0; dc--) { proto_tree_add_item(tree, hf_smb2_dialect, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; } } else { /* capabilities */ offset = dissect_smb2_capabilities(tree, tvb, offset); /* server guid */ proto_tree_add_item(tree, hf_smb2_server_guid, tvb, offset, 16, ENC_LITTLE_ENDIAN); offset += 16; /* security mode, skip second byte */ offset = dissect_smb2_secmode(tree, tvb, offset); offset++; /* dialect */ proto_tree_add_item(tree, hf_smb2_dialect, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; } } static void dissect_smb2_FSCTL_SRV_ENUMERATE_SNAPSHOTS(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, gboolean data_in) { guint32 num_volumes; /* There is no in data */ if (data_in) { return; } /* num volumes */ num_volumes = tvb_get_letohl(tvb, offset); proto_tree_add_item(tree, hf_smb2_ioctl_shadow_copy_num_volumes, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* num labels */ proto_tree_add_item(tree, hf_smb2_ioctl_shadow_copy_num_labels, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* count */ proto_tree_add_item(tree, hf_smb2_ioctl_shadow_copy_count, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; while (num_volumes--) { const char *name; guint16 bc; int len = 0; int old_offset = 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); offset = old_offset+len; if (!len) { break; } } } int dissect_smb2_FILE_OBJECTID_BUFFER(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset) { proto_item *item = NULL; proto_tree *tree = NULL; /* FILE_OBJECTID_BUFFER */ if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_FILE_OBJECTID_BUFFER, tvb, offset, 64, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_FILE_OBJECTID_BUFFER); } /* Object ID */ proto_tree_add_item(tree, hf_smb2_object_id, tvb, offset, 16, ENC_LITTLE_ENDIAN); offset += 16; /* Birth Volume ID */ proto_tree_add_item(tree, hf_smb2_birth_volume_id, tvb, offset, 16, ENC_LITTLE_ENDIAN); offset += 16; /* Birth Object ID */ proto_tree_add_item(tree, hf_smb2_birth_object_id, tvb, offset, 16, ENC_LITTLE_ENDIAN); offset += 16; /* Domain ID */ proto_tree_add_item(tree, hf_smb2_domain_id, tvb, offset, 16, ENC_LITTLE_ENDIAN); offset += 16; return offset; } static int dissect_smb2_FSCTL_CREATE_OR_GET_OBJECT_ID(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; } /* FILE_OBJECTID_BUFFER */ offset = dissect_smb2_FILE_OBJECTID_BUFFER(tvb, pinfo, tree, offset); return offset; } static int dissect_smb2_FSCTL_GET_COMPRESSION(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; } /* compression format */ proto_tree_add_item(tree, hf_smb2_compression_format, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; return offset; } static int dissect_smb2_FSCTL_SET_COMPRESSION(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; } /* compression format */ proto_tree_add_item(tree, hf_smb2_compression_format, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; 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) { /* There is no out data */ if (!data_in) { return offset; } /* FILE_OBJECTID_BUFFER */ offset = dissect_smb2_FILE_OBJECTID_BUFFER(tvb, pinfo, tree, offset); return offset; } static int dissect_smb2_FSCTL_SET_OBJECT_ID_EXTENDED(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; } /* FILE_OBJECTID_BUFFER->ExtendedInfo */ /* Birth Volume ID */ proto_tree_add_item(tree, hf_smb2_birth_volume_id, tvb, offset, 16, ENC_LITTLE_ENDIAN); offset += 16; /* Birth Object ID */ proto_tree_add_item(tree, hf_smb2_birth_object_id, tvb, offset, 16, ENC_LITTLE_ENDIAN); offset += 16; /* Domain ID */ proto_tree_add_item(tree, hf_smb2_domain_id, tvb, offset, 16, ENC_LITTLE_ENDIAN); offset += 16; 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); } 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--; } } static void dissect_smb2_FSCTL_REPARSE_POINT(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset) { proto_item *item = NULL; proto_tree *tree = NULL; offset_length_buffer_t s_olb, p_olb; /* SYMBOLIC_LINK_REPARSE_DATA_BUFFER */ if (parent_tree) { item = proto_tree_add_item(parent_tree, hf_smb2_SYMBOLIC_LINK_REPARSE_DATA_BUFFER, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2_SYMBOLIC_LINK_REPARSE_DATA_BUFFER); } /* reparse tag */ proto_tree_add_item(tree, hf_smb2_reparse_tag, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_smb2_reparse_data_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 2, ENC_NA); offset += 2; /* substitute name offset/length */ offset = dissect_smb2_olb_length_offset(tvb, offset, &s_olb, OLB_O_UINT16_S_UINT16, hf_smb2_symlink_substitute_name); /* print name offset/length */ offset = dissect_smb2_olb_length_offset(tvb, offset, &p_olb, OLB_O_UINT16_S_UINT16, hf_smb2_symlink_print_name); /* flags */ proto_tree_add_item(tree, hf_smb2_symlink_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* substitute name string */ dissect_smb2_olb_off_string(pinfo, tree, tvb, &s_olb, offset, OLB_TYPE_UNICODE_STRING); /* print name string */ dissect_smb2_olb_off_string(pinfo, tree, tvb, &p_olb, offset, OLB_TYPE_UNICODE_STRING); } static void dissect_smb2_FSCTL_SET_REPARSE_POINT(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, gboolean data_in) { if (!data_in) { return; } dissect_smb2_FSCTL_REPARSE_POINT(tvb, pinfo, parent_tree, offset); } static void dissect_smb2_FSCTL_GET_REPARSE_POINT(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, gboolean data_in) { if (data_in) { return; } dissect_smb2_FSCTL_REPARSE_POINT(tvb, pinfo, parent_tree, offset); } void 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; dc = tvb_reported_length(tvb); switch (ioctl_function) { case 0x00060194: /* FSCTL_DFS_GET_REFERRALS */ if (data_in) { dissect_get_dfs_request_data(tvb, pinfo, tree, 0, &dc, TRUE); } else { dissect_get_dfs_referral_data(tvb, pinfo, tree, 0, &dc, TRUE); } break; 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); break; case 0x001401FC: /* FSCTL_QUERY_NETWORK_INTERFACE_INFO */ dissect_smb2_FSCTL_QUERY_NETWORK_INTERFACE_INFO(tvb, pinfo, tree, 0, data_in); break; case 0x00140200: /* FSCTL_VALIDATE_NEGOTIATE_INFO_224 */ dissect_smb2_FSCTL_VALIDATE_NEGOTIATE_INFO_224(tvb, pinfo, tree, 0, data_in); break; case 0x00140204: /* FSCTL_VALIDATE_NEGOTIATE_INFO */ dissect_smb2_FSCTL_VALIDATE_NEGOTIATE_INFO(tvb, pinfo, tree, 0, data_in); break; 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 0x000900A4: /* FSCTL_SET_REPARSE_POINT */ dissect_smb2_FSCTL_SET_REPARSE_POINT(tvb, pinfo, tree, 0, data_in); break; case 0x000900A8: /* FSCTL_GET_REPARSE_POINT */ dissect_smb2_FSCTL_GET_REPARSE_POINT(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 */ dissect_smb2_FSCTL_QUERY_SHARED_VIRTUAL_DISK_SUPPORT(tvb, pinfo, tree, 0, data_in); break; case 0x00090304: /* FSCTL_SVHDX_SYNC_TUNNEL or response */ case 0x00090364: /* FSCTL_SVHDX_ASYNC_TUNNEL or response */ call_dissector_with_data(rsvd_handle, tvb, pinfo, top_tree, &data_in); break; case 0x00090350: /* FSCTL_STORAGE_QOS_CONTROL */ dissect_smb2_FSCTL_STORAGE_QOS_CONTROL(tvb, pinfo, tree, 0, 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_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) { 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) { smb2_pipe_set_file_id(pinfo, si); dissect_smb2_ioctl_data(tvb, pinfo, tree, si->top_tree, si->ioctl_function, FALSE, si); } static int dissect_smb2_ioctl_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si) { offset_length_buffer_t o_olb; offset_length_buffer_t i_olb; proto_tree *flags_tree = NULL; proto_item *flags_item = NULL; /* buffer code */ offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 2, ENC_NA); offset += 2; /* ioctl function */ offset = dissect_smb2_ioctl_function(tvb, pinfo, tree, offset, &si->ioctl_function); /* fid */ offset = dissect_smb2_fid(tvb, pinfo, tree, offset, si, FID_MODE_USE); /* in buffer offset/length */ offset = dissect_smb2_olb_length_offset(tvb, offset, &i_olb, OLB_O_UINT32_S_UINT32, hf_smb2_ioctl_in_data); /* max ioctl in size */ proto_tree_add_item(tree, hf_smb2_max_ioctl_in_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* out buffer offset/length */ offset = dissect_smb2_olb_length_offset(tvb, offset, &o_olb, OLB_O_UINT32_S_UINT32, hf_smb2_ioctl_out_data); /* max ioctl out size */ proto_tree_add_item(tree, hf_smb2_max_ioctl_out_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* flags */ if (tree) { flags_item = proto_tree_add_item(tree, hf_smb2_ioctl_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN); flags_tree = proto_item_add_subtree(flags_item, ett_smb2_ioctl_flags); } proto_tree_add_item(flags_tree, hf_smb2_ioctl_is_fsctl, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA); offset += 4; /* try to decode these blobs in the order they were encoded * so that for "short" packets we will dissect as much as possible * before aborting with "short packet" */ if (i_olb.off>o_olb.off) { /* out buffer */ dissect_smb2_olb_buffer(pinfo, tree, tvb, &o_olb, si, dissect_smb2_ioctl_data_out); /* in buffer */ dissect_smb2_olb_buffer(pinfo, tree, tvb, &i_olb, si, dissect_smb2_ioctl_data_in); } else { /* in buffer */ dissect_smb2_olb_buffer(pinfo, tree, tvb, &i_olb, si, dissect_smb2_ioctl_data_in); /* out buffer */ dissect_smb2_olb_buffer(pinfo, tree, tvb, &o_olb, si, dissect_smb2_ioctl_data_out); } offset = dissect_smb2_olb_tvb_max_offset(offset, &o_olb); offset = dissect_smb2_olb_tvb_max_offset(offset, &i_olb); return offset; } static int dissect_smb2_ioctl_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si) { offset_length_buffer_t o_olb; offset_length_buffer_t i_olb; gboolean continue_dissection; switch (si->status) { /* buffer code */ 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); offset += 2; /* ioctl function */ offset = dissect_smb2_ioctl_function(tvb, pinfo, tree, offset, &si->ioctl_function); /* fid */ offset = dissect_smb2_fid(tvb, pinfo, tree, offset, si, FID_MODE_USE); /* in buffer offset/length */ offset = dissect_smb2_olb_length_offset(tvb, offset, &i_olb, OLB_O_UINT32_S_UINT32, hf_smb2_ioctl_in_data); /* out buffer offset/length */ offset = dissect_smb2_olb_length_offset(tvb, offset, &o_olb, OLB_O_UINT32_S_UINT32, hf_smb2_ioctl_out_data); /* flags: reserved: must be zero */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA); offset += 4; /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA); offset += 4; /* try to decode these blobs in the order they were encoded * so that for "short" packets we will dissect as much as possible * before aborting with "short packet" */ if (i_olb.off>o_olb.off) { /* out buffer */ dissect_smb2_olb_buffer(pinfo, tree, tvb, &o_olb, si, dissect_smb2_ioctl_data_out); /* in buffer */ dissect_smb2_olb_buffer(pinfo, tree, tvb, &i_olb, si, dissect_smb2_ioctl_data_in); } else { /* in buffer */ dissect_smb2_olb_buffer(pinfo, tree, tvb, &i_olb, si, dissect_smb2_ioctl_data_in); /* out buffer */ dissect_smb2_olb_buffer(pinfo, tree, tvb, &o_olb, si, dissect_smb2_ioctl_data_out); } offset = dissect_smb2_olb_tvb_max_offset(offset, &i_olb); offset = dissect_smb2_olb_tvb_max_offset(offset, &o_olb); return offset; } 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; /* buffer code */ offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); /* padding and reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 2, ENC_NA); offset += 2; /* length */ len = tvb_get_letohl(tvb, offset); proto_tree_add_item(tree, hf_smb2_read_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* offset */ off = tvb_get_letoh64(tvb, offset); proto_tree_add_item(tree, hf_smb2_file_offset, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; col_append_fstr(pinfo->cinfo, COL_INFO, " Len:%d Off:%" G_GINT64_MODIFIER "u", len, off); /* fid */ offset = dissect_smb2_fid(tvb, pinfo, tree, offset, si, FID_MODE_USE); /* minimum count */ proto_tree_add_item(tree, hf_smb2_min_count, tvb, offset, 4, ENC_LITTLE_ENDIAN); 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; /* remaining bytes */ proto_tree_add_item(tree, hf_smb2_remaining_bytes, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* 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); /* 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; } offset = dissect_smb2_olb_tvb_max_offset(offset, &c_olb); /* Store len and offset */ if (si->saved) { si->saved->file_offset=off; si->saved->bytes_moved=len; } return offset; } static int dissect_smb2_read_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si _U_) { guint16 dataoffset = 0; guint32 data_tvb_len; guint32 length; gboolean continue_dissection; switch (si->status) { /* buffer code */ 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); proto_tree_add_item(tree, hf_smb2_data_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* length might even be 64bits if they are ambitious*/ length = tvb_get_letohl(tvb, offset); proto_tree_add_item(tree, hf_smb2_read_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* remaining */ proto_tree_add_item(tree, hf_smb2_read_remaining, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA); offset += 4; data_tvb_len=(guint32)tvb_captured_length_remaining(tvb, 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 */ goto out; } } /* data */ proto_tree_add_item(tree, hf_smb2_read_data, tvb, offset, length, ENC_NA); offset += MIN(length,data_tvb_len); out: 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 */ feed_eo_smb2(tvb,pinfo,si,dataoffset,length,si->saved->file_offset); } } return offset; } static void report_create_context_malformed_buffer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, const char *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) { proto_item *item = NULL; if (tree) { item = proto_tree_get_parent(tree); proto_item_append_text(item, ": SMB2_FILE_FULL_EA_INFO"); } dissect_smb2_file_full_ea_info(tvb, pinfo, tree, 0, si); } static void dissect_smb2_ExtA_buffer_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si _U_) { report_create_context_malformed_buffer(tvb, pinfo, tree, "ExtA Response"); } static void dissect_smb2_SecD_buffer_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si) { proto_item *item = NULL; if (tree) { item = proto_tree_get_parent(tree); proto_item_append_text(item, ": SMB2_SEC_INFO_00"); } dissect_smb2_sec_info_00(tvb, pinfo, tree, 0, si); } static void dissect_smb2_SecD_buffer_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si _U_) { report_create_context_malformed_buffer(tvb, pinfo, tree, "SecD Response"); } static void dissect_smb2_TWrp_buffer_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_) { proto_item *item = NULL; if (tree) { item = proto_tree_get_parent(tree); proto_item_append_text(item, ": Timestamp"); } dissect_nt_64bit_time(tvb, tree, 0, hf_smb2_twrp_timestamp); } static void dissect_smb2_TWrp_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, "TWrp Response"); } static void dissect_smb2_QFid_buffer_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_) { proto_item *item = NULL; if (tree) { item = proto_tree_get_parent(tree); } if (item) { 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"); } } } static void 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; proto_item *sub_tree; item = proto_tree_get_parent(tree); 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); } static void dissect_smb2_AlSi_buffer_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_) { proto_tree_add_item(tree, hf_smb2_allocation_size, tvb, 0, 8, ENC_LITTLE_ENDIAN); } static void dissect_smb2_AlSi_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, "AlSi Response"); } static void dissect_smb2_DHnQ_buffer_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si) { dissect_smb2_fid(tvb, pinfo, tree, 0, si, FID_MODE_DHNQ); } static void dissect_smb2_DHnQ_buffer_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_) { proto_tree_add_item(tree, hf_smb2_dhnq_buffer_reserved, tvb, 0, 8, ENC_LITTLE_ENDIAN); } static void dissect_smb2_DHnC_buffer_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si) { dissect_smb2_fid(tvb, pinfo, tree, 0, si, FID_MODE_DHNC); } static void dissect_smb2_DHnC_buffer_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si _U_) { report_create_context_malformed_buffer(tvb, pinfo, tree, "DHnC Response"); } /* * SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 * 4 - timeout * 4 - flags * 8 - reserved * 16 - create guid * * SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2 * 4 - timeout * 4 - flags * * SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 * 16 - file id * 16 - create guid * 4 - flags * * SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 * - nothing - */ #define SMB2_DH2X_FLAGS_PERSISTENT_HANDLE 0x00000002 static void dissect_smb2_DH2Q_buffer_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_) { static const int *dh2x_flags_fields[] = { &hf_smb2_dh2x_buffer_flags_persistent_handle, NULL }; int offset = 0; proto_item *item; proto_item *sub_tree; item = proto_tree_get_parent(tree); 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); offset += 4; /* flags */ proto_tree_add_bitmask(sub_tree, tvb, offset, hf_smb2_dh2x_buffer_flags, ett_smb2_dh2x_flags, dh2x_flags_fields, ENC_LITTLE_ENDIAN); offset += 4; /* reserved */ proto_tree_add_item(sub_tree, hf_smb2_dh2x_buffer_reserved, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* create guid */ proto_tree_add_item(sub_tree, hf_smb2_dh2x_buffer_create_guid, tvb, offset, 16, ENC_LITTLE_ENDIAN); } static void 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; proto_item *sub_tree; item = proto_tree_get_parent(tree); 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); offset += 4; /* flags */ proto_tree_add_item(sub_tree, hf_smb2_dh2x_buffer_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN); } static void dissect_smb2_DH2C_buffer_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si) { int offset = 0; proto_item *item; proto_item *sub_tree; item = proto_tree_get_parent(tree); 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); offset += 16; /* create guid */ proto_tree_add_item(sub_tree, hf_smb2_dh2x_buffer_create_guid, tvb, offset, 16, ENC_LITTLE_ENDIAN); offset += 16; /* flags */ proto_tree_add_item(sub_tree, hf_smb2_dh2x_buffer_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN); } static void dissect_smb2_DH2C_buffer_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si _U_) { report_create_context_malformed_buffer(tvb, pinfo, tree, "DH2C Response"); } static void dissect_smb2_MxAc_buffer_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_) { int offset = 0; proto_item *item = NULL; if (tree) { item = proto_tree_get_parent(tree); } if (tvb_reported_length(tvb) == 0) { if (item) { proto_item_append_text(item, ": NO DATA"); } return; } if (item) { proto_item_append_text(item, ": Timestamp"); } dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_mxac_timestamp); } static void 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; proto_tree *sub_tree; item = proto_tree_get_parent(tree); if (tvb_reported_length(tvb) == 0) { proto_item_append_text(item, ": NO DATA"); return; } 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; dissect_smb_access_mask(tvb, sub_tree, offset); } /* * SMB2_CREATE_REQUEST_LEASE 32 * 16 - lease key * 4 - lease state * 4 - lease flags * 8 - lease duration * * SMB2_CREATE_REQUEST_LEASE_V2 52 * 16 - lease key * 4 - lease state * 4 - lease flags * 8 - lease duration * 16 - parent lease key * 2 - epoch * 2 - reserved */ #define SMB2_LEASE_STATE_READ_CACHING 0x00000001 #define SMB2_LEASE_STATE_HANDLE_CACHING 0x00000002 #define SMB2_LEASE_STATE_WRITE_CACHING 0x00000004 #define SMB2_LEASE_FLAGS_BREAK_ACK_REQUIRED 0x00000001 #define SMB2_LEASE_FLAGS_BREAK_IN_PROGRESS 0x00000002 #define SMB2_LEASE_FLAGS_PARENT_LEASE_KEY_SET 0x00000004 static const int *lease_state_fields[] = { &hf_smb2_lease_state_read_caching, &hf_smb2_lease_state_handle_caching, &hf_smb2_lease_state_write_caching, NULL }; static const int *lease_flags_fields[] = { &hf_smb2_lease_flags_break_ack_required, &hf_smb2_lease_flags_break_in_progress, &hf_smb2_lease_flags_parent_lease_key_set, NULL }; static void dissect_SMB2_CREATE_LEASE_VX(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, smb2_info_t *si _U_) { int offset = 0; int len; proto_tree *sub_tree = NULL; proto_item *parent_item; 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; } 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(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, smb2_info_t *si _U_) { int offset = 0; guint32 version; 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_ret_uint(sub_tree, hf_smb2_svhdx_open_device_context_version, tvb, offset, 4, ENC_LITTLE_ENDIAN, &version); 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_LITTLE_ENDIAN); 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); offset += 126; if (version == 2) { /* VirtualDiskPropertiesInitialized */ proto_tree_add_item(sub_tree, hf_smb2_svhdx_open_device_context_virtual_disk_properties_initialized, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* ServerServiceVersion */ proto_tree_add_item(sub_tree, hf_smb2_svhdx_open_device_context_server_service_version, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* VirtualSectorSize */ proto_tree_add_item(sub_tree, hf_smb2_svhdx_open_device_context_virtual_sector_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* PhysicalSectorSize */ proto_tree_add_item(sub_tree, hf_smb2_svhdx_open_device_context_physical_sector_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* VirtualSize */ proto_tree_add_item(sub_tree, hf_smb2_svhdx_open_device_context_virtual_size, tvb, offset, 8, ENC_LITTLE_ENDIAN); } } 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 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 }; 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; item = proto_tree_get_parent(tree); 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"); /* 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_aapl_reserved, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; switch (command_code) { 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; /* 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; case SMB2_AAPL_RESOLVE_ID: /* file ID */ proto_tree_add_item(sub_tree, hf_smb2_file_id, tvb, offset, 8, ENC_LITTLE_ENDIAN); break; default: break; } } #define SMB2_AAPL_SUPPORTS_RESOLVE_ID 0x00000001 #define SMB2_AAPL_CASE_SENSITIVE 0x00000002 #define SMB2_AAPL_SUPPORTS_FULL_SYNC 0x00000004 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_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; proto_item *sub_tree; guint32 command_code; guint64 server_query_bitmask; item = proto_tree_get_parent(tree); 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"); /* 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_aapl_reserved, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; switch (command_code) { 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); typedef struct create_context_data_dissectors { create_context_data_dissector_t request; create_context_data_dissector_t response; } create_context_data_dissectors_t; struct create_context_data_tag_dissectors { const char *tag; const char *val; create_context_data_dissectors_t dissectors; }; struct create_context_data_tag_dissectors create_context_dissectors_array[] = { { "ExtA", "SMB2_CREATE_EA_BUFFER", { dissect_smb2_ExtA_buffer_request, dissect_smb2_ExtA_buffer_response } }, { "SecD", "SMB2_CREATE_SD_BUFFER", { dissect_smb2_SecD_buffer_request, dissect_smb2_SecD_buffer_response } }, { "AlSi", "SMB2_CREATE_ALLOCATION_SIZE", { dissect_smb2_AlSi_buffer_request, dissect_smb2_AlSi_buffer_response } }, { "MxAc", "SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST", { dissect_smb2_MxAc_buffer_request, dissect_smb2_MxAc_buffer_response } }, { "DHnQ", "SMB2_CREATE_DURABLE_HANDLE_REQUEST", { dissect_smb2_DHnQ_buffer_request, dissect_smb2_DHnQ_buffer_response } }, { "DHnC", "SMB2_CREATE_DURABLE_HANDLE_RECONNECT", { dissect_smb2_DHnC_buffer_request, dissect_smb2_DHnC_buffer_response } }, { "DH2Q", "SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2", { dissect_smb2_DH2Q_buffer_request, dissect_smb2_DH2Q_buffer_response } }, { "DH2C", "SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2", { dissect_smb2_DH2C_buffer_request, dissect_smb2_DH2C_buffer_response } }, { "TWrp", "SMB2_CREATE_TIMEWARP_TOKEN", { dissect_smb2_TWrp_buffer_request, dissect_smb2_TWrp_buffer_response } }, { "QFid", "SMB2_CREATE_QUERY_ON_DISK_ID", { dissect_smb2_QFid_buffer_request, dissect_smb2_QFid_buffer_response } }, { "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 } }, { "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, dissect_smb2_svhdx_open_device_context} }, { "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* get_create_context_data_tag_dissectors(const char *tag) { static struct create_context_data_tag_dissectors INVALID = { NULL, "", { NULL, NULL } }; size_t i; for (i = 0; ival); proto_item_append_text(sub_item, ": %s \"%s\"", tag_dissectors->val, tag); /* data */ dissectors = &tag_dissectors->dissectors; if (dissectors) dissector = (si->flags & SMB2_FLAGS_RESPONSE) ? dissectors->response : dissectors->request; dissect_smb2_olb_buffer(pinfo, sub_tree, tvb, &data_olb, si, dissector); if (chain_offset) { tvbuff_t *chain_tvb; chain_tvb = tvb_new_subset_remaining(tvb, chain_offset); /* next extra info */ dissect_smb2_create_extra_info(chain_tvb, pinfo, parent_tree, si); } } static int dissect_smb2_create_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si) { offset_length_buffer_t f_olb, e_olb; const char *fname; /* buffer code */ offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); /* security flags */ offset++; /* oplock */ offset = dissect_smb2_oplock(tree, tvb, offset); /* impersonation level */ proto_tree_add_item(tree, hf_smb2_impersonation_level, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* create flags */ proto_tree_add_item(tree, hf_smb2_create_flags, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 8, ENC_NA); offset += 8; /* access mask */ offset = dissect_smb_access_mask(tvb, tree, offset); /* File Attributes */ offset = dissect_file_ext_attr(tvb, tree, offset); /* share access */ offset = dissect_nt_share_access(tvb, tree, offset); /* create disposition */ proto_tree_add_item(tree, hf_smb2_create_disposition, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* create options */ offset = dissect_nt_create_options(tvb, tree, offset); /* filename offset/length */ offset = dissect_smb2_olb_length_offset(tvb, offset, &f_olb, OLB_O_UINT16_S_UINT16, hf_smb2_filename); /* extrainfo offset */ offset = dissect_smb2_olb_length_offset(tvb, offset, &e_olb, OLB_O_UINT32_S_UINT32, hf_smb2_extrainfo); /* filename string */ fname = dissect_smb2_olb_string(pinfo, tree, tvb, &f_olb, OLB_TYPE_UNICODE_STRING); col_append_fstr(pinfo->cinfo, COL_INFO, " File: %s", fname); /* save the name if it looks sane */ if (!pinfo->fd->visited) { if (si->saved && si->saved->extra_info_type == SMB2_EI_FILENAME) { wmem_free(wmem_file_scope(), si->saved->extra_info); si->saved->extra_info = NULL; si->saved->extra_info_type = SMB2_EI_NONE; } if (si->saved && f_olb.len < 256) { si->saved->extra_info_type = SMB2_EI_FILENAME; si->saved->extra_info = (gchar *)wmem_alloc(wmem_file_scope(), f_olb.len+1); g_snprintf((gchar *)si->saved->extra_info, f_olb.len+1, "%s", fname); } } /* If extrainfo_offset is non-null then this points to another * buffer. The offset is relative to the start of the smb packet */ dissect_smb2_olb_buffer(pinfo, tree, tvb, &e_olb, si, dissect_smb2_create_extra_info); offset = dissect_smb2_olb_tvb_max_offset(offset, &f_olb); offset = dissect_smb2_olb_tvb_max_offset(offset, &e_olb); return offset; } #define SMB2_CREATE_REP_FLAGS_REPARSE_POINT 0x01 static int dissect_smb2_create_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si) { guint64 end_of_file; guint32 attr_mask; offset_length_buffer_t e_olb; static const int *create_rep_flags_fields[] = { &hf_smb2_create_rep_flags_reparse_point, NULL }; gboolean continue_dissection; switch (si->status) { /* buffer code */ 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); /* reserved */ proto_tree_add_bitmask(tree, tvb, offset, hf_smb2_create_rep_flags, ett_smb2_create_rep_flags, create_rep_flags_fields, ENC_LITTLE_ENDIAN); offset += 1; /* create action */ proto_tree_add_item(tree, hf_smb2_create_action, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* create time */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_create_timestamp); /* last access */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_access_timestamp); /* last write */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_write_timestamp); /* last change */ offset = dissect_nt_64bit_time(tvb, tree, offset, hf_smb2_last_change_timestamp); /* allocation size */ proto_tree_add_item(tree, hf_smb2_allocation_size, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* end of file */ end_of_file = tvb_get_letoh64(tvb, offset); if (si->eo_file_info) { si->eo_file_info->end_of_file = tvb_get_letoh64(tvb, offset); } proto_tree_add_item(tree, hf_smb2_end_of_file, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* File Attributes */ attr_mask=tvb_get_letohl(tvb, offset); offset = dissect_file_ext_attr(tvb, tree, offset); /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA); offset += 4; /* fid */ offset = dissect_smb2_fid(tvb, pinfo, tree, offset, si, FID_MODE_OPEN); /* We save this after dissect_smb2_fid just because it would be possible to have this response without having the mathing request. In that case the entry in the file info hash table has been created in dissect_smb2_fid */ if (si->eo_file_info) { si->eo_file_info->end_of_file = end_of_file; si->eo_file_info->attr_mask = attr_mask; } /* extrainfo offset */ offset = dissect_smb2_olb_length_offset(tvb, offset, &e_olb, OLB_O_UINT32_S_UINT32, hf_smb2_extrainfo); /* If extrainfo_offset is non-null then this points to another * buffer. The offset is relative to the start of the smb packet */ dissect_smb2_olb_buffer(pinfo, tree, tvb, &e_olb, si, dissect_smb2_create_extra_info); offset = dissect_smb2_olb_tvb_max_offset(offset, &e_olb); /* free si->saved->extra_info we don't need it any more */ if (si->saved && si->saved->extra_info_type == SMB2_EI_FILENAME) { wmem_free(wmem_file_scope(), si->saved->extra_info); si->saved->extra_info = NULL; si->saved->extra_info_type = SMB2_EI_NONE; } return offset; } static int dissect_smb2_setinfo_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si) { guint32 setinfo_size; guint16 setinfo_offset; /* buffer code */ offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); /* class and info level */ offset = dissect_smb2_class_infolevel(pinfo, tvb, offset, tree, si); /* size */ setinfo_size = tvb_get_letohl(tvb, offset); proto_tree_add_item(tree, hf_smb2_setinfo_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* offset */ setinfo_offset = tvb_get_letohs(tvb, offset); proto_tree_add_item(tree, hf_smb2_setinfo_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* some unknown bytes */ proto_tree_add_item(tree, hf_smb2_unknown, tvb, offset, 6, ENC_NA); offset += 6; /* fid */ dissect_smb2_fid(tvb, pinfo, tree, offset, si, FID_MODE_USE); /* data */ if (si->saved) dissect_smb2_infolevel(tvb, pinfo, tree, setinfo_offset, si, si->saved->smb2_class, si->saved->infolevel); offset = setinfo_offset + setinfo_size; return offset; } 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) { /* buffer code */ 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; } static int dissect_smb2_break_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si) { guint16 buffer_code; /* buffer code */ buffer_code = tvb_get_letohs(tvb, offset); offset = dissect_smb2_buffercode(tree, tvb, offset, NULL); if (buffer_code == 24) { /* OPLOCK Break */ /* oplock */ offset = dissect_smb2_oplock(tree, tvb, offset); /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 1, ENC_NA); offset += 1; /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA); offset += 4; /* fid */ offset = dissect_smb2_fid(tvb, pinfo, tree, offset, si, FID_MODE_USE); return offset; } if (buffer_code == 36) { /* Lease Break Acknowledgment */ /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 2, ENC_NA); offset +=2; /* lease flags */ proto_tree_add_bitmask(tree, tvb, offset, hf_smb2_lease_flags, ett_smb2_lease_flags, lease_flags_fields, ENC_LITTLE_ENDIAN); offset += 4; /* lease key */ proto_tree_add_item(tree, hf_smb2_lease_key, tvb, offset, 16, ENC_LITTLE_ENDIAN); offset += 16; /* lease state */ proto_tree_add_bitmask(tree, tvb, offset, hf_smb2_lease_state, ett_smb2_lease_state, lease_state_fields, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_smb2_lease_duration, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; return offset; } return offset; } static int dissect_smb2_break_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si) { guint16 buffer_code; gboolean continue_dissection; /* buffer code */ buffer_code = tvb_get_letohs(tvb, offset); 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 */ /* oplock */ offset = dissect_smb2_oplock(tree, tvb, offset); /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 1, ENC_NA); offset += 1; /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 4, ENC_NA); offset += 4; /* fid */ offset = dissect_smb2_fid(tvb, pinfo, tree, offset, si, FID_MODE_USE); /* in break requests from server to client here're 24 byte zero bytes * which are likely a bug in windows (they may use 2* 24 bytes instead of just * 1 *24 bytes */ return offset; } if (buffer_code == 44) { proto_item *item; /* Lease Break Notification */ /* 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, ett_smb2_lease_flags, lease_flags_fields, ENC_LITTLE_ENDIAN); offset += 4; /* lease key */ proto_tree_add_item(tree, hf_smb2_lease_key, tvb, offset, 16, ENC_LITTLE_ENDIAN); offset += 16; /* current lease state */ item = proto_tree_add_bitmask(tree, tvb, offset, hf_smb2_lease_state, ett_smb2_lease_state, lease_state_fields, ENC_LITTLE_ENDIAN); if (item) { proto_item_prepend_text(item, "Current "); } offset += 4; /* new lease state */ item = proto_tree_add_bitmask(tree, tvb, offset, hf_smb2_lease_state, ett_smb2_lease_state, lease_state_fields, ENC_LITTLE_ENDIAN); if (item) { proto_item_prepend_text(item, "New "); } offset += 4; /* break reason - reserved */ proto_tree_add_item(tree, hf_smb2_lease_break_reason, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* access mask hint - reserved */ proto_tree_add_item(tree, hf_smb2_lease_access_mask_hint, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* share mask hint - reserved */ proto_tree_add_item(tree, hf_smb2_lease_share_mask_hint, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; return offset; } if (buffer_code == 36) { /* Lease Break Response */ /* reserved */ proto_tree_add_item(tree, hf_smb2_reserved, tvb, offset, 2, ENC_NA); offset +=2; /* lease flags */ proto_tree_add_bitmask(tree, tvb, offset, hf_smb2_lease_flags, ett_smb2_lease_flags, lease_flags_fields, ENC_LITTLE_ENDIAN); offset += 4; /* lease key */ proto_tree_add_item(tree, hf_smb2_lease_key, tvb, offset, 16, ENC_LITTLE_ENDIAN); offset += 16; /* lease state */ proto_tree_add_bitmask(tree, tvb, offset, hf_smb2_lease_state, ett_smb2_lease_state, lease_state_fields, ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_smb2_lease_duration, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; return offset; } return offset; } /* names here are just until we find better names for these functions */ static const value_string smb2_cmd_vals[] = { { 0x00, "Negotiate Protocol" }, { 0x01, "Session Setup" }, { 0x02, "Session Logoff" }, { 0x03, "Tree Connect" }, { 0x04, "Tree Disconnect" }, { 0x05, "Create" }, { 0x06, "Close" }, { 0x07, "Flush" }, { 0x08, "Read" }, { 0x09, "Write" }, { 0x0A, "Lock" }, { 0x0B, "Ioctl" }, { 0x0C, "Cancel" }, { 0x0D, "KeepAlive" }, { 0x0E, "Find" }, { 0x0F, "Notify" }, { 0x10, "GetInfo" }, { 0x11, "SetInfo" }, { 0x12, "Break" }, { 0x13, "unknown-0x13" }, { 0x14, "unknown-0x14" }, { 0x15, "unknown-0x15" }, { 0x16, "unknown-0x16" }, { 0x17, "unknown-0x17" }, { 0x18, "unknown-0x18" }, { 0x19, "unknown-0x19" }, { 0x1A, "unknown-0x1A" }, { 0x1B, "unknown-0x1B" }, { 0x1C, "unknown-0x1C" }, { 0x1D, "unknown-0x1D" }, { 0x1E, "unknown-0x1E" }, { 0x1F, "unknown-0x1F" }, { 0x20, "unknown-0x20" }, { 0x21, "unknown-0x21" }, { 0x22, "unknown-0x22" }, { 0x23, "unknown-0x23" }, { 0x24, "unknown-0x24" }, { 0x25, "unknown-0x25" }, { 0x26, "unknown-0x26" }, { 0x27, "unknown-0x27" }, { 0x28, "unknown-0x28" }, { 0x29, "unknown-0x29" }, { 0x2A, "unknown-0x2A" }, { 0x2B, "unknown-0x2B" }, { 0x2C, "unknown-0x2C" }, { 0x2D, "unknown-0x2D" }, { 0x2E, "unknown-0x2E" }, { 0x2F, "unknown-0x2F" }, { 0x30, "unknown-0x30" }, { 0x31, "unknown-0x31" }, { 0x32, "unknown-0x32" }, { 0x33, "unknown-0x33" }, { 0x34, "unknown-0x34" }, { 0x35, "unknown-0x35" }, { 0x36, "unknown-0x36" }, { 0x37, "unknown-0x37" }, { 0x38, "unknown-0x38" }, { 0x39, "unknown-0x39" }, { 0x3A, "unknown-0x3A" }, { 0x3B, "unknown-0x3B" }, { 0x3C, "unknown-0x3C" }, { 0x3D, "unknown-0x3D" }, { 0x3E, "unknown-0x3E" }, { 0x3F, "unknown-0x3F" }, { 0x40, "unknown-0x40" }, { 0x41, "unknown-0x41" }, { 0x42, "unknown-0x42" }, { 0x43, "unknown-0x43" }, { 0x44, "unknown-0x44" }, { 0x45, "unknown-0x45" }, { 0x46, "unknown-0x46" }, { 0x47, "unknown-0x47" }, { 0x48, "unknown-0x48" }, { 0x49, "unknown-0x49" }, { 0x4A, "unknown-0x4A" }, { 0x4B, "unknown-0x4B" }, { 0x4C, "unknown-0x4C" }, { 0x4D, "unknown-0x4D" }, { 0x4E, "unknown-0x4E" }, { 0x4F, "unknown-0x4F" }, { 0x50, "unknown-0x50" }, { 0x51, "unknown-0x51" }, { 0x52, "unknown-0x52" }, { 0x53, "unknown-0x53" }, { 0x54, "unknown-0x54" }, { 0x55, "unknown-0x55" }, { 0x56, "unknown-0x56" }, { 0x57, "unknown-0x57" }, { 0x58, "unknown-0x58" }, { 0x59, "unknown-0x59" }, { 0x5A, "unknown-0x5A" }, { 0x5B, "unknown-0x5B" }, { 0x5C, "unknown-0x5C" }, { 0x5D, "unknown-0x5D" }, { 0x5E, "unknown-0x5E" }, { 0x5F, "unknown-0x5F" }, { 0x60, "unknown-0x60" }, { 0x61, "unknown-0x61" }, { 0x62, "unknown-0x62" }, { 0x63, "unknown-0x63" }, { 0x64, "unknown-0x64" }, { 0x65, "unknown-0x65" }, { 0x66, "unknown-0x66" }, { 0x67, "unknown-0x67" }, { 0x68, "unknown-0x68" }, { 0x69, "unknown-0x69" }, { 0x6A, "unknown-0x6A" }, { 0x6B, "unknown-0x6B" }, { 0x6C, "unknown-0x6C" }, { 0x6D, "unknown-0x6D" }, { 0x6E, "unknown-0x6E" }, { 0x6F, "unknown-0x6F" }, { 0x70, "unknown-0x70" }, { 0x71, "unknown-0x71" }, { 0x72, "unknown-0x72" }, { 0x73, "unknown-0x73" }, { 0x74, "unknown-0x74" }, { 0x75, "unknown-0x75" }, { 0x76, "unknown-0x76" }, { 0x77, "unknown-0x77" }, { 0x78, "unknown-0x78" }, { 0x79, "unknown-0x79" }, { 0x7A, "unknown-0x7A" }, { 0x7B, "unknown-0x7B" }, { 0x7C, "unknown-0x7C" }, { 0x7D, "unknown-0x7D" }, { 0x7E, "unknown-0x7E" }, { 0x7F, "unknown-0x7F" }, { 0x80, "unknown-0x80" }, { 0x81, "unknown-0x81" }, { 0x82, "unknown-0x82" }, { 0x83, "unknown-0x83" }, { 0x84, "unknown-0x84" }, { 0x85, "unknown-0x85" }, { 0x86, "unknown-0x86" }, { 0x87, "unknown-0x87" }, { 0x88, "unknown-0x88" }, { 0x89, "unknown-0x89" }, { 0x8A, "unknown-0x8A" }, { 0x8B, "unknown-0x8B" }, { 0x8C, "unknown-0x8C" }, { 0x8D, "unknown-0x8D" }, { 0x8E, "unknown-0x8E" }, { 0x8F, "unknown-0x8F" }, { 0x90, "unknown-0x90" }, { 0x91, "unknown-0x91" }, { 0x92, "unknown-0x92" }, { 0x93, "unknown-0x93" }, { 0x94, "unknown-0x94" }, { 0x95, "unknown-0x95" }, { 0x96, "unknown-0x96" }, { 0x97, "unknown-0x97" }, { 0x98, "unknown-0x98" }, { 0x99, "unknown-0x99" }, { 0x9A, "unknown-0x9A" }, { 0x9B, "unknown-0x9B" }, { 0x9C, "unknown-0x9C" }, { 0x9D, "unknown-0x9D" }, { 0x9E, "unknown-0x9E" }, { 0x9F, "unknown-0x9F" }, { 0xA0, "unknown-0xA0" }, { 0xA1, "unknown-0xA1" }, { 0xA2, "unknown-0xA2" }, { 0xA3, "unknown-0xA3" }, { 0xA4, "unknown-0xA4" }, { 0xA5, "unknown-0xA5" }, { 0xA6, "unknown-0xA6" }, { 0xA7, "unknown-0xA7" }, { 0xA8, "unknown-0xA8" }, { 0xA9, "unknown-0xA9" }, { 0xAA, "unknown-0xAA" }, { 0xAB, "unknown-0xAB" }, { 0xAC, "unknown-0xAC" }, { 0xAD, "unknown-0xAD" }, { 0xAE, "unknown-0xAE" }, { 0xAF, "unknown-0xAF" }, { 0xB0, "unknown-0xB0" }, { 0xB1, "unknown-0xB1" }, { 0xB2, "unknown-0xB2" }, { 0xB3, "unknown-0xB3" }, { 0xB4, "unknown-0xB4" }, { 0xB5, "unknown-0xB5" }, { 0xB6, "unknown-0xB6" }, { 0xB7, "unknown-0xB7" }, { 0xB8, "unknown-0xB8" }, { 0xB9, "unknown-0xB9" }, { 0xBA, "unknown-0xBA" }, { 0xBB, "unknown-0xBB" }, { 0xBC, "unknown-0xBC" }, { 0xBD, "unknown-0xBD" }, { 0xBE, "unknown-0xBE" }, { 0xBF, "unknown-0xBF" }, { 0xC0, "unknown-0xC0" }, { 0xC1, "unknown-0xC1" }, { 0xC2, "unknown-0xC2" }, { 0xC3, "unknown-0xC3" }, { 0xC4, "unknown-0xC4" }, { 0xC5, "unknown-0xC5" }, { 0xC6, "unknown-0xC6" }, { 0xC7, "unknown-0xC7" }, { 0xC8, "unknown-0xC8" }, { 0xC9, "unknown-0xC9" }, { 0xCA, "unknown-0xCA" }, { 0xCB, "unknown-0xCB" }, { 0xCC, "unknown-0xCC" }, { 0xCD, "unknown-0xCD" }, { 0xCE, "unknown-0xCE" }, { 0xCF, "unknown-0xCF" }, { 0xD0, "unknown-0xD0" }, { 0xD1, "unknown-0xD1" }, { 0xD2, "unknown-0xD2" }, { 0xD3, "unknown-0xD3" }, { 0xD4, "unknown-0xD4" }, { 0xD5, "unknown-0xD5" }, { 0xD6, "unknown-0xD6" }, { 0xD7, "unknown-0xD7" }, { 0xD8, "unknown-0xD8" }, { 0xD9, "unknown-0xD9" }, { 0xDA, "unknown-0xDA" }, { 0xDB, "unknown-0xDB" }, { 0xDC, "unknown-0xDC" }, { 0xDD, "unknown-0xDD" }, { 0xDE, "unknown-0xDE" }, { 0xDF, "unknown-0xDF" }, { 0xE0, "unknown-0xE0" }, { 0xE1, "unknown-0xE1" }, { 0xE2, "unknown-0xE2" }, { 0xE3, "unknown-0xE3" }, { 0xE4, "unknown-0xE4" }, { 0xE5, "unknown-0xE5" }, { 0xE6, "unknown-0xE6" }, { 0xE7, "unknown-0xE7" }, { 0xE8, "unknown-0xE8" }, { 0xE9, "unknown-0xE9" }, { 0xEA, "unknown-0xEA" }, { 0xEB, "unknown-0xEB" }, { 0xEC, "unknown-0xEC" }, { 0xED, "unknown-0xED" }, { 0xEE, "unknown-0xEE" }, { 0xEF, "unknown-0xEF" }, { 0xF0, "unknown-0xF0" }, { 0xF1, "unknown-0xF1" }, { 0xF2, "unknown-0xF2" }, { 0xF3, "unknown-0xF3" }, { 0xF4, "unknown-0xF4" }, { 0xF5, "unknown-0xF5" }, { 0xF6, "unknown-0xF6" }, { 0xF7, "unknown-0xF7" }, { 0xF8, "unknown-0xF8" }, { 0xF9, "unknown-0xF9" }, { 0xFA, "unknown-0xFA" }, { 0xFB, "unknown-0xFB" }, { 0xFC, "unknown-0xFC" }, { 0xFD, "unknown-0xFD" }, { 0xFE, "unknown-0xFE" }, { 0xFF, "unknown-0xFF" }, { 0x00, NULL }, }; value_string_ext smb2_cmd_vals_ext = VALUE_STRING_EXT_INIT(smb2_cmd_vals); static const char *decode_smb2_name(guint16 cmd) { if (cmd > 0xFF) return "unknown"; return(smb2_cmd_vals[cmd & 0xFF].strptr); } static smb2_function smb2_dissector[256] = { /* 0x00 NegotiateProtocol*/ {dissect_smb2_negotiate_protocol_request, dissect_smb2_negotiate_protocol_response}, /* 0x01 SessionSetup*/ {dissect_smb2_session_setup_request, dissect_smb2_session_setup_response}, /* 0x02 SessionLogoff*/ {dissect_smb2_sessionlogoff_request, dissect_smb2_sessionlogoff_response}, /* 0x03 TreeConnect*/ {dissect_smb2_tree_connect_request, dissect_smb2_tree_connect_response}, /* 0x04 TreeDisconnect*/ {dissect_smb2_tree_disconnect_request, dissect_smb2_tree_disconnect_response}, /* 0x05 Create*/ {dissect_smb2_create_request, dissect_smb2_create_response}, /* 0x06 Close*/ {dissect_smb2_close_request, dissect_smb2_close_response}, /* 0x07 Flush*/ {dissect_smb2_flush_request, dissect_smb2_flush_response}, /* 0x08 Read*/ {dissect_smb2_read_request, dissect_smb2_read_response}, /* 0x09 Writew*/ {dissect_smb2_write_request, dissect_smb2_write_response}, /* 0x0a Lock */ {dissect_smb2_lock_request, dissect_smb2_lock_response}, /* 0x0b Ioctl*/ {dissect_smb2_ioctl_request, dissect_smb2_ioctl_response}, /* 0x0c Cancel*/ {dissect_smb2_cancel_request, NULL}, /* 0x0d KeepAlive*/ {dissect_smb2_keepalive_request, dissect_smb2_keepalive_response}, /* 0x0e Find*/ {dissect_smb2_find_request, dissect_smb2_find_response}, /* 0x0f Notify*/ {dissect_smb2_notify_request, dissect_smb2_notify_response}, /* 0x10 GetInfo*/ {dissect_smb2_getinfo_request, dissect_smb2_getinfo_response}, /* 0x11 SetInfo*/ {dissect_smb2_setinfo_request, dissect_smb2_setinfo_response}, /* 0x12 Break */ {dissect_smb2_break_request, dissect_smb2_break_response}, /* 0x13 */ {NULL, NULL}, /* 0x14 */ {NULL, NULL}, /* 0x15 */ {NULL, NULL}, /* 0x16 */ {NULL, NULL}, /* 0x17 */ {NULL, NULL}, /* 0x18 */ {NULL, NULL}, /* 0x19 */ {NULL, NULL}, /* 0x1a */ {NULL, NULL}, /* 0x1b */ {NULL, NULL}, /* 0x1c */ {NULL, NULL}, /* 0x1d */ {NULL, NULL}, /* 0x1e */ {NULL, NULL}, /* 0x1f */ {NULL, NULL}, /* 0x20 */ {NULL, NULL}, /* 0x21 */ {NULL, NULL}, /* 0x22 */ {NULL, NULL}, /* 0x23 */ {NULL, NULL}, /* 0x24 */ {NULL, NULL}, /* 0x25 */ {NULL, NULL}, /* 0x26 */ {NULL, NULL}, /* 0x27 */ {NULL, NULL}, /* 0x28 */ {NULL, NULL}, /* 0x29 */ {NULL, NULL}, /* 0x2a */ {NULL, NULL}, /* 0x2b */ {NULL, NULL}, /* 0x2c */ {NULL, NULL}, /* 0x2d */ {NULL, NULL}, /* 0x2e */ {NULL, NULL}, /* 0x2f */ {NULL, NULL}, /* 0x30 */ {NULL, NULL}, /* 0x31 */ {NULL, NULL}, /* 0x32 */ {NULL, NULL}, /* 0x33 */ {NULL, NULL}, /* 0x34 */ {NULL, NULL}, /* 0x35 */ {NULL, NULL}, /* 0x36 */ {NULL, NULL}, /* 0x37 */ {NULL, NULL}, /* 0x38 */ {NULL, NULL}, /* 0x39 */ {NULL, NULL}, /* 0x3a */ {NULL, NULL}, /* 0x3b */ {NULL, NULL}, /* 0x3c */ {NULL, NULL}, /* 0x3d */ {NULL, NULL}, /* 0x3e */ {NULL, NULL}, /* 0x3f */ {NULL, NULL}, /* 0x40 */ {NULL, NULL}, /* 0x41 */ {NULL, NULL}, /* 0x42 */ {NULL, NULL}, /* 0x43 */ {NULL, NULL}, /* 0x44 */ {NULL, NULL}, /* 0x45 */ {NULL, NULL}, /* 0x46 */ {NULL, NULL}, /* 0x47 */ {NULL, NULL}, /* 0x48 */ {NULL, NULL}, /* 0x49 */ {NULL, NULL}, /* 0x4a */ {NULL, NULL}, /* 0x4b */ {NULL, NULL}, /* 0x4c */ {NULL, NULL}, /* 0x4d */ {NULL, NULL}, /* 0x4e */ {NULL, NULL}, /* 0x4f */ {NULL, NULL}, /* 0x50 */ {NULL, NULL}, /* 0x51 */ {NULL, NULL}, /* 0x52 */ {NULL, NULL}, /* 0x53 */ {NULL, NULL}, /* 0x54 */ {NULL, NULL}, /* 0x55 */ {NULL, NULL}, /* 0x56 */ {NULL, NULL}, /* 0x57 */ {NULL, NULL}, /* 0x58 */ {NULL, NULL}, /* 0x59 */ {NULL, NULL}, /* 0x5a */ {NULL, NULL}, /* 0x5b */ {NULL, NULL}, /* 0x5c */ {NULL, NULL}, /* 0x5d */ {NULL, NULL}, /* 0x5e */ {NULL, NULL}, /* 0x5f */ {NULL, NULL}, /* 0x60 */ {NULL, NULL}, /* 0x61 */ {NULL, NULL}, /* 0x62 */ {NULL, NULL}, /* 0x63 */ {NULL, NULL}, /* 0x64 */ {NULL, NULL}, /* 0x65 */ {NULL, NULL}, /* 0x66 */ {NULL, NULL}, /* 0x67 */ {NULL, NULL}, /* 0x68 */ {NULL, NULL}, /* 0x69 */ {NULL, NULL}, /* 0x6a */ {NULL, NULL}, /* 0x6b */ {NULL, NULL}, /* 0x6c */ {NULL, NULL}, /* 0x6d */ {NULL, NULL}, /* 0x6e */ {NULL, NULL}, /* 0x6f */ {NULL, NULL}, /* 0x70 */ {NULL, NULL}, /* 0x71 */ {NULL, NULL}, /* 0x72 */ {NULL, NULL}, /* 0x73 */ {NULL, NULL}, /* 0x74 */ {NULL, NULL}, /* 0x75 */ {NULL, NULL}, /* 0x76 */ {NULL, NULL}, /* 0x77 */ {NULL, NULL}, /* 0x78 */ {NULL, NULL}, /* 0x79 */ {NULL, NULL}, /* 0x7a */ {NULL, NULL}, /* 0x7b */ {NULL, NULL}, /* 0x7c */ {NULL, NULL}, /* 0x7d */ {NULL, NULL}, /* 0x7e */ {NULL, NULL}, /* 0x7f */ {NULL, NULL}, /* 0x80 */ {NULL, NULL}, /* 0x81 */ {NULL, NULL}, /* 0x82 */ {NULL, NULL}, /* 0x83 */ {NULL, NULL}, /* 0x84 */ {NULL, NULL}, /* 0x85 */ {NULL, NULL}, /* 0x86 */ {NULL, NULL}, /* 0x87 */ {NULL, NULL}, /* 0x88 */ {NULL, NULL}, /* 0x89 */ {NULL, NULL}, /* 0x8a */ {NULL, NULL}, /* 0x8b */ {NULL, NULL}, /* 0x8c */ {NULL, NULL}, /* 0x8d */ {NULL, NULL}, /* 0x8e */ {NULL, NULL}, /* 0x8f */ {NULL, NULL}, /* 0x90 */ {NULL, NULL}, /* 0x91 */ {NULL, NULL}, /* 0x92 */ {NULL, NULL}, /* 0x93 */ {NULL, NULL}, /* 0x94 */ {NULL, NULL}, /* 0x95 */ {NULL, NULL}, /* 0x96 */ {NULL, NULL}, /* 0x97 */ {NULL, NULL}, /* 0x98 */ {NULL, NULL}, /* 0x99 */ {NULL, NULL}, /* 0x9a */ {NULL, NULL}, /* 0x9b */ {NULL, NULL}, /* 0x9c */ {NULL, NULL}, /* 0x9d */ {NULL, NULL}, /* 0x9e */ {NULL, NULL}, /* 0x9f */ {NULL, NULL}, /* 0xa0 */ {NULL, NULL}, /* 0xa1 */ {NULL, NULL}, /* 0xa2 */ {NULL, NULL}, /* 0xa3 */ {NULL, NULL}, /* 0xa4 */ {NULL, NULL}, /* 0xa5 */ {NULL, NULL}, /* 0xa6 */ {NULL, NULL}, /* 0xa7 */ {NULL, NULL}, /* 0xa8 */ {NULL, NULL}, /* 0xa9 */ {NULL, NULL}, /* 0xaa */ {NULL, NULL}, /* 0xab */ {NULL, NULL}, /* 0xac */ {NULL, NULL}, /* 0xad */ {NULL, NULL}, /* 0xae */ {NULL, NULL}, /* 0xaf */ {NULL, NULL}, /* 0xb0 */ {NULL, NULL}, /* 0xb1 */ {NULL, NULL}, /* 0xb2 */ {NULL, NULL}, /* 0xb3 */ {NULL, NULL}, /* 0xb4 */ {NULL, NULL}, /* 0xb5 */ {NULL, NULL}, /* 0xb6 */ {NULL, NULL}, /* 0xb7 */ {NULL, NULL}, /* 0xb8 */ {NULL, NULL}, /* 0xb9 */ {NULL, NULL}, /* 0xba */ {NULL, NULL}, /* 0xbb */ {NULL, NULL}, /* 0xbc */ {NULL, NULL}, /* 0xbd */ {NULL, NULL}, /* 0xbe */ {NULL, NULL}, /* 0xbf */ {NULL, NULL}, /* 0xc0 */ {NULL, NULL}, /* 0xc1 */ {NULL, NULL}, /* 0xc2 */ {NULL, NULL}, /* 0xc3 */ {NULL, NULL}, /* 0xc4 */ {NULL, NULL}, /* 0xc5 */ {NULL, NULL}, /* 0xc6 */ {NULL, NULL}, /* 0xc7 */ {NULL, NULL}, /* 0xc8 */ {NULL, NULL}, /* 0xc9 */ {NULL, NULL}, /* 0xca */ {NULL, NULL}, /* 0xcb */ {NULL, NULL}, /* 0xcc */ {NULL, NULL}, /* 0xcd */ {NULL, NULL}, /* 0xce */ {NULL, NULL}, /* 0xcf */ {NULL, NULL}, /* 0xd0 */ {NULL, NULL}, /* 0xd1 */ {NULL, NULL}, /* 0xd2 */ {NULL, NULL}, /* 0xd3 */ {NULL, NULL}, /* 0xd4 */ {NULL, NULL}, /* 0xd5 */ {NULL, NULL}, /* 0xd6 */ {NULL, NULL}, /* 0xd7 */ {NULL, NULL}, /* 0xd8 */ {NULL, NULL}, /* 0xd9 */ {NULL, NULL}, /* 0xda */ {NULL, NULL}, /* 0xdb */ {NULL, NULL}, /* 0xdc */ {NULL, NULL}, /* 0xdd */ {NULL, NULL}, /* 0xde */ {NULL, NULL}, /* 0xdf */ {NULL, NULL}, /* 0xe0 */ {NULL, NULL}, /* 0xe1 */ {NULL, NULL}, /* 0xe2 */ {NULL, NULL}, /* 0xe3 */ {NULL, NULL}, /* 0xe4 */ {NULL, NULL}, /* 0xe5 */ {NULL, NULL}, /* 0xe6 */ {NULL, NULL}, /* 0xe7 */ {NULL, NULL}, /* 0xe8 */ {NULL, NULL}, /* 0xe9 */ {NULL, NULL}, /* 0xea */ {NULL, NULL}, /* 0xeb */ {NULL, NULL}, /* 0xec */ {NULL, NULL}, /* 0xed */ {NULL, NULL}, /* 0xee */ {NULL, NULL}, /* 0xef */ {NULL, NULL}, /* 0xf0 */ {NULL, NULL}, /* 0xf1 */ {NULL, NULL}, /* 0xf2 */ {NULL, NULL}, /* 0xf3 */ {NULL, NULL}, /* 0xf4 */ {NULL, NULL}, /* 0xf5 */ {NULL, NULL}, /* 0xf6 */ {NULL, NULL}, /* 0xf7 */ {NULL, NULL}, /* 0xf8 */ {NULL, NULL}, /* 0xf9 */ {NULL, NULL}, /* 0xfa */ {NULL, NULL}, /* 0xfb */ {NULL, NULL}, /* 0xfc */ {NULL, NULL}, /* 0xfd */ {NULL, NULL}, /* 0xfe */ {NULL, NULL}, /* 0xff */ {NULL, NULL}, }; #define ENC_ALG_aes128_ccm 0x0001 static int dissect_smb2_transform_header(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, smb2_transform_info_t *sti, tvbuff_t **enc_tvb, tvbuff_t **plain_tvb) { proto_item *sesid_item = NULL; proto_tree *sesid_tree = NULL; smb2_sesid_info_t sesid_key; int sesid_offset; guint8 *plain_data = NULL; guint8 *decryption_key = NULL; proto_item *item; static const int *sf_fields[] = { &hf_smb2_encryption_aes128_ccm, NULL }; *enc_tvb = NULL; *plain_tvb = NULL; /* signature */ proto_tree_add_item(tree, hf_smb2_transform_signature, tvb, offset, 16, ENC_NA); offset += 16; /* nonce */ proto_tree_add_item(tree, hf_smb2_transform_nonce, tvb, offset, 16, ENC_NA); tvb_memcpy(tvb, sti->nonce, offset, 16); offset += 16; /* size */ proto_tree_add_item(tree, hf_smb2_transform_msg_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); sti->size = tvb_get_letohl(tvb, offset); offset += 4; /* reserved */ proto_tree_add_item(tree, hf_smb2_transform_reserved, tvb, offset, 2, ENC_NA); offset += 2; /* enc algorithm */ proto_tree_add_bitmask(tree, tvb, offset, hf_smb2_transform_enc_alg, ett_smb2_transform_enc_alg, sf_fields, ENC_LITTLE_ENDIAN); sti->alg = tvb_get_letohs(tvb, offset); offset += 2; /* session ID */ 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); sesid_tree = proto_item_add_subtree(sesid_item, ett_smb2_sesid_tree); offset += 8; /* now we need to first lookup the uid session */ sesid_key.sesid = sti->sesid; sti->session = (smb2_sesid_info_t *)g_hash_table_lookup(sti->conv->sesids, &sesid_key); if (sti->session != NULL && sti->session->auth_frame != (guint32)-1) { item = proto_tree_add_string(sesid_tree, hf_smb2_acct_name, tvb, sesid_offset, 0, sti->session->acct_name); PROTO_ITEM_SET_GENERATED(item); proto_item_append_text(sesid_item, " Acct:%s", sti->session->acct_name); item = proto_tree_add_string(sesid_tree, hf_smb2_domain_name, tvb, sesid_offset, 0, sti->session->domain_name); PROTO_ITEM_SET_GENERATED(item); proto_item_append_text(sesid_item, " Domain:%s", sti->session->domain_name); item = proto_tree_add_string(sesid_tree, hf_smb2_host_name, tvb, sesid_offset, 0, sti->session->host_name); PROTO_ITEM_SET_GENERATED(item); proto_item_append_text(sesid_item, " Host:%s", sti->session->host_name); item = proto_tree_add_uint(sesid_tree, hf_smb2_auth_frame, tvb, sesid_offset, 0, sti->session->auth_frame); PROTO_ITEM_SET_GENERATED(item); } if (sti->session != NULL && sti->alg == ENC_ALG_aes128_ccm) { if (pinfo->destport == sti->session->server_port) { decryption_key = sti->session->server_decryption_key; } else { decryption_key = sti->session->client_decryption_key; } if (memcmp(decryption_key, zeros, NTLMSSP_KEY_LEN) == 0) { decryption_key = NULL; } } if (decryption_key != NULL) { gcry_cipher_hd_t cipher_hd = NULL; guint8 A_1[NTLMSSP_KEY_LEN] = { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; memcpy(&A_1[1], sti->nonce, 15 - 4); 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)) { 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, NTLMSSP_KEY_LEN)) { gcry_cipher_close(cipher_hd); wmem_free(pinfo->pool, plain_data); plain_data = NULL; goto done_decryption; } if (gcry_cipher_setctr(cipher_hd, A_1, NTLMSSP_KEY_LEN)) { gcry_cipher_close(cipher_hd); 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); wmem_free(pinfo->pool, plain_data); plain_data = NULL; goto done_decryption; } /* Done with the cipher. */ gcry_cipher_close(cipher_hd); } done_decryption: *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); add_new_data_source(pinfo, *plain_tvb, "Decrypted SMB3"); } offset += sti->size; return offset; } static int dissect_smb2_command(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, smb2_info_t *si) { int (*cmd_dissector)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, smb2_info_t *si); proto_item *cmd_item; proto_tree *cmd_tree; int old_offset = offset; 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_dissector = (si->flags & SMB2_FLAGS_RESPONSE)? smb2_dissector[si->opcode&0xff].response: smb2_dissector[si->opcode&0xff].request; if (cmd_dissector) { 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_captured_length(tvb); } proto_item_set_len(cmd_item, offset-old_offset); return offset; } static int dissect_smb2_tid_sesid(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, smb2_info_t *si) { proto_item *tid_item = NULL; proto_tree *tid_tree = NULL; smb2_tid_info_t tid_key; int tid_offset = 0; proto_item *sesid_item = NULL; proto_tree *sesid_tree = NULL; smb2_sesid_info_t sesid_key; int sesid_offset; proto_item *item; if (si->flags&SMB2_FLAGS_ASYNC_CMD) { proto_tree_add_item(tree, hf_smb2_aid, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; } else { /* Process ID */ proto_tree_add_item(tree, hf_smb2_pid, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; /* Tree ID */ 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); tid_tree = proto_item_add_subtree(tid_item, ett_smb2_tid_tree); offset += 4; } /* Session ID */ 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); sesid_tree = proto_item_add_subtree(sesid_item, ett_smb2_sesid_tree); offset += 8; /* now we need to first lookup the uid session */ sesid_key.sesid = si->sesid; si->session = (smb2_sesid_info_t *)g_hash_table_lookup(si->conv->sesids, &sesid_key); if (!si->session) { guint8 seskey[NTLMSSP_KEY_LEN] = {0, }; if (si->opcode != 0x03) return offset; /* if we come to a session that is unknown, and the operation is * a tree connect, we create a dummy sessison, so we can hang the * tree data on it */ 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); if (si->flags & SMB2_FLAGS_RESPONSE) { si->session->server_port = pinfo->srcport; } else { si->session->server_port = pinfo->destport; } if (seskey_find_sid_key(si->sesid, seskey)) { smb2_set_session_keys(si->session, seskey); } g_hash_table_insert(si->conv->sesids, si->session, si->session); return offset; } if (si->session->auth_frame != (guint32)-1) { item = proto_tree_add_string(sesid_tree, hf_smb2_acct_name, tvb, sesid_offset, 0, si->session->acct_name); PROTO_ITEM_SET_GENERATED(item); proto_item_append_text(sesid_item, " Acct:%s", si->session->acct_name); item = proto_tree_add_string(sesid_tree, hf_smb2_domain_name, tvb, sesid_offset, 0, si->session->domain_name); PROTO_ITEM_SET_GENERATED(item); proto_item_append_text(sesid_item, " Domain:%s", si->session->domain_name); item = proto_tree_add_string(sesid_tree, hf_smb2_host_name, tvb, sesid_offset, 0, si->session->host_name); PROTO_ITEM_SET_GENERATED(item); proto_item_append_text(sesid_item, " Host:%s", si->session->host_name); item = proto_tree_add_uint(sesid_tree, hf_smb2_auth_frame, tvb, sesid_offset, 0, si->session->auth_frame); PROTO_ITEM_SET_GENERATED(item); } if (!(si->flags&SMB2_FLAGS_ASYNC_CMD)) { /* see if we can find the name for this tid */ tid_key.tid = si->tid; si->tree = (smb2_tid_info_t *)g_hash_table_lookup(si->session->tids, &tid_key); if (!si->tree) return offset; item = proto_tree_add_string(tid_tree, hf_smb2_tree, tvb, tid_offset, 4, si->tree->name); PROTO_ITEM_SET_GENERATED(item); proto_item_append_text(tid_item, " %s", si->tree->name); item = proto_tree_add_uint(tid_tree, hf_smb2_share_type, tvb, tid_offset, 0, si->tree->share_type); PROTO_ITEM_SET_GENERATED(item); item = proto_tree_add_uint(tid_tree, hf_smb2_tcon_frame, tvb, tid_offset, 0, si->tree->connect_frame); PROTO_ITEM_SET_GENERATED(item); } return offset; } static int dissect_smb2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean first_in_chain) { gboolean smb2_transform_header = FALSE; proto_item *item = NULL; proto_tree *tree = NULL; proto_item *header_item = NULL; proto_tree *header_tree = NULL; int offset = 0; int chain_offset = 0; const char *label = smb_header_label; conversation_t *conversation; smb2_saved_info_t *ssi = NULL, ssi_key; smb2_info_t *si; smb2_transform_info_t *sti; char *fid_name; guint32 open_frame,close_frame; smb2_eo_file_info_t *eo_file_info; e_ctx_hnd *policy_hnd_hashtablekey; sti = wmem_new(wmem_packet_scope(), smb2_transform_info_t); 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; label = smb_transform_header_label; } /* find which conversation we are part of and get the data for that * conversation */ conversation = find_or_create_conversation(pinfo); si->conv = (smb2_conv_info_t *)conversation_get_proto_data(conversation, proto_smb2); if (!si->conv) { /* no smb2_into_t structure for this conversation yet, * create it. */ si->conv = wmem_new(wmem_file_scope(), smb2_conv_info_t); /* qqq this leaks memory for now since we never free the hashtables */ si->conv->matched = g_hash_table_new(smb2_saved_info_hash_matched, smb2_saved_info_equal_matched); si->conv->unmatched = g_hash_table_new(smb2_saved_info_hash_unmatched, 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 * callback to free them. Ideally wmem would implement a simple * hash table so we wouldn't have to do this. */ wmem_register_callback(wmem_file_scope(), smb2_conv_destroy, si->conv); conversation_add_proto_data(conversation, proto_smb2, si->conv); } sti->conv = si->conv; col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMB2"); if (first_in_chain) { /* first packet */ col_clear(pinfo->cinfo, COL_INFO); } else { col_append_str(pinfo->cinfo, COL_INFO, ";"); } item = proto_tree_add_item(parent_tree, proto_smb2, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_smb2); 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_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 */ si->flags = tvb_get_letohl(tvb, offset+12); /* header length */ proto_tree_add_item(header_tree, hf_smb2_header_len, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* credit charge (previously "epoch" (unused) which has been deprecated as of "SMB 2.1") */ proto_tree_add_item(header_tree, hf_smb2_credit_charge, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* Status Code */ if (si->flags & SMB2_FLAGS_RESPONSE) { si->status = tvb_get_letohl(tvb, offset); proto_tree_add_item(header_tree, hf_smb2_nt_status, tvb, offset, 4, ENC_LITTLE_ENDIAN); offset += 4; } else { si->status = 0; proto_tree_add_item(header_tree, hf_smb2_channel_sequence, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(header_tree, hf_smb2_reserved, tvb, offset, 2, ENC_NA); offset += 2; } /* opcode */ si->opcode = tvb_get_letohs(tvb, offset); proto_tree_add_item(header_tree, hf_smb2_cmd, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; /* credits */ if (si->flags & SMB2_FLAGS_RESPONSE) { proto_tree_add_item(header_tree, hf_smb2_credits_granted, tvb, offset, 2, ENC_LITTLE_ENDIAN); } else { proto_tree_add_item(header_tree, hf_smb2_credits_requested, tvb, offset, 2, ENC_LITTLE_ENDIAN); } offset += 2; /* flags */ if (header_tree) { 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; /* Next Command */ chain_offset = tvb_get_letohl(tvb, offset); proto_tree_add_item(header_tree, hf_smb2_chain_offset, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Message ID */ si->msg_id = tvb_get_letoh64(tvb, offset); ssi_key.msg_id = si->msg_id; proto_tree_add_item(header_tree, hf_smb2_msg_id, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; /* Tree ID and Session ID */ offset = dissect_smb2_tid_sesid(pinfo, header_tree, tvb, offset, si); /* Signature */ proto_tree_add_item(header_tree, hf_smb2_signature, tvb, offset, 16, ENC_NA); offset += 16; proto_item_set_len(header_item, offset); col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s", decode_smb2_name(si->opcode), (si->flags & SMB2_FLAGS_RESPONSE)?"Response":"Request"); if (si->status) { col_append_fstr( pinfo->cinfo, COL_INFO, ", Error: %s", val_to_str_ext(si->status, &NT_errors_ext, "Unknown (0x%08X)")); } if (!pinfo->fd->visited) { /* see if we can find this msg_id in the unmatched table */ ssi = (smb2_saved_info_t *)g_hash_table_lookup(si->conv->unmatched, &ssi_key); if (!(si->flags & SMB2_FLAGS_RESPONSE)) { /* This is a request */ if (ssi) { /* this is a request and we already found * an older ssi so just delete the previous * one */ g_hash_table_remove(si->conv->unmatched, ssi); ssi = NULL; } if (!ssi) { /* 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->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 (!((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->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 couldn't find it in the matched table, it might still * be in the unmatched table */ if (!ssi) { ssi = (smb2_saved_info_t *)g_hash_table_lookup(si->conv->unmatched, &ssi_key); } } if (ssi) { 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) { eo_file_info = (smb2_eo_file_info_t *)g_hash_table_lookup(si->conv->files,&ssi->policy_hnd); if (!eo_file_info) { /* XXX This should never happen */ /* assert(1==0); */ eo_file_info = wmem_new(wmem_file_scope(), smb2_eo_file_info_t); policy_hnd_hashtablekey = wmem_new(wmem_file_scope(), e_ctx_hnd); memcpy(policy_hnd_hashtablekey, &ssi->policy_hnd, sizeof(e_ctx_hnd)); eo_file_info->end_of_file=0; g_hash_table_insert(si->conv->files,policy_hnd_hashtablekey,eo_file_info); } si->eo_file_info=eo_file_info; } } } if (!(si->flags & SMB2_FLAGS_RESPONSE)) { if (ssi->frame_res) { proto_item *tmp_item; tmp_item = proto_tree_add_uint(header_tree, hf_smb2_response_in, tvb, 0, 0, ssi->frame_res); PROTO_ITEM_SET_GENERATED(tmp_item); } } else { if (ssi->frame_req) { proto_item *tmp_item; nstime_t t, deltat; 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->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 don't have ssi yet we must fake it */ /*qqq*/ si->saved = ssi; tap_queue_packet(smb2_tap, pinfo, si); /* Decode the payload */ offset = dissect_smb2_command(pinfo, tree, tvb, offset, si); } else { proto_tree *enc_tree; tvbuff_t *enc_tvb = NULL; tvbuff_t *plain_tvb = NULL; /* SMB2_TRANSFORM marker */ 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_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); } else { col_append_str(pinfo->cinfo, COL_INFO, "Encrypted SMB3"); proto_tree_add_item(enc_tree, hf_smb2_transform_encrypted_data, enc_tvb, 0, sti->size, ENC_NA); } if (tvb_reported_length_remaining(tvb, offset) > 0) { chain_offset = offset; } } if (chain_offset > 0) { tvbuff_t *next_tvb; proto_item_set_len(item, chain_offset); next_tvb = tvb_new_subset_remaining(tvb, chain_offset); offset = dissect_smb2(next_tvb, pinfo, parent_tree, FALSE); } return offset; } static gboolean dissect_smb2_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void *data _U_) { /* must check that this really is a smb2 packet */ if (tvb_captured_length(tvb) < 4) return FALSE; if (((tvb_get_guint8(tvb, 0) != 0xfe) && (tvb_get_guint8(tvb, 0) != 0xfd)) || (tvb_get_guint8(tvb, 1) != 'S') || (tvb_get_guint8(tvb, 2) != 'M') || (tvb_get_guint8(tvb, 3) != 'B') ) { return FALSE; } dissect_smb2(tvb, pinfo, parent_tree, TRUE); return TRUE; } void proto_register_smb2(void) { module_t *smb2_module; static hf_register_info hf[] = { { &hf_smb2_cmd, { "Command", "smb2.cmd", FT_UINT16, BASE_DEC | BASE_EXT_STRING, &smb2_cmd_vals_ext, 0, "SMB2 Command Opcode", HFILL } }, { &hf_smb2_response_to, { "Response to", "smb2.response_to", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0, "This packet is a response to the packet in this frame", HFILL } }, { &hf_smb2_response_in, { "Response in", "smb2.response_in", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0, "The response to this packet is in this packet", HFILL } }, { &hf_smb2_time, { "Time from request", "smb2.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0, "Time between Request and Response for SMB2 cmds", HFILL } }, { &hf_smb2_header_len, { "Header Length", "smb2.header_len", FT_UINT16, BASE_DEC, NULL, 0, "SMB2 Size of Header", HFILL } }, { &hf_smb2_nt_status, { "NT Status", "smb2.nt_status", FT_UINT32, BASE_HEX | BASE_EXT_STRING, &NT_errors_ext, 0, "NT Status code", HFILL } }, { &hf_smb2_msg_id, { "Message ID", "smb2.msg_id", FT_UINT64, BASE_DEC|BASE_VAL64_STRING|BASE_SPECIAL_VALS, VALS64(unique_unsolicited_response), 0, NULL, HFILL } }, { &hf_smb2_tid, { "Tree Id", "smb2.tid", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_aid, { "Async Id", "smb2.aid", FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_sesid, { "Session Id", "smb2.sesid", FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_previous_sesid, { "Previous Session Id", "smb2.previous_sesid", FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_chain_offset, { "Chain Offset", "smb2.chain_offset", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_end_of_file, { "End Of File", "smb2.eof", FT_UINT64, BASE_DEC, NULL, 0, "SMB2 End Of File/File size", HFILL } }, { &hf_smb2_nlinks, { "Number of Links", "smb2.nlinks", FT_UINT32, BASE_DEC, NULL, 0, "Number of links to this object", HFILL } }, { &hf_smb2_file_id, { "File Id", "smb2.file_id", FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_allocation_size, { "Allocation Size", "smb2.allocation_size", FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_max_response_size, { "Max Response Size", "smb2.max_response_size", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_getinfo_input_size, { "Getinfo Input Size", "smb2.getinfo_input_size", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_getinfo_input_offset, { "Getinfo Input Offset", "smb2.getinfo_input_offset", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_getinfo_additional, { "Additional Info", "smb2.getinfo_additional", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_getinfo_flags, { "Flags", "smb2.getinfo_flags", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_setinfo_size, { "Setinfo Size", "smb2.setinfo_size", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_setinfo_offset, { "Setinfo Offset", "smb2.setinfo_offset", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_max_ioctl_out_size, { "Max Ioctl Out Size", "smb2.max_ioctl_out_size", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_max_ioctl_in_size, { "Max Ioctl In Size", "smb2.max_ioctl_in_size", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_required_buffer_size, { "Required Buffer Size", "smb2.required_size", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_pid, { "Process Id", "smb2.pid", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, /* SMB2 header flags */ { &hf_smb2_flags, { "Flags", "smb2.flags", FT_UINT32, BASE_HEX, NULL, 0, "SMB2 flags", HFILL } }, { &hf_smb2_flags_response, { "Response", "smb2.flags.response", FT_BOOLEAN, 32, TFS(&tfs_flags_response), SMB2_FLAGS_RESPONSE, "Whether this is an SMB2 Request or Response", HFILL } }, { &hf_smb2_flags_async_cmd, { "Async command", "smb2.flags.async", FT_BOOLEAN, 32, TFS(&tfs_flags_async_cmd), SMB2_FLAGS_ASYNC_CMD, NULL, HFILL } }, { &hf_smb2_flags_dfs_op, { "DFS operation", "smb2.flags.dfs", FT_BOOLEAN, 32, TFS(&tfs_flags_dfs_op), SMB2_FLAGS_DFS_OP, NULL, HFILL } }, { &hf_smb2_flags_chained, { "Chained", "smb2.flags.chained", FT_BOOLEAN, 32, TFS(&tfs_flags_chained), SMB2_FLAGS_CHAINED, "Whether the pdu continues a chain or not", HFILL } }, { &hf_smb2_flags_signature, { "Signing", "smb2.flags.signature", FT_BOOLEAN, 32, TFS(&tfs_flags_signature), SMB2_FLAGS_SIGNATURE, "Whether the pdu is signed or not", 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, NULL, HFILL } }, { &hf_smb2_filename_len, { "Filename Length", "smb2.filename.len", FT_UINT32, BASE_DEC, NULL, 0, NULL, 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 } }, { &hf_smb2_find_info_level, { "Info Level", "smb2.find.infolevel", FT_UINT32, BASE_DEC, VALS(smb2_find_info_levels), 0, "Find_Info Infolevel", HFILL } }, { &hf_smb2_find_flags, { "Find Flags", "smb2.find.flags", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_find_pattern, { "Search Pattern", "smb2.find.pattern", FT_STRING, BASE_NONE, NULL, 0, "Find pattern", HFILL } }, { &hf_smb2_find_info_blob, { "Info", "smb2.find.info_blob", FT_BYTES, BASE_NONE, NULL, 0, "Find Info", HFILL } }, { &hf_smb2_ea_size, { "EA Size", "smb2.ea_size", FT_UINT32, BASE_DEC, NULL, 0, "Size of EA data", HFILL } }, { &hf_smb2_position_information, { "Position Information", "smb2.position_info", FT_UINT64, BASE_DEC, NULL, 0, "Current file position", HFILL } }, { &hf_smb2_mode_information, { "Mode Information", "smb2.mode_info", FT_UINT32, BASE_HEX, NULL, 0, "File mode informatino", HFILL } }, { &hf_smb2_mode_file_write_through, { "FILE_WRITE_THROUGH", "smb2.mode.file_write_through", FT_UINT32, BASE_HEX, NULL, 0x02, NULL, HFILL } }, { &hf_smb2_mode_file_sequential_only, { "FILE_SEQUENTIAL_ONLY", "smb2.mode.file_sequential_only", FT_UINT32, BASE_HEX, NULL, 0x04, NULL, HFILL } }, { &hf_smb2_mode_file_no_intermediate_buffering, { "FILE_NO_INTERMEDIATE_BUFFERING", "smb2.mode.file_no_intermediate_buffering", FT_UINT32, BASE_HEX, NULL, 0x08, NULL, HFILL } }, { &hf_smb2_mode_file_synchronous_io_alert, { "FILE_SYNCHRONOUS_IO_ALERT", "smb2.mode.file_synchronous_io_alert", FT_UINT32, BASE_HEX, NULL, 0x10, NULL, HFILL } }, { &hf_smb2_mode_file_synchronous_io_nonalert, { "FILE_SYNCHRONOUS_IO_NONALERT", "smb2.mode.file_synchronous_io_nonalert", FT_UINT32, BASE_HEX, NULL, 0x20, NULL, HFILL } }, { &hf_smb2_mode_file_delete_on_close, { "FILE_DELETE_ON_CLOSE", "smb2.mode.file_delete_on_close", FT_UINT32, BASE_HEX, NULL, 0x1000, NULL, HFILL } }, { &hf_smb2_alignment_information, { "Alignment Information", "smb2.alignment_info", FT_UINT32, BASE_HEX, VALS(smb2_alignment_vals), 0, "File alignment", HFILL} }, { &hf_smb2_class, { "Class", "smb2.class", FT_UINT8, BASE_HEX, VALS(smb2_class_vals), 0, "Info class", HFILL } }, { &hf_smb2_infolevel, { "InfoLevel", "smb2.infolevel", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_infolevel_file_info, { "InfoLevel", "smb2.file_info.infolevel", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &smb2_file_info_levels_ext, 0, "File_Info Infolevel", HFILL } }, { &hf_smb2_infolevel_fs_info, { "InfoLevel", "smb2.fs_info.infolevel", FT_UINT8, BASE_HEX | BASE_EXT_STRING, &smb2_fs_info_levels_ext, 0, "Fs_Info Infolevel", HFILL } }, { &hf_smb2_infolevel_sec_info, { "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 } }, { &hf_smb2_read_length, { "Read Length", "smb2.read_length", FT_UINT32, BASE_DEC, NULL, 0, "Amount of data to read", HFILL } }, { &hf_smb2_read_remaining, { "Read Remaining", "smb2.read_remaining", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_create_flags, { "Create Flags", "smb2.create_flags", FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_file_offset, { "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 } }, { &hf_smb2_ioctl_out_data, { "Out Data", "smb2.ioctl.out", FT_NONE, BASE_NONE, NULL, 0, "Ioctl Out", HFILL } }, { &hf_smb2_ioctl_in_data, { "In Data", "smb2.ioctl.in", FT_NONE, BASE_NONE, NULL, 0, "Ioctl In", HFILL } }, { &hf_smb2_server_guid, { "Server Guid", "smb2.server_guid", FT_GUID, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_client_guid, { "Client Guid", "smb2.client_guid", FT_GUID, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_object_id, { "ObjectId", "smb2.object_id", FT_GUID, BASE_NONE, NULL, 0, "ObjectID for this FID", HFILL } }, { &hf_smb2_birth_volume_id, { "BirthVolumeId", "smb2.birth_volume_id", FT_GUID, BASE_NONE, NULL, 0, "ObjectID for the volume where this FID was originally created", HFILL } }, { &hf_smb2_birth_object_id, { "BirthObjectId", "smb2.birth_object_id", FT_GUID, BASE_NONE, NULL, 0, "ObjectID for this FID when it was originally created", HFILL } }, { &hf_smb2_domain_id, { "DomainId", "smb2.domain_id", FT_GUID, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_create_timestamp, { "Create", "smb2.create.time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, "Time when this object was created", HFILL } }, { &hf_smb2_fid, { "File Id", "smb2.fid", FT_GUID, BASE_NONE, NULL, 0, "SMB2 File Id", HFILL } }, { &hf_smb2_write_data, { "Write Data", "smb2.write_data", FT_BYTES, BASE_NONE, NULL, 0, "SMB2 Data to be written", HFILL } }, { &hf_smb2_write_flags, { "Write Flags", "smb2.write.flags", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_write_flags_write_through, { "Write through", "smb2.write.flags.write_through", FT_BOOLEAN, 32, NULL, SMB2_WRITE_FLAG_WRITE_THROUGH, NULL, HFILL } }, { &hf_smb2_write_count, { "Write Count", "smb2.write.count", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_write_remaining, { "Write Remaining", "smb2.write.remaining", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_read_data, { "Read Data", "smb2.read_data", FT_BYTES, BASE_NONE, NULL, 0, "SMB2 Data that is read", HFILL } }, { &hf_smb2_last_access_timestamp, { "Last Access", "smb2.last_access.time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, "Time when this object was last accessed", HFILL } }, { &hf_smb2_last_write_timestamp, { "Last Write", "smb2.last_write.time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, "Time when this object was last written to", HFILL } }, { &hf_smb2_last_change_timestamp, { "Last Change", "smb2.last_change.time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, "Time when this object was last changed", HFILL } }, { &hf_smb2_file_all_info, { "SMB2_FILE_ALL_INFO", "smb2.file_all_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_file_allocation_info, { "SMB2_FILE_ALLOCATION_INFO", "smb2.file_allocation_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_file_endoffile_info, { "SMB2_FILE_ENDOFFILE_INFO", "smb2.file_endoffile_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_file_alternate_name_info, { "SMB2_FILE_ALTERNATE_NAME_INFO", "smb2.file_alternate_name_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_file_stream_info, { "SMB2_FILE_STREAM_INFO", "smb2.file_stream_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_file_pipe_info, { "SMB2_FILE_PIPE_INFO", "smb2.file_pipe_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_file_compression_info, { "SMB2_FILE_COMPRESSION_INFO", "smb2.file_compression_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_file_basic_info, { "SMB2_FILE_BASIC_INFO", "smb2.file_basic_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_file_standard_info, { "SMB2_FILE_STANDARD_INFO", "smb2.file_standard_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_file_internal_info, { "SMB2_FILE_INTERNAL_INFO", "smb2.file_internal_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_file_mode_info, { "SMB2_FILE_MODE_INFO", "smb2.file_mode_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_file_alignment_info, { "SMB2_FILE_ALIGNMENT_INFO", "smb2.file_alignment_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_file_position_info, { "SMB2_FILE_POSITION_INFO", "smb2.file_position_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_file_access_info, { "SMB2_FILE_ACCESS_INFO", "smb2.file_access_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_file_ea_info, { "SMB2_FILE_EA_INFO", "smb2.file_ea_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_file_network_open_info, { "SMB2_FILE_NETWORK_OPEN_INFO", "smb2.file_network_open_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_file_attribute_tag_info, { "SMB2_FILE_ATTRIBUTE_TAG_INFO", "smb2.file_attribute_tag_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_file_disposition_info, { "SMB2_FILE_DISPOSITION_INFO", "smb2.file_disposition_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_file_full_ea_info, { "SMB2_FILE_FULL_EA_INFO", "smb2.file_full_ea_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_file_rename_info, { "SMB2_FILE_RENAME_INFO", "smb2.file_rename_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_fs_info_01, { "FileFsVolumeInformation", "smb2.fs_volume_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_fs_info_03, { "FileFsSizeInformation", "smb2.fs_size_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_fs_info_04, { "FileFsDeviceInformation", "smb2.fs_device_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_fs_info_05, { "FileFsAttributeInformation", "smb2.fs_attribute_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_fs_info_06, { "FileFsControlInformation", "smb2.fs_control_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_fs_info_07, { "FileFsFullSizeInformation", "smb2.fs_full_size_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_fs_objectid_info, { "FileFsObjectIdInformation", "smb2.fs_objectid_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_sec_info_00, { "SMB2_SEC_INFO_00", "smb2.sec_info_00", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_quota_info, { "SMB2_QUOTA_INFO", "smb2.quota_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_query_quota_info, { "SMB2_QUERY_QUOTA_INFO", "smb2.query_quota_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_qq_single, { "ReturnSingle", "smb2.query_quota_info.single", FT_BOOLEAN, 8, NULL, 0xff, NULL, HFILL } }, { &hf_smb2_qq_restart, { "RestartScan", "smb2.query_quota_info.restart", FT_BOOLEAN, 8, NULL, 0xff, NULL, HFILL } }, { &hf_smb2_qq_sidlist_len, { "SidListLength", "smb2.query_quota_info.sidlistlen", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_qq_start_sid_len, { "StartSidLength", "smb2.query_quota_info.startsidlen", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_qq_start_sid_offset, { "StartSidOffset", "smb2.query_quota_info.startsidoffset", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_disposition_delete_on_close, { "Delete on close", "smb2.disposition.delete_on_close", FT_BOOLEAN, 8, TFS(&tfs_disposition_delete_on_close), 0x01, NULL, HFILL } }, { &hf_smb2_create_disposition, { "Disposition", "smb2.create.disposition", FT_UINT32, BASE_DEC, VALS(create_disposition_vals), 0, "Create disposition, what to do if the file does/does not exist", HFILL } }, { &hf_smb2_create_action, { "Create Action", "smb2.create.action", FT_UINT32, BASE_DEC, VALS(oa_open_vals), 0, NULL, HFILL } }, { &hf_smb2_create_rep_flags, { "Response Flags", "smb2.create.rep_flags", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_create_rep_flags_reparse_point, { "ReparsePoint", "smb2.create.rep_flags.reparse_point", FT_BOOLEAN, 8, NULL, SMB2_CREATE_REP_FLAGS_REPARSE_POINT, NULL, HFILL } }, { &hf_smb2_extrainfo, { "ExtraInfo", "smb2.create.extrainfo", FT_NONE, BASE_NONE, NULL, 0, "Create ExtraInfo", HFILL } }, { &hf_smb2_create_chain_offset, { "Chain Offset", "smb2.create.chain_offset", FT_UINT32, BASE_HEX, NULL, 0, "Offset to next entry in chain or 0", HFILL } }, { &hf_smb2_create_chain_data, { "Data", "smb2.create.chain_data", FT_NONE, BASE_NONE, NULL, 0, "Chain Data", HFILL } }, { &hf_smb2_FILE_OBJECTID_BUFFER, { "FILE_OBJECTID_BUFFER", "smb2.FILE_OBJECTID_BUFFER", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_lease_key, { "Lease Key", "smb2.lease.lease_key", FT_GUID, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_lease_state, { "Lease State", "smb2.lease.lease_state", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_lease_state_read_caching, { "Read Caching", "smb2.lease.lease_state.read_caching", FT_BOOLEAN, 32, NULL, SMB2_LEASE_STATE_READ_CACHING, NULL, HFILL } }, { &hf_smb2_lease_state_handle_caching, { "Handle Caching", "smb2.lease.lease_state.handle_caching", FT_BOOLEAN, 32, NULL, SMB2_LEASE_STATE_HANDLE_CACHING, NULL, HFILL } }, { &hf_smb2_lease_state_write_caching, { "Write Caching", "smb2.lease.lease_state.write_caching", FT_BOOLEAN, 32, NULL, SMB2_LEASE_STATE_WRITE_CACHING, NULL, HFILL } }, { &hf_smb2_lease_flags, { "Lease Flags", "smb2.lease.lease_flags", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_lease_flags_break_ack_required, { "Break Ack Required", "smb2.lease.lease_state.break_ack_required", FT_BOOLEAN, 32, NULL, SMB2_LEASE_FLAGS_BREAK_ACK_REQUIRED, NULL, HFILL } }, { &hf_smb2_lease_flags_break_in_progress, { "Break In Progress", "smb2.lease.lease_state.break_in_progress", FT_BOOLEAN, 32, NULL, SMB2_LEASE_FLAGS_BREAK_IN_PROGRESS, NULL, HFILL } }, { &hf_smb2_lease_flags_parent_lease_key_set, { "Parent Lease Key Set", "smb2.lease.lease_state.parent_lease_key_set", FT_BOOLEAN, 32, NULL, SMB2_LEASE_FLAGS_PARENT_LEASE_KEY_SET, NULL, HFILL } }, { &hf_smb2_lease_duration, { "Lease Duration", "smb2.lease.lease_duration", FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_parent_lease_key, { "Parent Lease Key", "smb2.lease.parent_lease_key", FT_GUID, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_lease_epoch, { "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, { "Lease Break Reason", "smb2.lease.lease_break_reason", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_lease_access_mask_hint, { "Access Mask Hint", "smb2.lease.access_mask_hint", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_lease_share_mask_hint, { "Share Mask Hint", "smb2.lease.share_mask_hint", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_next_offset, { "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, NULL, HFILL } }, { &hf_smb2_negotiate_context_data_length, { "DataLength", "smb2.negotiate_context.data_length", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_negotiate_context_offset, { "NegotiateContextOffset", "smb2.negotiate_context.offset", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_negotiate_context_count, { "NegotiateContextCount", "smb2.negotiate_context.count", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_hash_alg_count, { "HashAlgorithmCount", "smb2.negotiate_context.hash_alg_count", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }}, { &hf_smb2_hash_algorithm, { "HashAlgorithm", "smb2.negotiate_context.hash_algorithm", FT_UINT16, BASE_HEX, VALS(smb2_hash_algorithm_types), 0, NULL, HFILL }}, { &hf_smb2_salt_length, { "SaltLength", "smb2.negotiate_context.salt_length", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }}, { &hf_smb2_salt, { "Salt", "smb2.negotiate_context.salt", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }}, { &hf_smb2_cipher_count, { "CipherCount", "smb2.negotiate_context.cipher_count", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }}, { &hf_smb2_cipher_id, { "CipherId", "smb2.negotiate_context.cipher_id", FT_UINT16, BASE_HEX, VALS(smb2_cipher_types), 0, NULL, 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_boot_time, { "Boot Time", "smb2.boot_time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, "Boot Time at server", HFILL } }, { &hf_smb2_ea_flags, { "EA Flags", "smb2.ea.flags", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_ea_name_len, { "EA Name Length", "smb2.ea.name_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_ea_data_len, { "EA Data Length", "smb2.ea.data_len", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_delete_pending, { "Delete Pending", "smb2.delete_pending", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_is_directory, { "Is Directory", "smb2.is_directory", FT_UINT8, BASE_DEC, NULL, 0, "Is this a directory?", HFILL } }, { &hf_smb2_oplock, { "Oplock", "smb2.create.oplock", FT_UINT8, BASE_HEX, VALS(oplock_vals), 0, "Oplock type", HFILL } }, { &hf_smb2_close_flags, { "Close Flags", "smb2.close.flags", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_notify_flags, { "Notify Flags", "smb2.notify.flags", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_buffer_code, { "StructureSize", "smb2.buffer_code", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_buffer_code_len, { "Fixed Part Length", "smb2.buffer_code.length", FT_UINT16, BASE_DEC, NULL, 0xFFFE, "Length of fixed portion of PDU", HFILL } }, { &hf_smb2_olb_length, { "Blob Length", "smb2.olb.length", FT_UINT32, BASE_DEC, NULL, 0, "Length of the buffer", HFILL } }, { &hf_smb2_olb_offset, { "Blob Offset", "smb2.olb.offset", FT_UINT32, BASE_HEX, NULL, 0, "Offset to the buffer", HFILL } }, { &hf_smb2_buffer_code_flags_dyn, { "Dynamic Part", "smb2.buffer_code.dynamic", FT_BOOLEAN, 16, NULL, 0x0001, "Whether a dynamic length blob follows", HFILL } }, { &hf_smb2_ea_data, { "EA Data", "smb2.ea.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_ea_name, { "EA Name", "smb2.ea.name", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_impersonation_level, { "Impersonation level", "smb2.impersonation.level", FT_UINT32, BASE_DEC, VALS(impersonation_level_vals), 0, NULL, HFILL } }, { &hf_smb2_ioctl_function, { "Function", "smb2.ioctl.function", FT_UINT32, BASE_HEX | BASE_EXT_STRING, &smb2_ioctl_vals_ext, 0, "Ioctl function", HFILL } }, { &hf_smb2_ioctl_function_device, { "Device", "smb2.ioctl.function.device", FT_UINT32, BASE_HEX | BASE_EXT_STRING, &smb2_ioctl_device_vals_ext, 0xffff0000, "Device for Ioctl", HFILL } }, { &hf_smb2_ioctl_function_access, { "Access", "smb2.ioctl.function.access", FT_UINT32, BASE_HEX, VALS(smb2_ioctl_access_vals), 0x0000c000, "Access for Ioctl", HFILL } }, { &hf_smb2_ioctl_function_function, { "Function", "smb2.ioctl.function.function", FT_UINT32, BASE_HEX, NULL, 0x00003ffc, "Function for Ioctl", HFILL } }, { &hf_smb2_ioctl_function_method, { "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, NULL, HFILL } }, { &hf_smb2_fsctl_odx_token_idlen, { "TokenIdLength", "smb2.fsctl.odx.token.idlen", FT_UINT16, BASE_DEC, NULL, 0, NULL, 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, NULL, HFILL } }, { &hf_smb2_fsctl_odx_copy_length, { "CopyLength", "smb2.fsctl.odx.copy_length", FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_fsctl_odx_xfer_length, { "TransferLength", "smb2.fsctl.odx.xfer_length", FT_UINT64, BASE_DEC, NULL, 0, NULL, 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 } }, { &hf_smb2_ioctl_resiliency_reserved, { "Reserved", "smb2.ioctl.resiliency.reserved", FT_UINT32, BASE_DEC, NULL, 0, "Resiliency reserved", HFILL } }, { &hf_smb2_ioctl_shared_virtual_disk_support, { "SharedVirtualDiskSupport", "smb2.ioctl.shared_virtual_disk.support", FT_UINT32, BASE_HEX, VALS(smb2_ioctl_shared_virtual_disk_vals), 0, "Supported shared capabilities", HFILL } }, { &hf_smb2_ioctl_shared_virtual_disk_handle_state, { "SharedVirtualDiskHandleState", "smb2.ioctl.shared_virtual_disk.handle_state", FT_UINT32, BASE_HEX, VALS(smb2_ioctl_shared_virtual_disk_hstate_vals), 0, NULL, HFILL } }, { &hf_smb2_ioctl_sqos_protocol_version, { "ProtocolVersion", "smb2.ioctl.sqos.protocol_version", FT_UINT16, BASE_HEX, VALS(smb2_ioctl_sqos_protocol_version_vals), 0, NULL, HFILL } }, { &hf_smb2_ioctl_sqos_reserved, { "Reserved", "smb2.ioctl.sqos.reserved", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_ioctl_sqos_options, { "Operations", "smb2.ioctl.sqos.operations", FT_UINT32, BASE_HEX, NULL, 0, "SQOS operations", HFILL } }, { &hf_smb2_ioctl_sqos_op_set_logical_flow_id, { "Set Logical Flow ID", "smb2.ioctl.sqos.operations.set_logical_flow_id", FT_BOOLEAN, 32, NULL, STORAGE_QOS_CONTROL_FLAG_SET_LOGICAL_FLOW_ID, "Whether Set Logical Flow ID operation is performed", HFILL } }, { &hf_smb2_ioctl_sqos_op_set_policy, { "Set Policy", "smb2.ioctl.sqos.operations.set_policy", FT_BOOLEAN, 32, NULL, STORAGE_QOS_CONTROL_FLAG_SET_POLICY, "Whether Set Policy operation is performed", HFILL } }, { &hf_smb2_ioctl_sqos_op_probe_policy, { "Probe Policy", "smb2.ioctl.sqos.operations.probe_policy", FT_BOOLEAN, 32, NULL, STORAGE_QOS_CONTROL_FLAG_PROBE_POLICY, "Whether Probe Policy operation is performed", HFILL } }, { &hf_smb2_ioctl_sqos_op_get_status, { "Get Status", "smb2.ioctl.sqos.operations.get_status", FT_BOOLEAN, 32, NULL, STORAGE_QOS_CONTROL_FLAG_GET_STATUS, "Whether Get Status operation is performed", HFILL } }, { &hf_smb2_ioctl_sqos_op_update_counters, { "Update Counters", "smb2.ioctl.sqos.operations.update_counters", FT_BOOLEAN, 32, NULL, STORAGE_QOS_CONTROL_FLAG_UPDATE_COUNTERS, "Whether Update Counters operation is performed", HFILL } }, { &hf_smb2_ioctl_sqos_logical_flow_id, { "LogicalFlowID", "smb2.ioctl.sqos.logical_flow_id", FT_GUID, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_ioctl_sqos_policy_id, { "PolicyID", "smb2.ioctl.sqos.policy_id", FT_GUID, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_ioctl_sqos_initiator_id, { "InitiatorID", "smb2.ioctl.sqos.initiator_id", FT_GUID, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_ioctl_sqos_limit, { "Limit", "smb2.ioctl.sqos.limit", FT_UINT64, BASE_DEC, NULL, 0, "Desired maximum throughput for the logical flow, in normalized IOPS", HFILL } }, { &hf_smb2_ioctl_sqos_reservation, { "Reservation", "smb2.ioctl.sqos.reservation", FT_UINT64, BASE_DEC, NULL, 0, "Desired minimum throughput for the logical flow, in normalized 8KB IOPS", HFILL } }, { &hf_smb2_ioctl_sqos_initiator_name, { "InitiatorName", "smb2.ioctl.sqos.initiator_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_smb2_ioctl_sqos_initiator_node_name, { "InitiatorNodeName", "smb2.ioctl.sqos.initiator_node_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_smb2_ioctl_sqos_io_count_increment, { "IoCountIncrement", "smb2.ioctl.sqos.io_count_increment", FT_UINT64, BASE_DEC, NULL, 0, "The total number of I/O requests issued by the initiator on the logical flow", HFILL } }, { &hf_smb2_ioctl_sqos_normalized_io_count_increment, { "NormalizedIoCountIncrement", "smb2.ioctl.sqos.normalized_io_count_increment", FT_UINT64, BASE_DEC, NULL, 0, "The total number of normalized 8-KB I/O requests issued by the initiator on the logical flow", HFILL } }, { &hf_smb2_ioctl_sqos_latency_increment, { "LatencyIncrement", "smb2.ioctl.sqos.latency_increment", FT_UINT64, BASE_DEC, NULL, 0, "The total latency (including initiator's queues delays) measured by the initiator", HFILL } }, { &hf_smb2_ioctl_sqos_lower_latency_increment, { "LowerLatencyIncrement", "smb2.ioctl.sqos.lower_latency_increment", FT_UINT64, BASE_DEC, NULL, 0, "The total latency (excluding initiator's queues delays) measured by the initiator", HFILL } }, { &hf_smb2_ioctl_sqos_bandwidth_limit, { "BandwidthLimit", "smb2.ioctl.sqos.bandwidth_limit", FT_UINT64, BASE_DEC, NULL, 0, "Desired maximum bandwidth for the logical flow, in kilobytes per second", HFILL } }, { &hf_smb2_ioctl_sqos_kilobyte_count_increment, { "KilobyteCountIncrement", "smb2.ioctl.sqos.kilobyte_count_increment", FT_UINT64, BASE_DEC, NULL, 0, "The total data transfer length of all I/O requests, in kilobyte units, issued by the initiator on the logical flow", HFILL } }, { &hf_smb2_ioctl_sqos_time_to_live, { "TimeToLive", "smb2.ioctl.sqos.time_to_live", FT_UINT32, BASE_DEC, NULL, 0, "The expected period of validity of the Status, MaximumIoRate and MinimumIoRate fields, expressed in milliseconds", HFILL } }, { &hf_smb2_ioctl_sqos_status, { "Status", "smb2.ioctl.sqos.status", FT_UINT32, BASE_HEX, VALS(smb2_ioctl_sqos_status_vals), 0, "The current status of the logical flow", HFILL } }, { &hf_smb2_ioctl_sqos_maximum_io_rate, { "MaximumIoRate", "smb2.ioctl.sqos.maximum_io_rate", FT_UINT64, BASE_DEC, NULL, 0, "The maximum I/O initiation rate currently assigned to the logical flow, expressed in normalized input/output operations per second (normalized IOPS)", HFILL } }, { &hf_smb2_ioctl_sqos_minimum_io_rate, { "MinimumIoRate", "smb2.ioctl.sqos.minimum_io_rate", FT_UINT64, BASE_DEC, NULL, 0, "The minimum I/O completion rate currently assigned to the logical flow, expressed in normalized IOPS", HFILL } }, { &hf_smb2_ioctl_sqos_base_io_size, { "BaseIoSize", "smb2.ioctl.sqos.base_io_size", FT_UINT32, BASE_DEC, NULL, 0, "The base I/O size used to compute the normalized size of an I/O request for the logical flow", HFILL } }, { &hf_smb2_ioctl_sqos_reserved2, { "Reserved", "smb2.ioctl.sqos.reserved2", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_ioctl_sqos_maximum_bandwidth, { "MaximumBandwidth", "smb2.ioctl.sqos.maximum_bandwidth", FT_UINT64, BASE_DEC, NULL, 0, "The maximum bandwidth currently assigned to the logical flow, expressed in kilobytes per second", HFILL } }, { &hf_windows_sockaddr_family, { "Socket Family", "smb2.windows.sockaddr.family", FT_UINT16, BASE_DEC, NULL, 0, "The socket address family (on windows)", HFILL } }, { &hf_windows_sockaddr_port, { "Socket Port", "smb2.windows.sockaddr.port", FT_UINT16, BASE_DEC, NULL, 0, "The socket address port", HFILL } }, { &hf_windows_sockaddr_in_addr, { "Socket IPv4", "smb2.windows.sockaddr.in.addr", FT_IPv4, BASE_NONE, NULL, 0, "The IPv4 address", HFILL } }, { &hf_windows_sockaddr_in6_flowinfo, { "IPv6 Flow Info", "smb2.windows.sockaddr.in6.flow_info", FT_UINT32, BASE_HEX, NULL, 0, "The socket IPv6 flow info", HFILL } }, { &hf_windows_sockaddr_in6_addr, { "Socket IPv6", "smb2.windows.sockaddr.in6.addr", FT_IPv6, BASE_NONE, NULL, 0, "The IPv6 address", HFILL } }, { &hf_windows_sockaddr_in6_scope_id, { "IPv6 Scope ID", "smb2.windows.sockaddr.in6.scope_id", FT_UINT32, BASE_DEC, NULL, 0, "The socket IPv6 scope id", HFILL } }, { &hf_smb2_ioctl_network_interface_next_offset, { "Next Offset", "smb2.ioctl.network_interfaces.next_offset", FT_UINT32, BASE_HEX, NULL, 0, "Offset to next entry in chain or 0", HFILL } }, { &hf_smb2_ioctl_network_interface_index, { "Interface Index", "smb2.ioctl.network_interfaces.index", FT_UINT32, BASE_DEC, NULL, 0, "The index of the interface", HFILL } }, { &hf_smb2_ioctl_network_interface_rss_queue_count, { "RSS Queue Count", "smb2.ioctl.network_interfaces.rss_queue_count", FT_UINT32, BASE_DEC, NULL, 0, "The RSS queue count", HFILL } }, { &hf_smb2_ioctl_network_interface_capabilities, { "Interface Cababilities", "smb2.ioctl.network_interfaces.capabilities", FT_UINT32, BASE_HEX, NULL, 0, "The RSS queue count", HFILL } }, { &hf_smb2_ioctl_network_interface_capability_rss, { "RSS", "smb2.ioctl.network_interfaces.capabilities.rss", FT_BOOLEAN, 32, TFS(&tfs_smb2_ioctl_network_interface_capability_rss), NETWORK_INTERFACE_CAP_RSS, "If the host supports RSS", HFILL } }, { &hf_smb2_ioctl_network_interface_capability_rdma, { "RDMA", "smb2.ioctl.network_interfaces.capabilities.rdma", FT_BOOLEAN, 32, TFS(&tfs_smb2_ioctl_network_interface_capability_rdma), NETWORK_INTERFACE_CAP_RDMA, "If the host supports RDMA", HFILL } }, { &hf_smb2_ioctl_network_interface_link_speed, { "Link Speed", "smb2.ioctl.network_interfaces.link_speed", FT_UINT64, BASE_DEC, NULL, 0, "The link speed of the interface", HFILL } }, { &hf_smb2_ioctl_shadow_copy_num_volumes, { "Num Volumes", "smb2.ioctl.shadow_copy.num_volumes", FT_UINT32, BASE_DEC, NULL, 0, "Number of shadow copy volumes", HFILL } }, { &hf_smb2_ioctl_shadow_copy_num_labels, { "Num Labels", "smb2.ioctl.shadow_copy.num_labels", FT_UINT32, BASE_DEC, NULL, 0, "Number of shadow copy labels", HFILL } }, { &hf_smb2_ioctl_shadow_copy_label, { "Label", "smb2.ioctl.shadow_copy.label", FT_STRING, BASE_NONE, NULL, 0, "Shadow copy label", HFILL } }, { &hf_smb2_compression_format, { "Compression Format", "smb2.compression_format", FT_UINT16, BASE_DEC, VALS(compression_format_vals), 0, NULL, HFILL } }, { &hf_smb2_checksum_algorithm, { "Checksum Algorithm", "smb2.checksum_algorithm", FT_UINT16, BASE_HEX, VALS(checksum_algorithm_vals), 0, NULL, HFILL } }, { &hf_smb2_integrity_reserved, { "Reserved", "smb2.integrity_reserved", FT_UINT16, BASE_DEC, NULL, 0, NULL, 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 } }, { &hf_smb2_credit_charge, { "Credit Charge", "smb2.credit.charge", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_credits_requested, { "Credits requested", "smb2.credits.requested", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_credits_granted, { "Credits granted", "smb2.credits.granted", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_channel_sequence, { "Channel Sequence", "smb2.channel_sequence", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_dialect_count, { "Dialect count", "smb2.dialect_count", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_dialect, { "Dialect", "smb2.dialect", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_security_mode, { "Security mode", "smb2.sec_mode", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_session_flags, { "Session Flags", "smb2.session_flags", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_lock_count, { "Lock Count", "smb2.lock_count", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_capabilities, { "Capabilities", "smb2.capabilities", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_ioctl_shadow_copy_count, { "Count", "smb2.ioctl.shadow_copy.count", FT_UINT32, BASE_DEC, NULL, 0, "Number of bytes for shadow copy label strings", HFILL } }, { &hf_smb2_auth_frame, { "Authenticated in Frame", "smb2.auth_frame", FT_UINT32, BASE_DEC, NULL, 0, "Which frame this user was authenticated in", HFILL } }, { &hf_smb2_tcon_frame, { "Connected in Frame", "smb2.tcon_frame", FT_UINT32, BASE_DEC, NULL, 0, "Which frame this share was connected in", HFILL } }, { &hf_smb2_tag, { "Tag", "smb2.tag", FT_STRING, BASE_NONE, NULL, 0, "Tag of chain entry", HFILL } }, { &hf_smb2_acct_name, { "Account", "smb2.acct", FT_STRING, BASE_NONE, NULL, 0, "Account Name", HFILL } }, { &hf_smb2_domain_name, { "Domain", "smb2.domain", FT_STRING, BASE_NONE, NULL, 0, "Domain Name", HFILL } }, { &hf_smb2_host_name, { "Host", "smb2.host", FT_STRING, BASE_NONE, NULL, 0, "Host Name", HFILL } }, { &hf_smb2_signature, { "Signature", "smb2.signature", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_unknown, { "Unknown", "smb2.unknown", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_twrp_timestamp, { "Timestamp", "smb2.twrp_timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, "TWrp timestamp", HFILL } }, { &hf_smb2_mxac_timestamp, { "Timestamp", "smb2.mxac_timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, "MxAc timestamp", HFILL } }, { &hf_smb2_mxac_status, { "Query Status", "smb2.mxac_status", FT_UINT32, BASE_HEX | BASE_EXT_STRING, &NT_errors_ext, 0, "NT Status code", HFILL } }, { &hf_smb2_qfid_fid, { "Opaque File ID", "smb2.qfid_fid", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_ses_flags_guest, { "Guest", "smb2.ses_flags.guest", FT_BOOLEAN, 16, NULL, SES_FLAGS_GUEST, NULL, HFILL } }, { &hf_smb2_ses_flags_null, { "Null", "smb2.ses_flags.null", FT_BOOLEAN, 16, NULL, SES_FLAGS_NULL, NULL, HFILL } }, { &hf_smb2_ses_flags_encrypt, { "Encrypt", "smb2.ses_flags.encrypt", FT_BOOLEAN, 16, NULL, SES_FLAGS_ENCRYPT, NULL, HFILL }}, { &hf_smb2_secmode_flags_sign_required, { "Signing required", "smb2.sec_mode.sign_required", FT_BOOLEAN, 8, NULL, NEGPROT_SIGN_REQ, "Is signing required", HFILL } }, { &hf_smb2_secmode_flags_sign_enabled, { "Signing enabled", "smb2.sec_mode.sign_enabled", FT_BOOLEAN, 8, NULL, NEGPROT_SIGN_ENABLED, "Is signing enabled", HFILL } }, { &hf_smb2_ses_req_flags, { "Flags", "smb2.ses_req_flags", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_ses_req_flags_session_binding, { "Session Binding Request", "smb2.ses_req_flags.session_binding", FT_BOOLEAN, 8, NULL, SES_REQ_FLAGS_SESSION_BINDING, "The client wants to bind to an existing session", HFILL } }, { &hf_smb2_cap_dfs, { "DFS", "smb2.capabilities.dfs", FT_BOOLEAN, 32, TFS(&tfs_cap_dfs), NEGPROT_CAP_DFS, "If the host supports dfs", HFILL } }, { &hf_smb2_cap_leasing, { "LEASING", "smb2.capabilities.leasing", FT_BOOLEAN, 32, TFS(&tfs_cap_leasing), NEGPROT_CAP_LEASING, "If the host supports leasing", HFILL } }, { &hf_smb2_cap_large_mtu, { "LARGE MTU", "smb2.capabilities.large_mtu", FT_BOOLEAN, 32, TFS(&tfs_cap_large_mtu), NEGPROT_CAP_LARGE_MTU, "If the host supports LARGE MTU", HFILL } }, { &hf_smb2_cap_multi_channel, { "MULTI CHANNEL", "smb2.capabilities.multi_channel", FT_BOOLEAN, 32, TFS(&tfs_cap_multi_channel), NEGPROT_CAP_MULTI_CHANNEL, "If the host supports MULTI CHANNEL", HFILL } }, { &hf_smb2_cap_persistent_handles, { "PERSISTENT HANDLES", "smb2.capabilities.persistent_handles", FT_BOOLEAN, 32, TFS(&tfs_cap_persistent_handles), NEGPROT_CAP_PERSISTENT_HANDLES, "If the host supports PERSISTENT HANDLES", HFILL } }, { &hf_smb2_cap_directory_leasing, { "DIRECTORY LEASING", "smb2.capabilities.directory_leasing", FT_BOOLEAN, 32, TFS(&tfs_cap_directory_leasing), NEGPROT_CAP_DIRECTORY_LEASING, "If the host supports DIRECTORY LEASING", HFILL } }, { &hf_smb2_cap_encryption, { "ENCRYPTION", "smb2.capabilities.encryption", FT_BOOLEAN, 32, TFS(&tfs_cap_encryption), NEGPROT_CAP_ENCRYPTION, "If the host supports ENCRYPTION", HFILL } }, { &hf_smb2_max_trans_size, { "Max Transaction Size", "smb2.max_trans_size", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_max_read_size, { "Max Read Size", "smb2.max_read_size", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_max_write_size, { "Max Write Size", "smb2.max_write_size", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_channel, { "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, { "Share flags", "smb2.share_flags", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_share_flags_dfs, { "DFS", "smb2.share_flags.dfs", FT_BOOLEAN, 32, NULL, SHARE_FLAGS_dfs, "The specified share is present in a Distributed File System (DFS) tree structure", HFILL } }, { &hf_smb2_share_flags_dfs_root, { "DFS root", "smb2.share_flags.dfs_root", FT_BOOLEAN, 32, NULL, SHARE_FLAGS_dfs_root, "The specified share is present in a Distributed File System (DFS) tree structure", HFILL } }, { &hf_smb2_share_flags_restrict_exclusive_opens, { "Restrict exclusive opens", "smb2.share_flags.restrict_exclusive_opens", FT_BOOLEAN, 32, NULL, SHARE_FLAGS_restrict_exclusive_opens, "The specified share disallows exclusive file opens that deny reads to an open file", HFILL } }, { &hf_smb2_share_flags_force_shared_delete, { "Force shared delete", "smb2.share_flags.force_shared_delete", FT_BOOLEAN, 32, NULL, SHARE_FLAGS_force_shared_delete, "Shared files in the specified share can be forcibly deleted", HFILL } }, { &hf_smb2_share_flags_allow_namespace_caching, { "Allow namepsace caching", "smb2.share_flags.allow_namespace_caching", FT_BOOLEAN, 32, NULL, SHARE_FLAGS_allow_namespace_caching, "Clients are allowed to cache the namespace of the specified share", HFILL } }, { &hf_smb2_share_flags_access_based_dir_enum, { "Access based directory enum", "smb2.share_flags.access_based_dir_enum", FT_BOOLEAN, 32, NULL, SHARE_FLAGS_access_based_dir_enum, "The server will filter directory entries based on the access permissions of the client", HFILL } }, { &hf_smb2_share_flags_force_levelii_oplock, { "Force level II oplock", "smb2.share_flags.force_levelii_oplock", FT_BOOLEAN, 32, NULL, SHARE_FLAGS_force_levelii_oplock, "The server will not issue exclusive caching rights on this share", HFILL } }, { &hf_smb2_share_flags_enable_hash_v1, { "Enable hash V1", "smb2.share_flags.enable_hash_v1", FT_BOOLEAN, 32, NULL, SHARE_FLAGS_enable_hash_v1, "The share supports hash generation V1 for branch cache retrieval of data (see also section 2.2.31.2 of MS-SMB2)", HFILL } }, { &hf_smb2_share_flags_enable_hash_v2, { "Enable hash V2", "smb2.share_flags.enable_hash_v2", FT_BOOLEAN, 32, NULL, SHARE_FLAGS_enable_hash_v2, "The share supports hash generation V2 for branch cache retrieval of data (see also section 2.2.31.2 of MS-SMB2)", HFILL } }, { &hf_smb2_share_flags_encrypt_data, { "Encrypted data required", "smb2.share_flags.encrypt_data", FT_BOOLEAN, 32, NULL, SHARE_FLAGS_encryption_required, "The share require data encryption", HFILL } }, { &hf_smb2_share_caching, { "Caching policy", "smb2.share.caching", FT_UINT32, BASE_HEX, VALS(share_cache_vals), 0, NULL, HFILL } }, { &hf_smb2_share_caps, { "Share Capabilities", "smb2.share_caps", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_share_caps_dfs, { "DFS", "smb2.share_caps.dfs", FT_BOOLEAN, 32, NULL, SHARE_CAPS_DFS, "The specified share is present in a DFS tree structure", HFILL } }, { &hf_smb2_share_caps_continuous_availability, { "CONTINUOUS AVAILABILITY", "smb2.share_caps.continuous_availability", FT_BOOLEAN, 32, NULL, SHARE_CAPS_CONTINUOUS_AVAILABILITY, "The specified share is continuously available", HFILL } }, { &hf_smb2_share_caps_scaleout, { "SCALEOUT", "smb2.share_caps.scaleout", FT_BOOLEAN, 32, NULL, SHARE_CAPS_SCALEOUT, "The specified share is a scaleout share", HFILL } }, { &hf_smb2_share_caps_cluster, { "CLUSTER", "smb2.share_caps.cluster", FT_BOOLEAN, 32, NULL, SHARE_CAPS_CLUSTER, "The specified share is a cluster share", HFILL } }, { &hf_smb2_ioctl_flags, { "Flags", "smb2.ioctl.flags", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_min_count, { "Min Count", "smb2.min_count", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_remaining_bytes, { "Remaining Bytes", "smb2.remaining_bytes", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_channel_info_offset, { "Channel Info Offset", "smb2.channel_info_offset", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_channel_info_length, { "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 } }, { &hf_smb2_output_buffer_len, { "Output Buffer Length", "smb2.output_buffer_len", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_close_pq_attrib, { "PostQuery Attrib", "smb2.close.pq_attrib", FT_BOOLEAN, 16, NULL, 0x0001, NULL, HFILL } }, { &hf_smb2_notify_watch_tree, { "Watch Tree", "smb2.notify.watch_tree", FT_BOOLEAN, 16, NULL, 0x0001, NULL, HFILL } }, { &hf_smb2_notify_out_data, { "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 } }, { &hf_smb2_find_flags_single_entry, { "Single Entry", "smb2.find.single_entry", FT_BOOLEAN, 8, NULL, SMB2_FIND_FLAG_SINGLE_ENTRY, NULL, HFILL } }, { &hf_smb2_find_flags_index_specified, { "Index Specified", "smb2.find.index_specified", FT_BOOLEAN, 8, NULL, SMB2_FIND_FLAG_INDEX_SPECIFIED, NULL, HFILL } }, { &hf_smb2_find_flags_reopen, { "Reopen", "smb2.find.reopen", FT_BOOLEAN, 8, NULL, SMB2_FIND_FLAG_REOPEN, NULL, HFILL } }, { &hf_smb2_file_index, { "File Index", "smb2.file_index", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_file_directory_info, { "FileDirectoryInfo", "smb2.find.file_directory_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_full_directory_info, { "FullDirectoryInfo", "smb2.find.full_directory_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_both_directory_info, { "FileBothDirectoryInfo", "smb2.find.both_directory_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_id_both_directory_info, { "FileIdBothDirectoryInfo", "smb2.find.id_both_directory_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_short_name_len, { "Short Name Length", "smb2.short_name_len", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_short_name, { "Short Name", "smb2.shortname", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_lock_info, { "Lock Info", "smb2.lock_info", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_lock_length, { "Length", "smb2.lock_length", FT_UINT64, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_lock_flags, { "Flags", "smb2.lock_flags", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_lock_flags_shared, { "Shared", "smb2.lock_flags.shared", FT_BOOLEAN, 32, NULL, 0x00000001, NULL, HFILL } }, { &hf_smb2_lock_flags_exclusive, { "Exclusive", "smb2.lock_flags.exclusive", FT_BOOLEAN, 32, NULL, 0x00000002, NULL, HFILL } }, { &hf_smb2_lock_flags_unlock, { "Unlock", "smb2.lock_flags.unlock", FT_BOOLEAN, 32, NULL, 0x00000004, NULL, HFILL } }, { &hf_smb2_lock_flags_fail_immediately, { "Fail Immediately", "smb2.lock_flags.fail_immediately", FT_BOOLEAN, 32, NULL, 0x00000010, NULL, HFILL } }, { &hf_smb2_error_context_count, { "Error Context Count", "smb2.error.context_count", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_error_reserved, { "Reserved", "smb2.error.reserved", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_error_byte_count, { "Byte Count", "smb2.error.byte_count", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_error_data, { "Error Data", "smb2.error.data", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_reserved, { "Reserved", "smb2.reserved", FT_BYTES, BASE_NONE, NULL, 0, NULL, 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, NULL, HFILL } }, { &hf_smb2_dhnq_buffer_reserved, { "Reserved", "smb2.dhnq_buffer_reserved", FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_dh2x_buffer_timeout, { "Timeout", "smb2.dh2x.timeout", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_dh2x_buffer_flags, { "Flags", "smb2.dh2x.flags", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_dh2x_buffer_flags_persistent_handle, { "Persistent Handle", "smb2.dh2x.flags.persistent_handle", FT_BOOLEAN, 32, NULL, SMB2_DH2X_FLAGS_PERSISTENT_HANDLE, NULL, HFILL } }, { &hf_smb2_dh2x_buffer_reserved, { "Reserved", "smb2.dh2x.reserved", FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_dh2x_buffer_create_guid, { "Create Guid", "smb2.dh2x.create_guid", FT_GUID, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_APP_INSTANCE_buffer_struct_size, { "Struct Size", "smb2.app_instance.struct_size", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_APP_INSTANCE_buffer_reserved, { "Reserved", "smb2.app_instance.reserved", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_APP_INSTANCE_buffer_app_guid, { "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_GUID, 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, NULL, 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_svhdx_open_device_context_virtual_disk_properties_initialized, { "VirtualDiskPropertiesInitialized", "smb2.svhdx_open_device_context.virtual_disk_properties_initialized", FT_BOOLEAN, 32, NULL, 0, "Whether VirtualSectorSize, PhysicalSectorSize, and VirtualSize fields are filled", HFILL } }, { &hf_smb2_svhdx_open_device_context_server_service_version, { "ServerServiceVersion", "smb2.svhdx_open_device_context.server_service_version", FT_UINT32, BASE_DEC, NULL, 0, "The current version of the protocol running on the server", HFILL } }, { &hf_smb2_svhdx_open_device_context_virtual_sector_size, { "VirtualSectorSize", "smb2.svhdx_open_device_context.virtual_sector_size", FT_UINT32, BASE_DEC, NULL, 0, "The virtual sector size of the virtual disk", HFILL } }, { &hf_smb2_svhdx_open_device_context_physical_sector_size, { "PhysicalSectorSize", "smb2.svhdx_open_device_context.physical_sector_size", FT_UINT32, BASE_DEC, NULL, 0, "The physical sector size of the virtual disk", HFILL } }, { &hf_smb2_svhdx_open_device_context_virtual_size, { "VirtualSize", "smb2.svhdx_open_device_context.virtual_size", FT_UINT64, BASE_DEC, NULL, 0, "The current length of the virtual disk, in bytes", 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 macOS 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 } }, { &hf_smb2_transform_nonce, { "Nonce", "smb2.header.transform.nonce", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_transform_msg_size, { "Message size", "smb2.header.transform.msg_size", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, { &hf_smb2_transform_reserved, { "Reserved", "smb2.header.transform.reserved", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_transform_enc_alg, { "Encryption ALG", "smb2.header.transform.encryption_alg", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } }, { &hf_smb2_encryption_aes128_ccm, { "SMB2_ENCRYPTION_AES128_CCM", "smb2.header.transform.enc_aes128_ccm", FT_BOOLEAN, 16, NULL, ENC_ALG_aes128_ccm, NULL, HFILL } }, { &hf_smb2_transform_encrypted_data, { "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, NULL, 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, NULL, HFILL } }, { &hf_smb2_pipe_fragments, { "Reassembled SMB2 Named Pipe fragments", "smb2.pipe.fragments", FT_NONE, BASE_NONE, NULL, 0x0, NULL, 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 } }, { &hf_smb2_symlink_error_response, { "Symbolic Link Error Response", "smb2.symlink_error_response", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_symlink_length, { "SymLink Length", "smb2.symlink.length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_smb2_symlink_error_tag, { "SymLink Error Tag", "smb2.symlink.error_tag", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_smb2_SYMBOLIC_LINK_REPARSE_DATA_BUFFER, { "SYMBOLIC_LINK_REPARSE_DATA_BUFFER", "smb2.SYMBOLIC_LINK_REPARSE_DATA_BUFFER", FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_smb2_reparse_tag, { "Reparse Tag", "smb2.symlink.reparse_tag", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_smb2_reparse_data_length, { "Reparse Data Length", "smb2.symlink.reparse_data_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_smb2_unparsed_path_length, { "Unparsed Path Length", "smb2.symlink.unparsed_path_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_smb2_symlink_substitute_name, { "Substitute Name", "smb2.symlink.substitute_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_smb2_symlink_print_name, { "Print Name", "smb2.symlink.print_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_smb2_symlink_flags, { "Flags", "smb2.symlink.flags", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, }; static gint *ett[] = { &ett_smb2, &ett_smb2_ea, &ett_smb2_olb, &ett_smb2_header, &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_file_ea_info, &ett_smb2_file_access_info, &ett_smb2_file_rename_info, &ett_smb2_file_disposition_info, &ett_smb2_file_position_info, &ett_smb2_file_full_ea_info, &ett_smb2_file_mode_info, &ett_smb2_file_alignment_info, &ett_smb2_file_all_info, &ett_smb2_file_allocation_info, &ett_smb2_file_endoffile_info, &ett_smb2_file_alternate_name_info, &ett_smb2_file_stream_info, &ett_smb2_file_pipe_info, &ett_smb2_file_compression_info, &ett_smb2_file_network_open_info, &ett_smb2_file_attribute_tag_info, &ett_smb2_fs_info_01, &ett_smb2_fs_info_03, &ett_smb2_fs_info_04, &ett_smb2_fs_info_05, &ett_smb2_fs_info_06, &ett_smb2_fs_info_07, &ett_smb2_fs_objectid_info, &ett_smb2_sec_info_00, &ett_smb2_quota_info, &ett_smb2_query_quota_info, &ett_smb2_tid_tree, &ett_smb2_sesid_tree, &ett_smb2_create_chain_element, &ett_smb2_MxAc_buffer, &ett_smb2_QFid_buffer, &ett_smb2_RqLs_buffer, &ett_smb2_ioctl_function, &ett_smb2_FILE_OBJECTID_BUFFER, &ett_smb2_flags, &ett_smb2_sec_mode, &ett_smb2_capabilities, &ett_smb2_ses_req_flags, &ett_smb2_ses_flags, &ett_smb2_create_rep_flags, &ett_smb2_lease_state, &ett_smb2_lease_flags, &ett_smb2_share_flags, &ett_smb2_share_caps, &ett_smb2_ioctl_flags, &ett_smb2_ioctl_network_interface, &ett_smb2_ioctl_sqos_opeations, &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_both_directory_info, &ett_smb2_id_both_directory_info, &ett_smb2_full_directory_info, &ett_smb2_file_name_info, &ett_smb2_lock_info, &ett_smb2_lock_flags, &ett_smb2_DH2Q_buffer, &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, &ett_smb2_symlink_error_response, &ett_smb2_SYMBOLIC_LINK_REPARSE_DATA_BUFFER, &ett_smb2_error_data, }; 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 }}, { &ei_smb2_invalid_getinfo_offset, { "smb2.invalid_getinfo_offset", PI_MALFORMED, PI_ERROR, "Input buffer offset isn't past the fixed data in the message", EXPFILL }}, { &ei_smb2_invalid_getinfo_size, { "smb2.invalid_getinfo_size", PI_MALFORMED, PI_ERROR, "Input buffer length goes past the end of the message", EXPFILL }}, { &ei_smb2_empty_getinfo_buffer, { "smb2.empty_getinfo_buffer", PI_PROTOCOL, PI_WARN, "Input buffer length is empty for a quota request", EXPFILL }}, }; expert_module_t* expert_smb2; /* SessionID <=> SessionKey mappings for decryption */ uat_t *seskey_uat; static uat_field_t seskey_uat_fields[] = { UAT_FLD_BUFFER(seskey_list, id, "Session ID", "The session ID buffer, coded as hex string, as it appears on the wire (LE)."), UAT_FLD_BUFFER(seskey_list, key, "Session Key", "The secret session key buffer, coded as 16-byte hex string as it appears on the wire (LE)."), UAT_END_FIELDS }; 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", "Use the full file name as File ID when exporting an SMB2 object", "Whether the export object functionality will take the full path file name as file identifier", &eosmb2_take_name_as_fid); 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); seskey_uat = uat_new("Secret session key to use for decryption", sizeof(smb2_seskey_field_t), "smb2_seskey_list", TRUE, &seskey_list, &num_seskey_list, (UAT_AFFECTS_DISSECTION | UAT_AFFECTS_FIELDS), NULL, seskey_list_copy_cb, seskey_list_update_cb, seskey_list_free_cb, NULL, NULL, seskey_uat_fields); prefs_register_uat_preference(smb2_module, "seskey_list", "Secret session keys for decryption", "A table of Session ID to Session key mappings used to derive decryption keys.", seskey_uat); smb2_pipe_subdissector_list = register_heur_dissector_list("smb2_pipe_subdissectors", proto_smb2); /* * 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_register(&smb2_pipe_reassembly_table, &addresses_reassembly_table_functions); 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_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); } /* * Editor modelines - http://www.wireshark.org/tools/modelines.html * * Local variables: * c-basic-offset: 8 * tab-width: 8 * indent-tabs-mode: t * End: * * vi: set shiftwidth=8 tabstop=8 noexpandtab: * :indentSize=8:tabSize=8:noTabs=false: */