new ssl_dissector_add() function which can be called from another dissectors (similar...
authorTomas Kukosa <tomas.kukosa@siemens.com>
Fri, 25 Aug 2006 08:07:26 +0000 (08:07 -0000)
committerTomas Kukosa <tomas.kukosa@siemens.com>
Fri, 25 Aug 2006 08:07:26 +0000 (08:07 -0000)
svn path=/trunk/; revision=19026

epan/dissectors/packet-dtls.c
epan/dissectors/packet-ssl-utils.c
epan/dissectors/packet-ssl-utils.h
epan/dissectors/packet-ssl.c
epan/libwireshark.def

index 902fb8cb4d79a73f9b0efe729a34e111c0a2dce2..651c8f466acb1e3a3f7b9eeb39b151e7424645eb 100644 (file)
@@ -164,20 +164,24 @@ dtls_init(void)
 static void 
 dtls_parse(void)
 {
+  ep_stack_t tmp_stack;
+  SslAssociation *tmp_assoc;
+
   if (dtls_key_hash)
     {
       g_hash_table_foreach(dtls_key_hash, ssl_private_key_free, NULL);
       g_hash_table_destroy(dtls_key_hash);
     }
-  if (dtls_associations)
-    {
-      g_tree_traverse(dtls_associations, ssl_association_remove_handle_udp, G_IN_ORDER, NULL);
-      g_tree_destroy(dtls_associations);
-    }
+
+  /* remove only associations created from key list */
+  tmp_stack = ep_stack_new();
+  g_tree_traverse(dtls_associations, ssl_assoc_from_key_list, G_IN_ORDER, tmp_stack);
+  while (tmp_assoc = ep_stack_pop(tmp_stack)) {
+    ssl_association_remove(dtls_associations, tmp_assoc);
+  }
 
   /* parse private keys string, load available keys and put them in key hash*/
   dtls_key_hash = g_hash_table_new(ssl_private_key_hash, ssl_private_key_equal);
-  dtls_associations = g_tree_new(ssl_association_cmp);
     
   if (dtls_keys_list && (dtls_keys_list[0] != 0)) 
     {            
@@ -187,7 +191,7 @@ dtls_parse(void)
   ssl_set_debug(dtls_debug_file_name);
 
   /* [re] add dtls dissection to default port in openssl 0.9.8b implementation */
-  ssl_association_add(dtls_associations, dtls_handle, 4433, "http", FALSE);   
+  ssl_association_add(dtls_associations, dtls_handle, 4433, "http", FALSE,FALSE);   
 }
 
 /*
@@ -318,7 +322,7 @@ dissect_dtls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     conversation_add_proto_data(conversation, proto_dtls, ssl_session);
             
     /* we need to know witch side of conversation is speaking */
-    if (ssl_packet_from_server(dtls_associations, pinfo->srcport)) {
+    if (ssl_packet_from_server(dtls_associations, pinfo->srcport, pinfo->ptype == PT_TCP)) {
       dummy.addr = pinfo->src;
       dummy.port = pinfo->srcport;
     }
@@ -444,7 +448,7 @@ decrypt_dtls_record(tvbuff_t *tvb, packet_info *pinfo, guint32 offset,
   }
     
   /* retrive decoder for this packet direction */    
-  if ((direction = ssl_packet_from_server(dtls_associations, pinfo->srcport)) != 0) {
+  if ((direction = ssl_packet_from_server(dtls_associations, pinfo->srcport, pinfo->ptype == PT_TCP)) != 0) {
     ssl_debug_printf("decrypt_dtls_record: using server decoder\n");
     decoder = &ssl->server;
   }
@@ -577,7 +581,7 @@ dissect_dtls_record(tvbuff_t *tvb, packet_info *pinfo,
   record_length = tvb_get_ntohs(tvb, offset + 11);
 
   if(ssl){   
-    if(ssl_packet_from_server(dtls_associations, pinfo->srcport)){
+    if(ssl_packet_from_server(dtls_associations, pinfo->srcport, pinfo->ptype == PT_TCP)){
       ssl->server.seq=sequence_number;
       ssl->server.epoch=epoch;
     }
@@ -758,8 +762,8 @@ dissect_dtls_record(tvbuff_t *tvb, packet_info *pinfo,
     /* we need dissector information when the selected packet is shown.
      * ssl session pointer is NULL at that time, so we can't access
      * info cached there*/         
-    association = ssl_association_find(dtls_associations, pinfo->srcport);
-    association = association ? association: ssl_association_find(dtls_associations, pinfo->destport);
+    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);
 
     proto_item_set_text(dtls_record_tree,
                        "%s Record Layer: %s Protocol: %s",
@@ -2147,7 +2151,10 @@ 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);
   ssl_lib_init();
   dtls_tap = register_tap("dtls");
@@ -2162,7 +2169,6 @@ proto_register_dtls(void)
 void
 proto_reg_handoff_dtls(void)
 {
-  dtls_handle = find_dissector("dtls");
     
   /* add now dissector to default ports.*/
   dtls_parse();
index c9525c6feba32ff5ff58506d9a88b5809d7cd8dc..14cf400e3140137fab008aace389627c9b0a2035 100644 (file)
@@ -1442,20 +1442,21 @@ ssl_private_key_free(gpointer id, gpointer key, gpointer dummy _U_)
 
 /* handling of association between tls/dtls ports and clear text protocol */
 void 
-ssl_association_add(GTree* associations, dissector_handle_t handle, guint port, gchar *protocol, gboolean tcp)
+ssl_association_add(GTree* associations, dissector_handle_t handle, guint port, gchar *protocol, gboolean tcp, gboolean from_key_list)
 {
 
   SslAssociation* assoc;
   assoc = g_malloc(sizeof(SslAssociation));
 
+  assoc->tcp = tcp;
+  assoc->ssl_port = port;
   assoc->info=g_malloc(strlen(protocol)+1);
   strcpy(assoc->info, protocol);
-  assoc->ssl_port = port;
-    
   assoc->handle = find_dissector(protocol); 
+  assoc->from_key_list = from_key_list;
 
-  ssl_debug_printf("association_add port %d protocol %s handle %p\n",
-                  port, protocol, assoc->handle);
+  ssl_debug_printf("association_add %s port %d protocol %s handle %p\n",
+                  (assoc->tcp)?"TCP":"UDP", port, protocol, assoc->handle);
 
   
   if(!assoc->handle){
@@ -1465,62 +1466,56 @@ ssl_association_add(GTree* associations, dissector_handle_t handle, guint port,
       dissector_add("tcp.port", port, handle);   
     else
       dissector_add("udp.port", port, handle);    
-    g_tree_insert(associations, (gpointer)port, assoc);
+    g_tree_insert(associations, assoc, assoc);
   }
 }
 
+void 
+ssl_association_remove(GTree* associations, SslAssociation *assoc)
+{
+  ssl_debug_printf("ssl_association_remove removing %s %u - %s handle %p\n",
+                  (assoc->tcp)?"TCP":"UDP", assoc->ssl_port, assoc->info, assoc->handle);
+  if (assoc->handle)
+    dissector_delete((assoc->tcp)?"tcp.port":"udp.port", assoc->ssl_port, assoc->handle);
+
+  g_tree_remove(associations, assoc);
+  g_free(assoc);
+}
 
 gint 
 ssl_association_cmp(gconstpointer a, gconstpointer b)
 {
-  return (gint)a-(gint)b;
+  const SslAssociation *assoc_a=a, *assoc_b=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)
+ssl_association_find(GTree * associations, guint port, gboolean tcp)
 {
   register SslAssociation* ret;
-  ret = g_tree_lookup(associations, (gpointer)port);
+  SslAssociation assoc_tmp;
 
-  ssl_debug_printf("association_find: port %d found %p\n", port, ret);
-  return ret;
-}
+  assoc_tmp.tcp = tcp;
+  assoc_tmp.ssl_port = port;
+  ret = g_tree_lookup(associations, &assoc_tmp);
 
-gint 
-ssl_association_remove_handle_tcp (gpointer key _U_, 
-                                  gpointer  data, gpointer  user_data _U_)
-{
-  SslAssociation* assoc;
-  assoc = (SslAssociation*) data;
-
-  ssl_debug_printf("association_remove_handle removing ptr %p handle %p\n",
-                  data, assoc->handle);
-  if (assoc->handle)
-    dissector_delete("tcp.port", assoc->ssl_port, assoc->handle);
-  g_free(data);
-  return 0;
+  ssl_debug_printf("association_find: %s port %d found %p\n", (tcp)?"TCP":"UDP", port, ret);
+  return ret;
 }
 
 gint 
-ssl_association_remove_handle_udp (gpointer key _U_, 
-                                  gpointer  data, gpointer  user_data _U_)
+ssl_assoc_from_key_list(gpointer key _U_, gpointer data, gpointer user_data)
 {
-  SslAssociation* assoc;
-  assoc = (SslAssociation*) data;
-
-  ssl_debug_printf("association_remove_handle removing ptr %p handle %p\n",
-                  data, assoc->handle);
-  if (assoc->handle)
-    dissector_delete("tcp.port", assoc->ssl_port, assoc->handle);
-  g_free(data);
-  return 0;
+  if (((SslAssociation*)data)->from_key_list)
+    ep_stack_push((ep_stack_t)user_data, data);
 }
 
 int 
-ssl_packet_from_server(GTree* associations, guint port)
+ssl_packet_from_server(GTree* associations, guint port, gboolean tcp)
 {
   register gint ret;
-  ret = ssl_association_find(associations, port) != 0;
+  ret = ssl_association_find(associations, port, tcp) != 0;
 
   ssl_debug_printf("packet_from_server: is from server %d\n", ret);    
   return ret;
@@ -1668,7 +1663,7 @@ ssl_parse_key_list(const gchar * keys_list, GHashTable *key_hash, GTree* associa
                     filename);
     g_hash_table_insert(key_hash, service, private_key);
            
-    ssl_association_add(associations, handle, atoi(port), protocol, tcp);
+    ssl_association_add(associations, handle, atoi(port), protocol, tcp, TRUE);
            
   } while (end != NULL);
   free(tmp);  
index 8f3b44d4bcd766c6891c68cdae7dcbe66b9cb51f..6f8e4b1fe92a78d07ac6e0c4f80ee826fb3ced2e 100644 (file)
@@ -657,9 +657,11 @@ typedef struct _SslDecryptSession {
 } SslDecryptSession;
 
 typedef struct _SslAssociation {
+  gboolean tcp;
   guint ssl_port;
   dissector_handle_t handle;
   gchar* info;
+  gboolean from_key_list;
 } SslAssociation;
 
 typedef struct _SslService {
@@ -754,24 +756,22 @@ ssl_private_key_free(gpointer id, gpointer key, gpointer dummy _U_);
 
 /* handling of association between tls/dtls ports and clear text protocol */
 extern void 
-ssl_association_add(GTree* associations, dissector_handle_t handle, guint port, gchar *protocol, gboolean tcp);
+ssl_association_add(GTree* associations, dissector_handle_t handle, guint port, gchar *protocol, gboolean tcp, gboolean from_key_list);
+
+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);
-
-extern gint 
-ssl_association_remove_handle_tcp (gpointer key _U_, 
-                                  gpointer  data, gpointer  user_data _U_);
+ssl_association_find(GTree * associations, guint port, gboolean tcp);
 
 extern gint 
-ssl_association_remove_handle_udp (gpointer key _U_, 
-                                  gpointer  data, gpointer  user_data _U_);
+ssl_assoc_from_key_list(gpointer key _U_, gpointer data, gpointer user_data);
 
 extern gint 
-ssl_packet_from_server(GTree* associations, guint port);
+ssl_packet_from_server(GTree* associations, guint port, gboolean tcp);
 
 /* add to packet data a newly allocated tvb with the specified real data*/
 extern void
index 61cbe26c4fda7e4bfe3120abe3e41e554e55dc31..196bec72826c8061432ae4c8ef263a08220f802f 100644 (file)
 #include <epan/dissectors/packet-x509af.h>
 #include <epan/emem.h>
 #include <epan/tap.h>
+#include "packet-ssl.h"
 #include "packet-ssl-utils.h"
 
 
@@ -230,6 +231,9 @@ static gint ssl_decrypted_data_avail = 0;
 static gchar* ssl_keys_list = NULL;
 static gchar* ssl_debug_file_name = NULL;
 
+/* Forward declaration we need below */
+void proto_reg_handoff_ssl(void);
+
 /* initialize/reset per capture state data (ssl sessions cache) */
 static void
 ssl_init(void)
@@ -241,6 +245,9 @@ ssl_init(void)
 static void
 ssl_parse(void)
 {
+       ep_stack_t tmp_stack;
+       SslAssociation *tmp_assoc;
+
     ssl_set_debug(ssl_debug_file_name);
 
     if (ssl_key_hash)
@@ -248,26 +255,22 @@ ssl_parse(void)
         g_hash_table_foreach(ssl_key_hash, ssl_private_key_free, NULL);
         g_hash_table_destroy(ssl_key_hash);
     }
-    if (ssl_associations)
-    {
-        g_tree_traverse(ssl_associations, ssl_association_remove_handle_tcp, G_IN_ORDER, NULL);
-        g_tree_destroy(ssl_associations);
-    }
+
+       /* remove only associations created from key list */
+       tmp_stack = ep_stack_new();
+    g_tree_traverse(ssl_associations, ssl_assoc_from_key_list, G_IN_ORDER, tmp_stack);
+       while (tmp_assoc = ep_stack_pop(tmp_stack)) {
+               ssl_association_remove(ssl_associations, tmp_assoc);
+       }
 
     /* parse private keys string, load available keys and put them in key hash*/
     ssl_key_hash = g_hash_table_new(ssl_private_key_hash,ssl_private_key_equal);
-    ssl_associations = g_tree_new(ssl_association_cmp);
 
     if (ssl_keys_list && (ssl_keys_list[0] != 0))
     {
         ssl_parse_key_list(ssl_keys_list,ssl_key_hash,ssl_associations,ssl_handle,TRUE);
     }
 
-    /* [re] add ssl dissection to defaults ports */
-    ssl_association_add(ssl_associations, ssl_handle, 443, "http", TRUE);
-    ssl_association_add(ssl_associations, ssl_handle, 636, "ldap", TRUE);
-    ssl_association_add(ssl_associations, ssl_handle, 993, "imap", TRUE);
-    ssl_association_add(ssl_associations, ssl_handle, 995, "pop", TRUE);
 }
 
 /* function that save app_data during sub protocol reassembling */
@@ -312,8 +315,8 @@ ssl_desegment_ssl_app_data(SslDecryptSession * ssl,  packet_info *pinfo){
              tvbuff_t* new_tvb;
              packet_info * pp;
              /* find out a dissector using server port*/
-             association = ssl_association_find(ssl_associations, pinfo->srcport);
-             association = association ? association: ssl_association_find(ssl_associations, pinfo->destport);
+             association = ssl_association_find(ssl_associations, pinfo->srcport, pinfo->ptype == PT_TCP);
+             association = association ? association: ssl_association_find(ssl_associations, pinfo->destport, pinfo->ptype == PT_TCP);
              /* create a copy of packet_info */
              pp=g_malloc(sizeof(packet_info));
              memcpy(pp, pinfo, sizeof(packet_info));
@@ -584,7 +587,7 @@ dissect_ssl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
         conversation_add_proto_data(conversation, proto_ssl, ssl_session);
 
         /* we need to know witch side of conversation is speaking*/
-        if (ssl_packet_from_server(ssl_associations, pinfo->srcport)) {
+        if (ssl_packet_from_server(ssl_associations, pinfo->srcport, pinfo->ptype == PT_TCP)) {
             dummy.addr = pinfo->src;
             dummy.port = pinfo->srcport;
         }
@@ -765,7 +768,7 @@ decrypt_ssl3_record(tvbuff_t *tvb, packet_info *pinfo, guint32 offset,
     }
 
     /* retrive decoder for this packet direction*/
-    if ((direction = ssl_packet_from_server(ssl_associations, pinfo->srcport)) != 0) {
+    if ((direction = ssl_packet_from_server(ssl_associations, pinfo->srcport, pinfo->ptype == PT_TCP)) != 0) {
         ssl_debug_printf("decrypt_ssl3_record: using server decoder\n");
         decoder = &ssl->server;
     }
@@ -1107,8 +1110,8 @@ dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
         /* we need dissector information when the selected packet is shown.
          * ssl session pointer is NULL at that time, so we can't access
          * info cached there*/
-        association = ssl_association_find(ssl_associations, pinfo->srcport);
-        association = association ? association: ssl_association_find(ssl_associations, pinfo->destport);
+        association = ssl_association_find(ssl_associations, pinfo->srcport, pinfo->ptype == PT_TCP);
+        association = association ? association: ssl_association_find(ssl_associations, pinfo->destport, pinfo->ptype == PT_TCP);
 
         proto_item_set_text(ssl_record_tree,
             "%s Record Layer: %s Protocol: %s",
@@ -3713,7 +3716,7 @@ proto_register_ssl(void)
     proto_register_subtree_array(ett, array_length(ett));
 
     {
-      module_t *ssl_module = prefs_register_protocol(proto_ssl, ssl_parse);
+      module_t *ssl_module = prefs_register_protocol(proto_ssl, proto_reg_handoff_ssl);
       prefs_register_bool_preference(ssl_module,
              "desegment_ssl_records",
              "Reassemble SSL records spanning multiple TCP segments",
@@ -3739,6 +3742,9 @@ proto_register_ssl(void)
     }
 
     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);
     ssl_lib_init();
@@ -3754,9 +3760,26 @@ proto_register_ssl(void)
 void
 proto_reg_handoff_ssl(void)
 {
-    ssl_handle = find_dissector("ssl");
 
-    /* add now dissector to default ports.*/
+    /* parse key list */
     ssl_parse();
+
+    /* add ssl dissection to defaults ports */
+    ssl_dissector_add(443, "http", TRUE);
+    ssl_dissector_add(636, "ldap", TRUE);
+    ssl_dissector_add(993, "imap", TRUE);
+    ssl_dissector_add(995, "pop", TRUE);
 }
 
+void
+ssl_dissector_add(guint port, gchar *protocol, gboolean tcp)
+{
+       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);
+}
index d283cf8a91b8ad3f097ee1912ca9de3a749fa052..9cb447b6be3e8dd8a56a60fed795f386c52eab4f 100644 (file)
@@ -629,6 +629,7 @@ sid_name_table                  DATA
 smb_cmd_vals                    DATA
 smb2_cmd_vals                    DATA
 sminmpec_values                 DATA
+ssl_dissector_add
 start_requested_stats
 started_with_special_privs
 stats_tree_branch_max_namelen