* Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
* 2001 Rewrite by Ronnie Sahlberg and Guy Harris
*
- * $Id: packet-smb.c,v 1.209 2002/02/21 18:39:49 tpot Exp $
+ * $Id: packet-smb.c,v 1.249 2002/04/24 07:19:25 tpot Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
static int hf_smb_fs_attr_vq = -1;
static int hf_smb_fs_attr_dim = -1;
static int hf_smb_fs_attr_vic = -1;
+static int hf_smb_quota_flags_enabled = -1;
+static int hf_smb_quota_flags_deny_disk = -1;
+static int hf_smb_quota_flags_log_limit = -1;
+static int hf_smb_quota_flags_log_warning = -1;
+static int hf_smb_soft_quota_limit = -1;
+static int hf_smb_hard_quota_limit = -1;
+static int hf_smb_user_quota_used = -1;
+static int hf_smb_user_quota_offset = -1;
+static int hf_smb_nt_rename_level = -1;
+static int hf_smb_cluster_count = -1;
static gint ett_smb = -1;
static gint ett_smb_hdr = -1;
static gint ett_smb_nt_share_access = -1;
static gint ett_smb_nt_security_flags = -1;
static gint ett_smb_nt_trans_setup = -1;
+static gint ett_smb_nt_trans_data = -1;
+static gint ett_smb_nt_trans_param = -1;
static gint ett_smb_nt_notify_completion_filter = -1;
static gint ett_smb_nt_ioctl_flags = -1;
static gint ett_smb_security_information_mask = -1;
static gint ett_smb_ace = -1;
static gint ett_smb_ace_flags = -1;
static gint ett_smb_sec_desc_type = -1;
+static gint ett_smb_quotaflags = -1;
proto_tree *top_tree=NULL; /* ugly */
guint32 filetime_high, filetime_low;
nstime_t ts;
+ /* XXX there seems also to be another special time value which is fairly common :
+ 0x40000000 00000000
+ the meaning of this one is yet unknown
+ */
if (tree) {
filetime_low = tvb_get_letohl(tvb, offset);
filetime_high = tvb_get_letohl(tvb, offset + 4);
proto_registrar_get_name(hf_date));
} else if(filetime_low==0 && filetime_high==0x80000000){
proto_tree_add_text(tree, tvb, offset, 8,
- "%s: Infinity (absolute time)",
+ "%s: Infinity (relative time)",
proto_registrar_get_name(hf_date));
} else if(filetime_low==0xffffffff && filetime_high==0x7fffffff){
proto_tree_add_text(tree, tvb, offset, 8,
- "%s: Infinity (relative time)",
+ "%s: Infinity (absolute time)",
proto_registrar_get_name(hf_date));
} else {
if (nt_time_to_nstime(filetime_high, filetime_low, &ts)) {
return offset;
}
+static int
+dissect_nt_rename_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
+{
+ int fn_len;
+ const char *fn;
+ guint8 wc;
+ guint16 bc;
+
+ WORD_COUNT;
+
+ /* search attributes */
+ offset = dissect_search_attributes(tvb, pinfo, tree, offset);
+
+ proto_tree_add_uint(tree, hf_smb_nt_rename_level, tvb, offset, 2, tvb_get_letohs(tvb, offset));
+ offset += 2;
+
+ proto_tree_add_item(tree, hf_smb_cluster_count, tvb, offset, 4, TRUE);
+ offset += 4;
+
+ BYTE_COUNT;
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* old file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
+ FALSE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_old_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Old Name: %s", fn);
+ }
+
+ /* buffer format */
+ CHECK_BYTE_COUNT(1);
+ proto_tree_add_item(tree, hf_smb_buffer_format, tvb, offset, 1, TRUE);
+ COUNT_BYTES(1);
+
+ /* file name */
+ fn = get_unicode_or_ascii_string(tvb, &offset, pinfo, &fn_len,
+ FALSE, FALSE, &bc);
+ if (fn == NULL)
+ goto endofcommand;
+ proto_tree_add_string(tree, hf_smb_file_name, tvb, offset, fn_len,
+ fn);
+ COUNT_BYTES(fn_len);
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", New Name: %s", fn);
+ }
+
+ END_OF_SMB
+
+ return offset;
+}
+
+
static int
dissect_query_information_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
{
dissect_read_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
{
guint8 wc;
- guint16 bc, fid;
+ guint16 bc;
+ smb_info_t *si;
+ unsigned int fid;
WORD_COUNT;
fid = tvb_get_letohs(tvb, offset);
add_fid(tvb, pinfo, tree, offset, 2, fid);
offset += 2;
+ if (!pinfo->fd->flags.visited) {
+ /* remember the FID for the processing of the response */
+ si = (smb_info_t *)pinfo->private_data;
+ si->sip->extra_info=(void *)fid;
+ }
/* read count */
proto_tree_add_item(tree, hf_smb_count, tvb, offset, 2, TRUE);
return offset;
}
+static int
+dissect_file_data_dcerpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+ proto_tree *top_tree, int offset, guint16 bc, guint16 datalen, guint16 fid)
+{
+ int tvblen;
+ tvbuff_t *dcerpc_tvb;
+
+ if(bc>datalen){
+ /* We have some initial padding bytes. */
+ /* XXX - use the data offset here instead? */
+ proto_tree_add_item(tree, hf_smb_padding, tvb, offset, bc-datalen,
+ TRUE);
+ offset += bc-datalen;
+ bc = datalen;
+ }
+ tvblen = tvb_length_remaining(tvb, offset);
+ dcerpc_tvb = tvb_new_subset(tvb, offset, tvblen, bc);
+ dissect_pipe_dcerpc(dcerpc_tvb, pinfo, top_tree, tree, fid);
+ if(bc>tvblen)
+ offset += tvblen;
+ else
+ offset += bc;
+ return offset;
+}
+
static int
dissect_read_file_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
{
guint16 cnt=0, bc;
guint8 wc;
+ smb_info_t *si = (smb_info_t *)pinfo->private_data;
+ int fid=0;
WORD_COUNT;
proto_tree_add_item(tree, hf_smb_reserved, tvb, offset, 8, TRUE);
offset += 8;
+ /* If we have seen the request, then print which FID this refers to */
+ /* first check if we have seen the request */
+ if(si->sip != NULL && si->sip->frame_req>0){
+ fid=(int)si->sip->extra_info;
+ add_fid(tvb, pinfo, tree, 0, 0, fid);
+ }
+
BYTE_COUNT;
/* buffer format */
proto_tree_add_item(tree, hf_smb_data_len, tvb, offset, 2, TRUE);
COUNT_BYTES(2);
- if (bc != 0) {
- /* file data */
- offset = dissect_file_data(tvb, pinfo, tree, offset, bc, bc);
+ /* another way to transport DCERPC over SMB is to skip Transaction completely and just
+ read write */
+ if(bc){
+ if(si->sip != NULL && si->sip->flags&SMB_SIF_TID_IS_IPC){
+ /* dcerpc call */
+ offset = dissect_file_data_dcerpc(tvb, pinfo, tree,
+ top_tree, offset, bc, bc, fid);
+ } else {
+ /* ordinary file data, or we didn't see the request,
+ so we don't know whether this is a DCERPC call
+ or not */
+ offset = dissect_file_data(tvb, pinfo, tree, offset, bc, bc);
+ }
bc = 0;
}
dissect_write_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
{
guint32 ofs=0;
- guint16 cnt=0, bc, fid;
+ guint16 cnt=0, bc, fid=0;
guint8 wc;
+ smb_info_t *si = (smb_info_t *)pinfo->private_data;
WORD_COUNT;
proto_tree_add_item(tree, hf_smb_data_len, tvb, offset, 2, TRUE);
COUNT_BYTES(2);
- if (check_col(pinfo->cinfo, COL_INFO))
- col_append_fstr(pinfo->cinfo, COL_INFO,
- ", %d byte%s at offset %d", cnt,
- (cnt == 1) ? "" : "s", ofs);
-
if (bc != 0) {
- /* file data */
- offset = dissect_file_data(tvb, pinfo, tree, offset, bc, bc);
+ if( (si->sip && si->sip->flags&SMB_SIF_TID_IS_IPC) && (ofs==0) ){
+ /* dcerpc call */
+ offset = dissect_file_data_dcerpc(tvb, pinfo, tree,
+ top_tree, offset, bc, bc, fid);
+ } else {
+ /* ordinary file data */
+ offset = dissect_file_data(tvb, pinfo, tree, offset, bc, bc);
+ }
bc = 0;
}
guint8 wc, cmd=0xff;
guint16 andxoffset=0, bc, datalen=0, dataoffset=0;
smb_info_t *si = (smb_info_t *)pinfo->private_data;
+ int fid=0;
WORD_COUNT;
/* If we have seen the request, then print which FID this refers to */
/* first check if we have seen the request */
if(si->sip != NULL && si->sip->frame_req>0){
- add_fid(tvb, pinfo, tree, 0, 0, (int)si->sip->extra_info);
+ fid=(int)si->sip->extra_info;
+ add_fid(tvb, pinfo, tree, 0, 0, fid);
}
/* remaining */
}
}
- /* file data */
- offset = dissect_file_data(tvb, pinfo, tree, offset, bc, datalen);
- bc = 0;
+ /* another way to transport DCERPC over SMB is to skip Transaction completely and just
+ read write */
+ if(bc){
+ if(si->sip != NULL && si->sip->flags&SMB_SIF_TID_IS_IPC){
+ /* dcerpc call */
+ offset = dissect_file_data_dcerpc(tvb, pinfo, tree,
+ top_tree, offset, bc, datalen, fid);
+ } else {
+ /* ordinary file data, or we didn't see the request,
+ so we don't know whether this is a DCERPC call
+ or not */
+ offset = dissect_file_data(tvb, pinfo, tree, offset, bc, datalen);
+ }
+ bc = 0;
+ }
END_OF_SMB
static int
dissect_write_andx_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree)
{
+ guint32 ofs=0;
guint8 wc, cmd=0xff;
guint16 andxoffset=0, bc, datalen=0, dataoffset=0;
smb_info_t *si = (smb_info_t *)pinfo->private_data;
- unsigned int fid;
+ unsigned int fid=0;
WORD_COUNT;
}
/* offset */
+ ofs = tvb_get_letohl(tvb, offset);
proto_tree_add_item(tree, hf_smb_offset, tvb, offset, 4, TRUE);
offset += 4;
}
/* file data */
- offset = dissect_file_data(tvb, pinfo, tree, offset, bc, datalen);
- bc = 0;
+ if (bc != 0) {
+ if( (si->sip && si->sip->flags&SMB_SIF_TID_IS_IPC) && (ofs==0) ){
+ /* dcerpc call */
+ offset = dissect_file_data_dcerpc(tvb, pinfo, tree,
+ top_tree, offset, bc, datalen, fid);
+ } else {
+ /* ordinary file data */
+ offset = dissect_file_data(tvb, pinfo, tree, offset,
+ bc, datalen);
+ }
+ bc = 0;
+ }
END_OF_SMB
COUNT_BYTES(dn_len);
if (check_col(pinfo->cinfo, COL_INFO)) {
- col_append_fstr(pinfo->cinfo, COL_INFO, ", User: %s@%s",
- an,dn);
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", User: ");
+
+ if (!dn[0] && !an[0])
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "anonymous");
+ else
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "%s\\%s", dn,an);
}
/* OS */
offset, an_len, an);
COUNT_BYTES(an_len);
+ /* Now when we know the service type, store it so that we know it for later commands down
+ this tree */
+ if(!pinfo->fd->flags.visited){
+ smb_info_t *si = (smb_info_t *)pinfo->private_data;
+ /* Remove any previous entry for this TID */
+ if(g_hash_table_lookup(si->ct->tid_service, (void *)si->tid)){
+ g_hash_table_remove(si->ct->tid_service, (void *)si->tid);
+ }
+ if(strcmp(an,"IPC") == 0){
+ g_hash_table_insert(si->ct->tid_service, (void *)si->tid, (void *)TID_IPC);
+ } else {
+ g_hash_table_insert(si->ct->tid_service, (void *)si->tid, (void *)TID_NORMAL);
+ }
+ }
+
+
if(wc==3){
if (bc != 0) {
/*
#define NT_TRANS_NOTIFY 4
#define NT_TRANS_RENAME 5
#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[] = {
- {NT_TRANS_CREATE, "NT CREATE"},
- {NT_TRANS_IOCTL, "NT IOCTL"},
- {NT_TRANS_SSD, "NT SET SECURITY DESC"},
- {NT_TRANS_NOTIFY, "NT NOTIFY"},
- {NT_TRANS_RENAME, "NT RENAME"},
- {NT_TRANS_QSD, "NT QUERY SECURITY DESC"},
+ {NT_TRANS_CREATE, "NT CREATE"},
+ {NT_TRANS_IOCTL, "NT IOCTL"},
+ {NT_TRANS_SSD, "NT SET SECURITY DESC"},
+ {NT_TRANS_NOTIFY, "NT NOTIFY"},
+ {NT_TRANS_RENAME, "NT RENAME"},
+ {NT_TRANS_QSD, "NT QUERY SECURITY DESC"},
+ {NT_TRANS_GET_USER_QUOTA, "NT GET USER QUOTA"},
+ {NT_TRANS_SET_USER_QUOTA, "NT SET USER QUOTA"},
{0, NULL}
};
{
proto_item *item = NULL;
proto_tree *tree = NULL;
- int old_offset = offset;
+ int old_offset = offset, sa_offset = offset;
+ guint *s_auths = NULL;
+ guint rid;
guint8 revision;
guint8 num_auth;
+ guint auth = 0; /* FIXME: What if it is larger than 32-bits */
int i;
GString *gstr;
/* XXX perhaps we should have these thing searchable?
a new FT_xxx thingie? SMB is quite common!*/
/* identifier authorities */
- gstr = g_string_new(NULL);
- CLEANUP_PUSH(free_g_string, gstr);
-
- g_string_sprintf(gstr, "S-1");
-
- proto_tree_add_text(tree, tvb, offset, 6, "Authorities");
+ /* FIXME: We should dynamically allocate the authorities array,
+ which is only one thing. Then we don't have to allocate two
+ strings below etc ...
+ */
for(i=0;i<6;i++){
- guint8 auth = tvb_get_guint8(tvb, offset);
+ auth = (auth << 8) + tvb_get_guint8(tvb, offset);
- if (auth > 0)
- g_string_sprintfa(gstr,"-%u", auth);
offset++;
}
- proto_tree_add_text(tree, tvb, offset, num_auth * 4, "Sub-authorities");
+ proto_tree_add_text(tree, tvb, offset - 6, 6, "Authority: %u", auth);
+
+ sa_offset = offset;
+
+ CLEANUP_PUSH(free, s_auths);
+
+ s_auths = g_malloc(sizeof(guint) * num_auth);
- /* sub authorities */
- for(i=0;i<num_auth;i++){
+ /* sub authorities, leave RID to last */
+ /* FIXME: If we take an exception now, we lose the whole
+ sub-authorities string thang */
+ for(i=0; i < (num_auth > 4?(num_auth - 1):num_auth); i++){
/* XXX should not be letohl but native byteorder according to
samba header files. considering that all non-x86 NT ports
are dead we can (?) assume that non le byte encodings
will be "uncommon"?*/
- g_string_sprintfa(gstr, "-%u",tvb_get_letohl(tvb, offset));
- offset+=4;
+ s_auths[i] = tvb_get_letohl(tvb, offset);
+ offset+=4;
}
- proto_item_append_text(item, ": %s", gstr->str);
-
CLEANUP_CALL_AND_POP;
+
+ gstr = g_string_new("");
+
+ for (i = 0; i < (num_auth>4?(num_auth - 1):num_auth); i++)
+ g_string_sprintfa(gstr, (i>0 ? "-%u" : "%u"), s_auths[i]);
+
+ proto_tree_add_text(tree, tvb, sa_offset, num_auth * 4, "Sub-authorities: %s", gstr->str);
+
+ if (num_auth > 4) {
+ rid = tvb_get_letohl(tvb, offset);
+ 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;
+ }
+ else {
+ proto_item_append_text(item, ": S-1-%u-%s", auth, gstr->str);
+ }
+
}
proto_item_set_len(item, offset-old_offset);
};
#define APPEND_ACE_TEXT(flag, item, string) \
- if(item && flag){ \
- proto_item_append_text(item, string); \
- }
+ if(flag){ \
+ if(item) \
+ proto_item_append_text(item, string, sep); \
+ sep = ", "; \
+ }
static int
dissect_nt_v2_ace_flags(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *parent_tree)
proto_item *item = NULL;
proto_tree *tree = NULL;
guint8 mask;
+ char *sep = " ";
mask = tvb_get_guint8(tvb, offset);
if(parent_tree){
item = proto_tree_add_text(parent_tree, tvb, offset, 1,
- "NT ACE Flags:0x%02x", mask);
+ "NT ACE Flags: 0x%02x", mask);
tree = proto_item_add_subtree(item, ett_smb_ace_flags);
}
proto_tree_add_boolean(tree, hf_smb_ace_flags_failed_access,
tvb, offset, 1, mask);
- APPEND_ACE_TEXT(mask&0x80, item, " Failed Access,");
+ APPEND_ACE_TEXT(mask&0x80, item, "%sFailed Access");
proto_tree_add_boolean(tree, hf_smb_ace_flags_successful_access,
tvb, offset, 1, mask);
- APPEND_ACE_TEXT(mask&0x40, item, " Successful Access,");
+ APPEND_ACE_TEXT(mask&0x40, item, "%sSuccessful Access");
proto_tree_add_boolean(tree, hf_smb_ace_flags_inherited_ace,
tvb, offset, 1, mask);
- APPEND_ACE_TEXT(mask&0x10, item, " Inherited ACE,");
+ APPEND_ACE_TEXT(mask&0x10, item, "%sInherited ACE");
proto_tree_add_boolean(tree, hf_smb_ace_flags_inherit_only,
tvb, offset, 1, mask);
- APPEND_ACE_TEXT(mask&0x08, item, " Inherit Only,");
+ APPEND_ACE_TEXT(mask&0x08, item, "%sInherit Only");
proto_tree_add_boolean(tree, hf_smb_ace_flags_non_propagate_inherit,
tvb, offset, 1, mask);
- APPEND_ACE_TEXT(mask&0x04, item, " No Propagate Inherit,");
+ APPEND_ACE_TEXT(mask&0x04, item, "%sNo Propagate Inherit");
proto_tree_add_boolean(tree, hf_smb_ace_flags_container_inherit,
tvb, offset, 1, mask);
- APPEND_ACE_TEXT(mask&0x02, item, " Container Inherit,");
+ APPEND_ACE_TEXT(mask&0x02, item, "%sContainer Inherit");
proto_tree_add_boolean(tree, hf_smb_ace_flags_object_inherit,
tvb, offset, 1, mask);
- APPEND_ACE_TEXT(mask&0x01, item, " Object Inherit,");
+ APPEND_ACE_TEXT(mask&0x01, item, "%sObject Inherit");
offset += 1;
proto_item *item = NULL;
proto_tree *tree = NULL;
int old_offset = offset;
+ guint16 size;
if(parent_tree){
item = proto_tree_add_text(parent_tree, tvb, offset, -1,
offset = dissect_nt_v2_ace_flags(tvb, pinfo, offset, tree);
/* size */
- proto_tree_add_item(tree, hf_smb_ace_size, tvb, offset, 2, TRUE);
+ size = tvb_get_letohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_ace_size, tvb, offset, 2, size);
offset += 2;
/* access mask */
offset = dissect_nt_sid(tvb, pinfo, offset, tree, "ACE");
proto_item_set_len(item, offset-old_offset);
- return offset;
+
+ /* Sometimes there is some spare space at the end of the ACE so use
+ the size field to work out where the end is. */
+
+ return old_offset + size;
}
static int
return offset;
}
+/* This function is also called from DCREPC services; it may be that, in
+ some cases, the NDR syntax must be followed, but that's not the case,
+ for example, for the security descriptor inside an LSA Security
+ Descriptor structure.
+ A "len" of -1 means that the NDR syntax must be followed.
+ In that case, we assume that owner SID, group SID, SACL, and DACL objects
+ are always stored in order (when present) and that all of them are aligned
+ on a 4 byte boundary, and we no longer use the xxx_offset other than to
+ check that they are non-NULL to be compatible with DCERPC NDR Unique.
+
+ Otherwise, we use the offsets to see where the owner SID, group SID,
+ SACL, and DACL are stored. */
int
dissect_nt_sec_desc(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *parent_tree, int len)
{
/*owner SID*/
if(owner_sid_offset){
- dissect_nt_sid(tvb, pinfo, old_offset+owner_sid_offset, tree, "Owner");
+ if (len == -1)
+ offset = dissect_nt_sid(tvb, pinfo, offset, tree, "Owner");
+ else
+ dissect_nt_sid(tvb, pinfo, old_offset+owner_sid_offset, tree, "Owner");
}
/*group SID*/
if(group_sid_offset){
- dissect_nt_sid(tvb, pinfo, old_offset+group_sid_offset, tree, "Group");
+ if (len == -1)
+ offset = dissect_nt_sid(tvb, pinfo, offset, tree, "Group");
+ else
+ dissect_nt_sid(tvb, pinfo, old_offset+group_sid_offset, tree, "Group");
}
/* sacl */
if(sacl_offset){
- dissect_nt_acl(tvb, pinfo, old_offset+sacl_offset, tree, "System (SACL)");
+ if (len == -1)
+ offset = dissect_nt_acl(tvb, pinfo, offset, tree, "System (SACL)");
+ else
+ dissect_nt_acl(tvb, pinfo, old_offset+sacl_offset, tree, "System (SACL)");
}
/* dacl */
if(dacl_offset){
- dissect_nt_acl(tvb, pinfo, old_offset+dacl_offset, tree, "User (DACL)");
+ if (len == -1)
+ offset = dissect_nt_acl(tvb, pinfo, offset, tree, "User (DACL)");
+ else
+ dissect_nt_acl(tvb, pinfo, old_offset+dacl_offset, tree, "User (DACL)");
}
}
- return offset+len;
+ if (len == -1) {
+ proto_item_set_len(item, offset-old_offset);
+ return offset;
+ } else
+ return offset+len;
}
static int
-dissect_nt_trans_data_request(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *parent_tree, int len, nt_trans_data *ntd)
+dissect_nt_user_quota(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint16 *bcp)
+{
+ int old_offset, old_sid_offset;
+ guint32 qsize;
+
+ do {
+ old_offset=offset;
+
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ qsize=tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_user_quota_offset, tvb, offset, 4, qsize);
+ COUNT_BYTES_TRANS_SUBR(4);
+
+ CHECK_BYTE_COUNT_TRANS_SUBR(4);
+ /* length of SID */
+ proto_tree_add_text(tree, tvb, offset, 4, "Length of SID: %d", tvb_get_letohl(tvb, offset));
+ COUNT_BYTES_TRANS_SUBR(4);
+
+ /* 16 unknown bytes */
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_unknown, tvb,
+ offset, 8, TRUE);
+ COUNT_BYTES_TRANS_SUBR(8);
+
+ /* number of bytes for used quota */
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_user_quota_used, tvb, offset, 8, TRUE);
+ COUNT_BYTES_TRANS_SUBR(8);
+
+ /* number of bytes for quota warning */
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_soft_quota_limit, tvb, offset, 8, TRUE);
+ COUNT_BYTES_TRANS_SUBR(8);
+
+ /* number of bytes for quota limit */
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_hard_quota_limit, tvb, offset, 8, TRUE);
+ COUNT_BYTES_TRANS_SUBR(8);
+
+ /* SID of the user */
+ old_sid_offset=offset;
+ offset = dissect_nt_sid(tvb, pinfo, offset, tree, "Quota");
+ *bcp -= (offset-old_sid_offset);
+
+ if(qsize){
+ offset = old_offset+qsize;
+ }
+ }while(qsize);
+
+
+ return offset;
+}
+
+
+static int
+dissect_nt_trans_data_request(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *parent_tree, int bc, nt_trans_data *ntd)
{
proto_item *item = NULL;
proto_tree *tree = NULL;
smb_info_t *si;
+ int old_offset = offset;
+ guint16 bcp=bc; /* XXX fixme */
si = (smb_info_t *)pinfo->private_data;
if(parent_tree){
- item = proto_tree_add_text(parent_tree, tvb, offset, len,
+ item = proto_tree_add_text(parent_tree, tvb, offset, bc,
"%s Data",
val_to_str(ntd->subcmd, nt_cmd_vals, "Unknown NT transaction (%u)"));
- tree = proto_item_add_subtree(item, ett_smb_nt_trans_setup);
+ tree = proto_item_add_subtree(item, ett_smb_nt_trans_data);
}
switch(ntd->subcmd){
break;
case NT_TRANS_IOCTL:
/* ioctl data */
- proto_tree_add_item(tree, hf_smb_nt_ioctl_data, tvb, offset, len, TRUE);
- offset += len;
+ proto_tree_add_item(tree, hf_smb_nt_ioctl_data, tvb, offset, bc, TRUE);
+ offset += bc;
break;
case NT_TRANS_SSD:
- offset = dissect_nt_sec_desc(tvb, pinfo, offset, tree, len);
+ offset = dissect_nt_sec_desc(tvb, pinfo, offset, tree, bc);
break;
case NT_TRANS_NOTIFY:
break;
break;
case NT_TRANS_QSD:
break;
+ case NT_TRANS_GET_USER_QUOTA:
+ /* unknown 4 bytes */
+ proto_tree_add_item(tree, hf_smb_unknown, tvb,
+ offset, 4, TRUE);
+ offset += 4;
+
+ /* length of SID */
+ proto_tree_add_text(tree, tvb, offset, 4, "Length of SID: %d", tvb_get_letohl(tvb, offset));
+ offset +=4;
+
+ offset = dissect_nt_sid(tvb, pinfo, offset, tree, "Quota");
+ break;
+ case NT_TRANS_SET_USER_QUOTA:
+ offset = dissect_nt_user_quota(tvb, pinfo, tree, offset, &bcp);
+ break;
+ }
+
+ /* ooops there were data we didnt know how to process */
+ if((offset-old_offset) < bc){
+ proto_tree_add_item(tree, hf_smb_unknown, tvb, offset,
+ bc - (offset-old_offset), TRUE);
+ offset += bc - (offset-old_offset);
}
return offset;
item = proto_tree_add_text(parent_tree, tvb, offset, len,
"%s Parameters",
val_to_str(ntd->subcmd, nt_cmd_vals, "Unknown NT transaction (%u)"));
- tree = proto_item_add_subtree(item, ett_smb_nt_trans_setup);
+ tree = proto_item_add_subtree(item, ett_smb_nt_trans_param);
}
switch(ntd->subcmd){
offset = dissect_security_information_mask(tvb, pinfo, tree, offset);
break;
}
+ case NT_TRANS_GET_USER_QUOTA:
+ /* not decoded yet */
+ break;
+ case NT_TRANS_SET_USER_QUOTA:
+ /* not decoded yet */
+ break;
}
return offset;
break;
case NT_TRANS_QSD:
break;
+ case NT_TRANS_GET_USER_QUOTA:
+ /* not decoded yet */
+ break;
+ case NT_TRANS_SET_USER_QUOTA:
+ /* not decoded yet */
+ break;
}
return old_offset+len;
proto_tree *tree = NULL;
smb_info_t *si;
smb_nt_transact_info_t *nti;
+ guint16 bcp;
si = (smb_info_t *)pinfo->private_data;
if (si->sip != NULL)
item = proto_tree_add_text(parent_tree, tvb, offset, len,
"Unknown NT Transaction Data (matching request not seen)");
}
- tree = proto_item_add_subtree(item, ett_smb_nt_trans_setup);
+ tree = proto_item_add_subtree(item, ett_smb_nt_trans_data);
}
if (nti == NULL) {
*/
offset = dissect_nt_sec_desc(tvb, pinfo, offset, tree, len);
break;
+ case NT_TRANS_GET_USER_QUOTA:
+ bcp=len;
+ offset = dissect_nt_user_quota(tvb, pinfo, tree, offset, &bcp);
+ break;
+ case NT_TRANS_SET_USER_QUOTA:
+ /* not decoded yet */
+ break;
}
return offset;
smb_info_t *si;
smb_nt_transact_info_t *nti;
guint16 fid;
+ int old_offset;
+ guint32 neo;
+ int padcnt;
si = (smb_info_t *)pinfo->private_data;
if (si->sip != NULL)
item = proto_tree_add_text(parent_tree, tvb, offset, len,
"Unknown NT Transaction Parameters (matching request not seen)");
}
- tree = proto_item_add_subtree(item, ett_smb_nt_trans_setup);
+ tree = proto_item_add_subtree(item, ett_smb_nt_trans_param);
}
if (nti == NULL) {
break;
case NT_TRANS_NOTIFY:
while(len){
+ old_offset = offset;
+
/* next entry offset */
- proto_tree_add_item(tree, hf_smb_next_entry_offset, tvb, offset, 4, TRUE);
+ neo = tvb_get_letohl(tvb, offset);
+ proto_tree_add_uint(tree, hf_smb_next_entry_offset, tvb, offset, 4, neo);
COUNT_BYTES(4);
len -= 4;
/* broken implementations */
/* broken implementations */
if(len<0)break;
+ if (neo == 0)
+ break; /* no more structures */
+
+ /* skip to next structure */
+ padcnt = (old_offset + neo) - offset;
+ if (padcnt < 0) {
+ /*
+ * XXX - this is bogus; flag it?
+ */
+ padcnt = 0;
+ }
+ if (padcnt != 0) {
+ COUNT_BYTES(padcnt);
+ len -= padcnt;
+ /* broken implementations */
+ if(len<0)break;
+ }
}
break;
case NT_TRANS_RENAME:
proto_tree_add_item(tree, hf_smb_sec_desc_len, tvb, offset, 4, TRUE);
offset += 4;
break;
+ case NT_TRANS_GET_USER_QUOTA:
+ proto_tree_add_text(tree, tvb, offset, 4, "Size of returned Quota data: %d",
+ tvb_get_letohl(tvb, offset));
+ offset += 4;
+ break;
+ case NT_TRANS_SET_USER_QUOTA:
+ /* not decoded yet */
+ break;
}
return offset;
break;
case NT_TRANS_QSD:
break;
+ case NT_TRANS_GET_USER_QUOTA:
+ /* not decoded yet */
+ break;
+ case NT_TRANS_SET_USER_QUOTA:
+ /* not decoded yet */
+ break;
}
return offset;
proto_item *it;
fragment_data *fd;
- it = proto_tree_add_text(tree, tvb, 0, 0, "Fragments");
- tr = proto_item_add_subtree(it, ett_smb_segments);
- for(fd=r_fd->next;fd;fd=fd->next){
- proto_tree_add_text(tr, tvb, 0, 0, "Frame:%u Data:%u-%u",
- fd->frame, fd->offset, fd->offset+fd->len-1);
- }
-
pd_tvb = tvb_new_real_data(r_fd->data, r_fd->datalen,
r_fd->datalen);
tvb_set_child_real_data_tvbuff(tvb, pd_tvb);
add_new_data_source(pinfo->fd, pd_tvb, "Reassembled SMB");
pinfo->fragmented = FALSE;
+
+ it = proto_tree_add_text(tree, pd_tvb, 0, -1, "Fragments");
+ tr = proto_item_add_subtree(it, ett_smb_segments);
+ for(fd=r_fd->next;fd;fd=fd->next){
+ proto_tree_add_text(tr, pd_tvb, fd->offset, fd->len,
+ "Frame:%u Data:%u-%u",
+ fd->frame, fd->offset,
+ fd->offset+fd->len-1);
+ }
}
{ 0x01, "FIND_FIRST2" },
{ 0x02, "FIND_NEXT2" },
{ 0x03, "QUERY_FS_INFORMATION" },
+ { 0x04, "SET_FS_QUOTA" },
{ 0x05, "QUERY_PATH_INFORMATION" },
{ 0x06, "SET_PATH_INFORMATION" },
{ 0x07, "QUERY_FILE_INFORMATION" },
{ 0x0103, "Query FS Size Info"},
{ 0x0104, "Query FS Device Info"},
{ 0x0105, "Query FS Attribute Info"},
+ { 1006, "Query FS Quota Info"},
{0, NULL}
};
+static const value_string nt_rename_vals[] = {
+ { 0x0103, "Create Hard Link"},
+ {0, NULL}
+};
+
+
static const value_string delete_pending_vals[] = {
{0, "Normal, no pending delete"},
{1, "This object has DELETE PENDING"},
}
+static const true_false_string tfs_quota_flags_deny_disk = {
+ "DENY DISK SPACE for users exceeding quota limit",
+ "Do NOT deny disk space for users exceeding quota limit"
+};
+static const true_false_string tfs_quota_flags_log_limit = {
+ "LOG EVENT when a user exceeds their QUOTA LIMIT",
+ "Do NOT log event when a user exceeds their quota limit"
+};
+static const true_false_string tfs_quota_flags_log_warning = {
+ "LOG EVENT when a user exceeds their WARNING LEVEL",
+ "Do NOT log event when a user exceeds their warning level"
+};
+static const true_false_string tfs_quota_flags_enabled = {
+ "Quotas are ENABLED of this fs",
+ "Quotas are NOT enabled on this fs"
+};
+static void
+dissect_quota_flags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+{
+ guint8 mask;
+ proto_item *item = NULL;
+ proto_tree *tree = NULL;
+
+ mask = tvb_get_guint8(tvb, offset);
+
+ if(parent_tree){
+ item = proto_tree_add_text(parent_tree, tvb, offset, 1,
+ "Quota Flags: 0x%02x %s", mask,
+ mask?"Enabled":"Disabled");
+ tree = proto_item_add_subtree(item, ett_smb_quotaflags);
+ }
+
+ proto_tree_add_boolean(tree, hf_smb_quota_flags_log_limit,
+ tvb, offset, 1, mask);
+ proto_tree_add_boolean(tree, hf_smb_quota_flags_log_warning,
+ tvb, offset, 1, mask);
+ proto_tree_add_boolean(tree, hf_smb_quota_flags_deny_disk,
+ tvb, offset, 1, mask);
+
+ if(mask && (!(mask&0x01))){
+ proto_tree_add_boolean_hidden(tree, hf_smb_quota_flags_enabled,
+ tvb, offset, 1, 0x01);
+ } else {
+ proto_tree_add_boolean(tree, hf_smb_quota_flags_enabled,
+ tvb, offset, 1, mask);
+ }
+
+}
+
+static int
+dissect_nt_quota(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint16 *bcp)
+{
+ /* first 24 bytes are unknown */
+ CHECK_BYTE_COUNT_TRANS_SUBR(24);
+ proto_tree_add_item(tree, hf_smb_unknown, tvb,
+ offset, 24, TRUE);
+ COUNT_BYTES_TRANS_SUBR(24);
+
+ /* number of bytes for quota warning */
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_soft_quota_limit, tvb, offset, 8, TRUE);
+ COUNT_BYTES_TRANS_SUBR(8);
+
+ /* number of bytes for quota limit */
+ CHECK_BYTE_COUNT_TRANS_SUBR(8);
+ proto_tree_add_item(tree, hf_smb_hard_quota_limit, tvb, offset, 8, TRUE);
+ COUNT_BYTES_TRANS_SUBR(8);
+
+ /* one byte of quota flags */
+ CHECK_BYTE_COUNT_TRANS_SUBR(1);
+ dissect_quota_flags(tvb, pinfo, tree, offset);
+ COUNT_BYTES_TRANS_SUBR(1);
+
+ /* these 7 bytes are unknown */
+ CHECK_BYTE_COUNT_TRANS_SUBR(7);
+ proto_tree_add_item(tree, hf_smb_unknown, tvb,
+ offset, 7, TRUE);
+ COUNT_BYTES_TRANS_SUBR(7);
+
+ return offset;
+}
+
static int
dissect_transaction2_request_data(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *parent_tree, int offset, int subcmd, guint16 dc)
case 0x03: /*TRANS2_QUERY_FS_INFORMATION*/
/* no data field in this request */
break;
+ case 0x04: /* TRANS2_SET_QUOTA */
+ offset = dissect_nt_quota(tvb, pinfo, tree, offset, &dc);
+ break;
case 0x05: /*TRANS2_QUERY_PATH_INFORMATION*/
/* no data field in this request */
break;
return offset;
}
-
/*dissect the data block for TRANS2_QUERY_FS_INFORMATION*/
static int
dissect_qfsi_vals(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
COUNT_BYTES_TRANS_SUBR(fn_len);
break;
+ case 1006: /* QUERY_FS_QUOTA_INFO */
+ offset = dissect_nt_quota(tvb, pinfo, tree, offset, bcp);
}
return offset;
proto_tree *tr;
proto_item *it;
fragment_data *fd;
-
- it = proto_tree_add_text(tree, tvb, 0, 0, "Fragments");
- tr = proto_item_add_subtree(it, ett_smb_segments);
- for(fd=r_fd->next;fd;fd=fd->next){
- proto_tree_add_text(tr, tvb, 0, 0, "Frame:%u Data:%u-%u",
- fd->frame, fd->offset, fd->offset+fd->len-1);
- }
-
+
pd_tvb = tvb_new_real_data(r_fd->data, r_fd->datalen,
r_fd->datalen);
tvb_set_child_real_data_tvbuff(tvb, pd_tvb);
add_new_data_source(pinfo->fd, pd_tvb, "Reassembled SMB");
pinfo->fragmented = FALSE;
+
+ it = proto_tree_add_text(tree, pd_tvb, 0, -1, "Fragments");
+ tr = proto_item_add_subtree(it, ett_smb_segments);
+ for(fd=r_fd->next;fd;fd=fd->next){
+ proto_tree_add_text(tr, pd_tvb, fd->offset, fd->len,
+ "Frame:%u Data:%u-%u",
+ fd->frame, fd->offset,
+ fd->offset+fd->len-1);
+ }
}
int (*response)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree);
} smb_function;
-smb_function smb_dissector[256] = {
+static smb_function smb_dissector[256] = {
/* 0x00 Create Dir*/ {dissect_old_dir_request, dissect_empty},
/* 0x01 Delete Dir*/ {dissect_old_dir_request, dissect_empty},
/* 0x02 Open File*/ {dissect_open_file_request, dissect_open_file_response},
/* 0xa2 NT CreateAndX*/ {dissect_nt_create_andx_request, dissect_nt_create_andx_response},
/* 0xa3 */ {dissect_unknown, dissect_unknown},
/* 0xa4 NT Cancel*/ {dissect_nt_cancel_request, dissect_unknown}, /*no response to this one*/
- /* 0xa5 */ {dissect_unknown, dissect_unknown},
+ /* 0xa5 */ {dissect_nt_rename_file_request, dissect_empty},
/* 0xa6 */ {dissect_unknown, dissect_unknown},
/* 0xa7 */ {dissect_unknown, dissect_unknown},
/* 0xa8 */ {dissect_unknown, dissect_unknown},
{ 0xA2, "NT Create AndX" },
{ 0xA3, "unknown-0xA3" },
{ 0xA4, "NT Cancel" },
- { 0xA5, "unknown-0xA5" },
+ { 0xA5, "NT Rename" },
{ 0xA6, "unknown-0xA6" },
{ 0xA7, "unknown-0xA7" },
{ 0xA8, "unknown-0xA8" },
g_hash_table_destroy(ct->matched);
if (ct->dcerpc_fid_to_frame)
g_hash_table_destroy(ct->dcerpc_fid_to_frame);
+ if (ct->tid_service)
+ g_hash_table_destroy(ct->tid_service);
}
static void
const gchar *string;
int string_len;
smb_info_t *si;
- int copylen;
+ unsigned int copylen;
if (*bcp == 0) {
/* Not enough data in buffer */
{SMBE_nosuchshare, "Requested share does not exist"},
{SMBE_filexists, "File in operation already exists"},
{SMBE_cannotopen, "Cannot open the file specified"},
- {SMBE_unknownlevel, "Unknown level??"},
+ {SMBE_unknownlevel, "Unknown info level"},
+ {SMBE_invalidname, "Invalid name"},
{SMBE_badpipe, "Named pipe invalid"},
{SMBE_pipebusy, "All instances of pipe are busy"},
{SMBE_pipeclosing, "Named pipe close in progress"},
{SMBE_invalidenvironment, "Invalid environment"},
{SMBE_printerdriverinuse, "Printer driver in use"},
{SMBE_invalidparam, "Invalid parameter"},
+ {SMBE_invalidformsize, "Invalid form size"},
+ {SMBE_invalidsecuritydescriptor, "Invalid security descriptor"},
{0, NULL}
};
}
+
+/* These are the MS country codes from
+
+ http://www.unicode.org/unicode/onlinedat/countries.html
+
+ For countries that share the same number, I choose to use only the
+ name of the largest country. Apologies for this. If this offends you,
+ here is the table to change that.
+
+ This also includes the code of 0 for "Default", which isn't in
+ that list, but is in Microsoft's SDKs and the Cygnus "winnls.h"
+ header file. Presumably it means "don't override the setting
+ on the user's machine".
+
+ Future versions of Microsoft's "winnls.h" header file might include
+ additional codes; the current version matches the Unicode Consortium's
+ table.
+*/
+const value_string ms_country_codes[] = {
+ { 0, "Default"},
+ { 1, "USA"},
+ { 2, "Canada"},
+ { 7, "Russia"},
+ { 20, "Egypt"},
+ { 27, "South Africa"},
+ { 30, "Greece"},
+ { 31, "Netherlands"},
+ { 32, "Belgium"},
+ { 33, "France"},
+ { 34, "Spain"},
+ { 36, "Hungary"},
+ { 39, "Italy"},
+ { 40, "Romania"},
+ { 41, "Switzerland"},
+ { 43, "Austria"},
+ { 44, "United Kingdom"},
+ { 45, "Denmark"},
+ { 46, "Sweden"},
+ { 47, "Norway"},
+ { 48, "Poland"},
+ { 49, "Germany"},
+ { 51, "Peru"},
+ { 52, "Mexico"},
+ { 54, "Argentina"},
+ { 55, "Brazil"},
+ { 56, "Chile"},
+ { 57, "Colombia"},
+ { 58, "Venezuela"},
+ { 60, "Malaysia"},
+ { 61, "Australia"},
+ { 62, "Indonesia"},
+ { 63, "Philippines"},
+ { 64, "New Zealand"},
+ { 65, "Singapore"},
+ { 66, "Thailand"},
+ { 81, "Japan"},
+ { 82, "South Korea"},
+ { 84, "Viet Nam"},
+ { 86, "China"},
+ { 90, "Turkey"},
+ { 91, "India"},
+ { 92, "Pakistan"},
+ {212, "Morocco"},
+ {213, "Algeria"},
+ {216, "Tunisia"},
+ {218, "Libya"},
+ {254, "Kenya"},
+ {263, "Zimbabwe"},
+ {298, "Faroe Islands"},
+ {351, "Portugal"},
+ {352, "Luxembourg"},
+ {353, "Ireland"},
+ {354, "Iceland"},
+ {355, "Albania"},
+ {358, "Finland"},
+ {359, "Bulgaria"},
+ {370, "Lithuania"},
+ {371, "Latvia"},
+ {372, "Estonia"},
+ {374, "Armenia"},
+ {375, "Belarus"},
+ {380, "Ukraine"},
+ {381, "Serbia"},
+ {385, "Croatia"},
+ {386, "Slovenia"},
+ {389, "Macedonia"},
+ {420, "Czech Republic"},
+ {421, "Slovak Republic"},
+ {501, "Belize"},
+ {502, "Guatemala"},
+ {503, "El Salvador"},
+ {504, "Honduras"},
+ {505, "Nicaragua"},
+ {506, "Costa Rica"},
+ {507, "Panama"},
+ {591, "Bolivia"},
+ {593, "Ecuador"},
+ {595, "Paraguay"},
+ {598, "Uruguay"},
+ {673, "Brunei Darussalam"},
+ {852, "Hong Kong"},
+ {853, "Macau"},
+ {886, "Taiwan"},
+ {960, "Maldives"},
+ {961, "Lebanon"},
+ {962, "Jordan"},
+ {963, "Syria"},
+ {964, "Iraq"},
+ {965, "Kuwait"},
+ {966, "Saudi Arabia"},
+ {967, "Yemen"},
+ {968, "Oman"},
+ {971, "United Arab Emirates"},
+ {972, "Israel"},
+ {973, "Bahrain"},
+ {974, "Qatar"},
+ {976, "Mongolia"},
+ {981, "Iran"},
+ {994, "Azerbaijan"},
+ {995, "Georgia"},
+ {996, "Kyrgyzstan"},
+
+ {0, NULL}
+};
+
/*
* NT error codes.
*
guint32 nt_status = 0;
guint8 errclass = 0;
guint16 errcode = 0;
- guint16 uid, pid, tid, mid;
guint32 pid_mid;
conversation_t *conversation;
} else {
si.unicode = FALSE;
}
- tid = tvb_get_letohs(tvb, offset+24);
- pid = tvb_get_letohs(tvb, offset+26);
- uid = tvb_get_letohs(tvb, offset+28);
- mid = tvb_get_letohs(tvb, offset+30);
- pid_mid = (pid << 16) | mid;
+ 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.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(
+ smb_saved_info_hash_unmatched,
+ smb_saved_info_equal_unmatched);
conversation_add_proto_data(conversation, proto_smb, si.ct);
}
if( (si.request)
- && (mid==0)
- && (uid==0)
- && (pid==0)
- && (tid==0) ){
+ && (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
*/
sip = g_mem_chunk_alloc(smb_saved_info_chunk);
sip->frame_req = pinfo->fd->num;
sip->frame_res = 0;
+ sip->flags = 0;
+ 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->extra_info = NULL;
g_hash_table_insert(si.ct->unmatched, (void *)pid_mid, sip);
offset += 12;
/* TID */
- proto_tree_add_uint(htree, hf_smb_tid, tvb, offset, 2, 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, 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, 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, mid);
+ proto_tree_add_uint(htree, hf_smb_mid, tvb, offset, 2, si.mid);
offset += 2;
pinfo->private_data = &si;
*/
col_append_fstr(
pinfo->cinfo, COL_INFO, ", Error: %s",
- val_to_str(nt_status, NT_errors, "%s"));
+ val_to_str(nt_status, NT_errors,
+ "Unknown (0x%08X)"));
}
} else {
/*
{ "Level of Interest", "smb.qfi_loi", FT_UINT16, BASE_DEC,
VALS(qfsi_vals), 0, "Level of interest for QUERY_FS_INFORMATION2 command", HFILL }},
+ { &hf_smb_nt_rename_level,
+ { "Level of Interest", "smb.ntr_loi", FT_UINT16, BASE_DEC,
+ VALS(nt_rename_vals), 0, "NT Rename level", HFILL }},
+
+ { &hf_smb_cluster_count,
+ { "Cluster count", "smb.ntr_clu", FT_UINT32, BASE_DEC,
+ NULL, 0, "Number of clusters", HFILL }},
+
{ &hf_smb_ea_size,
{ "EA Size", "smb.ea_size", FT_UINT32, BASE_DEC,
NULL, 0, "Size of file's EA information", HFILL }},
{ "Free Units", "smb.free_alloc_units", FT_UINT64, BASE_DEC,
NULL, 0, "Number of free allocation units", HFILL }},
+ { &hf_smb_soft_quota_limit,
+ { "(Soft) Quota Treshold", "smb.quota.soft.default", FT_UINT64, BASE_DEC,
+ NULL, 0, "Soft Quota treshold", HFILL }},
+
+ { &hf_smb_hard_quota_limit,
+ { "(Hard) Quota Limit", "smb.quota.hard.default", FT_UINT64, BASE_DEC,
+ NULL, 0, "Hard Quota limit", HFILL }},
+
+ { &hf_smb_user_quota_used,
+ { "Quota Used", "smb.quota.used", FT_UINT64, BASE_DEC,
+ NULL, 0, "How much Quota is used by this user", HFILL }},
+
{ &hf_smb_max_name_len,
{ "Max name length", "smb.fs_max_name_len", FT_UINT32, BASE_DEC,
NULL, 0, "Maximum length of each file name component in number of bytes", HFILL }},
{ "Num ACEs", "smb.acl.num_aces", FT_UINT32, BASE_DEC,
NULL, 0, "Number of ACE structures for this ACL", HFILL }},
+ { &hf_smb_user_quota_offset,
+ { "Next Offset", "smb.quota.user.offset", FT_UINT32, BASE_DEC,
+ NULL, 0, "Relative offset to next user quota structure", HFILL }},
+
{ &hf_smb_ace_type,
{ "Type", "smb.ace.type", FT_UINT8, BASE_DEC,
VALS(ace_type_vals), 0, "Type of ACE", HFILL }},
TFS(&tfs_ace_flags_failed_access), 0x80, "Should failed accesses be audited?", HFILL }},
{ &hf_smb_sec_desc_type_owner_defaulted,
- { "Onwer Defaulted", "smb.sec_desc.type.owner_defaulted", FT_BOOLEAN, 16,
+ { "Owner Defaulted", "smb.sec_desc.type.owner_defaulted", FT_BOOLEAN, 16,
TFS(&tfs_sec_desc_type_owner_defaulted), 0x0001, "Is Owner Defaulted set?", HFILL }},
{ &hf_smb_sec_desc_type_group_defaulted,
{ "Self Relative", "smb.sec_desc.type.self_relative", FT_BOOLEAN, 16,
TFS(&tfs_sec_desc_type_self_relative), 0x8000, "Is this SecDesc self relative?", HFILL }},
+ { &hf_smb_quota_flags_deny_disk,
+ { "Deny Disk", "smb.quota.flags.deny_disk", FT_BOOLEAN, 8,
+ TFS(&tfs_quota_flags_deny_disk), 0x02, "Is the default quota limit enforced?", HFILL }},
+
+ { &hf_smb_quota_flags_log_limit,
+ { "Log Limit", "smb.quota.flags.log_limit", FT_BOOLEAN, 8,
+ TFS(&tfs_quota_flags_log_limit), 0x20, "Should the server log an event when the limit is exceeded?", HFILL }},
+
+ { &hf_smb_quota_flags_log_warning,
+ { "Log Warning", "smb.quota.flags.log_warning", FT_BOOLEAN, 8,
+ TFS(&tfs_quota_flags_log_warning), 0x10, "Should the server log an event when the warning level is exceeded?", HFILL }},
+
+ { &hf_smb_quota_flags_enabled,
+ { "Enabled", "smb.quota.flags.enabled", FT_BOOLEAN, 8,
+ TFS(&tfs_quota_flags_enabled), 0x01, "Is quotas enabled of this FS?", HFILL }},
+
};
static gint *ett[] = {
&ett_smb,
&ett_smb_nt_share_access,
&ett_smb_nt_security_flags,
&ett_smb_nt_trans_setup,
+ &ett_smb_nt_trans_data,
+ &ett_smb_nt_trans_param,
&ett_smb_nt_notify_completion_filter,
&ett_smb_nt_ioctl_flags,
&ett_smb_security_information_mask,
&ett_smb_ace,
&ett_smb_ace_flags,
&ett_smb_sec_desc_type,
+ &ett_smb_quotaflags,
};
module_t *smb_module;
smb_module = prefs_register_protocol(proto_smb, NULL);
prefs_register_bool_preference(smb_module, "trans_reassembly",
"Reassemble SMB Transaction payload",
- "Whether the dissector should do reassembly the payload of SMB Transaction commands spanning multiple SMB PDUs",
+ "Whether the dissector should reassemble the payload of SMB Transaction commands spanning multiple SMB PDUs",
&smb_trans_reassembly);
prefs_register_bool_preference(smb_module, "dcerpc_reassembly",
"Reassemble DCERPC over SMB",
- "Whether the dissector should do reassembly of DCERPC over SMB commands",
+ "Whether the dissector should reassemble DCERPC over SMB commands",
&smb_dcerpc_reassembly);
register_init_routine(smb_trans_reassembly_init);
register_init_routine(smb_dcerpc_reassembly_init);