aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnders Broman <anders.broman@ericsson.com>2012-06-19 06:24:30 +0000
committerAnders Broman <anders.broman@ericsson.com>2012-06-19 06:24:30 +0000
commit99e919bf8b0423fef45a642960b1d0290b74d0c5 (patch)
treea0e1ff1caefc4425016e1ecaa287925946d4251e
parent24d2178eb7947280532786c8057b362d5e4fe36e (diff)
From Richard Sharpe:
packet-smb.c does not properly handle NT TRANSACT requests (and probably TRANSACT and TRANSACT2 requests) https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=7351 svn path=/trunk/; revision=43347
-rw-r--r--epan/dissectors/packet-smb.c106
-rw-r--r--epan/dissectors/packet-smb.h3
2 files changed, 96 insertions, 13 deletions
diff --git a/epan/dissectors/packet-smb.c b/epan/dissectors/packet-smb.c
index c91cfbe708..7cd76f5354 100644
--- a/epan/dissectors/packet-smb.c
+++ b/epan/dissectors/packet-smb.c
@@ -8852,7 +8852,8 @@ static int
dissect_nt_transaction_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, proto_tree *smb_tree _U_)
{
guint8 wc, sc;
- guint32 pc=0, po=0, dc=0, od=0;
+ guint32 pc=0, pd = 0, po=0, dc=0, od=0, dd = 0;
+ guint32 td=0, tp=0;
smb_info_t *si;
smb_saved_info_t *sip;
int subcmd;
@@ -8860,6 +8861,9 @@ dissect_nt_transaction_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree
guint16 bc;
guint32 padcnt;
smb_nt_transact_info_t *nti=NULL;
+ fragment_data *r_fd = NULL;
+ tvbuff_t *pd_tvb=NULL;
+ gboolean save_fragmented;
ntd.subcmd = ntd.sd_len = ntd.ea_len = 0;
@@ -8887,11 +8891,13 @@ dissect_nt_transaction_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree
/* total param count */
- proto_tree_add_item(tree, hf_smb_total_param_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ tp = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_total_param_count, tvb, offset, 4, tp);
offset += 4;
/* total data count */
- proto_tree_add_item(tree, hf_smb_total_data_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ td = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_total_data_count, tvb, offset, 4, td);
offset += 4;
if(wc>=19){
@@ -8940,7 +8946,8 @@ dissect_nt_transaction_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree
/* primary request */
} else {
/* secondary request */
- proto_tree_add_item(tree, hf_smb_data_disp32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ dd = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_data_disp32, tvb, offset, 4, dd);
offset += 4;
}
@@ -9003,8 +9010,54 @@ dissect_nt_transaction_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree
BYTE_COUNT;
- /* parameters */
- if(po>(guint32)offset){
+ /* reassembly of SMB NT Transaction data payload.
+ In this section we do reassembly of both the data and parameters
+ blocks of the SMB transaction command.
+ */
+ save_fragmented = pinfo->fragmented;
+ /* do we need reassembly? */
+ if( (td&&(td!=dc)) || (tp&&(tp!=pc)) ){
+ /* oh yeah, either data or parameter section needs
+ reassembly...
+ */
+ pinfo->fragmented = TRUE;
+ if(smb_trans_reassembly){
+ /* ...and we were told to do reassembly */
+ if(pc && ((unsigned int)tvb_length_remaining(tvb, po)>=pc) ){
+ r_fd = smb_trans_defragment(tree, pinfo, tvb,
+ po, pc, pd, td+tp);
+ }
+ if((r_fd==NULL) && dc && ((unsigned int)tvb_length_remaining(tvb, od)>=dc) ){
+ r_fd = smb_trans_defragment(tree, pinfo, tvb,
+ od, dc, dd+tp, td+tp);
+ }
+ }
+ }
+
+ /* if we got a reassembled fd structure from the reassembly routine we
+ must create pd_tvb from it
+ */
+ if(r_fd){
+ proto_item *frag_tree_item;
+
+ pd_tvb = tvb_new_child_real_data(tvb, r_fd->data, r_fd->datalen,
+ r_fd->datalen);
+ add_new_data_source(pinfo, pd_tvb, "Reassembled SMB");
+
+ show_fragment_tree(r_fd, &smb_frag_items, tree, pinfo, pd_tvb, &frag_tree_item);
+ }
+
+ if(pd_tvb){
+ /* we have reassembled data, grab param and data from there */
+ dissect_nt_trans_param_request(pd_tvb, pinfo, 0, tree, tp,
+ &ntd, (guint16) tvb_length(pd_tvb), nti);
+ dissect_nt_trans_data_request(pd_tvb, pinfo, tp, tree, td, &ntd, nti);
+ COUNT_BYTES(bc); /* We are done */
+ } else {
+ /* we do not have reassembled data, just use what we have in the
+ packet as well as we can */
+ /* parameters */
+ if(po>(guint32)offset){
/* We have some initial padding bytes.
*/
padcnt = po-offset;
@@ -9013,15 +9066,15 @@ dissect_nt_transaction_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree
CHECK_BYTE_COUNT(padcnt);
proto_tree_add_item(tree, hf_smb_padding, tvb, offset, padcnt, ENC_NA);
COUNT_BYTES(padcnt);
- }
- if(pc){
+ }
+ if(pc){
CHECK_BYTE_COUNT(pc);
dissect_nt_trans_param_request(tvb, pinfo, offset, tree, pc, &ntd, bc, nti);
COUNT_BYTES(pc);
- }
+ }
- /* data */
- if(od>(guint32)offset){
+ /* data */
+ if(od>(guint32)offset){
/* We have some initial padding bytes.
*/
padcnt = od-offset;
@@ -9029,12 +9082,13 @@ dissect_nt_transaction_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree
padcnt = bc;
proto_tree_add_item(tree, hf_smb_padding, tvb, offset, padcnt, ENC_NA);
COUNT_BYTES(padcnt);
- }
- if(dc){
+ }
+ if(dc){
CHECK_BYTE_COUNT(dc);
dissect_nt_trans_data_request(
tvb, pinfo, offset, tree, dc, &ntd, nti);
COUNT_BYTES(dc);
+ }
}
END_OF_SMB
@@ -9549,6 +9603,7 @@ dissect_nt_transaction_response(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tre
dissect_nt_trans_param_response(pd_tvb, pinfo, 0, tree, tp,
&ntd, (guint16) tvb_length(pd_tvb));
dissect_nt_trans_data_response(pd_tvb, pinfo, tp, tree, td, &ntd, nti);
+ COUNT_BYTES(bc); /* We are done */
} else {
/* we do not have reassembled data, just use what we have in the
packet as well as we can */
@@ -17213,6 +17268,8 @@ free_hash_tables(gpointer ctarg, gpointer user_data _U_)
g_hash_table_destroy(ct->unmatched);
if (ct->matched)
g_hash_table_destroy(ct->matched);
+ if (ct->primaries)
+ g_hash_table_destroy(ct->primaries);
if (ct->tid_service)
g_hash_table_destroy(ct->tid_service);
g_free(ct);
@@ -17575,6 +17632,10 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
smb_saved_info_equal_matched);
si->ct->unmatched= g_hash_table_new(smb_saved_info_hash_unmatched,
smb_saved_info_equal_unmatched);
+ /* We used the same key format as the unmatched entries */
+ si->ct->primaries=g_hash_table_new(
+ smb_saved_info_hash_unmatched,
+ smb_saved_info_equal_unmatched);
si->ct->tid_service=g_hash_table_new(
smb_saved_info_hash_unmatched,
smb_saved_info_equal_unmatched);
@@ -17640,6 +17701,12 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
new_key->pid_mid = pid_mid;
g_hash_table_insert(si->ct->matched, new_key,
sip);
+ } else {
+ if (si->cmd == SMB_COM_TRANSACTION_SECONDARY ||
+ si->cmd == SMB_COM_TRANSACTION2_SECONDARY ||
+ si->cmd == SMB_COM_NT_TRANSACT_SECONDARY) {
+ sip = g_hash_table_lookup(si->ct->primaries, GUINT_TO_POINTER(pid_mid));
+ }
}
} else {
/* we have seen this packet before; check the
@@ -17785,6 +17852,12 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
sip=NULL;
}
}
+ } else {
+ if (si->cmd == SMB_COM_TRANSACTION ||
+ si->cmd == SMB_COM_TRANSACTION2 ||
+ si->cmd == SMB_COM_NT_TRANSACT) {
+ sip = g_hash_table_lookup(si->ct->primaries, GUINT_TO_POINTER(pid_mid));
+ }
}
if(si->request){
sip = se_alloc(sizeof(smb_saved_info_t));
@@ -17806,6 +17879,13 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
new_key->frame = sip->frame_req;
new_key->pid_mid = pid_mid;
g_hash_table_insert(si->ct->matched, new_key, sip);
+
+ /* If it is a TRANSACT cmd, insert in hash */
+ if (si->cmd == SMB_COM_TRANSACTION ||
+ si->cmd == SMB_COM_TRANSACTION2 ||
+ si->cmd == SMB_COM_NT_TRANSACT) {
+ g_hash_table_insert(si->ct->primaries, GUINT_TO_POINTER(pid_mid), sip);
+ }
}
} else {
/* we have seen this packet before; check the
diff --git a/epan/dissectors/packet-smb.h b/epan/dissectors/packet-smb.h
index 6f502d8d62..7de45eebc5 100644
--- a/epan/dissectors/packet-smb.h
+++ b/epan/dissectors/packet-smb.h
@@ -282,6 +282,9 @@ typedef struct conv_tables {
/* these two tables are used to match requests with responses */
GHashTable *unmatched;
GHashTable *matched;
+ /* This table keeps primary transact requests so secondaries can find
+ them */
+ GHashTable *primaries;
/* This table is used to track TID->services for a conversation */
GHashTable *tid_service;