wireshark/packet-dcerpc-lsa.c

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);
}