wireshark/packet-dcerpc-lsa.c
Guy Harris ee5ca25d31 Include files from the "epan" directory and subdirectories thereof with
"epan/..." pathnames, so as to avoid collisions with header files in any
of the directories in which we look (e.g., "proto.h", as some other
package has its own "proto.h" file which it installs in the top-level
include directory).

Don't add "-I" flags to search "epan", as that's no longer necessary
(and we want includes of "epan" headers to fail if the "epan/" is left
out, so that we don't re-introduce includes lacking "epan/").

svn path=/trunk/; revision=4586
2002-01-21 07:37:49 +00:00

1229 lines
31 KiB
C

/* packet-dcerpc-lsa.c
* Routines for SMB \PIPE\lsarpc packet disassembly
* Copyright 2001, Tim Potter <tpot@samba.org>
*
* $Id: packet-dcerpc-lsa.c,v 1.7 2002/01/21 07:36:33 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
*
* 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.
*
* 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.
*
* 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
#include <glib.h>
#include <string.h>
#include <epan/packet.h>
#include "packet-dcerpc.h"
#include "packet-dcerpc-nt.h"
#include "packet-dcerpc-lsa.h"
#include "smb.h"
/*
* Parse a unicode string.
*
* typedef struct {
* short length;
* short size;
* [size_is(size/2)] [length_is(length/2)] [unique] wchar_t *string;
* } UNICODE_STRING;
*
*/
static int ett_UNISTR = -1;
static int ett_UNISTR_hdr = -1;
static int prs_UNISTR(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, int flags, GList **ptr_list,
char *name)
{
proto_tree *scalars, *buffers;
guint16 length, size;
if (flags & PARSE_SCALARS) {
proto_item *item;
proto_tree *subtree;
item = proto_tree_add_text(tree, tvb, offset, 0,
"String header");
subtree = proto_item_add_subtree(item, ett_UNISTR_hdr);
offset = prs_uint16(tvb, offset, pinfo, subtree, &length,
"Length");
offset = prs_uint16(tvb, offset, pinfo, subtree, &size,
"Size");
offset = prs_push_ptr(tvb, offset, pinfo, subtree,
ptr_list, "Data");
}
if (flags & PARSE_BUFFERS) {
proto_item *item;
proto_tree *subtree;
guint32 max_len, stroffset, actual_count, i;
int old_offset;
guint16 *string;
char *astring;
/* Parse data */
old_offset = offset;
offset = prs_uint32(tvb, offset, pinfo, NULL, &max_len,
"Max length");
offset = prs_uint32(tvb, offset, pinfo, NULL, &stroffset,
"Offset");
offset = prs_uint32(tvb, offset, pinfo, NULL,
&actual_count, "Actual length");
offset = prs_uint16s(tvb, offset, pinfo, NULL,
actual_count, &string, "Data");
/* Insert into display */
astring = fake_unicode(string, actual_count);
if (!astring || !astring[0])
astring = strdup("(NULL)");
item = proto_tree_add_text(tree, tvb, old_offset,
offset - old_offset, "String: %s",
astring);
free(astring);
subtree = proto_item_add_subtree(item, ett_UNISTR);
proto_tree_add_text(subtree, tvb, old_offset, 4,
"Max length: %d", max_len);
old_offset += 4;
proto_tree_add_text(subtree, tvb, old_offset, 4,
"Offset: %d", stroffset);
old_offset += 4;
proto_tree_add_text(subtree, tvb, old_offset, 4,
"Actual length: %d", actual_count);
old_offset += 4;
if (prs_pop_ptr(ptr_list, "Data"))
proto_tree_add_text(subtree, tvb, old_offset,
actual_count * 2, "Data");
}
return offset;
}
/*
* typedef struct {
* char revision;
* char subauth_count;
* char authority[6];
* [size_is(subauth_count)] long subauth[*];
* } SID;
*
*/
static int ett_SID = -1;
/* For some reason the SID structure is treated as a scalar type. For
instance in an array of SIDs, I would have thought that this entire
structure should be in the scalars part of the RPC but instead is in
the buffers section. I am probably misunderstanding NDR arrays
though. - tpot */
static int prs_SID(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree)
{
guint8 subauth_count, id_auth[6];
int old_offset, i;
proto_item *item;
proto_tree *subtree;
guint32 ia, *subauths, subauth_max;
guint8 revision;
char sid_str[128];
old_offset = offset;
offset = prs_uint32(tvb, offset, pinfo, NULL, &subauth_max,
"Array max count");
offset = prs_uint8(tvb, offset, pinfo, NULL, &revision, "Revision");
offset = prs_uint8(tvb, offset, pinfo, NULL, &subauth_count,
"Subauth count");
for (i = 0; i < 6; i++)
offset = prs_uint8(tvb, offset, pinfo, NULL, &id_auth[i],
"Authority");
ia = id_auth[5] + (id_auth[4] << 8 ) + (id_auth[3] << 16) +
(id_auth[2] << 24);
sprintf(sid_str, "S-%u-%u", revision, ia);
offset = prs_uint32s(tvb, offset, pinfo, NULL, subauth_count,
&subauths, "Subauth count");
for (i = 0; i < subauth_count; i++) {
char sa[16];
sprintf(sa, "-%u", subauths[i]);
strcat(sid_str, sa);
}
/* Insert into display */
item = proto_tree_add_text(tree, tvb, offset, 0, "SID: %s", sid_str);
subtree = proto_item_add_subtree(item, ett_SID);
proto_tree_add_text(subtree, tvb, old_offset, 4,
"Subauth array max count: %d", subauth_max);
old_offset += 4;
proto_tree_add_text(subtree, tvb, old_offset, 1, "Revision: %d",
revision);
old_offset++;
proto_tree_add_text(subtree, tvb, old_offset, 1, "Subauth count: %d",
subauth_count);
old_offset++;
proto_tree_add_text(subtree, tvb, old_offset, 6, "Authority");
old_offset += 6;
proto_tree_add_text(subtree, tvb, old_offset, subauth_count * 4,
"Subauthorities");
old_offset += subauth_count * 4;
return offset;
}
/*
* Close a policy handle.
*
* long LsarClose(
* [in,out] [context_handle] void **hnd
* );
*
*/
static int LsaClose_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, char *drep)
{
if (check_col(pinfo->cinfo, COL_INFO))
col_set_str(pinfo->cinfo, COL_INFO, "ClosePolicy request");
offset = prs_policy_hnd(tvb, offset, pinfo, tree, NULL);
return offset;
}
static int LsaClose_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, char *drep)
{
if (check_col(pinfo->cinfo, COL_INFO))
col_set_str(pinfo->cinfo, COL_INFO, "ClosePolicy reply");
offset = prs_policy_hnd(tvb, offset, pinfo, tree, NULL);
offset = prs_ntstatus(tvb, offset, pinfo, tree);
return offset;
}
/*
* Dissect a SECURITY_DESCRIPTOR structure
*
* typedef struct {
* char revision;
* char reserved;
* short control;
* [unique] SID *owner;
* [unique] SID *group;
* [unique] SEC_ACL *sacl;
* [unique] SEC_ACL *dacl;
* } SECURITY_DESCRIPTOR;
*
*/
static int prs_SECURITY_DESCRIPTOR(tvbuff_t *tvb, int offset,
packet_info *pinfo, proto_tree *tree,
int flags)
{
/* Not implemented */
return offset;
}
/* Dissect a SECURITY_QOS structure
*
* typedef struct {
* uint32 struct_len;
* uint16 imp_level;
* char track_context;
* char effective_only;
* } SECURITY_QOS;
*
*/
static int ett_SECURITY_QOS = -1;
static int ett_SECURITY_QOS_hdr = -1;
static int prs_SECURITY_QOS(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, int flags)
{
if (flags & PARSE_SCALARS) {
proto_item *item;
proto_tree *subtree;
item = proto_tree_add_text(tree, tvb, offset, 0,
"SECURITY_QOS header");
subtree = proto_item_add_subtree(item, ett_SECURITY_QOS_hdr);
offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
"Struct length");
offset = prs_uint16(tvb, offset, pinfo, subtree, NULL,
"Implementation level");
offset = prs_uint8(tvb, offset, pinfo, subtree, NULL,
"Track context");
offset = prs_uint8(tvb, offset, pinfo, subtree, NULL,
"Effective only");
}
if (flags & PARSE_BUFFERS) {
proto_item *item;
proto_tree *subtree;
item = proto_tree_add_text(tree, tvb, offset, 0,
"SECURITY_QOS");
subtree = proto_item_add_subtree(item, ett_SECURITY_QOS);
}
return offset;
}
/*
* Dissect an OBJECT_ATTRIBUTES structure.
*
* typedef struct {
* uint32 struct_len;
* [unique] char *root_dir;
* [unique] unistr2 *name;
* uint32 attributes;
* [unique] SECURITY_DESCRIPTOR *sec_desc;
* [unique] SECURITY_QOS *sec_qos;
* } OBJECT_ATTRIBUTES;
*
*/
static int prs_OBJECT_ATTRIBUTES(tvbuff_t *tvb, int offset,
packet_info *pinfo, proto_tree *tree,
int flags, GList **ptr_list)
{
if (flags & PARSE_SCALARS) {
offset = prs_uint32(tvb, offset, pinfo, tree, NULL,
"Structure length");
offset = prs_push_ptr(tvb, offset, pinfo, tree, ptr_list,
"Root directory");
offset = prs_push_ptr(tvb, offset, pinfo, tree, ptr_list,
"Name");
offset = prs_uint32(tvb, offset, pinfo, tree, NULL,
"Attributes");
offset = prs_push_ptr(tvb, offset, pinfo, tree, ptr_list,
"SECURITY_DESCRIPTOR");
offset = prs_push_ptr(tvb, offset, pinfo, tree, ptr_list,
"SEC_QOS");
}
if (flags & PARSE_BUFFERS) {
if (prs_pop_ptr(ptr_list, "Root directory"))
offset = prs_uint8(tvb, offset, pinfo, tree, NULL,
"Root directory");
if (prs_pop_ptr(ptr_list, "Name"))
offset = prs_UNISTR2(tvb, offset, pinfo, tree,
flags, NULL, "Name");
if (prs_pop_ptr(ptr_list, "SECURITY_DESCRIPTOR"))
offset = prs_SECURITY_DESCRIPTOR(
tvb, offset, pinfo, tree, flags);
if (prs_pop_ptr(ptr_list, "SEC_QOS"))
offset = prs_SECURITY_QOS(
tvb, offset, pinfo, tree, flags);
}
return offset;
}
/*
* Open a LSA policy handle. Note that due to a bug in Microsoft's
* original IDL, only the first character of the server name is ever sent
* across the wire. Since the server name is in UNC format this will be a
* single '\'.
*
* uint32 LsarOpenPolicy(
* [in] [unique] wchar_t *server,
* [in] [ref] OBJECT_ATTRIBUTES *attribs,
* [in] uint32 access,
* [out] [context_handle] void **hnd
* );
*
*/
static int LsaOpenPolicy_q(tvbuff_t * tvb, int offset,
packet_info * pinfo, proto_tree * tree,
char *drep)
{
GList *ptr_list = NULL;
int flags = PARSE_SCALARS|PARSE_BUFFERS;
guint32 access;
if (check_col(pinfo->cinfo, COL_INFO))
col_set_str(pinfo->cinfo, COL_INFO, "OpenPolicy request");
offset = prs_push_ptr(tvb, offset, pinfo, tree, &ptr_list, "Server");
if (prs_pop_ptr(&ptr_list, "Server"))
offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Server");
offset = prs_OBJECT_ATTRIBUTES(tvb, offset, pinfo, tree, flags,
&ptr_list);
offset = prs_uint32(tvb, offset, pinfo, tree, &access, NULL);
proto_tree_add_text(tree, tvb, offset, 4, "Access: 0x%08x", access);
return offset;
}
static int LsaOpenPolicy_r(tvbuff_t * tvb, int offset,
packet_info * pinfo, proto_tree * tree,
char *drep)
{
if (check_col(pinfo->cinfo, COL_INFO))
col_set_str(pinfo->cinfo, COL_INFO, "OpenPolicy reply");
offset = prs_policy_hnd(tvb, offset, pinfo, tree, NULL);
offset = prs_ntstatus(tvb, offset, pinfo, tree);
return offset;
}
/*
* Parse a NAME_AND_SID structure.
*
* typedef struct {
* UNICODE_STRING name;
* [unique] SID *sid;
* } NAME_AND_SID;
*
*/
int ett_NAME_AND_SID = -1;
int ett_NAME_AND_SID_hdr = -1;
static int prs_NAME_AND_SID(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, int flags, GList **ptr_list)
{
if (flags & PARSE_SCALARS) {
proto_item *item;
proto_tree *subtree;
item = proto_tree_add_text(tree, tvb, offset, 0,
"NAME_AND_SID header");
subtree = proto_item_add_subtree(item, ett_NAME_AND_SID_hdr);
offset = prs_UNISTR(tvb, offset, pinfo, subtree,
PARSE_SCALARS, ptr_list, "Name");
offset = prs_push_ptr(tvb, offset, pinfo, subtree,
ptr_list, "SID");
}
if (flags & PARSE_BUFFERS) {
proto_item *item;
proto_tree *subtree;
item = proto_tree_add_text(tree, tvb, offset, 0,
"NAME_AND_SID");
subtree = proto_item_add_subtree(item, ett_NAME_AND_SID);
offset = prs_UNISTR(tvb, offset, pinfo, subtree,
PARSE_BUFFERS, ptr_list, "Name");
if (prs_pop_ptr(ptr_list, "SID"))
offset = prs_SID(tvb, offset, pinfo, subtree);
}
return offset;
}
/*
* Parse a POLICY_INFORMATION structure.
*
* typedef union {
* [case(1)] AUDIT_LOG_INFO audit_log;
* [case(2)] AUDIT_SETTINGS audit_settings;
* [case(3)] NAME_AND_SID primary_domain;
* [case(5)] NAME_AND_SID account_domain;
* [case(4)] UNICODE_STRING account;
* [case(6)] SERVER_ROLE server_role;
* [case(7)] REPLICA_SOURCE replica_source;
* [case(8)] QUOTA_INFO default_quota;
* [case(9)] HISTORY history;
* [case(10)] AUDIT_SET_INFO audit_set;
* [case(11)] AUDIT_QUERY_INFO audit_query;
* } POLICY_INFORMATION;
*
*/
static int ett_POLICY_INFORMATION = -1;
static int prs_POLICY_INFORMATION(tvbuff_t *tvb, int offset,
packet_info *pinfo, proto_tree *tree,
int flags)
{
guint16 level;
proto_item *item;
proto_tree *subtree;
GList *ptr_list = NULL;
item = proto_tree_add_text(tree, tvb, offset, 0, "POLICY_INFORMATION");
subtree = proto_item_add_subtree(item, ett_POLICY_INFORMATION);
offset = prs_uint16(tvb, offset, pinfo, subtree, &level, "Info level");
switch (level) {
case 1:
/* offset = prs_AUDIT_LOG_INFO(tvb, offset, pinfo, subtree); */
break;
case 2:
/* offset = prs_AUDIT_SETTINGS(tvb, offset, pinfo, subtree); */
break;
case 3:
offset = prs_NAME_AND_SID(tvb, offset, pinfo, subtree,
flags, &ptr_list);
break;
case 4:
/* offset = prs_UNISTR2(tvb, offset, pinfo, subtree); */
break;
case 5:
offset = prs_NAME_AND_SID(tvb, offset, pinfo, subtree,
flags, &ptr_list);
break;
case 6:
/* offset = prs_SERVER_ROLE(tvb, offset, pinfo, subtree); */
break;
case 7:
/* offset = prs_REPLICA_SOURCE(tvb, offset, pinfo, subtree); */
break;
case 8:
/* offset = prs_QUOTA_INFO(tvb, offset, pinfo, subtree); */
break;
case 9:
/* offset = prs_HISTORY(tvb, offset, pinfo, subtree); */
break;
case 10:
/* offset = prs_AUDIT_SET_INFO(tvb, offset, pinfo, subtree); */
break;
case 11:
/* offset = prs_AUDIT_QUERY_INFO(tvb, offset, pinfo, subtree); */
break;
}
return offset;
}
/*
* uint32 LsarQueryInformationPolicy(
* [in] [context_handle] void *hnd,
* [in] uint16 level,
* [out] [switch_is(level)] [ref] POLICY_INFORMATION **info
* );
*
*/
static int LsaQueryInfoPolicy_q(tvbuff_t *tvb, int offset,
packet_info *pinfo, proto_tree *tree, char *drep)
{
if (check_col(pinfo->cinfo, COL_INFO))
col_set_str(pinfo->cinfo, COL_INFO, "QueryInfo request");
offset = prs_policy_hnd(tvb, offset, pinfo, tree, NULL);
offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Info level");
return offset;
}
static int LsaQueryInfoPolicy_r(tvbuff_t *tvb, int offset,
packet_info *pinfo, proto_tree *tree, char *drep)
{
GList *ptr_list = NULL;
int flags = PARSE_SCALARS|PARSE_BUFFERS;
if (check_col(pinfo->cinfo, COL_INFO))
col_set_str(pinfo->cinfo, COL_INFO, "QueryInfo reply");
offset = prs_push_ptr(tvb, offset, pinfo, tree, &ptr_list,
"POLICY_INFORMATION");
if (prs_pop_ptr(&ptr_list, "POLICY_INFORMATION"))
offset = prs_POLICY_INFORMATION(tvb, offset, pinfo, tree,
flags);
offset = prs_ntstatus(tvb, offset, pinfo, tree);
return offset;
}
/*
* Parse a DOM_RID structure.
*
* typedef struct {
* short type;
* long rid;
* long dom_idx;
* } DOM_RID;
*
*/
static int ett_DOM_RID = -1;
static int prs_DOM_RID(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, int flags, GList **ptr_list)
{
if (flags & PARSE_SCALARS) {
proto_item *item;
proto_tree *subtree;
item = proto_tree_add_text(tree, tvb, offset, 0, "DOM_RID");
subtree = proto_item_add_subtree(item, ett_DOM_RID);
offset = prs_uint16(tvb, offset, pinfo, subtree, NULL, "Type");
offset = prs_uint32(tvb, offset, pinfo, subtree, NULL, "RID");
offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
"Domain index");
}
if (flags & PARSE_BUFFERS) {
}
return offset;
}
/*
* Parse a DOM_RID_ARRAY structure.
*
* typedef struct {
* long count;
* [size_is(count)] [unique] DOM_RID *rids;
* } DOM_RID_ARRAY;
*
*/
static int ett_DOM_RID_ARRAY = -1;
static int ett_DOM_RID_ARRAY_hdr = -1;
static int prs_DOM_RID_ARRAY(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, int flags, GList **ptr_list)
{
if (flags & PARSE_SCALARS) {
proto_item *item;
proto_tree *subtree;
item = proto_tree_add_text(tree, tvb, offset, 0,
"DOM_RID_ARRAY header");
subtree = proto_item_add_subtree(item, ett_DOM_RID_ARRAY_hdr);
offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
"Count");
offset = prs_push_ptr(tvb, offset, pinfo, subtree, ptr_list,
"RIDs");
}
if (flags & PARSE_BUFFERS) {
proto_item *item;
proto_tree *subtree;
guint32 count, i;
item = proto_tree_add_text(tree, tvb, offset, 0,
"DOM_RID_ARRAY");
subtree = proto_item_add_subtree(item, ett_DOM_RID_ARRAY);
if (prs_pop_ptr(ptr_list, "RIDs")) {
offset = prs_uint32(tvb, offset, pinfo, subtree, &count,
"Count");
for (i = 0; i < count; i++) {
offset = prs_DOM_RID(tvb, offset, pinfo,
subtree, PARSE_SCALARS,
ptr_list);
}
for (i = 0; i < count; i++) {
offset = prs_DOM_RID(tvb, offset, pinfo,
subtree, PARSE_BUFFERS,
ptr_list);
}
}
}
return offset;
}
/*
* Parse a NAME_AND_SID_ARRAY structure.
*
* typedef struct {
* long count;
* [size_is(count)] [unique] NAME_AND_SID *objects;
* } NAME_AND_SID_ARRAY;
*
*/
static int ett_NAME_AND_SID_ARRAY = -1;
static int ett_NAME_AND_SID_ARRAY_hdr = -1;
static int prs_NAME_AND_SID_ARRAY(tvbuff_t *tvb, int offset,
packet_info *pinfo, proto_tree *tree,
int flags, GList **ptr_list)
{
if (flags & PARSE_SCALARS) {
proto_item *item;
proto_tree *subtree;
item = proto_tree_add_text(tree, tvb, offset, 0,
"NAME_AND_SID_ARRAY header");
subtree = proto_item_add_subtree(
item, ett_NAME_AND_SID_ARRAY_hdr);
offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
"Count");
offset = prs_push_ptr(tvb, offset, pinfo, subtree, ptr_list,
"NAME_AND_SIDs");
offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
"Max count");
}
if (flags & PARSE_BUFFERS) {
proto_item *item;
proto_tree *subtree;
guint32 count, i;
item = proto_tree_add_text(tree, tvb, offset, 0,
"NAME_AND_SID_ARRAY");
subtree = proto_item_add_subtree(
item, ett_NAME_AND_SID_ARRAY);
offset = prs_uint32(tvb, offset, pinfo, subtree, &count,
"Count");
if (prs_pop_ptr(ptr_list, "NAME_AND_SIDs")) {
for (i = 0; i < count; i++) {
offset = prs_NAME_AND_SID(tvb, offset, pinfo,
subtree,
PARSE_SCALARS,
ptr_list);
}
for (i = 0; i < count; i++) {
offset = prs_NAME_AND_SID(tvb, offset, pinfo,
subtree,
PARSE_BUFFERS,
ptr_list);
}
}
}
return offset;
}
/*
* Parse a DOM_REF_INFO structure.
*
* typedef struct {
* NAME_AND_SID_ARRAY domains;
* long count;
* } DOM_REF_INFO;
*
*/
static int ett_DOM_REF_INFO = -1;
static int ett_DOM_REF_INFO_hdr = -1;
static int prs_DOM_REF_INFO(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, int flags, GList **ptr_list)
{
if (flags & PARSE_SCALARS) {
proto_item *item;
proto_tree *subtree;
item = proto_tree_add_text(tree, tvb, offset, 0,
"DOM_REF_INFO header");
subtree = proto_item_add_subtree(item, ett_DOM_REF_INFO_hdr);
}
if (flags & PARSE_BUFFERS) {
proto_item *item;
proto_tree *subtree;
item = proto_tree_add_text(tree, tvb, offset, 0,
"DOM_REF_INFO");
subtree = proto_item_add_subtree(item, ett_DOM_REF_INFO);
offset = prs_NAME_AND_SID_ARRAY(tvb, offset, pinfo, subtree,
PARSE_SCALARS, ptr_list);
offset = prs_NAME_AND_SID_ARRAY(tvb, offset, pinfo, subtree,
PARSE_BUFFERS, ptr_list);
}
return offset;
}
/*
* Convert a list of names to a list of SIDs.
*
* uint32 LsarLookupNames(
* [in] [context_handle] void *hnd,
* [in] uint32 num_names,
* [in] [size_is(num_names)] [ref] UNISTR2 *names,
* [out] [ref] DOM_REF_INFO **domains,
* [in,out] [ref] DOM_RID_ARRAY *rids,
* [in] uint16 level,
* [in,out] [ref] uint32 *num_mapped
* );
*
*/
static int LsaLookupNames_q(tvbuff_t *tvb, int offset,
packet_info *pinfo, proto_tree *tree, char *drep)
{
GList *ptr_list = NULL;
guint32 count, i;
if (check_col(pinfo->cinfo, COL_INFO))
col_set_str(pinfo->cinfo, COL_INFO, "LookupNames request");
offset = prs_policy_hnd(tvb, offset, pinfo, tree, NULL);
offset = prs_uint32(tvb, offset, pinfo, tree, &count, "Num names");
offset = prs_uint32(tvb, offset, pinfo, tree, &count,
"Name array max count");
for (i = 0; i < count; i++)
offset = prs_UNISTR(tvb, offset, pinfo, tree, PARSE_SCALARS,
&ptr_list, "Name");
for (i = 0; i < count; i++)
offset = prs_UNISTR(tvb, offset, pinfo, tree, PARSE_BUFFERS,
&ptr_list, "Name");
offset = prs_DOM_RID_ARRAY(tvb, offset, pinfo, tree,
PARSE_SCALARS|PARSE_BUFFERS, &ptr_list);
offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Info level");
offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Num mapped");
return offset;
}
static int LsaLookupNames_r(tvbuff_t *tvb, int offset,
packet_info *pinfo, proto_tree *tree, char *drep)
{
GList *ptr_list = NULL;
if (check_col(pinfo->cinfo, COL_INFO))
col_set_str(pinfo->cinfo, COL_INFO, "LookupNames reply");
offset = prs_push_ptr(tvb, offset, pinfo, tree, &ptr_list, "Domains");
if (prs_pop_ptr(&ptr_list, "Domains"))
offset = prs_DOM_REF_INFO(tvb, offset, pinfo, tree,
PARSE_SCALARS|PARSE_BUFFERS,
&ptr_list);
offset = prs_DOM_RID_ARRAY(tvb, offset, pinfo, tree,
PARSE_SCALARS|PARSE_BUFFERS, &ptr_list);
offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Num mapped");
offset = prs_ntstatus(tvb, offset, pinfo, tree);
g_assert(g_list_length(ptr_list) == 0);
return offset;
}
/*
* Parse a SID_ARRAY structure.
*
* typedef struct {
* long count;
* [size_is(count)] [unique] PSID *sids;
* } SID_ARRAY;
*
*/
static int ett_SID_ARRAY = -1;
static int ett_SID_ARRAY_hdr = -1;
static int prs_SID_ARRAY(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, int flags, GList **ptr_list)
{
if (flags & PARSE_SCALARS) {
proto_item *item;
proto_tree *subtree;
item = proto_tree_add_text(tree, tvb, offset, 0,
"SID_ARRAY header");
subtree = proto_item_add_subtree(item, ett_SID_ARRAY_hdr);
offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
"Count");
offset = prs_push_ptr(tvb, offset, pinfo, subtree, ptr_list,
"SIDs");
}
if (flags & PARSE_BUFFERS) {
proto_item *item;
proto_tree *subtree;
guint32 count, i;
item = proto_tree_add_text(tree, tvb, offset, 0,
"SID_ARRAY");
subtree = proto_item_add_subtree(item, ett_SID_ARRAY);
if (prs_pop_ptr(ptr_list, "SIDs")) {
offset = prs_uint32(tvb, offset, pinfo, subtree,
&count, "Count");
for (i = 0; i < count; i++)
offset = prs_push_ptr(tvb, offset, pinfo,
subtree, ptr_list, "SID");
for (i = 0; i < count; i++) {
if (prs_pop_ptr(ptr_list, "SID"))
offset = prs_SID(tvb, offset, pinfo,
subtree);
}
}
}
return offset;
}
/*
* Parse an ACCOUNT_NAME structure.
*
* typedef struct {
* unsigned short type;
* UNICODE_STRING name;
* long dom_idx;
* } ACCOUNT_NAME;
*
*/
static int prs_ACCOUNT_NAME(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, int flags, GList **ptr_list)
{
if (flags & PARSE_SCALARS) {
offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Type");
offset = prs_uint32(tvb, offset, pinfo, tree, NULL,
"Domain index");
offset = prs_UNISTR(tvb, offset, pinfo, tree,
PARSE_SCALARS, ptr_list, "Name");
}
if (flags & PARSE_BUFFERS) {
offset = prs_UNISTR(tvb, offset, pinfo, tree,
PARSE_BUFFERS, ptr_list, "Name");
}
return offset;
}
/*
* Parse an ACCOUNT_NAME_ARRAY structure.
*
* typedef struct {
* long count;
* [size_is(count)] [unique] ACCOUNT_NAME *domains;
* } ACCOUNT_NAME_ARRAY;
*
*/
static int prs_ACCOUNT_NAME_ARRAY(tvbuff_t *tvb, int offset,
packet_info *pinfo, proto_tree *tree,
int flags, GList **ptr_list)
{
if (flags & PARSE_SCALARS) {
proto_item *item;
proto_tree *subtree;
item = proto_tree_add_text(tree, tvb, offset, 0,
"ACCOUNT_NAME_ARRAY header");
subtree = proto_item_add_subtree(item, ett_SID_ARRAY_hdr);
offset = prs_uint32(tvb, offset, pinfo, subtree, NULL,
"Count");
offset = prs_push_ptr(tvb, offset, pinfo, subtree, ptr_list,
"ACCOUNT_NAMEs");
}
if (flags & PARSE_BUFFERS) {
proto_item *item;
proto_tree *subtree;
guint32 count, i;
item = proto_tree_add_text(tree, tvb, offset, 0,
"ACCOUNT_NAME_ARRAY");
subtree = proto_item_add_subtree(item, ett_SID_ARRAY);
if (prs_pop_ptr(ptr_list, "ACCOUNT_NAMEs")) {
offset = prs_uint32(tvb, offset, pinfo, subtree,
&count, "Count");
for (i = 0; i < count; i++) {
offset = prs_ACCOUNT_NAME(tvb, offset, pinfo,
subtree,
PARSE_SCALARS,
ptr_list);
}
for (i = 0; i < count; i++) {
offset = prs_ACCOUNT_NAME(tvb, offset, pinfo,
subtree,
PARSE_BUFFERS,
ptr_list);
}
}
}
return offset;
}
/*
* Convert a list of SIDs to a list of names.
*
* long LsarLookupSids(
* [in] [context_handle] void *hnd,
* [in] [ref] SID_ARRAY *sids,
* [out] [ref] DOM_REF_INFO **domains,
* [in,out] [ref] ACCOUNT_NAME_ARRAY *names,
* [in] unsigned short level,
* [in,out] [ref] long *num_mapped
* );
*
*/
static int LsaLookupSids_q(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, char *drep)
{
GList *ptr_list = NULL;
int flags = PARSE_SCALARS|PARSE_BUFFERS;
if (check_col(pinfo->cinfo, COL_INFO))
col_set_str(pinfo->cinfo, COL_INFO, "LookupSids request");
offset = prs_policy_hnd(tvb, offset, pinfo, tree, NULL);
offset = prs_SID_ARRAY(tvb, offset, pinfo, tree, flags, &ptr_list);
offset = prs_ACCOUNT_NAME_ARRAY(tvb, offset, pinfo, tree, flags,
&ptr_list);
offset = prs_uint16(tvb, offset, pinfo, tree, NULL, "Info level");
offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Num mapped");
return offset;
}
static int LsaLookupSids_r(tvbuff_t *tvb, int offset, packet_info *pinfo,
proto_tree *tree, char *drep)
{
GList *ptr_list = NULL;
if (check_col(pinfo->cinfo, COL_INFO))
col_set_str(pinfo->cinfo, COL_INFO, "LookupSids reply");
offset = prs_push_ptr(tvb, offset, pinfo, tree, &ptr_list,
"DOM_REF_INFO");
if (prs_pop_ptr(&ptr_list, "DOM_REF_INFO"))
offset = prs_DOM_REF_INFO(tvb, offset, pinfo, tree,
PARSE_SCALARS|PARSE_BUFFERS,
&ptr_list);
offset = prs_ACCOUNT_NAME_ARRAY(tvb, offset, pinfo, tree,
PARSE_SCALARS|PARSE_BUFFERS,
&ptr_list);
offset = prs_uint32(tvb, offset, pinfo, tree, NULL, "Num mapped");
offset = prs_ntstatus(tvb, offset, pinfo, tree);
return offset;
}
/*
* List of subdissectors for this pipe.
*/
static dcerpc_sub_dissector dcerpc_lsa_dissectors[] = {
{ LSA_CLOSE, "LSA_CLOSE", LsaClose_q, LsaClose_r },
{ LSA_DELETE, "LSA_DELETE", NULL, NULL },
{ LSA_ENUM_PRIVS, "LSA_ENUM_PRIVS", NULL, NULL },
{ LSA_QUERYSECOBJ, "LSA_QUERYSECOBJ", NULL, NULL },
{ LSA_SETSECOBJ, "LSA_SETSECOBJ", NULL, NULL },
{ LSA_CHANGEPASSWORD, "LSA_CHANGEPASSWORD", NULL, NULL },
{ LSA_OPENPOLICY, "LSA_OPENPOLICY",
LsaOpenPolicy_q, LsaOpenPolicy_r },
{ LSA_QUERYINFOPOLICY, "LSA_QUERYINFOPOLICY",
LsaQueryInfoPolicy_q, LsaQueryInfoPolicy_r },
{ LSA_SETINFOPOLICY, "LSA_SETINFOPOLICY", NULL, NULL },
{ LSA_CLEARAUDITLOG, "LSA_CLEARAUDITLOG", NULL, NULL },
{ LSA_CREATEACCOUNT, "LSA_CREATEACCOUNT", NULL, NULL },
{ LSA_ENUM_ACCOUNTS, "LSA_ENUM_ACCOUNTS", NULL, NULL },
{ LSA_CREATETRUSTDOM, "LSA_CREATETRUSTDOM", NULL, NULL },
{ LSA_ENUMTRUSTDOM, "LSA_ENUMTRUSTDOM", NULL, NULL },
{ LSA_LOOKUPNAMES, "LSA_LOOKUPNAMES",
LsaLookupNames_q, LsaLookupNames_r },
{ LSA_LOOKUPSIDS, "LSA_LOOKUPSIDS",
LsaLookupSids_q, LsaLookupSids_r },
{ LSA_CREATESECRET, "LSA_CREATESECRET", NULL, NULL },
{ LSA_OPENACCOUNT, "LSA_OPENACCOUNT", NULL, NULL },
{ LSA_ENUMPRIVSACCOUNT, "LSA_ENUMPRIVSACCOUNT", NULL, NULL },
{ LSA_ADDPRIVS, "LSA_ADDPRIVS", NULL, NULL },
{ LSA_REMOVEPRIVS, "LSA_REMOVEPRIVS", NULL, NULL },
{ LSA_GETQUOTAS, "LSA_GETQUOTAS", NULL, NULL },
{ LSA_SETQUOTAS, "LSA_SETQUOTAS", NULL, NULL },
{ LSA_GETSYSTEMACCOUNT, "LSA_GETSYSTEMACCOUNT", NULL, NULL },
{ LSA_SETSYSTEMACCOUNT, "LSA_SETSYSTEMACCOUNT", NULL, NULL },
{ LSA_OPENTRUSTDOM, "LSA_OPENTRUSTDOM", NULL, NULL },
{ LSA_QUERYTRUSTDOM, "LSA_QUERYTRUSTDOM", NULL, NULL },
{ LSA_SETINFOTRUSTDOM, "LSA_SETINFOTRUSTDOM", NULL, NULL },
{ LSA_OPENSECRET, "LSA_OPENSECRET", NULL, NULL },
{ LSA_SETSECRET, "LSA_SETSECRET", NULL, NULL },
{ LSA_QUERYSECRET, "LSA_QUERYSECRET", NULL, NULL },
{ LSA_LOOKUPPRIVVALUE, "LSA_LOOKUPPRIVVALUE", NULL, NULL },
{ LSA_LOOKUPPRIVNAME, "LSA_LOOKUPPRIVNAME", NULL, NULL },
{ LSA_PRIV_GET_DISPNAME, "LSA_PRIV_GET_DISPNAME", NULL, NULL },
{ LSA_DELETEOBJECT, "LSA_DELETEOBJECT", NULL, NULL },
{ LSA_ENUMACCTWITHRIGHT, "LSA_ENUMACCTWITHRIGHT", NULL, NULL },
{ LSA_ENUMACCTRIGHTS, "LSA_ENUMACCTRIGHTS", NULL, NULL },
{ LSA_ADDACCTRIGHTS, "LSA_ADDACCTRIGHTS", NULL, NULL },
{ LSA_REMOVEACCTRIGHTS, "LSA_REMOVEACCTRIGHTS", NULL, NULL },
{ LSA_QUERYTRUSTDOMINFO, "LSA_QUERYTRUSTDOMINFO", NULL, NULL },
{ LSA_SETTRUSTDOMINFO, "LSA_SETTRUSTDOMINFO", NULL, NULL },
{ LSA_DELETETRUSTDOM, "LSA_DELETETRUSTDOM", NULL, NULL },
{ LSA_STOREPRIVDATA, "LSA_STOREPRIVDATA", NULL, NULL },
{ LSA_RETRPRIVDATA, "LSA_RETRPRIVDATA", NULL, NULL },
{ LSA_OPENPOLICY2, "LSA_OPENPOLICY2", NULL, NULL },
{ LSA_UNK_GET_CONNUSER, "LSA_UNK_GET_CONNUSER", NULL, NULL },
{0, NULL, NULL, NULL },
};
/* Protocol registration */
static int proto_dcerpc_lsa = -1;
static gint ett_dcerpc_lsa = -1;
void
proto_register_dcerpc_lsa(void)
{
static gint *ett[] = {
&ett_dcerpc_lsa,
&ett_UNISTR,
&ett_UNISTR_hdr,
&ett_NAME_AND_SID,
&ett_NAME_AND_SID_hdr,
&ett_SID,
&ett_POLICY_INFORMATION,
&ett_DOM_REF_INFO,
&ett_DOM_REF_INFO_hdr,
&ett_DOM_RID_ARRAY,
&ett_DOM_RID_ARRAY_hdr,
&ett_DOM_RID,
&ett_SID_ARRAY,
&ett_SID_ARRAY_hdr,
&ett_NAME_AND_SID_ARRAY,
&ett_NAME_AND_SID_ARRAY_hdr,
&ett_SECURITY_QOS,
&ett_SECURITY_QOS_hdr,
};
proto_dcerpc_lsa = proto_register_protocol(
"Microsoft Local Security Architecture", "LSA", "lsa");
proto_register_subtree_array(ett, array_length(ett));
}
/* Protocol handoff */
static e_uuid_t uuid_dcerpc_lsa = {
0x12345778, 0x1234, 0xabcd,
{ 0xef, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab}
};
static guint16 ver_dcerpc_lsa = 0;
void
proto_reg_handoff_dcerpc_lsa(void)
{
/* Register protocol as dcerpc */
dcerpc_init_uuid(proto_dcerpc_lsa, ett_dcerpc_lsa, &uuid_dcerpc_lsa,
ver_dcerpc_lsa, dcerpc_lsa_dissectors);
}