Report bogus handshake length values with expert info. This includes

trying to handle reassembly of packets with *differing* handshake length
values a bit better.

Make coding style a little more consistent.

svn path=/trunk/; revision=48916
This commit is contained in:
Guy Harris 2013-04-18 19:19:38 +00:00
parent c35b6c5f6d
commit d89d6c8314
1 changed files with 85 additions and 42 deletions

View File

@ -53,6 +53,7 @@
#include <epan/packet.h> #include <epan/packet.h>
#include <epan/conversation.h> #include <epan/conversation.h>
#include <epan/expert.h>
#include <epan/prefs.h> #include <epan/prefs.h>
#include <epan/asn1.h> #include <epan/asn1.h>
#include <epan/dissectors/packet-x509af.h> #include <epan/dissectors/packet-x509af.h>
@ -532,6 +533,7 @@ dissect_dtls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
static gboolean static gboolean
dissect_dtls_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) dissect_dtls_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{ {
/* Stronger confirmation of DTLS packet is provided by verifying the /* Stronger confirmation of DTLS packet is provided by verifying the
* captured payload length against the remainder of the UDP packet size. */ * captured payload length against the remainder of the UDP packet size. */
@ -1130,7 +1132,7 @@ dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo,
* } Handshake; * } Handshake;
*/ */
proto_tree *ti; proto_tree *ti, *length_item = NULL, *fragment_length_item = NULL;
proto_tree *ssl_hand_tree; proto_tree *ssl_hand_tree;
const gchar *msg_type_str; const gchar *msg_type_str;
guint8 msg_type; guint8 msg_type;
@ -1139,6 +1141,8 @@ dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo,
guint32 fragment_offset; guint32 fragment_offset;
guint32 fragment_length; guint32 fragment_length;
gboolean first_iteration; gboolean first_iteration;
gboolean frag_hand;
guint32 reassembled_length;
ti = NULL; ti = NULL;
ssl_hand_tree = NULL; ssl_hand_tree = NULL;
@ -1202,7 +1206,7 @@ dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo,
length = tvb_get_ntoh24(tvb, offset); length = tvb_get_ntoh24(tvb, offset);
if (ssl_hand_tree) if (ssl_hand_tree)
proto_tree_add_uint(ssl_hand_tree, hf_dtls_handshake_length, length_item = proto_tree_add_uint(ssl_hand_tree, hf_dtls_handshake_length,
tvb, offset, 3, length); tvb, offset, 3, length);
offset += 3; offset += 3;
@ -1220,18 +1224,35 @@ dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo,
fragment_length = tvb_get_ntoh24(tvb, offset); fragment_length = tvb_get_ntoh24(tvb, offset);
if (ssl_hand_tree) if (ssl_hand_tree)
proto_tree_add_uint(ssl_hand_tree, hf_dtls_handshake_fragment_length, fragment_length_item = proto_tree_add_uint(ssl_hand_tree,
tvb, offset, 3, fragment_length); hf_dtls_handshake_fragment_length,
tvb, offset, 3,
fragment_length);
offset += 3; offset += 3;
proto_item_set_len(ti, fragment_length + 12); proto_item_set_len(ti, fragment_length + 12);
fragmented = fragment_length != length; fragmented = FALSE;
if (fragment_length + fragment_offset > length)
{
if (fragment_offset == 0)
{
expert_add_info_format(pinfo, fragment_length_item, PI_PROTOCOL,
PI_ERROR,
"Fragment length is larger than message length");
}
else
{
fragmented = TRUE;
expert_add_info_format(pinfo, fragment_length_item, PI_PROTOCOL,
PI_ERROR,
"Fragment runs past the end of the message");
}
}
else if (fragment_length < length)
{
fragmented = TRUE;
/* Handle fragments of known message type */ /* Handle fragments of known message type */
if (fragmented)
{
gboolean frag_hand;
switch (msg_type) { switch (msg_type) {
case SSL_HND_HELLO_REQUEST: case SSL_HND_HELLO_REQUEST:
case SSL_HND_CLIENT_HELLO: case SSL_HND_CLIENT_HELLO:
@ -1253,7 +1274,8 @@ dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo,
break; break;
} }
if (frag_hand) { if (frag_hand)
{
/* Fragmented handshake message */ /* Fragmented handshake message */
pinfo->fragmented = TRUE; pinfo->fragmented = TRUE;
@ -1263,10 +1285,30 @@ dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo,
frag_msg = fragment_add(&dtls_reassembly_table, frag_msg = fragment_add(&dtls_reassembly_table,
tvb, offset, pinfo, message_seq, NULL, tvb, offset, pinfo, message_seq, NULL,
fragment_offset, fragment_length, TRUE); fragment_offset, fragment_length, TRUE);
/*
* Do we already have a length for this reassembly?
*/
reassembled_length = fragment_get_tot_len(&dtls_reassembly_table,
pinfo, message_seq, NULL);
if (reassembled_length == 0)
{
/* No - set it to the length specified by this packet. */
fragment_set_tot_len(&dtls_reassembly_table, fragment_set_tot_len(&dtls_reassembly_table,
pinfo, message_seq, NULL, length); pinfo, message_seq, NULL, length);
}
else
{
/* Yes - if this packet specifies a different length,
report an error. */
if (reassembled_length != length)
{
expert_add_info_format(pinfo, length_item, PI_PROTOCOL,
PI_ERROR,
"Message length differs from value in earlier fragment");
}
}
if (frag_msg && (fragment_length + fragment_offset) == length) if (frag_msg && (fragment_length + fragment_offset) == reassembled_length)
{ {
/* Reassembled */ /* Reassembled */
new_tvb = process_reassembled_data(tvb, offset, pinfo, new_tvb = process_reassembled_data(tvb, offset, pinfo,
@ -1286,7 +1328,8 @@ dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo,
} }
} }
if (tree) { if (tree)
{
/* set the label text on the record layer expanding node */ /* set the label text on the record layer expanding node */
if (first_iteration) if (first_iteration)
{ {