summaryrefslogtreecommitdiff
path: root/epan/dissectors/packet-ssl.c
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2016-01-11 21:47:03 +0100
committerAnders Broman <a.broman58@gmail.com>2016-01-14 05:39:18 +0000
commit50dc0e8edb990dbb2340cc339ffbc6adc372bb21 (patch)
tree51f2ef7bd2e4fcbc8ebd30e781794b6175c521a9 /epan/dissectors/packet-ssl.c
parent6fba2d2d7a502c4dff96e09f2d0b13179d1c19ef (diff)
downloadwireshark-50dc0e8edb990dbb2340cc339ffbc6adc372bb21.tar.gz
ssl: improve interaction with heuristics subdissectors
Do not call heuristics dissectors when the SSL application data protocol is known (via STARTTLS or via an earlier packet in session). When the protocol is *not* known, first try heuristics on the initial payload. If a match is found, it can then override the protocol that would otherwise be used due to a port number match. The HTTP2 dissector is adjusted to take advantage of that such that HTTP2 on non-standard ports still get detected as HTTP2. Also save dissector registration to avoid the http2 dissector from showing up as "(null)". Now HTTP2 is really shown as "http2" and not "http" in the "Application Data Protocol"! The CredSSP dissector is untested and not modified as I don't know if the whole stream will be SSL. Tested with fix-ssl.pcap and a http2 capture (from bug 11331) wrapped in SSL (without ALPN). Change-Id: I134e2d4ac22287bc0a5aeadb1e38cb4059fa108b Reviewed-on: https://code.wireshark.org/review/13179 Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan/dissectors/packet-ssl.c')
-rw-r--r--epan/dissectors/packet-ssl.c101
1 files changed, 66 insertions, 35 deletions
diff --git a/epan/dissectors/packet-ssl.c b/epan/dissectors/packet-ssl.c
index 98e1e38b2a..a0480ef79d 100644
--- a/epan/dissectors/packet-ssl.c
+++ b/epan/dissectors/packet-ssl.c
@@ -914,14 +914,15 @@ decrypt_ssl3_record(tvbuff_t *tvb, packet_info *pinfo, guint32 offset,
static void
process_ssl_payload(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, SslSession *session);
+ proto_tree *tree, SslSession *session,
+ dissector_handle_t app_handle_port);
static void
desegment_ssl(tvbuff_t *tvb, packet_info *pinfo, int offset,
guint32 seq, guint32 nxtseq,
SslSession *session,
proto_tree *root_tree, proto_tree *tree,
- SslFlow *flow)
+ SslFlow *flow, dissector_handle_t app_handle_port)
{
fragment_head *ipfd_head;
gboolean must_desegment;
@@ -1029,7 +1030,7 @@ again:
* contain a continuation of a higher-level PDU.
* Call the normal subdissector.
*/
- process_ssl_payload(tvb, offset, pinfo, tree, session);
+ process_ssl_payload(tvb, offset, pinfo, tree, session, app_handle_port);
called_dissector = TRUE;
/* Did the subdissector ask us to desegment some more data
@@ -1083,7 +1084,7 @@ again:
add_new_data_source(pinfo, next_tvb, "Reassembled SSL");
/* call subdissector */
- process_ssl_payload(next_tvb, 0, pinfo, tree, session);
+ process_ssl_payload(next_tvb, 0, pinfo, tree, session, app_handle_port);
called_dissector = TRUE;
/*
@@ -1339,7 +1340,8 @@ export_pdu_packet(tvbuff_t *tvb, packet_info *pinfo, guint tag, const gchar *nam
static void
process_ssl_payload(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, SslSession *session)
+ proto_tree *tree, SslSession *session,
+ dissector_handle_t app_handle_port)
{
tvbuff_t *next_tvb;
heur_dtbl_entry_t *hdtbl_entry;
@@ -1347,36 +1349,54 @@ process_ssl_payload(tvbuff_t *tvb, int offset, packet_info *pinfo,
next_tvb = tvb_new_subset_remaining(tvb, offset);
- if (session->app_handle) {
- ssl_debug_printf("%s: found handle %p (%s)\n", G_STRFUNC,
- (void *)session->app_handle,
- dissector_handle_get_dissector_name(session->app_handle));
-
+ /* If the appdata proto is not yet known (no STARTTLS), try heuristics
+ * first, then ports-based dissectors. Port 443 is too overloaded... */
+ if (!session->app_handle) {
+ /* The heuristics dissector should set the app_handle if it wants to be
+ * called in the future. */
if (dissector_try_heuristic(ssl_heur_subdissector_list, next_tvb,
- pinfo, proto_tree_get_root(tree), &hdtbl_entry, NULL)) {
+ pinfo, proto_tree_get_root(tree), &hdtbl_entry,
+ &session->app_handle)) {
+ ssl_debug_printf("%s: found heuristics dissector %s, app_handle is %p (%s)\n",
+ G_STRFUNC, hdtbl_entry->short_name,
+ (void *)session->app_handle,
+ dissector_handle_get_dissector_name(session->app_handle));
if (have_tap_listener(exported_pdu_tap)) {
export_pdu_packet(next_tvb, pinfo, EXP_PDU_TAG_HEUR_PROTO_NAME, hdtbl_entry->short_name);
}
+ return;
+ }
+ if (app_handle_port) {
+ /* Heuristics failed, just try the port-based dissector. */
+ session->app_handle = app_handle_port;
} else {
- if (have_tap_listener(exported_pdu_tap)) {
- export_pdu_packet(next_tvb, pinfo, EXP_PDU_TAG_PROTO_NAME,
- dissector_handle_get_dissector_name(session->app_handle));
- }
- saved_match_port = pinfo->match_uint;
- if (ssl_packet_from_server(session, ssl_associations, pinfo)) {
- pinfo->match_uint = pinfo->srcport;
- } else {
- pinfo->match_uint = pinfo->destport;
- }
- call_dissector(session->app_handle, next_tvb, pinfo, proto_tree_get_root(tree));
- pinfo->match_uint = saved_match_port;
+ /* No heuristics, no port-based proto, unknown protocol. */
+ return;
}
}
+
+ ssl_debug_printf("%s: found handle %p (%s)\n", G_STRFUNC,
+ (void *)session->app_handle,
+ dissector_handle_get_dissector_name(session->app_handle));
+
+ if (have_tap_listener(exported_pdu_tap)) {
+ export_pdu_packet(next_tvb, pinfo, EXP_PDU_TAG_PROTO_NAME,
+ dissector_handle_get_dissector_name(session->app_handle));
+ }
+ saved_match_port = pinfo->match_uint;
+ if (ssl_packet_from_server(session, ssl_associations, pinfo)) {
+ pinfo->match_uint = pinfo->srcport;
+ } else {
+ pinfo->match_uint = pinfo->destport;
+ }
+ call_dissector(session->app_handle, next_tvb, pinfo, proto_tree_get_root(tree));
+ pinfo->match_uint = saved_match_port;
}
static void
dissect_ssl_payload(tvbuff_t *tvb, packet_info *pinfo, int offset,
- proto_tree *tree, SslSession *session)
+ proto_tree *tree, SslSession *session,
+ dissector_handle_t app_handle_port)
{
gboolean save_fragmented;
guint16 save_can_desegment;
@@ -1407,7 +1427,7 @@ dissect_ssl_payload(tvbuff_t *tvb, packet_info *pinfo, int offset,
pinfo->can_desegment = 2;
desegment_ssl(next_tvb, pinfo, 0, appl_data->seq, appl_data->nxtseq,
session, proto_tree_get_root(tree), tree,
- appl_data->flow);
+ appl_data->flow, app_handle_port);
} else if (session->app_handle) {
/* No - just call the subdissector.
Mark this as fragmented, so if somebody throws an exception,
@@ -1416,7 +1436,7 @@ dissect_ssl_payload(tvbuff_t *tvb, packet_info *pinfo, int offset,
save_fragmented = pinfo->fragmented;
pinfo->fragmented = TRUE;
- process_ssl_payload(next_tvb, 0, pinfo, tree, session);
+ process_ssl_payload(next_tvb, 0, pinfo, tree, session, app_handle_port);
pinfo->fragmented = save_fragmented;
}
@@ -1683,6 +1703,9 @@ dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
break;
}
case SSL_ID_APP_DATA:
+ {
+ dissector_handle_t app_handle;
+
if (ssl){
decrypt_ssl3_record(tvb, pinfo, offset,
record_length, content_type, ssl, TRUE);
@@ -1697,29 +1720,37 @@ dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
/* app_handle discovery is done here instead of dissect_ssl_payload()
* because the protocol name needs to be displayed below. */
- if (!session->app_handle) {
+ app_handle = session->app_handle;
+ if (!app_handle) {
/* Unknown protocol handle, ssl_starttls_ack was not called before.
- * Try to find an appropriate dissection handle and cache it. */
- dissector_handle_t handle;
- handle = dissector_get_uint_handle(ssl_associations, pinfo->srcport);
- handle = handle ? handle : dissector_get_uint_handle(ssl_associations, pinfo->destport);
- if (handle) session->app_handle = handle;
+ * Try to find a port-based protocol and use it if there is no
+ * heuristics dissector (see process_ssl_payload). */
+ app_handle = dissector_get_uint_handle(ssl_associations, pinfo->srcport);
+ if (!app_handle) app_handle = dissector_get_uint_handle(ssl_associations, pinfo->destport);
}
proto_item_set_text(ssl_record_tree,
"%s Record Layer: %s Protocol: %s",
val_to_str_const(session->version, ssl_version_short_names, "SSL"),
val_to_str_const(content_type, ssl_31_content_type, "unknown"),
- session->app_handle
- ? dissector_handle_get_dissector_name(session->app_handle)
+ app_handle ? dissector_handle_get_dissector_name(app_handle)
: "Application Data");
proto_tree_add_item(ssl_record_tree, hf_ssl_record_appdata, tvb,
offset, record_length, ENC_NA);
- dissect_ssl_payload(tvb, pinfo, offset, tree, session);
+ dissect_ssl_payload(tvb, pinfo, offset, tree, session, app_handle);
+
+ /* Set app proto again in case the heuristics found a different proto. */
+ if (session->app_handle != app_handle)
+ proto_item_set_text(ssl_record_tree,
+ "%s Record Layer: %s Protocol: %s",
+ val_to_str_const(session->version, ssl_version_short_names, "SSL"),
+ val_to_str_const(content_type, ssl_31_content_type, "unknown"),
+ dissector_handle_get_dissector_name(session->app_handle));
break;
+ }
case SSL_ID_HEARTBEAT:
{
tvbuff_t *decrypted;