Author: tpot Date: 2005-03-13 02:57:35 +0000 (Sun, 13 Mar 2005) New Revision: 246
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=lorikeet&rev=246 Log: Ethereal plugin to use the output of ndrdump to generate parser output. Needs a patch to ndrdump to accept data from stdin. Added: trunk/ethereal/ndrdump/ trunk/ethereal/ndrdump/Makefile trunk/ethereal/ndrdump/moduleinfo.c trunk/ethereal/ndrdump/moduleinfo.h trunk/ethereal/ndrdump/ndrdump.c Changeset: Added: trunk/ethereal/ndrdump/Makefile =================================================================== --- trunk/ethereal/ndrdump/Makefile 2005-03-13 00:34:15 UTC (rev 245) +++ trunk/ethereal/ndrdump/Makefile 2005-03-13 02:57:35 UTC (rev 246) @@ -0,0 +1,9 @@ +PLUGIN = ndrdump.so + +CFLAGS = -I ../include $(shell pkg-config --cflags glib-2.0) -g +LDFLAGS= -shared -Wl,--export-dynamic -Wl,-soname -Wl,$(PLUGIN) + +OBJS = moduleinfo.o ndrdump.o + +ndrdump.so: $(OBJS) + $(CC) -o $(PLUGIN) $(OBJS) $(LDFLAGS) Copied: trunk/ethereal/ndrdump/moduleinfo.c (from rev 244, trunk/ethereal/pidl/moduleinfo.c) Copied: trunk/ethereal/ndrdump/moduleinfo.h (from rev 244, trunk/ethereal/pidl/moduleinfo.h) Added: trunk/ethereal/ndrdump/ndrdump.c =================================================================== --- trunk/ethereal/ndrdump/ndrdump.c 2005-03-13 00:34:15 UTC (rev 245) +++ trunk/ethereal/ndrdump/ndrdump.c 2005-03-13 02:57:35 UTC (rev 246) @@ -0,0 +1,172 @@ +#include "config.h" + +#include <gmodule.h> +#include "plugins/plugin_api.h" +#include "epan/packet.h" +#include "epan/dissectors/packet-dcerpc.h" + +#include <sys/types.h> +#include <sys/wait.h> + +static int proto_dcerpc_samr = -1; + +static gint ett_dcerpc_samr = -1; + +static int hf_samr_opnum = -1; + +static e_uuid_t uuid_dcerpc_samr = { + 0x12345778, 0x1234, 0xabcd, + { 0xef, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xac } +}; + +static guint16 ver_dcerpc_samr = 1.0; + +static void process_data(char *data, int data_len, proto_tree *tree, + tvbuff_t *tvb, int offset) +{ + gchar **lines = g_strsplit(data, "\n", 0); + + if (*lines) { /* skip opcode */ + proto_tree_add_text(tree, tvb, offset, 0, *lines); + lines++; + } + + if (*lines) { /* skip in/out */ + proto_tree_add_text(tree, tvb, offset, 0, *lines); + lines++; + } + +#define END_TOKEN "pull returned" + + while (*lines) { + if (strncmp(*lines, END_TOKEN, strlen(END_TOKEN)) == 0) { + proto_tree_add_text(tree, tvb, offset, 0, + *lines + strlen(END_TOKEN)); + break; + } + + proto_tree_add_text(tree, tvb, offset, 0, *lines); + lines++; + } +} + +static int +ndrdump_dissect_packet(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep) +{ + dcerpc_info *di = (dcerpc_info *)pinfo->private_data; + dcerpc_call_value *dcv = (dcerpc_call_value *)di->call_data; + int read_pipe[2], write_pipe[2]; + pid_t child_pid; + int status; + + /* Create pipe to ndrdump */ + + if (pipe(read_pipe) == -1 || pipe(write_pipe) == -1) { + perror("pipe"); + return 1; + } + + if ((child_pid = fork()) == -1) { + perror("fork"); + return 1; + } + +#define PARENT_READ read_pipe[0] +#define CHILD_WRITE read_pipe[1] +#define CHILD_READ write_pipe[0] +#define PARENT_WRITE write_pipe[1] + + if (child_pid == 0) { + + close(PARENT_WRITE); + close(PARENT_READ); + + dup2(CHILD_READ, fileno(stdin)); + dup2(CHILD_WRITE, fileno(stdout)); + + char *opnum; + asprintf(&opnum, "%d", dcv->opnum); + + execlp("ndrdump", "ndrdump", "samr", opnum, + (di->ptype == PDU_REQ) ? "in" : "out", NULL); + exit(1); + } + + close(CHILD_READ); + close(CHILD_WRITE); + + /* Write data */ + + char *tvb_data = (char *)tvb_get_ptr(tvb, offset, -1); + + int result = write(PARENT_WRITE, tvb_data, + tvb_length_remaining(tvb, offset)); + + close(PARENT_WRITE); + + /* Read ndrdump output */ + + char *data = NULL, buf[255]; + int num_read, data_len = 0; + + while((num_read = read(PARENT_READ, buf, 255)) > 0) { + data = realloc(data, data_len + num_read); + memcpy(data + data_len, buf, num_read); + data_len += num_read; + } + + if (data && data_len) + process_data(data, data_len, tree, tvb, offset); + + waitpid(child_pid, &status, 0); + + if (WIFSIGNALED(status)) { + g_warning("ndrdump caught signal %d\n", WTERMSIG(status)); + } + + if (WEXITSTATUS(status) != 0) { + } + + return offset + tvb_length_remaining(tvb, offset); +} + +static dcerpc_sub_dissector ndrdump_dissectors[] = { + { 0, "Opnum 0", ndrdump_dissect_packet, ndrdump_dissect_packet }, + { 1, "Opnum 1", ndrdump_dissect_packet, ndrdump_dissect_packet }, + { 2, "Opnum 2", ndrdump_dissect_packet, ndrdump_dissect_packet }, + { 3, "Opnum 3", ndrdump_dissect_packet, ndrdump_dissect_packet }, + { 4, "Opnum 4", ndrdump_dissect_packet, ndrdump_dissect_packet }, + {0, NULL, NULL, NULL } +}; + +G_MODULE_EXPORT void +plugin_reg_handoff(void) +{ + dcerpc_init_uuid(proto_dcerpc_samr, ett_dcerpc_samr, + &uuid_dcerpc_samr, ver_dcerpc_samr, + ndrdump_dissectors, hf_samr_opnum); +} + +G_MODULE_EXPORT void +plugin_init(plugin_address_table_t *pat) +{ + static gint *ett[] = { + &ett_dcerpc_samr, + }; + + static hf_register_info hf[] = { + { &hf_samr_opnum, + { "Operation", "samr.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, "Operation", HFILL }}, + }; + + plugin_address_table_init(pat); + + proto_dcerpc_samr = + proto_register_protocol("ndrdump_samr", "ndrdump_samr", + "ndrdump_samr"); + + proto_register_subtree_array(ett, array_length(ett)); + + proto_register_field_array(proto_dcerpc_samr, hf, array_length(hf)); +}