diff --git a/asn1/h225/packet-h225-template.c b/asn1/h225/packet-h225-template.c index b2b6ec0a0c..4b7cab749f 100644 --- a/asn1/h225/packet-h225-template.c +++ b/asn1/h225/packet-h225-template.c @@ -940,7 +940,7 @@ void proto_reg_handoff_h225(void) { static gboolean h225_prefs_initialized = FALSE; - static dissector_handle_t h225ras_handle; + static dissector_handle_t h225ras_handle, q931_tpkt_handle; static guint saved_h225_tls_port; if (!h225_prefs_initialized) { @@ -953,12 +953,13 @@ proto_reg_handoff_h225(void) h4501_handle = find_dissector("h4501"); data_handle = find_dissector("data"); h225_prefs_initialized = TRUE; + q931_tpkt_handle = find_dissector("q931.tpkt"); } else { - ssl_dissector_delete(saved_h225_tls_port, "q931.tpkt", TRUE); + ssl_dissector_delete(saved_h225_tls_port, q931_tpkt_handle); } saved_h225_tls_port = h225_tls_port; - ssl_dissector_add(saved_h225_tls_port, "q931.tpkt", TRUE); + ssl_dissector_add(saved_h225_tls_port, q931_tpkt_handle); } diff --git a/asn1/ldap/packet-ldap-template.c b/asn1/ldap/packet-ldap-template.c index 0dbe926b4c..736d6be206 100644 --- a/asn1/ldap/packet-ldap-template.c +++ b/asn1/ldap/packet-ldap-template.c @@ -2399,13 +2399,13 @@ prefs_register_ldap(void) if(ssl_port != global_ldaps_tcp_port) { if(ssl_port) - ssl_dissector_delete(ssl_port, "ldap", TRUE); + ssl_dissector_delete(ssl_port, ldap_handle); /* Set our port number for future use */ ssl_port = global_ldaps_tcp_port; if(ssl_port) - ssl_dissector_add(ssl_port, "ldap", TRUE); + ssl_dissector_add(ssl_port, ldap_handle); } } diff --git a/debian/libwireshark0.symbols b/debian/libwireshark0.symbols index bdecd3ff9a..a99d25e0c2 100644 --- a/debian/libwireshark0.symbols +++ b/debian/libwireshark0.symbols @@ -1239,8 +1239,8 @@ libwireshark.so.0 libwireshark0 #MINVER# srt_table_iterate_tables@Base 1.99.8 srtcp_add_address@Base 1.9.1 srtp_add_address@Base 1.9.1 - ssl_dissector_add@Base 1.9.1 - ssl_dissector_delete@Base 1.9.1 + ssl_dissector_add@Base 2.1.0 + ssl_dissector_delete@Base 2.1.0 ssl_session_hash@Base 1.9.1 ssl_crandom_hash@Base 1.99.4 ssl_set_master_secret@Base 1.9.1 diff --git a/epan/dissectors/packet-amqp.c b/epan/dissectors/packet-amqp.c index 9b7eab4262..1d17d7501a 100644 --- a/epan/dissectors/packet-amqp.c +++ b/epan/dissectors/packet-amqp.c @@ -14012,12 +14012,12 @@ proto_reg_handoff_amqp(void) /* Register for TLS/SSL payload dissection */ if (old_amqps_port != 0 && old_amqps_port != amqps_port){ - ssl_dissector_delete(old_amqps_port, "amqp", TRUE); + ssl_dissector_delete(old_amqps_port, amqp_tcp_handle); } if (amqps_port != 0 && old_amqps_port != amqps_port) { old_amqps_port = amqps_port; - ssl_dissector_add(amqps_port, "amqp", TRUE); + ssl_dissector_add(amqps_port, amqp_tcp_handle); } } diff --git a/epan/dissectors/packet-dtls.c b/epan/dissectors/packet-dtls.c index 900aed3b09..3f02c7b7eb 100644 --- a/epan/dissectors/packet-dtls.c +++ b/epan/dissectors/packet-dtls.c @@ -136,8 +136,9 @@ static expert_field ei_dtls_heartbeat_payload_length = EI_INIT; static ssl_master_key_map_t dtls_master_key_map; static GHashTable *dtls_key_hash = NULL; +static wmem_stack_t *key_list_stack = NULL; static reassembly_table dtls_reassembly_table; -static GTree* dtls_associations = NULL; +static dissector_table_t dtls_associations = NULL; static dissector_handle_t dtls_handle = NULL; static StringInfo dtls_compressed_data = {NULL, 0}; static StringInfo dtls_decrypted_data = {NULL, 0}; @@ -201,6 +202,10 @@ dtls_init(void) static void dtls_cleanup(void) { + if (key_list_stack != NULL) { + wmem_destroy_stack(key_list_stack); + key_list_stack = NULL; + } reassembly_table_destroy(&dtls_reassembly_table); ssl_common_cleanup(&dtls_master_key_map, &dtls_keylog_file, &dtls_decrypted_data, &dtls_compressed_data); @@ -210,8 +215,8 @@ dtls_cleanup(void) static void dtls_parse_uat(void) { - wmem_stack_t *tmp_stack; - guint i; + guint i, port; + dissector_handle_t handle; if (dtls_key_hash) { @@ -219,12 +224,14 @@ dtls_parse_uat(void) } /* remove only associations created from key list */ - tmp_stack = wmem_stack_new(NULL); - g_tree_foreach(dtls_associations, ssl_assoc_from_key_list, tmp_stack); - while (wmem_stack_count(tmp_stack) > 0) { - ssl_association_remove(dtls_associations, (SslAssociation *)wmem_stack_pop(tmp_stack)); + if (key_list_stack != NULL) { + while (wmem_stack_count(key_list_stack) > 0) { + port = GPOINTER_TO_UINT(wmem_stack_pop(key_list_stack)); + handle = dissector_get_uint_handle(dtls_associations, port); + if (handle != NULL) + ssl_association_remove("dtls.port", dtls_handle, handle, port, FALSE); + } } - wmem_destroy_stack(tmp_stack); /* parse private keys string, load available keys and put them in key hash*/ dtls_key_hash = g_hash_table_new_full(ssl_private_key_hash, @@ -234,10 +241,15 @@ dtls_parse_uat(void) if (ndtlsdecrypt > 0) { + if (key_list_stack == NULL) + key_list_stack = wmem_stack_new(NULL); + for (i = 0; i < ndtlsdecrypt; i++) { ssldecrypt_assoc_t *d = &(dtlskeylist_uats[i]); - ssl_parse_key_list(d, dtls_key_hash, dtls_associations, dtls_handle, FALSE); + ssl_parse_key_list(d, dtls_key_hash, "dtls.port", dtls_handle, FALSE); + if (key_list_stack) + wmem_stack_push(key_list_stack, GUINT_TO_POINTER(atoi(d->port))); } } @@ -869,10 +881,10 @@ dissect_dtls_record(tvbuff_t *tvb, packet_info *pinfo, if (!session->app_handle) { /* Unknown protocol handle, ssl_starttls_ack was not called before. * Try to find an appropriate dissection handle and cache it. */ - SslAssociation *association; - association = ssl_association_find(dtls_associations, pinfo->srcport, pinfo->ptype == PT_TCP); - association = association ? association : ssl_association_find(dtls_associations, pinfo->destport, pinfo->ptype == PT_TCP); - if (association) session->app_handle = association->handle; + dissector_handle_t handle; + handle = dissector_get_uint_handle(dtls_associations, pinfo->srcport); + handle = handle ? handle : dissector_get_uint_handle(dtls_associations, pinfo->destport); + if (handle) session->app_handle = handle; } proto_item_set_text(dtls_record_tree, @@ -1622,6 +1634,31 @@ UAT_CSTRING_CB_DEF(sslkeylist_uats,port,ssldecrypt_assoc_t) UAT_CSTRING_CB_DEF(sslkeylist_uats,protocol,ssldecrypt_assoc_t) UAT_FILENAME_CB_DEF(sslkeylist_uats,keyfile,ssldecrypt_assoc_t) UAT_CSTRING_CB_DEF(sslkeylist_uats,password,ssldecrypt_assoc_t) + +static gboolean +dtlsdecrypt_uat_fld_protocol_chk_cb(void* r _U_, const char* p, guint len _U_, const void* u1 _U_, const void* u2 _U_, char** err) +{ + if (!p || strlen(p) == 0u) { + *err = g_strdup_printf("No protocol given."); + return FALSE; + } + + if (!find_dissector(p)) { + if (proto_get_id_by_filter_name(p) != -1) { + *err = g_strdup_printf("While '%s' is a valid dissector filter name, that dissector is not configured" + " to support DTLS decryption.\n\n" + "If you need to decrypt '%s' over DTLS, please contact the Wireshark development team.", p, p); + } else { + char* ssl_str = ssl_association_info("dtls.port", "UDP"); + *err = g_strdup_printf("Could not find dissector for: '%s'\nCommonly used DTLS dissectors include:\n%s", p, ssl_str); + g_free(ssl_str); + } + return FALSE; + } + + *err = NULL; + return TRUE; +} #endif void proto_reg_handoff_dtls(void); @@ -1823,6 +1860,8 @@ proto_register_dtls(void) proto_dtls = proto_register_protocol("Datagram Transport Layer Security", "DTLS", "dtls"); + dtls_associations = register_dissector_table("dtls.port", "DTLS UDP Dissector", FT_UINT16, BASE_DEC, DISSECTOR_TABLE_NOT_ALLOW_DUPLICATE); + /* Required function calls to register the header fields and * subtrees used */ proto_register_field_array(proto_dtls, hf, array_length(hf)); @@ -1838,7 +1877,7 @@ proto_register_dtls(void) static uat_field_t dtlskeylist_uats_flds[] = { UAT_FLD_CSTRING_OTHER(sslkeylist_uats, ipaddr, "IP address", ssldecrypt_uat_fld_ip_chk_cb, "IPv4 or IPv6 address"), UAT_FLD_CSTRING_OTHER(sslkeylist_uats, port, "Port", ssldecrypt_uat_fld_port_chk_cb, "Port Number"), - UAT_FLD_CSTRING_OTHER(sslkeylist_uats, protocol, "Protocol", ssldecrypt_uat_fld_protocol_chk_cb, "Protocol"), + UAT_FLD_CSTRING_OTHER(sslkeylist_uats, protocol, "Protocol", dtlsdecrypt_uat_fld_protocol_chk_cb, "Protocol"), UAT_FLD_FILENAME_OTHER(sslkeylist_uats, keyfile, "Key File", ssldecrypt_uat_fld_fileopen_chk_cb, "Path to the keyfile."), UAT_FLD_CSTRING_OTHER(sslkeylist_uats, password," Password (p12 file)", ssldecrypt_uat_fld_password_chk_cb, "Password"), UAT_END_FIELDS @@ -1880,8 +1919,6 @@ proto_register_dtls(void) register_dissector("dtls", dissect_dtls, proto_dtls); dtls_handle = find_dissector("dtls"); - dtls_associations = g_tree_new(ssl_association_cmp); - register_init_routine(dtls_init); register_cleanup_routine(dtls_cleanup); dtls_tap = register_tap("dtls"); diff --git a/epan/dissectors/packet-h225.c b/epan/dissectors/packet-h225.c index 867bf8da33..cf611e473a 100644 --- a/epan/dissectors/packet-h225.c +++ b/epan/dissectors/packet-h225.c @@ -11691,7 +11691,7 @@ void proto_reg_handoff_h225(void) { static gboolean h225_prefs_initialized = FALSE; - static dissector_handle_t h225ras_handle; + static dissector_handle_t h225ras_handle, q931_tpkt_handle; static guint saved_h225_tls_port; if (!h225_prefs_initialized) { @@ -11704,12 +11704,13 @@ proto_reg_handoff_h225(void) h4501_handle = find_dissector("h4501"); data_handle = find_dissector("data"); h225_prefs_initialized = TRUE; + q931_tpkt_handle = find_dissector("q931.tpkt"); } else { - ssl_dissector_delete(saved_h225_tls_port, "q931.tpkt", TRUE); + ssl_dissector_delete(saved_h225_tls_port, q931_tpkt_handle); } saved_h225_tls_port = h225_tls_port; - ssl_dissector_add(saved_h225_tls_port, "q931.tpkt", TRUE); + ssl_dissector_add(saved_h225_tls_port, q931_tpkt_handle); } diff --git a/epan/dissectors/packet-http.c b/epan/dissectors/packet-http.c index 695ba6eabc..6e57020286 100644 --- a/epan/dissectors/packet-http.c +++ b/epan/dissectors/packet-http.c @@ -2994,12 +2994,12 @@ dissect_ssdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) static void range_delete_http_ssl_callback(guint32 port) { - ssl_dissector_delete(port, "http", TRUE); + ssl_dissector_delete(port, http_handle); } static void range_add_http_ssl_callback(guint32 port) { - ssl_dissector_add(port, "http", TRUE); + ssl_dissector_add(port, http_handle); } static void reinit_http(void) { diff --git a/epan/dissectors/packet-imap.c b/epan/dissectors/packet-imap.c index a95da306f4..9673f6b149 100644 --- a/epan/dissectors/packet-imap.c +++ b/epan/dissectors/packet-imap.c @@ -359,7 +359,7 @@ void proto_reg_handoff_imap(void) { dissector_add_uint("tcp.port", TCP_PORT_IMAP, imap_handle); - ssl_dissector_add(TCP_PORT_SSL_IMAP, "imap", TRUE); + ssl_dissector_add(TCP_PORT_SSL_IMAP, imap_handle); ssl_handle = find_dissector("ssl"); } /* diff --git a/epan/dissectors/packet-ldap.c b/epan/dissectors/packet-ldap.c index fe26c37390..025f3f89f7 100644 --- a/epan/dissectors/packet-ldap.c +++ b/epan/dissectors/packet-ldap.c @@ -5964,13 +5964,13 @@ prefs_register_ldap(void) if(ssl_port != global_ldaps_tcp_port) { if(ssl_port) - ssl_dissector_delete(ssl_port, "ldap", TRUE); + ssl_dissector_delete(ssl_port, ldap_handle); /* Set our port number for future use */ ssl_port = global_ldaps_tcp_port; if(ssl_port) - ssl_dissector_add(ssl_port, "ldap", TRUE); + ssl_dissector_add(ssl_port, ldap_handle); } } diff --git a/epan/dissectors/packet-pop.c b/epan/dissectors/packet-pop.c index a90c44eb28..2d7bbbd028 100644 --- a/epan/dissectors/packet-pop.c +++ b/epan/dissectors/packet-pop.c @@ -468,7 +468,7 @@ proto_reg_handoff_pop(void) { pop_handle = find_dissector("pop"); dissector_add_uint("tcp.port", TCP_PORT_POP, pop_handle); - ssl_dissector_add(TCP_PORT_SSL_POP, "pop", TRUE); + ssl_dissector_add(TCP_PORT_SSL_POP, pop_handle); data_handle = find_dissector("data"); /* find the IMF dissector */ diff --git a/epan/dissectors/packet-sip.c b/epan/dissectors/packet-sip.c index 08a70181fc..a41df2b21d 100644 --- a/epan/dissectors/packet-sip.c +++ b/epan/dissectors/packet-sip.c @@ -6453,13 +6453,13 @@ proto_reg_handoff_sip(void) } else { dissector_delete_uint_range("tcp.port", sip_tcp_port_range, sip_tcp_handle); g_free(sip_tcp_port_range); - ssl_dissector_delete(saved_sip_tls_port, "sip.tcp", TRUE); + ssl_dissector_delete(saved_sip_tls_port, sip_tcp_handle); } /* Set our port number for future use */ sip_tcp_port_range = range_copy(global_sip_tcp_port_range); dissector_add_uint_range("tcp.port", sip_tcp_port_range, sip_tcp_handle); saved_sip_tls_port = sip_tls_port; - ssl_dissector_add(saved_sip_tls_port, "sip.tcp", TRUE); + ssl_dissector_add(saved_sip_tls_port, sip_tcp_handle); exported_pdu_tap = find_tap_id(EXPORT_PDU_TAP_NAME_LAYER_7); } diff --git a/epan/dissectors/packet-skinny.c b/epan/dissectors/packet-skinny.c index 9883ee8c27..01f79cdbf8 100644 --- a/epan/dissectors/packet-skinny.c +++ b/epan/dissectors/packet-skinny.c @@ -9732,7 +9732,7 @@ proto_reg_handoff_skinny(void) /* Skinny content type and internet media type used by other dissectors are the same */ media_type_dissector_table = find_dissector_table("media_type"); dissector_add_uint("tcp.port", TCP_PORT_SKINNY, skinny_handle); - ssl_dissector_add(SSL_PORT_SKINNY, "skinny", TRUE); + ssl_dissector_add(SSL_PORT_SKINNY, skinny_handle); } /* diff --git a/epan/dissectors/packet-skinny.c.in b/epan/dissectors/packet-skinny.c.in index 464cd4b076..8d09e9352c 100644 --- a/epan/dissectors/packet-skinny.c.in +++ b/epan/dissectors/packet-skinny.c.in @@ -543,7 +543,7 @@ proto_reg_handoff_skinny(void) /* Skinny content type and internet media type used by other dissectors are the same */ media_type_dissector_table = find_dissector_table("media_type"); dissector_add_uint("tcp.port", TCP_PORT_SKINNY, skinny_handle); - ssl_dissector_add(SSL_PORT_SKINNY, "skinny", TRUE); + ssl_dissector_add(SSL_PORT_SKINNY, skinny_handle); } /* diff --git a/epan/dissectors/packet-smtp.c b/epan/dissectors/packet-smtp.c index d428c40e41..d8621300d5 100644 --- a/epan/dissectors/packet-smtp.c +++ b/epan/dissectors/packet-smtp.c @@ -1298,7 +1298,7 @@ proto_reg_handoff_smtp(void) { smtp_handle = find_dissector("smtp"); dissector_add_uint("tcp.port", TCP_PORT_SMTP, smtp_handle); - ssl_dissector_add(TCP_PORT_SSL_SMTP, "smtp", TRUE); + ssl_dissector_add(TCP_PORT_SSL_SMTP, smtp_handle); dissector_add_uint("tcp.port", TCP_PORT_SUBMISSION, smtp_handle); /* find the IMF dissector */ diff --git a/epan/dissectors/packet-spdy.c b/epan/dissectors/packet-spdy.c index e79b100e40..98d81364a7 100644 --- a/epan/dissectors/packet-spdy.c +++ b/epan/dissectors/packet-spdy.c @@ -1940,7 +1940,7 @@ void proto_reg_handoff_spdy(void) { dissector_add_uint("tcp.port", TCP_PORT_SPDY, spdy_handle); /* Use "0" to avoid overwriting HTTPS port and still offer support over SSL */ - ssl_dissector_add(0, "spdy", TRUE); + ssl_dissector_add(0, spdy_handle); data_handle = find_dissector("data"); media_handle = find_dissector("media"); diff --git a/epan/dissectors/packet-ssl-utils.c b/epan/dissectors/packet-ssl-utils.c index 41a021edb7..9aceb8eb38 100644 --- a/epan/dissectors/packet-ssl-utils.c +++ b/epan/dissectors/packet-ssl-utils.c @@ -4137,82 +4137,37 @@ ssl_private_key_hash (gconstpointer v) /* Handling of association between tls/dtls ports and clear text protocol. {{{ */ void -ssl_association_add(GTree* associations, dissector_handle_t handle, guint port, const gchar *protocol, gboolean tcp, gboolean from_key_list) +ssl_association_add(const char* dissector_table_name, dissector_handle_t main_handle, dissector_handle_t subdissector_handle, guint port, gboolean tcp) { + DISSECTOR_ASSERT(main_handle); + DISSECTOR_ASSERT(subdissector_handle); + ssl_debug_printf("association_add %s port %d handle %p\n", dissector_table_name, port, (void *)subdissector_handle); - SslAssociation* assoc; - assoc = (SslAssociation *)g_malloc(sizeof(SslAssociation)); - - assoc->tcp = tcp; - assoc->ssl_port = port; - assoc->info=g_strdup(protocol); - assoc->handle = find_dissector(protocol); - assoc->from_key_list = from_key_list; - - ssl_debug_printf("association_add %s port %d protocol %s handle %p\n", - (assoc->tcp)?"TCP":"UDP", port, protocol, (void *)(assoc->handle)); - - - if (!assoc->handle) { - ssl_debug_printf("association_add could not find handle for protocol '%s', try to find 'data' dissector\n", protocol); - assoc->handle = find_dissector("data"); - } - - DISSECTOR_ASSERT(assoc->handle != NULL); if (port) { + dissector_add_uint(dissector_table_name, port, subdissector_handle); if (tcp) - dissector_add_uint("tcp.port", port, handle); + dissector_add_uint("tcp.port", port, main_handle); else - dissector_add_uint("udp.port", port, handle); - dissector_add_uint("sctp.port", port, handle); + dissector_add_uint("udp.port", port, main_handle); + dissector_add_uint("sctp.port", port, main_handle); + } else { + dissector_add_for_decode_as(dissector_table_name, subdissector_handle); } - g_tree_insert(associations, assoc, assoc); } void -ssl_association_remove(GTree* associations, SslAssociation *assoc) +ssl_association_remove(const char* dissector_table_name, dissector_handle_t main_handle, dissector_handle_t subdissector_handle, guint port, gboolean tcp) { - ssl_debug_printf("ssl_association_remove removing %s %u - %s handle %p\n", - (assoc->tcp)?"TCP":"UDP", assoc->ssl_port, assoc->info, (void *)(assoc->handle)); - if (assoc->handle) { - dissector_delete_uint((assoc->tcp)?"tcp.port":"udp.port", assoc->ssl_port, assoc->handle); - dissector_delete_uint("sctp.port", assoc->ssl_port, assoc->handle); + ssl_debug_printf("ssl_association_remove removing %s %u - handle %p\n", + tcp?"TCP":"UDP", port, (void *)subdissector_handle); + if (main_handle) { + dissector_delete_uint(tcp?"tcp.port":"udp.port", port, main_handle); + dissector_delete_uint("sctp.port", port, main_handle); } - g_free(assoc->info); - - g_tree_remove(associations, assoc); - g_free(assoc); -} - -gint -ssl_association_cmp(gconstpointer a, gconstpointer b) -{ - const SslAssociation *assoc_a=(const SslAssociation *)a, *assoc_b=(const SslAssociation *)b; - if (assoc_a->tcp != assoc_b->tcp) return (assoc_a->tcp)?1:-1; - return assoc_a->ssl_port - assoc_b->ssl_port; -} - -SslAssociation* -ssl_association_find(GTree * associations, guint port, gboolean tcp) -{ - register SslAssociation* ret; - SslAssociation assoc_tmp; - - assoc_tmp.tcp = tcp; - assoc_tmp.ssl_port = port; - ret = (SslAssociation *)g_tree_lookup(associations, &assoc_tmp); - - ssl_debug_printf("association_find: %s port %d found %p\n", (tcp)?"TCP":"UDP", port, (void *)ret); - return ret; -} - -gint -ssl_assoc_from_key_list(gpointer key _U_, gpointer data, gpointer user_data) -{ - if (((SslAssociation*)data)->from_key_list) - wmem_stack_push((wmem_stack_t*)user_data, data); - return FALSE; + if (port) { + dissector_delete_uint(dissector_table_name, port, subdissector_handle); + } } void @@ -4224,7 +4179,7 @@ ssl_set_server(SslSession *session, address *addr, port_type ptype, guint32 port } int -ssl_packet_from_server(SslSession *session, GTree *associations, packet_info *pinfo) +ssl_packet_from_server(SslSession *session, dissector_table_t table, packet_info *pinfo) { gint ret; if (session->srv_ptype != PT_NONE) { @@ -4232,7 +4187,7 @@ ssl_packet_from_server(SslSession *session, GTree *associations, packet_info *pi (session->srv_port == pinfo->srcport) && addresses_equal(&session->srv_addr, &pinfo->src); } else { - ret = ssl_association_find(associations, pinfo->srcport, pinfo->ptype != PT_UDP) != 0; + ret = (dissector_get_uint_handle(table, pinfo->srcport) != 0); } ssl_debug_printf("packet_from_server: is from server - %s\n", (ret)?"TRUE":"FALSE"); @@ -4382,7 +4337,7 @@ ssl_common_cleanup(ssl_master_key_map_t *mk_map, FILE **ssl_keylog_file, #if defined(HAVE_LIBGNUTLS) && defined(HAVE_LIBGCRYPT) /* Load a single RSA key file item from preferences. {{{ */ void -ssl_parse_key_list(const ssldecrypt_assoc_t *uats, GHashTable *key_hash, GTree* associations, dissector_handle_t handle, gboolean tcp) +ssl_parse_key_list(const ssldecrypt_assoc_t *uats, GHashTable *key_hash, const char* dissector_table_name, dissector_handle_t main_handle, gboolean tcp) { gnutls_x509_privkey_t priv_key; gcry_sexp_t private_key; @@ -4390,7 +4345,7 @@ ssl_parse_key_list(const ssldecrypt_assoc_t *uats, GHashTable *key_hash, GTree* int ret; size_t key_id_len = 20; guchar *key_id = NULL; - + dissector_handle_t handle; /* try to load keys file first */ fp = ws_fopen(uats->keyfile, "rb"); if (!fp) { @@ -4439,7 +4394,9 @@ ssl_parse_key_list(const ssldecrypt_assoc_t *uats, GHashTable *key_hash, GTree* int port = atoi(uats->port); /* Also maps "start_tls" -> 0 (wildcard) */ ssl_debug_printf("ssl_init port '%d' filename '%s' password(only for p12 file) '%s'\n", port, uats->keyfile, uats->password); - ssl_association_add(associations, handle, port, uats->protocol, tcp, TRUE); + + handle = find_dissector(uats->protocol); + ssl_association_add(dissector_table_name, main_handle, handle, port, tcp); } end: @@ -4449,7 +4406,7 @@ end: /* }}} */ #else void -ssl_parse_key_list(const ssldecrypt_assoc_t *uats _U_, GHashTable *key_hash _U_, GTree* associations _U_, dissector_handle_t handle _U_, gboolean tcp _U_) +ssl_parse_key_list(const ssldecrypt_assoc_t *uats _U_, GHashTable *key_hash _U_, const char* dissector_table_name _U_, dissector_handle_t main_handle _U_, gboolean tcp _U_) { report_failure("Can't load private key files, support is not compiled in."); } @@ -4893,31 +4850,6 @@ ssldecrypt_uat_fld_port_chk_cb(void* r _U_, const char* p, guint len _U_, const return TRUE; } -gboolean -ssldecrypt_uat_fld_protocol_chk_cb(void* r _U_, const char* p, guint len _U_, const void* u1 _U_, const void* u2 _U_, char** err) -{ - if (!p || strlen(p) == 0u) { - *err = g_strdup_printf("No protocol given."); - return FALSE; - } - - if (!find_dissector(p)) { - if (proto_get_id_by_filter_name(p) != -1) { - *err = g_strdup_printf("While '%s' is a valid dissector filter name, that dissector is not configured" - " to support SSL decryption.\n\n" - "If you need to decrypt '%s' over SSL, please contact the Wireshark development team.", p, p); - } else { - char* ssl_str = ssl_association_info(); - *err = g_strdup_printf("Could not find dissector for: '%s'\nCommonly used SSL dissectors include:\n%s", p, ssl_str); - g_free(ssl_str); - } - return FALSE; - } - - *err = NULL; - return TRUE; -} - gboolean ssldecrypt_uat_fld_fileopen_chk_cb(void* r _U_, const char* p, guint len _U_, const void* u1 _U_, const void* u2 _U_, char** err) { @@ -4973,6 +4905,40 @@ ssldecrypt_uat_fld_password_chk_cb(void *r _U_, const char *p _U_, guint len _U_ } /* UAT preferences callbacks. }}} */ +/** maximum size of ssl_association_info() string */ +#define SSL_ASSOC_MAX_LEN 8192 + +typedef struct ssl_association_info_callback_data +{ + gchar *str; + const char *table_protocol; +} ssl_association_info_callback_data_t; + +/** + * callback function used by ssl_association_info() to traverse the SSL associations. + */ +static void +ssl_association_info_(const gchar *table _U_, gpointer handle, gpointer user_data) +{ + ssl_association_info_callback_data_t* data = (ssl_association_info_callback_data_t*)user_data; + const int l = (const int)strlen(data->str); + g_snprintf(data->str+l, SSL_ASSOC_MAX_LEN-l, "'%s' %s\n", dissector_handle_get_short_name((dissector_handle_t)handle), data->table_protocol); +} + +/** + * @return an information string on the SSL protocol associations. The string has ephemeral lifetime/scope. + */ +gchar* +ssl_association_info(const char* dissector_table_name, const char* table_protocol) +{ + ssl_association_info_callback_data_t data; + + data.str = (gchar *)g_malloc0(SSL_ASSOC_MAX_LEN); + data.table_protocol = table_protocol; + dissector_table_foreach_handle(dissector_table_name, ssl_association_info_, &data); + return data.str; +} + /** Begin of code related to dissection of wire data. */ diff --git a/epan/dissectors/packet-ssl-utils.h b/epan/dissectors/packet-ssl-utils.h index f7a2496759..dcf1f8b515 100644 --- a/epan/dissectors/packet-ssl-utils.h +++ b/epan/dissectors/packet-ssl-utils.h @@ -410,14 +410,6 @@ typedef struct _SslDecryptSession { } SslDecryptSession; -typedef struct _SslAssociation { - gboolean tcp; - guint ssl_port; - dissector_handle_t handle; - gchar* info; - gboolean from_key_list; -} SslAssociation; - /* User Access Table */ typedef struct _ssldecrypt_assoc_t { char* ipaddr; @@ -447,9 +439,9 @@ gint ssl_get_keyex_alg(gint cipher); gboolean ssldecrypt_uat_fld_ip_chk_cb(void*, const char*, unsigned, const void*, const void*, char** err); gboolean ssldecrypt_uat_fld_port_chk_cb(void*, const char*, unsigned, const void*, const void*, char** err); -gboolean ssldecrypt_uat_fld_protocol_chk_cb(void*, const char*, unsigned, const void*, const void*, char** err); gboolean ssldecrypt_uat_fld_fileopen_chk_cb(void*, const char*, unsigned, const void*, const void*, char** err); gboolean ssldecrypt_uat_fld_password_chk_cb(void*, const char*, unsigned, const void*, const void*, char** err); +gchar* ssl_association_info(const char* dissector_table_name, const char* table_protocol); /** Retrieve a SslSession, creating it if it did not already exist. * @param conversation The SSL conversation. @@ -541,22 +533,13 @@ ssl_private_key_free(gpointer key); /* handling of association between tls/dtls ports and clear text protocol */ extern void -ssl_association_add(GTree* associations, dissector_handle_t handle, guint port, const gchar *protocol, gboolean tcp, gboolean from_key_list); +ssl_association_add(const char* dissector_table_name, dissector_handle_t main_handle, dissector_handle_t subdissector_handle, guint port, gboolean tcp); extern void -ssl_association_remove(GTree* associations, SslAssociation *assoc); +ssl_association_remove(const char* dissector_table_name, dissector_handle_t main_handle, dissector_handle_t subdissector_handle, guint port, gboolean tcp); extern gint -ssl_association_cmp(gconstpointer a, gconstpointer b); - -extern SslAssociation* -ssl_association_find(GTree * associations, guint port, gboolean tcp); - -extern gint -ssl_assoc_from_key_list(gpointer key _U_, gpointer data, gpointer user_data); - -extern gint -ssl_packet_from_server(SslSession *session, GTree *associations, packet_info *pinfo); +ssl_packet_from_server(SslSession *session, dissector_table_t table, packet_info *pinfo); /* add to packet data a copy of the specified real data */ extern void @@ -587,7 +570,7 @@ ssl_load_keyfile(const gchar *ssl_keylog_filename, FILE **keylog_file, /* parse ssl related preferences (private keys and ports association strings) */ extern void -ssl_parse_key_list(const ssldecrypt_assoc_t * uats, GHashTable *key_hash, GTree* associations, dissector_handle_t handle, gboolean tcp); +ssl_parse_key_list(const ssldecrypt_assoc_t * uats, GHashTable *key_hash, const char* dissector_table_name, dissector_handle_t main_handle, gboolean tcp); /* store master secret into session data cache */ extern void diff --git a/epan/dissectors/packet-ssl.c b/epan/dissectors/packet-ssl.c index ae9daf8956..23d7a6d7c3 100644 --- a/epan/dissectors/packet-ssl.c +++ b/epan/dissectors/packet-ssl.c @@ -308,7 +308,8 @@ GHashTable *ssl_session_hash; GHashTable *ssl_crandom_hash; static GHashTable *ssl_key_hash = NULL; -static GTree *ssl_associations = NULL; +static wmem_stack_t *key_list_stack = NULL; +static dissector_table_t ssl_associations = NULL; static dissector_handle_t ssl_handle = NULL; static StringInfo ssl_compressed_data = {NULL, 0}; static StringInfo ssl_decrypted_data = {NULL, 0}; @@ -363,6 +364,10 @@ ssl_init(void) static void ssl_cleanup(void) { + if (key_list_stack != NULL) { + wmem_destroy_stack(key_list_stack); + key_list_stack = NULL; + } reassembly_table_destroy(&ssl_reassembly_table); ssl_common_cleanup(&ssl_master_key_map, &ssl_keylog_file, &ssl_decrypted_data, &ssl_compressed_data); @@ -377,8 +382,8 @@ ssl_cleanup(void) static void ssl_parse_uat(void) { - wmem_stack_t *tmp_stack; - guint i; + guint i, port; + dissector_handle_t handle; ssl_set_debug(ssl_debug_file_name); @@ -388,22 +393,27 @@ ssl_parse_uat(void) } /* remove only associations created from key list */ - tmp_stack = wmem_stack_new(NULL); - g_tree_foreach(ssl_associations, ssl_assoc_from_key_list, tmp_stack); - while (wmem_stack_count(tmp_stack) > 0) { - ssl_association_remove(ssl_associations, (SslAssociation *)wmem_stack_pop(tmp_stack)); + if (key_list_stack != NULL) { + while (wmem_stack_count(key_list_stack) > 0) { + port = GPOINTER_TO_UINT(wmem_stack_pop(key_list_stack)); + handle = dissector_get_uint_handle(ssl_associations, port); + if (handle != NULL) + ssl_association_remove("ssl.port", ssl_handle, handle, port, FALSE); + } } - wmem_destroy_stack(tmp_stack); - /* parse private keys string, load available keys and put them in key hash*/ ssl_key_hash = g_hash_table_new_full(ssl_private_key_hash, ssl_private_key_equal, g_free, ssl_private_key_free); if (nssldecrypt > 0) { + if (key_list_stack == NULL) + key_list_stack = wmem_stack_new(NULL); for (i = 0; i < nssldecrypt; i++) { ssldecrypt_assoc_t *ssl_uat = &(sslkeylist_uats[i]); - ssl_parse_key_list(ssl_uat, ssl_key_hash, ssl_associations, ssl_handle, TRUE); + ssl_parse_key_list(ssl_uat, ssl_key_hash, "ssl.port", ssl_handle, TRUE); + if (key_list_stack) + wmem_stack_push(key_list_stack, GUINT_TO_POINTER(atoi(ssl_uat->port))); } } @@ -441,39 +451,6 @@ ssl_parse_old_keys(void) } } -/********************************************************************* - * - * SSL Associations tree - * - *********************************************************************/ - -/** maximum size of ssl_association_info() string */ -#define SSL_ASSOC_MAX_LEN 8192 - -/** - * callback function used by ssl_association_info() to traverse the SSL associations. - */ -static gboolean -ssl_association_info_(gpointer key_ _U_, gpointer value_, gpointer s_) -{ - SslAssociation *value = (SslAssociation *)value_; - gchar *s = (gchar *)s_; - const int l = (const int)strlen(s); - g_snprintf(s+l, SSL_ASSOC_MAX_LEN-l, "'%s' %s %i\n", value->info, value->tcp ? "TCP":"UDP", value->ssl_port); - return FALSE; -} - -/** - * @return an information string on the SSL protocol associations. The string has ephemeral lifetime/scope. - */ -gchar* -ssl_association_info(void) -{ - gchar *s = (gchar *)g_malloc0(SSL_ASSOC_MAX_LEN); - g_tree_foreach(ssl_associations, ssl_association_info_, s); - return s; -} - /********************************************************************* * * Forward Declarations @@ -1709,11 +1686,10 @@ dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo, if (!session->app_handle) { /* Unknown protocol handle, ssl_starttls_ack was not called before. * Try to find an appropriate dissection handle and cache it. */ - SslAssociation *association; - association = ssl_association_find(ssl_associations, pinfo->srcport, pinfo->ptype != PT_UDP); - association = association ? association: ssl_association_find(ssl_associations, pinfo->destport, pinfo->ptype != PT_UDP); - association = association ? association: ssl_association_find(ssl_associations, 0, pinfo->ptype != PT_UDP); - if (association) session->app_handle = association->handle; + 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; } proto_item_set_text(ssl_record_tree, @@ -3651,6 +3627,31 @@ UAT_CSTRING_CB_DEF(sslkeylist_uats,port,ssldecrypt_assoc_t) UAT_CSTRING_CB_DEF(sslkeylist_uats,protocol,ssldecrypt_assoc_t) UAT_FILENAME_CB_DEF(sslkeylist_uats,keyfile,ssldecrypt_assoc_t) UAT_CSTRING_CB_DEF(sslkeylist_uats,password,ssldecrypt_assoc_t) + +static gboolean +ssldecrypt_uat_fld_protocol_chk_cb(void* r _U_, const char* p, guint len _U_, const void* u1 _U_, const void* u2 _U_, char** err) +{ + if (!p || strlen(p) == 0u) { + *err = g_strdup_printf("No protocol given."); + return FALSE; + } + + if (!find_dissector(p)) { + if (proto_get_id_by_filter_name(p) != -1) { + *err = g_strdup_printf("While '%s' is a valid dissector filter name, that dissector is not configured" + " to support SSL decryption.\n\n" + "If you need to decrypt '%s' over SSL, please contact the Wireshark development team.", p, p); + } else { + char* ssl_str = ssl_association_info("ssl.port", "TCP"); + *err = g_strdup_printf("Could not find dissector for: '%s'\nCommonly used SSL dissectors include:\n%s", p, ssl_str); + g_free(ssl_str); + } + return FALSE; + } + + *err = NULL; + return TRUE; +} #endif /********************************************************************* @@ -4090,6 +4091,8 @@ proto_register_ssl(void) proto_ssl = proto_register_protocol("Secure Sockets Layer", "SSL", "ssl"); + ssl_associations = register_dissector_table("ssl.port", "SSL TCP Dissector", FT_UINT16, BASE_DEC, DISSECTOR_TABLE_NOT_ALLOW_DUPLICATE); + /* Required function calls to register the header fields and * subtrees used */ proto_register_field_array(proto_ssl, hf, array_length(hf)); @@ -4167,8 +4170,6 @@ proto_register_ssl(void) new_register_dissector("ssl", dissect_ssl, proto_ssl); ssl_handle = find_dissector("ssl"); - ssl_associations = g_tree_new(ssl_association_cmp); - register_init_routine(ssl_init); register_cleanup_routine(ssl_cleanup); ssl_tap = register_tap("ssl"); @@ -4191,27 +4192,15 @@ proto_reg_handoff_ssl(void) } void -ssl_dissector_add(guint port, const gchar *protocol, gboolean tcp) +ssl_dissector_add(guint port, dissector_handle_t handle) { - SslAssociation *assoc; - - assoc = ssl_association_find(ssl_associations, port, tcp); - if (assoc) { - ssl_association_remove(ssl_associations, assoc); - } - - ssl_association_add(ssl_associations, ssl_handle, port, protocol, tcp, FALSE); + ssl_association_add("ssl.port", ssl_handle, handle, port, TRUE); } void -ssl_dissector_delete(guint port, const gchar *protocol, gboolean tcp) +ssl_dissector_delete(guint port, dissector_handle_t handle) { - SslAssociation *assoc; - - assoc = ssl_association_find(ssl_associations, port, tcp); - if (assoc && (assoc->handle == find_dissector(protocol))) { - ssl_association_remove(ssl_associations, assoc); - } + ssl_association_remove("ssl.port", ssl_handle, handle, port, TRUE); } /* diff --git a/epan/dissectors/packet-ssl.h b/epan/dissectors/packet-ssl.h index 499ba8d22e..ba800bddba 100644 --- a/epan/dissectors/packet-ssl.h +++ b/epan/dissectors/packet-ssl.h @@ -24,14 +24,15 @@ #define __PACKET_SSL_H__ #include "ws_symbol_export.h" +#include /** Maps Session-ID to pre-master secrets. */ WS_DLL_PUBLIC GHashTable *ssl_session_hash; /** Maps Client Random to pre-master secrets. */ WS_DLL_PUBLIC GHashTable *ssl_crandom_hash; -WS_DLL_PUBLIC void ssl_dissector_add(guint port, const gchar *protocol, gboolean tcp); -WS_DLL_PUBLIC void ssl_dissector_delete(guint port, const gchar *protocol, gboolean tcp); +WS_DLL_PUBLIC void ssl_dissector_add(guint port, dissector_handle_t handle); +WS_DLL_PUBLIC void ssl_dissector_delete(guint port, dissector_handle_t handle); WS_DLL_PUBLIC void ssl_set_master_secret(guint32 frame_num, address *addr_srv, address *addr_cli, port_type ptype, guint32 port_srv, guint32 port_cli, @@ -41,6 +42,4 @@ WS_DLL_PUBLIC void ssl_set_master_secret(guint32 frame_num, address *addr_srv, a extern gboolean ssl_ignore_mac_failed; -gchar* ssl_association_info(void); - #endif /* __PACKET_SSL_H__ */