Ethereal-dev: [Ethereal-dev] a few things for dcerpc
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Todd Sabin <tas@xxxxxxxxxxx>
Date: 18 Nov 2001 19:44:51 -0500
Here's a patch (and a new file) for some dcerpc stuff. It does the following: o Modifies the dcerpc handoff to subdissectors slightly. It also needs to pass the data representation to the subdissector. Also, if no subdissector is found, it puts a "Stub data" entry in the tree. o Adds optional TCP desegmentation to the dcerpc layer. Note that dcerpc has it's own ability to fragment PDUs. This isn't for dealing with that, but with the case of a single PDU being broken over more than one TCP segment. o Adds a little bit of dissection to packet-dcerpc-epm.c. Mainly just proof of concept for the dcerpc handoff stuff. (Writing this is how I realized the need for the drep.) o Adds packet-dcerpc-ndr.c, which will contain NDR dissection routines for use by subdissectors. Todd
? packet-dcerpc-ndr.c Index: Makefile.am =================================================================== RCS file: /cvsroot/ethereal/Makefile.am,v retrieving revision 1.381 diff -u -r1.381 Makefile.am --- Makefile.am 2001/11/15 21:11:01 1.381 +++ Makefile.am 2001/11/19 00:17:40 @@ -100,6 +100,7 @@ packet-dcerpc-conv.c \ packet-dcerpc-epm.c \ packet-dcerpc-mgmt.c \ + packet-dcerpc-ndr.c \ packet-dcerpc-remact.c \ packet-dcerpc-oxid.c \ packet-ddtp.c \ Index: packet-dcerpc-epm.c =================================================================== RCS file: /cvsroot/ethereal/packet-dcerpc-epm.c,v retrieving revision 1.1 diff -u -r1.1 packet-dcerpc-epm.c --- packet-dcerpc-epm.c 2001/07/11 01:25:44 1.1 +++ packet-dcerpc-epm.c 2001/11/19 00:17:40 @@ -41,6 +41,18 @@ static int proto_epm = -1; +static int hf_epm_inquiry_type = -1; +static int hf_epm_object_p = -1; +static int hf_epm_object = -1; +static int hf_epm_if_id_p = -1; +static int hf_epm_if_id = -1; +static int hf_epm_ver_maj = -1; +static int hf_epm_ver_min = -1; +static int hf_epm_ver_opt = -1; +static int hf_epm_lookup_hnd = -1; +static int hf_epm_max_ents = -1; +static int hf_epm_num_ents = -1; + static gint ett_epm = -1; @@ -48,10 +60,69 @@ static guint16 ver_epm = 3; +static int +epm_dissect_ept_lookup_rqst (tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, + char *drep) +{ + guint32 dummy; + offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, + hf_epm_inquiry_type, NULL); + offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, + hf_epm_object_p, &dummy); + if (dummy) { + offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep, + hf_epm_object, NULL); + } + offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, + hf_epm_if_id_p, &dummy); + if (dummy) { + offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep, + hf_epm_if_id, NULL); + offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep, + hf_epm_ver_maj, NULL); + offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep, + hf_epm_ver_min, NULL); + } + offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, + hf_epm_ver_opt, NULL); + if (tree) { + proto_tree_add_bytes (tree, hf_epm_lookup_hnd, tvb, offset, 20, + tvb_get_ptr (tvb, offset, 20)); + } + offset += 20; + + offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, + hf_epm_max_ents, NULL); + return offset; +} + + +static int +epm_dissect_ept_lookup_resp (tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, + char *drep) +{ + guint32 dummy; + + /* need a dissect_ndr_ctx_handle */ + if (tree) { + proto_tree_add_bytes (tree, hf_epm_lookup_hnd, tvb, offset, 20, + tvb_get_ptr (tvb, offset, 20)); + } + offset += 20; + + offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep, + hf_epm_num_ents, NULL); + /* FIXME: more to do here */ + return offset; +} + + static dcerpc_sub_dissector epm_dissectors[] = { { 0, "ept_insert", NULL, NULL }, { 1, "ept_delete", NULL, NULL }, - { 2, "ept_lookup", NULL, NULL }, + { 2, "ept_lookup", epm_dissect_ept_lookup_rqst, epm_dissect_ept_lookup_resp }, { 3, "ept_map", NULL, NULL }, { 4, "ept_lookup_handle_free", NULL, NULL }, { 5, "ept_inq_object", NULL, NULL }, @@ -63,18 +134,36 @@ void proto_register_epm (void) { -#if 0 static hf_register_info hf[] = { - }; -#endif + { &hf_epm_inquiry_type, + { "Inquiry type", "epm.inq_type", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_epm_object_p, + { "Object pointer", "epm.object_p", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_epm_object, + { "Object", "epm.object", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_epm_if_id_p, + { "Interface pointer", "epm.if_id_p", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_epm_if_id, + { "Interface", "epm.if_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_epm_ver_maj, + { "Version Major", "epm.ver_maj", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_epm_ver_min, + { "Version Minor", "epm.ver_min", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_epm_ver_opt, + { "Version Option", "epm.ver_opt", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_epm_lookup_hnd, + { "Lookup Handle", "epm.lookup_hnd", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }}, + { &hf_epm_max_ents, + { "Max entries", "epm.max_ents", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + { &hf_epm_num_ents, + { "Num entries", "epm.num_ents", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, + }; static gint *ett[] = { &ett_epm, }; proto_epm = proto_register_protocol ("DCE/RPC Endpoint Mapper", "EPM", "epm"); -#if 0 proto_register_field_array (proto_epm, hf, array_length (hf)); -#endif proto_register_subtree_array (ett, array_length (ett)); } Index: packet-dcerpc.c =================================================================== RCS file: /cvsroot/ethereal/packet-dcerpc.c,v retrieving revision 1.14 diff -u -r1.14 packet-dcerpc.c --- packet-dcerpc.c 2001/11/12 09:04:11 1.14 +++ packet-dcerpc.c 2001/11/19 00:17:40 @@ -38,6 +38,7 @@ #include "packet.h" #include "packet-dcerpc.h" #include "conversation.h" +#include "prefs.h" static const value_string pckt_vals[] = { { 0, "Request"}, @@ -169,6 +170,9 @@ static gint ett_dcerpc_dg_flags1 = -1; static gint ett_dcerpc_dg_flags2 = -1; +/* try to desegment big DCE/RPC packets over TCP? */ +static gboolean dcerpc_cn_desegment = TRUE; + /* * Subdissectors */ @@ -425,15 +429,16 @@ proto_tree *dcerpc_tree, tvbuff_t *tvb, gint offset, e_uuid_t *uuid, guint16 ver, - guint16 opnum, gboolean is_rqst) + guint16 opnum, gboolean is_rqst, + char *drep) { dcerpc_uuid_key key; dcerpc_uuid_value *sub_proto; int length; - proto_item *sub_item; proto_tree *sub_tree = NULL; dcerpc_sub_dissector *proc; gchar *name = NULL; + dcerpc_dissect_fnct_t *sub_dissect; key.uuid = *uuid; key.ver = ver; @@ -450,6 +455,7 @@ } if (tree) { + proto_item *sub_item; sub_item = proto_tree_add_item (tree, sub_proto->proto, tvb, offset, tvb_length (tvb) - offset, FALSE); if (sub_item) { @@ -476,14 +482,17 @@ col_set_str (pinfo->fd, COL_PROTOCOL, sub_proto->name); } - if (is_rqst) { - if (proc->dissect_rqst) - return proc->dissect_rqst(tvb, offset, pinfo, sub_tree); + sub_dissect = is_rqst ? proc->dissect_rqst : proc->dissect_resp; + if (sub_dissect) { + sub_dissect (tvb, offset, pinfo, sub_tree, drep); } else { - if (proc->dissect_resp) - return proc->dissect_resp(tvb, offset, pinfo, sub_tree); + length = tvb_length_remaining (tvb, offset); + if (length > 0) { + proto_tree_add_text (sub_tree, tvb, offset, length, + "Stub data (%d byte%s)", length, + plurality(length, "", "s")); + } } - return 0; } @@ -817,7 +826,7 @@ tvb_new_subset (tvb, offset, length, reported_length), 0, &value->uuid, value->ver, - opnum, TRUE); + opnum, TRUE, hdr->drep); } } } @@ -870,7 +879,7 @@ tvb_new_subset (tvb, offset, length, reported_length), 0, &value->uuid, value->ver, - value->opnum, FALSE); + value->opnum, FALSE, hdr->drep); } } } @@ -929,6 +938,13 @@ hdr.call_id = dcerpc_tvb_get_ntohl (tvb, offset, hdr.drep); offset += 4; + if (dcerpc_cn_desegment && pinfo->can_desegment + && hdr.frag_len > tvb_length_remaining (tvb, 0)) { + pinfo->desegment_offset = 0; + pinfo->desegment_len = hdr.frag_len - tvb_length_remaining (tvb, 0); + return TRUE; + } + if (tree) { ti = proto_tree_add_item (tree, proto_dcerpc, tvb, 0, tvb_length(tvb), FALSE); if (ti) { @@ -1213,17 +1229,17 @@ dcerpc_call_add_map (hdr.seqnum, conv, hdr.opnum, hdr.if_ver, &hdr.if_id); dcerpc_try_handoff (pinfo, tree, dcerpc_tree, tvb, offset, - &hdr.if_id, hdr.if_ver, hdr.opnum, TRUE); + &hdr.if_id, hdr.if_ver, hdr.opnum, TRUE, hdr.drep); break; case PDU_RESP: { dcerpc_call_value *v = dcerpc_call_lookup (hdr.seqnum, conv); if (v) { dcerpc_try_handoff (pinfo, tree, dcerpc_tree, tvb, offset, - &v->uuid, v->ver, v->opnum, FALSE); + &v->uuid, v->ver, v->opnum, FALSE, hdr.drep); } else { dcerpc_try_handoff (pinfo, tree, dcerpc_tree, tvb, offset, - &hdr.if_id, hdr.if_ver, hdr.opnum, FALSE); + &hdr.if_id, hdr.if_ver, hdr.opnum, FALSE, hdr.drep); } } break; @@ -1438,6 +1454,12 @@ proto_register_subtree_array (ett, array_length (ett)); register_init_routine (dcerpc_init_protocol); + prefs_register_bool_preference (prefs_register_protocol (proto_dcerpc, + NULL), + "desegment_dcerpc", + "Desegment all DCE/RPC over TCP", + "Whether the DCE/RPC dissector should desegment all DCE/RPC over TCP", + &dcerpc_cn_desegment); dcerpc_uuids = g_hash_table_new (dcerpc_uuid_hash, dcerpc_uuid_equal); } Index: packet-dcerpc.h =================================================================== RCS file: /cvsroot/ethereal/packet-dcerpc.h,v retrieving revision 1.2 diff -u -r1.2 packet-dcerpc.h --- packet-dcerpc.h 2001/07/11 01:25:45 1.2 +++ packet-dcerpc.h 2001/11/19 00:17:40 @@ -83,12 +83,43 @@ #define PDU_ALTER_ACK 15 #define PDU_AUTH3 16 - +/* + * helpers for packet-dcerpc.c and packet-dcerpc-ndr.c + * If you're writing a subdissector, you almost certainly want the + * NDR functions below. + */ guint16 dcerpc_tvb_get_ntohs (tvbuff_t *tvb, gint offset, char *drep); guint32 dcerpc_tvb_get_ntohl (tvbuff_t *tvb, gint offset, char *drep); void dcerpc_tvb_get_uuid (tvbuff_t *tvb, gint offset, char *drep, e_uuid_t *uuid); +int dissect_dcerpc_uint8 (tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, char *drep, + int hfindex, guint8 *pdata); +int dissect_dcerpc_uint16 (tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, char *drep, + int hfindex, guint16 *pdata); +int dissect_dcerpc_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, char *drep, + int hfindex, guint32 *pdata); + + +/* + * NDR routines for subdissectors. + */ +int dissect_ndr_uint8 (tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, char *drep, + int hfindex, guint8 *pdata); +int dissect_ndr_uint16 (tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, char *drep, + int hfindex, guint16 *pdata); +int dissect_ndr_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, char *drep, + int hfindex, guint32 *pdata); +int dissect_ndr_uuid_t (tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, char *drep, + int hfindex, e_uuid_t *pdata); + -typedef int (dcerpc_dissect_fnct_t)(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree); +typedef int (dcerpc_dissect_fnct_t)(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, char *drep); typedef struct _dcerpc_sub_dissector { guint16 num;
/* packet-dcerpc-ndr.c * Routines for DCERPC NDR dissection * Copyright 2001, Todd Sabin <tas@xxxxxxxxxxx> * * $Id: $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@xxxxxxxxxxxx> * 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 #ifdef HAVE_SYS_TYPES_H #include <sys/types.h> #endif #include <string.h> #include <ctype.h> #include <glib.h> #include "packet.h" #include "packet-dcerpc.h" /* * The NDR routines are for use by dcerpc subdissetors. They're * primarily for making sure things are aligned properly according * to the rules of NDR. */ int dissect_ndr_uint8 (tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree, char *drep, int hfindex, guint8 *pdata) { /* no alignment needed */ return dissect_dcerpc_uint8 (tvb, offset, pinfo, tree, drep, hfindex, pdata); } int dissect_ndr_uint16 (tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree, char *drep, int hfindex, guint16 *pdata) { if (offset % 2) { offset++; } return dissect_dcerpc_uint16 (tvb, offset, pinfo, tree, drep, hfindex, pdata); } int dissect_ndr_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree, char *drep, int hfindex, guint32 *pdata) { if (offset % 4) { offset += 4 - (offset % 4); } return dissect_dcerpc_uint32 (tvb, offset, pinfo, tree, drep, hfindex, pdata); } int dissect_ndr_uuid_t (tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree, char *drep, int hfindex, e_uuid_t *pdata) { e_uuid_t uuid; /* uuid's are aligned to 4 bytes, due to initial uint32 in struct */ if (offset % 4) { offset += 4 - (offset % 4); } dcerpc_tvb_get_uuid (tvb, offset, drep, &uuid); if (tree) { proto_tree_add_string_format (tree, hfindex, tvb, offset, 16, "", "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", uuid.Data1, uuid.Data2, uuid.Data3, uuid.Data4[0], uuid.Data4[1], uuid.Data4[2], uuid.Data4[3], uuid.Data4[4], uuid.Data4[5], uuid.Data4[6], uuid.Data4[7]); } if (pdata) { *pdata = uuid; } return offset + 16; }
- Follow-Ups:
- Re: [Ethereal-dev] a few things for dcerpc
- From: Ronnie Sahlberg
- Re: [Ethereal-dev] a few things for dcerpc
- From: Guy Harris
- Re: [Ethereal-dev] a few things for dcerpc
- Prev by Date: Re: [Ethereal-dev] [PATCH] fid tracking
- Next by Date: Re: [Ethereal-dev] [PATCH] Ethereal dissectors for Microsoft Windows NT DCE/RPC
- Previous by thread: Re: [Ethereal-dev] Time codes for text2pcap?
- Next by thread: Re: [Ethereal-dev] a few things for dcerpc
- Index(es):