diff options
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dissectors/packet-smb.c | 232 | ||||
-rw-r--r-- | epan/dissectors/packet-smb.h | 33 |
2 files changed, 255 insertions, 10 deletions
diff --git a/epan/dissectors/packet-smb.c b/epan/dissectors/packet-smb.c index ee71c3156f..a16f965ae5 100644 --- a/epan/dissectors/packet-smb.c +++ b/epan/dissectors/packet-smb.c @@ -30,6 +30,8 @@ # include "config.h" #endif +#include <inttypes.h> + #include <time.h> #include <string.h> #include <glib.h> @@ -765,6 +767,7 @@ static gint ett_smb_posic_ace = -1; static gint ett_smb_posix_ace_perms = -1; static int smb_tap = -1; +static int smb_eo_tap = -1; static dissector_handle_t gssapi_handle; static dissector_handle_t ntlmssp_handle; @@ -884,6 +887,13 @@ static int dissect_smb_command(tvbuff_t *tvb, packet_info *pinfo, int offset, pr gboolean sid_name_snooping = FALSE; +/* Compare funtion to maintain the GSL_fid_info ordered + Order criteria: packet where the fid was opened */ +gint fid_cmp(smb_fid_info_t *fida, smb_fid_info_t *fidb) +{ + return (fida->opened_in - fidb->opened_in); +} + /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX These are needed by the reassembly of SMB Transaction payload and DCERPC over SMB XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ @@ -3444,6 +3454,10 @@ dissect_smb_fid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_item *it; proto_tree *tr; smb_fid_info_t *fid_info=NULL; + smb_fid_info_t *suspect_fid_info=NULL; + /* We need this to use an array-accessed tree */ + GSList *GSL_iterator; + int found=0; DISSECTOR_ASSERT(si); @@ -3460,17 +3474,38 @@ dissect_smb_fid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, fid_info->opened_in=pinfo->fd->num; fid_info->closed_in=0; fid_info->type=SMB_FID_TYPE_UNKNOWN; + fid_info->fid=fid; + fid_info->tid=si->tid; if(si->sip && (si->sip->extra_info_type==SMB_EI_FILEDATA)){ fid_info->fsi=si->sip->extra_info; } else { fid_info->fsi=NULL; } - - se_tree_insert32(si->ct->fid_tree, fid, fid_info); + /* We don't use the fid_tree anymore to access and + maintain the fid information of analized files. + (was se_tree_insert32(si->ct->fid_tree, fid, fid_info);) + We'll use a single list instead to keep track of the + files (fid) opened. + Note that the insert_sorted function allows to insert duplicates + but being inside this if section should prevent it */ + si->ct->GSL_fid_info=g_slist_insert_sorted( + si->ct->GSL_fid_info, + fid_info, + (GCompareFunc)fid_cmp); } if(!fid_info){ - fid_info=se_tree_lookup32(si->ct->fid_tree, fid); + /* we use the single linked list to access this fid_info + (was fid_info=se_tree_lookup32(si->ct->fid_tree, fid);) */ + 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); + found+=1; + } } if(!fid_info){ return NULL; @@ -6014,6 +6049,18 @@ dissect_open_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, i fn); COUNT_BYTES(fn_len); + /* Copied this portion of code from create_andx_request + to guarantee that fsi and si->sip are always correctly filled out */ + if((!pinfo->fd->flags.visited) && si->sip && fn){ + smb_fid_saved_info_t *fsi; + + fsi=se_alloc(sizeof(smb_fid_saved_info_t)); + fsi->filename=se_strdup(fn); + + 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))); @@ -6092,6 +6139,10 @@ dissect_open_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint8 wc, cmd=0xff; guint16 andxoffset=0, bc; guint16 fid; + guint16 ftype; + guint16 fattr; + smb_fid_info_t *fid_info=NULL; + gboolean isdir=FALSE; WORD_COUNT; @@ -6115,16 +6166,22 @@ dissect_open_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /* fid */ fid = tvb_get_letohs(tvb, offset); - dissect_smb_fid(tvb, pinfo, tree, offset, 2, fid, TRUE, FALSE, FALSE); + /* we add fid_info= to this call so that we save the result */ + fid_info=dissect_smb_fid(tvb, pinfo, tree, offset, 2, fid, TRUE, FALSE, FALSE); + offset += 2; /* File Attributes */ + fattr = tvb_get_letohs(tvb, offset); + isdir = fattr & 0x10; offset = dissect_file_attributes(tvb, tree, offset, 2); /* last write time */ offset = dissect_smb_UTIME(tvb, tree, offset, hf_smb_last_write_time); /* File Size */ + /* We store the file_size in the fid_info */ + fid_info->end_of_file=(guint64) tvb_get_letohl(tvb, offset); proto_tree_add_item(tree, hf_smb_file_size, tvb, offset, 4, TRUE); offset += 4; @@ -6132,8 +6189,30 @@ dissect_open_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, offset = dissect_access(tvb, tree, offset, "Granted"); /* File Type */ + ftype=tvb_get_letohs(tvb, offset); proto_tree_add_item(tree, hf_smb_file_type, tvb, offset, 2, TRUE); offset += 2; + /* Copied from dissect_nt_create_andx_response + Try to remember the type of this fid so that we can dissect + any future security descriptor (access mask) properly + */ + fid_info->type=SMB_FID_TYPE_UNKNOWN; + if(ftype==0){ + if(isdir==0){ + if(fid_info){ + fid_info->type=SMB_FID_TYPE_FILE; + } + } else { + if(fid_info){ + fid_info->type=SMB_FID_TYPE_DIR; + } + } + } + if(ftype==2 || ftype==1){ + if(fid_info){ + fid_info->type=SMB_FID_TYPE_PIPE; + } + } /* IPC State */ offset = dissect_ipc_state(tvb, tree, offset, FALSE); @@ -6303,6 +6382,15 @@ 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) { @@ -6310,8 +6398,18 @@ dissect_read_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 andxoffset=0, bc, datalen_low, dataoffset=0; guint32 datalen=0, datalen_high; smb_info_t *si = (smb_info_t *)pinfo->private_data; - int fid=0; 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,packet_number; + tvbuff_t *data_tvb; + GSList *GSL_iterator; + int found=0; DISSECTOR_ASSERT(si); @@ -6413,6 +6511,51 @@ dissect_read_andx_response(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) { + packet_number=pinfo->fd->num; + /* 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 = 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); + found+=1; + } + } + tid_info = 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 = data_tvb->real_data; + 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); + } + END_OF_SMB if (cmd != 0xff) { /* there is an andX command */ @@ -6432,10 +6575,19 @@ dissect_write_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 andxoffset=0, bc, dataoffset=0, datalen_low, datalen_high; guint32 datalen=0; smb_info_t *si = (smb_info_t *)pinfo->private_data; - unsigned int fid=0; + 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,packet_number; + tvbuff_t *data_tvb; + GSList *GSL_iterator; + int found=0; DISSECTOR_ASSERT(si); @@ -6575,6 +6727,65 @@ dissect_write_andx_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) { + packet_number=pinfo->fd->num; + /* 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 = 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, fi +d);) */ + 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); + found+=1; + } + } + tid_info = 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 = data_tvb->real_data; + 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); + } + END_OF_SMB if (cmd != 0xff) { /* there is an andX command */ @@ -9911,6 +10122,8 @@ dissect_nt_create_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t offset += 8; /* end of file */ + /* We store the end of file */ + fid_info->end_of_file=tvb_get_letoh64(tvb, offset); proto_tree_add_item(tree, hf_smb_end_of_file, tvb, offset, 8, TRUE); offset += 8; @@ -16735,6 +16948,8 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) si->ct->fid_tree=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "SMB fid_tree"); si->ct->tid_tree=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "SMB tid_tree"); si->ct->uid_tree=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "SMB uid_tree"); + /* Initialize the GSL_fid_info for this ct */ + si->ct->GSL_fid_info=NULL; conversation_add_proto_data(conversation, proto_smb, si->ct); } @@ -19650,6 +19865,9 @@ proto_register_smb(void) register_init_routine(smb_trans_reassembly_init); smb_tap = register_tap("smb"); + /* Register the tap for the "Export Object" function */ + smb_eo_tap = register_tap("smb_eo"); /* SMB Export Object tap */ + register_dissector("smb", dissect_smb, proto_smb); } diff --git a/epan/dissectors/packet-smb.h b/epan/dissectors/packet-smb.h index 11b9432458..dea3c0cb67 100644 --- a/epan/dissectors/packet-smb.h +++ b/epan/dissectors/packet-smb.h @@ -177,6 +177,25 @@ WS_VAR_IMPORT const value_string nt_cmd_vals[]; #define SMBE_sharebufexc 36 /* A sharing buffer has been exceeded */ #define SMBE_diskfull 39 +/* Used for SMB Export Object feature */ +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; +} smb_eo_t; + +/* Strings that describes the SMB object type */ +WS_VAR_IMPORT const value_string smb_fid_types[]; + /* the information we need to keep around for NT transatcion commands */ typedef struct { int subcmd; @@ -238,7 +257,8 @@ typedef struct { int subcmd; int trans_subcmd; int function; - int fid; + /* Unification of fid variable type (was int) */ + guint16 fid; guint16 lanman_cmd; guchar *param_descrip; /* Keep these descriptors around */ guchar *data_descrip; @@ -269,6 +289,8 @@ typedef struct conv_tables { /* track fid to fidstruct (filename/openframe/closeframe */ emem_tree_t *fid_tree; + /* We'll use a GSL list instead */ + GSList *GSL_fid_info; /* track tid to fidstruct (sharename/shareframe/unshareframe */ emem_tree_t *tid_tree; @@ -334,8 +356,13 @@ typedef struct _smb_fid_saved_info_t { guint32 create_disposition; } smb_fid_saved_info_t; struct _smb_fid_into_t { - int opened_in; - int closed_in; + guint16 tid,fid; + /* The end_of_file will store the last registered offset or + the reported end_of_file from the SMB protocol */ + gint64 end_of_file; + /* These two were int */ + guint opened_in; + guint closed_in; int type; smb_fid_saved_info_t *fsi; }; |