forked from osmocom/wireshark
Check our array lengths and refuse to process them if they're too large.
Fixes bug 3986. Use tvb_memeql and proto_tree_add_item instead of digging around in tvb->real_data. svn path=/trunk/; revision=29813
This commit is contained in:
parent
40e2849be8
commit
ffd3a72374
|
@ -167,32 +167,32 @@ static void dissect_opcua_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree
|
|||
col_set_str(pinfo->cinfo, COL_PROTOCOL, "OpcUa");
|
||||
|
||||
/* parse message type */
|
||||
if (tvb->real_data[0] == 'H' && tvb->real_data[1] == 'E' && tvb->real_data[2] == 'L')
|
||||
if (tvb_memeql(tvb, 0, "HEL", 3))
|
||||
{
|
||||
msgtype = MSG_HELLO;
|
||||
pfctParse = parseHello;
|
||||
}
|
||||
else if (tvb->real_data[0] == 'A' && tvb->real_data[1] == 'C' && tvb->real_data[2] == 'K')
|
||||
else if (tvb_memeql(tvb, 0, "ACK", 3))
|
||||
{
|
||||
msgtype = MSG_ACKNOWLEDGE;
|
||||
pfctParse = parseAcknowledge;
|
||||
}
|
||||
else if (tvb->real_data[0] == 'E' && tvb->real_data[1] == 'R' && tvb->real_data[2] == 'R')
|
||||
else if (tvb_memeql(tvb, 0, "ERR", 3))
|
||||
{
|
||||
msgtype = MSG_ERROR;
|
||||
pfctParse = parseError;
|
||||
}
|
||||
else if (tvb->real_data[0] == 'M' && tvb->real_data[1] == 'S' && tvb->real_data[2] == 'G')
|
||||
else if (tvb_memeql(tvb, 0, "MSG", 3))
|
||||
{
|
||||
msgtype = MSG_MESSAGE;
|
||||
pfctParse = parseMessage;
|
||||
}
|
||||
else if (tvb->real_data[0] == 'O' && tvb->real_data[1] == 'P' && tvb->real_data[2] == 'N')
|
||||
else if (tvb_memeql(tvb, 0, "OPN", 3))
|
||||
{
|
||||
msgtype = MSG_OPENSECURECHANNEL;
|
||||
pfctParse = parseOpenSecureChannel;
|
||||
}
|
||||
else if (tvb->real_data[0] == 'C' && tvb->real_data[1] == 'L' && tvb->real_data[2] == 'O')
|
||||
else if (tvb_memeql(tvb, 0, "CLO", 3))
|
||||
{
|
||||
msgtype = MSG_CLOSESECURECHANNEL;
|
||||
pfctParse = parseCloseSecureChannel;
|
||||
|
|
|
@ -34,9 +34,6 @@
|
|||
#include <string.h>
|
||||
#include <epan/emem.h>
|
||||
|
||||
/* string buffer */
|
||||
#define MAX_BUFFER 256
|
||||
|
||||
#define DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID_FLAG 0x01
|
||||
#define DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE_FLAG 0x02
|
||||
#define DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT_FLAG 0x04
|
||||
|
@ -56,6 +53,9 @@
|
|||
#define EXTOBJ_ENCODINGMASK_BINBODY_FLAG 0x01
|
||||
#define EXTOBJ_ENCODINGMASK_XMLBODY_FLAG 0x02
|
||||
|
||||
/* Chosen arbitrarily */
|
||||
#define MAX_ARRAY_LEN 10000
|
||||
|
||||
static int hf_opcua_diag_mask_symbolicflag = -1;
|
||||
static int hf_opcua_diag_mask_namespaceflag = -1;
|
||||
static int hf_opcua_diag_mask_localizedtextflag = -1;
|
||||
|
@ -338,35 +338,28 @@ void parseInt64(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, int hfIndex)
|
|||
|
||||
void parseString(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, int hfIndex)
|
||||
{
|
||||
char *szValue = ep_alloc(MAX_BUFFER);
|
||||
char *szValue;
|
||||
gint iOffset = *pOffset;
|
||||
gint32 iLen = tvb_get_letohl(tvb, *pOffset);
|
||||
iOffset+=4;
|
||||
|
||||
if (szValue)
|
||||
if (iLen == -1)
|
||||
{
|
||||
if (iLen == -1)
|
||||
{
|
||||
g_snprintf(szValue, MAX_BUFFER, "[OpcUa Null String]");
|
||||
}
|
||||
else if (iLen >= 0)
|
||||
{
|
||||
int iStrLen = iLen;
|
||||
if (iStrLen > (MAX_BUFFER-1)) iStrLen = MAX_BUFFER - 1;
|
||||
/* copy non null terminated string of length iStrlen */
|
||||
strncpy(szValue, (char*)&tvb->real_data[iOffset], iStrLen);
|
||||
/* set null terminator */
|
||||
szValue[iStrLen] = 0;
|
||||
iOffset += iLen; /* eat the whole string */
|
||||
}
|
||||
else
|
||||
{
|
||||
g_snprintf(szValue, MAX_BUFFER, "[Invalid String] Ups, something is wrong with this message.");
|
||||
}
|
||||
|
||||
proto_tree_add_string(tree, hfIndex, tvb, *pOffset, (iOffset - *pOffset), szValue);
|
||||
*pOffset = iOffset;
|
||||
proto_tree_add_string(tree, hfIndex, tvb, *pOffset, (iOffset - *pOffset),
|
||||
"[OpcUa Null String]");
|
||||
}
|
||||
else if (iLen >= 0)
|
||||
{
|
||||
iOffset += iLen; /* eat the whole string */
|
||||
proto_tree_add_item(tree, hfIndex, tvb, *pOffset, (iOffset - *pOffset), TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
szValue = ep_strdup_printf("[Invalid String] Invalid length: %d", iLen);
|
||||
proto_tree_add_string(tree, hfIndex, tvb, *pOffset, (iOffset - *pOffset), szValue);
|
||||
}
|
||||
|
||||
*pOffset = iOffset;
|
||||
}
|
||||
|
||||
void parseStatusCode(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, int hfIndex)
|
||||
|
@ -644,9 +637,17 @@ void parseVariant(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, char *szFieldN
|
|||
proto_tree *subtree = proto_item_add_subtree(ti, ett_opcua_array);
|
||||
int i;
|
||||
|
||||
for (i=0; i<ArrayLength; i++)
|
||||
if (ArrayLength < MAX_ARRAY_LEN)
|
||||
{
|
||||
parseInt32(subtree, tvb, pOffset, hf_opcua_Int32);
|
||||
for (i=0; i<ArrayLength; i++)
|
||||
{
|
||||
parseInt32(subtree, tvb, pOffset, hf_opcua_Int32);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* XXX - This should be expert_add_info_format, but we need pinfo for that */
|
||||
PROTO_ITEM_SET_GENERATED(proto_tree_add_text(tree, tvb, iOffset, 4, "Array length %d too large to process", ArrayLength));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -668,11 +669,17 @@ void parseArraySimple(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, int hfInde
|
|||
/* read array length */
|
||||
iLen = tvb_get_letohl(tvb, *pOffset);
|
||||
proto_tree_add_item(subtree, hf_opcua_ArraySize, tvb, *pOffset, 4, TRUE);
|
||||
*pOffset += 4;
|
||||
|
||||
if (iLen == -1) return; /* no array */
|
||||
if (iLen == 0) return; /* array with zero elements*/
|
||||
|
||||
if (iLen > MAX_ARRAY_LEN)
|
||||
{
|
||||
PROTO_ITEM_SET_GENERATED(proto_tree_add_text(tree, tvb, *pOffset, 4, "Array length %d too large to process", iLen));
|
||||
return;
|
||||
}
|
||||
|
||||
*pOffset += 4;
|
||||
for (i=0; i<iLen; i++)
|
||||
{
|
||||
(*pParserFunction)(subtree, tvb, pOffset, hfIndex);
|
||||
|
@ -694,11 +701,17 @@ void parseArrayEnum(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, fctEnumParse
|
|||
/* read array length */
|
||||
iLen = tvb_get_letohl(tvb, *pOffset);
|
||||
proto_tree_add_item(subtree, hf_opcua_ArraySize, tvb, *pOffset, 4, TRUE);
|
||||
*pOffset += 4;
|
||||
|
||||
if (iLen == -1) return; /* no array */
|
||||
if (iLen == 0) return; /* array with zero elements*/
|
||||
|
||||
if (iLen > MAX_ARRAY_LEN)
|
||||
{
|
||||
PROTO_ITEM_SET_GENERATED(proto_tree_add_text(tree, tvb, *pOffset, 4, "Array length %d too large to process", iLen));
|
||||
return;
|
||||
}
|
||||
|
||||
*pOffset += 4;
|
||||
for (i=0; i<iLen; i++)
|
||||
{
|
||||
(*pParserFunction)(subtree, tvb, pOffset);
|
||||
|
@ -719,11 +732,17 @@ void parseArrayComplex(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, char *szF
|
|||
/* read array length */
|
||||
iLen = tvb_get_letohl(tvb, *pOffset);
|
||||
proto_tree_add_item(subtree, hf_opcua_ArraySize, tvb, *pOffset, 4, TRUE);
|
||||
*pOffset += 4;
|
||||
|
||||
if (iLen == -1) return; /* no array */
|
||||
if (iLen == 0) return; /* array with zero elements*/
|
||||
|
||||
if (iLen > MAX_ARRAY_LEN)
|
||||
{
|
||||
PROTO_ITEM_SET_GENERATED(proto_tree_add_text(tree, tvb, *pOffset, 4, "Array length %d too large to process", iLen));
|
||||
return;
|
||||
}
|
||||
|
||||
*pOffset += 4;
|
||||
for (i=0; i<iLen; i++)
|
||||
{
|
||||
char szNum[20];
|
||||
|
|
|
@ -126,35 +126,11 @@ void registerTransportLayerTypes(int proto)
|
|||
proto_register_field_array(proto, hf, array_length(hf));
|
||||
}
|
||||
|
||||
/** helper functions for adding strings,
|
||||
* that are not zero terminated.
|
||||
*/
|
||||
void addString(proto_tree *tree,
|
||||
int hfindex,
|
||||
tvbuff_t *tvb,
|
||||
gint start,
|
||||
gint length,
|
||||
const char *value)
|
||||
{
|
||||
char *szValue = ep_alloc(256);
|
||||
|
||||
if (szValue)
|
||||
{
|
||||
if (length > 255) length = 255;
|
||||
/* copy non null terminated string data */
|
||||
strncpy(szValue, value, length);
|
||||
/* set null terminator */
|
||||
szValue[length] = 0;
|
||||
|
||||
proto_tree_add_string(tree, hfindex, tvb, start, length, szValue);
|
||||
}
|
||||
}
|
||||
|
||||
/* Transport Layer: message parsers */
|
||||
void parseHello(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)
|
||||
{
|
||||
addString(tree, hf_opcua_transport_type, tvb, *pOffset, 3, tvb->real_data); *pOffset+=3;
|
||||
addString(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, &tvb->real_data[*pOffset]); *pOffset+=1;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, TRUE); *pOffset+=3;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, TRUE); *pOffset+=1;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, TRUE); *pOffset+=4;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_ver, tvb, *pOffset, 4, TRUE); *pOffset+=4;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_rbs, tvb, *pOffset, 4, TRUE); *pOffset+=4;
|
||||
|
@ -166,8 +142,8 @@ void parseHello(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)
|
|||
|
||||
void parseAcknowledge(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)
|
||||
{
|
||||
addString(tree, hf_opcua_transport_type, tvb, *pOffset, 3, tvb->real_data); *pOffset+=3;
|
||||
addString(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, &tvb->real_data[*pOffset]); *pOffset+=1;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, TRUE); *pOffset+=3;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, TRUE); *pOffset+=1;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, TRUE); *pOffset+=4;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_ver, tvb, *pOffset, 4, TRUE); *pOffset+=4;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_rbs, tvb, *pOffset, 4, TRUE); *pOffset+=4;
|
||||
|
@ -178,8 +154,8 @@ void parseAcknowledge(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)
|
|||
|
||||
void parseError(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)
|
||||
{
|
||||
addString(tree, hf_opcua_transport_type, tvb, *pOffset, 3, tvb->real_data); *pOffset+=3;
|
||||
addString(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, &tvb->real_data[*pOffset]); *pOffset+=1;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, TRUE); *pOffset+=3;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, TRUE); *pOffset+=1;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, TRUE); *pOffset+=4;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_error, tvb, *pOffset, 4, TRUE); *pOffset+=4;
|
||||
parseString(tree, tvb, pOffset, hf_opcua_transport_reason);
|
||||
|
@ -192,8 +168,8 @@ void parseMessage(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)
|
|||
proto_tree *nodeid_tree;
|
||||
int ServiceId = 0;
|
||||
|
||||
addString(tree, hf_opcua_transport_type, tvb, *pOffset, 3, tvb->real_data); *pOffset+=3;
|
||||
addString(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, &tvb->real_data[*pOffset]); *pOffset+=1;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, TRUE); *pOffset+=3;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, TRUE); *pOffset+=1;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, TRUE); *pOffset+=4;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_scid, tvb, *pOffset, 4, TRUE); *pOffset+=4;
|
||||
|
||||
|
@ -223,8 +199,8 @@ void parseOpenSecureChannel(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)
|
|||
proto_tree *nodeid_tree;
|
||||
int ServiceId = 0;
|
||||
|
||||
addString(tree, hf_opcua_transport_type, tvb, *pOffset, 3, tvb->real_data); *pOffset+=3;
|
||||
addString(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, &tvb->real_data[*pOffset]); *pOffset+=1;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, TRUE); *pOffset+=3;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, TRUE); *pOffset+=1;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, TRUE); *pOffset+=4;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_scid, tvb, *pOffset, 4, TRUE); *pOffset+=4;
|
||||
parseString(tree, tvb, pOffset, hf_opcua_transport_spu);
|
||||
|
@ -247,8 +223,8 @@ void parseOpenSecureChannel(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)
|
|||
|
||||
void parseCloseSecureChannel(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)
|
||||
{
|
||||
addString(tree, hf_opcua_transport_type, tvb, *pOffset, 3, tvb->real_data); *pOffset+=3;
|
||||
addString(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, &tvb->real_data[*pOffset]); *pOffset+=1;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, TRUE); *pOffset+=3;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, TRUE); *pOffset+=1;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, TRUE); *pOffset+=4;
|
||||
proto_tree_add_item(tree, hf_opcua_transport_scid, tvb, *pOffset, 4, TRUE); *pOffset+=4;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue