diff options
author | Guy Harris <guy@alum.mit.edu> | 2018-05-26 18:42:41 -0700 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2018-05-27 01:43:27 +0000 |
commit | 5b30d5c7675fd03a420257c334808549eddc6e7e (patch) | |
tree | e4622039f3a5da1e3690cd1416199e1b5a9e99c2 /epan/dissectors | |
parent | 53a373693ccc55b6475264bd8d1fc611930d1c0f (diff) |
Have a dissector table for SSL/TLS/DTLS ALPN protocol IDs.
Have dissectors register with their protocol ID string in that table,
rather than having a table in epan/dissectors/packet-ssl-utils.c that
has to be updated for new protocols.
Have a table of protocol ID string prefixes, to handle the case of
protocols such as SPDY and HTTP2 drafts, where multiple protocol IDs are
used for different versions.
Change-Id: I363d04895a88e779fbbca7dc8e1f31aa1970a31a
Reviewed-on: https://code.wireshark.org/review/27836
Reviewed-by: Guy Harris <guy@alum.mit.edu>
Diffstat (limited to 'epan/dissectors')
-rw-r--r-- | epan/dissectors/packet-dtls.c | 4 | ||||
-rw-r--r-- | epan/dissectors/packet-http.c | 6 | ||||
-rw-r--r-- | epan/dissectors/packet-http2.c | 6 | ||||
-rw-r--r-- | epan/dissectors/packet-ssl-utils.c | 116 | ||||
-rw-r--r-- | epan/dissectors/packet-ssl-utils.h | 8 | ||||
-rw-r--r-- | epan/dissectors/packet-ssl.c | 4 | ||||
-rw-r--r-- | epan/dissectors/packet-stun.c | 7 | ||||
-rw-r--r-- | epan/dissectors/packet-turnchannel.c | 7 |
8 files changed, 104 insertions, 54 deletions
diff --git a/epan/dissectors/packet-dtls.c b/epan/dissectors/packet-dtls.c index 8735f1abe1..b7bfdbe2a1 100644 --- a/epan/dissectors/packet-dtls.c +++ b/epan/dissectors/packet-dtls.c @@ -1955,6 +1955,10 @@ proto_register_dtls(void) dtls_associations = register_dissector_table("dtls.port", "DTLS Port", proto_dtls, FT_UINT16, BASE_DEC); + ssl_common_register_dtls_alpn_dissector_table("dtls.handshake.extensions_alpn_str", + "DTLS Application-Layer Protocol Negotiation (ALPN) Protocol IDs", + proto_dtls); + /* Required function calls to register the header fields and * subtrees used */ proto_register_field_array(proto_dtls, hf, array_length(hf)); diff --git a/epan/dissectors/packet-http.c b/epan/dissectors/packet-http.c index 85bba25eff..afe8c1fd8f 100644 --- a/epan/dissectors/packet-http.c +++ b/epan/dissectors/packet-http.c @@ -4098,6 +4098,12 @@ proto_reg_handoff_http(void) ssdp_handle = create_dissector_handle(dissect_ssdp, proto_ssdp); dissector_add_uint_with_preference("udp.port", UDP_PORT_SSDP, ssdp_handle); + /* + * SSL/TLS Application-Layer Protocol Negotiation (ALPN) protocol + * ID. + */ + dissector_add_string("ssl.handshake.extensions_alpn_str", "http/1.1", http_ssl_handle); + ntlmssp_handle = find_dissector_add_dependency("ntlmssp", proto_http); gssapi_handle = find_dissector_add_dependency("gssapi", proto_http); sstp_handle = find_dissector_add_dependency("sstp", proto_http); diff --git a/epan/dissectors/packet-http2.c b/epan/dissectors/packet-http2.c index d0ffdc39b4..fe3e7c3880 100644 --- a/epan/dissectors/packet-http2.c +++ b/epan/dissectors/packet-http2.c @@ -3326,6 +3326,12 @@ proto_reg_handoff_http2(void) dissector_add_for_decode_as_with_preference("tcp.port", http2_handle); + /* + * SSL/TLS Application-Layer Protocol Negotiation (ALPN) protocol + * ID. + */ + dissector_add_string("ssl.handshake.extensions_alpn_str", "h2", http2_handle); + heur_dissector_add("ssl", dissect_http2_heur_ssl, "HTTP2 over SSL", "http2_ssl", proto_http2, HEURISTIC_ENABLE); heur_dissector_add("http", dissect_http2_heur, "HTTP2 over TCP", "http2_tcp", proto_http2, HEURISTIC_ENABLE); diff --git a/epan/dissectors/packet-ssl-utils.c b/epan/dissectors/packet-ssl-utils.c index a693a709a2..273a8a1d8b 100644 --- a/epan/dissectors/packet-ssl-utils.c +++ b/epan/dissectors/packet-ssl-utils.c @@ -1402,39 +1402,26 @@ static const bytes_string ct_logids[] = { }; /* - * http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids + * Application-Layer Protocol Negotiation (ALPN) dissector tables. */ -/* string_string is inappropriate as it compares strings while - * "byte strings MUST NOT be truncated" (RFC 7301) */ -typedef struct ssl_alpn_protocol { - const char *proto_name; - gboolean match_exact; - const char *dissector_name; -} ssl_alpn_protocol_t; +static dissector_table_t ssl_alpn_dissector_table; +static dissector_table_t dtls_alpn_dissector_table; /* - * For SSL/TLS; the dissectors should handle running atop a byte-stream - * protocol such as TCP. + * Special cases for prefix matching of the ALPN, if the ALPN includes + * a version number for a draft or protocol revision. */ -static const ssl_alpn_protocol_t ssl_alpn_protocols[] = { - { "http/1.1", TRUE, "http" }, +typedef struct ssl_alpn_prefix_match_protocol { + const char *proto_prefix; + const char *dissector_name; +} ssl_alpn_prefix_match_protocol_t; + +static const ssl_alpn_prefix_match_protocol_t ssl_alpn_prefix_match_protocols[] = { /* 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/", FALSE, "spdy" }, - { "stun.turn", TRUE, "turnchannel-tcp" }, /* RFC 7443 */ - { "stun.nat-discovery", TRUE, "stun-tcp" }, /* RFC 7443 */ + { "spdy/", "spdy" }, /* draft-ietf-httpbis-http2-16 */ - { "h2-", FALSE, "http2" }, /* draft versions */ - { "h2", TRUE, "http2" }, /* final version */ -}; - -/* - * For DTLS; the dissectors should handle running atop a datagram - * protocol such as UDP. - */ -static const ssl_alpn_protocol_t dtls_alpn_protocols[] = { - { "stun.turn", TRUE, "turnchannel" }, /* RFC 7443 */ - { "stun.nat-discovery", TRUE, "stun-udp" }, /* RFC 7443 */ + { "h2-", "http2" }, /* draft versions */ }; const value_string quic_transport_parameter_id[] = { @@ -5893,9 +5880,6 @@ ssl_dissect_hnd_hello_ext_alpn(ssl_common_dissect_t *hf, tvbuff_t *tvb, proto_item *ti; guint32 next_offset, alpn_length, name_length; guint8 *proto_name = NULL; - guint32 proto_name_length = 0; - const ssl_alpn_protocol_t *alpn_protocols; - size_t n_alpn_protocols; /* ProtocolName protocol_name_list<2..2^16-1> */ if (!ssl_add_vector(hf, tvb, pinfo, tree, offset, offset_end, &alpn_length, @@ -5923,9 +5907,10 @@ ssl_dissect_hnd_hello_ext_alpn(ssl_common_dissect_t *hf, tvbuff_t *tvb, tvb, offset, name_length, ENC_ASCII|ENC_NA); /* Remember first ALPN ProtocolName entry for server. */ if (hnd_type == SSL_HND_SERVER_HELLO || hnd_type == SSL_HND_ENCRYPTED_EXTENSIONS) { - proto_name_length = name_length; + /* '\0'-terminated string for dissector table match and prefix + * comparison purposes. */ proto_name = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, - proto_name_length, ENC_ASCII); + name_length, ENC_ASCII); } offset += name_length; } @@ -5933,31 +5918,38 @@ ssl_dissect_hnd_hello_ext_alpn(ssl_common_dissect_t *hf, tvbuff_t *tvb, /* If ALPN is given in ServerHello, then ProtocolNameList MUST contain * exactly one "ProtocolName". */ if (proto_name) { - alpn_protocols = is_dtls ? dtls_alpn_protocols : ssl_alpn_protocols; - n_alpn_protocols = is_dtls ? G_N_ELEMENTS(dtls_alpn_protocols) : G_N_ELEMENTS(ssl_alpn_protocols); - /* '\0'-terminated string for prefix/full string comparison purposes. */ - for (size_t i = 0; i < n_alpn_protocols; i++) { - const ssl_alpn_protocol_t *alpn_proto = &alpn_protocols[i]; - - if ((alpn_proto->match_exact && - proto_name_length == strlen(alpn_proto->proto_name) && - !strcmp(proto_name, alpn_proto->proto_name)) || - (!alpn_proto->match_exact && g_str_has_prefix(proto_name, alpn_proto->proto_name))) { - - 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 = ssl_find_appdata_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; + dissector_handle_t handle; + + if (is_dtls) { + handle = dissector_get_string_handle(dtls_alpn_dissector_table, + proto_name); + } else { + handle = dissector_get_string_handle(ssl_alpn_dissector_table, + proto_name); + if (handle == NULL) { + /* Try prefix matching */ + for (size_t i = 0; i < G_N_ELEMENTS(ssl_alpn_prefix_match_protocols); i++) { + const ssl_alpn_prefix_match_protocol_t *alpn_proto = &ssl_alpn_prefix_match_protocols[i]; + + /* string_string is inappropriate as it compares strings + * while "byte strings MUST NOT be truncated" (RFC 7301) */ + if (g_str_has_prefix(proto_name, alpn_proto->proto_prefix)) { + handle = find_dissector(alpn_proto->dissector_name); + break; + } + } } } + if (handle != NULL) { + /* 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. */ + ssl_debug_printf("%s: changing handle %p to %p (%s)", G_STRFUNC, + (void *)session->app_handle, + (void *)handle, + dissector_handle_get_dissector_name(handle)); + session->app_handle = handle; + } } return offset; @@ -8755,6 +8747,22 @@ tls13_dissect_hnd_key_update(ssl_common_dissect_t *hf, tvbuff_t *tvb, } void +ssl_common_register_ssl_alpn_dissector_table(const char *name, + const char *ui_name, const int proto) +{ + ssl_alpn_dissector_table = register_dissector_table(name, ui_name, + proto, FT_STRING, FALSE); +} + +void +ssl_common_register_dtls_alpn_dissector_table(const char *name, + const char *ui_name, const int proto) +{ + dtls_alpn_dissector_table = register_dissector_table(name, ui_name, + proto, FT_STRING, FALSE); +} + +void ssl_common_register_options(module_t *module, ssl_common_options_t *options) { prefs_register_string_preference(module, "psk", "Pre-Shared-Key", diff --git a/epan/dissectors/packet-ssl-utils.h b/epan/dissectors/packet-ssl-utils.h index 24daf2749b..2595849cf9 100644 --- a/epan/dissectors/packet-ssl-utils.h +++ b/epan/dissectors/packet-ssl-utils.h @@ -1987,6 +1987,14 @@ ssl_common_dissect_t name = { \ /* }}} */ extern void +ssl_common_register_ssl_alpn_dissector_table(const char *name, + const char *ui_name, const int proto); + +extern void +ssl_common_register_dtls_alpn_dissector_table(const char *name, + const char *ui_name, const int proto); + +extern void ssl_common_register_options(module_t *module, ssl_common_options_t *options); #ifdef SSL_DECRYPT_DEBUG diff --git a/epan/dissectors/packet-ssl.c b/epan/dissectors/packet-ssl.c index 1714063938..ec98259155 100644 --- a/epan/dissectors/packet-ssl.c +++ b/epan/dissectors/packet-ssl.c @@ -4647,6 +4647,10 @@ proto_register_ssl(void) /* heuristic dissectors for any premable e.g. CredSSP before RDP */ ssl_heur_subdissector_list = register_heur_dissector_list("ssl", proto_ssl); + ssl_common_register_ssl_alpn_dissector_table("ssl.handshake.extensions_alpn_str", + "SSL/TLS Application-Layer Protocol Negotiation (ALPN) Protocol IDs", + proto_ssl); + ssl_handle = register_dissector("ssl", dissect_ssl, proto_ssl); register_init_routine(ssl_init); diff --git a/epan/dissectors/packet-stun.c b/epan/dissectors/packet-stun.c index 46e5a38234..6a8734cf00 100644 --- a/epan/dissectors/packet-stun.c +++ b/epan/dissectors/packet-stun.c @@ -1731,6 +1731,13 @@ proto_reg_handoff_stun(void) dissector_add_uint_with_preference("tcp.port", TCP_PORT_STUN, stun_tcp_handle); dissector_add_uint_with_preference("udp.port", UDP_PORT_STUN, stun_udp_handle); + /* + * SSL/TLS and DTLS Application-Layer Protocol Negotiation (ALPN) + * protocol ID. + */ + dissector_add_string("ssl.handshake.extensions_alpn_str", "stun.nat-discovery", stun_tcp_handle); + dissector_add_string("dtls.handshake.extensions_alpn_str", "stun.nat-discovery", stun_udp_handle); + heur_dissector_add("udp", dissect_stun_heur, "STUN over UDP", "stun_udp", proto_stun, HEURISTIC_ENABLE); data_handle = find_dissector("data"); diff --git a/epan/dissectors/packet-turnchannel.c b/epan/dissectors/packet-turnchannel.c index 339db978f3..e3c2f364f4 100644 --- a/epan/dissectors/packet-turnchannel.c +++ b/epan/dissectors/packet-turnchannel.c @@ -202,6 +202,13 @@ proto_reg_handoff_turnchannel(void) dissector_add_for_decode_as_with_preference("tcp.port", turnchannel_tcp_handle); dissector_add_for_decode_as_with_preference("udp.port", turnchannel_udp_handle); + /* + * SSL/TLS and DTLS Application-Layer Protocol Negotiation (ALPN) + * protocol ID. + */ + dissector_add_string("ssl.handshake.extensions_alpn_str", "stun.turn", turnchannel_tcp_handle); + dissector_add_string("dtls.handshake.extensions_alpn_str", "stun.turn", turnchannel_udp_handle); + /* TURN negotiation is handled through STUN2 dissector (packet-stun.c), so only it should be able to determine if a packet is a TURN packet */ heur_dissector_add("stun", dissect_turnchannel_heur, "TURN Channel over STUN", "turnchannel_stun", proto_turnchannel, HEURISTIC_ENABLE); |