summaryrefslogtreecommitdiff
path: root/source4/build/pidl/eparser.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/build/pidl/eparser.c')
-rw-r--r--source4/build/pidl/eparser.c540
1 files changed, 540 insertions, 0 deletions
diff --git a/source4/build/pidl/eparser.c b/source4/build/pidl/eparser.c
new file mode 100644
index 0000000000..541c712d51
--- /dev/null
+++ b/source4/build/pidl/eparser.c
@@ -0,0 +1,540 @@
+#include "eparser.h"
+#include <string.h>
+
+static gint ett_array = -1;
+
+struct ndr_pull *ndr_pull_init(tvbuff_t *tvb, int offset, packet_info *pinfo,
+ guint8 *drep)
+{
+ struct ndr_pull *ndr;
+
+ ndr = (struct ndr_pull *)g_malloc(sizeof(*ndr));
+
+ ndr->tvb = tvb_new_subset(tvb, offset, -1, -1);
+ ndr->offset = 0;
+ ndr->pinfo = pinfo;
+ ndr->drep = drep;
+ ndr->flags = NDR_SCALARS|NDR_BUFFERS|LIBNDR_FLAG_REF_ALLOC;
+ return ndr;
+}
+
+/*
+ mark the start of a structure
+*/
+void ndr_pull_struct_start(struct ndr_pull *ndr)
+{
+ struct ndr_ofs_list *ofs;
+
+ ofs = g_malloc(sizeof(*ofs));
+ ofs->offset = ndr->offset;
+ ofs->next = ndr->ofs_list;
+ ndr->ofs_list = ofs;
+}
+
+/*
+ mark the end of a structure
+*/
+void ndr_pull_struct_end(struct ndr_pull *ndr)
+{
+ ndr->ofs_list = ndr->ofs_list->next;
+}
+
+void ndr_pull_align(struct ndr_pull *ndr, int size)
+{
+ if (!(ndr->flags & LIBNDR_FLAG_NOALIGN)) {
+ ndr->offset = (ndr->offset + (size-1)) & ~(size-1);
+ }
+}
+
+void ndr_pull_ptr(struct ndr_pull *ndr, proto_tree *tree, int hf, guint32 *ptr)
+{
+ ndr_pull_uint32(ndr, tree, hf, ptr);
+}
+
+static int hf_string4_len = -1;
+static int hf_string4_offset = -1;
+static int hf_string4_len2 = -1;
+static int hf_string_data = -1;
+
+void ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, proto_tree *tree,
+ char **s)
+{
+ guint32 len1, ofs, len2;
+ char *data;
+
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return;
+ }
+
+ switch (ndr->flags & LIBNDR_STRING_FLAGS) {
+ case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
+ case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
+
+ ndr_pull_uint32(ndr, tree, hf_string4_len, &len1);
+ ndr_pull_uint32(ndr, tree, hf_string4_offset, &ofs);
+ ndr_pull_uint32(ndr, tree, hf_string4_len2, &len2);
+
+ if (len2 > 65535)
+ return;
+
+ data = g_malloc(len2*2);
+
+ proto_tree_add_bytes(tree, hf_string_data, ndr->tvb,
+ ndr->offset, len2 * 2, data);
+
+ g_free(data);
+
+ ndr->offset += len2 * 2;
+
+#if 0
+
+ ndr_pull_uint32(ndr, &len1));
+ ndr_pull_uint32(ndr, &ofs);
+ ndr_pull_uint32(ndr, &len2);
+ if (len2 > len1) {
+ return ndr_pull_error(ndr, NDR_ERR_STRING,
+ "Bad string lengths len1=%u ofs=%u len2=%u\n",
+ len1, ofs, len2);
+ }
+ if (len2 == 0) {
+ *s = talloc_strdup(ndr->mem_ctx, "");
+ break;
+ }
+ NDR_PULL_NEED_BYTES(ndr, len2*2);
+ ret = convert_string_talloc(ndr->mem_ctx, chset, CH_UNIX,
+ ndr->data+ndr->offset,
+ len2*2,
+ (const void **)&as);
+ if (ret == -1) {
+ return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
+ "Bad character conversion");
+ }
+ ndr_pull_advance(ndr, len2*2);
+
+ /* this is a way of detecting if a string is sent with the wrong
+ termination */
+ if (ndr->flags & LIBNDR_FLAG_STR_NOTERM) {
+ if (strlen(as) < len2) {
+ DEBUG(6,("short string '%s'\n", as));
+ }
+ } else {
+ if (strlen(as) == len2) {
+ DEBUG(6,("long string '%s'\n", as));
+ }
+ }
+ *s = as;
+
+#endif
+
+ break;
+
+ case LIBNDR_FLAG_STR_SIZE4:
+
+#if 0
+
+ ndr_pull_uint32(ndr, &len1);
+ NDR_PULL_NEED_BYTES(ndr, len1*2);
+ if (len1 == 0) {
+ *s = talloc_strdup(ndr->mem_ctx, "");
+ break;
+ }
+ ret = convert_string_talloc(ndr->mem_ctx, chset, CH_UNIX,
+ ndr->data+ndr->offset,
+ len1*2,
+ (const void **)&as);
+ if (ret == -1) {
+ return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
+ "Bad character conversion");
+ }
+ ndr_pull_advance(ndr, len1*2);
+ *s = as;
+
+#endif
+
+ break;
+
+ case LIBNDR_FLAG_STR_NULLTERM:
+
+#if 0
+
+ len1 = strnlen_w(ndr->data+ndr->offset,
+ (ndr->data_size - ndr->offset)/2);
+ if (len1*2+2 <= ndr->data_size - ndr->offset) {
+ len1++;
+ }
+ ret = convert_string_talloc(ndr->mem_ctx, chset, CH_UNIX,
+ ndr->data+ndr->offset,
+ len1*2,
+ (const void **)s);
+ if (ret == -1) {
+ return ndr_pull_error(ndr, NDR_ERR_CHARCNV,
+ "Bad character conversion");
+ }
+ ndr_pull_advance(ndr, len1*2);
+
+#endif
+
+ break;
+
+ case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4:
+ case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM:
+
+#if 0
+
+ ndr_pull_uint32(ndr, &len1);
+ ndr_pull_uint32(ndr, &ofs);
+ ndr_pull_uint32(ndr, &len2);
+ if (len2 > len1) {
+ return ndr_pull_error(ndr, NDR_ERR_STRING,
+ "Bad ascii string lengths len1=%u ofs=%u len2=%u\n",
+ len1, ofs, len2);
+ }
+ NDR_ALLOC_N(ndr, as, (len2+1));
+ ndr_pull_bytes(ndr, as, len2);
+ as[len2] = 0;
+ (*s) = as;
+
+#endif
+
+ break;
+
+ case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_LEN4:
+
+#if 0
+ ndr_pull_uint32(ndr, &ofs);
+ ndr_pull_uint32(ndr, &len2);
+ NDR_ALLOC_N(ndr, as, (len2+1));
+ ndr_pull_bytes(ndr, as, len2);
+ as[len2] = 0;
+ (*s) = as;
+
+#endif
+
+ break;
+
+ case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_SIZE2:
+
+#if 0
+
+ ndr_pull_uint16(ndr, &len3);
+ NDR_ALLOC_N(ndr, as, (len3+1));
+ ndr_pull_bytes(ndr, as, len3);
+ as[len3] = 0;
+ (*s) = as;
+
+#endif
+
+ break;
+
+ case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM:
+
+#if 0
+
+ len1 = strnlen(ndr->data+ndr->offset, (ndr->data_size - ndr->offset));
+ if (len1+1 <= ndr->data_size - ndr->offset) {
+ len1++;
+ }
+ NDR_ALLOC_N(ndr, as, (len1+1));
+ ndr_pull_bytes(ndr, as, len1);
+ as[len1] = 0;
+ (*s) = as;
+
+#endif
+
+ break;
+
+ default:
+
+#if 0
+
+ return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n",
+ ndr->flags & LIBNDR_STRING_FLAGS);
+
+#endif
+
+ }
+}
+
+void ndr_pull_array_uint32(struct ndr_pull *ndr, int ndr_flags,
+ proto_tree *tree, char *name, int hf, void *data,
+ int count)
+{
+ int i;
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return;
+ }
+ for (i=0;i<count;i++) {
+ ndr_pull_uint32(ndr, tree, hf, NULL);
+ }
+}
+
+void ndr_pull_array_uint16(struct ndr_pull *ndr, int ndr_flags,
+ proto_tree *tree, char *name, int hf, void *data,
+ int count)
+{
+ int i;
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return;
+ }
+ for (i=0;i<count;i++) {
+ ndr_pull_uint16(ndr, tree, hf, NULL);
+ }
+}
+
+void ndr_pull_array_uint8(struct ndr_pull *ndr, int ndr_flags,
+ proto_tree *tree, char *name, int hf, void *data,
+ int count)
+{
+ int i;
+ if (!(ndr_flags & NDR_SCALARS)) {
+ return;
+ }
+ for (i=0;i<count;i++) {
+ ndr_pull_uint8(ndr, tree, hf, NULL);
+ }
+}
+
+void ndr_pull_array(struct ndr_pull *ndr, int ndr_flags, proto_tree *tree,
+ char *name, void *data, int size, int count,
+ void (*pull_fn)(struct ndr_pull *, int ndr_flags,
+ proto_tree *tree, void *fn_data))
+{
+ proto_tree **subtrees;
+ int i;
+
+ subtrees = (proto_tree **)g_malloc(sizeof(proto_tree **) * count);
+
+ if (!(ndr_flags & NDR_SCALARS)) goto buffers;
+ for (i=0;i<count;i++) {
+ proto_item *item;
+ item = proto_tree_add_text(tree, ndr->tvb, ndr->offset, 0, "Array entry");
+ subtrees[i] = proto_item_add_subtree(item, ett_array);
+
+ if ((ndr_flags & (NDR_SCALARS|NDR_BUFFERS)) == (NDR_SCALARS|NDR_BUFFERS))
+ pull_fn(ndr, NDR_SCALARS, subtrees[i], data);
+ else
+ pull_fn(ndr, NDR_SCALARS, tree, data);
+
+ }
+ if (!(ndr_flags & NDR_BUFFERS)) goto done;
+buffers:
+ for (i=0;i<count;i++) {
+ if ((ndr_flags & (NDR_SCALARS|NDR_BUFFERS)) == (NDR_SCALARS|NDR_BUFFERS))
+ pull_fn(ndr, NDR_BUFFERS, subtrees[i], data);
+ else
+ pull_fn(ndr, NDR_BUFFERS, tree, data);
+ }
+ done:
+ g_free(subtrees);
+}
+
+void ndr_pull_relative(struct ndr_pull *ndr, void *data, int size,
+ void (*fn)(struct ndr_pull *, int ndr_flags,
+ char *name))
+{
+}
+
+void ndr_pull_uint8(struct ndr_pull *ndr, proto_tree *tree, int hf, uint8 *data)
+{
+ ndr->offset = dissect_ndr_uint8(
+ ndr->tvb, ndr->offset, ndr->pinfo,
+ tree, ndr->drep, hf, data);
+}
+
+void ndr_pull_uint16(struct ndr_pull *ndr, proto_tree *tree, int hf, uint16 *data)
+{
+ ndr->offset = dissect_ndr_uint16(
+ ndr->tvb, ndr->offset, ndr->pinfo,
+ tree, ndr->drep, hf, data);
+}
+
+void ndr_pull_uint32(struct ndr_pull *ndr, proto_tree *tree, int hf, uint32 *data)
+{
+ ndr->offset = dissect_ndr_uint32(
+ ndr->tvb, ndr->offset, ndr->pinfo,
+ tree, ndr->drep, hf, data);
+}
+
+void ndr_pull_uint64(struct ndr_pull *ndr, proto_tree *tree, int hf, uint64 *data)
+{
+ ndr->offset = dissect_ndr_uint64(
+ ndr->tvb, ndr->offset, ndr->pinfo,
+ tree, ndr->drep, hf, data);
+}
+
+void ndr_pull_int8(struct ndr_pull *ndr, proto_tree *tree, int hf, int8 *data)
+{
+}
+
+void ndr_pull_int16(struct ndr_pull *ndr, proto_tree *tree, int hf, int16 *data)
+{
+}
+
+void ndr_pull_int32(struct ndr_pull *ndr, proto_tree *tree, int hf, int32 *data)
+{
+}
+
+void ndr_pull_int64(struct ndr_pull *ndr, proto_tree *tree, int hf, int64 *data)
+{
+}
+
+void ndr_pull_NTTIME(struct ndr_pull *ndr, proto_tree *tree, int hf, NTTIME *data)
+{
+}
+
+void ndr_pull_NTSTATUS(struct ndr_pull *ndr, proto_tree *tree, int hf, NTSTATUS *data)
+{
+ ndr->offset = dissect_ntstatus(
+ ndr->tvb, ndr->offset, ndr->pinfo,
+ tree, ndr->drep, hf, data);
+}
+
+void ndr_pull_HYPER_T(struct ndr_pull *ndr, proto_tree *tree, int hf, HYPER_T *data)
+{
+}
+
+void ndr_pull_dom_sid2(struct ndr_pull *ndr, int ndr_flags, proto_tree *tree, struct dom_sid2 *data)
+{
+}
+
+void ndr_pull_subcontext_flags_fn(struct ndr_pull *ndr, proto_tree *tree,
+ size_t sub_size, void *data,
+ void (*fn)(struct ndr_pull *, int ndr_flags,
+ proto_tree *tree, void *data))
+{
+ struct ndr_pull ndr2;
+
+ ndr_pull_subcontext_header(ndr, tree, sub_size, &ndr2);
+ fn(&ndr2, NDR_SCALARS|NDR_BUFFERS, tree, data);
+ if (sub_size) {
+ ndr_pull_advance(ndr, tvb_length(ndr2.tvb));
+ } else {
+ ndr_pull_advance(ndr, ndr2.offset);
+ }
+}
+
+void ndr_pull_subcontext(struct ndr_pull *ndr, struct ndr_pull *ndr2,
+ guint32 size)
+{
+ ndr2->tvb = tvb_new_subset(
+ ndr->tvb, ndr->offset,
+ (tvb_length_remaining(ndr->tvb, ndr->offset) > size) ? size :
+ tvb_length_remaining(ndr->tvb, ndr->offset),
+ (tvb_reported_length_remaining(ndr->tvb, ndr->offset) > size) ? size :
+ tvb_reported_length_remaining(ndr->tvb, ndr->offset));
+
+ ndr2->offset = 0;
+ ndr2->flags = ndr->flags;
+
+ ndr2->pinfo = ndr->pinfo;
+ ndr2->drep = ndr->drep;
+ ndr2->ofs_list = ndr->ofs_list;
+}
+
+static int hf_subcontext_size_2 = -1;
+static int hf_subcontext_size_4 = -1;
+
+void ndr_pull_subcontext_header(struct ndr_pull *ndr, proto_tree *tree,
+ size_t sub_size, struct ndr_pull *ndr2)
+{
+ switch (sub_size) {
+ case 0: {
+ guint32 size = tvb_length(ndr->tvb) - ndr->offset;
+ if (size == 0) return;
+ ndr_pull_subcontext(ndr, ndr2, size);
+ break;
+ }
+
+ case 2: {
+ guint16 size;
+ ndr_pull_uint16(ndr, tree, hf_subcontext_size_2, &size);
+ if (size == 0) return;
+ ndr_pull_subcontext(ndr, ndr2, size);
+ break;
+ }
+
+ case 4: {
+ guint32 size;
+ ndr_pull_uint32(ndr, tree, hf_subcontext_size_4, &size);
+ if (size == 0) return;
+ ndr_pull_subcontext(ndr, ndr2, size);
+ break;
+ }
+ default: ;
+// return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext size %d", sub_size);
+ }
+}
+
+void ndr_pull_advance(struct ndr_pull *ndr, int offset)
+{
+ ndr->offset += offset;
+}
+
+struct subtree_info {
+ char *name;
+ proto_tree *subtree;
+};
+
+proto_tree *get_subtree(proto_tree *tree, char *name, struct ndr_pull *ndr,
+ gint ett)
+{
+ GSList *list, *l;
+ proto_item *item;
+ struct subtree_info *info;
+
+ /* Get current list value */
+
+ if (!tree)
+ return NULL;
+
+ list = (GSList *)tree->user_data;
+
+ /* Look for name */
+
+ for (l = list; l; l = g_slist_next(l)) {
+ info = l->data;
+
+ if (strcmp(name, info->name) == 0)
+ return info->subtree;
+ }
+
+ /* Create new subtree entry */
+
+ info = (struct subtree_info *)g_malloc(sizeof(struct subtree_info));
+
+ info->name = g_strdup(name);
+ item = proto_tree_add_text(tree, ndr->tvb, ndr->offset, 0, name);
+ info->subtree = proto_item_add_subtree(item, ett);
+
+ /* Don't forget to add new list head */
+
+ list = g_slist_append(list, info);
+
+ tree->user_data = list;
+
+ return info->subtree;
+}
+
+void proto_register_eparser(void)
+{
+ static hf_register_info hf[] = {
+ { &hf_string4_len, { "String4 length", "eparser.string4_length", FT_UINT32, BASE_DEC, NULL, 0x0, "String4 length", HFILL }},
+ { &hf_string4_offset, { "String4 offset", "eparser.string4_offset", FT_UINT32, BASE_DEC, NULL, 0x0, "String4 offset", HFILL }},
+ { &hf_string4_len2, { "String4 length2", "eparser.string4_length2", FT_UINT32, BASE_DEC, NULL, 0x0, "String4 length2", HFILL }},
+ { &hf_string_data, { "String data", "eparser.string_data", FT_BYTES, BASE_NONE, NULL, 0x0, "String data", HFILL }},
+ { &hf_subcontext_size_2, { "Subcontext size2", "eparser.subcontext_size2", FT_UINT16, BASE_DEC, NULL, 0x0, "Subcontext size2", HFILL }},
+ { &hf_subcontext_size_4, { "Subcontext size4", "eparser.subcontext_size4", FT_UINT16, BASE_DEC, NULL, 0x0, "Subcontext size4", HFILL }},
+// { &hf_relative_ofs, { "Relative offset", "eparser.relative_offset", FT_UINT32, BASE_DEC, NULL, 0x0, "Relative offset", HFILL }},
+// { &hf_subtree_list, { "Subtree list", "", FT_UINT64, BASE_DEC, NULL, 0,"", HFILL }},
+ };
+
+ static gint *ett[] = {
+ &ett_array,
+ };
+
+ int proto_dcerpc;
+
+ proto_dcerpc = proto_get_id_by_filter_name("dcerpc");
+ proto_register_field_array(proto_dcerpc, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}