diff options
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | Makefile.nmake | 3 | ||||
-rw-r--r-- | packet-dcerpc-lsa.c | 1153 | ||||
-rw-r--r-- | packet-dcerpc-nt.c | 370 | ||||
-rw-r--r-- | packet-dcerpc-nt.h | 74 |
5 files changed, 1588 insertions, 16 deletions
diff --git a/Makefile.am b/Makefile.am index b9b41cf94a..5426155264 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ # Makefile.am # Automake file for Ethereal # -# $Id: Makefile.am,v 1.396 2001/12/15 23:56:04 guy Exp $ +# $Id: Makefile.am,v 1.397 2001/12/16 20:17:09 guy Exp $ # # Ethereal - Network traffic analyzer # By Gerald Combs <gerald@ethereal.com> @@ -457,6 +457,8 @@ ETHEREAL_COMMON_SRC = \ llcsaps.h \ nlpid.h \ oui.h \ + packet-dcerpc-nt.h \ + packet-dcerpc-nt.c \ pcap-util.c \ pcap-util.h \ ppptypes.h \ diff --git a/Makefile.nmake b/Makefile.nmake index d7a86e1ebf..9ffabcd9cf 100644 --- a/Makefile.nmake +++ b/Makefile.nmake @@ -1,7 +1,7 @@ ## Makefile for building ethereal.exe with Microsoft C and nmake ## Use: $(MAKE) /$(MAKEFLAGS) -f makefile.nmake # -# $Id: Makefile.nmake,v 1.153 2001/12/12 01:29:01 guy Exp $ +# $Id: Makefile.nmake,v 1.154 2001/12/16 20:17:09 guy Exp $ include config.nmake include <win32.mak> @@ -256,6 +256,7 @@ ETHEREAL_COMMON_OBJECTS = \ getopt.obj \ in_cksum.obj \ ipproto.obj \ + packet-dcerpc-nt.obj \ pcap-util.obj \ prefs.obj \ print.obj \ diff --git a/packet-dcerpc-lsa.c b/packet-dcerpc-lsa.c index 97797d4a43..0560f15cf9 100644 --- a/packet-dcerpc-lsa.c +++ b/packet-dcerpc-lsa.c @@ -1,8 +1,8 @@ /* packet-dcerpc-lsa.c - * Routines for SMB \\PIPE\\lsarpc packet disassembly + * Routines for SMB \PIPE\lsarpc packet disassembly * Copyright 2001, Tim Potter <tpot@samba.org> * - * $Id: packet-dcerpc-lsa.c,v 1.2 2001/12/09 00:07:37 guy Exp $ + * $Id: packet-dcerpc-lsa.c,v 1.3 2001/12/16 20:17:10 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@ethereal.com> @@ -28,39 +28,1133 @@ #endif #include <glib.h> +#include <string.h> + #include "packet.h" #include "packet-dcerpc.h" +#include "packet-dcerpc-nt.h" #include "packet-dcerpc-lsa.h" +#include "smb.h" -static int proto_dcerpc_lsa = -1; -static gint ett_dcerpc_lsa = -1; +/* + * 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 e_uuid_t uuid_dcerpc_lsa = { - 0x12345778, 0x1234, 0xabcd, - { 0xef, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab} -}; +/* Convert a (little endian) unicode string to ASCII. We fake it by just + taking every odd byte. */ -static guint16 ver_dcerpc_lsa = 0; +static char *fake_unicode(guint16 *data, int len) +{ + char *buffer; + int i; + + buffer = malloc(len + 1); + + for (i = 0; i < len; i++) + buffer[i] = data[i] & 0xff; + + buffer[len] = 0; + + return buffer; +} + +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); + + 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); + 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); + 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); + 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")) + goto done; + + 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); + } +done: + } + + 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")) + goto done; + + 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); + } + done: + } + + 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); + + 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")) + goto done; + + 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); + } + done: + } + + 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")) + goto done; + + 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); + } + done: + } + + 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); + + 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", NULL, NULL }, + { 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", NULL, NULL }, - { LSA_QUERYINFOPOLICY, "LSA_QUERYINFOPOLICY", 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", NULL, NULL }, - { LSA_LOOKUPSIDS, "LSA_LOOKUPSIDS", 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 }, @@ -95,11 +1189,33 @@ static dcerpc_sub_dissector dcerpc_lsa_dissectors[] = { {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( @@ -108,6 +1224,15 @@ proto_register_dcerpc_lsa(void) 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) { diff --git a/packet-dcerpc-nt.c b/packet-dcerpc-nt.c new file mode 100644 index 0000000000..7af722d4b7 --- /dev/null +++ b/packet-dcerpc-nt.c @@ -0,0 +1,370 @@ +/* packet-dcerpc-nt.c + * Routines for DCERPC over SMB packet disassembly + * Copyright 2001, Tim Potter <tpot@samba.org> + * + * $Id: packet-dcerpc-nt.c,v 1.1 2001/12/16 20:17:10 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 "packet.h" +#include "packet-dcerpc.h" +#include "packet-dcerpc-nt.h" +#include "smb.h" + +/* + * This file contains helper routines that are used by the DCERPC over SMB + * dissectors for ethereal. + */ + +/* Align offset to a n-byte boundary */ + +int prs_align(int offset, int n) +{ + if (offset % n) + offset += n - (offset % n); + + return offset; +} + +/* Parse a 8-bit integer */ + +int prs_uint8(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint8 *data, char *name) +{ + guint8 i; + + /* No alignment required */ + + i = tvb_get_guint8(tvb, offset); + offset++; + + if (name && tree) + proto_tree_add_text(tree, tvb, offset - 1, 1, + "%s: %d", name, i); + + if (data) + *data = i; + + return offset; +} + +int prs_uint8s(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, int count, guint8 **data, char *name) +{ + const guint8 *ptr; + + /* No alignment required */ + + ptr = tvb_get_ptr(tvb, offset, count); + + if (name && tree) + proto_tree_add_text(tree, tvb, offset, count, "%s", name); + + if (data) + *data = (guint8 *)ptr; + + offset += count; + + return offset; +} + +/* Parse a 16-bit integer */ + +int prs_uint16(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint16 *data, char *name) +{ + guint16 i; + + offset = prs_align(offset, 2); + + i = tvb_get_letohs(tvb, offset); + offset += 2; + + if (name && tree) + proto_tree_add_text(tree, tvb, offset - 2, 2, + "%s: %d", name, i); + if (data) + *data = i; + + return offset; +} + +/* Parse a number of uint16's */ + +int prs_uint16s(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, int count, guint16 **data, char *name) +{ + const guint8 *ptr; + + offset = prs_align(offset, 2); + + ptr = tvb_get_ptr(tvb, offset, count * 2); + + if (name && tree) + proto_tree_add_text(tree, tvb, offset, count * 2, + "%s", name); + if (data) + *data = (guint16 *)ptr; + + offset += count * 2; + + return offset; +} + +/* Parse a 32-bit integer */ + +int prs_uint32(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint32 *data, char *name) +{ + guint32 i; + + offset = prs_align(offset, 4); + + i = tvb_get_letohl(tvb, offset); + offset += 4; + + if (name && tree) + proto_tree_add_text(tree, tvb, offset - 4, 4, + "%s: %d", name, i); + + if (data) + *data = i; + + return offset; +} + +/* Parse a number of 32-bit integers */ + +int prs_uint32s(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, int count, guint32 **data, char *name) +{ + const guint8 *ptr; + + offset = prs_align(offset, 4); + + ptr = tvb_get_ptr(tvb, offset, count * 4); + + if (name && tree) + proto_tree_add_text(tree, tvb, offset - 4, 4, + "%s", name); + if (data) + *data = (guint32 *)ptr; + + offset += count * 4; + + return offset; +} + +/* Parse a NT status code */ + +int prs_ntstatus(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree) +{ + guint32 status; + + offset = prs_uint32(tvb, offset, pinfo, tree, &status, NULL); + + if (tree) + proto_tree_add_text(tree, tvb, offset - 4, 4, "Status: %s", + val_to_str(status, NT_errors, "???")); + + return offset; +} + +/* + * We need to keep track of deferred referrents as they appear in the + * packet after all the non-pointer objects. + * to keep track of pointers as they are parsed as scalars and need to be + * remembered for the next call to the prs function. + * + * Pointers are stored in a linked list and pushed in the PARSE_SCALARS + * section of the prs function and popped in the PARSE_BUFFERS section. If + * we try to pop off a referrent that has a different name then we are + * expecting then something has gone wrong. + */ + +#undef DEBUG_PTRS + +struct ptr { + char *name; + guint32 value; +}; + +/* Create a new pointer */ + +static struct ptr *new_ptr(char *name, guint32 value) +{ + struct ptr *p; + + p = g_malloc(sizeof(struct ptr)); + + p->name = g_strdup(name); + p->value = value; + + return p; +} + +/* Free a pointer */ + +static void free_ptr(struct ptr *p) +{ + if (p) { + g_free(p->name); + g_free(p); + } +} + +/* Parse a pointer and store it's value in a linked list */ + +int prs_push_ptr(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, GList **ptr_list, char *name) +{ + struct ptr *p; + guint32 value; + + offset = prs_uint32(tvb, offset, pinfo, tree, &value, NULL); + + if (name && tree) + proto_tree_add_text(tree, tvb, offset - 4, 4, + "%s pointer: 0x%08x", name, value); + + p = new_ptr(name, value); + + *ptr_list = g_list_append(*ptr_list, p); + +#ifdef DEBUG_PTRS + fprintf(stderr, "DEBUG_PTRS: pushing %s ptr = 0x%08x, %d ptrs in " + "list\n", name, value, g_list_length(*ptr_list)); +#endif + + return offset; +} + +/* Pop a pointer of a given name. Return it's value. */ + +guint32 prs_pop_ptr(GList **ptr_list, char *name) +{ + GList *elt; + struct ptr *p; + guint32 result; + + g_assert(g_list_length(*ptr_list) != 0); /* List too short */ + + /* Get pointer at head of list */ + + elt = g_list_first(*ptr_list); + p = (struct ptr *)elt->data; + result = p->value; + +#ifdef DEBUG_PTRS + if (strcmp(p->name, name) != 0) { + fprintf(stderr, "DEBUG_PTRS: wrong pointer (%s != %s)\n", + p->name, name); + } +#endif + + /* Free pointer record */ + + *ptr_list = g_list_remove_link(*ptr_list, elt); + +#ifdef DEBUG_PTRS + fprintf(stderr, "DEBUG_PTRS: popping %s ptr = 0x%08x, %d ptrs in " + "list\n", p->name, p->value, g_list_length(*ptr_list)); +#endif + + free_ptr(p); + + return result; +} + +/* + * Parse a UNISTR2 structure + * + * typedef struct { + * short length; + * short size; + * [size_is(size/2)] [length_is(length/2)] [unique] wchar_t *string; + * } UNICODE_STRING; + * + */ + +/* Convert a string from little-endian unicode to ascii. At the moment we + fake it by taking every odd byte. )-: The caller must free the + result returned. */ + +static char *fake_unicode(guint16 *data, int len) +{ + char *buffer; + int i; + + buffer = malloc(len + 1); + + for (i = 0; i < len; i++) + buffer[i] = data[i] & 0xff; + + buffer[len] = 0; + + return buffer; +} + +/* Parse a UNISTR2 structure */ + +int prs_UNISTR2(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, int flags, char **data, char *name) +{ + guint32 len = 0, unknown = 0, max_len = 0; + + if (flags & PARSE_SCALARS) { + offset = prs_uint32(tvb, offset, pinfo, tree, &len, "Length"); + offset = prs_uint32(tvb, offset, pinfo, tree, &unknown, + "Offset"); + offset = prs_uint32(tvb, offset, pinfo, tree, &max_len, + "Max length"); + } + + if (flags & PARSE_BUFFERS) { + guint16 *data16; + + offset = prs_uint16s(tvb, offset, pinfo, tree, max_len, + &data16, "Buffer"); + + if (data) + *data = fake_unicode(data16, max_len); + } + + return offset; +} + +/* Parse a policy handle. */ + +int prs_policy_hnd(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree) +{ + offset = prs_align(offset, 4); + + proto_tree_add_text(tree, tvb, offset, 20, "Policy Handle"); + + return offset + 20; +} diff --git a/packet-dcerpc-nt.h b/packet-dcerpc-nt.h new file mode 100644 index 0000000000..be3a813e07 --- /dev/null +++ b/packet-dcerpc-nt.h @@ -0,0 +1,74 @@ +/* packet-dcerpc-nt.h + * Routines for DCERPC over SMB packet disassembly + * Copyright 2001, Tim Potter <tpot@samba.org> + * + * $Id: packet-dcerpc-nt.h,v 1.1 2001/12/16 20:17:10 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. + */ + +#ifndef __PACKET_DCERPC_NT_H +#define __PACKET_DCEPRC_NT_H + +/* Routines for parsing simple types */ + +int prs_align(int offset, int n); + +int prs_uint8(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint8 *data, char *name); + +int prs_uint8s(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, int count, guint8 **data, char *name); + +int prs_uint16(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint16 *data, char *name); + +int prs_uint16s(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, int count, guint16 **data, char *name); + +int prs_uint32(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint32 *data, char *name); + +int prs_uint32s(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, int count, guint32 **data, char *name); + +/* Parse NT status code */ + +int prs_ntstatus(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree); + +/* Parse some common RPC structures */ + +int prs_UNISTR2(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, int flags, char **data, char *name); + +int prs_policy_hnd(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree); + +/* Routines for handling deferral of referants in NDR */ + +#define PARSE_SCALARS 1 +#define PARSE_BUFFERS 2 + +int prs_push_ptr(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, GList **ptr_list, char *name); + +guint32 prs_pop_ptr(GList **ptr_list, char *name); + +#endif /* packet-dcerpc-nt.h */ |