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,8 +1206,8 @@ 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;
message_seq = tvb_get_ntohs(tvb,offset); message_seq = tvb_get_ntohs(tvb,offset);
@ -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)
/* Handle fragments of known message type */
if (fragmented)
{ {
gboolean frag_hand; 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 */
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,40 +1274,62 @@ dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo,
break; break;
} }
if (frag_hand) { if (frag_hand)
/* Fragmented handshake message */ {
pinfo->fragmented = TRUE; /* Fragmented handshake message */
pinfo->fragmented = TRUE;
/* Don't pass the reassembly code data that doesn't exist */ /* Don't pass the reassembly code data that doesn't exist */
tvb_ensure_bytes_exist(tvb, offset, fragment_length); tvb_ensure_bytes_exist(tvb, offset, fragment_length);
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);
fragment_set_tot_len(&dtls_reassembly_table, /*
pinfo, message_seq, NULL, length); * 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,
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,
"Reassembled DTLS", "Reassembled DTLS",
frag_msg, frag_msg,
&dtls_frag_items, &dtls_frag_items,
NULL, tree); NULL, tree);
frag_str = " (Reassembled)"; frag_str = " (Reassembled)";
} }
else else
{ {
frag_str = " (Fragment)"; frag_str = " (Fragment)";
} }
if (check_col(pinfo->cinfo, COL_INFO)) if (check_col(pinfo->cinfo, COL_INFO))
col_append_str(pinfo->cinfo, COL_INFO, frag_str); col_append_str(pinfo->cinfo, COL_INFO, frag_str);
} }
} }
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)
{ {
@ -1337,7 +1380,7 @@ dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo,
else else
{ {
sub_tvb = tvb_new_subset(tvb, offset, fragment_length, sub_tvb = tvb_new_subset(tvb, offset, fragment_length,
fragment_length); fragment_length);
} }
/* now dissect the handshake message, if necessary */ /* now dissect the handshake message, if necessary */
@ -1963,9 +2006,9 @@ dissect_dtls_hnd_new_ses_ticket(tvbuff_t *tvb,
ti = proto_tree_add_text(tree, tvb, offset, 6+nst_len, "TLS Session Ticket"); ti = proto_tree_add_text(tree, tvb, offset, 6+nst_len, "TLS Session Ticket");
subtree = proto_item_add_subtree(ti, ett_dtls_new_ses_ticket); subtree = proto_item_add_subtree(ti, ett_dtls_new_ses_ticket);
proto_tree_add_item(subtree, hf_dtls_handshake_session_ticket_lifetime_hint, proto_tree_add_item(subtree, hf_dtls_handshake_session_ticket_lifetime_hint,
tvb, offset, 4, ENC_BIG_ENDIAN); tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4; offset += 4;
proto_tree_add_uint(subtree, hf_dtls_handshake_session_ticket_len, proto_tree_add_uint(subtree, hf_dtls_handshake_session_ticket_len,
tvb, offset, 2, nst_len); tvb, offset, 2, nst_len);