aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-ssl-utils.c
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2015-02-07 13:16:59 +0100
committerMichael Mann <mmann78@netscape.net>2015-02-09 12:58:18 +0000
commit3222cd1df6b0c8a43d959a7913fc3bf4b53e9422 (patch)
tree76e3e33d2adceef45bb85d45500f7fadaac9b50e /epan/dissectors/packet-ssl-utils.c
parent702618fa615482383733587e58c5b0619ae50e35 (diff)
ssl-utils: use ALPN hint for improved spdy/http2 recognition
This patch improves detection of a SPDY/3.1 in SSL capture. While at it, add other protocols from the RFC/drafts. spdy was tested against a private capture from spdy/3.1 communication between Chromium 40 and ssl.gstatic.com. http2 was tested against http2-16-ssl.pcapng from http://wiki.wireshark.org/SampleCaptures#SSL_with_decryption_keys Change-Id: I111efae34d614b7d8e37eaaa686b391d332753dd Reviewed-on: https://code.wireshark.org/review/7000 Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com> Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Michael Mann <mmann78@netscape.net>
Diffstat (limited to 'epan/dissectors/packet-ssl-utils.c')
-rw-r--r--epan/dissectors/packet-ssl-utils.c58
1 files changed, 56 insertions, 2 deletions
diff --git a/epan/dissectors/packet-ssl-utils.c b/epan/dissectors/packet-ssl-utils.c
index 02d0075b8f..09859e9d65 100644
--- a/epan/dissectors/packet-ssl-utils.c
+++ b/epan/dissectors/packet-ssl-utils.c
@@ -1167,6 +1167,26 @@ const value_string tls_cert_status_type[] = {
{ 0, NULL }
};
+/* string_string is inappropriate as it compares strings while
+ * "byte strings MUST NOT be truncated" (RFC 7301) */
+typedef struct ssl_alpn_protocol {
+ const guint8 *proto_name;
+ size_t proto_name_len;
+ const char *dissector_name;
+} ssl_alpn_protocol_t;
+/* http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids */
+static const ssl_alpn_protocol_t ssl_alpn_protocols[] = {
+ { "http/1.1", sizeof("http/1.1"), "http" },
+ /* SPDY moves so fast, just 1, 2 and 3 are registered with IANA but there
+ * already exists 3.1 as of this writing... match the prefix. */
+ { "spdy/", sizeof("spdy/") - 1, "spdy" },
+ { "stun.turn", sizeof("stun.turn"), "turnchannel" },
+ { "stun.nat-discovery", sizeof("stun.nat-discovery"), "stun" },
+ /* draft-ietf-httpbis-http2-16 */
+ { "h2-", sizeof("h2-") - 1, "http2" }, /* draft versions */
+ { "h2", sizeof("h2"), "http2" }, /* final version */
+};
+
/* we keep this internal to packet-ssl-utils, as there should be
no need to access it any other way.
@@ -4978,7 +4998,8 @@ ssl_dissect_hnd_hello_ext_sig_hash_algs(ssl_common_dissect_t *hf, tvbuff_t *tvb,
static gint
ssl_dissect_hnd_hello_ext_alpn(ssl_common_dissect_t *hf, tvbuff_t *tvb,
- proto_tree *tree, guint32 offset, guint32 ext_len)
+ proto_tree *tree, guint32 offset, guint32 ext_len,
+ gboolean is_client, SslSession *session)
{
guint16 alpn_length;
guint8 name_length;
@@ -4998,6 +5019,39 @@ ssl_dissect_hnd_hello_ext_alpn(ssl_common_dissect_t *hf, tvbuff_t *tvb,
tvb, offset, alpn_length, ENC_NA);
alpn_tree = proto_item_add_subtree(ti, hf->ett.hs_ext_alpn);
+ /* If ALPN is given in ServerHello, then ProtocolNameList MUST contain
+ * exactly one "ProtocolName". */
+ if (!is_client) {
+ guint8 *proto_name;
+ size_t i;
+
+ name_length = tvb_get_guint8(tvb, offset);
+ /* '\0'-terminated string for prefix/full string comparison purposes. */
+ proto_name = tvb_get_string_enc(wmem_packet_scope(), tvb, offset + 1,
+ name_length, ENC_ASCII);
+ for (i = 0; i < G_N_ELEMENTS(ssl_alpn_protocols); i++) {
+ const ssl_alpn_protocol_t *alpn_proto = &ssl_alpn_protocols[i];
+
+ if (name_length >= alpn_proto->proto_name_len &&
+ (memcmp(proto_name, alpn_proto->proto_name,
+ alpn_proto->proto_name_len) == 0)) {
+
+ dissector_handle_t handle;
+ /* ProtocolName match, so set the App data dissector handle.
+ * This may override protocols given via the UAT dialog, but
+ * since the ALPN hint is precise, do it anyway. */
+ handle = find_dissector(alpn_proto->dissector_name);
+ ssl_debug_printf("%s: changing handle %p to %p (%s)", G_STRFUNC,
+ (void *)session->app_handle,
+ (void *)handle, alpn_proto->dissector_name);
+ /* if dissector is disabled, do not overwrite previous one */
+ if (handle)
+ session->app_handle = handle;
+ break;
+ }
+ }
+ }
+
while (alpn_length > 0) {
name_length = tvb_get_guint8(tvb, offset);
proto_tree_add_item(alpn_tree, hf->hf.hs_ext_alpn_str_len,
@@ -5998,7 +6052,7 @@ ssl_dissect_hnd_hello_ext(ssl_common_dissect_t *hf, tvbuff_t *tvb, proto_tree *t
offset = ssl_dissect_hnd_hello_ext_sig_hash_algs(hf, tvb, ext_tree, offset, ext_len);
break;
case SSL_HND_HELLO_EXT_ALPN:
- offset = ssl_dissect_hnd_hello_ext_alpn(hf, tvb, ext_tree, offset, ext_len);
+ offset = ssl_dissect_hnd_hello_ext_alpn(hf, tvb, ext_tree, offset, ext_len, is_client, session);
break;
case SSL_HND_HELLO_EXT_NPN:
offset = ssl_dissect_hnd_hello_ext_npn(hf, tvb, ext_tree, offset, ext_len);