Improve heuristic standard detection:

- Make sccp_called_calling_looks_valid() static.
 - Reject GT-routed Class-2 (it's not used).
 - Handle UDTS.
 - Handle optional pointer on several messages.

svn path=/trunk/; revision=40782
This commit is contained in:
Jeff Morriss 2012-01-31 04:02:08 +00:00
parent cf24e97617
commit b0ab8e5df4
1 changed files with 99 additions and 26 deletions

View File

@ -818,8 +818,13 @@ static const value_string assoc_protos[] = {
{ 0, NULL }
};
gboolean
sccp_called_calling_looks_valid(tvbuff_t *tvb, guint8 my_mtp3_standard)
#define is_connectionless(m) \
( m == SCCP_MSG_TYPE_UDT || m == SCCP_MSG_TYPE_UDTS \
|| m == SCCP_MSG_TYPE_XUDT|| m == SCCP_MSG_TYPE_XUDTS \
|| m == SCCP_MSG_TYPE_LUDT|| m == SCCP_MSG_TYPE_LUDTS)
static gboolean
sccp_called_calling_looks_valid(tvbuff_t *tvb, guint8 my_mtp3_standard, gboolean is_co)
{
guint8 ai, ri, gti, ssni, pci;
@ -849,8 +854,15 @@ sccp_called_calling_looks_valid(tvbuff_t *tvb, guint8 my_mtp3_standard)
/* Route on SSN with no SSN? */
if (ri == ROUTE_ON_SSN && ssni == 0)
return FALSE;
/* Route on GT with no GT? */
if (ri != ROUTE_ON_SSN && gti == AI_GTI_NO_GT)
if (ri == ROUTE_ON_GT && gti == AI_GTI_NO_GT)
return FALSE;
/* GT routed and connection-oriented (Class-2)?
* Yes, that's theoretically possible, but it's not used.
*/
if (ri == ROUTE_ON_GT && is_co)
return FALSE;
return TRUE;
@ -901,21 +913,38 @@ looks_like_valid_sccp(tvbuff_t *tvb, guint8 my_mtp3_standard)
break;
case SCCP_MSG_TYPE_UDT:
case SCCP_MSG_TYPE_XUDT: /* 0x11 */
case SCCP_MSG_TYPE_UDTS:
{
/* Class lower four bits */
msg_class = tvb_get_guint8(tvb, offset) & CLASS_CLASS_MASK;
if (msg_class > 1)
return FALSE;
offset += PROTOCOL_CLASS_LENGTH;
if (msgtype == SCCP_MSG_TYPE_UDT || msgtype == SCCP_MSG_TYPE_XUDT) {
/* Class lower four bits */
msg_class = tvb_get_guint8(tvb, offset) & CLASS_CLASS_MASK;
if (msg_class > 1)
return FALSE;
offset += PROTOCOL_CLASS_LENGTH;
}
if (msgtype == SCCP_MSG_TYPE_XUDT)
offset += HOP_COUNTER_LENGTH;
if (msgtype == SCCP_MSG_TYPE_UDTS) {
cause = tvb_get_guint8(tvb, offset);
if (!match_strval(cause, sccp_return_cause_values))
return FALSE;
offset += RETURN_CAUSE_LENGTH;
}
called_ptr = tvb_get_guint8(tvb, offset) + offset;
calling_ptr = tvb_get_guint8(tvb, offset+1) + offset+1;
data_ptr = tvb_get_guint8(tvb, offset+2) + offset+2;
if (msgtype == SCCP_MSG_TYPE_XUDT)
opt_ptr = tvb_get_guint8(tvb, offset+3) + offset+3;
offset += POINTER_LENGTH;
calling_ptr = tvb_get_guint8(tvb, offset) + offset;
offset += POINTER_LENGTH;
data_ptr = tvb_get_guint8(tvb, offset) + offset;
offset += POINTER_LENGTH;
if (msgtype == SCCP_MSG_TYPE_XUDT) {
opt_ptr = tvb_get_guint8(tvb, offset);
if (opt_ptr)
opt_ptr += offset;
offset += POINTER_LENGTH;
}
/* Check that all the pointers are within bounds */
if (called_ptr > len || calling_ptr > len || data_ptr > len || opt_ptr > len)
@ -926,8 +955,6 @@ looks_like_valid_sccp(tvbuff_t *tvb, guint8 my_mtp3_standard)
tvb_get_guint8(tvb, calling_ptr) > len ||
tvb_get_guint8(tvb, data_ptr) > len)
return FALSE;
if (msgtype == SCCP_MSG_TYPE_XUDT && tvb_get_guint8(tvb, opt_ptr) > len)
return FALSE;
}
break;
case SCCP_MSG_TYPE_CR:
@ -947,6 +974,11 @@ looks_like_valid_sccp(tvbuff_t *tvb, guint8 my_mtp3_standard)
msg_class = tvb_get_guint8(tvb, offset) & CLASS_CLASS_MASK;
if (msg_class != 2)
return FALSE;
offset += PROTOCOL_CLASS_LENGTH;
opt_ptr = tvb_get_guint8(tvb, offset);
if (opt_ptr)
opt_ptr += offset;
}
break;
case SCCP_MSG_TYPE_CREF:
@ -956,6 +988,11 @@ looks_like_valid_sccp(tvbuff_t *tvb, guint8 my_mtp3_standard)
cause = tvb_get_guint8(tvb, offset);
if (!match_strval(cause, sccp_refusal_cause_values))
return FALSE;
offset += REFUSAL_CAUSE_LENGTH;
opt_ptr = tvb_get_guint8(tvb, offset);
if (opt_ptr)
opt_ptr += offset;
}
break;
case SCCP_MSG_TYPE_RLSD:
@ -966,6 +1003,13 @@ looks_like_valid_sccp(tvbuff_t *tvb, guint8 my_mtp3_standard)
cause = tvb_get_guint8(tvb, offset);
if (!match_strval(cause, sccp_release_cause_values))
return FALSE;
offset += RELEASE_CAUSE_LENGTH;
if (offset + 1U > len)
return FALSE;
opt_ptr = tvb_get_guint8(tvb, offset);
if (opt_ptr)
opt_ptr += offset;
}
break;
case SCCP_MSG_TYPE_RLC:
@ -975,16 +1019,26 @@ looks_like_valid_sccp(tvbuff_t *tvb, guint8 my_mtp3_standard)
}
break;
case SCCP_MSG_TYPE_DT1: /* 6 */
if (len < 7) {
if (len < 8) {
/* Mandatory parameter(data)+ at least one data */
return FALSE;
}
offset += DESTINATION_LOCAL_REFERENCE_LENGTH;
offset += POINTER_LENGTH;
data_ptr = tvb_get_guint8(tvb, offset);
if (tvb_get_guint8(tvb, data_ptr) > len) {
/* Are any of the spare bits in set? */
if (tvb_get_guint8(tvb, offset) & ~SEGMENTING_REASSEMBLING_MASK)
return FALSE;
offset += SEGMENTING_REASSEMBLING_LENGTH;
data_ptr = tvb_get_guint8(tvb, offset) + offset;
/* Verify the data pointer is within bounds */
if (data_ptr > len)
return FALSE;
offset += POINTER_LENGTH;
/* Verify the data length uses the rest of the message */
if (tvb_get_guint8(tvb, data_ptr) + offset + 1U != len)
return FALSE;
}
break;
default:
@ -996,10 +1050,35 @@ looks_like_valid_sccp(tvbuff_t *tvb, guint8 my_mtp3_standard)
guint8 param_len = tvb_get_guint8(tvb, called_ptr);
tvbuff_t *param_tvb = tvb_new_subset(tvb, called_ptr, param_len, param_len);
if (!sccp_called_calling_looks_valid(param_tvb, my_mtp3_standard))
if (!sccp_called_calling_looks_valid(param_tvb, my_mtp3_standard, !is_connectionless(msgtype)))
return FALSE;
}
if (opt_ptr) {
guint8 opt_param;
/* Check that the optional pointer is within bounds */
if (opt_ptr+1U > len)
return FALSE;
opt_param = tvb_get_guint8(tvb, opt_ptr);
/* Check if the (1st) parameter tag is valid */
if (!match_strval(opt_param, sccp_parameter_values))
return FALSE;
/* Check that the (1st) parameter length is within bounds */
if (opt_param != PARAMETER_END_OF_OPTIONAL_PARAMETERS &&
opt_ptr+2U <= len &&
tvb_get_guint8(tvb, opt_ptr+1U) < len)
return FALSE;
/* If we're at the end of the parameters, are we also at the end of the
* message?
*/
if (opt_param == PARAMETER_END_OF_OPTIONAL_PARAMETERS && opt_ptr+1U != len)
return FALSE;
}
return TRUE;
}
@ -1252,12 +1331,6 @@ dissect_sccp_slr_param(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guin
col_append_fstr(pinfo->cinfo, COL_INFO, "SLR=%d ", slr);
}
#define is_connectionless(m) \
( m == SCCP_MSG_TYPE_UDT || m == SCCP_MSG_TYPE_UDTS \
|| m == SCCP_MSG_TYPE_XUDT|| m == SCCP_MSG_TYPE_XUDTS \
|| m == SCCP_MSG_TYPE_LUDT|| m == SCCP_MSG_TYPE_LUDTS)
static proto_tree *
dissect_sccp_gt_address_information(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, guint length,