diff options
author | Guy Harris <guy@alum.mit.edu> | 2001-12-05 08:20:30 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2001-12-05 08:20:30 +0000 |
commit | 6b253331f087fbecb5de5e4548fbbe644d19b7af (patch) | |
tree | 43a7a7e7ed39be14d47f53c6f515e1acd3d37a15 /packet-smb.c | |
parent | faacd2b71c6e1141c7fa88ca2164e56fb4a0daa7 (diff) | |
download | wireshark-6b253331f087fbecb5de5e4548fbbe644d19b7af.tar.gz wireshark-6b253331f087fbecb5de5e4548fbbe644d19b7af.tar.bz2 wireshark-6b253331f087fbecb5de5e4548fbbe644d19b7af.zip |
Support for reassembly of DCERPC over SMB, from Ronnie Sahlberg.
svn path=/trunk/; revision=4335
Diffstat (limited to 'packet-smb.c')
-rw-r--r-- | packet-smb.c | 195 |
1 files changed, 114 insertions, 81 deletions
diff --git a/packet-smb.c b/packet-smb.c index e9b3eb529e..adda0b19a9 100644 --- a/packet-smb.c +++ b/packet-smb.c @@ -2,7 +2,7 @@ * Routines for smb packet dissection * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com> * - * $Id: packet-smb.c,v 1.178 2001/12/05 00:49:31 guy Exp $ + * $Id: packet-smb.c,v 1.179 2001/12/05 08:20:28 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -666,18 +666,24 @@ static const gchar *get_unicode_or_ascii_string(tvbuff_t *tvb, /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - These are needed by the reassembly of SMB Transaction payload + These are needed by the reassembly of SMB Transaction payload and DCERPC over SMB XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ -/* Reassembly of SMB Transaction calls */ static gboolean smb_trans_reassembly = FALSE; +gboolean smb_dcerpc_reassembly = FALSE; static GHashTable *smb_trans_fragment_table = NULL; +GHashTable *dcerpc_fragment_table = NULL; static void smb_trans_reassembly_init(void) { fragment_table_init(&smb_trans_fragment_table); } +static void +smb_dcerpc_reassembly_init(void) +{ + fragment_table_init(&dcerpc_fragment_table); +} static fragment_data * @@ -802,10 +808,6 @@ static int smb_transact2_info_init_count = 200; static GMemChunk *smb_transact_info_chunk = NULL; static int smb_transact_info_init_count = 200; -typedef struct conv_tables { - GHashTable *unmatched; - GHashTable *matched; -} conv_tables_t; static GMemChunk *conv_tables_chunk = NULL; static int conv_tables_count = 10; @@ -4597,8 +4599,8 @@ static int dissect_read_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree) { guint8 wc, cmd=0xff; - guint16 andxoffset=0, bc, datalen=0; - smb_info_t *si; + guint16 andxoffset=0, bc, datalen=0, dataoffset=0; + smb_info_t *si = (smb_info_t *)pinfo->private_data; WORD_COUNT; @@ -4621,7 +4623,6 @@ dissect_read_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, offset += 2; /* If we have seen the request, then print which FID this refers to */ - si = (smb_info_t *)pinfo->private_data; /* first check if we have seen the request */ if(si->sip != NULL && si->sip->frame_req>0){ add_fid(tvb, pinfo, tree, 0, 0, (int)si->sip->extra_info); @@ -4645,7 +4646,8 @@ dissect_read_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, offset += 2; /* data offset */ - proto_tree_add_item(tree, hf_smb_data_offset, tvb, offset, 2, TRUE); + dataoffset=tvb_get_letohs(tvb, offset); + proto_tree_add_uint(tree, hf_smb_data_offset, tvb, offset, 2, dataoffset); offset += 2; /* 10 reserved bytes */ @@ -4655,6 +4657,43 @@ dissect_read_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, BYTE_COUNT; + /* is this part of DCERPC over SMB reassembly?*/ + if(smb_dcerpc_reassembly && !pinfo->fd->flags.visited && (bc<=tvb_length_remaining(tvb, offset)) ){ + guint32 frame; + frame=(guint32)g_hash_table_lookup(si->ct->dcerpc_fid_to_frame, + si->sip->extra_info); + if(frame){ + fragment_data *fd_head; + /* first fragment is always from a SMB Trans command and + offset 0 of the following read/write SMB commands start + BEYOND the first Trans SMB payload. Look for offset + in first read fragment */ + fd_head=fragment_get(pinfo, frame, dcerpc_fragment_table); + if(fd_head){ + /* skip to last fragment and add this data there*/ + while(fd_head->next){ + fd_head=fd_head->next; + } + /* if dataoffset was not specified in the SMB command + then we try to guess it as good as we can + */ + if(dataoffset==0){ + dataoffset=offset+bc-datalen; + } + fd_head=fragment_add(tvb, dataoffset, pinfo, + frame, dcerpc_fragment_table, + fd_head->offset+fd_head->len, + datalen, TRUE); + /* we completed reassembly, abort searching for more + fragments*/ + if(fd_head){ + g_hash_table_remove(si->ct->dcerpc_fid_to_frame, + si->sip->extra_info); + } + } + } + } + /* file data */ offset = dissect_file_data(tvb, pinfo, tree, offset, bc, datalen); bc = 0; @@ -12745,6 +12784,7 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) guint8 errclass = 0; guint16 errcode = 0; guint16 uid, pid, tid; + conversation_t *conversation; top_tree=parent_tree; @@ -12798,6 +12838,29 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) proto_tree_add_text(htree, tvb, offset, 4, "Server Component: SMB"); offset += 4; /* Skip the marker */ + /* find which conversation we are part of and get the tables for that + conversation*/ + conversation = find_conversation(&pinfo->src, &pinfo->dst, + pinfo->ptype, pinfo->srcport, pinfo->destport, 0); + if(conversation){ + si.ct=conversation_get_proto_data(conversation, proto_smb); + } else { + /* OK this is a new conversation, we must create it + and attach appropriate data (matched and unmatched + table for this conversation) + */ + conversation = conversation_new(&pinfo->src, &pinfo->dst, + pinfo->ptype, pinfo->srcport, pinfo->destport, 0); + si.ct = g_mem_chunk_alloc(conv_tables_chunk); + si.ct->matched= g_hash_table_new(smb_saved_info_hash_matched, + smb_saved_info_equal_matched); + si.ct->unmatched= g_hash_table_new(smb_saved_info_hash_matched, + smb_saved_info_equal_matched); + si.ct->dcerpc_fid_to_frame=g_hash_table_new( + smb_saved_info_hash_matched, + smb_saved_info_equal_matched); + conversation_add_proto_data(conversation, proto_smb, si.ct); + } if( (si.request) && (si.mid==0) @@ -12829,47 +12892,37 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) requests smb_saved_info_t but we dont touch it or change anything in it. */ - conversation_t *conversation; - conv_tables_t *ct; si.unidir = TRUE; /*we dont expect an answer to this one*/ - - /* find which conversation we are part of and get the tables for that - conversation*/ - conversation = find_conversation(&pinfo->src, &pinfo->dst, - pinfo->ptype, pinfo->srcport, pinfo->destport, 0); - if(conversation){ - ct=conversation_get_proto_data(conversation, proto_smb); - if(!pinfo->fd->flags.visited){ - /* try to find which original call we match and if we - find it add us to the matched table. Dont touch - anything else since we dont want this one to mess - up the request/response matching. We still consider - the initial call the real request and this is only - some sort of continuation. - */ - /* we only check the unmatched table and assume that the - last seen MID matching ours is the right one. - This can fail but is better than nothing - */ - sip=g_hash_table_lookup(ct->unmatched, (void *)si.mid); - if(sip!=NULL){ - g_hash_table_insert(ct->matched, (void *)pinfo->fd->num, sip); - } - } else { - /* we have seen this packet before; check the - matching table - */ - sip=g_hash_table_lookup(ct->matched, (void *)pinfo->fd->num); - if(sip==NULL){ - /* - We didn't find it. - Too bad, unfortunately there is not really much we can - do now since this means that we never saw the initial - request. - */ - } + if(!pinfo->fd->flags.visited){ + /* try to find which original call we match and if we + find it add us to the matched table. Dont touch + anything else since we dont want this one to mess + up the request/response matching. We still consider + the initial call the real request and this is only + some sort of continuation. + */ + /* we only check the unmatched table and assume that the + last seen MID matching ours is the right one. + This can fail but is better than nothing + */ + sip=g_hash_table_lookup(si.ct->unmatched, (void *)si.mid); + if(sip!=NULL){ + g_hash_table_insert(si.ct->matched, (void *)pinfo->fd->num, sip); + } + } else { + /* we have seen this packet before; check the + matching table + */ + sip=g_hash_table_lookup(si.ct->matched, (void *)pinfo->fd->num); + if(sip==NULL){ + /* + We didn't find it. + Too bad, unfortunately there is not really much we can + do now since this means that we never saw the initial + request. + */ } } @@ -12902,38 +12955,13 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) } } } else { /* normal bidirectional request or response */ - conversation_t *conversation; - conv_tables_t *ct; - si.unidir = FALSE; - /* first we try to find which conversation this packet is - part of - */ - conversation = find_conversation(&pinfo->src, &pinfo->dst, - pinfo->ptype, pinfo->srcport, pinfo->destport, 0); - if(conversation==NULL){ - /* OK this is a new conversation, we must create it - and attach appropriate data (matched and unmatched - table for this conversation) - */ - conversation = conversation_new(&pinfo->src, &pinfo->dst, - pinfo->ptype, pinfo->srcport, pinfo->destport, 0); - ct = g_mem_chunk_alloc(conv_tables_chunk); - ct->matched= g_hash_table_new(smb_saved_info_hash_matched, - smb_saved_info_equal_matched); - ct->unmatched= g_hash_table_new(smb_saved_info_hash_matched, - smb_saved_info_equal_matched); - conversation_add_proto_data(conversation, proto_smb, ct); - } else { - /* this is an old conversation, just get the tables */ - ct=conversation_get_proto_data(conversation, proto_smb); - } if(!pinfo->fd->flags.visited){ /* first see if we find an unmatched smb "equal" to the current one */ - sip=g_hash_table_lookup(ct->unmatched, (void *)si.mid); + sip=g_hash_table_lookup(si.ct->unmatched, (void *)si.mid); if(sip!=NULL){ if(si.request){ /* ok, we are processing an SMB @@ -12950,7 +12978,7 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) request and concentrate on the present one instead. */ - g_hash_table_remove(ct->unmatched, (void *)si.mid); + g_hash_table_remove(si.ct->unmatched, (void *)si.mid); } else { /* we have found a response to some request we have seen earlier. What we do now depends on whether this is the first response @@ -12959,13 +12987,13 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) if(sip->frame_res==0){ /* ok it is the first response we have seen to this packet */ sip->frame_res = pinfo->fd->num; - g_hash_table_insert(ct->matched, (void *)sip->frame_req, sip); - g_hash_table_insert(ct->matched, (void *)sip->frame_res, sip); + g_hash_table_insert(si.ct->matched, (void *)sip->frame_req, sip); + g_hash_table_insert(si.ct->matched, (void *)sip->frame_res, sip); } else { /* we have already seen another response to this one, but register it anyway so we see which request it matches */ - g_hash_table_insert(ct->matched, (void *)pinfo->fd->num, sip); + g_hash_table_insert(si.ct->matched, (void *)pinfo->fd->num, sip); } } } @@ -12974,7 +13002,7 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) sip->frame_req = pinfo->fd->num; sip->frame_res = 0; sip->extra_info = NULL; - g_hash_table_insert(ct->unmatched, (void *)si.mid, sip); + g_hash_table_insert(si.ct->unmatched, (void *)si.mid, sip); } } else { /* we have seen this packet before; check the @@ -12985,7 +13013,7 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) we've seen this packet before, we've already saved the information. */ - sip=g_hash_table_lookup(ct->matched, (void *)pinfo->fd->num); + sip=g_hash_table_lookup(si.ct->matched, (void *)pinfo->fd->num); } } @@ -14911,7 +14939,12 @@ proto_register_smb(void) "Reassemble SMB Transaction payload", "Whether the dissector should do reassembly the payload of SMB Transaction commands spanning multiple SMB PDUs", &smb_trans_reassembly); + prefs_register_bool_preference(smb_module, "smb.dcerpc.reassembly", + "Reassemble DCERPC over SMB", + "Whether the dissector should do reassembly of DCERPC over SMB commands", + &smb_dcerpc_reassembly); register_init_routine(smb_trans_reassembly_init); + register_init_routine(smb_dcerpc_reassembly_init); } void |