Create real dissector tables for SSL and DTLS to use.
authorMichael Mann <mmann78@netscape.net>
Fri, 6 Nov 2015 04:20:45 +0000 (23:20 -0500)
committerMichael Mann <mmann78@netscape.net>
Sat, 7 Nov 2015 14:11:01 +0000 (14:11 +0000)
Since ssl_dissector_[add|delete] only take TCP dissectors, remove the parameter and just use it within the "internal" ssl_association_add call.

Change-Id: I0fdf941389934c20cbacf910250e17520614e706
Reviewed-on: https://code.wireshark.org/review/11591
Petri-Dish: Michael Mann <mmann78@netscape.net>
Reviewed-by: Michael Mann <mmann78@netscape.net>
19 files changed:
asn1/h225/packet-h225-template.c
asn1/ldap/packet-ldap-template.c
debian/libwireshark0.symbols
epan/dissectors/packet-amqp.c
epan/dissectors/packet-dtls.c
epan/dissectors/packet-h225.c
epan/dissectors/packet-http.c
epan/dissectors/packet-imap.c
epan/dissectors/packet-ldap.c
epan/dissectors/packet-pop.c
epan/dissectors/packet-sip.c
epan/dissectors/packet-skinny.c
epan/dissectors/packet-skinny.c.in
epan/dissectors/packet-smtp.c
epan/dissectors/packet-spdy.c
epan/dissectors/packet-ssl-utils.c
epan/dissectors/packet-ssl-utils.h
epan/dissectors/packet-ssl.c
epan/dissectors/packet-ssl.h

index b2b6ec0a0ca088f782081d3c131f868944ce5f90..4b7cab749f21b7fa3f4530fa2dc6611a81909b21 100644 (file)
@@ -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);
 }
 
 
index 0dbe926b4c18f589fb71470d42496f5a71b1b197..736d6be20663cb13e9d49c69c6dd638c759b2014 100644 (file)
@@ -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);
   }
 
 }
index bdecd3ff9abcd93aeb2681fcd011b0dba1ad9130..a99d25e0c2ee90905b98d71bb317a3690d56d96f 100644 (file)
@@ -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
index 9b7eab42625a11358fbe33bca0e54978be8f868f..1d17d7501a873612bfb806cef0ed096386a5ebd0 100644 (file)
@@ -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);
     }
 }
 
index 900aed3b09e22b00004552fdfa46efdf1ef0f498..3f02c7b7ebb9e916155f519eb1cf9dceacdffd36 100644 (file)
@@ -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");
index 867bf8da33aa10c9f70ad8310b86170993d35172..cf611e473a53f20bfabfb8bd950b0cbffbc42396 100644 (file)
@@ -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);
 }
 
 
index 695ba6eabce150f6d935ed263098f6f3d5b8a9ba..6e57020286a82003d2457988ba34661d7410c876 100644 (file)
@@ -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) {
index a95da306f45d319c968274b62956856b20513767..9673f6b149fc389b32ccc9edb946b7b05344b679 100644 (file)
@@ -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");
 }
 /*
index fe26c3739020f221ff6a520408ed7c8528daf0cc..025f3f89f7c188a9b1e0d416d45109687233d513 100644 (file)
@@ -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);
   }
 
 }
index a90c44eb28d0be3c19384e6898b53657abf58731..2d7bbbd0284974d488924731e3bced387ac9493f 100644 (file)
@@ -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 */
index 08a70181fcb770adf346c2a1a96e496941adc4ed..a41df2b21d60817535ff1fcd9e06792521256897 100644 (file)
@@ -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);
 }
index 9883ee8c27d05ebad0bdc8debb354e82e345ee49..01f79cdbf87a4ff4b1b7875d42ce50f3e4477053 100644 (file)
@@ -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);
 }
 
 /*
index 464cd4b076ca51a53a31951904ca0813cd0376b9..8d09e9352cc95005f390aa0d0bf8f3cd4ae8a635 100644 (file)
@@ -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);
 }
 
 /*
index d428c40e4153d6671304280d40916293a46152b4..d8621300d59c3151c19e8f6f616a483faade32b9 100644 (file)
@@ -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 */
index e79b100e4057fc14ae9d5fd0fadad740edef3fe6..98d81364a7255a288a1e3f872b8ed8641ad5297c 100644 (file)
@@ -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");
index 41a021edb7fe8d6951ac1532044291488aab0bb6..9aceb8eb38a8963f9651b42a78f1d0274d70760a 100644 (file)
@@ -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. */
 
index f7a2496759390e184a13dca10cd0c9d25e6a16a4..dcf1f8b515d2d902a4dea0bddf24c87eb972a6cd 100644 (file)
@@ -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);
-
-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);
+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_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
index ae9daf8956f8ddd835a4735be0b2853f3265b822..23d7a6d7c3a9900be73b7fc5fc757f7e99a2fb1e 100644 (file)
@@ -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);
 }
 
 /*
index 499ba8d22e86e0329f6e6e9d05255490615e0a17..ba800bddba009716faa6a891048b869d550a100d 100644 (file)
 #define __PACKET_SSL_H__
 
 #include "ws_symbol_export.h"
+#include <epan/packet.h>
 
 /** 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__ */