diff --git a/plugins/epan/opcua/opcua.c b/plugins/epan/opcua/opcua.c index fc26d9f30d..4ca68a9e83 100644 --- a/plugins/epan/opcua/opcua.c +++ b/plugins/epan/opcua/opcua.c @@ -38,7 +38,7 @@ void proto_reg_handoff_opcua(void); /* declare parse function pointer */ typedef int (*FctParse)(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); -static int proto_opcua = -1; +int proto_opcua = -1; static dissector_handle_t opcua_handle; /** Official IANA registered port for OPC UA Binary Protocol. */ #define OPCUA_PORT_RANGE "4840" diff --git a/plugins/epan/opcua/opcua_simpletypes.c b/plugins/epan/opcua/opcua_simpletypes.c index a787f21c35..ab006b7552 100644 --- a/plugins/epan/opcua/opcua_simpletypes.c +++ b/plugins/epan/opcua/opcua_simpletypes.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "opcua_simpletypes.h" #include "opcua_hfindeces.h" #include "opcua_statuscode.h" @@ -80,6 +81,7 @@ /* Chosen arbitrarily */ #define MAX_ARRAY_LEN 10000 +#define MAX_NESTING_DEPTH 100 static int hf_opcua_diag_mask = -1; static int hf_opcua_diag_mask_symbolicflag = -1; @@ -168,6 +170,9 @@ int hf_opcua_resultMask_displayname = -1; int hf_opcua_resultMask_typedefinition = -1; static expert_field ei_array_length = EI_INIT; +static expert_field ei_nesting_depth = EI_INIT; + +extern int proto_opcua; /** NodeId encoding mask table */ static const value_string g_nodeidmasks[] = { @@ -526,6 +531,7 @@ void registerSimpleTypes(int proto) static ei_register_info ei[] = { { &ei_array_length, { "opcua.array.length", PI_UNDECODED, PI_ERROR, "Max array length exceeded", EXPFILL }}, + { &ei_nesting_depth, { "opcua.nestingdepth", PI_UNDECODED, PI_ERROR, "Max nesting depth exceeded", EXPFILL }}, }; proto_register_field_array(proto, hf, array_length(hf)); @@ -802,9 +808,19 @@ void parseDiagnosticInfo(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gi guint8 EncodingMask; proto_tree *subtree; proto_item *ti; + guint opcua_nested_count; subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_diagnosticinfo, &ti, "%s: DiagnosticInfo", szFieldName); + /* prevent a too high nesting depth */ + opcua_nested_count = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_opcua, 0)); + if (++opcua_nested_count > MAX_NESTING_DEPTH) + { + expert_add_info(pinfo, ti, &ei_nesting_depth); + return; + } + p_add_proto_data(pinfo->pool, pinfo, proto_opcua, 0, GUINT_TO_POINTER(opcua_nested_count)); + /* parse encoding mask */ EncodingMask = tvb_get_guint8(tvb, iOffset); proto_tree_add_bitmask(subtree, tvb, iOffset, hf_opcua_diag_mask, ett_opcua_diagnosticinfo_encodingmask, diag_mask, ENC_LITTLE_ENDIAN); @@ -912,6 +928,16 @@ void parseVariant(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOf gint iOffset = *pOffset; guint8 EncodingMask; gint32 ArrayDimensions = 0; + guint opcua_nested_count; + + /* prevent a too high nesting depth */ + opcua_nested_count = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_opcua, 0)); + if (++opcua_nested_count > MAX_NESTING_DEPTH) + { + expert_add_info(pinfo, ti, &ei_nesting_depth); + return; + } + p_add_proto_data(pinfo->pool, pinfo, proto_opcua, 0, GUINT_TO_POINTER(opcua_nested_count)); EncodingMask = tvb_get_guint8(tvb, iOffset); proto_tree_add_item(subtree, hf_opcua_variant_encodingmask, tvb, iOffset, 1, ENC_LITTLE_ENDIAN); @@ -1167,10 +1193,20 @@ void parseExtensionObject(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, g guint32 TypeId; proto_tree *extobj_tree; proto_item *ti; + guint opcua_nested_count; /* add extension object subtree */ extobj_tree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_extensionobject, &ti, "%s: ExtensionObject", szFieldName); + /* prevent a too high nesting depth */ + opcua_nested_count = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_opcua, 0)); + if (++opcua_nested_count > MAX_NESTING_DEPTH) + { + expert_add_info(pinfo, ti, &ei_nesting_depth); + return; + } + p_add_proto_data(pinfo->pool, pinfo, proto_opcua, 0, GUINT_TO_POINTER(opcua_nested_count)); + /* add nodeid subtree */ TypeId = getExtensionObjectType(tvb, &iOffset); parseExpandedNodeId(extobj_tree, tvb, pinfo, &iOffset, "TypeId");