SMB2: properly show reused FIDs

When dissecting a trace containing the same FID multiple times (for
different file paths) Wireshark would get confused and show file path
of the latest occurence of the FID for all usage.

Example:

  => open  req "\dir\lol.txt"
  <= open  rsp fid=0x123

from this point, 0x123 is "lol.txt", yet wireshark will show "bar.txt"

  => write req fid=0x123 data="foo"
  <= write rsp ok
  => close req fid=0x123
  <= close rsp ok

from this point, 0x123 is no longuer valid

  => open  req "\dir\bar.txt"
  <= open  rsp fid=0x123

from this point, 0x123 is "bar.txt"

  => write req fid=0x123 data="foo"
  <= write rsp ok
  => close req fid=0x123
  <= close rsp ok

Wireshark displays "bar.txt" for all occurences of 0x123. This patch
fixes that and stores the interval (in frame numbers) in which each
FID is valid. From the first time the FID is seen to the time the
close is done.

Change-Id: I9027bb1756d1dbee0393b50786f49845b79f129c
Reviewed-on: https://code.wireshark.org/review/36192
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
Aurelien Aptel 2020-02-26 18:08:52 +01:00 committed by Anders Broman
parent 4fe7fbd51d
commit ab274af1ed
2 changed files with 39 additions and 11 deletions

View File

@ -1318,24 +1318,33 @@ smb2_sesid_info_hash(gconstpointer k)
static gint
smb2_fid_info_equal(gconstpointer k1, gconstpointer k2)
{
const smb2_fid_info_t *key1 = (const smb2_fid_info_t *)k1;
const smb2_fid_info_t *key2 = (const smb2_fid_info_t *)k2;
const smb2_fid_info_t *key = (const smb2_fid_info_t *)k1;
const smb2_fid_info_t *val = (const smb2_fid_info_t *)k2;
if (key1->fid_persistent != key2->fid_persistent) {
return 0;
};
if (!key->frame_key) {
key = (const smb2_fid_info_t *)k2;
val = (const smb2_fid_info_t *)k1;
}
if (key1->fid_volatile != key2->fid_volatile) {
if (key->fid_persistent != val->fid_persistent) {
return 0;
};
}
if (key1->sesid != key2->sesid) {
if (key->fid_volatile != val->fid_volatile) {
return 0;
};
}
if (key1->tid != key2->tid) {
if (key->sesid != val->sesid) {
return 0;
};
}
if (key->tid != val->tid) {
return 0;
}
if (!(val->frame_beg <= key->frame_key && key->frame_key <= val->frame_end)) {
return 0;
}
return 1;
}
@ -2262,10 +2271,12 @@ dissect_smb2_fid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset
smb2_fid_info_t sfi_key;
smb2_fid_info_t *sfi = NULL;
memset(&sfi_key, 0, sizeof(sfi_key));
sfi_key.fid_persistent = tvb_get_letoh64(tvb, offset);
sfi_key.fid_volatile = tvb_get_letoh64(tvb, offset+8);
sfi_key.sesid = si->sesid;
sfi_key.tid = si->tid;
sfi_key.frame_key = pinfo->num;
sfi_key.name = NULL;
di.conformant_run = 0;
@ -2278,6 +2289,10 @@ dissect_smb2_fid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset
if (!pinfo->fd->visited) {
sfi = wmem_new(wmem_file_scope(), smb2_fid_info_t);
*sfi = sfi_key;
sfi->frame_key = 0;
sfi->frame_beg = si->saved ? si->saved->frame_req : pinfo->num;
sfi->frame_end = G_MAXUINT32;
if (si->saved && si->saved->extra_info_type == SMB2_EI_FILENAME) {
sfi->name = wmem_strdup(wmem_file_scope(), (char *)si->saved->extra_info);
} else {
@ -2315,6 +2330,13 @@ dissect_smb2_fid(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset
}
break;
case FID_MODE_CLOSE:
if (!pinfo->fd->visited) {
smb2_fid_info_t *fid = (smb2_fid_info_t *)g_hash_table_lookup(si->session->fids, &sfi_key);
if (fid) {
/* set last frame */
fid->frame_end = pinfo->num;
}
}
offset = dissect_nt_guid_hnd(tvb, offset, pinfo, tree, &di, drep, hf_smb2_fid, &policy_hnd, &hnd_item, FALSE, TRUE);
break;
case FID_MODE_USE:

View File

@ -43,6 +43,12 @@ typedef struct _smb2_fid_info_t {
guint64 fid_volatile;
guint64 sesid; /* *host* byte order - not necessarily little-endian! */
guint32 tid;
/* only used for key lookup in equal func, must be zero when inserting */
guint32 frame_key;
/* first and last frame nums this FID is valid */
guint32 frame_beg;
guint32 frame_end;
/* file name used to open this FID */
char *name;
} smb2_fid_info_t;