diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
commit | e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch) | |
tree | 68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/dissectors/packet-dcerpc-ndr.c | |
parent | Initial commit. (diff) | |
download | wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip |
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dissectors/packet-dcerpc-ndr.c')
-rw-r--r-- | epan/dissectors/packet-dcerpc-ndr.c | 576 |
1 files changed, 576 insertions, 0 deletions
diff --git a/epan/dissectors/packet-dcerpc-ndr.c b/epan/dissectors/packet-dcerpc-ndr.c new file mode 100644 index 00000000..c4640da0 --- /dev/null +++ b/epan/dissectors/packet-dcerpc-ndr.c @@ -0,0 +1,576 @@ +/* packet-dcerpc-ndr.c + * Routines for DCERPC NDR dissection + * Copyright 2001, Todd Sabin <tas@webspan.net> + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include <epan/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, dcerpc_info *di, guint8 *drep, + int hfindex, guint8 *pdata) +{ + /* Some callers expect us to initialize pdata, even in error conditions, so + * do it right away in case we forget later */ + if (pdata) + *pdata = 0; + + if (di->conformant_run) { + /* just a run to handle conformant arrays, no scalars to dissect */ + return offset; + } + + /* no alignment needed */ + return dissect_dcerpc_uint8(tvb, offset, pinfo, + tree, drep, hfindex, pdata); +} + +int +PIDL_dissect_uint8_val(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, dcerpc_info *di, guint8 *drep, + int hfindex, guint32 param, guint8 *pval) +{ + guint8 val; + + if (di->conformant_run) { + /* just a run to handle conformant arrays, no scalars to dissect */ + return offset; + } + + /* no alignment needed */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, + tree, drep, hfindex, &val); + + if (param&PIDL_SET_COL_INFO) { + header_field_info *hf_info; + char *valstr; + + hf_info = proto_registrar_get_nth(hfindex); + + valstr = (char *)wmem_alloc(pinfo->pool, 64); + valstr[0]=0; + + switch (hf_info->display) { + case BASE_DEC: + if (hf_info->strings) { + snprintf(valstr, 64, "%s(%d)",val_to_str(val, (const value_string *)hf_info->strings, "Unknown:%u"), val); + } else { + snprintf(valstr, 64, "%d", val); + } + break; + case BASE_HEX: + if (hf_info->strings) { + snprintf(valstr, 64, "%s(0x%02x)",val_to_str(val, (const value_string *)hf_info->strings, "Unknown:%u"), val); + } else { + snprintf(valstr, 64, "0x%02x", val); + } + break; + default: + REPORT_DISSECTOR_BUG("Invalid hf->display value"); + } + + col_append_fstr(pinfo->cinfo, COL_INFO," %s:%s", hf_info->name, valstr); + } + if (pval) { + *pval = val; + } + + return offset; +} + +int +PIDL_dissect_uint8(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, dcerpc_info *di, guint8 *drep, + int hfindex, guint32 param) +{ + return PIDL_dissect_uint8_val(tvb, offset, pinfo, tree, di, drep, hfindex, param, NULL); +} + + +int +dissect_ndr_uint16(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, dcerpc_info *di, guint8 *drep, + int hfindex, guint16 *pdata) +{ + /* Some callers expect us to initialize pdata, even in error conditions, so + * do it right away in case we forget later */ + if (pdata) + *pdata = 0; + + if (di->conformant_run) { + /* just a run to handle conformant arrays, no scalars to dissect */ + return offset; + } + + + if (!di->no_align && (offset % 2)) { + offset++; + } + return dissect_dcerpc_uint16(tvb, offset, pinfo, + tree, drep, hfindex, pdata); +} + +int +PIDL_dissect_uint16_val(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, dcerpc_info *di, guint8 *drep, + int hfindex, guint32 param, guint16 *pval) +{ + guint16 val; + + if (di->conformant_run) { + /* just a run to handle conformant arrays, no scalars to dissect */ + return offset; + } + + + if (!di->no_align && (offset % 2)) { + offset++; + } + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, + tree, drep, hfindex, &val); + + if (param&PIDL_SET_COL_INFO) { + header_field_info *hf_info; + char *valstr; + + hf_info = proto_registrar_get_nth(hfindex); + + valstr = (char *)wmem_alloc(pinfo->pool, 64); + valstr[0]=0; + + switch (hf_info->display) { + case BASE_DEC: + if (hf_info->strings) { + snprintf(valstr, 64, "%s(%d)",val_to_str(val, (const value_string *)hf_info->strings, "Unknown:%u"), val); + } else { + snprintf(valstr, 64, "%d", val); + } + break; + case BASE_HEX: + if (hf_info->strings) { + snprintf(valstr, 64, "%s(0x%04x)",val_to_str(val, (const value_string *)hf_info->strings, "Unknown:%u"), val); + } else { + snprintf(valstr, 64, "0x%04x", val); + } + break; + default: + REPORT_DISSECTOR_BUG("Invalid hf->display value"); + } + + col_append_fstr(pinfo->cinfo, COL_INFO," %s:%s", hf_info->name, valstr); + } + + if (pval) { + *pval = val; + } + return offset; +} + +int +PIDL_dissect_uint16(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, dcerpc_info *di, guint8 *drep, + int hfindex, guint32 param) +{ + return PIDL_dissect_uint16_val(tvb, offset, pinfo, tree, di, drep, hfindex, param, NULL); +} + +int +dissect_ndr_uint32(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, dcerpc_info *di, guint8 *drep, + int hfindex, guint32 *pdata) +{ + /* Some callers expect us to initialize pdata, even in error conditions, so + * do it right away in case we forget later */ + if (pdata) + *pdata = 0; + + if ((di != NULL) && (di->conformant_run)) { + /* just a run to handle conformant arrays, no scalars to dissect */ + return offset; + } + + + if ((di != NULL) && (!di->no_align) && (offset % 4)) { + offset += 4 - (offset % 4); + } + return dissect_dcerpc_uint32(tvb, offset, pinfo, + tree, drep, hfindex, pdata); +} + +/* This is used to dissect the new datatypes, such as pointers and conformance + data, which is 4 bytes in size in NDR but 8 bytes in NDR64. +*/ +int +dissect_ndr_uint3264(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, dcerpc_info *di, guint8 *drep, + int hfindex, guint3264 *pdata) +{ + if (di->call_data->flags & DCERPC_IS_NDR64) { + return dissect_ndr_uint64(tvb, offset, pinfo, tree, di, drep, hfindex, pdata); + } else { + guint32 val = 0; + offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, hfindex, &val); + if (pdata) { + *pdata = val; + } + return offset; + } +} + +/* This is used to dissect the new datatypes, such as enums + that are 2 bytes in size in NDR but 4 bytes in NDR64. +*/ +int +dissect_ndr_uint1632(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, dcerpc_info *di, guint8 *drep, + int hfindex, guint1632 *pdata) +{ + if (di->call_data->flags & DCERPC_IS_NDR64) { + return dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, hfindex, pdata); + } else { + guint16 val = 0; + offset = dissect_ndr_uint16(tvb, offset, pinfo, tree, di, drep, hfindex, &val); + if (pdata) { + *pdata = val; + } + return offset; + } +} + +int +PIDL_dissect_uint32_val(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, dcerpc_info *di, guint8 *drep, + int hfindex, guint32 param, guint32 *rval) +{ + guint32 val; + + if (di->conformant_run) { + /* just a run to handle conformant arrays, no scalars to dissect */ + return offset; + } + + + if (!di->no_align && (offset % 4)) { + offset += 4 - (offset % 4); + } + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, + tree, drep, hfindex, &val); + + if (param&PIDL_SET_COL_INFO) { + header_field_info *hf_info; + char *valstr; + + hf_info = proto_registrar_get_nth(hfindex); + + valstr = (char *)wmem_alloc(pinfo->pool, 64); + valstr[0]=0; + + switch (hf_info->display) { + case BASE_DEC: + if (hf_info->strings) { + snprintf(valstr, 64, "%s(%d)",val_to_str(val, (const value_string *)hf_info->strings, "Unknown:%u"), val); + } else { + snprintf(valstr, 64, "%d", val); + } + break; + case BASE_HEX: + if (hf_info->strings) { + snprintf(valstr, 64, "%s(0x%08x)",val_to_str(val, (const value_string *)hf_info->strings, "Unknown:%u"), val); + } else { + snprintf(valstr, 64, "0x%08x", val); + } + break; + default: + REPORT_DISSECTOR_BUG("Invalid hf->display value"); + } + + col_append_fstr(pinfo->cinfo, COL_INFO," %s:%s", hf_info->name, valstr); + } + if (rval != NULL) { + *rval = val; + } + return offset; +} + +int +PIDL_dissect_uint32(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, dcerpc_info *di, guint8 *drep, + int hfindex, guint32 param) +{ + return PIDL_dissect_uint32_val(tvb, offset, pinfo, tree, di, drep, hfindex, param, NULL); +} + +/* Double uint32 + This function dissects the 64bit datatype that is common for + ms interfaces and which is 32bit aligned. + It is really just 2 uint32's +*/ +int +dissect_ndr_duint32(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, dcerpc_info *di, guint8 *drep, + int hfindex, guint64 *pdata) +{ + /* Some callers expect us to initialize pdata, even in error conditions, so + * do it right away in case we forget later */ + if (pdata) + *pdata = 0; + + if (di->conformant_run) { + /* just a run to handle conformant arrays, no scalars to dissect */ + return offset; + } + + if (!di->no_align && (offset % 4)) { + offset += 4 - (offset % 4); + } + return dissect_dcerpc_uint64(tvb, offset, pinfo, + tree, di, drep, hfindex, pdata); +} + +/* uint64 : hyper + a 64 bit integer aligned to proper 8 byte boundaries +*/ +int +dissect_ndr_uint64(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, dcerpc_info *di, guint8 *drep, + int hfindex, guint64 *pdata) +{ + /* Some callers expect us to initialize pdata, even in error conditions, so + * do it right away in case we forget later */ + if (pdata) + *pdata = 0; + + if (di->conformant_run) { + /* just a run to handle conformant arrays, no scalars to dissect */ + return offset; + } + + if (!di->no_align && (offset % 8)) { + gint padding = 8 - (offset % 8); + proto_tree_add_item(tree, hf_dcerpc_ndr_padding, tvb, offset, padding, ENC_NA); + offset += padding; + } + return dissect_dcerpc_uint64(tvb, offset, pinfo, + tree, di, drep, hfindex, pdata); +} + +int +PIDL_dissect_uint64_val(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, dcerpc_info *di, guint8 *drep, + int hfindex, guint32 param, guint64 *pval) +{ + guint64 val; + + if (di->conformant_run) { + /* just a run to handle conformant arrays, no scalars to dissect */ + return offset; + } + + if (!di->no_align && (offset % 8)) { + offset += 8 - (offset % 8); + } + offset = dissect_dcerpc_uint64(tvb, offset, pinfo, + tree, di, drep, hfindex, &val); + + if (param&PIDL_SET_COL_INFO) { + header_field_info *hf_info; + char *valstr; + + hf_info = proto_registrar_get_nth(hfindex); + + valstr = (char *)wmem_alloc(pinfo->pool, 64); + valstr[0]=0; + + switch (hf_info->display) { + case BASE_DEC: + if (hf_info->strings) { + snprintf(valstr, 64, "%s(%" PRIu64 ")",val_to_str( (guint32) val, (const value_string *)hf_info->strings, "Unknown:%u"), val); + } else { + snprintf(valstr, 64, "%" PRIu64, val); + } + break; + case BASE_HEX: + if (hf_info->strings) { + snprintf(valstr, 64, "%s(0x%" PRIx64 ")",val_to_str( (guint32) val, (const value_string *)hf_info->strings, "Unknown:%u"), val); + } else { + snprintf(valstr, 64, "0x%" PRIx64, val); + } + break; + default: + REPORT_DISSECTOR_BUG("Invalid hf->display value"); + } + + col_append_fstr(pinfo->cinfo, COL_INFO," %s:%s", hf_info->name, valstr); + } + + if (pval) { + *pval = val; + } + return offset; +} + +int +PIDL_dissect_uint64(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, dcerpc_info *di, guint8 *drep, + int hfindex, guint32 param) +{ + return PIDL_dissect_uint64_val(tvb, offset, pinfo, tree, di, drep, hfindex, param, NULL); +} + +int +dissect_ndr_float(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, dcerpc_info *di, guint8 *drep, + int hfindex, gfloat *pdata) +{ + /* Some callers expect us to initialize pdata, even in error conditions, so + * do it right away in case we forget later */ + if (pdata) + *pdata = 0; + + + if (di->conformant_run) { + /* just a run to handle conformant arrays, no scalars to dissect */ + return offset; + } + + if (!di->no_align && (offset % 4)) { + offset += 4 - (offset % 4); + } + return dissect_dcerpc_float(tvb, offset, pinfo, + tree, drep, hfindex, pdata); +} + + +int +dissect_ndr_double(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, dcerpc_info *di, guint8 *drep, + int hfindex, gdouble *pdata) +{ + /* Some callers expect us to initialize pdata, even in error conditions, so + * do it right away in case we forget later */ + if (pdata) + *pdata = 0; + + if (di->conformant_run) { + /* just a run to handle conformant arrays, no scalars to dissect */ + return offset; + } + + if (!di->no_align && (offset % 8)) { + offset += 8 - (offset % 8); + } + return dissect_dcerpc_double(tvb, offset, pinfo, + tree, drep, hfindex, pdata); +} + +/* handles unix 32 bit time_t */ +int +dissect_ndr_time_t(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, dcerpc_info *di, guint8 *drep, + int hfindex, guint32 *pdata) +{ + /* Some callers expect us to initialize pdata, even in error conditions, so + * do it right away in case we forget later */ + if (pdata) + *pdata = 0; + + if (di->conformant_run) { + /* just a run to handle conformant arrays, no scalars to dissect */ + return offset; + } + + + if (!di->no_align && (offset % 4)) { + offset += 4 - (offset % 4); + } + return dissect_dcerpc_time_t(tvb, offset, pinfo, + tree, drep, hfindex, pdata); +} + +int +dissect_ndr_uuid_t(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, dcerpc_info *di, guint8 *drep, + int hfindex, e_guid_t *pdata) +{ + /* Some callers expect us to initialize pdata, even in error conditions, so + * do it right away in case we forget later */ + if (pdata) + memset(pdata, 0, sizeof(*pdata)); + + if (di->conformant_run) { + /* just a run to handle conformant arrays, no scalars to dissect */ + return offset; + } + + /* uuid's are aligned to 4 bytes, due to initial uint32 in struct */ + if (!di->no_align && (offset % 4)) { + offset += 4 - (offset % 4); + } + return dissect_dcerpc_uuid_t(tvb, offset, pinfo, + tree, drep, hfindex, pdata); +} + +/* + * XXX - at least according to the DCE RPC 1.1 "nbase.idl", an + * "ndr_context_handle" is an unsigned32 "context_handle_attributes" + * and a uuid_t "context_handle_uuid". The attributes do not appear to + * be used, and always appear to be set to 0, in the DCE RPC 1.1 code. + * + * Should we display an "ndr_context_handle" with a tree holding the + * attributes and the uuid_t? + */ +int +dissect_ndr_ctx_hnd(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_, + proto_tree *tree, dcerpc_info *di, guint8 *drep, + int hfindex, e_ctx_hnd *pdata) +{ + static e_ctx_hnd ctx_hnd; + + if (di->conformant_run) { + /* just a run to handle conformant arrays, no scalars to dissect */ + return offset; + } + + if (!di->no_align && (offset % 4)) { + offset += 4 - (offset % 4); + } + ctx_hnd.attributes = dcerpc_tvb_get_ntohl(tvb, offset, drep); + dcerpc_tvb_get_uuid(tvb, offset+4, drep, &ctx_hnd.uuid); + if (tree) { + /* Bytes is bytes - don't worry about the data representation */ + proto_tree_add_item(tree, hfindex, tvb, offset, 20, ENC_NA); + } + if (pdata) { + *pdata = ctx_hnd; + } + return offset + 20; +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ |