forked from osmocom/wireshark
The recent length check added to proto_tree_add_string() revealed a
couple of problems when reading the PROTOS SNMP captures. Check for integer overflows in dissect_snmp_pdu and asn1_null_decode. svn path=/trunk/; revision=12609
This commit is contained in:
parent
a95e6e0407
commit
a0ad7be1d1
10
asn1.c
10
asn1.c
|
@ -418,7 +418,17 @@ asn1_eoc_decode (ASN1_SCK *asn1, int eoc)
|
||||||
int
|
int
|
||||||
asn1_null_decode ( ASN1_SCK *asn1, int enc_len)
|
asn1_null_decode ( ASN1_SCK *asn1, int enc_len)
|
||||||
{
|
{
|
||||||
|
int start_off = asn1->offset;
|
||||||
|
|
||||||
asn1->offset += enc_len;
|
asn1->offset += enc_len;
|
||||||
|
/*
|
||||||
|
* Check for integer overflows.
|
||||||
|
* XXX - ASN1_ERR_LENGTH_MISMATCH seemed like the most appropriate
|
||||||
|
* error from the ones available. Should we make a new one?
|
||||||
|
*/
|
||||||
|
if (asn1->offset < 0 || asn1->offset < start_off)
|
||||||
|
return ASN1_ERR_LENGTH_MISMATCH;
|
||||||
|
|
||||||
return ASN1_ERR_NOERROR;
|
return ASN1_ERR_NOERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1015,7 +1015,7 @@ snmp_variable_decode(proto_tree *snmp_tree,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
||||||
proto_tree *tree, proto_tree *root_tree, ASN1_SCK asn1, guint pdu_type, int start)
|
proto_tree *tree, proto_tree *root_tree, ASN1_SCK *asn1p, guint pdu_type, int start)
|
||||||
{
|
{
|
||||||
gboolean def;
|
gboolean def;
|
||||||
guint length;
|
guint length;
|
||||||
|
@ -1064,7 +1064,7 @@ dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
||||||
"Unknown PDU type %#x");
|
"Unknown PDU type %#x");
|
||||||
if (check_col(pinfo->cinfo, COL_INFO))
|
if (check_col(pinfo->cinfo, COL_INFO))
|
||||||
col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
|
col_add_str(pinfo->cinfo, COL_INFO, pdu_type_string);
|
||||||
length = asn1.offset - start;
|
length = asn1p->offset - start;
|
||||||
if (tree) {
|
if (tree) {
|
||||||
proto_tree_add_uint(tree, hf_snmp_pdutype, tvb, offset, length,
|
proto_tree_add_uint(tree, hf_snmp_pdutype, tvb, offset, length,
|
||||||
pdu_type);
|
pdu_type);
|
||||||
|
@ -1083,7 +1083,7 @@ dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
||||||
case SNMP_MSG_TRAP2:
|
case SNMP_MSG_TRAP2:
|
||||||
case SNMP_MSG_REPORT:
|
case SNMP_MSG_REPORT:
|
||||||
/* request id */
|
/* request id */
|
||||||
ret = asn1_uint32_decode (&asn1, &request_id, &length);
|
ret = asn1_uint32_decode (asn1p, &request_id, &length);
|
||||||
if (ret != ASN1_ERR_NOERROR) {
|
if (ret != ASN1_ERR_NOERROR) {
|
||||||
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
||||||
"request ID", ret);
|
"request ID", ret);
|
||||||
|
@ -1096,7 +1096,7 @@ dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
||||||
offset += length;
|
offset += length;
|
||||||
|
|
||||||
/* error status, or getbulk non-repeaters */
|
/* error status, or getbulk non-repeaters */
|
||||||
ret = asn1_uint32_decode (&asn1, &error_status, &length);
|
ret = asn1_uint32_decode (asn1p, &error_status, &length);
|
||||||
if (ret != ASN1_ERR_NOERROR) {
|
if (ret != ASN1_ERR_NOERROR) {
|
||||||
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
||||||
(pdu_type == SNMP_MSG_GETBULK) ? "non-repeaters"
|
(pdu_type == SNMP_MSG_GETBULK) ? "non-repeaters"
|
||||||
|
@ -1118,7 +1118,7 @@ dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
||||||
offset += length;
|
offset += length;
|
||||||
|
|
||||||
/* error index, or getbulk max-repetitions */
|
/* error index, or getbulk max-repetitions */
|
||||||
ret = asn1_uint32_decode (&asn1, &error_index, &length);
|
ret = asn1_uint32_decode (asn1p, &error_index, &length);
|
||||||
if (ret != ASN1_ERR_NOERROR) {
|
if (ret != ASN1_ERR_NOERROR) {
|
||||||
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
||||||
(pdu_type == SNMP_MSG_GETBULK) ? "max repetitions"
|
(pdu_type == SNMP_MSG_GETBULK) ? "max repetitions"
|
||||||
|
@ -1140,7 +1140,7 @@ dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
||||||
|
|
||||||
case SNMP_MSG_TRAP:
|
case SNMP_MSG_TRAP:
|
||||||
/* enterprise */
|
/* enterprise */
|
||||||
ret = asn1_oid_decode (&asn1, &enterprise, &enterprise_length,
|
ret = asn1_oid_decode (asn1p, &enterprise, &enterprise_length,
|
||||||
&length);
|
&length);
|
||||||
if (ret != ASN1_ERR_NOERROR) {
|
if (ret != ASN1_ERR_NOERROR) {
|
||||||
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
||||||
|
@ -1157,8 +1157,8 @@ dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
||||||
offset += length;
|
offset += length;
|
||||||
|
|
||||||
/* agent address */
|
/* agent address */
|
||||||
start = asn1.offset;
|
start = asn1p->offset;
|
||||||
ret = asn1_header_decode (&asn1, &cls, &con, &tag,
|
ret = asn1_header_decode (asn1p, &cls, &con, &tag,
|
||||||
&def, &agent_address_length);
|
&def, &agent_address_length);
|
||||||
if (ret != ASN1_ERR_NOERROR) {
|
if (ret != ASN1_ERR_NOERROR) {
|
||||||
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
||||||
|
@ -1178,14 +1178,14 @@ dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
||||||
"agent_address", ASN1_ERR_WRONG_LENGTH_FOR_TYPE);
|
"agent_address", ASN1_ERR_WRONG_LENGTH_FOR_TYPE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ret = asn1_string_value_decode (&asn1,
|
ret = asn1_string_value_decode (asn1p,
|
||||||
agent_address_length, &agent_address);
|
agent_address_length, &agent_address);
|
||||||
if (ret != ASN1_ERR_NOERROR) {
|
if (ret != ASN1_ERR_NOERROR) {
|
||||||
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
||||||
"agent address", ret);
|
"agent address", ret);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
length = asn1.offset - start;
|
length = asn1p->offset - start;
|
||||||
if (tree) {
|
if (tree) {
|
||||||
if (agent_address_length != 4) {
|
if (agent_address_length != 4) {
|
||||||
proto_tree_add_text(tree, tvb, offset,
|
proto_tree_add_text(tree, tvb, offset,
|
||||||
|
@ -1203,7 +1203,7 @@ dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
||||||
offset += length;
|
offset += length;
|
||||||
|
|
||||||
/* generic trap type */
|
/* generic trap type */
|
||||||
ret = asn1_uint32_decode (&asn1, &trap_type, &length);
|
ret = asn1_uint32_decode (asn1p, &trap_type, &length);
|
||||||
if (ret != ASN1_ERR_NOERROR) {
|
if (ret != ASN1_ERR_NOERROR) {
|
||||||
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
||||||
"generic trap type", ret);
|
"generic trap type", ret);
|
||||||
|
@ -1216,7 +1216,7 @@ dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
||||||
offset += length;
|
offset += length;
|
||||||
|
|
||||||
/* specific trap type */
|
/* specific trap type */
|
||||||
ret = asn1_uint32_decode (&asn1, &specific_type, &length);
|
ret = asn1_uint32_decode (asn1p, &specific_type, &length);
|
||||||
if (ret != ASN1_ERR_NOERROR) {
|
if (ret != ASN1_ERR_NOERROR) {
|
||||||
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
||||||
"specific trap type", ret);
|
"specific trap type", ret);
|
||||||
|
@ -1229,8 +1229,8 @@ dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
||||||
offset += length;
|
offset += length;
|
||||||
|
|
||||||
/* timestamp */
|
/* timestamp */
|
||||||
start = asn1.offset;
|
start = asn1p->offset;
|
||||||
ret = asn1_header_decode (&asn1, &cls, &con, &tag,
|
ret = asn1_header_decode (asn1p, &cls, &con, &tag,
|
||||||
&def, ×tamp_length);
|
&def, ×tamp_length);
|
||||||
if (ret != ASN1_ERR_NOERROR) {
|
if (ret != ASN1_ERR_NOERROR) {
|
||||||
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
||||||
|
@ -1243,14 +1243,14 @@ dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
||||||
"timestamp", ASN1_ERR_WRONG_TYPE);
|
"timestamp", ASN1_ERR_WRONG_TYPE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ret = asn1_uint32_value_decode(&asn1, timestamp_length,
|
ret = asn1_uint32_value_decode(asn1p, timestamp_length,
|
||||||
×tamp);
|
×tamp);
|
||||||
if (ret != ASN1_ERR_NOERROR) {
|
if (ret != ASN1_ERR_NOERROR) {
|
||||||
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
||||||
"timestamp", ret);
|
"timestamp", ret);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
length = asn1.offset - start;
|
length = asn1p->offset - start;
|
||||||
if (tree) {
|
if (tree) {
|
||||||
proto_tree_add_uint(tree, hf_snmp_timestamp, tvb,
|
proto_tree_add_uint(tree, hf_snmp_timestamp, tvb,
|
||||||
offset, length, timestamp);
|
offset, length, timestamp);
|
||||||
|
@ -1261,7 +1261,7 @@ dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
||||||
|
|
||||||
/* variable bindings */
|
/* variable bindings */
|
||||||
/* get header for variable-bindings sequence */
|
/* get header for variable-bindings sequence */
|
||||||
ret = asn1_sequence_decode(&asn1, &variable_bindings_length, &length);
|
ret = asn1_sequence_decode(asn1p, &variable_bindings_length, &length);
|
||||||
if (ret != ASN1_ERR_NOERROR) {
|
if (ret != ASN1_ERR_NOERROR) {
|
||||||
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
||||||
"variable bindings header", ret);
|
"variable bindings header", ret);
|
||||||
|
@ -1276,7 +1276,7 @@ dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
||||||
sequence_length = 0;
|
sequence_length = 0;
|
||||||
|
|
||||||
/* parse type */
|
/* parse type */
|
||||||
ret = asn1_sequence_decode(&asn1, &variable_length, &length);
|
ret = asn1_sequence_decode(asn1p, &variable_length, &length);
|
||||||
if (ret != ASN1_ERR_NOERROR) {
|
if (ret != ASN1_ERR_NOERROR) {
|
||||||
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
||||||
"variable binding header", ret);
|
"variable binding header", ret);
|
||||||
|
@ -1285,7 +1285,7 @@ dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
||||||
sequence_length += length;
|
sequence_length += length;
|
||||||
|
|
||||||
/* parse object identifier */
|
/* parse object identifier */
|
||||||
ret = asn1_oid_decode (&asn1, &variable_oid,
|
ret = asn1_oid_decode (asn1p, &variable_oid,
|
||||||
&variable_oid_length, &length);
|
&variable_oid_length, &length);
|
||||||
if (ret != ASN1_ERR_NOERROR) {
|
if (ret != ASN1_ERR_NOERROR) {
|
||||||
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
dissect_snmp_parse_error(tvb, offset, pinfo, tree,
|
||||||
|
@ -1353,7 +1353,7 @@ dissect_common_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
||||||
/* Parse the variable's value */
|
/* Parse the variable's value */
|
||||||
next_tvb = NULL;
|
next_tvb = NULL;
|
||||||
ret = snmp_variable_decode(tree, variable_oid,
|
ret = snmp_variable_decode(tree, variable_oid,
|
||||||
variable_oid_length, &asn1, offset, &length, &next_tvb);
|
variable_oid_length, asn1p, offset, &length, &next_tvb);
|
||||||
if (next_tvb) {
|
if (next_tvb) {
|
||||||
new_format_oid(variable_oid, variable_oid_length,
|
new_format_oid(variable_oid, variable_oid_length,
|
||||||
&non_decoded_oid, &decoded_oid);
|
&non_decoded_oid, &decoded_oid);
|
||||||
|
@ -1631,7 +1631,7 @@ dissect_snmp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
||||||
* length.
|
* length.
|
||||||
*/
|
*/
|
||||||
message_length += length;
|
message_length += length;
|
||||||
if (message_length < length) {
|
if (message_length < length || (gint) message_length < 0) {
|
||||||
/*
|
/*
|
||||||
* The message length was probably so large that the
|
* The message length was probably so large that the
|
||||||
* total length overflowed.
|
* total length overflowed.
|
||||||
|
@ -2021,7 +2021,7 @@ dissect_snmp_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
||||||
"PDU type", ASN1_ERR_WRONG_TYPE);
|
"PDU type", ASN1_ERR_WRONG_TYPE);
|
||||||
return message_length;
|
return message_length;
|
||||||
}
|
}
|
||||||
dissect_common_pdu(tvb, offset, pinfo, snmp_tree, tree, asn1, pdu_type, start);
|
dissect_common_pdu(tvb, offset, pinfo, snmp_tree, tree, &asn1, pdu_type, start);
|
||||||
return message_length;
|
return message_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2289,7 +2289,7 @@ dissect_smux_pdu(tvbuff_t *tvb, int offset, packet_info *pinfo,
|
||||||
"PDU type", ASN1_ERR_WRONG_TYPE);
|
"PDU type", ASN1_ERR_WRONG_TYPE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dissect_common_pdu(tvb, offset, pinfo, smux_tree, tree, asn1, pdu_type, start);
|
dissect_common_pdu(tvb, offset, pinfo, smux_tree, tree, &asn1, pdu_type, start);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Reference in New Issue