Add the mask for an NT ACL ACE to the summary list for each ACE. This
[obnox/wireshark/wip.git] / packet-smb.c
index eec564cd9699fec5c27690363e281df46554508a..169946f29c08e8c1d5c32223e173ab2fecfc8b78 100644 (file)
@@ -3,7 +3,7 @@
  * 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>
@@ -40,7 +40,6 @@
 #include <epan/packet.h>
 #include <epan/conversation.h>
 #include "smb.h"
-#include "alignment.h"
 #include <epan/strutil.h>
 #include "prefs.h"
 #include "reassemble.h"
@@ -481,6 +480,10 @@ static int hf_smb_create_action = -1;
 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;
@@ -1255,8 +1258,8 @@ nt_time_to_nstime(guint32 filetime_high, guint32 filetime_low, nstime_t *tv)
        /*
         * 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;
 }
@@ -4743,7 +4746,7 @@ dissect_locking_andx_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *
                        proto_item *litem = NULL;
                        proto_tree *ltree = NULL;
                        if(lt&0x10){
-                               char buf[8];
+                               guint8 buf[8];
                                guint32 val;
 
                                /* large lock format */
@@ -4827,7 +4830,7 @@ dissect_locking_andx_request(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *
                        proto_item *litem = NULL;
                        proto_tree *ltree = NULL;
                        if(lt&0x10){
-                               char buf[8];
+                               guint8 buf[8];
                                guint32 val;
 
                                /* large lock format */
@@ -5567,16 +5570,30 @@ dissect_write_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
        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;
                }
@@ -5712,6 +5729,7 @@ dissect_session_setup_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree
        guint16 pwlen=0;
        guint16 sbloblen=0;
        guint16 apwlen=0, upwlen=0;
+       gboolean unicodeflag;
 
        WORD_COUNT;
 
@@ -5847,9 +5865,20 @@ dissect_session_setup_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree
                        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,
@@ -5862,9 +5891,20 @@ dissect_session_setup_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree
                 * 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,
@@ -7461,8 +7501,8 @@ static void map_standard_access(guint32 *access_mask,
 
 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;
@@ -7488,6 +7528,10 @@ dissect_nt_access_mask(tvbuff_t *tvb, gint offset, packet_info *pinfo,
                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);
@@ -7671,7 +7715,7 @@ static int hf_smb_access_mask = -1;
 
 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;
@@ -7681,6 +7725,7 @@ dissect_nt_v2_ace(tvbuff_t *tvb, int offset, packet_info *pinfo,
        char *sid_str = NULL;
        guint8 type;
        guint8 flags;
+       guint32 perms = 0;
 
        if(parent_tree){
                item = proto_tree_add_text(parent_tree, tvb, offset, -1,
@@ -7703,15 +7748,17 @@ dissect_nt_v2_ace(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
        /* 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);
 
@@ -7725,7 +7772,7 @@ dissect_nt_v2_ace(tvbuff_t *tvb, int offset, packet_info *pinfo,
 
 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;
@@ -7871,7 +7918,7 @@ dissect_nt_sec_desc_type(tvbuff_t *tvb, int offset, proto_tree *parent_tree)
 
 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;
@@ -11417,6 +11464,52 @@ dissect_4_2_19_4(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
        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
@@ -11530,6 +11623,7 @@ dissect_spi_loi_vals(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
                    &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;
@@ -11557,11 +11651,10 @@ dissect_spi_loi_vals(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
                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:
@@ -12805,7 +12898,7 @@ dissect_4_3_4_6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
        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,
@@ -13504,7 +13597,7 @@ dissect_qfsi_vals(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
                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);
 
@@ -18283,6 +18376,22 @@ proto_register_smb(void)
                { "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 }},