aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexis La Goutte <alexis.lagoutte@gmail.com>2013-03-09 08:44:14 +0000
committerAlexis La Goutte <alexis.lagoutte@gmail.com>2013-03-09 08:44:14 +0000
commita4eb0a12ed36795fb75ab427e5bc2d09a8b95ca0 (patch)
treecfc06ac1a525d2b3b124e5dcb2e77207b6fe790f
parente5d5bb67bc4265ab96bff535d0eb8ca8820e062f (diff)
From Jose Pico via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8377 NEW FEATURE IMPLEMENTED: SMB2 SUPPORT FOR EXPORT->OBJECTS->SMB
Added functionality: - SMB2 support for Export->Objects->SMB - support for SMB_COM_CREATE, SMB_COM_OPEN, SMB_COM_READ and SMB_COM_WRITE commands - Ability to choose between File Id and full file name as identifier for file re-building. Implemented as an option under Edit->Preferences->Protocols->SMB and Edit->Preferences->Protocols->SMB2. Other minor changes and fixes: - Full filename in file - Inclusion of IP of SMB server when treeid name (i.e. hostname) is not known - UTF-8 filenames encoding before passing them to Export Object Window - Re-written insert_chunk function of export_object_smb.c to make it easier to debug - Fixed of an error in insert_chunk function of export_object_smb.c (the verification of next free_chunk was always skipped after deleting one free_chunk). - Removed duplicated code by inserting the function feed_eo_smb in packet-smb.c and packet-smb2.c - Changed the label of Export->Objects->SMB menu into Export->Objects->SMB/SMB2 svn path=/trunk/; revision=48210
-rw-r--r--epan/dissectors/packet-smb.c378
-rw-r--r--epan/dissectors/packet-smb.h36
-rw-r--r--epan/dissectors/packet-smb2.c269
-rw-r--r--epan/dissectors/packet-smb2.h64
-rw-r--r--ui/export_object.h4
-rw-r--r--ui/export_object_smb.c652
-rw-r--r--ui/gtk/export_object_dlg.c36
-rw-r--r--ui/gtk/main_menubar.c2
8 files changed, 984 insertions, 457 deletions
diff --git a/epan/dissectors/packet-smb.c b/epan/dissectors/packet-smb.c
index 1c2683ceac..4f608c5aa9 100644
--- a/epan/dissectors/packet-smb.c
+++ b/epan/dissectors/packet-smb.c
@@ -924,6 +924,107 @@ static int dissect_smb_command(tvbuff_t *tvb, packet_info *pinfo, int offset, pr
gboolean sid_display_hex = FALSE;
gboolean sid_name_snooping = FALSE;
+/* ExportObject preferences variable */
+gboolean eosmb_take_name_as_fid = FALSE ;
+/* Utility to get an str reprensenting ipv4 or ipv6 address */
+const gchar *tree_ip_str(packet_info *pinfo, guint16 cmd) {
+ const gchar *buf;
+
+ if (pinfo->src.type==AT_IPv4) {
+ if ( cmd==SMB_COM_READ_ANDX ||
+ cmd==SMB_COM_READ ||
+ cmd==SMB2_COM_READ) {
+ buf=(gchar *)ip_to_str(pinfo->src.data);
+ } else {
+ buf=(gchar *)ip_to_str(pinfo->dst.data);
+ }
+ } else {
+ if ( cmd==SMB_COM_READ_ANDX ||
+ cmd==SMB_COM_READ ||
+ cmd==SMB2_COM_READ) {
+ buf=(gchar *)ip6_to_str(pinfo->src.data);
+ } else {
+ buf=(gchar *)ip6_to_str(pinfo->dst.data);
+ }
+ }
+
+ return buf;
+}
+
+
+/* ExportObject feed function*/
+static void
+feed_eo_smb(guint16 cmd, guint16 fid, tvbuff_t * tvb,packet_info *pinfo,guint16 dataoffset,guint32 datalen, guint32 chunk_len, guint64 file_offset) {
+ smb_eo_t *eo_info; /* eo_info variable to pass info. to
+ export object and aux */
+ smb_tid_info_t *tid_info = NULL;
+ smb_fid_info_t *fid_info = NULL;
+ smb_fid_info_t *suspect_fid_info = NULL;
+ tvbuff_t *data_tvb;
+ GSList *GSL_iterator;
+
+ smb_info_t *si = (smb_info_t *)pinfo->private_data;
+
+ /* Create a new tvb to point to the payload data */
+ data_tvb = tvb_new_subset(tvb, dataoffset, datalen, datalen);
+ /* Create the eo_info to pass to the listener */
+ eo_info = ep_alloc(sizeof(smb_eo_t));
+
+ /* Try to get fid_info and tid_info */
+ if (fid_info == NULL) {
+ GSL_iterator = si->ct->GSL_fid_info;
+ while (GSL_iterator) {
+ suspect_fid_info = GSL_iterator->data;
+ if (suspect_fid_info->opened_in > pinfo->fd->num) break;
+ if ((suspect_fid_info->tid == si->tid) && (suspect_fid_info->fid == fid))
+ fid_info = suspect_fid_info;
+ GSL_iterator = g_slist_next(GSL_iterator);
+ }
+ }
+
+
+ tid_info = se_tree_lookup32(si->ct->tid_tree, si->tid);
+
+ /* Construct the eo_info structure */
+ eo_info->smbversion=1;
+ if (tid_info) {
+ if (tid_info->filename) {
+ eo_info->hostname = tid_info->filename;
+ } else {
+ eo_info->hostname = ep_strdup_printf("\\\\%s\\TREEID_UNKNOWN",tree_ip_str(pinfo,cmd));
+ }
+ }
+ else eo_info->hostname = ep_strdup_printf("\\\\%s\\TREEID_%i",tree_ip_str(pinfo,cmd),si->tid);
+ if (fid_info) {
+ eo_info->filename = NULL;
+ if (fid_info->fsi)
+ if (fid_info->fsi->filename)
+ eo_info->filename = (gchar *) fid_info->fsi->filename;
+ if (!eo_info->filename) eo_info->filename = ep_strdup_printf("\\FILEID_%i",fid);
+ eo_info->fid_type = fid_info->type;
+ eo_info->end_of_file = fid_info->end_of_file;
+ } else {
+ eo_info->fid_type = SMB_FID_TYPE_UNKNOWN;
+ eo_info->filename = ep_strdup_printf("\\FILEID_%i",fid);
+ eo_info->end_of_file = 0;
+ }
+ if (eosmb_take_name_as_fid) {
+ eo_info->fid = g_str_hash(eo_info->filename);
+ } else {
+ eo_info->fid = fid;
+ }
+ eo_info->tid = si->tid;
+ eo_info->uid = si->uid;
+ eo_info->payload_len = datalen;
+ eo_info->payload_data = tvb_get_ptr(data_tvb, 0, datalen);
+ eo_info->smb_file_offset = file_offset;
+ eo_info->smb_chunk_len = chunk_len;
+ eo_info->cmd = cmd;
+ /* Queue data to the listener */
+
+ tap_queue_packet(smb_eo_tap, pinfo, eo_info);
+} /* feed_eo_smb */
+
/* Compare funtion to maintain the GSL_fid_info ordered
Order criteria: packet where the fid was opened */
static gint
@@ -3172,6 +3273,7 @@ dissect_open_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, i
const char *fn;
guint8 wc;
guint16 bc;
+ smb_fid_saved_info_t *fsi; /* eo_smb needs to track this info */
DISSECTOR_ASSERT(si);
@@ -3199,6 +3301,23 @@ dissect_open_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, i
fn);
COUNT_BYTES(fn_len);
+ /* store it for the fid->name/openframe/closeframe matching in
+ * dissect_smb_fid() called from the response.
+ */
+ if ((!pinfo->fd->flags.visited) && si->sip && fn) {
+ fsi = se_alloc(sizeof(smb_fid_saved_info_t));
+ fsi->filename = se_strdup(fn);
+ fsi->create_flags = 0;
+ fsi->access_mask = 0;
+ fsi->file_attributes = 0;
+ fsi->share_access = 0;
+ fsi->create_options = 0;
+ fsi->create_disposition = 0;
+
+ si->sip->extra_info_type = SMB_EI_FILEDATA;
+ si->sip->extra_info = fsi;
+ }
+
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s",
format_text(fn, strlen(fn)));
@@ -3572,12 +3691,31 @@ dissect_open_file_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
guint8 wc;
guint16 bc;
guint16 fid;
+ smb_fid_info_t *fid_info = NULL; /* eo_smb needs to track this info */
+ guint16 fattr;
+ gboolean isdir = FALSE;
WORD_COUNT;
/* fid */
fid = tvb_get_letohs(tvb, offset);
- dissect_smb_fid(tvb, pinfo, tree, offset, 2, fid, TRUE, FALSE, FALSE);
+
+ fid_info = dissect_smb_fid(tvb, pinfo, tree, offset, 2, fid, TRUE, FALSE, FALSE);
+ if (fid_info) {
+ /* This command is used to create and open a new file or open
+ and truncate an existing file to zero length */
+ fid_info->end_of_file = 0;
+ /* File Type */
+ fattr=fid_info->fsi->file_attributes;
+ /* XXX Volumes considered as directories */
+ isdir = (fattr & SMB_FILE_ATTRIBUTE_DIRECTORY) || (fattr & SMB_FILE_ATTRIBUTE_VOLUME);
+ if (isdir == 0) {
+ fid_info->type = SMB_FID_TYPE_FILE;
+ } else {
+ fid_info->type = SMB_FID_TYPE_DIR;
+ }
+ }
+
offset += 2;
/* File Attributes */
@@ -3711,12 +3849,30 @@ dissect_create_file_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
guint8 wc;
guint16 bc;
guint16 fid;
+ smb_fid_info_t *fid_info = NULL; /* eo_smb needs to track this info */
+ guint16 fattr;
+ gboolean isdir = FALSE;
WORD_COUNT;
/* fid */
fid = tvb_get_letohs(tvb, offset);
- dissect_smb_fid(tvb, pinfo, tree, offset, 2, fid, TRUE, FALSE, FALSE);
+ fid_info = dissect_smb_fid(tvb, pinfo, tree, offset, 2, fid, TRUE, FALSE, FALSE);
+ if (fid_info) {
+ /* This command is used to create and open a new file or open
+ and truncate an existing file to zero length */
+ fid_info->end_of_file = 0;
+ /* File Type */
+ fattr=fid_info->fsi->file_attributes;
+ /* XXX Volumes considered as directories */
+ isdir = (fattr & SMB_FILE_ATTRIBUTE_DIRECTORY) || (fattr & SMB_FILE_ATTRIBUTE_VOLUME);
+ if (isdir == 0) {
+ fid_info->type = SMB_FID_TYPE_FILE;
+ } else {
+ fid_info->type = SMB_FID_TYPE_DIR;
+ }
+ }
+
offset += 2;
BYTE_COUNT;
@@ -3734,12 +3890,16 @@ dissect_create_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
const char *fn;
guint8 wc;
guint16 bc;
+ smb_fid_saved_info_t *fsi; /* eo_smb needs to track this info */
+ guint32 file_attributes = 0;
DISSECTOR_ASSERT(si);
WORD_COUNT;
/* file attributes */
+ /* We read the two lower bytes into the four-bytes file-attributes, because they are compatible */
+ file_attributes = tvb_get_letohs(tvb, offset);
offset = dissect_file_attributes(tvb, tree, offset);
/* creation time */
@@ -3761,6 +3921,24 @@ dissect_create_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
fn);
COUNT_BYTES(fn_len);
+ /* store it for the fid->name/openframe/closeframe matching in
+ * dissect_smb_fid() called from the response.
+ */
+ if ((!pinfo->fd->flags.visited) && si->sip && fn) {
+ fsi = se_alloc(sizeof(smb_fid_saved_info_t));
+ fsi->filename = se_strdup(fn);
+ fsi->create_flags = 0;
+ fsi->access_mask = 0;
+ fsi->file_attributes = file_attributes;
+ fsi->share_access = 0;
+ fsi->create_options = 0;
+ fsi->create_disposition = 0;
+
+ si->sip->extra_info_type = SMB_EI_FILEDATA;
+ si->sip->extra_info = fsi;
+ }
+
+
if (check_col(pinfo->cinfo, COL_INFO)) {
col_append_fstr(pinfo->cinfo, COL_INFO, ", Path: %s",
format_text(fn, strlen(fn)));
@@ -4101,6 +4279,12 @@ dissect_set_information_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t
return offset;
}
+typedef struct _rw_info_t {
+ guint64 offset;
+ guint32 len;
+ guint16 fid;
+} rw_info_t;
+
static int
dissect_read_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
{
@@ -4108,6 +4292,8 @@ dissect_read_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, i
guint16 cnt = 0, bc;
guint32 ofs = 0;
unsigned int fid;
+ rw_info_t *rwi = NULL;
+ smb_info_t *si = (smb_info_t *)pinfo->private_data;
WORD_COUNT;
@@ -4135,6 +4321,16 @@ dissect_read_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, i
proto_tree_add_item(tree, hf_smb_remaining, tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
+ /* save the offset/len for this transaction */
+ if (si->sip && !pinfo->fd->flags.visited) {
+ rwi = se_alloc(sizeof(rw_info_t));
+ rwi->offset = ofs;
+ rwi->len = cnt;
+ rwi->fid = fid;
+ si->sip->extra_info_type = SMB_EI_RWINFO;
+ si->sip->extra_info = rwi;
+ }
+
BYTE_COUNT;
END_OF_SMB
@@ -4225,6 +4421,9 @@ dissect_read_file_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
guint8 wc;
smb_info_t *si = (smb_info_t *)pinfo->private_data;
int fid = 0;
+ guint32 datalen=0,dataoffset=0;
+ guint32 tvblen;
+ rw_info_t *rwi = NULL;
DISSECTOR_ASSERT(si);
@@ -4248,7 +4447,9 @@ dissect_read_file_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
/* data len */
CHECK_BYTE_COUNT(2);
proto_tree_add_item(tree, hf_smb_data_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
+ datalen = tvb_get_letohs(tvb, offset);
COUNT_BYTES(2);
+ dataoffset=offset;
/* file data, might be DCERPC on a pipe */
if (bc) {
@@ -4257,6 +4458,33 @@ dissect_read_file_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
bc = 0;
}
+ /* If we have seen the request, then print which FID this refers to */
+ if ((si->sip != NULL) && (si->sip->frame_req > 0) && (si->sip->extra_info_type == SMB_EI_FID)) {
+ fid = GPOINTER_TO_INT(si->sip->extra_info);
+ }
+
+ if (si->sip && (si->sip->extra_info_type == SMB_EI_RWINFO)) {
+ rwi = si->sip->extra_info;
+ }
+ if (rwi) {
+ proto_item *it;
+
+ it = proto_tree_add_uint64(tree, hf_smb_file_rw_offset, tvb, 0, 0, rwi->offset);
+
+ PROTO_ITEM_SET_GENERATED(it);
+ it = proto_tree_add_uint(tree, hf_smb_file_rw_length, tvb, 0, 0, rwi->len);
+ PROTO_ITEM_SET_GENERATED(it);
+
+ /* we need the fid for the call to dcerpc below */
+ fid = rwi->fid;
+ }
+
+ /* feed the export object tap listener */
+ tvblen = tvb_length_remaining(tvb, dataoffset);
+ if (have_tap_listener(smb_eo_tap) && (datalen == tvblen) && rwi) {
+ feed_eo_smb(SMB_COM_READ,fid,tvb,pinfo,dataoffset,datalen,rwi->len,rwi->offset);
+ }
+
END_OF_SMB
return offset;
@@ -4296,11 +4524,6 @@ dissect_lock_and_read_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree
return offset;
}
-typedef struct _rw_info_t {
- guint64 offset;
- guint32 len;
- guint16 fid;
-} rw_info_t;
static int
@@ -4311,6 +4534,8 @@ dissect_write_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
guint8 wc;
smb_info_t *si = (smb_info_t *)pinfo->private_data;
rw_info_t *rwi = NULL;
+ guint32 datalen=0,dataoffset=0;
+ guint32 tvblen;
DISSECTOR_ASSERT(si);
@@ -4323,6 +4548,7 @@ dissect_write_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
/* write count */
cnt = tvb_get_letohs(tvb, offset);
+ datalen = cnt;
proto_tree_add_uint(tree, hf_smb_count, tvb, offset, 2, cnt);
offset += 2;
@@ -4374,6 +4600,7 @@ dissect_write_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
CHECK_BYTE_COUNT(2);
proto_tree_add_item(tree, hf_smb_data_len, tvb, offset, 2, ENC_LITTLE_ENDIAN);
COUNT_BYTES(2);
+ dataoffset=offset;
/* file data, might be DCERPC on a pipe */
if (bc != 0) {
@@ -4382,6 +4609,12 @@ dissect_write_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
bc = 0;
}
+ /* feed the export object tap listener */
+ tvblen = tvb_length_remaining(tvb, dataoffset);
+ if (have_tap_listener(smb_eo_tap) && (datalen == tvblen) && rwi) {
+ feed_eo_smb(SMB_COM_WRITE,fid,tvb,pinfo,dataoffset,datalen,rwi->len,rwi->offset);
+ }
+
END_OF_SMB
return offset;
@@ -6424,15 +6657,6 @@ dissect_read_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, i
return offset;
}
-/* Strings that describes the SMB object type */
-const value_string smb_fid_types[] = {
- {SMB_FID_TYPE_UNKNOWN,"UNKNOWN"},
- {SMB_FID_TYPE_FILE,"FILE"},
- {SMB_FID_TYPE_DIR,"DIRECTORY (Not Implemented)"},
- {SMB_FID_TYPE_PIPE,"PIPE (Not Implemented)"},
- {0, NULL}
-};
-
static int
dissect_read_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
{
@@ -6443,14 +6667,7 @@ dissect_read_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
rw_info_t *rwi = NULL;
guint16 fid = 0; /* was int fid = 0; */
- smb_eo_t *eo_info; /* eo_info variable to pass info. to
- export object and aux */
- smb_tid_info_t *tid_info = NULL;
- smb_fid_info_t *fid_info = NULL;
- smb_fid_info_t *suspect_fid_info = NULL;
guint32 tvblen;
- tvbuff_t *data_tvb;
- GSList *GSL_iterator;
DISSECTOR_ASSERT(si);
@@ -6562,51 +6779,7 @@ dissect_read_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
/* feed the export object tap listener */
tvblen = tvb_length_remaining(tvb, dataoffset);
if (have_tap_listener(smb_eo_tap) && (datalen == tvblen) && rwi) {
- /* Create a new tvb to point to the payload data */
- data_tvb = tvb_new_subset(tvb, dataoffset, datalen, tvblen);
- /* Create the eo_info to pass to the listener */
- eo_info = (smb_eo_t *)ep_alloc(sizeof(smb_eo_t));
-
- /* Try to get fid_info and tid_info */
- if (fid_info == NULL) {
- GSL_iterator = si->ct->GSL_fid_info;
- while (GSL_iterator) {
- suspect_fid_info = (smb_fid_info_t *)GSL_iterator->data;
- if (suspect_fid_info->opened_in > pinfo->fd->num) break;
- if ((suspect_fid_info->tid == si->tid) && (suspect_fid_info->fid == fid))
- fid_info = suspect_fid_info;
- GSL_iterator = g_slist_next(GSL_iterator);
- }
- }
- tid_info = (smb_tid_info_t *)se_tree_lookup32(si->ct->tid_tree, si->tid);
-
- /* Construct the eo_info structure */
- if (tid_info) eo_info->hostname = tid_info->filename;
- else eo_info->hostname = ep_strdup_printf("\\\\TREEID_%i",si->tid);
- if (fid_info) {
- eo_info->filename = NULL;
- if (fid_info->fsi)
- if (fid_info->fsi->filename)
- eo_info->filename = (gchar *) fid_info->fsi->filename;
- if (!eo_info->filename) eo_info->filename = ep_strdup_printf("\\FILEID_%i",fid);
- eo_info->fid_type = fid_info->type;
- eo_info->end_of_file = fid_info->end_of_file;
- } else {
- eo_info->fid_type = SMB_FID_TYPE_UNKNOWN;
- eo_info->filename = ep_strdup_printf("\\FILEID_%i",fid);
- eo_info->end_of_file = 0;
- }
- eo_info->fid = fid;
- eo_info->tid = si->tid;
- eo_info->uid = si->uid;
- eo_info->payload_len = datalen;
- eo_info->payload_data = tvb_get_ptr(data_tvb, 0, datalen);
- eo_info->smb_file_offset = rwi->offset;
- eo_info->smb_chunk_len = rwi->len;
- eo_info->cmd = SMB_COM_READ_ANDX;
- /* Queue data to the listener */
-
- tap_queue_packet(smb_eo_tap, pinfo, eo_info);
+ feed_eo_smb(SMB_COM_READ_ANDX,fid,tvb,pinfo,dataoffset,datalen,rwi->len,rwi->offset);
}
END_OF_SMB
@@ -6633,15 +6806,8 @@ dissect_write_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
guint16 fid = 0; /* was unsigned int fid = 0; */
guint16 mode = 0;
rw_info_t *rwi = NULL;
- /* eo_info variables to pass info. to export object and
- other aux */
- smb_eo_t *eo_info;
- smb_tid_info_t *tid_info = NULL;
- smb_fid_info_t *fid_info = NULL;
- smb_fid_info_t *suspect_fid_info = NULL;
- guint32 tvblen;
- tvbuff_t *data_tvb;
- GSList *GSL_iterator;
+
+ guint32 tvblen;
DISSECTOR_ASSERT(si);
@@ -6791,57 +6957,7 @@ dissect_write_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
/* feed the export object tap listener */
tvblen = tvb_length_remaining(tvb, dataoffset);
if (have_tap_listener(smb_eo_tap) && (datalen == tvblen) && rwi) {
- /* Create a new tvb to point to the payload data */
- data_tvb = tvb_new_subset(tvb, dataoffset, datalen, tvblen);
- /* Create the eo_info to pass to the listener */
- eo_info = (smb_eo_t *)ep_alloc(sizeof(smb_eo_t));
-
- /* Try to get fid_info and tid_info */
- if (fid_info == NULL) {
- /* We'll use a GSL instead */
- /* (was fid_info = se_tree_lookup32(si->ct->fid_tree, fid);) */
- GSL_iterator = si->ct->GSL_fid_info;
- while (GSL_iterator) {
- suspect_fid_info = (smb_fid_info_t *)GSL_iterator->data;
- if (suspect_fid_info->opened_in > pinfo->fd->num)
- break;
- if ((suspect_fid_info->tid == si->tid) && (suspect_fid_info->fid == fid))
- fid_info = suspect_fid_info;
- GSL_iterator = g_slist_next(GSL_iterator);
- }
- }
- tid_info = (smb_tid_info_t *)se_tree_lookup32(si->ct->tid_tree, si->tid);
-
- /* Construct the eo_info structure */
- if (tid_info) eo_info->hostname = tid_info->filename;
- else eo_info->hostname = ep_strdup_printf("\\\\TREEID_%i",si->tid);
- if (fid_info) {
- eo_info->filename = NULL;
- if (fid_info->fsi) {
- if (fid_info->fsi->filename) {
- eo_info->filename = (gchar *) fid_info->fsi->filename;
- }
- }
- if (!eo_info->filename) eo_info->filename = ep_strdup_printf("\\FILEID_%i",fid);
- eo_info->fid_type = fid_info->type;
- eo_info->end_of_file = fid_info->end_of_file;
- } else {
- eo_info->fid_type = SMB_FID_TYPE_UNKNOWN;
- eo_info->filename = ep_strdup_printf("\\FILEID_%i",fid);
- eo_info->end_of_file = 0;
- }
- eo_info->fid = fid;
- eo_info->tid = si->tid;
- eo_info->uid = si->uid;
- eo_info->payload_len = datalen;
- eo_info->payload_data = tvb_get_ptr(data_tvb, 0, datalen);
- eo_info->smb_file_offset = rwi->offset;
- eo_info->smb_chunk_len = rwi->len;
- eo_info->cmd = SMB_COM_WRITE_ANDX;
-
- /* Queue data to the listener */
-
- tap_queue_packet(smb_eo_tap, pinfo, eo_info);
+ feed_eo_smb(SMB_COM_WRITE_ANDX,fid,tvb,pinfo,dataoffset,datalen,rwi->len,rwi->offset);
}
END_OF_SMB
@@ -20921,6 +21037,12 @@ proto_register_smb(void)
"Whether the dissector should display SIDs and RIDs in hexadecimal rather than decimal",
&sid_display_hex);
+ /* Will Export Object take name as fid ? */
+ prefs_register_bool_preference(smb_module, "eosmb_take_name_as_fid",
+ "Use the full file name as File ID when exporting an SMB object",
+ "Whether the export object functionality will take the full path file name as file identifier",
+ &eosmb_take_name_as_fid);
+
register_init_routine(smb_trans_reassembly_init);
smb_tap = register_tap("smb");
diff --git a/epan/dissectors/packet-smb.h b/epan/dissectors/packet-smb.h
index 074526f6b0..a048e92a06 100644
--- a/epan/dissectors/packet-smb.h
+++ b/epan/dissectors/packet-smb.h
@@ -28,7 +28,6 @@
#include "ws_symbol_export.h"
-
WS_DLL_PUBLIC gboolean sid_name_snooping;
/* SMB command codes, from the SNIA CIFS spec. With MSVC and a
@@ -38,7 +37,6 @@ WS_DLL_PUBLIC value_string_ext smb_cmd_vals_ext;
WS_DLL_PUBLIC value_string_ext trans2_cmd_vals_ext;
WS_DLL_PUBLIC value_string_ext nt_cmd_vals_ext;
-
#define SMB_COM_CREATE_DIRECTORY 0x00
#define SMB_COM_DELETE_DIRECTORY 0x01
#define SMB_COM_OPEN 0x02
@@ -179,25 +177,24 @@ WS_DLL_PUBLIC value_string_ext nt_cmd_vals_ext;
#define SMBE_sharebufexc 36 /* A sharing buffer has been exceeded */
#define SMBE_diskfull 39
-/* Used for SMB Export Object feature */
+/* used for SMB export object functionality */
typedef struct _smb_eo_t {
- guint8 cmd;
- int tid,uid,fid;
- guint32 pkt_num;
- gchar *hostname;
- gchar *filename;
- int fid_type;
- gint64 end_of_file;
- gchar *content_type;
- guint32 payload_len;
- const guint8 *payload_data;
- guint64 smb_file_offset;
- guint32 smb_chunk_len;
+ guint smbversion;
+ guint16 cmd;
+ int tid,uid;
+ guint fid;
+ guint32 pkt_num;
+ gchar *hostname;
+ gchar *filename;
+ int fid_type;
+ gint64 end_of_file;
+ gchar *content_type;
+ guint32 payload_len;
+ const guint8 *payload_data;
+ guint64 smb_file_offset;
+ guint32 smb_chunk_len;
} smb_eo_t;
-/* Strings that describes the SMB object type */
-WS_DLL_PUBLIC const value_string smb_fid_types[];
-
/* the information we need to keep around for NT transatcion commands */
typedef struct {
int subcmd;
@@ -437,4 +434,7 @@ extern int dissect_sfi_SMB_FILE_PIPE_INFO(tvbuff_t *tvb, packet_info *pinfo _U_,
extern int dissect_get_dfs_request_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint16 *bcp);
extern int dissect_get_dfs_referral_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint16 *bcp);
+/* Returns an IP (v4 or v6) of the server in a SMB/SMB2 conversation */
+extern const gchar *tree_ip_str(packet_info *pinfo, guint16 cmd);
+
#endif
diff --git a/epan/dissectors/packet-smb2.c b/epan/dissectors/packet-smb2.c
index 48e55eed07..2132c61b9d 100644
--- a/epan/dissectors/packet-smb2.c
+++ b/epan/dissectors/packet-smb2.c
@@ -46,6 +46,7 @@
#include "packet-smb.h"
#include "packet-dcerpc-nt.h"
#include <string.h>
+#include <epan/prefs.h>
#include <glib.h>
/* Use libgcrypt for cipher libraries. */
@@ -402,6 +403,7 @@ static gint ett_smb2_transform_enc_alg = -1;
static gint ett_smb2_buffercode = -1;
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;
@@ -517,6 +519,9 @@ static const value_string smb2_find_info_levels[] = {
{ 0, NULL }
};
+/* 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 SEQNUM field.
@@ -644,6 +649,149 @@ static void smb2_key_derivation(const guint8 *KI _U_, guint32 KI_len _U_,
#endif
}
+/* for export-object-smb2 */
+static gchar *policy_hnd_to_file_id(const e_ctx_hnd *hnd) {
+gchar *file_id;
+ file_id = ep_strdup_printf(
+ "%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(tvb, dataoffset, length, length);
+ /* Create the eo_info to pass to the listener */
+ eo_info = ep_alloc(sizeof(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->fd->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 = ep_strdup_printf("\\%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 = ep_strdup(auxstring);
+ } else {
+ eo_info->filename = ep_strdup_printf("\\%s",auxstring);
+ }
+ }
+ } else {
+ auxstring=ep_strdup_printf("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 = ep_strdup(si->tree->name);
+ } else {
+ eo_info->hostname = ep_strdup_printf("\\\\%s\\TREEID_%i",tree_ip_str(pinfo,si->opcode),si->tree->tid);
+ }
+ } else {
+ eo_info->tid=0;
+ eo_info->hostname = ep_strdup_printf("\\\\%s\\TREEID_UNKNOWN",tree_ip_str(pinfo,si->opcode));
+ }
+
+ /* packet number */
+ eo_info->pkt_num = pinfo->fd->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 (length<si->saved->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);
@@ -1198,9 +1346,11 @@ dissect_smb2_fid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset
static dcerpc_call_value call_data;
void *old_private_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;
di.conformant_run = 0;
/* we need di->call_data->flags.NDR64 == 0 */
@@ -1219,6 +1369,21 @@ dissect_smb2_fid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset
}
dcerpc_store_polhnd_name(&policy_hnd, pinfo,
fid_name);
+
+ /* If needed, create the file entry and save the policy hnd */
+ if (si->saved) { si->saved->policy_hnd = policy_hnd; }
+
+ if (si->conv) {
+ eo_file_info = g_hash_table_lookup(si->conv->files,&policy_hnd);
+ if (!eo_file_info) {
+ eo_file_info = se_alloc(sizeof(smb2_eo_file_info_t));
+ policy_hnd_hashtablekey = se_alloc(sizeof(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:
@@ -1234,8 +1399,8 @@ dissect_smb2_fid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset
pinfo->private_data = old_private_data;
- /* put the filename in col_info */
if (dcerpc_fetch_polhnd_data(&policy_hnd, &fid_name, NULL, &open_frame, &close_frame, pinfo->fd->num)) {
+ /* put the filename in col_info */
if (fid_name) {
if (hnd_item) {
proto_item_append_text(hnd_item, " %s", fid_name);
@@ -1244,6 +1409,25 @@ dissect_smb2_fid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset
col_append_fstr(pinfo->cinfo, COL_INFO, " %s", fid_name);
}
}
+
+ /* 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 = 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 */
+ //assert(1==0);
+ eo_file_info = se_alloc(sizeof(smb2_eo_file_info_t));
+ policy_hnd_hashtablekey = se_alloc(sizeof(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;
@@ -3844,6 +4028,8 @@ dissect_file_data_dcerpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_
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;
guint32 length;
guint64 off;
static const int *f_fields[] = {
@@ -3855,6 +4041,7 @@ dissect_smb2_write_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
/* 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;
@@ -3865,6 +4052,7 @@ dissect_smb2_write_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
/* 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;
@@ -3903,8 +4091,17 @@ dissect_smb2_write_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
/* just ordinary data */
proto_tree_add_item(tree, hf_smb2_write_data, tvb, offset, length, ENC_NA);
+
+ data_tvb_len=(guint32)tvb_length_remaining(tvb, offset);
+
offset += MIN(length,(guint32)tvb_length_remaining(tvb, offset));
+ 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;
}
@@ -4675,6 +4872,12 @@ dissect_smb2_read_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, i
/* there is a buffer here but it is never used (yet) */
+ /* Store len and offset */
+ if (si->saved) {
+ si->saved->file_offset=off;
+ si->saved->bytes_moved=len;
+ }
+
return offset;
}
@@ -4682,8 +4885,9 @@ dissect_smb2_read_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, i
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;
-
switch (si->status) {
case 0x00000000: break;
default: return dissect_smb2_error_response(tvb, pinfo, tree, offset, si);
@@ -4693,6 +4897,7 @@ dissect_smb2_read_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
offset = dissect_smb2_buffercode(tree, tvb, offset, NULL);
/* 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;
@@ -4719,7 +4924,16 @@ dissect_smb2_read_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
/* data */
proto_tree_add_item(tree, hf_smb2_read_data, tvb, offset, length, ENC_NA);
- offset += MIN(length,(guint32)tvb_length_remaining(tvb, offset));
+
+ data_tvb_len=(guint32)tvb_length_remaining(tvb, offset);
+
+ offset += MIN(length,data_tvb_len);
+
+ 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;
}
@@ -5388,6 +5602,8 @@ dissect_smb2_create_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
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,
@@ -5431,10 +5647,15 @@ dissect_smb2_create_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
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 */
@@ -5443,6 +5664,15 @@ dissect_smb2_create_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
/* 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);
@@ -6557,9 +6787,14 @@ dissect_smb2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolea
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 = ep_alloc(sizeof(smb2_transform_info_t));
si = ep_alloc(sizeof(smb2_info_t));
+ si->eo_file_info = NULL;
si->conv = NULL;
si->saved = NULL;
si->tree = NULL;
@@ -6587,6 +6822,7 @@ dissect_smb2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolea
smb2_saved_info_equal_unmatched);
si->conv->sesids = g_hash_table_new(smb2_sesid_info_hash,
smb2_sesid_info_equal);
+ si->conv->files = g_hash_table_new(smb2_eo_files_hash,smb2_eo_files_equal);
conversation_add_proto_data(conversation, proto_smb2, si->conv);
}
@@ -6762,6 +6998,24 @@ dissect_smb2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolea
}
if (ssi) {
+ if (dcerpc_fetch_polhnd_data(&ssi->policy_hnd, &fid_name, NULL, &open_frame, &close_frame, pinfo->fd->num)) {
+ /* If needed, create the file entry and save the policy hnd */
+ if (!si->eo_file_info) {
+ if (si->conv) {
+ eo_file_info = 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 = se_alloc(sizeof(smb2_eo_file_info_t));
+ policy_hnd_hashtablekey = se_alloc(sizeof(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;
@@ -6855,6 +7109,7 @@ dissect_smb2_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, vo
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,
@@ -7995,8 +8250,16 @@ proto_register_smb2(void)
proto_register_subtree_array(ett, array_length(ett));
proto_register_field_array(proto_smb2, hf, array_length(hf));
+ 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);
+
register_heur_dissector_list("smb2_heur_subdissectors", &smb2_heur_subdissector_list);
smb2_tap = register_tap("smb2");
+ smb2_eo_tap = register_tap("smb_eo"); /* SMB Export Object tap */
+
}
void
diff --git a/epan/dissectors/packet-smb2.h b/epan/dissectors/packet-smb2.h
index 61c9e440fb..919e99b407 100644
--- a/epan/dissectors/packet-smb2.h
+++ b/epan/dissectors/packet-smb2.h
@@ -25,6 +25,9 @@
#ifndef __PACKET_SMB2_H__
#define __PACKET_SMB2_H__
+#include "packet-dcerpc.h"
+#include "packet-smb.h"
+
/* SMB2 command codes. With MSVC and a
* libwireshark.dll, we need a special declaration.
*/
@@ -41,6 +44,13 @@ WS_DLL_PUBLIC value_string_ext smb2_cmd_vals_ext;
* private data is set to NULL when the structure is created. It is used
* for communications between the Request and the Response packets.
*/
+
+/* extra info needed by export object smb */
+typedef struct _smb2_eo_file_info_t {
+ guint32 attr_mask;
+ gint64 end_of_file;
+} smb2_eo_file_info_t;
+
typedef enum {
SMB2_EI_NONE, /* Unassigned / NULL */
SMB2_EI_TREENAME, /* tid tracking char * */
@@ -53,6 +63,10 @@ typedef struct _smb2_saved_info_t {
guint64 seqnum;
guint32 frame_req, frame_res;
nstime_t req_time;
+ e_ctx_hnd policy_hnd; /* for eo_smb tracking */
+ smb_eo_t *eo_info_t; /* for storing eo_smb infos */
+ guint64 file_offset; /* needed file_offset for eo_smb */
+ guint32 bytes_moved; /* needed for eo_smb */
void *extra_info;
smb2_extra_info_t extra_info_type;
} smb2_saved_info_t;
@@ -84,8 +98,11 @@ typedef struct _smb2_conv_info_t {
GHashTable *unmatched;
GHashTable *matched;
GHashTable *sesids;
+ /* table to store some infos for smb export object */
+ GHashTable *files;
} smb2_conv_info_t;
+
/* This structure contains information from the SMB2 header
* as well as pointers to the conversation and the transaction specific
* structures.
@@ -96,6 +113,52 @@ typedef struct _smb2_conv_info_t {
#define SMB2_FLAGS_SIGNATURE 0x00000008
#define SMB2_FLAGS_DFS_OP 0x10000000
#define SMB2_FLAGS_REPLAY_OPERATION 0x20000000
+
+/* SMB2 FLAG MASKS */
+#define SMB2_FLAGS_ATTR_ENCRYPTED 0x00004000
+#define SMB2_FLAGS_ATTR_INDEXED 0x00002000
+#define SMB2_FLAGS_ATTR_OFFLINE 0x00001000
+#define SMB2_FLAGS_ATTR_COMPRESSED 0x00000800
+#define SMB2_FLAGS_ATTR_REPARSEPOINT 0x00000400
+#define SMB2_FLAGS_ATTR_SPARSE 0x00000200
+#define SMB2_FLAGS_ATTR_TEMPORARY 0x00000100
+#define SMB2_FLAGS_ATTR_NORMAL 0x00000080
+#define SMB2_FLAGS_ATTR_DEVICE 0x00000040
+#define SMB2_FLAGS_ATTR_ARCHIVE 0x00000020
+#define SMB2_FLAGS_ATTR_DIRECTORY 0x00000010
+#define SMB2_FLAGS_ATTR_VOLUMEID 0x00000008
+#define SMB2_FLAGS_ATTR_SYSTEM 0x00000004
+#define SMB2_FLAGS_ATTR_HIDDEN 0x00000002
+#define SMB2_FLAGS_ATTR_READONLY 0x00000001
+
+/* SMB2 FILE TYPES ASIGNED TO EXPORT OBJECTS */
+#define SMB2_FID_TYPE_UNKNOWN 0
+#define SMB2_FID_TYPE_FILE 1
+#define SMB2_FID_TYPE_DIR 2
+#define SMB2_FID_TYPE_PIPE 3
+#define SMB2_FID_TYPE_OTHER 4
+
+/* SMB2 COMMAND CODES */
+#define SMB2_COM_NEGOTIATE_PROTOCOL 0x00
+#define SMB2_COM_SESSION_SETUP 0x01
+#define SMB2_COM_SESSION_LOGOFF 0x02
+#define SMB2_COM_TREE_CONNECT 0x03
+#define SMB2_COM_TREE_DISCONNECT 0x04
+#define SMB2_COM_CREATE 0x05
+#define SMB2_COM_CLOSE 0x06
+#define SMB2_COM_FLUSH 0x07
+#define SMB2_COM_READ 0x08
+#define SMB2_COM_WRITE 0x09
+#define SMB2_COM_LOCK 0x0A
+#define SMB2_COM_IOCTL 0x0B
+#define SMB2_COM_CANCEL 0x0C
+#define SMB2_COM_KEEPALIVE 0x0D
+#define SMB2_COM_FIND 0x0E
+#define SMB2_COM_NOTIFY 0x0F
+#define SMB2_COM_GETINFO 0x10
+#define SMB2_COM_SETINFO 0x11
+#define SMB2_COM_BREAK 0x12
+
typedef struct _smb2_info_t {
guint16 opcode;
guint32 ioctl_function;
@@ -104,6 +167,7 @@ typedef struct _smb2_info_t {
guint64 sesid;
gint64 seqnum;
guint32 flags;
+ smb2_eo_file_info_t *eo_file_info; /* eo_smb extra info */
smb2_conv_info_t *conv;
smb2_saved_info_t *saved;
smb2_tid_info_t *tree;
diff --git a/ui/export_object.h b/ui/export_object.h
index ba73361224..c42d8524ff 100644
--- a/ui/export_object.h
+++ b/ui/export_object.h
@@ -59,9 +59,9 @@ const char *ct2ext(const char *content_type);
gboolean eo_dicom_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_,
const void *data);
gboolean eo_http_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_,
- const void *data);
+ const void *data);
gboolean eo_smb_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_,
- const void *data);
+ const void *data);
void eo_smb_cleanup(void);
diff --git a/ui/export_object_smb.c b/ui/export_object_smb.c
index 9153b70787..2e15795a47 100644
--- a/ui/export_object_smb.c
+++ b/ui/export_object_smb.c
@@ -34,6 +34,7 @@
#include <epan/packet.h>
#include <epan/dissectors/packet-smb.h>
+#include <epan/dissectors/packet-smb2.h>
#include <epan/tap.h>
#include "export_object.h"
@@ -45,16 +46,33 @@
#define SMB_EO_CONTAINS_READS 0x01
#define SMB_EO_CONTAINS_WRITES 0x02
#define SMB_EO_CONTAINS_READSANDWRITES 0x03
-#define LEGAL_FILENAME_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVXYZ1234567890_."
+#define LEGAL_FILENAME_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_.- /\\{}[]=()&%$!,;.+&%$~#@"
static const value_string smb_eo_contains_string[] = {
- {SMB_EO_CONTAINS_NOTHING, "" },
- {SMB_EO_CONTAINS_READS, "R" },
- {SMB_EO_CONTAINS_WRITES, "W" },
- {SMB_EO_CONTAINS_READSANDWRITES, "R&W"},
- {0, NULL}
- };
-
+ {SMB_EO_CONTAINS_NOTHING, "" },
+ {SMB_EO_CONTAINS_READS, "R" },
+ {SMB_EO_CONTAINS_WRITES, "W" },
+ {SMB_EO_CONTAINS_READSANDWRITES, "R&W"},
+ {0, NULL}
+};
+
+/* Strings that describes the SMB object type */
+static const value_string smb_fid_types[] = {
+ {SMB_FID_TYPE_UNKNOWN,"UNKNOWN"},
+ {SMB_FID_TYPE_FILE,"FILE"},
+ {SMB_FID_TYPE_DIR,"DIRECTORY (Not Implemented)"},
+ {SMB_FID_TYPE_PIPE,"PIPE (Not Implemented)"},
+ {0, NULL}
+};
+
+static const value_string smb2_fid_types[] = {
+ {SMB2_FID_TYPE_UNKNOWN,"UNKNOWN"},
+ {SMB2_FID_TYPE_FILE,"FILE"},
+ {SMB2_FID_TYPE_DIR,"DIRECTORY (Not Implemented)"},
+ {SMB2_FID_TYPE_PIPE,"PIPE (Not Implemented)"},
+ {SMB2_FID_TYPE_OTHER,"OTHER (Not Implemented)"},
+ {0, NULL}
+};
/* This struct contains the relationship between
the row# in the export_object window and the file being captured;
@@ -96,318 +114,350 @@ typedef struct _free_chunk {
static void
insert_chunk(active_file *file, export_object_entry_t *entry, const smb_eo_t *eo_info)
{
- guint nfreechunks = g_slist_length(file->free_chunk_list);
- guint i;
- free_chunk *current_free_chunk;
- free_chunk *new_free_chunk;
- guint64 chunk_offset = eo_info->smb_file_offset;
- guint64 chunk_length = eo_info->payload_len;
- guint64 chunk_end_offset = chunk_offset + chunk_length-1;
- /* Size of file in memory */
- guint64 calculated_size = chunk_offset + chunk_length;
- gpointer dest_memory_addr;
-
- /* Let's recalculate the file length and data gathered */
- if ((file->data_gathered == 0) && (nfreechunks == 0)) {
- /* If this is the first entry for this file, we first
- create an initial free chunk */
- new_free_chunk = g_malloc(sizeof(free_chunk));
- new_free_chunk->start_offset = 0;
- new_free_chunk->end_offset = MAX(file->file_length, chunk_end_offset+1) - 1;
- file->free_chunk_list = NULL;
- file->free_chunk_list = g_slist_append(file->free_chunk_list, new_free_chunk);
- nfreechunks += 1;
- } else {
- if (chunk_end_offset > file->file_length-1) {
- new_free_chunk = g_malloc(sizeof(free_chunk));
- new_free_chunk->start_offset = file->file_length;
- new_free_chunk->end_offset = chunk_end_offset;
- file->free_chunk_list = g_slist_append(file->free_chunk_list, new_free_chunk);
- nfreechunks += 1;
- }
- }
- file->file_length = MAX(file->file_length, chunk_end_offset+1);
-
- for (i=0; i<nfreechunks; i++) {
- current_free_chunk = g_slist_nth_data(file->free_chunk_list, i);
- if (chunk_offset <= current_free_chunk->start_offset) {
- if (chunk_end_offset >= current_free_chunk->start_offset) {
- if (chunk_end_offset < current_free_chunk->end_offset) {
- file->data_gathered +=
- (chunk_end_offset-current_free_chunk->start_offset + 1);
- current_free_chunk->start_offset = chunk_end_offset + 1;
- } else {
- file->data_gathered +=
- (current_free_chunk->end_offset-current_free_chunk->start_offset + 1);
- file->free_chunk_list =
- g_slist_remove(file->free_chunk_list, current_free_chunk);
- nfreechunks -= 1;
- if (nfreechunks == 0) { /* The free chunk list is empty */
- g_slist_free(file->free_chunk_list);
- file->free_chunk_list = NULL;
- break;
- }
- }
- } else {
- break;
- }
- } else {
- if (chunk_offset <= current_free_chunk->end_offset) {
- if (chunk_end_offset < current_free_chunk->end_offset) {
- new_free_chunk = g_malloc(sizeof(free_chunk));
- new_free_chunk->start_offset = chunk_end_offset + 1;
- new_free_chunk->end_offset = current_free_chunk->end_offset;
- current_free_chunk->end_offset = chunk_offset-1;
- file->free_chunk_list =
- g_slist_insert(file->free_chunk_list, new_free_chunk, i + 1);
- file->data_gathered += chunk_length;
- } else {
- file->data_gathered += current_free_chunk->end_offset-chunk_offset + 1;
- current_free_chunk->end_offset = chunk_offset-1;
- }
- }
- }
- }
-
- /* Now, let's insert the data chunk into memory
- ...first, we shall be able to allocate the memory */
- if (!entry->payload_data) {
- /* This is a New file */
- if (calculated_size > G_MAXSIZE) {
- /*
- * The argument to g_try_malloc() is
- * a gsize, the maximum value of which is
- * G_MAXSIZE. If the calculated size is
- * bigger than that, we just say the attempt
- * to allocate memory failed.
- */
- entry->payload_data = NULL;
- } else {
- entry->payload_data = g_try_malloc((gsize)calculated_size);
- entry->payload_len = calculated_size;
- }
- if (!entry->payload_data) {
- /* Memory error */
- file->is_out_of_memory = TRUE;
- }
- } else {
- /* This is an existing file in memory */
- if (calculated_size > (guint64) entry->payload_len &&
- !file->is_out_of_memory) {
- /* We need more memory */
- if (calculated_size > G_MAXSIZE) {
- /*
- * As for g_try_malloc(), so for
- * g_try_realloc().
- */
- dest_memory_addr = NULL;
- } else {
- dest_memory_addr = g_try_realloc(
- entry->payload_data,
- (gsize)calculated_size);
- }
- if (!dest_memory_addr) {
- /* Memory error */
- file->is_out_of_memory = TRUE;
- /* We don't have memory for this file.
- Free the current file content from memory */
- g_free(entry->payload_data);
- entry->payload_data = NULL;
- entry->payload_len = 0;
- } else {
- entry->payload_data = dest_memory_addr;
- entry->payload_len = calculated_size;
- }
- }
- }
- /* ...then, put the chunk of the file in the right place */
- if (!file->is_out_of_memory) {
- dest_memory_addr = entry->payload_data + chunk_offset;
- g_memmove(dest_memory_addr, eo_info->payload_data, eo_info->payload_len);
- }
+gint nfreechunks = g_slist_length(file->free_chunk_list);
+gint i;
+free_chunk *current_free_chunk;
+free_chunk *new_free_chunk;
+guint64 chunk_offset = eo_info->smb_file_offset;
+guint64 chunk_length = eo_info->payload_len;
+guint64 chunk_end_offset = chunk_offset + chunk_length-1;
+/* Size of file in memory */
+guint64 calculated_size = chunk_offset + chunk_length;
+gpointer dest_memory_addr;
+
+ /* Let's recalculate the file length and data gathered */
+ if ((file->data_gathered == 0) && (nfreechunks == 0)) {
+ /* If this is the first entry for this file, we first
+ create an initial free chunk */
+ new_free_chunk = g_malloc(sizeof(free_chunk));
+ new_free_chunk->start_offset = 0;
+ new_free_chunk->end_offset = MAX(file->file_length, chunk_end_offset+1) - 1;
+ file->free_chunk_list = NULL;
+ file->free_chunk_list = g_slist_append(file->free_chunk_list, new_free_chunk);
+ nfreechunks += 1;
+ } else {
+ if (chunk_end_offset > file->file_length-1) {
+ new_free_chunk = g_malloc(sizeof(free_chunk));
+ new_free_chunk->start_offset = file->file_length;
+ new_free_chunk->end_offset = chunk_end_offset;
+ file->free_chunk_list = g_slist_append(file->free_chunk_list, new_free_chunk);
+ nfreechunks += 1;
+ }
+ }
+ file->file_length = MAX(file->file_length, chunk_end_offset+1);
+
+ /* Recalculate each free chunk according with the incoming data chunk */
+ for (i=0; i<nfreechunks; i++) {
+ current_free_chunk = g_slist_nth_data(file->free_chunk_list, i);
+ /* 1. data chunk before the free chunk? */
+ /* -> free chunk is not altered and no new data gathered */
+ if (chunk_end_offset<current_free_chunk->start_offset) {
+ continue;
+ }
+ /* 2. data chunk overlaps the first part of free_chunk */
+ /* -> free chunk shrinks from the beggining */
+ if (chunk_offset<=current_free_chunk->start_offset && chunk_end_offset>=current_free_chunk->start_offset && chunk_end_offset<current_free_chunk->end_offset) {
+ file->data_gathered += chunk_end_offset-current_free_chunk->start_offset+1;
+ current_free_chunk->start_offset=chunk_end_offset+1;
+ continue;
+ }
+ /* 3. data chunk overlaps completely the free chunk */
+ /* -> free chunk is removed */
+ if (chunk_offset<=current_free_chunk->start_offset && chunk_end_offset>=current_free_chunk->end_offset) {
+ file->data_gathered += current_free_chunk->end_offset-current_free_chunk->start_offset+1;
+ file->free_chunk_list = g_slist_remove(file->free_chunk_list, current_free_chunk);
+ nfreechunks -= 1;
+ if (nfreechunks == 0) { /* The free chunk list is empty */
+ g_slist_free(file->free_chunk_list);
+ file->free_chunk_list = NULL;
+ break;
+ }
+ i--;
+ continue;
+ }
+ /* 4. data chunk is inside the free chunk */
+ /* -> free chunk is splitted into two */
+ if (chunk_offset>current_free_chunk->start_offset && chunk_end_offset<current_free_chunk->end_offset) {
+ new_free_chunk = g_malloc(sizeof(free_chunk));
+ new_free_chunk->start_offset = chunk_end_offset + 1;
+ new_free_chunk->end_offset = current_free_chunk->end_offset;
+ current_free_chunk->end_offset = chunk_offset-1;
+ file->free_chunk_list = g_slist_insert(file->free_chunk_list, new_free_chunk, i + 1);
+ file->data_gathered += chunk_length;
+ continue;
+ }
+ /* 5.- data chunk overlaps the end part of free chunk */
+ /* -> free chunk shrinks from the end */
+ if (chunk_offset>current_free_chunk->start_offset && chunk_offset<=current_free_chunk->end_offset && chunk_end_offset>=current_free_chunk->end_offset) {
+ file->data_gathered += current_free_chunk->end_offset-chunk_offset+1;
+ current_free_chunk->end_offset = chunk_offset-1;
+ continue;
+ }
+ /* 6.- data chunk is after the free chunk */
+ /* -> free chunk is not altered and no new data gathered */
+ if (chunk_offset>current_free_chunk->end_offset) {
+ continue;
+ }
+ }
+
+ /* Now, let's insert the data chunk into memory
+ ...first, we shall be able to allocate the memory */
+ if (!entry->payload_data) {
+ /* This is a New file */
+ if (calculated_size > G_MAXSIZE) {
+ /*
+ * The argument to g_try_malloc() is
+ * a gsize, the maximum value of which is
+ * G_MAXSIZE. If the calculated size is
+ * bigger than that, we just say the attempt
+ * to allocate memory failed.
+ */
+ entry->payload_data = NULL;
+ } else {
+ entry->payload_data = g_try_malloc((gsize)calculated_size);
+ entry->payload_len = calculated_size;
+ }
+ if (!entry->payload_data) {
+ /* Memory error */
+ file->is_out_of_memory = TRUE;
+ }
+ } else {
+ /* This is an existing file in memory */
+ if (calculated_size > (guint64) entry->payload_len &&
+ !file->is_out_of_memory) {
+ /* We need more memory */
+ if (calculated_size > G_MAXSIZE) {
+ /*
+ * As for g_try_malloc(), so for
+ * g_try_realloc().
+ */
+ dest_memory_addr = NULL;
+ } else {
+ dest_memory_addr = g_try_realloc(
+ entry->payload_data,
+ (gsize)calculated_size);
+ }
+ if (!dest_memory_addr) {
+ /* Memory error */
+ file->is_out_of_memory = TRUE;
+ /* We don't have memory for this file.
+ Free the current file content from memory */
+ g_free(entry->payload_data);
+ entry->payload_data = NULL;
+ entry->payload_len = 0;
+ } else {
+ entry->payload_data = dest_memory_addr;
+ entry->payload_len = calculated_size;
+ }
+ }
+ }
+ /* ...then, put the chunk of the file in the right place */
+ if (!file->is_out_of_memory) {
+ dest_memory_addr = entry->payload_data + chunk_offset;
+ g_memmove(dest_memory_addr, eo_info->payload_data, eo_info->payload_len);
+ }
}
/* We use this function to obtain the index in the GSL of a given file */
static int
find_incoming_file(GSList *GSL_active_files_p, active_file *incoming_file)
{
- int i, row, last;
- active_file *in_list_file;
-
- row = -1;
- last = g_slist_length(GSL_active_files_p) - 1;
-
- /* We lookup in reverse order because it is more likely that the file
- is one of the latest */
- for (i=last; i>=0; i--) {
- in_list_file = g_slist_nth_data(GSL_active_files_p, i);
- /* The best-working criteria of two identical files is that the file
- that is the same of the file that we are analyzing is the last one
- in the list that has the same tid and the same fid */
- /* note that we have excluded in_list_file->uid == incoming_file->uid
- from the comparison, because a file can be opened by different
- SMB users and it is still the same file */
- if (in_list_file->tid == incoming_file->tid &&
- in_list_file->fid == incoming_file->fid) {
- row = i;
- break;
- }
- }
-
- return row;
+ int i, row, last;
+ active_file *in_list_file;
+
+ row = -1;
+ last = g_slist_length(GSL_active_files_p) - 1;
+
+ /* We lookup in reverse order because it is more likely that the file
+ is one of the latest */
+ for (i=last; i>=0; i--) {
+ in_list_file = g_slist_nth_data(GSL_active_files_p, i);
+ /* The best-working criteria of two identical files is that the file
+ that is the same of the file that we are analyzing is the last one
+ in the list that has the same tid and the same fid */
+ /* note that we have excluded in_list_file->uid == incoming_file->uid
+ from the comparison, because a file can be opened by different
+ SMB users and it is still the same file */
+ if (in_list_file->tid == incoming_file->tid &&
+ in_list_file->fid == incoming_file->fid) {
+ row = i;
+ break;
+ }
+ }
+
+ return row;
}
/* This is the function answering to the registered tap listener call */
gboolean
eo_smb_packet(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *data)
{
- export_object_list_t *object_list = tapdata;
- const smb_eo_t *eo_info = data;
-
- export_object_entry_t *entry;
- export_object_entry_t *current_entry;
- active_file incoming_file;
- gint active_row;
- active_file *new_file;
- active_file *current_file;
- guint8 contains;
- gboolean is_supported_filetype;
- gfloat percent;
-
- gchar **aux_string_v;
-
- /* Is this an eo_smb supported file_type? (right now we only support FILE */
- is_supported_filetype = (eo_info->fid_type == SMB_FID_TYPE_FILE);
-
- /* What kind of data this packet contains? */
- switch(eo_info->cmd) {
- case SMB_COM_READ_ANDX:
- contains = SMB_EO_CONTAINS_READS;
- break;
- case SMB_COM_WRITE_ANDX:
- contains = SMB_EO_CONTAINS_WRITES;
- break;
- default:
- contains = SMB_EO_CONTAINS_NOTHING;
- break;
- }
-
- /* Is this data from an already tracked file or not? */
- incoming_file.tid = eo_info->tid;
- incoming_file.uid = eo_info->uid;
- incoming_file.fid = eo_info->fid;
- active_row = find_incoming_file(GSL_active_files, &incoming_file);
-
- if (active_row == -1) { /* This is a new-tracked file */
- /* Construct the entry in the list of active files */
- entry = g_malloc(sizeof(export_object_entry_t));
- entry->payload_data = NULL;
- entry->payload_len = 0;
- new_file = g_malloc(sizeof(active_file));
- new_file->tid = incoming_file.tid;
- new_file->uid = incoming_file.uid;
- new_file->fid = incoming_file.fid;
- new_file->file_length = eo_info->end_of_file;
- new_file->flag_contains = contains;
- new_file->free_chunk_list = NULL;
- new_file->data_gathered = 0;
- new_file->is_out_of_memory = FALSE;
- entry->pkt_num = pinfo->fd->num;
- entry->hostname = g_strdup(eo_info->hostname);
- if (g_str_has_prefix(eo_info->filename, "\\")) {
- aux_string_v = g_strsplit(eo_info->filename, "\\", -1);
- entry->filename = g_strdup(aux_string_v[g_strv_length(aux_string_v)-1]);
- g_strfreev(aux_string_v);
- } else {
- entry->filename = g_strdup(eo_info->filename);
- }
-
- /* Insert the first chunk in the chunk list of this file */
- if (is_supported_filetype) {
- insert_chunk(new_file, entry, eo_info);
- }
-
- if (new_file->is_out_of_memory) {
- entry->content_type =
- g_strdup_printf("%s (%"G_GUINT64_FORMAT"?/%"G_GUINT64_FORMAT") %s [mem!!]",
- match_strval(eo_info->fid_type, smb_fid_types),
- new_file->data_gathered,
- new_file->file_length,
- match_strval(contains, smb_eo_contains_string));
- } else {
- if (new_file->file_length > 0) {
- percent = (gfloat) (100*new_file->data_gathered/new_file->file_length);
- } else {
- percent = 0.0f;
- }
-
- entry->content_type =
- g_strdup_printf("%s (%"G_GUINT64_FORMAT"/%"G_GUINT64_FORMAT") %s [%5.2f%%]",
- match_strval(eo_info->fid_type, smb_fid_types),
- new_file->data_gathered,
- new_file->file_length,
- match_strval(contains, smb_eo_contains_string),
- percent);
- }
-
- object_list_add_entry(object_list, entry);
- GSL_active_files =
- g_slist_append(GSL_active_files, new_file);
- }
- else if (is_supported_filetype) {
- current_file = g_slist_nth_data(GSL_active_files, active_row);
- /* Recalculate the current file flags */
- current_file->flag_contains = current_file->flag_contains|contains;
- current_entry = object_list_get_entry(object_list, active_row);
-
- insert_chunk(current_file, current_entry, eo_info);
-
- /* Modify the current_entry object_type string */
- if (current_file->is_out_of_memory) {
- current_entry->content_type =
- g_strdup_printf("%s (%"G_GUINT64_FORMAT"?/%"G_GUINT64_FORMAT") %s [mem!!]",
- match_strval(eo_info->fid_type, smb_fid_types),
- current_file->data_gathered,
- current_file->file_length,
- match_strval(current_file->flag_contains, smb_eo_contains_string));
- } else {
- percent = (gfloat) (100*current_file->data_gathered/current_file->file_length);
- current_entry->content_type =
- g_strdup_printf("%s (%"G_GUINT64_FORMAT"/%"G_GUINT64_FORMAT") %s [%5.2f%%]",
- match_strval(eo_info->fid_type, smb_fid_types),
- current_file->data_gathered,
- current_file->file_length,
- match_strval(current_file->flag_contains, smb_eo_contains_string),
- percent);
- }
- }
-
- return TRUE; /* State changed - window should be redrawn */
+export_object_list_t *object_list = tapdata;
+const smb_eo_t *eo_info = data;
+
+export_object_entry_t *entry;
+export_object_entry_t *current_entry;
+active_file incoming_file;
+gint active_row;
+active_file *new_file;
+active_file *current_file;
+guint8 contains;
+gboolean is_supported_filetype;
+gfloat percent;
+
+gchar *aux_smb_fid_type_string;
+
+ if (eo_info->smbversion==1) {
+ /* Is this an eo_smb supported file_type? (right now we only support FILE) */
+ is_supported_filetype = (eo_info->fid_type == SMB_FID_TYPE_FILE);
+ aux_smb_fid_type_string=g_strdup(match_strval(eo_info->fid_type, smb_fid_types));
+
+ /* What kind of data this packet contains? */
+ switch(eo_info->cmd) {
+ case SMB_COM_READ_ANDX:
+ case SMB_COM_READ:
+ contains = SMB_EO_CONTAINS_READS;
+ break;
+ case SMB_COM_WRITE_ANDX:
+ case SMB_COM_WRITE:
+ contains = SMB_EO_CONTAINS_WRITES;
+ break;
+ default:
+ contains = SMB_EO_CONTAINS_NOTHING;
+ break;
+ }
+ } else {
+ /* Is this an eo_smb supported file_type? (right now we only support FILE) */
+ is_supported_filetype = (eo_info->fid_type == SMB2_FID_TYPE_FILE );
+ aux_smb_fid_type_string=g_strdup(match_strval(eo_info->fid_type, smb2_fid_types));
+
+ /* What kind of data this packet contains? */
+ switch(eo_info->cmd) {
+ case SMB2_COM_READ:
+ contains = SMB_EO_CONTAINS_READS;
+ break;
+ case SMB2_COM_WRITE:
+ contains = SMB_EO_CONTAINS_WRITES;
+ break;
+ default:
+ contains = SMB_EO_CONTAINS_NOTHING;
+ break;
+ }
+ }
+
+
+ /* Is this data from an already tracked file or not? */
+ incoming_file.tid = eo_info->tid;
+ incoming_file.uid = eo_info->uid;
+ incoming_file.fid = eo_info->fid;
+ active_row = find_incoming_file(GSL_active_files, &incoming_file);
+
+ if (active_row == -1) { /* This is a new-tracked file */
+ /* Construct the entry in the list of active files */
+ entry = g_malloc(sizeof(export_object_entry_t));
+ entry->payload_data = NULL;
+ entry->payload_len = 0;
+ new_file = g_malloc(sizeof(active_file));
+ new_file->tid = incoming_file.tid;
+ new_file->uid = incoming_file.uid;
+ new_file->fid = incoming_file.fid;
+ new_file->file_length = eo_info->end_of_file;
+ new_file->flag_contains = contains;
+ new_file->free_chunk_list = NULL;
+ new_file->data_gathered = 0;
+ new_file->is_out_of_memory = FALSE;
+ entry->pkt_num = pinfo->fd->num;
+
+ entry->hostname=g_filename_display_name(g_strcanon(eo_info->hostname,LEGAL_FILENAME_CHARS,'?'));
+ entry->filename=g_filename_display_name(g_strcanon(eo_info->filename,LEGAL_FILENAME_CHARS,'?'));
+
+ /* Insert the first chunk in the chunk list of this file */
+ if (is_supported_filetype) {
+ insert_chunk(new_file, entry, eo_info);
+ }
+
+ if (new_file->is_out_of_memory) {
+ entry->content_type =
+ g_strdup_printf("%s (%"G_GUINT64_FORMAT"?/%"G_GUINT64_FORMAT") %s [mem!!]",
+ aux_smb_fid_type_string,
+ new_file->data_gathered,
+ new_file->file_length,
+ match_strval(contains, smb_eo_contains_string));
+ } else {
+ if (new_file->file_length > 0) {
+ percent = (gfloat) (100*new_file->data_gathered/new_file->file_length);
+ } else {
+ percent = 0.0f;
+ }
+
+ entry->content_type =
+ g_strdup_printf("%s (%"G_GUINT64_FORMAT"/%"G_GUINT64_FORMAT") %s [%5.2f%%]",
+ aux_smb_fid_type_string,
+ new_file->data_gathered,
+ new_file->file_length,
+ match_strval(contains, smb_eo_contains_string),
+ percent);
+ }
+
+ object_list_add_entry(object_list, entry);
+ GSL_active_files = g_slist_append(GSL_active_files, new_file);
+ }
+ else if (is_supported_filetype) {
+ current_file = g_slist_nth_data(GSL_active_files, active_row);
+ /* Recalculate the current file flags */
+ current_file->flag_contains = current_file->flag_contains|contains;
+ current_entry = object_list_get_entry(object_list, active_row);
+
+ insert_chunk(current_file, current_entry, eo_info);
+
+ /* Modify the current_entry object_type string */
+ if (current_file->is_out_of_memory) {
+ current_entry->content_type =
+ g_strdup_printf("%s (%"G_GUINT64_FORMAT"?/%"G_GUINT64_FORMAT") %s [mem!!]",
+ aux_smb_fid_type_string,
+ current_file->data_gathered,
+ current_file->file_length,
+ match_strval(current_file->flag_contains, smb_eo_contains_string));
+ } else {
+ percent = (gfloat) (100*current_file->data_gathered/current_file->file_length);
+ current_entry->content_type =
+ g_strdup_printf("%s (%"G_GUINT64_FORMAT"/%"G_GUINT64_FORMAT") %s [%5.2f%%]",
+ aux_smb_fid_type_string,
+ current_file->data_gathered,
+ current_file->file_length,
+ match_strval(current_file->flag_contains, smb_eo_contains_string),
+ percent);
+ }
+ }
+
+ return TRUE; /* State changed - window should be redrawn */
}
+
+
/* This is the eo_protocoldata_reset function that is used in the export_object module
to cleanup any previous private data of the export object functionality before perform
the eo_reset function or when the window closes */
void
eo_smb_cleanup(void)
{
- int i, last;
- active_file *in_list_file;
-
- /* Free any previous data structures used in previous invocation to the
- export_object_smb function */
- last = g_slist_length(GSL_active_files);
- if (GSL_active_files) {
- for (i=last-1; i>=0; i--) {
- in_list_file = g_slist_nth_data(GSL_active_files, i);
- if (in_list_file->free_chunk_list) {
- g_slist_free(in_list_file->free_chunk_list);
- in_list_file->free_chunk_list = NULL;
- }
- g_free(in_list_file);
- }
- g_slist_free(GSL_active_files);
- GSL_active_files = NULL;
- }
+int i, last;
+active_file *in_list_file;
+
+ /* Free any previous data structures used in previous invocation to the
+ export_object_smb function */
+ last = g_slist_length(GSL_active_files);
+ if (GSL_active_files) {
+ for (i=last-1; i>=0; i--) {
+ in_list_file = g_slist_nth_data(GSL_active_files, i);
+ if (in_list_file->free_chunk_list) {
+ g_slist_free(in_list_file->free_chunk_list);
+ in_list_file->free_chunk_list = NULL;
+ }
+ g_free(in_list_file);
+ }
+ g_slist_free(GSL_active_files);
+ GSL_active_files = NULL;
+ }
}
/*
diff --git a/ui/gtk/export_object_dlg.c b/ui/gtk/export_object_dlg.c
index 6b49bbb943..27afb762b9 100644
--- a/ui/gtk/export_object_dlg.c
+++ b/ui/gtk/export_object_dlg.c
@@ -132,6 +132,26 @@ eo_win_destroy_cb(GtkWindow *win _U_, gpointer data)
if (eo_protocoldata_reset != NULL) eo_protocoldata_reset();
}
+static gchar *eo_saveable_pathname(gchar *filename) {
+gchar **splitted_pathname;
+gchar *auxstring, *saveable_pathname;
+guint nparts,i;
+
+ saveable_pathname = NULL;
+ splitted_pathname = g_strsplit_set(filename,"\\",-1);
+ nparts = g_strv_length(splitted_pathname);
+ if (nparts>0) {
+ saveable_pathname=g_strdup(splitted_pathname[0]);
+ }
+ for (i=1;i<nparts;i++) {
+ auxstring = g_strconcat(saveable_pathname,"__",splitted_pathname[i],NULL);
+ g_free(saveable_pathname);
+ saveable_pathname = auxstring;
+ }
+
+ return saveable_pathname;
+}
+
static void
eo_save_clicked_cb(GtkWidget *widget _U_, gpointer arg)
{
@@ -139,6 +159,7 @@ eo_save_clicked_cb(GtkWidget *widget _U_, gpointer arg)
export_object_list_t *object_list = arg;
export_object_entry_t *entry;
gchar *filename = NULL;
+ gchar *auxfilename = NULL;
entry = g_slist_nth_data(object_list->entries,
object_list->row_selected);
@@ -154,14 +175,18 @@ eo_save_clicked_cb(GtkWidget *widget _U_, gpointer arg)
gtk_window_set_transient_for(GTK_WINDOW(save_as_w),
GTK_WINDOW(object_list->dlg));
+ auxfilename = eo_saveable_pathname(entry->filename);
+
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(save_as_w),
- entry->filename);
+ auxfilename);
+
if(gtk_dialog_run(GTK_DIALOG(save_as_w)) == GTK_RESPONSE_ACCEPT) {
filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(save_as_w));
eo_save_entry(filename, entry, TRUE);
}
+ g_free(auxfilename);
g_free(filename);
window_destroy(save_as_w);
}
@@ -178,6 +203,7 @@ eo_save_all_clicked_cb(GtkWidget *widget _U_, gpointer arg)
gboolean all_saved = TRUE;
gchar *save_in_path;
GString *safe_filename;
+ gchar *auxfilename = NULL;
int count = 0;
save_in_w = file_selection_new("Wireshark: Save All Objects In ...",
@@ -194,10 +220,12 @@ eo_save_all_clicked_cb(GtkWidget *widget _U_, gpointer arg)
if ((strlen(save_in_path) < MAXFILELEN)) {
do {
g_free(save_as_fullpath);
- if (entry->filename)
- safe_filename = eo_massage_str(entry->filename,
+ if (entry->filename) {
+ auxfilename = eo_saveable_pathname(entry->filename);
+ safe_filename = eo_massage_str(auxfilename,
MAXFILELEN - strlen(save_in_path), count);
- else {
+ g_free(auxfilename);
+ } else {
char generic_name[256];
const char *ext;
ext = ct2ext(entry->content_type);
diff --git a/ui/gtk/main_menubar.c b/ui/gtk/main_menubar.c
index 4f53ba667f..37c4c7b3e5 100644
--- a/ui/gtk/main_menubar.c
+++ b/ui/gtk/main_menubar.c
@@ -1448,7 +1448,7 @@ static const GtkActionEntry main_menu_bar_entries[] = {
NULL, NULL, G_CALLBACK(export_pdml_cmd_cb) },
{ "/File/ExportObjects/HTTP", NULL, "_HTTP", NULL, NULL, G_CALLBACK(eo_http_cb) },
{ "/File/ExportObjects/DICOM", NULL, "_DICOM", NULL, NULL, G_CALLBACK(eo_dicom_cb) },
- { "/File/ExportObjects/SMB", NULL, "_SMB", NULL, NULL, G_CALLBACK(eo_smb_cb) },
+ { "/File/ExportObjects/SMB", NULL, "_SMB/SMB2", NULL, NULL, G_CALLBACK(eo_smb_cb) },
{ "/Edit/Copy", NULL, "Copy", NULL, NULL, NULL },