packet-smb2: dissect the read response data with dissect_smb2_olb_*

Some servers add some padding between fixed read response header and the
actual data.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
This commit is contained in:
Stefan Metzmacher 2021-06-29 09:30:27 +02:00 committed by Wireshark GitLab Utility
parent 38810b763b
commit d9328a9839
1 changed files with 53 additions and 28 deletions

View File

@ -225,6 +225,7 @@ static int hf_smb2_write_flags_write_through = -1;
static int hf_smb2_write_flags_write_unbuffered = -1;
static int hf_smb2_write_count = -1;
static int hf_smb2_write_remaining = -1;
static int hf_smb2_read_blob = -1;
static int hf_smb2_read_length = -1;
static int hf_smb2_read_remaining = -1;
static int hf_smb2_read_padding = -1;
@ -1746,6 +1747,7 @@ static int dissect_smb2_file_full_ea_info(tvbuff_t *tvb, packet_info *pinfo, pro
enum offset_length_buffer_offset_size {
OLB_O_UINT16_S_UINT16,
OLB_O_UINT16_S_UINT32,
OLB_O_UINT8_P_UINT8_S_UINT32,
OLB_O_UINT32_S_UINT32,
OLB_S_UINT32_O_UINT32
};
@ -1780,6 +1782,16 @@ dissect_smb2_olb_length_offset(tvbuff_t *tvb, int offset, offset_length_buffer_t
olb->len_offset = offset;
offset += 4;
break;
case OLB_O_UINT8_P_UINT8_S_UINT32:
olb->off = tvb_get_guint8(tvb, offset);
olb->off_offset = offset;
offset += 1;
/* 1 byte reserved */
offset += 1;
olb->len = tvb_get_letohl(tvb, offset);
olb->len_offset = offset;
offset += 4;
break;
case OLB_O_UINT32_S_UINT32:
olb->off = tvb_get_letohl(tvb, offset);
olb->off_offset = offset;
@ -1854,6 +1866,11 @@ dissect_smb2_olb_off_string(packet_info *pinfo, proto_tree *parent_tree, tvbuff_
proto_tree_add_item(tree, hf_smb2_olb_offset, tvb, olb->off_offset, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_smb2_olb_length, tvb, olb->len_offset, 4, ENC_LITTLE_ENDIAN);
break;
case OLB_O_UINT8_P_UINT8_S_UINT32:
proto_tree_add_item(tree, hf_smb2_olb_offset, tvb, olb->off_offset, 1, ENC_NA);
proto_tree_add_item(tree, hf_smb2_reserved, tvb, olb->off_offset+1, 1, ENC_NA);
proto_tree_add_item(tree, hf_smb2_olb_length, tvb, olb->len_offset, 4, ENC_LITTLE_ENDIAN);
break;
case OLB_O_UINT32_S_UINT32:
proto_tree_add_item(tree, hf_smb2_olb_offset, tvb, olb->off_offset, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(tree, hf_smb2_olb_length, tvb, olb->len_offset, 4, ENC_LITTLE_ENDIAN);
@ -1909,6 +1926,11 @@ dissect_smb2_olb_buffer(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *t
proto_tree_add_item(parent_tree, hf_smb2_olb_offset, tvb, olb->off_offset, 2, ENC_LITTLE_ENDIAN);
proto_tree_add_item(parent_tree, hf_smb2_olb_length, tvb, olb->len_offset, 4, ENC_LITTLE_ENDIAN);
break;
case OLB_O_UINT8_P_UINT8_S_UINT32:
proto_tree_add_item(parent_tree, hf_smb2_olb_offset, tvb, olb->off_offset, 1, ENC_NA);
proto_tree_add_item(parent_tree, hf_smb2_reserved, tvb, olb->off_offset+1, 1, ENC_NA);
proto_tree_add_item(parent_tree, hf_smb2_olb_length, tvb, olb->len_offset, 4, ENC_LITTLE_ENDIAN);
break;
case OLB_O_UINT32_S_UINT32:
proto_tree_add_item(parent_tree, hf_smb2_olb_offset, tvb, olb->off_offset, 4, ENC_LITTLE_ENDIAN);
proto_tree_add_item(parent_tree, hf_smb2_olb_length, tvb, olb->len_offset, 4, ENC_LITTLE_ENDIAN);
@ -8024,13 +8046,29 @@ dissect_smb2_read_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, i
return offset;
}
static void
dissect_smb2_read_blob(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, smb2_info_t *si)
{
gint offset = 0;
gint length = tvb_captured_length_remaining(tvb, offset);
smb2_pipe_set_file_id(pinfo, si);
offset = dissect_file_data_smb2_pipe(tvb, pinfo, tree, offset, length, si->top_tree, si);
if (offset != 0) {
/* managed to dissect pipe data */
return;
}
/* data */
proto_tree_add_item(tree, hf_smb2_read_data, tvb, offset, length, ENC_NA);
}
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;
offset_length_buffer_t olb;
guint32 data_tvb_len;
guint32 length;
gboolean continue_dissection;
switch (si->status) {
@ -8040,15 +8078,10 @@ dissect_smb2_read_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
if (!continue_dissection) return offset;
}
/* 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;
/* length might even be 64bits if they are ambitious*/
length = tvb_get_letohl(tvb, offset);
proto_tree_add_item(tree, hf_smb2_read_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
offset += 4;
/* data offset 8 bit, 8 bit reserved, length 32bit */
offset = dissect_smb2_olb_length_offset(tvb, offset, &olb,
OLB_O_UINT8_P_UINT8_S_UINT32,
hf_smb2_read_blob);
/* remaining */
proto_tree_add_item(tree, hf_smb2_read_remaining, tvb, offset, 4, ENC_LITTLE_ENDIAN);
@ -8060,26 +8093,13 @@ dissect_smb2_read_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
data_tvb_len=(guint32)tvb_captured_length_remaining(tvb, offset);
/* data or namedpipe ?*/
if (length) {
int oldoffset = offset;
smb2_pipe_set_file_id(pinfo, si);
offset = dissect_file_data_smb2_pipe(tvb, pinfo, tree, offset, length, si->top_tree, si);
if (offset != oldoffset) {
/* managed to dissect pipe data */
goto out;
}
}
dissect_smb2_olb_buffer(pinfo, tree, tvb, &olb, si, dissect_smb2_read_blob);
/* data */
proto_tree_add_item(tree, hf_smb2_read_data, tvb, offset, length, ENC_NA);
offset += MIN(olb.len, data_tvb_len);
offset += MIN(length,data_tvb_len);
out:
if (have_tap_listener(smb2_eo_tap) && (data_tvb_len == length)) {
if (have_tap_listener(smb2_eo_tap) && (data_tvb_len == olb.len)) {
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);
feed_eo_smb2(tvb,pinfo,si,olb.off,olb.len,si->saved->file_offset);
}
}
@ -11514,6 +11534,11 @@ proto_register_smb2(void)
NULL, 0, "Amount of data to write", HFILL }
},
{ &hf_smb2_read_blob,
{ "Info", "smb2.read.blob", FT_BYTES, BASE_NONE,
NULL, 0, "Read Blob", HFILL }
},
{ &hf_smb2_read_length,
{ "Read Length", "smb2.read_length", FT_UINT32, BASE_DEC,
NULL, 0, "Amount of data to read", HFILL }