* Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
* 2001 Rewrite by Ronnie Sahlberg and Guy Harris
*
- * $Id: packet-smb.c,v 1.379 2003/12/18 00:18:54 guy Exp $
+ * $Id: packet-smb.c,v 1.389 2004/03/30 07:39:05 sharpe Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
#include <epan/packet.h>
#include <epan/conversation.h>
#include "smb.h"
-#include "alignment.h"
#include <epan/strutil.h>
#include "prefs.h"
#include "reassemble.h"
static int hf_smb_file_id = -1;
static int hf_smb_ea_error_offset = -1;
static int hf_smb_end_of_file = -1;
+static int hf_smb_replace = -1;
+static int hf_smb_root_dir_handle = -1;
+static int hf_smb_target_name_len = -1;
+static int hf_smb_target_name = -1;
static int hf_smb_device_type = -1;
static int hf_smb_is_directory = -1;
static int hf_smb_next_entry_offset = -1;
/*
* Get the time as seconds and nanoseconds.
*/
- tv->secs = d;
- tv->nsecs = (d - tv->secs)*1000000000;
+ tv->secs = (time_t) d;
+ tv->nsecs = (int) ((d - tv->secs)*1000000000);
return TRUE;
}
proto_item *litem = NULL;
proto_tree *ltree = NULL;
if(lt&0x10){
- char buf[8];
+ guint8 buf[8];
guint32 val;
/* large lock format */
proto_item *litem = NULL;
proto_tree *ltree = NULL;
if(lt&0x10){
- char buf[8];
+ guint8 buf[8];
guint32 val;
/* large lock format */
BYTE_COUNT;
/* if both the MessageStart and the WriteRawNamedPipe flags are set
- the first two bytes of the payload is the length of the data
- also this tells us that this is indeed the IPC$ share
- (if we didnt already know that
+ the first two bytes of the payload is the length of the data.
+ Assume that all WriteAndX PDUs that have MESSAGE_START set to
+ be over the IPC$ share and thus they all transport DCERPC.
+ (if we didnt already know that from the TreeConnect call)
*/
- if((mode&(WRITE_MODE_MESSAGE_START|WRITE_MODE_RAW))==(WRITE_MODE_MESSAGE_START|WRITE_MODE_RAW)){
- proto_tree_add_item(tree, hf_smb_pipe_write_len, tvb, offset, 2, TRUE);
- offset += 2;
- dataoffset += 2;
- bc -= 2;
- datalen -= 2;
+ if(mode&WRITE_MODE_MESSAGE_START){
+ if(mode&WRITE_MODE_RAW){
+ proto_tree_add_item(tree, hf_smb_pipe_write_len, tvb, offset, 2, TRUE);
+ offset += 2;
+ dataoffset += 2;
+ bc -= 2;
+ datalen -= 2;
+ }
+ if(!pinfo->fd->flags.visited){
+ /* In case we did not see the TreeConnect call,
+ store this TID here as well as a IPC TID
+ so we know that future Read/Writes to this
+ TID is (probably) DCERPC.
+ */
+ if(g_hash_table_lookup(si->ct->tid_service, (void *)si->tid)){
+ g_hash_table_remove(si->ct->tid_service, (void *)si->tid);
+ }
+ g_hash_table_insert(si->ct->tid_service, (void *)si->tid, (void *)TID_IPC);
+ }
if(si->sip){
si->sip->flags|=SMB_SIF_TID_IS_IPC;
}
guint16 pwlen=0;
guint16 sbloblen=0;
guint16 apwlen=0, upwlen=0;
+ gboolean unicodeflag;
WORD_COUNT;
COUNT_BYTES(sbloblen);
}
- /* OS */
+ /* OS
+ * Eventhough this field should honour the unicode flag
+ * some ms clients gets this wrong.
+ * At least XP SP1 sends this in ASCII
+ * even when the unicode flag is on.
+ * Test if the first three bytes are "Win"
+ * and if so just override the flag.
+ */
+ unicodeflag=si->unicode;
+ if( !strncmp(tvb_get_ptr(tvb, offset, 3), "Win", 3) ){
+ unicodeflag=FALSE;
+ }
an = get_unicode_or_ascii_string(tvb, &offset,
- si->unicode, &an_len, FALSE, FALSE, &bc);
+ unicodeflag, &an_len, FALSE, FALSE, &bc);
if (an == NULL)
goto endofcommand;
proto_tree_add_string(tree, hf_smb_os, tvb,
* appear to. I suspect that's a bug that got fixed; I also
* suspect that, in practice, nobody ever looks at that field
* because the bug didn't appear to get fixed until NT 5.0....
+ *
+ * Eventhough this field should honour the unicode flag
+ * some ms clients gets this wrong.
+ * At least XP SP1 sends this in ASCII
+ * even when the unicode flag is on.
+ * Test if the first three bytes are "Win"
+ * and if so just override the flag.
*/
+ unicodeflag=si->unicode;
+ if( !strncmp(tvb_get_ptr(tvb, offset, 3), "Win", 3) ){
+ unicodeflag=FALSE;
+ }
an = get_unicode_or_ascii_string(tvb, &offset,
- si->unicode, &an_len, FALSE, FALSE, &bc);
+ unicodeflag, &an_len, FALSE, FALSE, &bc);
if (an == NULL)
goto endofcommand;
proto_tree_add_string(tree, hf_smb_lanman, tvb,
int
dissect_nt_access_mask(tvbuff_t *tvb, gint offset, packet_info *pinfo,
- proto_tree *tree, char *drep, int hfindex,
- struct access_mask_info *ami)
+ proto_tree *tree, guint8 *drep, int hfindex,
+ struct access_mask_info *ami, guint32 *perms)
{
proto_item *item;
proto_tree *subtree, *generic_tree, *standard_tree, *specific_tree;
offset += 4;
}
+ if (perms) {
+ *perms = access;
+ }
+
item = proto_tree_add_uint(tree, hfindex, tvb, offset - 4, 4, access);
subtree = proto_item_add_subtree(item, ett_nt_access_mask);
static int
dissect_nt_v2_ace(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *parent_tree, char *drep,
+ proto_tree *parent_tree, guint8 *drep,
struct access_mask_info *ami)
{
proto_item *item = NULL;
char *sid_str = NULL;
guint8 type;
guint8 flags;
+ guint32 perms = 0;
if(parent_tree){
item = proto_tree_add_text(parent_tree, tvb, offset, -1,
/* access mask */
offset = dissect_nt_access_mask(
- tvb, offset, pinfo, tree, drep, hf_smb_access_mask, ami);
+ tvb, offset, pinfo, tree, drep,
+ hf_smb_access_mask, ami, &perms);
/* SID */
offset = dissect_nt_sid(tvb, offset, tree, "ACE", &sid_str, -1);
if (item)
proto_item_append_text(
- item, "%s, flags 0x%02x, %s", sid_str, flags,
- val_to_str(type, ace_type_vals, "Unknown ACE type (0x%02x)"));
+ item, "%s, flags 0x%02x, %s, mask 0x%08x", sid_str, flags,
+ val_to_str(type, ace_type_vals, "Unknown ACE type (0x%02x)"),
+ perms);
g_free(sid_str);
static int
dissect_nt_acl(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *parent_tree, char *drep, char *name,
+ proto_tree *parent_tree, guint8 *drep, char *name,
struct access_mask_info *ami)
{
proto_item *item = NULL;
int
dissect_nt_sec_desc(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *parent_tree, char *drep, int len,
+ proto_tree *parent_tree, guint8 *drep, int len,
struct access_mask_info *ami)
{
proto_item *item = NULL;
return offset;
}
+/* Set File Rename Info */
+
+static const true_false_string tfs_smb_replace = {
+ "Remove target file if it exists",
+ "Do NOT remove target file if it exists",
+};
+
+static int
+dissect_rename_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
+ int offset, guint16 *bcp, gboolean *trunc)
+{
+ smb_info_t *si = pinfo->private_data;
+ const char *fn;
+ guint32 target_name_len;
+ int fn_len;
+
+ /* Replace flag */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_replace, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* Root directory handle */
+ CHECK_BYTE_COUNT_SUBR(4);
+ proto_tree_add_item(tree, hf_smb_root_dir_handle, tvb, offset, 4, TRUE);
+ COUNT_BYTES_SUBR(4);
+
+ /* Target name length */
+ CHECK_BYTE_COUNT_SUBR(4);
+ target_name_len = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_target_name_len, tvb, offset, 4, target_name_len);
+ COUNT_BYTES_SUBR(4);
+
+ /* Target name */
+ fn_len = target_name_len;
+ fn = get_unicode_or_ascii_string(
+ tvb, &offset, si->unicode, &fn_len, FALSE, TRUE, bcp);
+
+ CHECK_STRING_SUBR(fn);
+ proto_tree_add_string(
+ tree, hf_smb_target_name, tvb, offset, fn_len, fn);
+ COUNT_BYTES_SUBR(fn_len);
+
+ *trunc = FALSE;
+ return offset;
+}
+
/*dissect the data block for TRANS2_QUERY_PATH_INFORMATION and
TRANS2_QUERY_FILE_INFORMATION*/
static int
&trunc);
break;
case 0x0101: /*Set File Basic Info*/
+ case 1004: /* SMB_FILE_BASIC_INFORMATION */
offset = dissect_4_2_16_4(tvb, pinfo, tree, offset, bcp,
&trunc);
break;
offset = dissect_4_2_16_13(tvb, pinfo, tree, offset, bcp,
&trunc);
break;
- case 1004:
- offset = dissect_4_2_16_4(tvb, pinfo, tree, offset, bcp,
+ case 1010: /* Set File Rename */
+ offset = dissect_rename_info(tvb, pinfo, tree, offset, bcp,
&trunc);
break;
- case 1010:
case 1013:
case 1014:
case 1016:
proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 1, TRUE);
COUNT_BYTES_SUBR(1);
- /* short file name */
+ /* short file name - it's not always in Unicode */
sfn = get_unicode_or_ascii_string(tvb, &offset, si->unicode, &sfn_len, FALSE, TRUE, bcp);
CHECK_STRING_SUBR(sfn);
proto_tree_add_string(tree, hf_smb_short_file_name, tvb, offset, 24,
e_uuid_t fs_id;
char uuid_str[DCERPC_UUID_STR_LEN];
int uuid_str_len;
- char drep = 0x10;
+ guint8 drep = 0x10;
CHECK_BYTE_COUNT_TRANS_SUBR(16);
{ "End Of File", "smb.end_of_file", FT_UINT64, BASE_DEC,
NULL, 0, "Offset to the first free byte in the file", HFILL }},
+ { &hf_smb_replace,
+ { "Replace", "smb.replace", FT_BOOLEAN, BASE_NONE,
+ TFS(&tfs_smb_replace), 0x0, "Remove target if it exists?", HFILL }},
+
+ { &hf_smb_root_dir_handle,
+ { "Root Directory Handle", "smb.root_dir_handle", FT_UINT32, BASE_HEX,
+ NULL, 0, "Root directory handle", HFILL }},
+
+ { &hf_smb_target_name_len,
+ { "Target name length", "smb.target_name_len", FT_UINT32, BASE_DEC,
+ NULL, 0, "Length of target file name", HFILL }},
+
+ { &hf_smb_target_name,
+ { "Target name", "smb.target_name", FT_STRING, BASE_NONE,
+ NULL, 0, "Target file name", HFILL }},
+
{ &hf_smb_device_type,
{ "Device Type", "smb.device.type", FT_UINT32, BASE_HEX,
VALS(device_type_vals), 0, "Type of device", HFILL }},