* Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
* 2001 Rewrite by Ronnie Sahlberg and Guy Harris
*
- * $Id: packet-smb.c,v 1.301 2002/12/19 11:22:37 sahlberg Exp $
+ * $Id: packet-smb.c,v 1.310 2003/02/25 02:00:32 tpot Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
#include <epan/strutil.h>
#include "prefs.h"
#include "reassemble.h"
+#include "tap.h"
#include "packet-smb-common.h"
#include "packet-smb-mailslot.h"
#include "packet-smb-pipe.h"
+#include "packet-dcerpc.h"
/*
* Various specifications and documents about SMB can be found in
static gint ett_smb_quotaflags = -1;
static gint ett_smb_secblob = -1;
+
+static int smb_tap = -1;
+
static dissector_handle_t gssapi_handle = NULL;
static dissector_handle_t ntlmssp_handle = NULL;
return key->frame + key->pid_mid;
}
-/*
- * The information we need to save about an NT Transaction request in order
- * to dissect the reply.
- */
-typedef struct {
- int subcmd;
-} smb_nt_transact_info_t;
-
static GMemChunk *smb_nt_transact_info_chunk = NULL;
static int smb_nt_transact_info_init_count = 200;
-/*
- * The information we need to save about a Transaction2 request in order
- * to dissect the reply.
- */
-typedef struct {
- int subcmd;
- int info_level;
- gboolean resume_keys; /* if "return resume" keys set in T2 FIND_FIRST request */
-} smb_transact2_info_t;
-
static GMemChunk *smb_transact2_info_chunk = NULL;
static int smb_transact2_info_init_count = 200;
#define NT_TRANS_QSD 6
#define NT_TRANS_GET_USER_QUOTA 7
#define NT_TRANS_SET_USER_QUOTA 8
-static const value_string nt_cmd_vals[] = {
+const value_string nt_cmd_vals[] = {
{NT_TRANS_CREATE, "NT CREATE"},
{NT_TRANS_IOCTL, "NT IOCTL"},
{NT_TRANS_SSD, "NT SET SECURITY DESC"},
return offset;
}
+/* FIXME: need to call dissect_nt_access_mask() instead */
static int
-dissect_nt_access_mask(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
+dissect_smb_access_mask(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
{
guint32 mask;
proto_item *item = NULL;
g_string_free(arg, TRUE);
}
+/* Dissect a NT SID. Label it with 'name' and return a string version of
+ the SID in the 'sid_str' parameter which must be freed by the caller. */
+
int
-dissect_nt_sid(tvbuff_t *tvb, int offset, proto_tree *parent_tree, char *name)
+dissect_nt_sid(tvbuff_t *tvb, int offset, proto_tree *parent_tree, char *name,
+ char **sid_str)
{
proto_item *item = NULL;
proto_tree *tree = NULL;
proto_tree_add_text(tree, tvb, offset, 4, "RID: %u", rid);
proto_item_append_text(item, ": S-1-%u-%s-%u", auth, gstr->str, rid);
offset+=4;
+ if (sid_str)
+ *sid_str = g_strdup_printf(
+ "S-1-%u-%s-%u", auth, gstr->str, rid);
}
else {
proto_item_append_text(item, ": S-1-%u-%s", auth, gstr->str);
+ if (sid_str)
+ *sid_str = g_strdup_printf("S-1-%u-%s", auth, gstr->str);
}
CLEANUP_CALL_AND_POP;
-
}
proto_item_set_len(item, offset-old_offset);
}
static int
-dissect_nt_v2_ace_flags(tvbuff_t *tvb, int offset, proto_tree *parent_tree)
+dissect_nt_v2_ace_flags(tvbuff_t *tvb, int offset, proto_tree *parent_tree,
+ guint8 *data)
{
proto_item *item = NULL;
proto_tree *tree = NULL;
char *sep = " ";
mask = tvb_get_guint8(tvb, offset);
+
+ if (data)
+ *data = mask;
+
+
if(parent_tree){
item = proto_tree_add_text(parent_tree, tvb, offset, 1,
"NT ACE Flags: 0x%02x", mask);
return offset;
}
+/* Dissect an access mask. All this stuff is kind of explained at MSDN:
+
+http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/windows_2000_windows_nt_access_mask_format.asp
+
+*/
+
+static gint ett_nt_access_mask = -1;
+static gint ett_nt_access_mask_generic = -1;
+static gint ett_nt_access_mask_standard = -1;
+static gint ett_nt_access_mask_specific = -1;
+
+static int hf_access_sacl = -1;
+static int hf_access_maximum_allowed = -1;
+static int hf_access_generic_read = -1;
+static int hf_access_generic_write = -1;
+static int hf_access_generic_execute = -1;
+static int hf_access_generic_all = -1;
+static int hf_access_standard_delete = -1;
+static int hf_access_standard_read_control = -1;
+static int hf_access_standard_synchronise = -1;
+static int hf_access_standard_write_dac = -1;
+static int hf_access_standard_write_owner = -1;
+static int hf_access_specific_15 = -1;
+static int hf_access_specific_14 = -1;
+static int hf_access_specific_13 = -1;
+static int hf_access_specific_12 = -1;
+static int hf_access_specific_11 = -1;
+static int hf_access_specific_10 = -1;
+static int hf_access_specific_9 = -1;
+static int hf_access_specific_8 = -1;
+static int hf_access_specific_7 = -1;
+static int hf_access_specific_6 = -1;
+static int hf_access_specific_5 = -1;
+static int hf_access_specific_4 = -1;
+static int hf_access_specific_3 = -1;
+static int hf_access_specific_2 = -1;
+static int hf_access_specific_1 = -1;
+static int hf_access_specific_0 = -1;
+
+int
+dissect_nt_access_mask(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+ proto_tree *tree, char *drep, int hfindex,
+ nt_access_mask_fn_t *specific_rights_fn)
+{
+ proto_item *item;
+ proto_tree *subtree, *generic, *standard, *specific;
+ guint32 access;
+
+ if (drep != NULL) {
+ /*
+ * Called from a DCE RPC protocol dissector, for a
+ * protocol where a 32-bit NDR integer contains
+ * an NT access mask; extract the access mask
+ * with an NDR call.
+ */
+ offset = dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
+ hfindex, &access);
+ } else {
+ /*
+ * Called from SMB, where the access mask is just a
+ * 4-byte little-endian quantity with no special
+ * NDR alignment requirement; extract it with
+ * "tvb_get_letohl()".
+ */
+ access = tvb_get_letohl(tvb, offset);
+ offset += 4;
+ }
+
+ item = proto_tree_add_uint(tree, hfindex, tvb, offset - 4, 4, access);
+
+ subtree = proto_item_add_subtree(item, ett_nt_access_mask);
+
+ /* Generic access rights */
+
+ item = proto_tree_add_text(subtree, tvb, offset - 4, 4,
+ "Generic rights: 0x%08x",
+ access & GENERIC_RIGHTS_MASK);
+
+ generic = proto_item_add_subtree(item, ett_nt_access_mask_generic);
+
+ proto_tree_add_boolean(
+ generic, hf_access_generic_read, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ generic, hf_access_generic_write, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ generic, hf_access_generic_execute, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ generic, hf_access_generic_all, tvb, offset - 4, 4,
+ access);
+
+ /* Reserved (??) */
+
+ proto_tree_add_boolean(
+ subtree, hf_access_maximum_allowed, tvb, offset - 4, 4,
+ access);
+
+ /* Access system security */
+
+ proto_tree_add_boolean(
+ subtree, hf_access_sacl, tvb, offset - 4, 4,
+ access);
+
+ /* Standard access rights */
+
+ item = proto_tree_add_text(subtree, tvb, offset - 4, 4,
+ "Standard rights: 0x%08x",
+ access & STANDARD_RIGHTS_MASK);
+
+ standard = proto_item_add_subtree(item, ett_nt_access_mask_standard);
+
+ proto_tree_add_boolean(
+ standard, hf_access_standard_synchronise, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ standard, hf_access_standard_write_owner, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ standard, hf_access_standard_write_dac, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ standard, hf_access_standard_read_control, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ standard, hf_access_standard_delete, tvb, offset - 4, 4,
+ access);
+
+ /* Specific access rights. Call the specific_rights_fn
+ pointer if we have one, otherwise just display bits 0-15 in
+ boring fashion. */
+
+ item = proto_tree_add_text(subtree, tvb, offset - 4, 4,
+ "Specific rights: 0x%08x",
+ access & SPECIFIC_RIGHTS_MASK);
+
+ specific = proto_item_add_subtree(item, ett_nt_access_mask_specific);
+
+ if (specific_rights_fn) {
+ specific_rights_fn(tvb, offset - 4, specific, access);
+ return offset;
+ }
+
+ proto_tree_add_boolean(
+ specific, hf_access_specific_15, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific, hf_access_specific_14, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific, hf_access_specific_13, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific, hf_access_specific_12, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific, hf_access_specific_11, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific, hf_access_specific_10, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific, hf_access_specific_9, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific, hf_access_specific_8, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific, hf_access_specific_7, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific, hf_access_specific_6, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific, hf_access_specific_5, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific, hf_access_specific_4, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific, hf_access_specific_3, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific, hf_access_specific_2, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific, hf_access_specific_1, tvb, offset - 4, 4,
+ access);
+
+ proto_tree_add_boolean(
+ specific, hf_access_specific_0, tvb, offset - 4, 4,
+ access);
+
+ return offset;
+}
+
+static int hf_smb_access_mask = -1;
+
static int
-dissect_nt_v2_ace(tvbuff_t *tvb, int offset, proto_tree *parent_tree)
+dissect_nt_v2_ace(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *parent_tree, char *drep,
+ nt_access_mask_fn_t *specific_rights_fn)
{
proto_item *item = NULL;
proto_tree *tree = NULL;
int old_offset = offset;
guint16 size;
+ char *sid_str;
+ guint8 type;
+ guint8 flags;
if(parent_tree){
item = proto_tree_add_text(parent_tree, tvb, offset, -1,
}
/* type */
- if(item){
- proto_item_append_text(item, val_to_str(tvb_get_guint8(tvb, offset), ace_type_vals, "Unknown ACE type (%u)"));
- }
- proto_tree_add_item(tree, hf_smb_ace_type, tvb, offset, 1, TRUE);
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_ace_type, tvb, offset, 1, type);
offset += 1;
/* flags */
- offset = dissect_nt_v2_ace_flags(tvb, offset, tree);
+ offset = dissect_nt_v2_ace_flags(tvb, offset, tree, &flags);
/* size */
size = tvb_get_letohs(tvb, offset);
offset += 2;
/* access mask */
- offset = dissect_nt_access_mask(tvb, tree, offset);
+ offset = dissect_nt_access_mask(
+ tvb, offset, pinfo, tree, drep, hf_smb_access_mask,
+ specific_rights_fn);
/* SID */
- offset = dissect_nt_sid(tvb, offset, tree, "ACE");
+ offset = dissect_nt_sid(tvb, offset, tree, "ACE", &sid_str);
+
+ 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)"));
+
+ g_free(sid_str);
proto_item_set_len(item, offset-old_offset);
}
static int
-dissect_nt_acl(tvbuff_t *tvb, int offset, proto_tree *parent_tree, char *name)
+dissect_nt_acl(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *parent_tree, char *drep, char *name,
+ nt_access_mask_fn_t *specific_rights_fn)
{
proto_item *item = NULL;
proto_tree *tree = NULL;
offset += 4;
while(num_aces--){
- offset=dissect_nt_v2_ace(tvb, offset, tree);
+ offset=dissect_nt_v2_ace(
+ tvb, offset, pinfo, tree, drep, specific_rights_fn);
}
}
}
int
-dissect_nt_sec_desc(tvbuff_t *tvb, int offset, proto_tree *parent_tree, int len)
+dissect_nt_sec_desc(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ proto_tree *parent_tree, char *drep, int len,
+ nt_access_mask_fn_t *specific_rights_fn)
{
proto_item *item = NULL;
proto_tree *tree = NULL;
/* offset to owner sid */
owner_sid_offset = tvb_get_letohl(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 4, "Offset to owner SID: %d", owner_sid_offset);
+ proto_tree_add_text(tree, tvb, offset, 4, "Offset to owner SID: %u", owner_sid_offset);
offset += 4;
/* offset to group sid */
group_sid_offset = tvb_get_letohl(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 4, "Offset to group SID: %d", group_sid_offset);
+ proto_tree_add_text(tree, tvb, offset, 4, "Offset to group SID: %u", group_sid_offset);
offset += 4;
/* offset to sacl */
sacl_offset = tvb_get_letohl(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 4, "Offset to SACL: %d", sacl_offset);
+ proto_tree_add_text(tree, tvb, offset, 4, "Offset to SACL: %u", sacl_offset);
offset += 4;
/* offset to dacl */
dacl_offset = tvb_get_letohl(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 4, "Offset to DACL: %d", dacl_offset);
+ proto_tree_add_text(tree, tvb, offset, 4, "Offset to DACL: %u", dacl_offset);
offset += 4;
/*owner SID*/
if(owner_sid_offset){
if (len == -1)
- offset = dissect_nt_sid(tvb, offset, tree, "Owner");
+ offset = dissect_nt_sid(tvb, offset, tree, "Owner", NULL);
else
- dissect_nt_sid(tvb, old_offset+owner_sid_offset, tree, "Owner");
+ dissect_nt_sid(
+ tvb, old_offset+owner_sid_offset, tree, "Owner", NULL);
}
/*group SID*/
if(group_sid_offset){
- dissect_nt_sid(tvb, old_offset+group_sid_offset, tree, "Group");
+ dissect_nt_sid(
+ tvb, old_offset+group_sid_offset, tree, "Group", NULL);
}
/* sacl */
if(sacl_offset){
- dissect_nt_acl(tvb, old_offset+sacl_offset, tree, "System (SACL)");
+ dissect_nt_acl(tvb, old_offset+sacl_offset, pinfo, tree,
+ drep, "System (SACL)", specific_rights_fn);
}
/* dacl */
if(dacl_offset){
- dissect_nt_acl(tvb, old_offset+dacl_offset, tree, "User (DACL)");
+ dissect_nt_acl(tvb, old_offset+dacl_offset, pinfo, tree,
+ drep, "User (DACL)", specific_rights_fn);
}
}
/* SID of the user */
old_sid_offset=offset;
- offset = dissect_nt_sid(tvb, offset, tree, "Quota");
+ offset = dissect_nt_sid(tvb, offset, tree, "Quota", NULL);
*bcp -= (offset-old_sid_offset);
if(qsize){
case NT_TRANS_CREATE:
/* security descriptor */
if(ntd->sd_len){
- offset = dissect_nt_sec_desc(tvb, offset, tree, ntd->sd_len);
+ offset = dissect_nt_sec_desc(
+ tvb, offset, pinfo, tree, NULL, ntd->sd_len,
+ NULL);
}
/* extended attributes */
break;
case NT_TRANS_SSD:
- offset = dissect_nt_sec_desc(tvb, offset, tree, bc);
+ offset = dissect_nt_sec_desc(
+ tvb, offset, pinfo, tree, NULL, bc, NULL);
break;
case NT_TRANS_NOTIFY:
break;
proto_tree_add_text(tree, tvb, offset, 4, "Length of SID: %d", tvb_get_letohl(tvb, offset));
offset +=4;
- offset = dissect_nt_sid(tvb, offset, tree, "Quota");
+ offset = dissect_nt_sid(tvb, offset, tree, "Quota", NULL);
break;
case NT_TRANS_SET_USER_QUOTA:
offset = dissect_nt_user_quota(tvb, tree, offset, &bcp);
COUNT_BYTES(4);
/* nt access mask */
- offset = dissect_nt_access_mask(tvb, tree, offset);
+ offset = dissect_smb_access_mask(tvb, tree, offset);
bc -= 4;
/* allocation size */
}
if(dc){
CHECK_BYTE_COUNT(dc);
- dissect_nt_trans_data_request(tvb, pinfo, offset, tree, dc, &ntd);
+ dissect_nt_trans_data_request(
+ tvb, pinfo, offset, tree, dc, &ntd);
COUNT_BYTES(dc);
}
case NT_TRANS_RENAME:
/* XXX not documented */
break;
- case NT_TRANS_QSD:
+ case NT_TRANS_QSD: {
/*
* XXX - this is probably a SECURITY_DESCRIPTOR structure,
* which may be documented in the Win32 documentation
* somewhere.
*/
- offset = dissect_nt_sec_desc(tvb, offset, tree, len);
+ offset = dissect_nt_sec_desc(
+ tvb, offset, pinfo, tree, NULL, len, NULL);
break;
+ }
case NT_TRANS_GET_USER_QUOTA:
bcp=len;
offset = dissect_nt_user_quota(tvb, tree, offset, &bcp);
offset += 4;
/* nt access mask */
- offset = dissect_nt_access_mask(tvb, tree, offset);
+ offset = dissect_smb_access_mask(tvb, tree, offset);
/* allocation size */
proto_tree_add_item(tree, hf_smb_alloc_size64, tvb, offset, 8, TRUE);
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
-static const value_string trans2_cmd_vals[] = {
+const value_string trans2_cmd_vals[] = {
{ 0x00, "OPEN2" },
{ 0x01, "FIND_FIRST2" },
{ 0x02, "FIND_NEXT2" },
COUNT_BYTES_SUBR(4);
/* delete pending */
- CHECK_BYTE_COUNT_SUBR(2);
- proto_tree_add_item(tree, hf_smb_delete_pending, tvb, offset, 2, TRUE);
- COUNT_BYTES_SUBR(2);
+ CHECK_BYTE_COUNT_SUBR(1);
+ proto_tree_add_item(tree, hf_smb_delete_pending, tvb, offset, 1, TRUE);
+ COUNT_BYTES_SUBR(1);
/* is directory */
CHECK_BYTE_COUNT_SUBR(1);
/* access flags */
CHECK_BYTE_COUNT_SUBR(4);
- offset = dissect_nt_access_mask(tvb, tree, offset);
+ offset = dissect_smb_access_mask(tvb, tree, offset);
COUNT_BYTES_SUBR(4);
/* index number */
* 1, contain all entries 0x00 to 0xff
* 2, all entries must be in order.
*/
-static const value_string smb_cmd_vals[] = {
+const value_string smb_cmd_vals[] = {
{ 0x00, "Create Directory" },
{ 0x01, "Delete Directory" },
{ 0x02, "Open" },
{SMBE_invalidsecuritydescriptor, "Invalid security descriptor"},
{SMBE_invalidowner, "Invalid owner"},
{SMBE_nomoreitems, "No more items"},
+ {SMBE_serverunavailable, "Server unavailable"},
{0, NULL}
};
proto_tree *tree = NULL, *htree = NULL;
guint8 flags;
guint16 flags2;
- smb_info_t si;
+ static smb_info_t si_arr[20];
+ static int si_counter=0;
+ smb_info_t *si;
smb_saved_info_t *sip = NULL;
smb_saved_info_key_t key;
smb_saved_info_key_t *new_key;
conversation_t *conversation;
nstime_t ns;
+ si_counter++;
+ if(si_counter==20){
+ si_counter=0;
+ }
+ si=&si_arr[si_counter];
+
top_tree=parent_tree;
/* must check that this really is a smb packet */
/* start off using the local variable, we will allocate a new one if we
need to*/
- si.cmd = tvb_get_guint8(tvb, offset+4);
+ si->cmd = tvb_get_guint8(tvb, offset+4);
flags = tvb_get_guint8(tvb, offset+9);
- si.request = !(flags&SMB_FLAGS_DIRN);
+ si->request = !(flags&SMB_FLAGS_DIRN);
flags2 = tvb_get_letohs(tvb, offset+10);
if(flags2 & 0x8000){
- si.unicode = TRUE; /* Mark them as Unicode */
+ si->unicode = TRUE; /* Mark them as Unicode */
} else {
- si.unicode = FALSE;
+ si->unicode = FALSE;
}
- si.tid = tvb_get_letohs(tvb, offset+24);
- si.pid = tvb_get_letohs(tvb, offset+26);
- si.uid = tvb_get_letohs(tvb, offset+28);
- si.mid = tvb_get_letohs(tvb, offset+30);
- pid_mid = (si.pid << 16) | si.mid;
- si.info_level = -1;
- si.info_count = -1;
+ si->tid = tvb_get_letohs(tvb, offset+24);
+ si->pid = tvb_get_letohs(tvb, offset+26);
+ si->uid = tvb_get_letohs(tvb, offset+28);
+ si->mid = tvb_get_letohs(tvb, offset+30);
+ pid_mid = (si->pid << 16) | si->mid;
+ si->info_level = -1;
+ si->info_count = -1;
if (parent_tree) {
item = proto_tree_add_item(parent_tree, proto_smb, tvb, offset,
pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
}
/* see if we already have the smb data for this conversation */
- si.ct=conversation_get_proto_data(conversation, proto_smb);
- if(!si.ct){
+ si->ct=conversation_get_proto_data(conversation, proto_smb);
+ if(!si->ct){
/* No, not yet. create it and attach it to the conversation */
- si.ct = g_mem_chunk_alloc(conv_tables_chunk);
- conv_tables = g_slist_prepend(conv_tables, si.ct);
- si.ct->matched= g_hash_table_new(smb_saved_info_hash_matched,
+ si->ct = g_mem_chunk_alloc(conv_tables_chunk);
+ conv_tables = g_slist_prepend(conv_tables, si->ct);
+ si->ct->matched= g_hash_table_new(smb_saved_info_hash_matched,
smb_saved_info_equal_matched);
- si.ct->unmatched= g_hash_table_new(smb_saved_info_hash_unmatched,
+ si->ct->unmatched= g_hash_table_new(smb_saved_info_hash_unmatched,
smb_saved_info_equal_unmatched);
- si.ct->dcerpc_fid_to_frame=g_hash_table_new(
+ si->ct->dcerpc_fid_to_frame=g_hash_table_new(
smb_saved_info_hash_unmatched,
smb_saved_info_equal_unmatched);
- si.ct->tid_service=g_hash_table_new(
+ si->ct->tid_service=g_hash_table_new(
smb_saved_info_hash_unmatched,
smb_saved_info_equal_unmatched);
- conversation_add_proto_data(conversation, proto_smb, si.ct);
+ conversation_add_proto_data(conversation, proto_smb, si->ct);
}
- if( (si.request)
- && (si.mid==0)
- && (si.uid==0)
- && (si.pid==0)
- && (si.tid==0) ){
+ if( (si->request)
+ && (si->mid==0)
+ && (si->uid==0)
+ && (si->pid==0)
+ && (si->tid==0) ){
/* this is a broadcast SMB packet, there will not be a reply.
We dont need to do anything
*/
- si.unidir = TRUE;
- } else if( (si.cmd==SMB_COM_NT_CANCEL) /* NT Cancel */
- ||(si.cmd==SMB_COM_TRANSACTION_SECONDARY) /* Transaction Secondary */
- ||(si.cmd==SMB_COM_TRANSACTION2_SECONDARY) /* Transaction2 Secondary */
- ||(si.cmd==SMB_COM_NT_TRANSACT_SECONDARY)){ /* NT Transaction Secondary */
+ si->unidir = TRUE;
+ } else if( (si->cmd==SMB_COM_NT_CANCEL) /* NT Cancel */
+ ||(si->cmd==SMB_COM_TRANSACTION_SECONDARY) /* Transaction Secondary */
+ ||(si->cmd==SMB_COM_TRANSACTION2_SECONDARY) /* Transaction2 Secondary */
+ ||(si->cmd==SMB_COM_NT_TRANSACT_SECONDARY)){ /* NT Transaction Secondary */
/* Ok, we got a special request type. This request is either
an NT Cancel or a continuation relative to a real request
in an earlier packet. In either case, we don't expect any
in it.
*/
- si.unidir = TRUE; /*we dont expect an answer to this one*/
+ si->unidir = TRUE; /*we dont expect an answer to this one*/
if(!pinfo->fd->flags.visited){
/* try to find which original call we match and if we
last seen MID matching ours is the right one.
This can fail but is better than nothing
*/
- sip=g_hash_table_lookup(si.ct->unmatched, (void *)pid_mid);
+ sip=g_hash_table_lookup(si->ct->unmatched, (void *)pid_mid);
if(sip!=NULL){
new_key = g_mem_chunk_alloc(smb_saved_info_key_chunk);
new_key->frame = pinfo->fd->num;
new_key->pid_mid = pid_mid;
- g_hash_table_insert(si.ct->matched, new_key,
+ g_hash_table_insert(si->ct->matched, new_key,
sip);
}
} else {
*/
key.frame = pinfo->fd->num;
key.pid_mid = pid_mid;
- sip=g_hash_table_lookup(si.ct->matched, &key);
+ sip=g_hash_table_lookup(si->ct->matched, &key);
if(sip==NULL){
/*
We didn't find it.
if(sip && sip->frame_req){
- switch(si.cmd){
+ switch(si->cmd){
case SMB_COM_NT_CANCEL:
proto_tree_add_uint(htree, hf_smb_cancel_to,
tvb, 0, 0, sip->frame_req);
break;
}
} else {
- switch(si.cmd){
+ switch(si->cmd){
case SMB_COM_NT_CANCEL:
proto_tree_add_text(htree, tvb, 0, 0,
"Cancellation to: <unknown frame>");
}
}
} else { /* normal bidirectional request or response */
- si.unidir = FALSE;
+ si->unidir = FALSE;
if(!pinfo->fd->flags.visited){
/* first see if we find an unmatched smb "equal" to
the current one
*/
- sip=g_hash_table_lookup(si.ct->unmatched, (void *)pid_mid);
+ sip=g_hash_table_lookup(si->ct->unmatched, (void *)pid_mid);
if(sip!=NULL){
gboolean cmd_match=FALSE;
* that's another valid type of reply
* to that command.
*/
- if(si.cmd==sip->cmd){
+ if(si->cmd==sip->cmd){
cmd_match=TRUE;
}
- else if(si.cmd==SMB_COM_NT_CANCEL){
+ else if(si->cmd==SMB_COM_NT_CANCEL){
cmd_match=TRUE;
}
- else if((si.cmd==SMB_COM_TRANSACTION_SECONDARY)
+ else if((si->cmd==SMB_COM_TRANSACTION_SECONDARY)
&& (sip->cmd==SMB_COM_TRANSACTION)){
cmd_match=TRUE;
}
- else if((si.cmd==SMB_COM_TRANSACTION2_SECONDARY)
+ else if((si->cmd==SMB_COM_TRANSACTION2_SECONDARY)
&& (sip->cmd==SMB_COM_TRANSACTION2)){
cmd_match=TRUE;
}
- else if((si.cmd==SMB_COM_NT_TRANSACT_SECONDARY)
+ else if((si->cmd==SMB_COM_NT_TRANSACT_SECONDARY)
&& (sip->cmd==SMB_COM_NT_TRANSACT)){
cmd_match=TRUE;
}
- if( (si.request) || (!cmd_match) ) {
+ if( (si->request) || (!cmd_match) ) {
/* If we are processing an SMB request but there was already
another "identical" smb resuest we had not matched yet.
This must mean that either we have a retransmission or that the
SMBs of different cmds but with identical MID and PID values and
if ethereal lost the first reply and the second request.
*/
- g_hash_table_remove(si.ct->unmatched, (void *)pid_mid);
+ g_hash_table_remove(si->ct->unmatched, (void *)pid_mid);
sip=NULL; /* XXX should free it as well */
} else {
/* we have found a response to some request we have seen earlier.
new_key = g_mem_chunk_alloc(smb_saved_info_key_chunk);
new_key->frame = sip->frame_res;
new_key->pid_mid = pid_mid;
- g_hash_table_insert(si.ct->matched, new_key, sip);
+ g_hash_table_insert(si->ct->matched, new_key, sip);
} else {
/* we have already seen another response to this one, but
register it anyway so we see which request it matches
new_key = g_mem_chunk_alloc(smb_saved_info_key_chunk);
new_key->frame = pinfo->fd->num;
new_key->pid_mid = pid_mid;
- g_hash_table_insert(si.ct->matched, new_key, sip);
+ g_hash_table_insert(si->ct->matched, new_key, sip);
}
}
}
- if(si.request){
+ if(si->request){
sip = g_mem_chunk_alloc(smb_saved_info_chunk);
sip->frame_req = pinfo->fd->num;
sip->frame_res = 0;
sip->req_time.secs=pinfo->fd->abs_secs;
sip->req_time.nsecs=pinfo->fd->abs_usecs*1000;
sip->flags = 0;
- if(g_hash_table_lookup(si.ct->tid_service, (void *)si.tid)
+ if(g_hash_table_lookup(si->ct->tid_service, (void *)si->tid)
== (void *)TID_IPC) {
sip->flags |= SMB_SIF_TID_IS_IPC;
}
- sip->cmd = si.cmd;
+ sip->cmd = si->cmd;
sip->extra_info = NULL;
- g_hash_table_insert(si.ct->unmatched, (void *)pid_mid, sip);
+ g_hash_table_insert(si->ct->unmatched, (void *)pid_mid, sip);
new_key = g_mem_chunk_alloc(smb_saved_info_key_chunk);
new_key->frame = sip->frame_req;
new_key->pid_mid = pid_mid;
- g_hash_table_insert(si.ct->matched, new_key, sip);
+ g_hash_table_insert(si->ct->matched, new_key, sip);
}
} else {
/* we have seen this packet before; check the
*/
key.frame = pinfo->fd->num;
key.pid_mid = pid_mid;
- sip=g_hash_table_lookup(si.ct->matched, &key);
+ sip=g_hash_table_lookup(si->ct->matched, &key);
}
}
/*
* Pass the "sip" on to subdissectors through "si".
*/
- si.sip = sip;
+ si->sip = sip;
if (sip != NULL) {
/*
* this is a response or the frame with the response to this
* frame - if we know the frame number (i.e., it's not 0).
*/
- if(si.request){
+ if(si->request){
if (sip->frame_res != 0)
proto_tree_add_uint(htree, hf_smb_response_in, tvb, 0, 0, sip->frame_res);
} else {
}
/* smb command */
- proto_tree_add_uint_format(htree, hf_smb_cmd, tvb, offset, 1, si.cmd, "SMB Command: %s (0x%02x)", decode_smb_name(si.cmd), si.cmd);
+ proto_tree_add_uint_format(htree, hf_smb_cmd, tvb, offset, 1, si->cmd, "SMB Command: %s (0x%02x)", decode_smb_name(si->cmd), si->cmd);
offset += 1;
if(flags2 & 0x4000){
offset += 12;
/* TID */
- proto_tree_add_uint(htree, hf_smb_tid, tvb, offset, 2, si.tid);
+ proto_tree_add_uint(htree, hf_smb_tid, tvb, offset, 2, si->tid);
offset += 2;
/* PID */
- proto_tree_add_uint(htree, hf_smb_pid, tvb, offset, 2, si.pid);
+ proto_tree_add_uint(htree, hf_smb_pid, tvb, offset, 2, si->pid);
offset += 2;
/* UID */
- proto_tree_add_uint(htree, hf_smb_uid, tvb, offset, 2, si.uid);
+ proto_tree_add_uint(htree, hf_smb_uid, tvb, offset, 2, si->uid);
offset += 2;
/* MID */
- proto_tree_add_uint(htree, hf_smb_mid, tvb, offset, 2, si.mid);
+ proto_tree_add_uint(htree, hf_smb_mid, tvb, offset, 2, si->mid);
offset += 2;
- pinfo->private_data = &si;
- dissect_smb_command(tvb, pinfo, offset, tree, si.cmd, TRUE);
+ pinfo->private_data = si;
+ dissect_smb_command(tvb, pinfo, offset, tree, si->cmd, TRUE);
/* Append error info from this packet to info string. */
- if (!si.request && check_col(pinfo->cinfo, COL_INFO)) {
+ if (!si->request && check_col(pinfo->cinfo, COL_INFO)) {
if (flags2 & 0x4000) {
/*
* The status is an NT status code; was there
}
}
+ tap_queue_packet(smb_tap, pinfo, si);
return TRUE;
}
{ &hf_smb_segments,
{ "SMB Segments", "smb.segment.segments", FT_NONE, BASE_NONE, NULL, 0x0,
"SMB Segments", HFILL }},
+
+ /* Access masks */
+
+ { &hf_smb_access_mask,
+ { "Access required", "smb.access_mask",
+ FT_UINT32, BASE_HEX, NULL, 0x0, "Access mask",
+ HFILL }},
+ { &hf_access_generic_read,
+ { "Generic read", "nt.access_mask.generic_read",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ GENERIC_READ_ACCESS, "Generic read", HFILL }},
+
+ { &hf_access_generic_write,
+ { "Generic write", "nt.access_mask.generic_write",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ GENERIC_WRITE_ACCESS, "Generic write", HFILL }},
+
+ { &hf_access_generic_execute,
+ { "Generic execute", "nt.access_mask.generic_execute",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ GENERIC_EXECUTE_ACCESS, "Generic execute", HFILL }},
+
+ { &hf_access_generic_all,
+ { "Generic all", "nt.access_mask.generic_all",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ GENERIC_ALL_ACCESS, "Generic all", HFILL }},
+
+ { &hf_access_maximum_allowed,
+ { "Maximum allowed", "nt.access_mask.maximum_allowed",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ MAXIMUM_ALLOWED_ACCESS, "Maximum allowed", HFILL }},
+
+ { &hf_access_sacl,
+ { "Access SACL", "nt.access_mask.access_sacl",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ ACCESS_SACL_ACCESS, "Access SACL", HFILL }},
+
+ { &hf_access_standard_read_control,
+ { "Read control", "nt.access_mask.read_control",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ READ_CONTROL_ACCESS, "Read control", HFILL }},
+
+ { &hf_access_standard_delete,
+ { "Delete", "nt.access_mask.delete",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ DELETE_ACCESS, "Delete", HFILL }},
+
+ { &hf_access_standard_synchronise,
+ { "Synchronise", "nt.access_mask.synchronise",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ SYNCHRONIZE_ACCESS, "Synchronise", HFILL }},
+
+ { &hf_access_standard_write_dac,
+ { "Write DAC", "nt.access_mask.write_dac",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ WRITE_DAC_ACCESS, "Write DAC", HFILL }},
+
+ { &hf_access_standard_write_owner,
+ { "Write owner", "nt.access_mask.write_owner",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ WRITE_OWNER_ACCESS, "Write owner", HFILL }},
+
+ { &hf_access_specific_15,
+ { "Specific access, bit 15", "nt.access_mask.specific_15",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x8000, "Specific access, bit 15", HFILL }},
+
+ { &hf_access_specific_14,
+ { "Specific access, bit 14", "nt.access_mask.specific_14",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x4000, "Specific access, bit 14", HFILL }},
+
+ { &hf_access_specific_13,
+ { "Specific access, bit 13", "nt.access_mask.specific_13",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x2000, "Specific access, bit 13", HFILL }},
+
+ { &hf_access_specific_12,
+ { "Specific access, bit 12", "nt.access_mask.specific_12",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x1000, "Specific access, bit 12", HFILL }},
+
+ { &hf_access_specific_11,
+ { "Specific access, bit 11", "nt.access_mask.specific_11",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0800, "Specific access, bit 11", HFILL }},
+
+ { &hf_access_specific_10,
+ { "Specific access, bit 10", "nt.access_mask.specific_10",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0400, "Specific access, bit 10", HFILL }},
+
+ { &hf_access_specific_9,
+ { "Specific access, bit 9", "nt.access_mask.specific_9",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0200, "Specific access, bit 9", HFILL }},
+
+ { &hf_access_specific_8,
+ { "Specific access, bit 8", "nt.access_mask.specific_8",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0100, "Specific access, bit 8", HFILL }},
+
+ { &hf_access_specific_7,
+ { "Specific access, bit 7", "nt.access_mask.specific_7",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0080, "Specific access, bit 7", HFILL }},
+
+ { &hf_access_specific_6,
+ { "Specific access, bit 6", "nt.access_mask.specific_6",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0040, "Specific access, bit 6", HFILL }},
+
+ { &hf_access_specific_5,
+ { "Specific access, bit 5", "nt.access_mask.specific_5",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0020, "Specific access, bit 5", HFILL }},
+
+ { &hf_access_specific_4,
+ { "Specific access, bit 4", "nt.access_mask.specific_4",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0010, "Specific access, bit 4", HFILL }},
+
+ { &hf_access_specific_3,
+ { "Specific access, bit 3", "nt.access_mask.specific_3",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0008, "Specific access, bit 3", HFILL }},
+
+ { &hf_access_specific_2,
+ { "Specific access, bit 2", "nt.access_mask.specific_2",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0004, "Specific access, bit 2", HFILL }},
+
+ { &hf_access_specific_1,
+ { "Specific access, bit 1", "nt.access_mask.specific_1",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0002, "Specific access, bit 1", HFILL }},
+
+ { &hf_access_specific_0,
+ { "Specific access, bit 0", "nt.access_mask.specific_0",
+ FT_BOOLEAN, 32, TFS(&flags_set_truth),
+ 0x0001, "Specific access, bit 0", HFILL }},
};
static gint *ett[] = {
&ett_smb,
&ett_smb_quotaflags,
&ett_smb_secblob,
&ett_smb_mac_support_flags,
+ &ett_nt_access_mask,
+ &ett_nt_access_mask_generic,
+ &ett_nt_access_mask_standard,
+ &ett_nt_access_mask_specific,
};
module_t *smb_module;
&smb_dcerpc_reassembly);
register_init_routine(smb_trans_reassembly_init);
register_init_routine(smb_dcerpc_reassembly_init);
+ smb_tap = register_tap("smb");
}
void