aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Tüxen <tuexen@fh-muenster.de>2012-02-26 13:50:52 +0000
committerMichael Tüxen <tuexen@fh-muenster.de>2012-02-26 13:50:52 +0000
commite929fdfdeef753a8844bf3075f824926fd1244db (patch)
tree70e56fe559911b22da16a0717584f3b7ade97fbb
parent83bf13e1e609e3fa3a935876e707aecfda4635de (diff)
From Robin Seggelmann: Add support for RFC 6520.
From me: Some cleanup Initial work was done by Denis Jaeger and Lukas Scharlau, but the code got rewritten by Robin. svn path=/trunk/; revision=41189
-rw-r--r--epan/dissectors/packet-dtls.c161
-rw-r--r--epan/dissectors/packet-ssl-utils.c24
-rw-r--r--epan/dissectors/packet-ssl-utils.h4
-rw-r--r--epan/dissectors/packet-ssl.c144
4 files changed, 324 insertions, 9 deletions
diff --git a/epan/dissectors/packet-dtls.c b/epan/dissectors/packet-dtls.c
index 3ae3fd33c2..dd3a75e6f4 100644
--- a/epan/dissectors/packet-dtls.c
+++ b/epan/dissectors/packet-dtls.c
@@ -133,6 +133,13 @@ static gint hf_dtls_handshake_dnames = -1;
static gint hf_dtls_handshake_dname_len = -1;
static gint hf_dtls_handshake_dname = -1;
+static gint hf_dtls_heartbeat_extension_mode = -1;
+static gint hf_dtls_heartbeat_message = -1;
+static gint hf_dtls_heartbeat_message_type = -1;
+static gint hf_dtls_heartbeat_message_payload_length = -1;
+static gint hf_dtls_heartbeat_message_payload = -1;
+static gint hf_dtls_heartbeat_message_padding = -1;
+
static gint hf_dtls_fragments = -1;
static gint hf_dtls_fragment = -1;
static gint hf_dtls_fragment_overlap = -1;
@@ -149,6 +156,7 @@ static gint ett_dtls = -1;
static gint ett_dtls_record = -1;
static gint ett_dtls_alert = -1;
static gint ett_dtls_handshake = -1;
+static gint ett_dtls_heartbeat = -1;
static gint ett_dtls_cipher_suites = -1;
static gint ett_dtls_comp_methods = -1;
static gint ett_dtls_extension = -1;
@@ -312,6 +320,11 @@ static void dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo,
guint *conv_version,
SslDecryptSession *conv_data, guint8 content_type);
+/* heartbeat message dissector */
+static void dissect_dtls_heartbeat(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, guint32 offset,
+ guint *conv_version, guint32 record_length);
+
static void dissect_dtls_hnd_cli_hello(tvbuff_t *tvb,
proto_tree *tree,
@@ -923,6 +936,27 @@ dissect_dtls_record(tvbuff_t *tvb, packet_info *pinfo,
proto_tree_add_item(dtls_record_tree, hf_dtls_record_appdata, tvb,
offset, record_length, ENC_NA);
break;
+ case SSL_ID_HEARTBEAT:
+ {
+ tvbuff_t* decrypted;
+
+ if (ssl && decrypt_dtls_record(tvb, pinfo, offset,
+ record_length, content_type, ssl, FALSE))
+ ssl_add_record_info(proto_dtls, pinfo, dtls_decrypted_data.data,
+ dtls_decrypted_data_avail, offset);
+
+ /* try to retrive and use decrypted alert record, if any. */
+ decrypted = ssl_get_record_info(tvb, proto_dtls, pinfo, offset);
+ if (decrypted) {
+ dissect_dtls_heartbeat(decrypted, pinfo, dtls_record_tree, 0,
+ conv_version, record_length);
+ add_new_data_source(pinfo, decrypted, "Decrypted SSL record");
+ } else {
+ dissect_dtls_heartbeat(tvb, pinfo, dtls_record_tree, offset,
+ conv_version, record_length);
+ }
+ break;
+ }
default:
/* shouldn't get here since we check above for valid types */
@@ -1377,6 +1411,86 @@ dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo,
}
}
+/* dissects the heartbeat message, filling in the tree */
+static void
+dissect_dtls_heartbeat(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, guint32 offset,
+ guint* conv_version, guint32 record_length)
+{
+ /* struct {
+ * HeartbeatMessageType type;
+ * uint16 payload_length;
+ * opaque payload;
+ * opaque padding;
+ * } HeartbeatMessage;
+ */
+
+ proto_tree *ti;
+ proto_tree *dtls_heartbeat_tree;
+ const gchar *type;
+ guint8 byte;
+ guint16 payload_length;
+ guint16 padding_length;
+
+ dtls_heartbeat_tree = NULL;
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, hf_dtls_heartbeat_message, tvb,
+ offset, record_length - 32, ENC_NA);
+ dtls_heartbeat_tree = proto_item_add_subtree(ti, ett_dtls_heartbeat);
+ }
+
+ /*
+ * set the record layer label
+ */
+
+ /* first lookup the names for the message type and the payload length */
+ byte = tvb_get_guint8(tvb, offset);
+ type = match_strval(byte, tls_heartbeat_type);
+
+ payload_length = tvb_get_ntohs(tvb, offset + 1);
+ padding_length = record_length - 3 - payload_length;
+
+ /* now set the text in the record layer line */
+ if (type && (payload_length <= record_length - 16 - 3)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "Heartbeat %s", type);
+ } else {
+ col_append_str(pinfo->cinfo, COL_INFO, "Encrypted Heartbeat");
+ }
+
+ if (tree) {
+ if (type && (payload_length <= record_length - 16 - 3)) {
+ proto_item_set_text(tree, "%s Record Layer: Heartbeat "
+ "%s",
+ val_to_str_const(*conv_version, ssl_version_short_names, "SSL"),
+ type);
+ proto_tree_add_item(dtls_heartbeat_tree, hf_dtls_heartbeat_message_type,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ proto_tree_add_uint(dtls_heartbeat_tree, hf_dtls_heartbeat_message_payload_length,
+ tvb, offset, 2, payload_length);
+ offset += 2;
+ proto_tree_add_bytes_format(dtls_heartbeat_tree, hf_dtls_heartbeat_message_payload,
+ tvb, offset, payload_length,
+ NULL, "Payload (%u byte%s)",
+ payload_length,
+ plurality(payload_length, "", "s"));
+ offset += payload_length;
+ proto_tree_add_bytes_format(dtls_heartbeat_tree, hf_dtls_heartbeat_message_padding,
+ tvb, offset, padding_length,
+ NULL, "Padding and HMAC (%u byte%s)",
+ padding_length,
+ plurality(padding_length, "", "s"));
+ } else {
+ proto_item_set_text(tree,
+ "%s Record Layer: Encrypted Heartbeat",
+ val_to_str_const(*conv_version, ssl_version_short_names, "SSL"));
+ proto_item_set_text(dtls_heartbeat_tree,
+ "Encrypted Heartbeat Message");
+ }
+ }
+}
+
static gint
dissect_dtls_hnd_hello_common(tvbuff_t *tvb, proto_tree *tree,
guint32 offset, SslDecryptSession* ssl, gint from_server)
@@ -1497,11 +1611,20 @@ dissect_dtls_hnd_hello_ext(tvbuff_t *tvb,
tvb, offset, 2, ext_len);
offset += 2;
- proto_tree_add_bytes_format(ext_tree, hf_dtls_handshake_extension_data,
- tvb, offset, ext_len, NULL,
- "Data (%u byte%s)", ext_len,
- plurality(ext_len, "", "s"));
- offset += ext_len;
+ switch (ext_type) {
+ case SSL_HND_HELLO_EXT_HEARTBEAT:
+ proto_tree_add_item(ext_tree, hf_dtls_heartbeat_extension_mode,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ break;
+ default:
+ proto_tree_add_bytes_format(ext_tree, hf_dtls_handshake_extension_data,
+ tvb, offset, ext_len, NULL,
+ "Data (%u byte%s)",
+ ext_len, plurality(ext_len, "", "s"));
+ offset += ext_len;
+ break;
+ }
+
left -= 2 + 2 + ext_len;
}
@@ -2369,6 +2492,33 @@ proto_register_dtls(void)
FT_BYTES, BASE_NONE, NULL, 0x0,
"Distinguished name of a CA that server trusts", HFILL }
},
+ { &hf_dtls_heartbeat_extension_mode,
+ { "Mode", "dtls.handshake.extension.heartbeat.mode",
+ FT_UINT8, BASE_DEC, VALS(tls_heartbeat_mode), 0x0,
+ "Heartbeat extension mode", HFILL }
+ },
+ { &hf_dtls_heartbeat_message,
+ { "Heartbeat Message", "dtls.heartbeat_message",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_dtls_heartbeat_message_type,
+ { "Type", "dtls.heartbeat_message.type",
+ FT_UINT8, BASE_DEC, VALS(tls_heartbeat_type), 0x0,
+ "Heartbeat message type", HFILL }
+ },
+ { &hf_dtls_heartbeat_message_payload_length,
+ { "Payload Length", "dtls.heartbeat_message.payload_length",
+ FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }
+ },
+ { &hf_dtls_heartbeat_message_payload,
+ { "Payload Length", "dtls.heartbeat_message.payload",
+ FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL }
+ },
+ { &hf_dtls_heartbeat_message_padding,
+ { "Payload Length", "dtls.heartbeat_message.padding",
+ FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL }
+ },
{ &hf_dtls_fragments,
{ "Message fragments", "dtls.fragments",
FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL }
@@ -2419,6 +2569,7 @@ proto_register_dtls(void)
&ett_dtls_record,
&ett_dtls_alert,
&ett_dtls_handshake,
+ &ett_dtls_heartbeat,
&ett_dtls_cipher_suites,
&ett_dtls_comp_methods,
&ett_dtls_extension,
diff --git a/epan/dissectors/packet-ssl-utils.c b/epan/dissectors/packet-ssl-utils.c
index 10c6fc1074..a56bd435a0 100644
--- a/epan/dissectors/packet-ssl-utils.c
+++ b/epan/dissectors/packet-ssl-utils.c
@@ -405,6 +405,7 @@ const value_string ssl_31_content_type[] = {
{ 21, "Alert" },
{ 22, "Handshake" },
{ 23, "Application Data" },
+ { 24, "Heartbeat" },
{ 0x00, NULL }
};
@@ -484,6 +485,18 @@ const value_string ssl_31_handshake_type[] = {
{ 0x00, NULL }
};
+const value_string tls_heartbeat_type[] = {
+ { 1, "Request" },
+ { 2, "Response" },
+ { 0x00, NULL }
+};
+
+const value_string tls_heartbeat_mode[] = {
+ { 1, "Peer allowed to send requests" },
+ { 2, "Peer not allowed to send requests" },
+ { 0x00, NULL }
+};
+
const value_string ssl_31_compression_method[] = {
{ 0, "null" },
{ 1, "DEFLATE" },
@@ -899,6 +912,7 @@ const value_string tls_hello_extension_types[] = {
{ 12, "srp" }, /* RFC 5054 */
{ 13, "signature_algorithms" }, /* RFC 5246 */
{ 14, "use_srtp" },
+ { SSL_HND_HELLO_EXT_HEARTBEAT, "Heartbeat" }, /* RFC 6520 */
{ 35, "SessionTicket TLS" }, /* RFC 4507 */
{ 65281, "renegotiation_info" },
{ 0, NULL }
@@ -3270,16 +3284,18 @@ ssl_association_add(GTree* associations, dissector_handle_t handle, guint port,
assoc->handle = find_dissector("data");
}
- if(!assoc->handle) {
+ if (!assoc->handle) {
fprintf(stderr, "association_add() could not find handle for protocol:%s\n",protocol);
} else {
- if(port) {
- if(tcp)
+ if (port) {
+ if (tcp)
dissector_add_uint("tcp.port", port, handle);
else
dissector_add_uint("udp.port", port, handle);
}
g_tree_insert(associations, assoc, assoc);
+
+ dissector_add("sctp.port", port, handle);
}
}
@@ -3586,7 +3602,7 @@ ssl_restore_session(SslDecryptSession* ssl, GHashTable *session_hash)
int
ssl_is_valid_content_type(guint8 type)
{
- if (type >= 0x14 && type <= 0x17)
+ if (type >= 0x14 && type <= 0x18)
{
return 1;
}
diff --git a/epan/dissectors/packet-ssl-utils.h b/epan/dissectors/packet-ssl-utils.h
index 6e11f59553..478681cc7b 100644
--- a/epan/dissectors/packet-ssl-utils.h
+++ b/epan/dissectors/packet-ssl-utils.h
@@ -71,6 +71,7 @@
#define SSL_ID_ALERT 0x15
#define SSL_ID_HANDSHAKE 0x16
#define SSL_ID_APP_DATA 0x17
+#define SSL_ID_HEARTBEAT 0x18
#define SSL_HND_HELLO_REQUEST 0
#define SSL_HND_CLIENT_HELLO 1
@@ -146,6 +147,7 @@
#define SSL_HND_HELLO_EXT_ELLIPTIC_CURVES 0x000a
#define SSL_HND_HELLO_EXT_EC_POINT_FORMATS 0x000b
+#define SSL_HND_HELLO_EXT_HEARTBEAT 0x000f
#define SSL_HND_CERT_STATUS_TYPE_OCSP 1
@@ -162,6 +164,8 @@ extern const value_string ssl_31_change_cipher_spec[];
extern const value_string ssl_31_alert_level[];
extern const value_string ssl_31_alert_description[];
extern const value_string ssl_31_handshake_type[];
+extern const value_string tls_heartbeat_type[];
+extern const value_string tls_heartbeat_mode[];
extern const value_string ssl_31_compression_method[];
extern const value_string ssl_31_key_exchange_algorithm[];
extern const value_string ssl_31_signature_algorithm[];
diff --git a/epan/dissectors/packet-ssl.c b/epan/dissectors/packet-ssl.c
index 87c04065ca..0abf6d48bf 100644
--- a/epan/dissectors/packet-ssl.c
+++ b/epan/dissectors/packet-ssl.c
@@ -254,11 +254,19 @@ static int hf_ssl_segment_too_long_fragment = -1;
static int hf_ssl_segment_error = -1;
static int hf_ssl_segment_count = -1;
+static gint hf_ssl_heartbeat_extension_mode = -1;
+static gint hf_ssl_heartbeat_message = -1;
+static gint hf_ssl_heartbeat_message_type = -1;
+static gint hf_ssl_heartbeat_message_payload_length = -1;
+static gint hf_ssl_heartbeat_message_payload = -1;
+static gint hf_ssl_heartbeat_message_padding = -1;
+
/* Initialize the subtree pointers */
static gint ett_ssl = -1;
static gint ett_ssl_record = -1;
static gint ett_ssl_alert = -1;
static gint ett_ssl_handshake = -1;
+static gint ett_ssl_heartbeat = -1;
static gint ett_ssl_cipher_suites = -1;
static gint ett_ssl_comp_methods = -1;
static gint ett_ssl_extension = -1;
@@ -455,6 +463,11 @@ static void dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
guint *conv_version, guint conv_cipher,
SslDecryptSession *conv_data, const guint8 content_type);
+/* heartbeat message dissector */
+static void dissect_ssl3_heartbeat(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, guint32 offset,
+ guint *conv_version, guint32 record_length);
+
/* hello extension dissector */
static gint dissect_ssl3_hnd_hello_ext_elliptic_curves(tvbuff_t *tvb,
proto_tree *tree, guint32 offset);
@@ -1659,6 +1672,25 @@ dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
dissect_ssl_payload(tvb, pinfo, offset, tree, association);
break;
+ case SSL_ID_HEARTBEAT:
+ {
+ tvbuff_t* decrypted;
+
+ if (ssl && decrypt_ssl3_record(tvb, pinfo, offset,
+ record_length, content_type, ssl, FALSE))
+ ssl_add_record_info(proto_ssl, pinfo, ssl_decrypted_data.data,
+ ssl_decrypted_data_avail, offset);
+
+ /* try to retrieve and use decrypted handshake record, if any. */
+ decrypted = ssl_get_record_info(tvb, proto_ssl, pinfo, offset);
+ if (decrypted) {
+ add_new_data_source(pinfo, decrypted, "Decrypted SSL record");
+ dissect_ssl3_heartbeat(decrypted, pinfo, ssl_record_tree, 0, conv_version, record_length);
+ } else {
+ dissect_ssl3_heartbeat(tvb, pinfo, ssl_record_tree, offset, conv_version, record_length);
+ }
+ break;
+ }
default:
/* shouldn't get here since we check above for valid types */
@@ -2107,6 +2139,86 @@ dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
}
}
+/* dissects the heartbeat message, filling in the tree */
+static void
+dissect_ssl3_heartbeat(tvbuff_t *tvb, packet_info *pinfo,
+ proto_tree *tree, guint32 offset,
+ guint* conv_version, guint32 record_length)
+{
+ /* struct {
+ * HeartbeatMessageType type;
+ * uint16 payload_length;
+ * opaque payload;
+ * opaque padding;
+ * } HeartbeatMessage;
+ */
+
+ proto_tree *ti;
+ proto_tree *tls_heartbeat_tree;
+ const gchar *type;
+ guint8 byte;
+ guint16 payload_length;
+ guint16 padding_length;
+
+ tls_heartbeat_tree = NULL;
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, hf_ssl_heartbeat_message, tvb,
+ offset, record_length - 32, ENC_NA);
+ tls_heartbeat_tree = proto_item_add_subtree(ti, ett_ssl_heartbeat);
+ }
+
+ /*
+ * set the record layer label
+ */
+
+ /* first lookup the names for the message type and the payload length */
+ byte = tvb_get_guint8(tvb, offset);
+ type = match_strval(byte, tls_heartbeat_type);
+
+ payload_length = tvb_get_ntohs(tvb, offset + 1);
+ padding_length = record_length - 3 - payload_length;
+
+ /* now set the text in the record layer line */
+ if (type && (payload_length <= record_length - 16 - 3)) {
+ col_append_fstr(pinfo->cinfo, COL_INFO, "Heartbeat %s", type);
+ } else {
+ col_append_str(pinfo->cinfo, COL_INFO, "Encrypted Heartbeat");
+ }
+
+ if (tree) {
+ if (type && (payload_length <= record_length - 16 - 3)) {
+ proto_item_set_text(tree, "%s Record Layer: Heartbeat "
+ "%s",
+ val_to_str_const(*conv_version, ssl_version_short_names, "SSL"),
+ type);
+ proto_tree_add_item(tls_heartbeat_tree, hf_ssl_heartbeat_message_type,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ proto_tree_add_uint(tls_heartbeat_tree, hf_ssl_heartbeat_message_payload_length,
+ tvb, offset, 2, payload_length);
+ offset += 2;
+ proto_tree_add_bytes_format(tls_heartbeat_tree, hf_ssl_heartbeat_message_payload,
+ tvb, offset, payload_length,
+ NULL, "Payload (%u byte%s)",
+ payload_length,
+ plurality(payload_length, "", "s"));
+ offset += payload_length;
+ proto_tree_add_bytes_format(tls_heartbeat_tree, hf_ssl_heartbeat_message_padding,
+ tvb, offset, padding_length,
+ NULL, "Padding and HMAC (%u byte%s)",
+ padding_length,
+ plurality(padding_length, "", "s"));
+ } else {
+ proto_item_set_text(tree,
+ "%s Record Layer: Encrypted Heartbeat",
+ val_to_str_const(*conv_version, ssl_version_short_names, "SSL"));
+ proto_item_set_text(tls_heartbeat_tree,
+ "Encrypted Heartbeat Message");
+ }
+ }
+}
+
static gint
dissect_ssl3_hnd_hello_common(tvbuff_t *tvb, proto_tree *tree,
guint32 offset, SslDecryptSession* ssl, gint from_server)
@@ -2233,6 +2345,10 @@ dissect_ssl3_hnd_hello_ext(tvbuff_t *tvb,
case SSL_HND_HELLO_EXT_EC_POINT_FORMATS:
offset = dissect_ssl3_hnd_hello_ext_ec_point_formats(tvb, ext_tree, offset);
break;
+ case SSL_HND_HELLO_EXT_HEARTBEAT:
+ proto_tree_add_item(ext_tree, hf_ssl_heartbeat_extension_mode,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ break;
default:
proto_tree_add_bytes_format(ext_tree, hf_ssl_handshake_extension_data,
tvb, offset, ext_len, NULL,
@@ -5064,6 +5180,33 @@ proto_register_ssl(void)
FT_NONE, BASE_NONE, NULL, 0x0,
"Distinguished name of a CA that server trusts", HFILL }
},
+ { &hf_ssl_heartbeat_extension_mode,
+ { "Mode", "ssl.handshake.extension.heartbeat.mode",
+ FT_UINT8, BASE_DEC, VALS(tls_heartbeat_mode), 0x0,
+ "Heartbeat extension mode", HFILL }
+ },
+ { &hf_ssl_heartbeat_message,
+ { "Heartbeat Message", "ssl.heartbeat_message",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL }
+ },
+ { &hf_ssl_heartbeat_message_type,
+ { "Type", "ssl.heartbeat_message.type",
+ FT_UINT8, BASE_DEC, VALS(tls_heartbeat_type), 0x0,
+ "Heartbeat message type", HFILL }
+ },
+ { &hf_ssl_heartbeat_message_payload_length,
+ { "Payload Length", "ssl.heartbeat_message.payload_length",
+ FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }
+ },
+ { &hf_ssl_heartbeat_message_payload,
+ { "Payload Length", "ssl.heartbeat_message.payload",
+ FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL }
+ },
+ { &hf_ssl_heartbeat_message_padding,
+ { "Payload Length", "ssl.heartbeat_message.padding",
+ FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL }
+ },
{ &hf_ssl2_handshake_challenge,
{ "Challenge", "ssl.handshake.challenge",
FT_NONE, BASE_NONE, NULL, 0x0,
@@ -5246,6 +5389,7 @@ proto_register_ssl(void)
&ett_ssl_record,
&ett_ssl_alert,
&ett_ssl_handshake,
+ &ett_ssl_heartbeat,
&ett_ssl_cipher_suites,
&ett_ssl_comp_methods,
&ett_ssl_extension,