2005-02-16 11:31:56 +00:00
|
|
|
/* TODO:
|
|
|
|
dissect_ndr_nt_SID_with_options see comment.
|
|
|
|
*/
|
2001-12-16 20:17:10 +00:00
|
|
|
/* packet-dcerpc-nt.c
|
|
|
|
* Routines for DCERPC over SMB packet disassembly
|
2003-01-16 22:40:48 +00:00
|
|
|
* Copyright 2001-2003, Tim Potter <tpot@samba.org>
|
2001-12-16 20:17:10 +00:00
|
|
|
*
|
2004-07-18 00:24:25 +00:00
|
|
|
* $Id$
|
2001-12-16 20:17:10 +00:00
|
|
|
*
|
2006-05-21 04:49:01 +00:00
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
2001-12-16 20:17:10 +00:00
|
|
|
* Copyright 1998 Gerald Combs
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
2001-12-16 20:17:10 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
2001-12-16 20:17:10 +00:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
2001-12-16 20:17:10 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2004-08-02 23:40:09 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
2001-12-16 20:17:10 +00:00
|
|
|
#include <glib.h>
|
2002-01-21 07:37:49 +00:00
|
|
|
#include <epan/packet.h>
|
2005-08-13 01:29:31 +00:00
|
|
|
#include <epan/emem.h>
|
2001-12-16 20:17:10 +00:00
|
|
|
#include "packet-dcerpc.h"
|
|
|
|
#include "packet-dcerpc-nt.h"
|
2004-08-03 02:28:49 +00:00
|
|
|
#include "packet-windows-common.h"
|
2001-12-16 20:17:10 +00:00
|
|
|
|
2009-09-30 07:53:12 +00:00
|
|
|
|
2009-10-20 08:44:26 +00:00
|
|
|
int hf_nt_cs_len = -1;
|
|
|
|
int hf_nt_cs_size = -1;
|
2009-10-06 08:07:17 +00:00
|
|
|
static int hf_lsa_String_name_len = -1;
|
|
|
|
static int hf_lsa_String_name_size = -1;
|
|
|
|
|
|
|
|
|
2009-10-11 14:32:36 +00:00
|
|
|
static gint ett_nt_unicode_string = -1;
|
2009-10-06 08:07:17 +00:00
|
|
|
static gint ett_lsa_String = -1;
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-09-30 07:53:12 +00:00
|
|
|
/* This is used to safely walk the decode tree up, one item at a time safely.
|
|
|
|
This is used by dcerpc dissectors that want to push the display of a string
|
|
|
|
higher up in the tree for greater visibility.
|
|
|
|
*/
|
|
|
|
#define GET_ITEM_PARENT(x) \
|
|
|
|
((x->parent!=NULL)?x->parent:x)
|
|
|
|
|
2001-12-16 20:17:10 +00:00
|
|
|
/*
|
|
|
|
* This file contains helper routines that are used by the DCERPC over SMB
|
2006-05-21 04:49:01 +00:00
|
|
|
* dissectors for wireshark.
|
2001-12-16 20:17:10 +00:00
|
|
|
*/
|
|
|
|
|
2003-05-15 05:24:19 +00:00
|
|
|
/*
|
|
|
|
* Used by several dissectors.
|
|
|
|
*/
|
|
|
|
const value_string platform_id_vals[] = {
|
|
|
|
{ 300, "DOS" },
|
|
|
|
{ 400, "OS/2" },
|
|
|
|
{ 500, "Windows NT" },
|
|
|
|
{ 600, "OSF" },
|
|
|
|
{ 700, "VMS" },
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
2003-02-07 08:56:12 +00:00
|
|
|
/* Parse some common RPC structures */
|
2002-03-06 08:58:01 +00:00
|
|
|
|
2003-02-03 02:00:54 +00:00
|
|
|
/* Dissect a counted string as a callback to dissect_ndr_pointer_cb() */
|
|
|
|
|
2002-03-11 00:15:20 +00:00
|
|
|
int
|
2003-02-03 02:00:54 +00:00
|
|
|
dissect_ndr_counted_string_cb(tvbuff_t *tvb, int offset,
|
|
|
|
packet_info *pinfo, proto_tree *tree,
|
2004-01-19 20:10:37 +00:00
|
|
|
guint8 *drep, int hf_index,
|
2003-02-03 02:00:54 +00:00
|
|
|
dcerpc_callback_fnct_t *callback,
|
|
|
|
void *callback_args)
|
2002-03-11 00:15:20 +00:00
|
|
|
{
|
2003-02-03 02:00:54 +00:00
|
|
|
dcerpc_info *di = pinfo->private_data;
|
|
|
|
guint16 len, size;
|
2002-03-11 00:15:20 +00:00
|
|
|
|
2009-10-04 08:11:09 +00:00
|
|
|
/* Structure starts with short, but is aligned for pointer */
|
2003-02-03 02:00:54 +00:00
|
|
|
|
2009-10-04 08:11:09 +00:00
|
|
|
ALIGN_TO_5_BYTES;
|
2003-02-03 02:00:54 +00:00
|
|
|
|
|
|
|
if (di->conformant_run)
|
2002-03-11 00:15:20 +00:00
|
|
|
return offset;
|
2005-10-17 18:56:27 +00:00
|
|
|
|
|
|
|
/*
|
2003-02-03 02:00:54 +00:00
|
|
|
struct {
|
|
|
|
short len;
|
|
|
|
short size;
|
|
|
|
[size_is(size/2), length_is(len/2), ptr] unsigned short *string;
|
|
|
|
} UNICODE_STRING;
|
2002-03-11 00:15:20 +00:00
|
|
|
|
2003-02-03 02:00:54 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
|
|
|
|
hf_nt_cs_len, &len);
|
2002-03-13 07:38:34 +00:00
|
|
|
|
2003-02-03 02:00:54 +00:00
|
|
|
offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
|
2005-10-17 18:56:27 +00:00
|
|
|
hf_nt_cs_size, &size);
|
2003-02-03 02:00:54 +00:00
|
|
|
|
|
|
|
offset = dissect_ndr_pointer_cb(tvb, offset, pinfo, tree, drep,
|
2003-02-07 22:44:54 +00:00
|
|
|
dissect_ndr_wchar_cvstring, NDR_POINTER_UNIQUE,
|
2003-02-03 02:00:54 +00:00
|
|
|
"Character Array", hf_index, callback, callback_args);
|
|
|
|
|
2009-10-04 08:11:09 +00:00
|
|
|
if (di->call_data->flags & DCERPC_IS_NDR64) {
|
|
|
|
ALIGN_TO_5_BYTES;
|
|
|
|
}
|
|
|
|
|
2003-02-03 02:00:54 +00:00
|
|
|
return offset;
|
2002-03-11 00:15:20 +00:00
|
|
|
}
|
|
|
|
|
2003-02-03 02:00:54 +00:00
|
|
|
static gint ett_nt_counted_string = -1;
|
|
|
|
|
|
|
|
static int
|
|
|
|
dissect_ndr_counted_string_helper(tvbuff_t *tvb, int offset,
|
|
|
|
packet_info *pinfo, proto_tree *tree,
|
2004-01-19 20:10:37 +00:00
|
|
|
guint8 *drep, int hf_index, int levels,
|
2003-02-03 02:00:54 +00:00
|
|
|
gboolean add_subtree)
|
2002-03-11 00:15:20 +00:00
|
|
|
{
|
2003-02-03 02:00:54 +00:00
|
|
|
proto_item *item;
|
|
|
|
proto_tree *subtree = tree;
|
2002-03-11 00:15:20 +00:00
|
|
|
|
2003-02-03 02:00:54 +00:00
|
|
|
if (add_subtree) {
|
2002-03-11 00:15:20 +00:00
|
|
|
|
2003-02-03 02:00:54 +00:00
|
|
|
item = proto_tree_add_text(
|
2008-10-31 15:47:47 +00:00
|
|
|
tree, tvb, offset, 0, "%s",
|
2003-02-03 02:00:54 +00:00
|
|
|
proto_registrar_get_name(hf_index));
|
2002-03-11 00:15:20 +00:00
|
|
|
|
2003-02-03 02:00:54 +00:00
|
|
|
subtree = proto_item_add_subtree(item, ett_nt_counted_string);
|
2002-03-11 00:15:20 +00:00
|
|
|
}
|
|
|
|
|
2003-02-08 09:41:44 +00:00
|
|
|
/*
|
|
|
|
* Add 2 levels, so that the string gets attached to the
|
|
|
|
* "Character Array" top-level item and to the top-level item
|
|
|
|
* added above.
|
|
|
|
*/
|
2003-02-03 02:00:54 +00:00
|
|
|
return dissect_ndr_counted_string_cb(
|
|
|
|
tvb, offset, pinfo, subtree, drep, hf_index,
|
2003-04-27 00:49:14 +00:00
|
|
|
cb_wstr_postprocess, GINT_TO_POINTER(2 + levels));
|
2002-03-11 00:15:20 +00:00
|
|
|
}
|
|
|
|
|
2003-02-03 02:00:54 +00:00
|
|
|
/* Dissect a counted string in-line. */
|
|
|
|
|
2003-01-28 06:27:01 +00:00
|
|
|
int
|
2003-02-03 02:00:54 +00:00
|
|
|
dissect_ndr_counted_string(tvbuff_t *tvb, int offset,
|
|
|
|
packet_info *pinfo, proto_tree *tree,
|
2004-01-19 20:10:37 +00:00
|
|
|
guint8 *drep, int hf_index, int levels)
|
2003-01-28 06:27:01 +00:00
|
|
|
{
|
2003-02-03 02:00:54 +00:00
|
|
|
return dissect_ndr_counted_string_helper(
|
|
|
|
tvb, offset, pinfo, tree, drep, hf_index, levels, TRUE);
|
|
|
|
}
|
2003-01-31 06:47:55 +00:00
|
|
|
|
2003-02-03 02:00:54 +00:00
|
|
|
/* Dissect a counted string as a callback to dissect_ndr_pointer().
|
|
|
|
This doesn't add a adds a proto item and subtreee for the string as
|
|
|
|
the pointer dissection already creates one. */
|
2003-01-31 06:47:55 +00:00
|
|
|
|
2003-02-03 02:00:54 +00:00
|
|
|
int
|
|
|
|
dissect_ndr_counted_string_ptr(tvbuff_t *tvb, int offset,
|
|
|
|
packet_info *pinfo, proto_tree *tree,
|
2004-01-19 20:10:37 +00:00
|
|
|
guint8 *drep)
|
2003-02-03 02:00:54 +00:00
|
|
|
{
|
|
|
|
dcerpc_info *di = pinfo->private_data;
|
|
|
|
|
|
|
|
return dissect_ndr_counted_string_helper(
|
2003-02-08 09:41:44 +00:00
|
|
|
tvb, offset, pinfo, tree, drep, di->hf_index, 0, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Dissect a counted byte_array as a callback to dissect_ndr_pointer_cb() */
|
|
|
|
|
|
|
|
static gint ett_nt_counted_byte_array = -1;
|
|
|
|
|
|
|
|
/* Dissect a counted byte array in-line. */
|
|
|
|
|
|
|
|
int
|
2003-05-09 01:43:59 +00:00
|
|
|
dissect_ndr_counted_byte_array_cb(tvbuff_t *tvb, int offset,
|
|
|
|
packet_info *pinfo, proto_tree *tree,
|
2004-01-19 20:10:37 +00:00
|
|
|
guint8 *drep, int hf_index,
|
2003-05-09 01:43:59 +00:00
|
|
|
dcerpc_callback_fnct_t *callback,
|
|
|
|
void *callback_args)
|
2003-02-08 09:41:44 +00:00
|
|
|
{
|
|
|
|
dcerpc_info *di = pinfo->private_data;
|
|
|
|
proto_item *item;
|
|
|
|
proto_tree *subtree;
|
|
|
|
guint16 len, size;
|
|
|
|
|
2009-10-04 08:11:09 +00:00
|
|
|
/* Structure starts with short, but is aligned for pointer */
|
2003-02-08 09:41:44 +00:00
|
|
|
|
2009-10-04 08:11:09 +00:00
|
|
|
ALIGN_TO_5_BYTES;
|
2003-02-08 09:41:44 +00:00
|
|
|
|
|
|
|
if (di->conformant_run)
|
|
|
|
return offset;
|
|
|
|
|
2008-10-31 15:47:47 +00:00
|
|
|
item = proto_tree_add_text(tree, tvb, offset, 0, "%s",
|
2003-02-08 09:41:44 +00:00
|
|
|
proto_registrar_get_name(hf_index));
|
|
|
|
|
|
|
|
subtree = proto_item_add_subtree(item, ett_nt_counted_byte_array);
|
2005-10-17 18:56:27 +00:00
|
|
|
|
|
|
|
/*
|
2003-02-08 09:41:44 +00:00
|
|
|
struct {
|
|
|
|
short len;
|
|
|
|
short size;
|
|
|
|
[size_is(size), length_is(len), ptr] unsigned char *string;
|
|
|
|
} WHATEVER_THIS_IS_CALLED;
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
offset = dissect_ndr_uint16(tvb, offset, pinfo, subtree, drep,
|
|
|
|
hf_nt_cs_len, &len);
|
|
|
|
|
|
|
|
offset = dissect_ndr_uint16(tvb, offset, pinfo, subtree, drep,
|
2005-10-17 18:56:27 +00:00
|
|
|
hf_nt_cs_size, &size);
|
2003-02-08 09:41:44 +00:00
|
|
|
|
2003-05-09 01:43:59 +00:00
|
|
|
offset = dissect_ndr_pointer_cb(tvb, offset, pinfo, subtree, drep,
|
2003-02-08 09:41:44 +00:00
|
|
|
dissect_ndr_char_cvstring, NDR_POINTER_UNIQUE,
|
2003-05-09 01:43:59 +00:00
|
|
|
"Byte Array", hf_index, callback, callback_args);
|
2003-02-08 09:41:44 +00:00
|
|
|
|
2009-10-04 08:11:09 +00:00
|
|
|
if (di->call_data->flags & DCERPC_IS_NDR64) {
|
|
|
|
ALIGN_TO_5_BYTES;
|
|
|
|
}
|
|
|
|
|
2003-02-08 09:41:44 +00:00
|
|
|
return offset;
|
2003-01-28 06:27:01 +00:00
|
|
|
}
|
2002-03-10 23:24:48 +00:00
|
|
|
|
2005-08-02 04:31:42 +00:00
|
|
|
static void cb_byte_array_postprocess(packet_info *pinfo, proto_tree *tree _U_,
|
2005-10-17 18:56:27 +00:00
|
|
|
proto_item *item, tvbuff_t *tvb,
|
2005-01-30 03:43:03 +00:00
|
|
|
int start_offset, int end_offset,
|
|
|
|
void *callback_args)
|
|
|
|
{
|
|
|
|
gint options = GPOINTER_TO_INT(callback_args);
|
|
|
|
gint levels = CB_STR_ITEM_LEVELS(options);
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
/* Align start_offset on 4-byte boundary. */
|
|
|
|
|
|
|
|
if (start_offset % 4)
|
|
|
|
start_offset += 4 - (start_offset % 4);
|
|
|
|
|
|
|
|
/* Get byte array value */
|
|
|
|
|
|
|
|
if ((end_offset - start_offset) <= 12)
|
|
|
|
return;
|
|
|
|
|
|
|
|
s = tvb_bytes_to_str(
|
|
|
|
tvb, start_offset + 12, (end_offset - start_offset - 12) );
|
|
|
|
|
|
|
|
/* Append string to COL_INFO */
|
|
|
|
|
|
|
|
if (options & CB_STR_COL_INFO) {
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", s);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Append string to upper-level proto_items */
|
|
|
|
|
|
|
|
if (levels > 0 && item && s && s[0]) {
|
|
|
|
proto_item_append_text(item, ": %s", s);
|
2009-09-30 07:53:12 +00:00
|
|
|
item = GET_ITEM_PARENT(item);
|
2005-01-30 03:43:03 +00:00
|
|
|
levels--;
|
|
|
|
if (levels > 0) {
|
|
|
|
proto_item_append_text(item, ": %s", s);
|
2009-09-30 07:53:12 +00:00
|
|
|
item = GET_ITEM_PARENT(item);
|
2005-01-30 03:43:03 +00:00
|
|
|
levels--;
|
|
|
|
while (levels > 0) {
|
|
|
|
proto_item_append_text(item, " %s", s);
|
2009-09-30 07:53:12 +00:00
|
|
|
item = GET_ITEM_PARENT(item);
|
2005-01-30 03:43:03 +00:00
|
|
|
levels--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-05-09 01:43:59 +00:00
|
|
|
int
|
|
|
|
dissect_ndr_counted_byte_array(tvbuff_t *tvb, int offset,
|
|
|
|
packet_info *pinfo, proto_tree *tree,
|
2005-01-30 02:52:25 +00:00
|
|
|
guint8 *drep, int hf_index, int levels)
|
2003-05-09 01:43:59 +00:00
|
|
|
{
|
|
|
|
return dissect_ndr_counted_byte_array_cb(
|
2005-01-30 03:43:03 +00:00
|
|
|
tvb, offset, pinfo, tree, drep, hf_index, cb_byte_array_postprocess, GINT_TO_POINTER(2 + levels));
|
2003-05-09 01:43:59 +00:00
|
|
|
}
|
|
|
|
|
2005-01-30 11:56:37 +00:00
|
|
|
/* Dissect a counted ascii string in-line. */
|
|
|
|
static gint ett_nt_counted_ascii_string = -1;
|
|
|
|
|
|
|
|
int
|
|
|
|
dissect_ndr_counted_ascii_string_cb(tvbuff_t *tvb, int offset,
|
|
|
|
packet_info *pinfo, proto_tree *tree,
|
|
|
|
guint8 *drep, int hf_index,
|
|
|
|
dcerpc_callback_fnct_t *callback,
|
|
|
|
void *callback_args)
|
|
|
|
{
|
|
|
|
dcerpc_info *di = pinfo->private_data;
|
|
|
|
proto_item *item;
|
|
|
|
proto_tree *subtree;
|
|
|
|
guint16 len, size;
|
|
|
|
|
2009-10-04 08:11:09 +00:00
|
|
|
/* Structure starts with short, but is aligned for pointer */
|
2005-01-30 11:56:37 +00:00
|
|
|
|
2009-10-04 08:11:09 +00:00
|
|
|
ALIGN_TO_5_BYTES;
|
2005-01-30 11:56:37 +00:00
|
|
|
|
|
|
|
if (di->conformant_run)
|
|
|
|
return offset;
|
|
|
|
|
2008-10-31 15:47:47 +00:00
|
|
|
item = proto_tree_add_text(tree, tvb, offset, 0, "%s",
|
2005-01-30 11:56:37 +00:00
|
|
|
proto_registrar_get_name(hf_index));
|
|
|
|
|
|
|
|
subtree = proto_item_add_subtree(item, ett_nt_counted_ascii_string);
|
2005-10-17 18:56:27 +00:00
|
|
|
|
|
|
|
/*
|
2005-01-30 11:56:37 +00:00
|
|
|
struct {
|
|
|
|
short len;
|
|
|
|
short size;
|
|
|
|
[size_is(size), length_is(len), ptr] unsigned char *string;
|
|
|
|
} WHATEVER_THIS_IS_CALLED;
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
offset = dissect_ndr_uint16(tvb, offset, pinfo, subtree, drep,
|
|
|
|
hf_nt_cs_len, &len);
|
|
|
|
|
|
|
|
offset = dissect_ndr_uint16(tvb, offset, pinfo, subtree, drep,
|
2005-10-17 18:56:27 +00:00
|
|
|
hf_nt_cs_size, &size);
|
2005-01-30 11:56:37 +00:00
|
|
|
|
|
|
|
offset = dissect_ndr_pointer_cb(tvb, offset, pinfo, subtree, drep,
|
|
|
|
dissect_ndr_char_cvstring, NDR_POINTER_UNIQUE,
|
|
|
|
"Ascii String", hf_index, callback, callback_args);
|
|
|
|
|
2009-10-04 08:11:09 +00:00
|
|
|
if (di->call_data->flags & DCERPC_IS_NDR64) {
|
|
|
|
ALIGN_TO_5_BYTES;
|
|
|
|
}
|
|
|
|
|
2005-01-30 11:56:37 +00:00
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
dissect_ndr_counted_ascii_string(tvbuff_t *tvb, int offset,
|
|
|
|
packet_info *pinfo, proto_tree *tree,
|
|
|
|
guint8 *drep, int hf_index, int levels)
|
|
|
|
{
|
|
|
|
return dissect_ndr_counted_ascii_string_cb(
|
|
|
|
tvb, offset, pinfo, tree, drep, hf_index, cb_str_postprocess, GINT_TO_POINTER(2 + levels));
|
|
|
|
}
|
|
|
|
|
2005-02-01 05:21:08 +00:00
|
|
|
static int hf_nt_guid = -1;
|
|
|
|
|
|
|
|
int
|
|
|
|
dissect_nt_GUID(tvbuff_t *tvb, int offset,
|
|
|
|
packet_info *pinfo, proto_tree *tree,
|
|
|
|
guint8 *drep)
|
|
|
|
{
|
|
|
|
offset=dissect_ndr_uuid_t(tvb, offset, pinfo, tree, drep, hf_nt_guid, NULL);
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2009-10-06 08:07:17 +00:00
|
|
|
/* This function is used to dissect a lsa_String
|
|
|
|
typedef [public] struct {
|
|
|
|
[value(strlen_m_term(name)*2)] uint16 name_len;
|
|
|
|
[value(strlen_m_term(name)*2)] uint16 name_size;
|
|
|
|
[string,charset(UTF16)] uint16 *name;
|
|
|
|
} lsa_String;
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
dissect_ndr_lsa_String(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *parent_tree, guint8 *drep, guint32 param, int hfindex)
|
|
|
|
{
|
|
|
|
proto_item *item = NULL;
|
|
|
|
proto_tree *tree = NULL;
|
|
|
|
dcerpc_info *di = pinfo->private_data;
|
|
|
|
int old_offset;
|
|
|
|
header_field_info *hf_info;
|
|
|
|
|
|
|
|
ALIGN_TO_5_BYTES;
|
|
|
|
|
|
|
|
old_offset = offset;
|
|
|
|
hf_info=proto_registrar_get_nth(hfindex);
|
|
|
|
|
|
|
|
if (parent_tree) {
|
|
|
|
item = proto_tree_add_text(parent_tree, tvb, offset, 0, "%s: ", hf_info->name);
|
|
|
|
tree = proto_item_add_subtree(item, ett_lsa_String);
|
|
|
|
}
|
|
|
|
|
|
|
|
offset = PIDL_dissect_uint16(tvb, offset, pinfo, tree, drep, hf_lsa_String_name_len, 0);
|
|
|
|
|
|
|
|
offset = PIDL_dissect_uint16(tvb, offset, pinfo, tree, drep, hf_lsa_String_name_size, 0);
|
|
|
|
|
|
|
|
offset = dissect_ndr_pointer_cb(
|
|
|
|
tvb, offset, pinfo, tree, drep,
|
|
|
|
dissect_ndr_wchar_cvstring, NDR_POINTER_UNIQUE,
|
|
|
|
hf_info->name, hfindex, cb_wstr_postprocess,
|
|
|
|
GINT_TO_POINTER(param));
|
|
|
|
|
|
|
|
proto_item_set_len(item, offset-old_offset);
|
|
|
|
|
|
|
|
if (di->call_data->flags & DCERPC_IS_NDR64) {
|
|
|
|
ALIGN_TO_5_BYTES;
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2002-03-10 23:24:48 +00:00
|
|
|
/* This function is used to dissect a DCERPC encoded 64 bit time value.
|
2004-08-03 02:28:49 +00:00
|
|
|
XXX it should be fixed both here and in dissect_nt_64bit_time so
|
2002-08-28 21:04:11 +00:00
|
|
|
it can handle both BIG and LITTLE endian encodings
|
2002-03-10 23:24:48 +00:00
|
|
|
*/
|
|
|
|
int
|
2002-08-28 21:04:11 +00:00
|
|
|
dissect_ndr_nt_NTTIME (tvbuff_t *tvb, int offset,
|
|
|
|
packet_info *pinfo, proto_tree *tree,
|
2004-01-19 20:10:37 +00:00
|
|
|
guint8 *drep _U_, int hf_index)
|
2002-03-10 23:24:48 +00:00
|
|
|
{
|
|
|
|
dcerpc_info *di;
|
|
|
|
|
|
|
|
di=pinfo->private_data;
|
|
|
|
if(di->conformant_run){
|
|
|
|
/*just a run to handle conformant arrays, nothing to dissect */
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
ALIGN_TO_4_BYTES;
|
|
|
|
|
2004-08-03 02:28:49 +00:00
|
|
|
offset = dissect_nt_64bit_time(tvb, tree, offset, hf_index);
|
2002-03-10 23:24:48 +00:00
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2002-03-25 05:42:02 +00:00
|
|
|
/* Define this symbol to display warnings about request/response and
|
|
|
|
policy handle hash table collisions. This happens when a packet with
|
|
|
|
the same conversation, smb fid and dcerpc call id occurs. I think this
|
|
|
|
is due to a bug in the dcerpc/smb fragment reassembly code. */
|
|
|
|
|
|
|
|
#undef DEBUG_HASH_COLL
|
|
|
|
|
|
|
|
/*
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
* Policy handle hashing.
|
|
|
|
*
|
|
|
|
* We hash based on the policy handle value; the items in the hash table
|
|
|
|
* are lists of policy handle information about one or more policy
|
|
|
|
* handles with that value. We have multiple values in case a given
|
|
|
|
* policy handle is opened in frame N, closed in frame M, and re-opened
|
|
|
|
* in frame O, where N < M < O.
|
|
|
|
*
|
|
|
|
* XXX - we really should also use a DCE RPC conversation/session handle
|
|
|
|
* of some sort, in case two separate sessions have the same handle
|
|
|
|
* value. A transport-layer conversation might not be sufficient, as you
|
|
|
|
* might, for example, have multiple pipes in a single SMB connection,
|
|
|
|
* and you might have the same handle opened and closed separately on
|
|
|
|
* those two pipes.
|
|
|
|
*
|
|
|
|
* The policy handle information has "first frame" and "last frame"
|
|
|
|
* information; the entry should be used when dissecting a given frame
|
|
|
|
* only if that frame is within the interval [first frame,last frame].
|
|
|
|
* The list is sorted by "first frame".
|
|
|
|
*
|
|
|
|
* This doesn't handle the case of a handle being opened in frame N and
|
|
|
|
* re-opened in frame M, where N < M, with no intervening close, but I'm
|
|
|
|
* not sure anything can handle that if it's within the same DCE RPC
|
|
|
|
* session (if it's not, the conversation/session handle would fix that).
|
2002-03-25 05:42:02 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
guint8 policy_hnd[20];
|
|
|
|
} pol_hash_key;
|
|
|
|
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
typedef struct {
|
|
|
|
pol_value *list; /* List of policy handle entries */
|
2002-03-25 05:42:02 +00:00
|
|
|
} pol_hash_value;
|
|
|
|
|
2005-10-17 18:56:27 +00:00
|
|
|
static GHashTable *pol_hash = NULL;
|
2002-03-25 05:42:02 +00:00
|
|
|
|
|
|
|
/* Hash function */
|
|
|
|
|
|
|
|
static guint pol_hash_fn(gconstpointer k)
|
|
|
|
{
|
2002-11-28 03:57:50 +00:00
|
|
|
const pol_hash_key *key = (const pol_hash_key *)k;
|
2002-03-25 05:42:02 +00:00
|
|
|
|
|
|
|
/* Bytes 4-7 of the policy handle are a timestamp so should make a
|
|
|
|
reasonable hash value */
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2002-03-25 05:42:02 +00:00
|
|
|
return key->policy_hnd[4] + (key->policy_hnd[5] << 8) +
|
|
|
|
(key->policy_hnd[6] << 16) + (key->policy_hnd[7] << 24);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return true if a policy handle is all zeros */
|
|
|
|
|
2002-06-28 01:23:26 +00:00
|
|
|
static gboolean is_null_pol(e_ctx_hnd *policy_hnd)
|
2002-03-25 05:42:02 +00:00
|
|
|
{
|
|
|
|
static guint8 null_policy_hnd[20];
|
|
|
|
|
|
|
|
return memcmp(policy_hnd, null_policy_hnd, 20) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Hash compare function */
|
|
|
|
|
|
|
|
static gint pol_hash_compare(gconstpointer k1, gconstpointer k2)
|
|
|
|
{
|
2002-11-28 03:57:50 +00:00
|
|
|
const pol_hash_key *key1 = (const pol_hash_key *)k1;
|
|
|
|
const pol_hash_key *key2 = (const pol_hash_key *)k2;
|
2002-03-25 05:42:02 +00:00
|
|
|
|
2002-08-28 21:04:11 +00:00
|
|
|
return memcmp(key1->policy_hnd, key2->policy_hnd,
|
2002-03-25 05:42:02 +00:00
|
|
|
sizeof(key1->policy_hnd)) == 0;
|
|
|
|
}
|
|
|
|
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
/*
|
|
|
|
* Look up the instance of a policy handle value in whose range of frames
|
|
|
|
* the specified frame falls.
|
|
|
|
*/
|
|
|
|
static pol_value *find_pol_handle(e_ctx_hnd *policy_hnd, guint32 frame,
|
|
|
|
pol_hash_value **valuep)
|
2002-03-25 05:42:02 +00:00
|
|
|
{
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
pol_hash_key key;
|
|
|
|
pol_value *pol;
|
2002-04-17 07:52:26 +00:00
|
|
|
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
memcpy(&key.policy_hnd, policy_hnd, sizeof(key.policy_hnd));
|
|
|
|
if ((*valuep = g_hash_table_lookup(pol_hash, &key))) {
|
|
|
|
/*
|
|
|
|
* Look for the first value such that both:
|
|
|
|
*
|
|
|
|
* 1) the first frame in which it was seen is
|
|
|
|
* <= the specified frame;
|
|
|
|
*
|
|
|
|
* 2) the last frame in which it was seen is
|
|
|
|
* either unknown (meaning we haven't yet
|
|
|
|
* seen a close or another open of the
|
|
|
|
* same handle, which is assumed to imply
|
|
|
|
* an intervening close that wasn't captured)
|
|
|
|
* or is >= the specified frame.
|
|
|
|
*
|
|
|
|
* If there's more than one such frame, that's the
|
|
|
|
* case where a handle is opened in frame N and
|
|
|
|
* reopened in frame M, with no intervening close;
|
|
|
|
* there is no right answer for that, so the instance
|
|
|
|
* opened in frame N is as right as anything else.
|
|
|
|
*/
|
|
|
|
for (pol = (*valuep)->list; pol != NULL; pol = pol->next) {
|
|
|
|
if (pol->first_frame <= frame &&
|
|
|
|
(pol->last_frame == 0 ||
|
|
|
|
pol->last_frame >= frame))
|
|
|
|
break; /* found one */
|
|
|
|
}
|
|
|
|
return pol;
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* The handle isn't in the hash table.
|
|
|
|
*/
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2002-03-25 05:42:02 +00:00
|
|
|
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
static void add_pol_handle(e_ctx_hnd *policy_hnd, guint32 frame,
|
|
|
|
pol_value *pol, pol_hash_value *value)
|
|
|
|
{
|
|
|
|
pol_hash_key *key;
|
|
|
|
pol_value *polprev, *polnext;
|
|
|
|
|
|
|
|
if (value == NULL) {
|
|
|
|
/*
|
|
|
|
* There's no hash value; create one, put the new
|
|
|
|
* value at the beginning of its policy handle list,
|
|
|
|
* and put the hash value in the policy handle hash
|
|
|
|
* table.
|
|
|
|
*/
|
2005-08-13 01:29:31 +00:00
|
|
|
value = se_alloc(sizeof(pol_hash_value));
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
value->list = pol;
|
|
|
|
pol->next = NULL;
|
2005-08-13 01:29:31 +00:00
|
|
|
key = se_alloc(sizeof(pol_hash_key));
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
memcpy(&key->policy_hnd, policy_hnd, sizeof(key->policy_hnd));
|
|
|
|
g_hash_table_insert(pol_hash, key, value);
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Put the new value in the hash value's policy handle
|
|
|
|
* list so that it's sorted by the first frame in
|
|
|
|
* which it appeared.
|
|
|
|
*
|
|
|
|
* Search for the first entry whose first frame number
|
|
|
|
* is greater than the current frame number, if any.
|
|
|
|
*/
|
|
|
|
for (polnext = value->list, polprev = NULL;
|
|
|
|
polnext != NULL && polnext->first_frame <= frame;
|
|
|
|
polprev = polnext, polnext = polnext->next)
|
|
|
|
;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "polprev" points to the entry in the list after
|
|
|
|
* which we should put the new entry; if it's null,
|
|
|
|
* that means we should put it at the beginning of
|
|
|
|
* the list.
|
|
|
|
*/
|
|
|
|
if (polprev == NULL)
|
|
|
|
value->list = pol;
|
|
|
|
else
|
|
|
|
polprev->next = pol;
|
2005-10-17 18:56:27 +00:00
|
|
|
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
/*
|
|
|
|
* "polnext" points to the entry in the list before
|
|
|
|
* which we should put the new entry; if it's null,
|
|
|
|
* that means we should put it at the end of the list.
|
|
|
|
*/
|
|
|
|
pol->next = polnext;
|
|
|
|
}
|
|
|
|
}
|
2002-03-25 05:42:02 +00:00
|
|
|
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
/* Store the open and close frame numbers of a policy handle */
|
2002-03-25 05:42:02 +00:00
|
|
|
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
void dcerpc_smb_store_pol_pkts(e_ctx_hnd *policy_hnd, packet_info *pinfo,
|
|
|
|
gboolean is_open, gboolean is_close)
|
|
|
|
{
|
|
|
|
pol_hash_value *value;
|
|
|
|
pol_value *pol;
|
2002-03-25 05:42:02 +00:00
|
|
|
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
/*
|
|
|
|
* By the time the first pass is done, the policy handle database
|
|
|
|
* has been completely constructed. If we've already seen this
|
|
|
|
* frame, there's nothing to do.
|
|
|
|
*/
|
|
|
|
if (pinfo->fd->flags.visited)
|
|
|
|
return;
|
2002-03-25 05:42:02 +00:00
|
|
|
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
if (is_null_pol(policy_hnd))
|
|
|
|
return;
|
2002-03-25 05:42:02 +00:00
|
|
|
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
/* Look up existing value */
|
|
|
|
pol = find_pol_handle(policy_hnd, pinfo->fd->num, &value);
|
|
|
|
|
|
|
|
if (pol != NULL) {
|
|
|
|
/*
|
|
|
|
* Update the existing value as appropriate.
|
|
|
|
*/
|
|
|
|
if (is_open) {
|
|
|
|
/*
|
|
|
|
* This is an open; we assume that we missed
|
|
|
|
* a close of this handle, so we set its
|
|
|
|
* "last frame" value and act as if we didn't
|
|
|
|
* see it.
|
|
|
|
*
|
|
|
|
* XXX - note that we might be called twice for
|
|
|
|
* the same operation (see "dissect_pipe_dcerpc()",
|
|
|
|
* which calls the DCE RPC dissector twice), so we
|
|
|
|
* must first check to see if this is a handle we
|
|
|
|
* just filled in.
|
|
|
|
*
|
|
|
|
* We check whether this handle's "first frame"
|
|
|
|
* frame number is this frame and its "last frame
|
|
|
|
* is 0; if so, this is presumably a duplicate call,
|
|
|
|
* and we don't do an implicit close.
|
|
|
|
*/
|
|
|
|
if (pol->first_frame == pinfo->fd->num &&
|
|
|
|
pol->last_frame == 0)
|
|
|
|
return;
|
|
|
|
pol->last_frame = pinfo->fd->num;
|
|
|
|
pol = NULL;
|
|
|
|
} else {
|
|
|
|
if (is_close) {
|
|
|
|
pol->close_frame = pinfo->fd->num;
|
|
|
|
pol->last_frame = pinfo->fd->num;
|
|
|
|
}
|
|
|
|
return;
|
2002-03-25 05:42:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create a new value */
|
|
|
|
|
2005-08-13 01:29:31 +00:00
|
|
|
pol = se_alloc(sizeof(pol_value));
|
2002-03-25 05:42:02 +00:00
|
|
|
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
pol->open_frame = is_open ? pinfo->fd->num : 0;
|
|
|
|
pol->close_frame = is_close ? pinfo->fd->num : 0;
|
|
|
|
pol->first_frame = pinfo->fd->num;
|
|
|
|
pol->last_frame = pol->close_frame; /* if 0, unknown; if non-0, known */
|
2007-08-28 11:45:08 +00:00
|
|
|
pol->type=0;
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
pol->name = NULL;
|
2002-06-28 01:23:26 +00:00
|
|
|
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
add_pol_handle(policy_hnd, pinfo->fd->num, pol, value);
|
2002-06-28 01:23:26 +00:00
|
|
|
}
|
|
|
|
|
2007-08-28 11:45:08 +00:00
|
|
|
/* Store the type of a policy handle */
|
|
|
|
static void dcerpc_store_polhnd_type(e_ctx_hnd *policy_hnd, packet_info *pinfo,
|
|
|
|
guint32 type)
|
|
|
|
{
|
|
|
|
pol_hash_value *value;
|
|
|
|
pol_value *pol;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* By the time the first pass is done, the policy handle database
|
|
|
|
* has been completely constructed. If we've already seen this
|
|
|
|
* frame, there's nothing to do.
|
|
|
|
*/
|
|
|
|
if (pinfo->fd->flags.visited)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (is_null_pol(policy_hnd))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Look up existing value */
|
|
|
|
pol = find_pol_handle(policy_hnd, pinfo->fd->num, &value);
|
2002-06-28 01:23:26 +00:00
|
|
|
|
2007-08-28 11:45:08 +00:00
|
|
|
if (pol != NULL) {
|
|
|
|
/*
|
|
|
|
* Update the existing value as appropriate.
|
|
|
|
*/
|
|
|
|
pol->type=type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Store a text string with a policy handle */
|
|
|
|
void dcerpc_store_polhnd_name(e_ctx_hnd *policy_hnd, packet_info *pinfo,
|
2005-07-26 08:01:16 +00:00
|
|
|
const char *name)
|
2002-06-28 01:23:26 +00:00
|
|
|
{
|
|
|
|
pol_hash_value *value;
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
pol_value *pol;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* By the time the first pass is done, the policy handle database
|
|
|
|
* has been completely constructed. If we've already seen this
|
|
|
|
* frame, there's nothing to do.
|
|
|
|
*/
|
|
|
|
if (pinfo->fd->flags.visited)
|
|
|
|
return;
|
2002-06-28 01:23:26 +00:00
|
|
|
|
|
|
|
if (is_null_pol(policy_hnd))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Look up existing value */
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
pol = find_pol_handle(policy_hnd, pinfo->fd->num, &value);
|
|
|
|
|
|
|
|
if (pol != NULL) {
|
|
|
|
/*
|
|
|
|
* This is the first pass; update the existing
|
|
|
|
* value as appropriate.
|
|
|
|
*/
|
|
|
|
if (pol->name && name) {
|
2002-06-28 01:23:26 +00:00
|
|
|
#ifdef DEBUG_HASH_COLL
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
if (strcmp(pol->name, name) != 0)
|
2002-06-28 01:23:26 +00:00
|
|
|
g_warning("dcerpc_smb: pol_hash name collision %s/%s\n", value->name, name);
|
|
|
|
#endif
|
2008-03-17 17:40:54 +00:00
|
|
|
/* pol->name is se_allocated, don't free it now */
|
2002-06-28 01:23:26 +00:00
|
|
|
}
|
|
|
|
|
2008-03-17 17:40:54 +00:00
|
|
|
pol->name = se_strdup(name);
|
2002-06-28 01:23:26 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create a new value */
|
|
|
|
|
2005-08-13 01:29:31 +00:00
|
|
|
pol = se_alloc(sizeof(pol_value));
|
2002-06-28 01:23:26 +00:00
|
|
|
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
pol->open_frame = 0;
|
|
|
|
pol->close_frame = 0;
|
|
|
|
pol->first_frame = pinfo->fd->num;
|
|
|
|
pol->last_frame = 0;
|
2007-08-28 11:45:08 +00:00
|
|
|
pol->type = 0;
|
2002-03-25 05:42:02 +00:00
|
|
|
if (name)
|
2008-03-17 17:40:54 +00:00
|
|
|
pol->name = se_strdup(name);
|
2002-03-25 05:42:02 +00:00
|
|
|
else
|
2008-03-17 17:40:54 +00:00
|
|
|
pol->name = se_strdup("<UNKNOWN>");
|
2002-03-25 05:42:02 +00:00
|
|
|
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
add_pol_handle(policy_hnd, pinfo->fd->num, pol, value);
|
2002-03-25 05:42:02 +00:00
|
|
|
}
|
|
|
|
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
/*
|
|
|
|
* Retrieve a policy handle.
|
|
|
|
*
|
|
|
|
* XXX - should this get an "is_close" argument, and match even closed
|
|
|
|
* policy handles if the call is a close, so we can handle retransmitted
|
|
|
|
* close operations?
|
|
|
|
*/
|
2002-03-25 05:42:02 +00:00
|
|
|
|
2008-03-17 17:40:54 +00:00
|
|
|
gboolean dcerpc_fetch_polhnd_data(e_ctx_hnd *policy_hnd,
|
2007-08-28 11:45:08 +00:00
|
|
|
char **name, guint32 *type,
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
guint32 *open_frame, guint32 *close_frame,
|
|
|
|
guint32 cur_frame)
|
2002-03-25 05:42:02 +00:00
|
|
|
{
|
|
|
|
pol_hash_value *value;
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
pol_value *pol;
|
2002-03-25 05:42:02 +00:00
|
|
|
|
|
|
|
/* Prevent uninitialised return vars */
|
|
|
|
|
|
|
|
if (name)
|
|
|
|
*name = NULL;
|
|
|
|
|
2007-08-28 11:45:08 +00:00
|
|
|
if (type)
|
|
|
|
*type = 0;
|
|
|
|
|
2002-03-25 05:42:02 +00:00
|
|
|
if (open_frame)
|
|
|
|
*open_frame = 0;
|
|
|
|
|
|
|
|
if (close_frame)
|
|
|
|
*close_frame = 0;
|
2008-03-17 17:40:54 +00:00
|
|
|
|
2002-03-25 05:42:02 +00:00
|
|
|
/* Look up existing value */
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
pol = find_pol_handle(policy_hnd, cur_frame, &value);
|
2002-03-25 05:42:02 +00:00
|
|
|
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
if (pol) {
|
2002-06-28 01:23:26 +00:00
|
|
|
if (name)
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
*name = pol->name;
|
2002-03-25 05:42:02 +00:00
|
|
|
|
2007-08-28 11:45:08 +00:00
|
|
|
if (type)
|
|
|
|
*type = pol->type;
|
|
|
|
|
2002-06-28 01:23:26 +00:00
|
|
|
if (open_frame)
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
*open_frame = pol->open_frame;
|
2002-03-25 05:42:02 +00:00
|
|
|
|
2002-06-28 01:23:26 +00:00
|
|
|
if (close_frame)
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
*close_frame = pol->close_frame;
|
2002-06-28 01:23:26 +00:00
|
|
|
}
|
2002-03-25 05:42:02 +00:00
|
|
|
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
return pol != NULL;
|
2002-03-25 05:42:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Initialise policy handle hash */
|
|
|
|
|
|
|
|
static void init_pol_hash(void)
|
|
|
|
{
|
|
|
|
/* Initialise hash table */
|
|
|
|
|
|
|
|
if (pol_hash) {
|
2008-03-17 17:40:54 +00:00
|
|
|
/* Everything in the table is se_ allocated so there's no
|
|
|
|
* need to go through and free it all.
|
|
|
|
*/
|
2002-03-25 05:42:02 +00:00
|
|
|
g_hash_table_destroy(pol_hash);
|
|
|
|
}
|
|
|
|
|
|
|
|
pol_hash = g_hash_table_new(pol_hash_fn, pol_hash_compare);
|
|
|
|
}
|
|
|
|
|
2002-04-16 02:02:04 +00:00
|
|
|
/* Dissect a NT status code */
|
|
|
|
|
|
|
|
int
|
|
|
|
dissect_ntstatus(tvbuff_t *tvb, gint offset, packet_info *pinfo,
|
2004-01-19 20:10:37 +00:00
|
|
|
proto_tree *tree, guint8 *drep,
|
2002-04-16 02:02:04 +00:00
|
|
|
int hfindex, guint32 *pdata)
|
|
|
|
{
|
|
|
|
guint32 status;
|
|
|
|
|
|
|
|
offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
|
|
|
|
hfindex, &status);
|
|
|
|
|
2003-01-16 22:40:48 +00:00
|
|
|
if (status != 0 && check_col(pinfo->cinfo, COL_INFO))
|
2002-04-16 02:02:04 +00:00
|
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
|
2002-08-28 21:04:11 +00:00
|
|
|
val_to_str(status, NT_errors,
|
2002-06-25 02:58:11 +00:00
|
|
|
"Unknown error 0x%08x"));
|
2002-04-16 02:02:04 +00:00
|
|
|
if (pdata)
|
|
|
|
*pdata = status;
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
2002-04-17 07:52:26 +00:00
|
|
|
|
2002-05-09 02:44:22 +00:00
|
|
|
/* Dissect a DOS status code */
|
|
|
|
|
|
|
|
int
|
|
|
|
dissect_doserror(tvbuff_t *tvb, gint offset, packet_info *pinfo,
|
2004-01-19 20:10:37 +00:00
|
|
|
proto_tree *tree, guint8 *drep,
|
2002-05-09 02:44:22 +00:00
|
|
|
int hfindex, guint32 *pdata)
|
|
|
|
{
|
|
|
|
guint32 status;
|
|
|
|
|
|
|
|
offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, drep,
|
|
|
|
hfindex, &status);
|
|
|
|
|
2003-01-16 22:40:48 +00:00
|
|
|
if (status != 0 && check_col(pinfo->cinfo, COL_INFO))
|
2002-05-09 02:44:22 +00:00
|
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
|
2002-08-28 21:04:11 +00:00
|
|
|
val_to_str(status, DOS_errors,
|
2002-06-25 02:57:39 +00:00
|
|
|
"Unknown error 0x%08x"));
|
2002-05-09 02:44:22 +00:00
|
|
|
if (pdata)
|
|
|
|
*pdata = status;
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2002-04-17 07:52:26 +00:00
|
|
|
/* Dissect a NT policy handle */
|
|
|
|
|
2003-01-24 05:32:54 +00:00
|
|
|
static int hf_nt_policy_open_frame = -1;
|
|
|
|
static int hf_nt_policy_close_frame = -1;
|
|
|
|
|
2003-02-03 02:00:54 +00:00
|
|
|
static gint ett_nt_policy_hnd = -1;
|
|
|
|
|
2005-11-11 22:12:10 +00:00
|
|
|
/* this function is used to dissect a "handle".
|
2007-03-11 06:16:00 +00:00
|
|
|
* it will keep track of which frame a handle is opened from and in which
|
2005-11-11 22:12:10 +00:00
|
|
|
* frame it is closed.
|
|
|
|
* normally, this function would be used for tracking 20 byte policy handles
|
|
|
|
* as used in dcerpc but it has shown VERY useful to also use it for tracking
|
|
|
|
* GUIDs such as for the file ids in smb2.
|
|
|
|
*/
|
2006-03-19 20:21:56 +00:00
|
|
|
typedef enum {
|
|
|
|
HND_TYPE_CTX_HANDLE,
|
|
|
|
HND_TYPE_GUID
|
|
|
|
} e_hnd_type;
|
|
|
|
|
2005-11-22 12:51:14 +00:00
|
|
|
static int
|
2005-11-11 22:12:10 +00:00
|
|
|
dissect_nt_hnd(tvbuff_t *tvb, gint offset, packet_info *pinfo,
|
2004-01-19 20:10:37 +00:00
|
|
|
proto_tree *tree, guint8 *drep, int hfindex,
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
e_ctx_hnd *pdata, proto_item **pitem,
|
2006-03-19 20:21:56 +00:00
|
|
|
gboolean is_open, gboolean is_close, e_hnd_type type)
|
2002-04-17 07:52:26 +00:00
|
|
|
{
|
2006-03-07 20:52:23 +00:00
|
|
|
proto_item *item=NULL;
|
2002-04-17 07:52:26 +00:00
|
|
|
proto_tree *subtree;
|
|
|
|
e_ctx_hnd hnd;
|
2002-04-22 09:43:03 +00:00
|
|
|
guint32 open_frame = 0, close_frame = 0;
|
2002-04-17 07:52:26 +00:00
|
|
|
char *name;
|
2002-05-07 00:35:14 +00:00
|
|
|
int old_offset = offset;
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
dcerpc_info *di;
|
|
|
|
|
|
|
|
di=pinfo->private_data;
|
|
|
|
if(di->conformant_run){
|
|
|
|
/*
|
|
|
|
* just a run to handle conformant arrays, no scalars to
|
|
|
|
* dissect - and "dissect_ndr_ctx_hnd()" won't return
|
|
|
|
* a handle, so we can't do the hashing stuff in any
|
|
|
|
* case
|
|
|
|
*/
|
|
|
|
return offset;
|
|
|
|
}
|
2002-04-17 07:52:26 +00:00
|
|
|
|
|
|
|
/* Add to proto tree */
|
|
|
|
|
2005-11-11 22:12:10 +00:00
|
|
|
switch(type){
|
|
|
|
case HND_TYPE_CTX_HANDLE:
|
|
|
|
item = proto_tree_add_text(tree, tvb, offset, sizeof(e_ctx_hnd),
|
|
|
|
"Policy Handle");
|
|
|
|
|
|
|
|
subtree = proto_item_add_subtree(item, ett_nt_policy_hnd);
|
2002-04-17 07:52:26 +00:00
|
|
|
|
2005-11-11 22:12:10 +00:00
|
|
|
offset = dissect_ndr_ctx_hnd(tvb, offset, pinfo, subtree, drep,
|
|
|
|
hfindex, &hnd);
|
|
|
|
break;
|
|
|
|
case HND_TYPE_GUID:
|
2005-11-12 01:21:43 +00:00
|
|
|
item = proto_tree_add_text(tree, tvb, offset, 16,
|
2005-11-11 22:12:10 +00:00
|
|
|
"GUID handle");
|
2002-04-17 07:52:26 +00:00
|
|
|
|
2005-11-11 22:12:10 +00:00
|
|
|
subtree = proto_item_add_subtree(item, ett_nt_policy_hnd);
|
|
|
|
|
|
|
|
hnd.attributes=0;
|
|
|
|
offset=dissect_ndr_uuid_t(tvb, offset, pinfo, subtree, drep, hfindex, &hnd.uuid);
|
|
|
|
break;
|
2006-03-19 20:21:56 +00:00
|
|
|
default:
|
|
|
|
DISSECTOR_ASSERT_NOT_REACHED();
|
|
|
|
return offset;
|
2005-11-11 22:12:10 +00:00
|
|
|
}
|
2002-04-17 07:52:26 +00:00
|
|
|
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
/*
|
|
|
|
* Create a new entry for this handle if it's not a null handle
|
|
|
|
* and no entry already exists, and, in any case, set the
|
|
|
|
* open, close, first, and last frame information as appropriate.
|
|
|
|
*/
|
|
|
|
dcerpc_smb_store_pol_pkts(&hnd, pinfo, is_open, is_close);
|
2002-05-11 22:29:43 +00:00
|
|
|
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
/* Insert open/close/name information if known */
|
2008-03-17 17:40:54 +00:00
|
|
|
if (dcerpc_fetch_polhnd_data(&hnd, &name, NULL, &open_frame,
|
2007-08-28 11:45:08 +00:00
|
|
|
&close_frame, pinfo->fd->num)) {
|
2002-04-17 07:52:26 +00:00
|
|
|
|
2005-02-16 10:25:00 +00:00
|
|
|
if (open_frame) {
|
2008-06-26 00:16:58 +00:00
|
|
|
proto_item *item_local;
|
2008-06-26 02:29:13 +00:00
|
|
|
item_local=proto_tree_add_uint(
|
2003-01-24 05:32:54 +00:00
|
|
|
subtree, hf_nt_policy_open_frame, tvb,
|
|
|
|
old_offset, sizeof(e_ctx_hnd), open_frame);
|
2008-06-26 00:16:58 +00:00
|
|
|
PROTO_ITEM_SET_GENERATED(item_local);
|
2005-02-16 10:25:00 +00:00
|
|
|
}
|
|
|
|
if (close_frame) {
|
2008-06-26 00:16:58 +00:00
|
|
|
proto_item *item_local;
|
|
|
|
item_local=proto_tree_add_uint(
|
2003-01-24 05:32:54 +00:00
|
|
|
subtree, hf_nt_policy_close_frame, tvb,
|
|
|
|
old_offset, sizeof(e_ctx_hnd), close_frame);
|
2008-06-26 00:16:58 +00:00
|
|
|
PROTO_ITEM_SET_GENERATED(item_local);
|
2005-02-16 10:25:00 +00:00
|
|
|
}
|
2003-01-24 05:32:54 +00:00
|
|
|
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
/*
|
|
|
|
* Don't append the handle name if pitem is null; that's
|
|
|
|
* an indication that our caller will do so, as we're
|
|
|
|
* supplying a pointer to the item so that they can do
|
|
|
|
* so.
|
|
|
|
*/
|
|
|
|
if (name != NULL && pitem == NULL)
|
2002-05-11 22:29:43 +00:00
|
|
|
proto_item_append_text(item, ": %s", name);
|
2002-04-17 07:52:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (pdata)
|
|
|
|
*pdata = hnd;
|
|
|
|
|
In the policy handle hashing, handle more than one policy handle having
the same value, as an open might return handle XXX, handle XXX might
then be closed, and a subsequent handle might return handle XXX, and we
want to keep the two handles distinct to avoid, for example, displaying
handles closed before they're opened.
In policy handle open replies, store the handle name only if the
operation succeeded. We can now do that without parsing the packet
twice.
Have "dissect_nt_policy_hnd()" optionally return, through a pointer, the
protocol tree item for the handle, so that its caller can decorate the
item with the name of the handle - that's done on opens, where we do
that only if the operation succeeds.
svn path=/trunk/; revision=7787
2003-06-05 04:22:04 +00:00
|
|
|
if (pitem)
|
|
|
|
*pitem = item;
|
|
|
|
|
2002-04-17 07:52:26 +00:00
|
|
|
return offset;
|
|
|
|
}
|
2002-05-09 02:44:22 +00:00
|
|
|
|
2005-11-11 22:12:10 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
dissect_nt_policy_hnd(tvbuff_t *tvb, gint offset, packet_info *pinfo,
|
|
|
|
proto_tree *tree, guint8 *drep, int hfindex,
|
|
|
|
e_ctx_hnd *pdata, proto_item **pitem,
|
|
|
|
gboolean is_open, gboolean is_close)
|
|
|
|
{
|
|
|
|
offset=dissect_nt_hnd(tvb, offset, pinfo,
|
|
|
|
tree, drep, hfindex,
|
|
|
|
pdata, pitem,
|
|
|
|
is_open, is_close, HND_TYPE_CTX_HANDLE);
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2007-03-11 06:16:00 +00:00
|
|
|
/* This function is called from PIDL generated dissectors to dissect a
|
2007-02-20 09:01:50 +00:00
|
|
|
* NT style policy handle (contect handle).
|
|
|
|
*
|
|
|
|
* param can be used to specify where policy handles are opened and closed
|
|
|
|
* by setting PARAM_VALUE to
|
|
|
|
* PIDL_POLHND_OPEN where the policy handle is opened/created
|
|
|
|
* PIDL_POLHND_CLOSE where it is closed.
|
2007-03-11 06:16:00 +00:00
|
|
|
* This enables policy handle tracking so that when a policy handle is
|
2007-02-20 09:01:50 +00:00
|
|
|
* dissected it will be so as an expansion showing which frame it was
|
|
|
|
* opened/closed in.
|
|
|
|
*
|
2007-03-11 06:16:00 +00:00
|
|
|
* See conformance file for winreg (epan/dissectors/pidl/winreg.cnf)
|
2007-02-20 09:01:50 +00:00
|
|
|
* for examples.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
PIDL_dissect_policy_hnd(tvbuff_t *tvb, gint offset, packet_info *pinfo,
|
|
|
|
proto_tree *tree, guint8 *drep, int hfindex,
|
|
|
|
guint32 param)
|
|
|
|
{
|
2007-02-21 20:21:11 +00:00
|
|
|
e_ctx_hnd policy_hnd;
|
|
|
|
dcerpc_info *di;
|
|
|
|
|
|
|
|
di=pinfo->private_data;
|
|
|
|
|
2007-02-20 09:01:50 +00:00
|
|
|
offset=dissect_nt_hnd(tvb, offset, pinfo,
|
|
|
|
tree, drep, hfindex,
|
2007-02-21 20:21:11 +00:00
|
|
|
&policy_hnd, NULL,
|
2007-02-20 09:01:50 +00:00
|
|
|
param&PIDL_POLHND_OPEN, param&PIDL_POLHND_CLOSE,
|
|
|
|
HND_TYPE_CTX_HANDLE);
|
|
|
|
|
2007-03-11 06:16:00 +00:00
|
|
|
/* If this was an open/create and we dont yet have a policy name
|
2007-02-21 20:21:11 +00:00
|
|
|
* then create one.
|
2007-03-11 06:16:00 +00:00
|
|
|
* XXX We do not yet have the infrastructure to know the name of the
|
2007-02-21 20:21:11 +00:00
|
|
|
* actual object so just show it as <...> for the time being.
|
|
|
|
*/
|
2007-03-11 06:16:00 +00:00
|
|
|
if((param&PIDL_POLHND_OPEN)
|
2007-02-21 20:21:11 +00:00
|
|
|
&& !pinfo->fd->flags.visited
|
|
|
|
&& !di->conformant_run){
|
2007-05-07 19:21:37 +00:00
|
|
|
char *pol_string=NULL;
|
2007-02-21 20:21:11 +00:00
|
|
|
char *pol_name=NULL;
|
2007-05-07 19:21:37 +00:00
|
|
|
dcerpc_call_value *dcv;
|
2007-02-21 20:21:11 +00:00
|
|
|
|
2007-05-07 19:21:37 +00:00
|
|
|
dcv = (dcerpc_call_value *)di->call_data;
|
|
|
|
pol_name = dcv->private_data;
|
|
|
|
if(!pol_name){
|
|
|
|
pol_name="<...>";
|
|
|
|
}
|
|
|
|
pol_string=ep_strdup_printf("%s(%s)", pinfo->dcerpc_procedure_name, pol_name);
|
2007-08-28 11:45:08 +00:00
|
|
|
dcerpc_store_polhnd_name(&policy_hnd, pinfo, pol_string);
|
|
|
|
dcerpc_store_polhnd_type(&policy_hnd, pinfo, param&PIDL_POLHND_TYPE_MASK);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Track this policy handle for the response */
|
|
|
|
if(!pinfo->fd->flags.visited
|
|
|
|
&& !di->conformant_run){
|
|
|
|
dcerpc_call_value *dcv;
|
|
|
|
|
|
|
|
dcv = (dcerpc_call_value *)di->call_data;
|
|
|
|
if(!dcv->pol){
|
|
|
|
dcv->pol=se_memdup(&policy_hnd, sizeof(e_ctx_hnd));
|
|
|
|
}
|
2007-02-21 20:21:11 +00:00
|
|
|
}
|
|
|
|
|
2007-02-20 09:01:50 +00:00
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2005-11-11 22:12:10 +00:00
|
|
|
/* this function must be called with hfindex being HF_GUID */
|
|
|
|
int
|
|
|
|
dissect_nt_guid_hnd(tvbuff_t *tvb, gint offset, packet_info *pinfo,
|
|
|
|
proto_tree *tree, guint8 *drep, int hfindex,
|
|
|
|
e_ctx_hnd *pdata, proto_item **pitem,
|
|
|
|
gboolean is_open, gboolean is_close)
|
|
|
|
{
|
|
|
|
offset=dissect_nt_hnd(tvb, offset, pinfo,
|
|
|
|
tree, drep, hfindex,
|
|
|
|
pdata, pitem,
|
|
|
|
is_open, is_close, HND_TYPE_GUID);
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2002-05-09 02:44:22 +00:00
|
|
|
/* Some helper routines to dissect a range of uint8 characters. I don't
|
|
|
|
think these are "official" NDR representations and are probably specific
|
|
|
|
to NT so for the moment they're put here instead of in packet-dcerpc.c
|
|
|
|
and packet-dcerpc-ndr.c. */
|
|
|
|
|
|
|
|
int
|
|
|
|
dissect_dcerpc_uint8s(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
|
2004-01-19 20:10:37 +00:00
|
|
|
proto_tree *tree, guint8 *drep, int hfindex,
|
2002-11-28 03:57:50 +00:00
|
|
|
int length, const guint8 **pdata)
|
2002-05-09 02:44:22 +00:00
|
|
|
{
|
2002-11-28 03:57:50 +00:00
|
|
|
const guint8 *data;
|
2002-05-09 02:44:22 +00:00
|
|
|
|
2002-11-28 03:57:50 +00:00
|
|
|
data = (const guint8 *)tvb_get_ptr(tvb, offset, length);
|
2002-05-09 02:44:22 +00:00
|
|
|
|
|
|
|
if (tree) {
|
|
|
|
proto_tree_add_item (tree, hfindex, tvb, offset, length, (drep[0] & 0x10));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pdata)
|
|
|
|
*pdata = data;
|
|
|
|
|
|
|
|
return offset + length;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
dissect_ndr_uint8s(tvbuff_t *tvb, gint offset, packet_info *pinfo,
|
2004-01-19 20:10:37 +00:00
|
|
|
proto_tree *tree, guint8 *drep,
|
2002-11-28 03:57:50 +00:00
|
|
|
int hfindex, int length, const guint8 **pdata)
|
2002-05-09 02:44:22 +00:00
|
|
|
{
|
|
|
|
dcerpc_info *di;
|
|
|
|
|
|
|
|
di=pinfo->private_data;
|
|
|
|
if(di->conformant_run){
|
|
|
|
/* just a run to handle conformant arrays, no scalars to dissect */
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* no alignment needed */
|
2002-08-28 21:04:11 +00:00
|
|
|
return dissect_dcerpc_uint8s(tvb, offset, pinfo,
|
2002-05-09 02:44:22 +00:00
|
|
|
tree, drep, hfindex, length, pdata);
|
|
|
|
}
|
2002-06-05 04:17:47 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
dissect_dcerpc_uint16s(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
|
2004-01-19 20:10:37 +00:00
|
|
|
proto_tree *tree, guint8 *drep, int hfindex,
|
2002-11-28 21:03:36 +00:00
|
|
|
int length)
|
2002-06-05 04:17:47 +00:00
|
|
|
{
|
|
|
|
if (tree) {
|
|
|
|
proto_tree_add_item (tree, hfindex, tvb, offset, length * 2, (drep[0] & 0x10));
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset + length * 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
dissect_ndr_uint16s(tvbuff_t *tvb, gint offset, packet_info *pinfo,
|
2004-01-19 20:10:37 +00:00
|
|
|
proto_tree *tree, guint8 *drep,
|
2002-11-28 21:03:36 +00:00
|
|
|
int hfindex, int length)
|
2002-06-05 04:17:47 +00:00
|
|
|
{
|
|
|
|
dcerpc_info *di;
|
|
|
|
|
|
|
|
di=pinfo->private_data;
|
|
|
|
if(di->conformant_run){
|
|
|
|
/* just a run to handle conformant arrays, no scalars to dissect */
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (offset % 2)
|
|
|
|
offset++;
|
|
|
|
|
2002-08-28 21:04:11 +00:00
|
|
|
return dissect_dcerpc_uint16s(tvb, offset, pinfo,
|
2002-11-28 21:03:36 +00:00
|
|
|
tree, drep, hfindex, length);
|
2002-06-05 04:17:47 +00:00
|
|
|
}
|
2003-01-24 05:32:54 +00:00
|
|
|
|
2003-01-28 06:27:01 +00:00
|
|
|
/*
|
|
|
|
* Helper routines for dissecting NDR strings
|
|
|
|
*/
|
2003-04-27 00:49:14 +00:00
|
|
|
void cb_wstr_postprocess(packet_info *pinfo, proto_tree *tree _U_,
|
2005-10-17 18:56:27 +00:00
|
|
|
proto_item *item, tvbuff_t *tvb,
|
2003-01-28 06:27:01 +00:00
|
|
|
int start_offset, int end_offset,
|
|
|
|
void *callback_args)
|
|
|
|
{
|
|
|
|
gint options = GPOINTER_TO_INT(callback_args);
|
2003-01-30 08:19:39 +00:00
|
|
|
gint levels = CB_STR_ITEM_LEVELS(options);
|
2003-01-28 06:27:01 +00:00
|
|
|
char *s;
|
|
|
|
|
2003-01-30 06:08:10 +00:00
|
|
|
/* Align start_offset on 4-byte boundary. */
|
|
|
|
|
|
|
|
if (start_offset % 4)
|
|
|
|
start_offset += 4 - (start_offset % 4);
|
|
|
|
|
2003-01-28 06:27:01 +00:00
|
|
|
/* Get string value */
|
|
|
|
|
|
|
|
if ((end_offset - start_offset) <= 12)
|
|
|
|
return; /* XXX: Use unistr2 dissector instead? */
|
|
|
|
|
2003-07-01 00:59:43 +00:00
|
|
|
/*
|
|
|
|
* XXX - need to handle non-printable characters here.
|
|
|
|
*
|
|
|
|
* XXX - this is typically called after the string has already
|
|
|
|
* been fetched and processed by some other routine; is there
|
|
|
|
* some way we can get that string, rather than duplicating the
|
|
|
|
* efforts of that routine?
|
|
|
|
*/
|
2005-08-10 14:17:27 +00:00
|
|
|
s = tvb_get_ephemeral_faked_unicode(
|
2003-02-24 01:22:30 +00:00
|
|
|
tvb, start_offset + 12, (end_offset - start_offset - 12) / 2,
|
|
|
|
TRUE);
|
2003-01-28 06:27:01 +00:00
|
|
|
|
|
|
|
/* Append string to COL_INFO */
|
|
|
|
|
|
|
|
if (options & CB_STR_COL_INFO) {
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", s);
|
|
|
|
}
|
|
|
|
|
2003-01-30 08:19:39 +00:00
|
|
|
/* Append string to upper-level proto_items */
|
2003-02-25 02:04:56 +00:00
|
|
|
if (levels > 0 && item && s && s[0]) {
|
2003-01-28 06:27:01 +00:00
|
|
|
proto_item_append_text(item, ": %s", s);
|
2009-09-30 07:53:12 +00:00
|
|
|
item = GET_ITEM_PARENT(item);
|
2003-01-30 08:19:39 +00:00
|
|
|
levels--;
|
2010-02-04 23:13:05 +00:00
|
|
|
if (item && levels > 0) {
|
2003-01-30 08:19:39 +00:00
|
|
|
proto_item_append_text(item, ": %s", s);
|
2009-09-30 07:53:12 +00:00
|
|
|
item = GET_ITEM_PARENT(item);
|
2003-01-30 08:19:39 +00:00
|
|
|
levels--;
|
2010-02-04 23:13:05 +00:00
|
|
|
while (item && levels > 0) {
|
2003-01-30 08:19:39 +00:00
|
|
|
proto_item_append_text(item, " %s", s);
|
2009-09-30 07:53:12 +00:00
|
|
|
item = GET_ITEM_PARENT(item);
|
2003-01-30 08:19:39 +00:00
|
|
|
levels--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-01-28 06:27:01 +00:00
|
|
|
|
|
|
|
/* Save string to dcv->private_data */
|
|
|
|
if (options & CB_STR_SAVE) {
|
|
|
|
dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
|
|
|
|
dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
|
2006-09-16 09:10:23 +00:00
|
|
|
dcv->private_data = s;
|
2003-01-28 06:27:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-04-27 00:49:14 +00:00
|
|
|
void cb_str_postprocess(packet_info *pinfo, proto_tree *tree _U_,
|
2005-10-17 18:56:27 +00:00
|
|
|
proto_item *item, tvbuff_t *tvb,
|
2003-04-27 00:49:14 +00:00
|
|
|
int start_offset, int end_offset,
|
|
|
|
void *callback_args)
|
|
|
|
{
|
|
|
|
gint options = GPOINTER_TO_INT(callback_args);
|
|
|
|
gint levels = CB_STR_ITEM_LEVELS(options);
|
2008-02-09 23:35:28 +00:00
|
|
|
guint8 *s;
|
2003-04-27 00:49:14 +00:00
|
|
|
|
|
|
|
/* Align start_offset on 4-byte boundary. */
|
|
|
|
|
|
|
|
if (start_offset % 4)
|
|
|
|
start_offset += 4 - (start_offset % 4);
|
|
|
|
|
|
|
|
/* Get string value */
|
|
|
|
|
|
|
|
if ((end_offset - start_offset) <= 12)
|
|
|
|
return; /* XXX: Use unistr2 dissector instead? */
|
|
|
|
|
2003-07-01 00:59:43 +00:00
|
|
|
/*
|
|
|
|
* XXX - need to handle non-printable characters here.
|
|
|
|
*
|
|
|
|
* XXX - this is typically called after the string has already
|
|
|
|
* been fetched and processed by some other routine; is there
|
|
|
|
* some way we can get that string, rather than duplicating the
|
|
|
|
* efforts of that routine?
|
|
|
|
*/
|
2005-08-10 13:41:13 +00:00
|
|
|
s = tvb_get_ephemeral_string(
|
2003-07-01 00:59:43 +00:00
|
|
|
tvb, start_offset + 12, (end_offset - start_offset - 12) );
|
2003-04-27 00:49:14 +00:00
|
|
|
|
|
|
|
/* Append string to COL_INFO */
|
|
|
|
|
|
|
|
if (options & CB_STR_COL_INFO) {
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", s);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Append string to upper-level proto_items */
|
|
|
|
|
|
|
|
if (levels > 0 && item && s && s[0]) {
|
|
|
|
proto_item_append_text(item, ": %s", s);
|
2009-09-30 07:53:12 +00:00
|
|
|
item = GET_ITEM_PARENT(item);
|
2003-04-27 00:49:14 +00:00
|
|
|
levels--;
|
|
|
|
if (levels > 0) {
|
|
|
|
proto_item_append_text(item, ": %s", s);
|
2009-09-30 07:53:12 +00:00
|
|
|
item = GET_ITEM_PARENT(item);
|
2003-04-27 00:49:14 +00:00
|
|
|
levels--;
|
|
|
|
while (levels > 0) {
|
|
|
|
proto_item_append_text(item, " %s", s);
|
2009-09-30 07:53:12 +00:00
|
|
|
item = GET_ITEM_PARENT(item);
|
2003-04-27 00:49:14 +00:00
|
|
|
levels--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Save string to dcv->private_data */
|
|
|
|
|
|
|
|
if (options & CB_STR_SAVE) {
|
|
|
|
dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
|
|
|
|
dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
|
2005-10-17 18:56:27 +00:00
|
|
|
|
2006-09-16 09:10:23 +00:00
|
|
|
dcv->private_data = s;
|
2003-04-27 00:49:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-01-28 06:27:01 +00:00
|
|
|
/* Dissect a pointer to a NDR string and append the string value to the
|
|
|
|
proto_item. */
|
|
|
|
|
2005-10-17 18:56:27 +00:00
|
|
|
int dissect_ndr_str_pointer_item(tvbuff_t *tvb, gint offset,
|
|
|
|
packet_info *pinfo, proto_tree *tree,
|
|
|
|
guint8 *drep, int type, const char *text,
|
2003-01-30 08:19:39 +00:00
|
|
|
int hf_index, int levels)
|
2003-01-28 06:27:01 +00:00
|
|
|
{
|
|
|
|
return dissect_ndr_pointer_cb(
|
2005-10-17 18:56:27 +00:00
|
|
|
tvb, offset, pinfo, tree, drep,
|
|
|
|
dissect_ndr_wchar_cvstring, type, text, hf_index,
|
2003-04-27 00:49:14 +00:00
|
|
|
cb_wstr_postprocess, GINT_TO_POINTER(levels + 1));
|
2003-01-28 06:27:01 +00:00
|
|
|
}
|
|
|
|
|
2004-05-15 10:05:09 +00:00
|
|
|
/* SID dissection routines */
|
|
|
|
|
2004-05-19 04:52:31 +00:00
|
|
|
static int hf_nt_count = -1;
|
|
|
|
static int hf_nt_domain_sid = -1;
|
2004-05-15 10:05:09 +00:00
|
|
|
|
|
|
|
int
|
2005-10-17 18:56:27 +00:00
|
|
|
dissect_ndr_nt_SID(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
2004-05-19 04:52:31 +00:00
|
|
|
proto_tree *tree, guint8 *drep)
|
2004-05-15 10:05:09 +00:00
|
|
|
{
|
|
|
|
dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
|
|
|
|
dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
|
2005-02-16 11:31:56 +00:00
|
|
|
char *sid_str=NULL;
|
2005-06-26 19:56:52 +00:00
|
|
|
const char *name;
|
2004-05-15 10:05:09 +00:00
|
|
|
|
|
|
|
if(di->hf_index!=-1){
|
|
|
|
name=proto_registrar_get_name(di->hf_index);
|
|
|
|
} else {
|
|
|
|
name="Domain";
|
|
|
|
}
|
|
|
|
if(di->conformant_run){
|
|
|
|
/* just a run to handle conformant arrays, no scalars to dissect */
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* the SID contains a conformant array, first we must eat
|
|
|
|
the 4-byte max_count before we can hand it off */
|
|
|
|
|
2009-10-03 05:16:51 +00:00
|
|
|
offset = dissect_ndr_uint3264 (tvb, offset, pinfo, tree, drep,
|
2004-05-15 10:05:09 +00:00
|
|
|
hf_nt_count, NULL);
|
|
|
|
|
2005-10-17 18:56:27 +00:00
|
|
|
offset = dissect_nt_sid(tvb, offset, tree, name, &sid_str,
|
2004-05-19 04:52:31 +00:00
|
|
|
hf_nt_domain_sid);
|
2004-05-15 10:05:09 +00:00
|
|
|
|
|
|
|
/* dcv can be null, for example when this ndr structure is embedded
|
|
|
|
* inside non-dcerpc pdus, i.e. kerberos PAC structure
|
|
|
|
*/
|
|
|
|
if(dcv){
|
|
|
|
dcv->private_data = sid_str;
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2005-02-16 11:31:56 +00:00
|
|
|
/* same as dissect_ndr_nt_SID() but takes the same options as counted strings
|
|
|
|
do to prettify the dissect pane and the COL_INFO summary line
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
dissect_ndr_nt_SID_with_options(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, guint32 options)
|
|
|
|
{
|
|
|
|
dcerpc_info *di = (dcerpc_info *)pinfo->private_data;
|
|
|
|
dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data;
|
|
|
|
gint levels = CB_STR_ITEM_LEVELS(options);
|
|
|
|
offset=dissect_ndr_nt_SID(tvb, offset, pinfo, tree, drep);
|
|
|
|
|
|
|
|
if(dcv && dcv->private_data){
|
|
|
|
char *s=dcv->private_data;
|
|
|
|
proto_item *item=(proto_item *)tree;
|
|
|
|
|
|
|
|
if ((options & CB_STR_COL_INFO)&&(!di->conformant_run)) {
|
2005-10-17 18:56:27 +00:00
|
|
|
/* kludge, ugly, but this is called twice for all
|
|
|
|
dcerpc interfaces due to how we chase pointers
|
2005-02-16 11:31:56 +00:00
|
|
|
and putting the sid twice on the summary line
|
|
|
|
looks even worse.
|
|
|
|
Real solution would be to block updates to col_info
|
|
|
|
while we just do a conformance run, this might
|
|
|
|
have sideeffects so it needs some more thoughts first.
|
|
|
|
*/
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", s);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Append string to upper-level proto_items */
|
|
|
|
|
|
|
|
if (levels > 0 && item && s && s[0]) {
|
|
|
|
proto_item_append_text(item, ": %s", s);
|
2009-09-30 07:53:12 +00:00
|
|
|
item = GET_ITEM_PARENT(item);
|
2005-02-16 11:31:56 +00:00
|
|
|
levels--;
|
|
|
|
if (levels > 0) {
|
|
|
|
proto_item_append_text(item, ": %s", s);
|
2009-09-30 07:53:12 +00:00
|
|
|
item = GET_ITEM_PARENT(item);
|
2005-02-16 11:31:56 +00:00
|
|
|
levels--;
|
|
|
|
while (levels > 0) {
|
|
|
|
proto_item_append_text(item, " %s", s);
|
2009-09-30 07:53:12 +00:00
|
|
|
item = GET_ITEM_PARENT(item);
|
2005-02-16 11:31:56 +00:00
|
|
|
levels--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2004-05-15 10:05:09 +00:00
|
|
|
static int
|
2005-10-17 18:56:27 +00:00
|
|
|
dissect_ndr_nt_SID_hf_through_ptr(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
2004-05-15 10:05:09 +00:00
|
|
|
proto_tree *tree, guint8 *drep)
|
|
|
|
{
|
2004-05-19 04:52:31 +00:00
|
|
|
offset = dissect_ndr_nt_SID(tvb, offset, pinfo, tree, drep);
|
2004-05-15 10:05:09 +00:00
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint ett_nt_sid_pointer = -1;
|
|
|
|
|
|
|
|
int
|
|
|
|
dissect_ndr_nt_PSID(tvbuff_t *tvb, int offset,
|
|
|
|
packet_info *pinfo, proto_tree *parent_tree,
|
2004-05-19 04:52:31 +00:00
|
|
|
guint8 *drep)
|
2004-05-15 10:05:09 +00:00
|
|
|
{
|
|
|
|
proto_item *item=NULL;
|
|
|
|
proto_tree *tree=NULL;
|
|
|
|
int old_offset=offset;
|
|
|
|
|
|
|
|
if(parent_tree){
|
|
|
|
item = proto_tree_add_text(parent_tree, tvb, offset, -1,
|
|
|
|
"SID pointer:");
|
|
|
|
tree = proto_item_add_subtree(item, ett_nt_sid_pointer);
|
|
|
|
}
|
|
|
|
|
|
|
|
offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
|
|
|
|
dissect_ndr_nt_SID_hf_through_ptr, NDR_POINTER_UNIQUE,
|
2004-05-19 04:52:31 +00:00
|
|
|
"SID pointer", hf_nt_domain_sid);
|
2004-05-15 10:05:09 +00:00
|
|
|
|
|
|
|
proto_item_set_len(item, offset-old_offset);
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const true_false_string tfs_nt_acb_disabled = {
|
|
|
|
"Account is DISABLED",
|
|
|
|
"Account is NOT disabled"
|
|
|
|
};
|
|
|
|
static const true_false_string tfs_nt_acb_homedirreq = {
|
|
|
|
"Homedir is REQUIRED",
|
|
|
|
"Homedir is NOT required"
|
|
|
|
};
|
|
|
|
static const true_false_string tfs_nt_acb_pwnotreq = {
|
|
|
|
"Password is NOT required",
|
|
|
|
"Password is REQUIRED"
|
|
|
|
};
|
|
|
|
static const true_false_string tfs_nt_acb_tempdup = {
|
|
|
|
"This is a TEMPORARY DUPLICATE account",
|
|
|
|
"This is NOT a temporary duplicate account"
|
|
|
|
};
|
|
|
|
static const true_false_string tfs_nt_acb_normal = {
|
|
|
|
"This is a NORMAL USER account",
|
|
|
|
"This is NOT a normal user account"
|
|
|
|
};
|
|
|
|
static const true_false_string tfs_nt_acb_mns = {
|
|
|
|
"This is a MNS account",
|
|
|
|
"This is NOT a mns account"
|
|
|
|
};
|
|
|
|
static const true_false_string tfs_nt_acb_domtrust = {
|
|
|
|
"This is a DOMAIN TRUST account",
|
|
|
|
"This is NOT a domain trust account"
|
|
|
|
};
|
|
|
|
static const true_false_string tfs_nt_acb_wstrust = {
|
|
|
|
"This is a WORKSTATION TRUST account",
|
|
|
|
"This is NOT a workstation trust account"
|
|
|
|
};
|
|
|
|
static const true_false_string tfs_nt_acb_svrtrust = {
|
|
|
|
"This is a SERVER TRUST account",
|
|
|
|
"This is NOT a server trust account"
|
|
|
|
};
|
|
|
|
static const true_false_string tfs_nt_acb_pwnoexp = {
|
|
|
|
"Passwords does NOT expire",
|
|
|
|
"Password will EXPIRE"
|
|
|
|
};
|
|
|
|
static const true_false_string tfs_nt_acb_autolock = {
|
|
|
|
"This account has been AUTO LOCKED",
|
|
|
|
"This account has NOT been auto locked"
|
|
|
|
};
|
|
|
|
|
|
|
|
static gint ett_nt_acct_ctrl = -1;
|
|
|
|
|
|
|
|
static int hf_nt_acct_ctrl = -1;
|
|
|
|
static int hf_nt_acb_disabled = -1;
|
|
|
|
static int hf_nt_acb_homedirreq = -1;
|
|
|
|
static int hf_nt_acb_pwnotreq = -1;
|
|
|
|
static int hf_nt_acb_tempdup = -1;
|
|
|
|
static int hf_nt_acb_normal = -1;
|
|
|
|
static int hf_nt_acb_mns = -1;
|
|
|
|
static int hf_nt_acb_domtrust = -1;
|
|
|
|
static int hf_nt_acb_wstrust = -1;
|
|
|
|
static int hf_nt_acb_svrtrust = -1;
|
|
|
|
static int hf_nt_acb_pwnoexp = -1;
|
|
|
|
static int hf_nt_acb_autolock = -1;
|
|
|
|
|
|
|
|
int
|
|
|
|
dissect_ndr_nt_acct_ctrl(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
|
|
|
proto_tree *parent_tree, guint8 *drep)
|
|
|
|
{
|
|
|
|
guint32 mask;
|
|
|
|
proto_item *item = NULL;
|
|
|
|
proto_tree *tree = NULL;
|
|
|
|
|
|
|
|
offset=dissect_ndr_uint32(tvb, offset, pinfo, NULL, drep,
|
|
|
|
hf_nt_acct_ctrl, &mask);
|
|
|
|
|
|
|
|
if(parent_tree){
|
|
|
|
item = proto_tree_add_uint(parent_tree, hf_nt_acct_ctrl,
|
|
|
|
tvb, offset-4, 4, mask);
|
|
|
|
tree = proto_item_add_subtree(item, ett_nt_acct_ctrl);
|
|
|
|
}
|
|
|
|
|
|
|
|
proto_tree_add_boolean(tree, hf_nt_acb_autolock,
|
|
|
|
tvb, offset-4, 4, mask);
|
|
|
|
proto_tree_add_boolean(tree, hf_nt_acb_pwnoexp,
|
|
|
|
tvb, offset-4, 4, mask);
|
|
|
|
proto_tree_add_boolean(tree, hf_nt_acb_svrtrust,
|
|
|
|
tvb, offset-4, 4, mask);
|
|
|
|
proto_tree_add_boolean(tree, hf_nt_acb_wstrust,
|
|
|
|
tvb, offset-4, 4, mask);
|
|
|
|
proto_tree_add_boolean(tree, hf_nt_acb_domtrust,
|
|
|
|
tvb, offset-4, 4, mask);
|
|
|
|
proto_tree_add_boolean(tree, hf_nt_acb_mns,
|
|
|
|
tvb, offset-4, 4, mask);
|
|
|
|
proto_tree_add_boolean(tree, hf_nt_acb_normal,
|
|
|
|
tvb, offset-4, 4, mask);
|
|
|
|
proto_tree_add_boolean(tree, hf_nt_acb_tempdup,
|
|
|
|
tvb, offset-4, 4, mask);
|
|
|
|
proto_tree_add_boolean(tree, hf_nt_acb_pwnotreq,
|
|
|
|
tvb, offset-4, 4, mask);
|
|
|
|
proto_tree_add_boolean(tree, hf_nt_acb_homedirreq,
|
|
|
|
tvb, offset-4, 4, mask);
|
|
|
|
proto_tree_add_boolean(tree, hf_nt_acb_disabled,
|
|
|
|
tvb, offset-4, 4, mask);
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int hf_logonhours_unknown_char;
|
|
|
|
|
|
|
|
static int
|
|
|
|
dissect_LOGON_HOURS_entry(tvbuff_t *tvb, int offset,
|
|
|
|
packet_info *pinfo, proto_tree *tree,
|
|
|
|
guint8 *drep)
|
|
|
|
{
|
|
|
|
offset = dissect_ndr_uint8(tvb, offset, pinfo, tree, drep,
|
|
|
|
hf_logonhours_unknown_char, NULL);
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint ett_nt_logon_hours_hours = -1;
|
|
|
|
|
|
|
|
static int
|
|
|
|
dissect_LOGON_HOURS_hours(tvbuff_t *tvb, int offset,
|
|
|
|
packet_info *pinfo, proto_tree *parent_tree,
|
|
|
|
guint8 *drep)
|
|
|
|
{
|
|
|
|
proto_item *item=NULL;
|
|
|
|
proto_tree *tree=NULL;
|
|
|
|
int old_offset=offset;
|
|
|
|
|
|
|
|
if(parent_tree){
|
|
|
|
item = proto_tree_add_text(parent_tree, tvb, offset, -1,
|
|
|
|
"LOGON_HOURS:");
|
|
|
|
tree = proto_item_add_subtree(item, ett_nt_logon_hours_hours);
|
|
|
|
}
|
|
|
|
|
|
|
|
offset = dissect_ndr_ucvarray(tvb, offset, pinfo, tree, drep,
|
|
|
|
dissect_LOGON_HOURS_entry);
|
|
|
|
|
|
|
|
proto_item_set_len(item, offset-old_offset);
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint ett_nt_logon_hours = -1;
|
|
|
|
static int hf_logonhours_divisions = -1;
|
|
|
|
|
|
|
|
int
|
|
|
|
dissect_ndr_nt_LOGON_HOURS(tvbuff_t *tvb, int offset,
|
|
|
|
packet_info *pinfo, proto_tree *parent_tree,
|
|
|
|
guint8 *drep)
|
|
|
|
{
|
|
|
|
proto_item *item=NULL;
|
|
|
|
proto_tree *tree=NULL;
|
|
|
|
int old_offset=offset;
|
|
|
|
|
|
|
|
ALIGN_TO_4_BYTES; /* strcture starts with short, but is aligned for longs */
|
|
|
|
|
|
|
|
if(parent_tree){
|
|
|
|
item = proto_tree_add_text(parent_tree, tvb, offset, -1,
|
|
|
|
"LOGON_HOURS:");
|
|
|
|
tree = proto_item_add_subtree(item, ett_nt_logon_hours);
|
|
|
|
}
|
|
|
|
|
|
|
|
offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, drep,
|
|
|
|
hf_logonhours_divisions, NULL);
|
|
|
|
/* XXX - is this a bitmask like the "logon hours" field in the
|
|
|
|
Remote API call "NetUserGetInfo()" with an information level
|
|
|
|
of 11? */
|
|
|
|
offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
|
|
|
|
dissect_LOGON_HOURS_hours, NDR_POINTER_UNIQUE,
|
|
|
|
"LOGON_HOURS", -1);
|
|
|
|
|
|
|
|
proto_item_set_len(item, offset-old_offset);
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
dissect_ndr_nt_PSID_no_hf(tvbuff_t *tvb, int offset,
|
|
|
|
packet_info *pinfo, proto_tree *parent_tree,
|
|
|
|
guint8 *drep)
|
|
|
|
{
|
2004-05-19 04:52:31 +00:00
|
|
|
offset=dissect_ndr_nt_PSID(tvb, offset, pinfo, parent_tree, drep);
|
2004-05-15 10:05:09 +00:00
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
dissect_ndr_nt_PSID_ARRAY_sids (tvbuff_t *tvb, int offset,
|
|
|
|
packet_info *pinfo, proto_tree *tree,
|
|
|
|
guint8 *drep)
|
|
|
|
{
|
|
|
|
offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
|
|
|
|
dissect_ndr_nt_PSID_no_hf);
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint ett_nt_sid_array = -1;
|
|
|
|
|
|
|
|
int
|
|
|
|
dissect_ndr_nt_PSID_ARRAY(tvbuff_t *tvb, int offset,
|
|
|
|
packet_info *pinfo, proto_tree *parent_tree,
|
|
|
|
guint8 *drep)
|
|
|
|
{
|
|
|
|
guint32 count;
|
|
|
|
proto_item *item=NULL;
|
|
|
|
proto_tree *tree=NULL;
|
2009-10-04 07:57:45 +00:00
|
|
|
dcerpc_info *di = pinfo->private_data;
|
2004-05-15 10:05:09 +00:00
|
|
|
int old_offset=offset;
|
|
|
|
|
|
|
|
if(parent_tree){
|
|
|
|
item = proto_tree_add_text(parent_tree, tvb, offset, -1,
|
|
|
|
"SID array:");
|
|
|
|
tree = proto_item_add_subtree(item, ett_nt_sid_array);
|
|
|
|
}
|
|
|
|
|
2009-10-04 07:57:45 +00:00
|
|
|
ALIGN_TO_5_BYTES;
|
|
|
|
|
2004-05-15 10:05:09 +00:00
|
|
|
offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
|
|
|
|
hf_nt_count, &count);
|
|
|
|
offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
|
|
|
|
dissect_ndr_nt_PSID_ARRAY_sids, NDR_POINTER_UNIQUE,
|
|
|
|
"PSID_ARRAY", -1);
|
|
|
|
|
|
|
|
proto_item_set_len(item, offset-old_offset);
|
2009-10-04 07:57:45 +00:00
|
|
|
|
|
|
|
if (di->call_data->flags & DCERPC_IS_NDR64) {
|
|
|
|
ALIGN_TO_5_BYTES;
|
|
|
|
}
|
|
|
|
|
2004-05-15 10:05:09 +00:00
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint ett_nt_sid_and_attributes = -1;
|
|
|
|
static int hf_nt_attrib = -1;
|
|
|
|
|
|
|
|
int
|
|
|
|
dissect_ndr_nt_SID_AND_ATTRIBUTES(tvbuff_t *tvb, int offset,
|
|
|
|
packet_info *pinfo, proto_tree *parent_tree,
|
|
|
|
guint8 *drep)
|
|
|
|
{
|
|
|
|
proto_item *item=NULL;
|
|
|
|
proto_tree *tree=NULL;
|
|
|
|
|
|
|
|
if(parent_tree){
|
|
|
|
item = proto_tree_add_text(parent_tree, tvb, offset, 0,
|
|
|
|
"SID_AND_ATTRIBUTES:");
|
|
|
|
tree = proto_item_add_subtree(item, ett_nt_sid_and_attributes);
|
|
|
|
}
|
|
|
|
|
2004-05-19 04:52:31 +00:00
|
|
|
offset = dissect_ndr_nt_PSID(tvb, offset, pinfo, tree, drep);
|
2004-05-15 10:05:09 +00:00
|
|
|
|
|
|
|
offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
|
|
|
|
hf_nt_attrib, NULL);
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint ett_nt_sid_and_attributes_array = -1;
|
|
|
|
|
|
|
|
int
|
|
|
|
dissect_ndr_nt_SID_AND_ATTRIBUTES_ARRAY(tvbuff_t *tvb, int offset,
|
|
|
|
packet_info *pinfo, proto_tree *parent_tree,
|
|
|
|
guint8 *drep)
|
|
|
|
{
|
|
|
|
proto_item *item=NULL;
|
|
|
|
proto_tree *tree=NULL;
|
|
|
|
int old_offset=offset;
|
|
|
|
|
|
|
|
if(parent_tree){
|
|
|
|
item = proto_tree_add_text(parent_tree, tvb, offset, 0,
|
|
|
|
"SID_AND_ATTRIBUTES array:");
|
|
|
|
tree = proto_item_add_subtree(item, ett_nt_sid_and_attributes_array);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
|
|
|
|
hf_samr_count, &count); */
|
|
|
|
offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
|
|
|
|
dissect_ndr_nt_SID_AND_ATTRIBUTES);
|
|
|
|
|
|
|
|
proto_item_set_len(item, offset-old_offset);
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
2003-01-24 05:32:54 +00:00
|
|
|
/*
|
|
|
|
* Register ett/hf values and perform DCERPC over SMB specific
|
|
|
|
* initialisation.
|
|
|
|
*/
|
|
|
|
void dcerpc_smb_init(int proto_dcerpc)
|
|
|
|
{
|
|
|
|
static hf_register_info hf[] = {
|
|
|
|
|
2003-02-03 02:00:54 +00:00
|
|
|
/* String handling */
|
|
|
|
|
|
|
|
{ &hf_nt_cs_size,
|
2007-10-08 00:32:03 +00:00
|
|
|
{ "Size", "dcerpc.nt.str.size", FT_UINT16, BASE_DEC,
|
2005-10-17 18:56:27 +00:00
|
|
|
NULL, 0x0, "Size of string in short integers",
|
2003-02-03 02:00:54 +00:00
|
|
|
HFILL }},
|
2005-10-17 18:56:27 +00:00
|
|
|
|
2003-02-03 02:00:54 +00:00
|
|
|
{ &hf_nt_cs_len,
|
2007-10-08 00:32:03 +00:00
|
|
|
{ "Length", "dcerpc.nt.str.len", FT_UINT16, BASE_DEC,
|
2005-10-17 18:56:27 +00:00
|
|
|
NULL, 0x0, "Length of string in short integers",
|
2003-02-03 02:00:54 +00:00
|
|
|
HFILL }},
|
2005-10-17 18:56:27 +00:00
|
|
|
|
2005-02-01 05:21:08 +00:00
|
|
|
/* GUIDs */
|
|
|
|
{ &hf_nt_guid,
|
2007-10-08 00:32:03 +00:00
|
|
|
{ "GUID", "dcerpc.nt.guid", FT_GUID, BASE_NONE,
|
2005-02-01 05:21:08 +00:00
|
|
|
NULL, 0x0, "GUID (uuid for groups?)", HFILL }},
|
|
|
|
|
2003-01-24 05:32:54 +00:00
|
|
|
/* Policy handles */
|
|
|
|
|
|
|
|
{ &hf_nt_policy_open_frame,
|
|
|
|
{ "Frame handle opened", "dcerpc.nt.open_frame",
|
|
|
|
FT_FRAMENUM, BASE_NONE, NULL, 0x0,
|
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
|
|
|
NULL, HFILL }},
|
2003-01-24 05:32:54 +00:00
|
|
|
|
|
|
|
{ &hf_nt_policy_close_frame,
|
2003-04-27 00:34:27 +00:00
|
|
|
{ "Frame handle closed", "dcerpc.nt.close_frame",
|
2003-01-24 05:32:54 +00:00
|
|
|
FT_FRAMENUM, BASE_NONE, NULL, 0x0,
|
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
|
|
|
NULL, HFILL }},
|
2004-05-15 10:05:09 +00:00
|
|
|
|
|
|
|
/* ACBs */
|
|
|
|
|
|
|
|
{ &hf_nt_acct_ctrl,
|
2007-10-08 00:32:03 +00:00
|
|
|
{ "Acct Ctrl", "dcerpc.nt.acct_ctrl", FT_UINT32, BASE_HEX,
|
2004-05-15 10:05:09 +00:00
|
|
|
NULL, 0x0, "Acct CTRL", HFILL }},
|
|
|
|
|
2005-10-17 18:56:27 +00:00
|
|
|
{ &hf_nt_acb_disabled,
|
2007-10-08 00:32:03 +00:00
|
|
|
{ "Account disabled", "dcerpc.nt.acb.disabled", FT_BOOLEAN, 32,
|
2005-10-17 18:56:27 +00:00
|
|
|
TFS(&tfs_nt_acb_disabled), 0x0001,
|
2004-05-15 10:05:09 +00:00
|
|
|
"If this account is enabled or disabled", HFILL }},
|
|
|
|
|
2005-10-17 18:56:27 +00:00
|
|
|
{ &hf_nt_acb_homedirreq,
|
2007-10-08 00:32:03 +00:00
|
|
|
{ "Home dir required", "dcerpc.nt.acb.homedirreq", FT_BOOLEAN, 32,
|
2005-10-17 18:56:27 +00:00
|
|
|
TFS(&tfs_nt_acb_homedirreq), 0x0002,
|
2007-03-11 06:16:00 +00:00
|
|
|
"Is homedirs required for this account?", HFILL }},
|
2004-05-15 10:05:09 +00:00
|
|
|
|
2005-10-17 18:56:27 +00:00
|
|
|
{ &hf_nt_acb_pwnotreq,
|
2007-10-08 00:32:03 +00:00
|
|
|
{ "Password required", "dcerpc.nt.acb.pwnotreq", FT_BOOLEAN, 32,
|
2005-10-17 18:56:27 +00:00
|
|
|
TFS(&tfs_nt_acb_pwnotreq), 0x0004,
|
2004-05-15 10:05:09 +00:00
|
|
|
"If a password is required for this account?", HFILL }},
|
|
|
|
|
2005-10-17 18:56:27 +00:00
|
|
|
{ &hf_nt_acb_tempdup,
|
2007-10-08 00:32:03 +00:00
|
|
|
{ "Temporary duplicate account", "dcerpc.nt.acb.tempdup", FT_BOOLEAN, 32,
|
2005-10-17 18:56:27 +00:00
|
|
|
TFS(&tfs_nt_acb_tempdup), 0x0008,
|
2004-05-15 10:05:09 +00:00
|
|
|
"If this is a temporary duplicate account", HFILL }},
|
|
|
|
|
2005-10-17 18:56:27 +00:00
|
|
|
{ &hf_nt_acb_normal,
|
2007-10-08 00:32:03 +00:00
|
|
|
{ "Normal user account", "dcerpc.nt.acb.normal", FT_BOOLEAN, 32,
|
2005-10-17 18:56:27 +00:00
|
|
|
TFS(&tfs_nt_acb_normal), 0x0010,
|
2004-05-15 10:05:09 +00:00
|
|
|
"If this is a normal user account", HFILL }},
|
|
|
|
|
2005-10-17 18:56:27 +00:00
|
|
|
{ &hf_nt_acb_mns,
|
2007-10-08 00:32:03 +00:00
|
|
|
{ "MNS logon user account", "dcerpc.nt.acb.mns", FT_BOOLEAN, 32,
|
2005-10-17 18:56:27 +00:00
|
|
|
TFS(&tfs_nt_acb_mns), 0x0020,
|
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
|
|
|
NULL, HFILL }},
|
2004-05-15 10:05:09 +00:00
|
|
|
|
2005-10-17 18:56:27 +00:00
|
|
|
{ &hf_nt_acb_domtrust,
|
2007-10-08 00:32:03 +00:00
|
|
|
{ "Interdomain trust account", "dcerpc.nt.acb.domtrust", FT_BOOLEAN, 32,
|
2005-10-17 18:56:27 +00:00
|
|
|
TFS(&tfs_nt_acb_domtrust), 0x0040,
|
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
|
|
|
NULL, HFILL }},
|
2005-10-17 18:56:27 +00:00
|
|
|
|
|
|
|
{ &hf_nt_acb_wstrust,
|
2007-10-08 00:32:03 +00:00
|
|
|
{ "Workstation trust account", "dcerpc.nt.acb.wstrust", FT_BOOLEAN, 32,
|
2005-10-17 18:56:27 +00:00
|
|
|
TFS(&tfs_nt_acb_wstrust), 0x0080,
|
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
|
|
|
NULL, HFILL }},
|
2005-10-17 18:56:27 +00:00
|
|
|
|
|
|
|
{ &hf_nt_acb_svrtrust,
|
2007-10-08 00:32:03 +00:00
|
|
|
{ "Server trust account", "dcerpc.nt.acb.svrtrust", FT_BOOLEAN, 32,
|
2005-10-17 18:56:27 +00:00
|
|
|
TFS(&tfs_nt_acb_svrtrust), 0x0100,
|
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
|
|
|
NULL, HFILL }},
|
2004-05-15 10:05:09 +00:00
|
|
|
|
2005-10-17 18:56:27 +00:00
|
|
|
{ &hf_nt_acb_pwnoexp,
|
2007-10-08 00:32:03 +00:00
|
|
|
{ "Password expires", "dcerpc.nt.acb.pwnoexp", FT_BOOLEAN, 32,
|
2005-10-17 18:56:27 +00:00
|
|
|
TFS(&tfs_nt_acb_pwnoexp), 0x0200,
|
2004-05-15 10:05:09 +00:00
|
|
|
"If this account expires or not", HFILL }},
|
|
|
|
|
2005-10-17 18:56:27 +00:00
|
|
|
{ &hf_nt_acb_autolock,
|
2007-10-08 00:32:03 +00:00
|
|
|
{ "Account is autolocked", "dcerpc.nt.acb.autolock", FT_BOOLEAN, 32,
|
2005-10-17 18:56:27 +00:00
|
|
|
TFS(&tfs_nt_acb_autolock), 0x0400,
|
2004-05-15 10:05:09 +00:00
|
|
|
"If this account has been autolocked", HFILL }},
|
|
|
|
|
|
|
|
/* SIDs */
|
|
|
|
|
2004-05-19 04:52:31 +00:00
|
|
|
{ &hf_nt_domain_sid,
|
2007-10-08 00:32:03 +00:00
|
|
|
{ "Domain SID", "dcerpc.nt.domain_sid",
|
2005-10-17 18:56:27 +00:00
|
|
|
FT_STRING, BASE_NONE, NULL, 0x0,
|
2004-05-19 04:52:31 +00:00
|
|
|
"The Domain SID", HFILL }},
|
|
|
|
|
2004-05-15 10:05:09 +00:00
|
|
|
{ &hf_nt_count,
|
2007-10-08 00:32:03 +00:00
|
|
|
{ "Count", "dcerpc.nt.count",
|
2005-10-17 18:56:27 +00:00
|
|
|
FT_UINT32, BASE_DEC, NULL, 0x0,
|
2004-05-15 10:05:09 +00:00
|
|
|
"Number of elements in following array", HFILL }},
|
|
|
|
|
|
|
|
/* Logon hours */
|
|
|
|
|
2005-10-17 18:56:27 +00:00
|
|
|
{ &hf_logonhours_divisions,
|
2007-10-08 00:32:03 +00:00
|
|
|
{ "Divisions", "dcerpc.nt.logonhours.divisions",
|
2005-10-17 18:56:27 +00:00
|
|
|
FT_UINT16, BASE_DEC, NULL, 0,
|
2004-05-15 10:05:09 +00:00
|
|
|
"Number of divisions for LOGON_HOURS", HFILL }},
|
|
|
|
|
2005-10-17 18:56:27 +00:00
|
|
|
{ &hf_logonhours_unknown_char,
|
2007-10-08 00:32:03 +00:00
|
|
|
{ "Unknown char", "dcerpc.nt.unknown.char",
|
2005-10-17 18:56:27 +00:00
|
|
|
FT_UINT8, BASE_HEX, NULL, 0x0,
|
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
|
|
|
"Unknown char. If you know what this is, contact wireshark developers.", HFILL }},
|
2004-05-15 10:05:09 +00:00
|
|
|
|
|
|
|
/* Misc */
|
|
|
|
|
2005-10-17 18:56:27 +00:00
|
|
|
{ &hf_nt_attrib,
|
2007-10-08 00:32:03 +00:00
|
|
|
{ "Attributes", "dcerpc.nt.attr",
|
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
|
|
|
FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
|
2009-10-06 08:07:17 +00:00
|
|
|
|
|
|
|
{ &hf_lsa_String_name_len,
|
|
|
|
{ "Name Len", "dcerpc.lsa_String.name_len",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
|
|
|
|
|
|
|
|
{ &hf_lsa_String_name_size,
|
|
|
|
{ "Name Size", "dcerpc.lsa_String.name_size",
|
|
|
|
FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
|
2003-01-24 05:32:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static gint *ett[] = {
|
|
|
|
&ett_nt_unicode_string,
|
2003-02-03 02:00:54 +00:00
|
|
|
&ett_nt_counted_string,
|
2003-02-08 09:41:44 +00:00
|
|
|
&ett_nt_counted_byte_array,
|
2003-01-24 05:32:54 +00:00
|
|
|
&ett_nt_policy_hnd,
|
2004-05-15 10:05:09 +00:00
|
|
|
&ett_nt_sid_pointer,
|
|
|
|
&ett_nt_acct_ctrl,
|
|
|
|
&ett_nt_logon_hours,
|
|
|
|
&ett_nt_logon_hours_hours,
|
|
|
|
&ett_nt_sid_array,
|
|
|
|
&ett_nt_sid_and_attributes_array,
|
|
|
|
&ett_nt_sid_and_attributes,
|
2005-01-30 11:56:37 +00:00
|
|
|
&ett_nt_counted_ascii_string,
|
2009-10-06 08:07:17 +00:00
|
|
|
&ett_lsa_String,
|
2003-01-24 05:32:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Register ett's and hf's */
|
|
|
|
|
|
|
|
proto_register_subtree_array(ett, array_length(ett));
|
|
|
|
proto_register_field_array(proto_dcerpc, hf, array_length(hf));
|
|
|
|
|
|
|
|
/* Initialise policy handle hash */
|
|
|
|
|
2005-10-17 18:56:27 +00:00
|
|
|
register_init_routine(&init_pol_hash);
|
2003-01-24 05:32:54 +00:00
|
|
|
}
|