forked from osmocom/wireshark
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>
This commit is contained in:
parent
53a373693c
commit
5b30d5c767
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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];
|
||||
dissector_handle_t handle;
|
||||
|
||||
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))) {
|
||||
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];
|
||||
|
||||
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;
|
||||
/* 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;
|
||||
|
@ -8754,6 +8746,22 @@ tls13_dissect_hnd_key_update(ssl_common_dissect_t *hf, tvbuff_t *tvb,
|
|||
proto_tree_add_item(tree, hf->hf.hs_key_update_request_update, tvb, offset, 1, ENC_NA);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -1986,6 +1986,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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue