aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/dissectors/packet-dtls.c4922
-rw-r--r--epan/dissectors/packet-ssl-utils.c579
-rw-r--r--epan/dissectors/packet-ssl-utils.h149
-rw-r--r--epan/dissectors/packet-ssl.c697
4 files changed, 2421 insertions, 3926 deletions
diff --git a/epan/dissectors/packet-dtls.c b/epan/dissectors/packet-dtls.c
index ca12f21c79..902fb8cb4d 100644
--- a/epan/dissectors/packet-dtls.c
+++ b/epan/dissectors/packet-dtls.c
@@ -4,8 +4,8 @@
*
* $Id$
*
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
@@ -22,6 +22,26 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
+ *
+ * DTLS dissection and decryption.
+ * See RFC 4347 for details about DTLS specs.
+ *
+ * Notes :
+ * This dissector is based on TLS one (packet-ssl.c) because of the proximity of DTLS and TLS, decryption works like him with RSA key exchange.
+ * It uses the sames things (file, libraries) that SSL one (gnutls, packet-ssl-utils.h) to make it easily maintenable.
+ *
+ * It was developped to dissect and decrypt OpenSSL v 0.9.8b DTLS implementation.
+ * It is limited to this implementation while there is no complete implementation.
+ *
+ * Implemented :
+ * - DTLS dissection
+ * - DTLS decryption (openssl one)
+ *
+ * Todo :
+ * - activate correct Mac calculation when openssl will be corrected
+ * (or if an other implementation works),
+ * corrected code is ready and commented in packet-ssl-utils.h file.
+ * - add missings things (desegmentation, reordering... that aren't present in actual OpenSSL implementation)
*/
#ifdef HAVE_CONFIG_H
@@ -32,6 +52,11 @@
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
#include <glib.h>
#include <epan/conversation.h>
@@ -42,7 +67,10 @@
#include <epan/tap.h>
#include "packet-ssl-utils.h"
-static gboolean ssl_desegment = TRUE;
+/* we need to remember the top tree so that subdissectors we call are created
+ * at the root and not deep down inside the DTLS decode
+ */
+static proto_tree *top_tree;
/*********************************************************************
*
@@ -51,89 +79,57 @@ static gboolean ssl_desegment = TRUE;
*********************************************************************/
/* Initialize the protocol and registered fields */
-static int dtls_tap = -1;
-static int proto_dtls = -1;
-static int hf_dtls_record = -1;
-static int hf_dtls_record_content_type = -1;
-static int hf_dtls_record_version = -1;
-static int hf_dtls_record_epoch = -1;
-static int hf_dtls_record_sequence_number = -1;
-static int hf_dtls_record_length = -1;
-static int hf_dtls_record_appdata = -1;
-static int hf_dtls_record_appdata_decrypted = -1;
-static int hf_ssl2_record = -1;
-static int hf_ssl2_record_is_escape = -1;
-static int hf_ssl2_record_padding_length = -1;
-static int hf_ssl2_msg_type = -1;
-static int hf_pct_msg_type = -1;
-static int hf_dtls_change_cipher_spec = -1;
-static int hf_dtls_alert_message = -1;
-static int hf_dtls_alert_message_level = -1;
-static int hf_dtls_alert_message_description = -1;
-static int hf_dtls_handshake_protocol = -1;
-static int hf_dtls_handshake_type = -1;
-static int hf_dtls_handshake_length = -1;
-static int hf_dtls_handshake_message_seq = -1;
-static int hf_dtls_handshake_fragment_offset = -1;
-static int hf_dtls_handshake_fragment_length = -1;
-static int hf_dtls_handshake_client_version = -1;
-static int hf_dtls_handshake_server_version = -1;
-static int hf_dtls_handshake_random_time = -1;
-static int hf_dtls_handshake_random_bytes = -1;
-static int hf_dtls_handshake_cookie_len = -1;
-static int hf_dtls_handshake_cookie = -1;
-static int hf_dtls_handshake_cipher_suites_len = -1;
-static int hf_dtls_handshake_cipher_suites = -1;
-static int hf_dtls_handshake_cipher_suite = -1;
-static int hf_dtls_handshake_session_id = -1;
-static int hf_dtls_handshake_comp_methods_len = -1;
-static int hf_dtls_handshake_comp_methods = -1;
-static int hf_dtls_handshake_comp_method = -1;
-static int hf_dtls_handshake_extensions_len = -1;
-static int hf_dtls_handshake_extension_type = -1;
-static int hf_dtls_handshake_extension_len = -1;
-static int hf_dtls_handshake_extension_data = -1;
-static int hf_dtls_handshake_certificates_len = -1;
-static int hf_dtls_handshake_certificates = -1;
-static int hf_dtls_handshake_certificate = -1;
-static int hf_dtls_handshake_certificate_len = -1;
-static int hf_dtls_handshake_cert_types_count = -1;
-static int hf_dtls_handshake_cert_types = -1;
-static int hf_dtls_handshake_cert_type = -1;
-static int hf_dtls_handshake_finished = -1;
-static int hf_dtls_handshake_md5_hash = -1;
-static int hf_dtls_handshake_sha_hash = -1;
-static int hf_dtls_handshake_session_id_len = -1;
-static int hf_dtls_handshake_dnames_len = -1;
-static int hf_dtls_handshake_dnames = -1;
-static int hf_dtls_handshake_dname_len = -1;
-static int hf_dtls_handshake_dname = -1;
-static int hf_ssl2_handshake_cipher_spec_len = -1;
-static int hf_ssl2_handshake_session_id_len = -1;
-static int hf_ssl2_handshake_challenge_len = -1;
-static int hf_ssl2_handshake_cipher_spec = -1;
-static int hf_ssl2_handshake_challenge = -1;
-static int hf_ssl2_handshake_clear_key_len = -1;
-static int hf_ssl2_handshake_enc_key_len = -1;
-static int hf_ssl2_handshake_key_arg_len = -1;
-static int hf_ssl2_handshake_clear_key = -1;
-static int hf_ssl2_handshake_enc_key = -1;
-static int hf_ssl2_handshake_key_arg = -1;
-static int hf_ssl2_handshake_session_id_hit = -1;
-static int hf_ssl2_handshake_cert_type = -1;
-static int hf_ssl2_handshake_connection_id_len = -1;
-static int hf_ssl2_handshake_connection_id = -1;
-static int hf_pct_handshake_cipher_spec = -1;
-static int hf_pct_handshake_hash_spec = -1;
-static int hf_pct_handshake_cert_spec = -1;
-static int hf_pct_handshake_cert = -1;
-static int hf_pct_handshake_server_cert = -1;
-static int hf_pct_handshake_exch_spec = -1;
-static int hf_pct_handshake_hash = -1;
-static int hf_pct_handshake_cipher = -1;
-static int hf_pct_handshake_exch = -1;
-static int hf_pct_handshake_sig = -1;
-static int hf_pct_msg_error_type = -1;
+static gint dtls_tap = -1;
+static gint proto_dtls = -1;
+static gint hf_dtls_record = -1;
+static gint hf_dtls_record_content_type = -1;
+static gint hf_dtls_record_version = -1;
+static gint hf_dtls_record_epoch = -1;
+static gint hf_dtls_record_sequence_number = -1;
+static gint hf_dtls_record_length = -1;
+static gint hf_dtls_record_appdata = -1;
+static gint hf_dtls_change_cipher_spec = -1;
+static gint hf_dtls_alert_message = -1;
+static gint hf_dtls_alert_message_level = -1;
+static gint hf_dtls_alert_message_description = -1;
+static gint hf_dtls_handshake_protocol = -1;
+static gint hf_dtls_handshake_type = -1;
+static gint hf_dtls_handshake_length = -1;
+static gint hf_dtls_handshake_message_seq = -1;
+static gint hf_dtls_handshake_fragment_offset = -1;
+static gint hf_dtls_handshake_fragment_length = -1;
+static gint hf_dtls_handshake_client_version = -1;
+static gint hf_dtls_handshake_server_version = -1;
+static gint hf_dtls_handshake_random_time = -1;
+static gint hf_dtls_handshake_random_bytes = -1;
+static gint hf_dtls_handshake_cookie_len = -1;
+static gint hf_dtls_handshake_cookie = -1;
+static gint hf_dtls_handshake_cipher_suites_len = -1;
+static gint hf_dtls_handshake_cipher_suites = -1;
+static gint hf_dtls_handshake_cipher_suite = -1;
+static gint hf_dtls_handshake_session_id = -1;
+static gint hf_dtls_handshake_comp_methods_len = -1;
+static gint hf_dtls_handshake_comp_methods = -1;
+static gint hf_dtls_handshake_comp_method = -1;
+static gint hf_dtls_handshake_extensions_len = -1;
+static gint hf_dtls_handshake_extension_type = -1;
+static gint hf_dtls_handshake_extension_len = -1;
+static gint hf_dtls_handshake_extension_data = -1;
+static gint hf_dtls_handshake_certificates_len = -1;
+static gint hf_dtls_handshake_certificates = -1;
+static gint hf_dtls_handshake_certificate = -1;
+static gint hf_dtls_handshake_certificate_len = -1;
+static gint hf_dtls_handshake_cert_types_count = -1;
+static gint hf_dtls_handshake_cert_types = -1;
+static gint hf_dtls_handshake_cert_type = -1;
+static gint hf_dtls_handshake_finished = -1;
+static gint hf_dtls_handshake_md5_hash = -1;
+static gint hf_dtls_handshake_sha_hash = -1;
+static gint hf_dtls_handshake_session_id_len = -1;
+static gint hf_dtls_handshake_dnames_len = -1;
+static gint hf_dtls_handshake_dnames = -1;
+static gint hf_dtls_handshake_dname_len = -1;
+static gint hf_dtls_handshake_dname = -1;
/* Initialize the subtree pointers */
static gint ett_dtls = -1;
@@ -146,510 +142,122 @@ static gint ett_dtls_extension = -1;
static gint ett_dtls_certs = -1;
static gint ett_dtls_cert_types = -1;
static gint ett_dtls_dnames = -1;
-static gint ett_pct_cipher_suites = -1;
-static gint ett_pct_hash_suites = -1;
-static gint ett_pct_cert_suites = -1;
-static gint ett_pct_exch_suites = -1;
-
-typedef struct {
- unsigned int ssl_port;
- unsigned int decrypted_port;
- dissector_handle_t handle;
- char* info;
-} SslAssociation;
-
-static char* dtls_keys_list = NULL;
-static char* dtls_ports_list = NULL;
-static char* dtls_debug_file_name = NULL;
-
-typedef struct _SslService {
- address addr;
- guint port;
-} SslService;
-
-static GHashTable *ssl_session_hash = NULL;
-static GHashTable *ssl_key_hash = NULL;
-static GTree* ssl_associations = NULL;
-static dissector_handle_t dtls_handle = NULL;
-static StringInfo ssl_decrypted_data = {NULL, 0};
-static int ssl_decrypted_data_avail = 0;
-
-/* Hash Functions for ssl sessions table and private keys table*/
-static gint
-ssl_equal (gconstpointer v, gconstpointer v2)
-{
- const StringInfo *val1 = (const StringInfo *)v;
- const StringInfo *val2 = (const StringInfo *)v2;
-
- if (val1->data_len == val2->data_len &&
- !memcmp(val1->data, val2->data, val2->data_len)) {
- return 1;
- }
- return 0;
-}
-
-static guint
-ssl_hash (gconstpointer v)
-{
- guint l,hash = 0;
- StringInfo* id = (StringInfo*) v;
- guint* cur = (guint*) id->data;
- for (l=4; (l<id->data_len); l+=4, cur++)
- hash = hash ^ (*cur);
-
- return hash;
-}
-
-static gint
-ssl_private_key_equal (gconstpointer v, gconstpointer v2)
-{
- const SslService *val1 = (const SslService *)v;
- const SslService *val2 = (const SslService *)v2;
-
- if ((val1->port == val2->port) &&
- ! CMP_ADDRESS(&val1->addr, &val2->addr)) {
- return 1;
- }
- return 0;
-}
-
-static guint
-ssl_private_key_hash (gconstpointer v)
-{
- const SslService *key = (const SslService *)v;
- guint l,hash = key->port, len = key->addr.len;
-
- guint* cur = (guint*) key->addr.data;
- for (l=4; (l<len); l+=4, cur++)
- hash = hash ^ (*cur);
-
- return hash;
-}
-
-/* private key table entries have a scope 'larger' then packet capture,
- * so we can't relay on se_alloc** function */
-static void
-ssl_private_key_free(gpointer id, gpointer key, gpointer dummy _U_)
-{
- g_free(id);
- ssl_free_key((SSL_PRIVATE_KEY*) key);
-}
-
-/* handling of association between ssl ports and clear text protocol */
-static void
-ssl_association_add(unsigned int port, unsigned int ctport,
- const char* info)
-{
- dissector_table_t udp_dissectors = find_dissector_table( "udp.port");
- SslAssociation* assoc = g_malloc(sizeof(SslAssociation)+strlen(info)+1);
-
- assoc->info = (char*) assoc+sizeof(SslAssociation);
- strcpy(assoc->info, info);
- assoc->ssl_port = port;
- assoc->decrypted_port = ctport;
- assoc->handle = dissector_get_port_handle(udp_dissectors, ctport);
-
- ssl_debug_printf("ssl_association_add port %d ctport %d info %s handle %p\n",
- port, ctport, info, assoc->handle);
-
- dissector_add("udp.port", port, dtls_handle);
- g_tree_insert(ssl_associations, (gpointer)port, assoc);
-}
-
-static gint
-ssl_association_cmp(gconstpointer a, gconstpointer b)
-{
- return (gint)a-(gint)b;
-}
-
-static inline
-SslAssociation* ssl_association_find(unsigned int port)
-{
- register SslAssociation* ret = g_tree_lookup(ssl_associations, (gpointer)port);
- ssl_debug_printf("ssl_association_find: port %d found %p\n", port, ret);
- return ret;
-}
-static gint
-ssl_association_remove_handle (gpointer key _U_,
- gpointer data, gpointer user_data _U_)
-{
- SslAssociation* assoc = (SslAssociation*) data;
- ssl_debug_printf("ssl_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;
-}
-
-static inline int
-ssl_packet_from_server(unsigned int port)
-{
- register int ret = ssl_association_find(port) != 0;
- ssl_debug_printf("ssl_packet_from_server: is from server %d\n", ret);
- return ret;
-}
-
-/* add to packet data a newly allocated tvb with the specified real data*/
-static void
-ssl_add_record_info(packet_info *pinfo, unsigned char* data, int data_len, int record_id)
-{
- unsigned char* real_data = se_alloc(data_len);
- SslRecordInfo* rec = se_alloc(sizeof(SslRecordInfo));
- SslPacketInfo* pi = p_get_proto_data(pinfo->fd, proto_dtls);
- if (!pi)
- {
- pi = se_alloc0(sizeof(SslPacketInfo));
- p_add_proto_data(pinfo->fd, proto_dtls,pi);
- }
-
- rec->id = record_id;
- rec->tvb = tvb_new_real_data(real_data, data_len, data_len);
- memcpy(real_data, data, data_len);
-
- /* head insertion */
- rec->next= pi->handshake_data;
- pi->handshake_data = rec;
-}
-
-/* search in packet data the tvbuff associated to the specified id */
-static tvbuff_t*
-ssl_get_record_info(packet_info *pinfo, int record_id)
-{
- SslRecordInfo* rec;
- SslPacketInfo* pi = p_get_proto_data(pinfo->fd, proto_dtls);
- if (!pi)
- return NULL;
-
- for (rec = pi->handshake_data; rec; rec = rec->next)
- if (rec->id == record_id)
- return rec->tvb;
+static GHashTable *dtls_session_hash = NULL;
+static GHashTable *dtls_key_hash = NULL;
+static GTree* dtls_associations = NULL;
+static dissector_handle_t dtls_handle = NULL;
+static StringInfo dtls_decrypted_data = {NULL, 0};
+static gint dtls_decrypted_data_avail = 0;
- return NULL;
-}
+static gchar* dtls_keys_list = NULL;
+static gchar* dtls_debug_file_name = NULL;
-/* initialize/reset per capture state data (ssl sessions cache) */
+/* initialize/reset per capture state data (dtls sessions cache) */
static void
-ssl_init(void)
+dtls_init(void)
{
- if (ssl_session_hash)
- g_hash_table_destroy(ssl_session_hash);
- ssl_session_hash = g_hash_table_new(ssl_hash, ssl_equal);
- if (ssl_decrypted_data.data)
- g_free(ssl_decrypted_data.data);
- ssl_decrypted_data.data = g_malloc0(32);
- ssl_decrypted_data.data_len = 32;
+ ssl_common_init(&dtls_session_hash, &dtls_decrypted_data);
}
-/* parse ssl related preferences (private keys and ports association strings) */
+/* parse dtls related preferences (private keys and ports association strings) */
static void
-ssl_parse(void)
+dtls_parse(void)
{
- if (ssl_key_hash)
+ if (dtls_key_hash)
{
- g_hash_table_foreach(ssl_key_hash, ssl_private_key_free, NULL);
- g_hash_table_destroy(ssl_key_hash);
+ g_hash_table_foreach(dtls_key_hash, ssl_private_key_free, NULL);
+ g_hash_table_destroy(dtls_key_hash);
}
- if (ssl_associations)
+ if (dtls_associations)
{
- g_tree_traverse(ssl_associations, ssl_association_remove_handle, G_IN_ORDER, NULL);
- g_tree_destroy(ssl_associations);
+ g_tree_traverse(dtls_associations, ssl_association_remove_handle_udp, G_IN_ORDER, NULL);
+ g_tree_destroy(dtls_associations);
}
- /* 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 (dtls_keys_list && (dtls_keys_list[0] != 0))
- {
- char* end;
- char* start = strdup(dtls_keys_list);
- char* tmp = start;
-
- ssl_debug_printf("ssl_init keys string %s\n", start);
- do {
- char* addr, *port, *filename;
- unsigned char* ip;
- SslService* service;
- SSL_PRIVATE_KEY * private_key;
- FILE* fp;
-
- addr = start;
- /* split ip/file couple with ',' separator*/
- end = strchr(start, ',');
- if (end) {
- *end = 0;
- start = end+1;
- }
-
- /* for each entry split ip, port, filename with ':' separator */
- ssl_debug_printf("ssl_init found host entry %s\n", addr);
- port = strchr(addr, ':');
- if (!port)
- {
- ssl_debug_printf("ssl_init entry malformed can't find port in %s\n", addr);
- break;
- }
- *port = 0;
- port++;
-
- filename = strchr(port,':');
- if (!filename)
- {
- ssl_debug_printf("ssl_init entry malformed can't find filename in %s\n", port);
- break;
- }
- *filename=0;
- filename++;
-
- /* convert ip and port string to network rappresentation*/
- service = g_malloc(sizeof(SslService) + 4);
- service->addr.type = AT_IPv4;
- service->addr.len = 4;
- service->addr.data = ip = ((unsigned char*)service) + sizeof(SslService);
- sscanf(addr, "%hhu.%hhu.%hhu.%hhu", &ip[0], &ip[1], &ip[2], &ip[3]);
- service->port = atoi(port);
- ssl_debug_printf("ssl_init addr %hhu.%hhu.%hhu.%hhu port %d filename %s\n",
- ip[0], ip[1], ip[2], ip[3], service->port, filename);
+ /* 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);
- /* try to load pen file*/
- fp = fopen(filename, "rb");
- if (!fp) {
- fprintf(stderr, "can't open file %s \n",filename);
- break;
- }
-
- private_key = ssl_load_key(fp);
- if (!private_key) {
- fprintf(stderr,"can't load private key from %s\n",
- filename);
- break;
- }
- fclose(fp);
-
- ssl_debug_printf("ssl_init private key file %s successfully loaded\n",
- filename);
- g_hash_table_insert(ssl_key_hash, service, private_key);
-
- } while (end != NULL);
- free(tmp);
+ if (dtls_keys_list && (dtls_keys_list[0] != 0))
+ {
+ ssl_parse_key_list(dtls_keys_list,dtls_key_hash,dtls_associations,dtls_handle,FALSE);
}
- /* parse ssl ports string and add ssl dissector to specifed port[s]*/
- if (dtls_ports_list && (dtls_ports_list[0] != 0))
- {
- char* end;
- char* start = strdup(dtls_ports_list);
- char* tmp = start;
-
- ssl_debug_printf("ssl_init ports string %s\n", start);
- do {
- char* port, *ctport, *info;
- unsigned int portn, ctportn;
-
- port = start;
- /* split ip/file couple with ',' separator*/
- end = strchr(start, ',');
- if (end) {
- *end = 0;
- start = end+1;
- }
-
- /* for each entry split ip, port, filename with ':' separator */
- ssl_debug_printf("ssl_init found port entry %s\n", port);
- ctport = strchr(port, ':');
- if (!ctport)
- break;
- *ctport = 0;
- ctport++;
-
- info = strchr(ctport,':');
- if (!info)
- break;
- *info=0;
- info++;
-
- /* add dissector to this port */
- portn = atoi(port);
- ctportn = atoi(ctport);
- if (!portn || !ctportn)
- break;
-
- ssl_debug_printf("ssl_init adding dissector to port %d (ct port %d)\n", portn, ctportn);
- ssl_association_add(portn, ctportn, info);
- } while (end != NULL);
- free(tmp);
- }
-
- ssl_set_debug(dtls_debug_file_name);
-
- /* [re] add ssl dissection to defaults ports */
- ssl_association_add(4433, 80, "OpenSSL Implementation");
-}
-
-/* store master secret into session data cache */
-static void
-ssl_save_session(SslDecryptSession* ssl)
-{
- /* allocate stringinfo chunks for session id and master secret data*/
- StringInfo* session_id = se_alloc0(sizeof(StringInfo) + ssl->session_id.data_len);
- StringInfo* master_secret = se_alloc0(48 + sizeof(StringInfo));
-
- master_secret->data = ((unsigned char*)master_secret+sizeof(StringInfo));
- session_id->data = ((unsigned char*)session_id+sizeof(StringInfo));
-
- ssl_data_set(session_id, ssl->session_id.data, ssl->session_id.data_len);
- ssl_data_set(master_secret, ssl->master_secret.data, ssl->master_secret.data_len);
- g_hash_table_insert(ssl_session_hash, session_id, master_secret);
- ssl_print_string("ssl_save_session stored session id", session_id);
- ssl_print_string("ssl_save_session stored master secret", master_secret);
-}
+ ssl_set_debug(dtls_debug_file_name);
-static void
-ssl_restore_session(SslDecryptSession* ssl)
-{
- StringInfo* ms = g_hash_table_lookup(ssl_session_hash, &ssl->session_id);
- if (!ms) {
- ssl_debug_printf("ssl_restore_session can't find stored session\n");
- return;
- }
- ssl_data_set(&ssl->master_secret, ms->data, ms->data_len);
- ssl->state |= SSL_MASTER_SECRET;
- ssl_debug_printf("ssl_restore_session master key retrived\n");
+ /* [re] add dtls dissection to default port in openssl 0.9.8b implementation */
+ ssl_association_add(dtls_associations, dtls_handle, 4433, "http", FALSE);
}
-
-/*********************************************************************
- *
- * Forward Declarations
- *
- *********************************************************************/
-
/*
- * SSL version 3 and TLS dissectors
+ * DTLS Dissection Routines
*
*/
+
/* record layer dissector */
-static int dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
+static gint dissect_dtls_record(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, guint32 offset,
- guint *conv_version,
- gboolean *need_desegmentation,
+ guint *conv_version,
SslDecryptSession *conv_data);
/* change cipher spec dissector */
-static void dissect_ssl3_change_cipher_spec(tvbuff_t *tvb,
+static void dissect_dtls_change_cipher_spec(tvbuff_t *tvb,
proto_tree *tree,
guint32 offset,
guint *conv_version, guint8 content_type);
/* alert message dissector */
-static void dissect_ssl3_alert(tvbuff_t *tvb, packet_info *pinfo,
+static void dissect_dtls_alert(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, guint32 offset,
guint *conv_version);
/* handshake protocol dissector */
-static void dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
+static void dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, guint32 offset,
guint32 record_length,
guint *conv_version,
SslDecryptSession *conv_data, guint8 content_type);
-static void dissect_ssl3_hnd_cli_hello(tvbuff_t *tvb,
+static void dissect_dtls_hnd_cli_hello(tvbuff_t *tvb,
proto_tree *tree,
guint32 offset, guint32 length,
SslDecryptSession* ssl);
-static void dissect_ssl3_hnd_hello_verify_request(tvbuff_t *tvb,
- proto_tree *tree,
- guint32 offset, guint32 length,
- SslDecryptSession* ssl);
+static void dissect_dtls_hnd_hello_verify_request(tvbuff_t *tvb,
+ proto_tree *tree,
+ guint32 offset,
+ SslDecryptSession* ssl);
-static void dissect_ssl3_hnd_srv_hello(tvbuff_t *tvb,
+static void dissect_dtls_hnd_srv_hello(tvbuff_t *tvb,
proto_tree *tree,
guint32 offset, guint32 length,
SslDecryptSession* ssl);
-static void dissect_ssl3_hnd_cert(tvbuff_t *tvb,
+static void dissect_dtls_hnd_cert(tvbuff_t *tvb,
proto_tree *tree, guint32 offset, packet_info *pinfo);
-static void dissect_ssl3_hnd_cert_req(tvbuff_t *tvb,
+static void dissect_dtls_hnd_cert_req(tvbuff_t *tvb,
proto_tree *tree,
guint32 offset);
-static void dissect_ssl3_hnd_finished(tvbuff_t *tvb,
+static void dissect_dtls_hnd_finished(tvbuff_t *tvb,
proto_tree *tree,
guint32 offset,
guint* conv_version);
-
-/*
- * SSL version 2 dissectors
- *
- */
-
-/* record layer dissector */
-static int dissect_ssl2_record(tvbuff_t *tvb, packet_info *pinfo,
- proto_tree *tree, guint32 offset,
- guint *conv_version,
- gboolean *need_desegmentation,
- SslDecryptSession* ssl);
-
-/* client hello dissector */
-static void dissect_ssl2_hnd_client_hello(tvbuff_t *tvb,
- proto_tree *tree,
- guint32 offset,
- SslDecryptSession* ssl);
-
-static void dissect_pct_msg_client_hello(tvbuff_t *tvb,
- proto_tree *tree,
- guint32 offset);
-
-/* client master key dissector */
-static void dissect_ssl2_hnd_client_master_key(tvbuff_t *tvb,
- proto_tree *tree,
- guint32 offset);
-static void dissect_pct_msg_client_master_key(tvbuff_t *tvb,
- proto_tree *tree,
- guint32 offset);
-
-/* server hello dissector */
-static void dissect_ssl2_hnd_server_hello(tvbuff_t *tvb,
- proto_tree *tree,
- guint32 offset, packet_info *pinfo);
-static void dissect_pct_msg_server_hello(tvbuff_t *tvb,
- proto_tree *tree,
- guint32 offset, packet_info *pinfo);
-
-
-static void dissect_pct_msg_server_verify(tvbuff_t *tvb,
- proto_tree *tree,
- guint32 offset);
-
-static void dissect_pct_msg_error(tvbuff_t *tvb,
- proto_tree *tree,
- guint32 offset);
-
/*
* Support Functions
*
*/
/*static void ssl_set_conv_version(packet_info *pinfo, guint version);*/
-static int ssl_is_valid_handshake_type(guint8 type);
-static int ssl_is_valid_content_type(guint8 type);
-static int ssl_is_valid_ssl_version(guint16 version);
-static int ssl_is_authoritative_version_message(guint8 content_type,
- guint8 next_byte);
-static int ssl_is_v2_client_hello(tvbuff_t *tvb, guint32 offset);
-static int ssl_looks_like_sslv2(tvbuff_t *tvb, guint32 offset);
-static int ssl_looks_like_sslv3(tvbuff_t *tvb, guint32 offset);
-static int ssl_looks_like_valid_v2_handshake(tvbuff_t *tvb,
- guint32 offset,
- guint32 record_length);
-static int ssl_looks_like_valid_pct_handshake(tvbuff_t *tvb,
- guint32 offset,
- guint32 record_length);
+static gint dtls_is_valid_handshake_type(guint8 type);
+
+static gint dtls_is_authoritative_version_message(guint8 content_type,
+ guint8 next_byte);
+static gint looks_like_dtls(tvbuff_t *tvb, guint32 offset);
+
/*********************************************************************
*
* Main dissector
@@ -662,299 +270,246 @@ static void
dissect_dtls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- conversation_t *conversation;
- void *conv_data;
- proto_item *ti = NULL;
- proto_tree *dtls_tree = NULL;
- guint32 offset = 0;
- gboolean first_record_in_frame = TRUE;
- gboolean need_desegmentation;
- SslDecryptSession* ssl_session = NULL;
- guint* conv_version;
-
- /* Track the version using conversations to reduce the
- * chance that a packet that simply *looks* like a v2 or
- * v3 packet is dissected improperly. This also allows
- * us to more frequently set the protocol column properly
- * for continuation data frames.
- *
- * Also: We use the copy in conv_version as our cached copy,
- * so that we don't have to search the conversation
- * table every time we want the version; when setting
- * the conv_version, must set the copy in the conversation
- * in addition to conv_version
- */
- conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
- pinfo->srcport, pinfo->destport, 0);
- if (!conversation)
+ conversation_t *conversation;
+ void *conv_data;
+ proto_item *ti;
+ proto_tree *dtls_tree;
+ guint32 offset;
+ gboolean first_record_in_frame;
+ SslDecryptSession* ssl_session;
+ guint* conv_version;
+ ti = NULL;
+ dtls_tree = NULL;
+ offset = 0;
+ first_record_in_frame = TRUE;
+ ssl_session = NULL;
+ top_tree=tree;
+
+ /* Track the version using conversations allows
+ * us to more frequently set the protocol column properly
+ * for continuation data frames.
+ *
+ * Also: We use the copy in conv_version as our cached copy,
+ * so that we don't have to search the conversation
+ * table every time we want the version; when setting
+ * the conv_version, must set the copy in the conversation
+ * in addition to conv_version
+ */
+ conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
+ if (!conversation)
{
- /* create a new conversation */
- conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
- pinfo->srcport, pinfo->destport, 0);
+ /* create a new conversation */
+ conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
}
- conv_data = conversation_get_proto_data(conversation, proto_dtls);
+ conv_data = conversation_get_proto_data(conversation, proto_dtls);
- /* PAOLO: manage ssl decryption data */
- /*get a valid ssl session pointer*/
- if (conv_data != NULL)
- ssl_session = conv_data;
- else {
- SslService dummy;
-
- ssl_session = se_alloc0(sizeof(SslDecryptSession));
- ssl_session_init(ssl_session);
- ssl_session->version = SSL_VER_UNKNOWN;
- conversation_add_proto_data(conversation, proto_dtls, ssl_session);
+ /* manage dtls decryption data */
+ /*get a valid ssl session pointer*/
+ if (conv_data != NULL)
+ ssl_session = conv_data;
+ else {
+ SslService dummy;
+
+ ssl_session = se_alloc0(sizeof(SslDecryptSession));
+ ssl_session_init(ssl_session);
+ ssl_session->version = SSL_VER_UNKNOWN;
+ conversation_add_proto_data(conversation, proto_dtls, ssl_session);
- /* we need to know witch side of conversation is speaking*/
- if (ssl_packet_from_server(pinfo->srcport)) {
- dummy.addr = pinfo->src;
- dummy.port = pinfo->srcport;
- }
- else {
- dummy.addr = pinfo->dst;
- dummy.port = pinfo->destport;
- }
- ssl_debug_printf("dissect_ssl server %hhd.%hhd.%hhd.%hhd:%d\n",
- dummy.addr.data[0],
- dummy.addr.data[1],dummy.addr.data[2],
- dummy.addr.data[3],dummy.port);
-
- /* try to retrive private key for this service. Do it now 'cause pinfo
- * is not always available
- * Note that with HAVE_LIBGNUTLS undefined private_key is allways 0
- * and thus decryption never engaged*/
- ssl_session->private_key = g_hash_table_lookup(ssl_key_hash, &dummy);
- if (!ssl_session->private_key)
- ssl_debug_printf("dissect_ssl can't find private key for this server!\n");
+ /* we need to know witch side of conversation is speaking */
+ if (ssl_packet_from_server(dtls_associations, pinfo->srcport)) {
+ dummy.addr = pinfo->src;
+ dummy.port = pinfo->srcport;
+ }
+ else {
+ dummy.addr = pinfo->dst;
+ dummy.port = pinfo->destport;
}
- conv_version= & ssl_session->version;
+ ssl_debug_printf("dissect_dtls server %hhd.%hhd.%hhd.%hhd:%d\n",
+ dummy.addr.data[0],
+ dummy.addr.data[1],dummy.addr.data[2],
+ dummy.addr.data[3],dummy.port);
- /* try decryption only the first time we see this packet
- * (to keep cipher syncronized)and only if we have
- * the server private key*/
- if (!ssl_session->private_key || pinfo->fd->flags.visited)
- ssl_session = NULL;
+ /* try to retrive private key for this service. Do it now 'cause pinfo
+ * is not always available
+ * Note that with HAVE_LIBGNUTLS undefined private_key is allways 0
+ * and thus decryption never engaged*/
+ ssl_session->private_key = g_hash_table_lookup(dtls_key_hash, &dummy);
+ if (!ssl_session->private_key)
+ ssl_debug_printf("dissect_dtls can't find private key for this server!\n");
+ }
+ conv_version= & ssl_session->version;
- /* Initialize the protocol column; we'll set it later when we
- * figure out what flavor of SSL it is (assuming we don't
- * throw an exception before we get the chance to do so). */
- if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ /* try decryption only the first time we see this packet
+ * (to keep cipher syncronized)and only if we have
+ * the server private key*/
+ if (!ssl_session->private_key || pinfo->fd->flags.visited)
+ ssl_session = NULL;
+
+ /* Initialize the protocol column; we'll set it later when we
+ * figure out what flavor of DTLS it is (actually only one
+ version exists). */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
{
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "DTLS");
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "DTLS");
}
- /* clear the the info column */
- if (check_col(pinfo->cinfo, COL_INFO))
- col_clear(pinfo->cinfo, COL_INFO);
-
- /* TCP packets and SSL records are orthogonal.
- * A tcp packet may contain multiple ssl records and an ssl
- * record may be spread across multiple tcp packets.
- *
- * This loop accounts for multiple ssl records in a single
- * frame, but not a single ssl record across multiple tcp
- * packets.
- *
- * Handling the single ssl record across multiple packets
- * may be possible using ethereal conversations, but
- * probably not cleanly. May have to wait for tcp stream
- * reassembly.
- */
+ /* clear the the info column */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
- /* Create display subtree for SSL as a whole */
- if (tree)
+ /* Create display subtree for SSL as a whole */
+ if (tree)
{
- ti = proto_tree_add_item(tree, proto_dtls, tvb, 0, -1, FALSE);
- dtls_tree = proto_item_add_subtree(ti, ett_dtls);
+ ti = proto_tree_add_item(tree, proto_dtls, tvb, 0, -1, FALSE);
+ dtls_tree = proto_item_add_subtree(ti, ett_dtls);
}
- /* iterate through the records in this tvbuff */
- while (tvb_reported_length_remaining(tvb, offset) != 0)
+ /* iterate through the records in this tvbuff */
+ while (tvb_reported_length_remaining(tvb, offset) != 0)
{
- /* on second and subsequent records per frame
- * add a delimiter on info column
- */
- if (!first_record_in_frame
- && check_col(pinfo->cinfo, COL_INFO))
+ /* on second and subsequent records per frame
+ * add a delimiter on info column
+ */
+ if (!first_record_in_frame
+ && check_col(pinfo->cinfo, COL_INFO))
{
- col_append_str(pinfo->cinfo, COL_INFO, ", ");
+ col_append_str(pinfo->cinfo, COL_INFO, ", ");
}
- /*
- * Assume, for now, that this doesn't need desegmentation.
- */
- need_desegmentation = FALSE;
-
- /* first try to dispatch off the cached version
- * known to be associated with the conversation
- */
- switch(*conv_version) {
- case SSL_VER_SSLv2:
- case SSL_VER_PCT:
- offset = dissect_ssl2_record(tvb, pinfo, dtls_tree,
- offset, conv_version,
- &need_desegmentation,
- ssl_session);
- break;
-
- case SSL_VER_SSLv3:
- case SSL_VER_TLS:
- case SSL_VER_DTLS:
- /* the version tracking code works too well ;-)
- * at times, we may visit a v2 client hello after
- * we already know the version of the connection;
- * work around that here by detecting and calling
- * the v2 dissector instead
- */
- if (ssl_is_v2_client_hello(tvb, offset))
- {
- offset = dissect_ssl2_record(tvb, pinfo, dtls_tree,
- offset, conv_version,
- &need_desegmentation,
- ssl_session);
- }
- else
- {
- offset = dissect_ssl3_record(tvb, pinfo, dtls_tree,
- offset, conv_version,
- &need_desegmentation,
- ssl_session);
- }
- break;
+ /* first try to dispatch off the cached version
+ * known to be associated with the conversation
+ */
+ switch(*conv_version) {
+ case SSL_VER_DTLS:
+ offset = dissect_dtls_record(tvb, pinfo, dtls_tree,
+ offset, conv_version,
+ ssl_session);
+ break;
- /* that failed, so apply some heuristics based
- * on this individual packet
- */
- default:
- if (ssl_looks_like_sslv2(tvb, offset))
- {
- /* looks like sslv2 or pct client hello */
- offset = dissect_ssl2_record(tvb, pinfo, dtls_tree,
- offset, conv_version,
- &need_desegmentation,
- ssl_session);
- }
- else if (ssl_looks_like_sslv3(tvb, offset))
- {
- /* looks like sslv3 or tls */
- offset = dissect_ssl3_record(tvb, pinfo, dtls_tree,
- offset, conv_version,
- &need_desegmentation,
- ssl_session);
- }
- else
- {
- /* looks like something unknown, so lump into
- * continuation data
- */
- offset = tvb_length(tvb);
- if (check_col(pinfo->cinfo, COL_INFO))
- col_append_str(pinfo->cinfo, COL_INFO,
- "Continuation Data");
-
- /* Set the protocol column */
- if (check_col(pinfo->cinfo, COL_PROTOCOL))
- {
- col_set_str(pinfo->cinfo, COL_PROTOCOL,
- ssl_version_short_names[*conv_version]);
- }
- }
- break;
- }
+ /* that failed, so apply some heuristics based
+ * on this individual packet
+ */
+ default:
+ if (looks_like_dtls(tvb, offset))
+ {
+ /* looks like dtls */
+ offset = dissect_dtls_record(tvb, pinfo, dtls_tree,
+ offset, conv_version,
+ ssl_session);
+ }
+ else
+ {
+ /* looks like something unknown, so lump into
+ * continuation data
+ */
+ offset = tvb_length(tvb);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO,
+ "Continuation Data");
+
+ /* Set the protocol column */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL,"DTLS");
+ }
+ }
+ break;
+ }
- /* Desegmentation return check */
- if (need_desegmentation)
- return;
- /* set up for next record in frame, if any */
- first_record_in_frame = FALSE;
+ /* set up for next record in frame, if any */
+ first_record_in_frame = FALSE;
}
- tap_queue_packet(dtls_tap, pinfo, (gpointer)proto_dtls);
+ tap_queue_packet(dtls_tap, pinfo, (gpointer)proto_dtls);
}
-static int
-decrypt_ssl3_record(tvbuff_t *tvb, packet_info *pinfo, guint32 offset,
- guint32 record_length, guint8 content_type, SslDecryptSession* ssl,
- gboolean save_plaintext)
+static gint
+decrypt_dtls_record(tvbuff_t *tvb, packet_info *pinfo, guint32 offset,
+ guint32 record_length, guint8 content_type, SslDecryptSession* ssl,
+ gboolean save_plaintext)
{
- int ret = 0;
- int direction;
- SslDecoder* decoder;
-
- /* if we can decrypt and decryption have success
- * add decrypted data to this packet info*/
- ssl_debug_printf("decrypt_ssl3_record: app_data len %d ssl state %X\n",
- record_length, ssl->state);
- if (!(ssl->state & SSL_HAVE_SESSION_KEY)) {
- ssl_debug_printf("decrypt_ssl3_record: no session key\n");
- return ret;
- }
+ gint ret;
+ gint direction;
+ SslDecoder* decoder;
+ ret = 0;
+
+ /* if we can decrypt and decryption have success
+ * add decrypted data to this packet info */
+ ssl_debug_printf("decrypt_dtls_record: app_data len %d ssl state %X\n",
+ record_length, ssl->state);
+ if (!(ssl->state & SSL_HAVE_SESSION_KEY)) {
+ ssl_debug_printf("decrypt_dtls_record: no session key\n");
+ return ret;
+ }
- /* retrive decoder for this packet direction*/
- if ((direction = ssl_packet_from_server(pinfo->srcport)) != 0) {
- ssl_debug_printf("decrypt_ssl3_record: using server decoder\n");
- decoder = &ssl->server;
- }
- else {
- ssl_debug_printf("decrypt_ssl3_record: using client decoder\n");
- decoder = &ssl->client;
- }
+ /* retrive decoder for this packet direction */
+ if ((direction = ssl_packet_from_server(dtls_associations, pinfo->srcport)) != 0) {
+ ssl_debug_printf("decrypt_dtls_record: using server decoder\n");
+ decoder = &ssl->server;
+ }
+ else {
+ ssl_debug_printf("decrypt_dtls_record: using client decoder\n");
+ decoder = &ssl->client;
+ }
- /* ensure we have enough storage space for decrypted data */
- if (record_length > ssl_decrypted_data.data_len)
+ /* ensure we have enough storage space for decrypted data */
+ if (record_length > dtls_decrypted_data.data_len)
{
- ssl_debug_printf("decrypt_ssl3_record: allocating %d bytes"
- " for decrypt data (old len %d)\n",
- record_length + 32, ssl_decrypted_data.data_len);
- ssl_decrypted_data.data = g_realloc(ssl_decrypted_data.data,
- record_length + 32);
- ssl_decrypted_data.data_len = record_length + 32;
+ ssl_debug_printf("decrypt_dtls_record: allocating %d bytes"
+ " for decrypt data (old len %d)\n",
+ record_length + 32, dtls_decrypted_data.data_len);
+ dtls_decrypted_data.data = g_realloc(dtls_decrypted_data.data,
+ record_length + 32);
+ dtls_decrypted_data.data_len = record_length + 32;
}
- /* run decryption and add decrypted payload to protocol data, if decryption
- * is successful*/
- ssl_decrypted_data_avail = ssl_decrypted_data.data_len;
- if (ssl_decrypt_record(ssl, decoder,
- content_type, tvb_get_ptr(tvb, offset, record_length),
- record_length, ssl_decrypted_data.data, &ssl_decrypted_data_avail) == 0)
- ret = 1;
- if (ret && save_plaintext)
- {
- SslPacketInfo* pi = p_get_proto_data(pinfo->fd, proto_dtls);
- if (!pi)
+ /* run decryption and add decrypted payload to protocol data, if decryption
+ * is successful*/
+ dtls_decrypted_data_avail = dtls_decrypted_data.data_len;
+ if (ssl_decrypt_record(ssl, decoder,
+ content_type, tvb_get_ptr(tvb, offset, record_length),
+ record_length, dtls_decrypted_data.data, &dtls_decrypted_data_avail) == 0)
+ ret = 1;
+ if (ret && save_plaintext)
+ {
+ SslPacketInfo* pi;
+ pi = p_get_proto_data(pinfo->fd, proto_dtls);
+
+ if (!pi)
{
- ssl_debug_printf("decrypt_ssl3_record: allocating app_data %d "
- "bytes for app data\n", ssl_decrypted_data_avail);
- /* first app data record: allocate and put packet data*/
- pi = se_alloc0(sizeof(SslPacketInfo));
- pi->app_data.data = se_alloc(ssl_decrypted_data_avail);
- pi->app_data.data_len = ssl_decrypted_data_avail;
- memcpy(pi->app_data.data, ssl_decrypted_data.data, ssl_decrypted_data_avail);
+ ssl_debug_printf("decrypt_dtls_record: allocating app_data %d "
+ "bytes for app data\n", dtls_decrypted_data_avail);
+ /* first app data record: allocate and put packet data*/
+ pi = se_alloc0(sizeof(SslPacketInfo));
+ pi->app_data.data = se_alloc(dtls_decrypted_data_avail);
+ pi->app_data.data_len = dtls_decrypted_data_avail;
+ memcpy(pi->app_data.data, dtls_decrypted_data.data, dtls_decrypted_data_avail);
}
- else {
- unsigned char* store;
- /* update previus record*/
- ssl_debug_printf("decrypt_ssl3_record: reallocating app_data "
- "%d bytes for app data (total %d appdata bytes)\n",
- ssl_decrypted_data_avail, pi->app_data.data_len + ssl_decrypted_data_avail);
- store = se_alloc(pi->app_data.data_len + ssl_decrypted_data_avail);
- memcpy(store, pi->app_data.data, pi->app_data.data_len);
- memcpy(&store[pi->app_data.data_len], ssl_decrypted_data.data, ssl_decrypted_data_avail);
- pi->app_data.data_len += (ssl_decrypted_data_avail);
+ else {
+ guchar* store;
+ /* update previus record*/
+ ssl_debug_printf("decrypt_dtls_record: reallocating app_data "
+ "%d bytes for app data (total %d appdata bytes)\n",
+ dtls_decrypted_data_avail, pi->app_data.data_len + dtls_decrypted_data_avail);
+ store = se_alloc(pi->app_data.data_len + dtls_decrypted_data_avail);
+ memcpy(store, pi->app_data.data, pi->app_data.data_len);
+ memcpy(&store[pi->app_data.data_len], dtls_decrypted_data.data, dtls_decrypted_data_avail);
+ pi->app_data.data_len += (dtls_decrypted_data_avail);
- /* old decrypted data ptr here appare to be leaked, but it's
- * collected by emem allocator */
- pi->app_data.data = store;
+ /* old decrypted data ptr here appare to be leaked, but it's
+ * collected by emem allocator */
+ pi->app_data.data = store;
- /* data ptr is changed, so remove old one and re-add the new one*/
- ssl_debug_printf("decrypt_ssl3_record: removing old app_data ptr\n");
- p_remove_proto_data(pinfo->fd, proto_dtls);
- }
+ /* data ptr is changed, so remove old one and re-add the new one*/
+ ssl_debug_printf("decrypt_dtls_record: removing old app_data ptr\n");
+ p_remove_proto_data(pinfo->fd, proto_dtls);
+ }
- ssl_debug_printf("decrypt_ssl3_record: setting decrypted app_data ptr %p\n",pi);
- p_add_proto_data(pinfo->fd, proto_dtls, pi);
+ ssl_debug_printf("decrypt_dtls_record: setting decrypted app_data ptr %p\n",pi);
+ p_add_proto_data(pinfo->fd, proto_dtls, pi);
}
- return ret;
+ return ret;
}
@@ -963,469 +518,392 @@ decrypt_ssl3_record(tvbuff_t *tvb, packet_info *pinfo, guint32 offset,
/*********************************************************************
*
- * SSL version 3 and TLS Dissection Routines
+ * DTLS Dissection Routines
*
*********************************************************************/
-static int
-dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
+static gint
+dissect_dtls_record(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, guint32 offset,
- guint *conv_version, gboolean *need_desegmentation,
+ guint *conv_version,
SslDecryptSession* ssl)
{
- /*
- * struct {
- * uint8 major, minor;
- * } ProtocolVersion;
- *
- *
- * enum {
- * change_cipher_spec(20), alert(21), handshake(22),
- * application_data(23), (255)
- * } ContentType;
- *
- * struct {
- * ContentType type;
- * ProtocolVersion version;
- * uint16 epoch; // New field
- * uint48 sequence_number; // New field
- * uint16 length;
- * opaque fragment[TLSPlaintext.length];
- * } TLSPlaintext;
- */
- guint32 record_length;
- guint16 version;
- guint16 epoch;
- gdouble sequence_number;
- gint64 sequence_number_temp;
-
- guint8 content_type;
- guint8 next_byte;
- proto_tree *ti = NULL;
- proto_tree *dtls_record_tree = NULL;
- guint32 available_bytes = 0;
- SslPacketInfo* pi;
- SslAssociation* association;
-
- available_bytes = tvb_length_remaining(tvb, offset);
-
- /*
- * Can we do reassembly?
- */
- if (ssl_desegment && pinfo->can_desegment) {
- /*
- * Yes - is the record header split across segment boundaries?
- */
- if (available_bytes < 13) {
- /*
- * Yes. Tell the TCP dissector where the data for this
- * message starts in the data it handed us, and how many
- * more bytes we need, and return.
- */
- pinfo->desegment_offset = offset;
- pinfo->desegment_len = 13 - available_bytes;
- *need_desegmentation = TRUE;
- return offset;
- }
- }
-
- /*
- * Get the record layer fields of interest
- */
- content_type = tvb_get_guint8(tvb, offset);
- version = tvb_get_ntohs(tvb, offset + 1);
- epoch = tvb_get_ntohs(tvb, offset + 3);
- sequence_number = tvb_get_ntohl(tvb, offset + 7);
- sequence_number_temp=tvb_get_ntohs(tvb, offset + 5);
- sequence_number_temp=sequence_number_temp<<32;
- sequence_number+=sequence_number_temp;
- record_length = tvb_get_ntohs(tvb, offset + 11);
-
- if(ssl){
- if(ssl_packet_from_server(pinfo->srcport)){
- ssl->server.seq=sequence_number;
- ssl->server.epoch=epoch;
- }
- else{
- ssl->client.seq=sequence_number;
- ssl->client.epoch=epoch;
- }
- }
- if (ssl_is_valid_content_type(content_type)) {
-
- /*
- * Can we do reassembly?
- */
- if (ssl_desegment && pinfo->can_desegment) {
- /*
- * Yes - is the record split across segment boundaries?
- */
- if (available_bytes < record_length + 13) {
- /*
- * Yes. Tell the TCP dissector where the data for this
- * message starts in the data it handed us, and how many
- * more bytes we need, and return.
- */
- pinfo->desegment_offset = offset;
- pinfo->desegment_len = (record_length + 13) - available_bytes;
- *need_desegmentation = TRUE;
- return offset;
- }
- }
-
- } else {
-
+ /*
+ * struct {
+ * uint8 major, minor;
+ * } ProtocolVersion;
+ *
+ *
+ * enum {
+ * change_cipher_spec(20), alert(21), handshake(22),
+ * application_data(23), (255)
+ * } ContentType;
+ *
+ * struct {
+ * ContentType type;
+ * ProtocolVersion version;
+ * uint16 epoch; // New field
+ * uint48 sequence_number; // New field
+ * uint16 length;
+ * opaque fragment[TLSPlaintext.length];
+ * } DTLSPlaintext;
+ */
+ guint32 record_length;
+ guint16 version;
+ guint16 epoch;
+ gdouble sequence_number;
+ gint64 sequence_number_temp;
+ guint8 content_type;
+ guint8 next_byte;
+ proto_tree *ti;
+ proto_tree *dtls_record_tree;
+ guint32 available_bytes;
+ SslPacketInfo* pi;
+ SslAssociation* association;
+ ti = NULL;
+ dtls_record_tree = NULL;
+ available_bytes = tvb_length_remaining(tvb, offset);
+
+ /*
+ * Get the record layer fields of interest
+ */
+ content_type = tvb_get_guint8(tvb, offset);
+ version = tvb_get_ntohs(tvb, offset + 1);
+ epoch = tvb_get_ntohs(tvb, offset + 3);
+ sequence_number = tvb_get_ntohl(tvb, offset + 7);
+ sequence_number_temp=tvb_get_ntohs(tvb, offset + 5);
+ sequence_number_temp=sequence_number_temp<<32;
+ sequence_number+=sequence_number_temp;
+ record_length = tvb_get_ntohs(tvb, offset + 11);
+
+ if(ssl){
+ if(ssl_packet_from_server(dtls_associations, pinfo->srcport)){
+ ssl->server.seq=sequence_number;
+ ssl->server.epoch=epoch;
+ }
+ else{
+ ssl->client.seq=sequence_number;
+ ssl->client.epoch=epoch;
+ }
+ }
+ if (!ssl_is_valid_content_type(content_type)) {
+
/* if we don't have a valid content_type, there's no sense
* continuing any further
*/
- if (check_col(pinfo->cinfo, COL_INFO))
- col_append_str(pinfo->cinfo, COL_INFO, "Continuation Data");
-
- /* Set the protocol column */
- if (check_col(pinfo->cinfo, COL_PROTOCOL))
- {
- col_set_str(pinfo->cinfo, COL_PROTOCOL,
- ssl_version_short_names[*conv_version]);
- }
- return offset + 13 + record_length;
- }
-
- /*
- * If GUI, fill in record layer part of tree
- */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "Continuation Data");
- if (tree)
+ /* Set the protocol column */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
{
- /* add the record layer subtree header */
- tvb_ensure_bytes_exist(tvb, offset, 13 + record_length);
- ti = proto_tree_add_item(tree, hf_dtls_record, tvb,
- offset, 13 + record_length, 0);
- dtls_record_tree = proto_item_add_subtree(ti, ett_dtls_record);
+ col_set_str(pinfo->cinfo, COL_PROTOCOL,"DTLS");
}
+ return offset + 13 + record_length;
+ }
+
+ /*
+ * If GUI, fill in record layer part of tree
+ */
+
+ if (tree)
+ {
+ /* add the record layer subtree header */
+ tvb_ensure_bytes_exist(tvb, offset, 13 + record_length);
+ ti = proto_tree_add_item(tree, hf_dtls_record, tvb,
+ offset, 13 + record_length, 0);
+ dtls_record_tree = proto_item_add_subtree(ti, ett_dtls_record);
+ }
- if (dtls_record_tree)
+ if (dtls_record_tree)
{
- /* show the one-byte content type */
- proto_tree_add_item(dtls_record_tree, hf_dtls_record_content_type,
- tvb, offset, 1, FALSE);
- offset++;
-
- /* add the version */
- proto_tree_add_item(dtls_record_tree, hf_dtls_record_version, tvb,
- offset, 2, FALSE);
- offset += 2;
+ /* show the one-byte content type */
+ proto_tree_add_item(dtls_record_tree, hf_dtls_record_content_type,
+ tvb, offset, 1, FALSE);
+ offset++;
- /* show epoch */
- proto_tree_add_uint(dtls_record_tree, hf_dtls_record_epoch, tvb, offset, 2, epoch);
+ /* add the version */
+ proto_tree_add_item(dtls_record_tree, hf_dtls_record_version, tvb,
+ offset, 2, FALSE);
+ offset += 2;
- offset += 2;
+ /* show epoch */
+ proto_tree_add_uint(dtls_record_tree, hf_dtls_record_epoch, tvb, offset, 2, epoch);
- /* add sequence_number */
+ offset += 2;
- proto_tree_add_double(dtls_record_tree, hf_dtls_record_sequence_number, tvb, offset, 6, sequence_number);
+ /* add sequence_number */
- offset += 6;
+ proto_tree_add_double(dtls_record_tree, hf_dtls_record_sequence_number, tvb, offset, 6, sequence_number);
- /* add the length */
- proto_tree_add_uint(dtls_record_tree, hf_dtls_record_length, tvb,
- offset, 2, record_length);
- offset += 2; /* move past length field itself */
+ offset += 6;
+ /* add the length */
+ proto_tree_add_uint(dtls_record_tree, hf_dtls_record_length, tvb,
+ offset, 2, record_length);
+ offset += 2; /* move past length field itself */
}
- else
+ else
{
- /* if no GUI tree, then just skip over those fields */
- offset += 13;
+ /* if no GUI tree, then just skip over those fields */
+ offset += 13;
}
-
- /*
- * if we don't already have a version set for this conversation,
- * but this message's version is authoritative (i.e., it's
- * not client_hello, then save the version to to conversation
- * structure and print the column version
- */
- next_byte = tvb_get_guint8(tvb, offset);
- if (*conv_version == SSL_VER_UNKNOWN
- && ssl_is_authoritative_version_message(content_type, next_byte))
+ /*
+ * if we don't already have a version set for this conversation,
+ * but this message's version is authoritative (i.e., it's
+ * not client_hello, then save the version to to conversation
+ * structure and print the column version
+ */
+ next_byte = tvb_get_guint8(tvb, offset);
+ if (*conv_version == SSL_VER_UNKNOWN
+ && dtls_is_authoritative_version_message(content_type, next_byte))
{
- if (version == SSLV3_VERSION)
- {
- *conv_version = SSL_VER_SSLv3;
- if (ssl) {
- ssl->version_netorder = version;
- ssl->state |= SSL_VERSION;
- }
- /*ssl_set_conv_version(pinfo, ssl->version);*/
- }
- else if (version == TLSV1_VERSION)
- {
-
- *conv_version = SSL_VER_TLS;
- if (ssl) {
- ssl->version_netorder = version;
- ssl->state |= SSL_VERSION;
- }
- /*ssl_set_conv_version(pinfo, ssl->version);*/
- }
- else if (version == TLSV1DOT1_VERSION)
- {
-
- *conv_version = SSL_VER_TLSv1DOT1;
- if (ssl) {
- ssl->version_netorder = version;
- ssl->state |= SSL_VERSION;
- }
- /*ssl_set_conv_version(pinfo, ssl->version);*/
- }
- else if (version == DTLSV1DOT0_VERSION)
+ if (version == DTLSV1DOT0_VERSION)
{
- *conv_version = SSL_VER_DTLS;
- if (ssl) {
- ssl->version_netorder = version;
- ssl->state |= SSL_VERSION;
- }
- /*ssl_set_conv_version(pinfo, ssl->version);*/
+ *conv_version = SSL_VER_DTLS;
+ if (ssl) {
+ ssl->version_netorder = version;
+ ssl->state |= SSL_VERSION;
+ }
+ /*ssl_set_conv_version(pinfo, ssl->version);*/
}
}
- if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
{
- if (version == DTLSV1DOT0_VERSION)
+ if (version == DTLSV1DOT0_VERSION)
{
- col_set_str(pinfo->cinfo, COL_PROTOCOL,
- ssl_version_short_names[SSL_VER_DTLS]);
+ col_set_str(pinfo->cinfo, COL_PROTOCOL,
+ ssl_version_short_names[SSL_VER_DTLS]);
}
- else
+ else
{
- col_set_str(pinfo->cinfo, COL_PROTOCOL,
- ssl_version_short_names[*conv_version]);
+ col_set_str(pinfo->cinfo, COL_PROTOCOL,"DTLS");
}
}
- /*
- * now dissect the next layer
- */
- ssl_debug_printf("dissect_ssl3_record: content_type %d\n",content_type);
+ /*
+ * now dissect the next layer
+ */
+ ssl_debug_printf("dissect_dtls_record: content_type %d\n",content_type);
- /* PAOLO try to decrypt each record (we must keep ciphers "in sync")
- * store plain text only for app data */
-
- switch (content_type) {
- case SSL_ID_CHG_CIPHER_SPEC:
- if (check_col(pinfo->cinfo, COL_INFO))
- col_append_str(pinfo->cinfo, COL_INFO, "Change Cipher Spec");
- dissect_ssl3_change_cipher_spec(tvb, dtls_record_tree,
- offset, conv_version, content_type);
- ssl_debug_printf("dissect_ssl3_change_cipher_spec\n");
- break;
- case SSL_ID_ALERT:
- {
- tvbuff_t* decrypted=0;
- if (ssl&&decrypt_ssl3_record(tvb, pinfo, offset,
- record_length, content_type, ssl, FALSE))
- ssl_add_record_info(pinfo, ssl_decrypted_data.data,
- ssl_decrypted_data_avail, offset);
-
- /* try to retrive and use decrypted alert record, if any. */
- decrypted = ssl_get_record_info(pinfo, offset);
- if (decrypted)
- dissect_ssl3_alert(decrypted, pinfo, dtls_record_tree, 0,
- conv_version);
- else
- dissect_ssl3_alert(tvb, pinfo, dtls_record_tree, offset,
- conv_version);
- break;
- }
- case SSL_ID_HANDSHAKE:
- {
- tvbuff_t* decrypted=0;
- /* try to decrypt handshake record, if possible. Store decrypted
- * record for later usage. The offset is used as 'key' to itentify
- * this record into the packet (we can have multiple handshake records
- * in the same frame) */
- if (ssl && decrypt_ssl3_record(tvb, pinfo, offset,
- record_length, content_type, ssl, FALSE))
- ssl_add_record_info(pinfo, ssl_decrypted_data.data,
- ssl_decrypted_data_avail, offset);
+ /* PAOLO try to decrypt each record (we must keep ciphers "in sync")
+ * store plain text only for app data */
+
+ switch (content_type) {
+ case SSL_ID_CHG_CIPHER_SPEC:
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "Change Cipher Spec");
+ dissect_dtls_change_cipher_spec(tvb, dtls_record_tree,
+ offset, conv_version, content_type);
+ break;
+ case SSL_ID_ALERT:
+ {
+ tvbuff_t* decrypted;
+ decrypted = 0;
+ if (ssl&&decrypt_dtls_record(tvb, pinfo, offset,
+ record_length, content_type, ssl, FALSE))
+ ssl_add_record_info(proto_dtls, pinfo, dtls_decrypted_data.data,
+ dtls_decrypted_data_avail, offset);
+
+ /* try to retrive and use decrypted alert record, if any. */
+ decrypted = ssl_get_record_info(proto_dtls, pinfo, offset);
+ if (decrypted)
+ dissect_dtls_alert(decrypted, pinfo, dtls_record_tree, 0,
+ conv_version);
+ else
+ dissect_dtls_alert(tvb, pinfo, dtls_record_tree, offset,
+ conv_version);
+ break;
+ }
+ case SSL_ID_HANDSHAKE:
+ {
+ tvbuff_t* decrypted;
+ decrypted = 0;
+ /* try to decrypt handshake record, if possible. Store decrypted
+ * record for later usage. The offset is used as 'key' to itentify
+ * this record into the packet (we can have multiple handshake records
+ * in the same frame) */
+ if (ssl && decrypt_dtls_record(tvb, pinfo, offset,
+ record_length, content_type, ssl, FALSE))
+ ssl_add_record_info(proto_dtls, pinfo, dtls_decrypted_data.data,
+ dtls_decrypted_data_avail, offset);
- /* try to retrive and use decrypted handshake record, if any. */
- decrypted = ssl_get_record_info(pinfo, offset);
- if (decrypted)
- dissect_ssl3_handshake(decrypted, pinfo, dtls_record_tree, 0,
- decrypted->length, conv_version, ssl, content_type);
- else
- dissect_ssl3_handshake(tvb, pinfo, dtls_record_tree, offset,
+ /* try to retrive and use decrypted handshake record, if any. */
+ decrypted = ssl_get_record_info(proto_dtls, pinfo, offset);
+ if (decrypted)
+ dissect_dtls_handshake(decrypted, pinfo, dtls_record_tree, 0,
+ decrypted->length, conv_version, ssl, content_type);
+ else
+ dissect_dtls_handshake(tvb, pinfo, dtls_record_tree, offset,
record_length, conv_version, ssl, content_type);
- break;
+ break;
}
- case SSL_ID_APP_DATA:
- if (ssl)
- decrypt_ssl3_record(tvb, pinfo, offset,
- record_length, content_type, ssl, TRUE);
+ case SSL_ID_APP_DATA:
+ if (ssl)
+ decrypt_dtls_record(tvb, pinfo, offset,
+ record_length, content_type, ssl, TRUE);
- /* show on info colum what we are decoding */
- if (check_col(pinfo->cinfo, COL_INFO))
- col_append_str(pinfo->cinfo, COL_INFO, "Application Data");
+ /* show on info colum what we are decoding */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "Application Data");
- if (!dtls_record_tree)
- break;
+ if (!dtls_record_tree)
+ break;
- /* 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(pinfo->srcport);
- association = association ? association: ssl_association_find(pinfo->destport);
-
- proto_item_set_text(dtls_record_tree,
- "%s Record Layer: %s Protocol: %s",
- ssl_version_short_names[*conv_version],
- val_to_str(content_type, ssl_31_content_type, "unknown"),
- association?association->info:"Application Data");
+ /* 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);
+
+ proto_item_set_text(dtls_record_tree,
+ "%s Record Layer: %s Protocol: %s",
+ ssl_version_short_names[*conv_version],
+ val_to_str(content_type, ssl_31_content_type, "unknown"),
+ association?association->info:"Application Data");
- /* show decrypted data info, if available */
- pi = p_get_proto_data(pinfo->fd, proto_dtls);
- if (pi && pi->app_data.data)
- {
- tvbuff_t* new_tvb;
+ proto_tree_add_item(dtls_record_tree, hf_dtls_record_appdata, tvb,
+ offset, record_length, 0);
+
+ /* show decrypted data info, if available */
+ pi = p_get_proto_data(pinfo->fd, proto_dtls);
+ if (pi && pi->app_data.data)
+ {
+ tvbuff_t* new_tvb;
- /* try to dissect decrypted data*/
- ssl_debug_printf("dissect_ssl3_record decrypted len %d\n",
- pi->app_data.data_len);
+ /* try to dissect decrypted data*/
+ ssl_debug_printf("dissect_dtls_record decrypted len %d\n",
+ pi->app_data.data_len);
- /* create new tvbuff for the decrypted data */
- new_tvb = tvb_new_real_data(pi->app_data.data,
- pi->app_data.data_len, pi->app_data.data_len);
- tvb_set_free_cb(new_tvb, g_free);
- /* tvb_set_child_real_data_tvbuff(tvb, new_tvb); */
+ /* create new tvbuff for the decrypted data */
+ new_tvb = tvb_new_real_data(pi->app_data.data,
+ pi->app_data.data_len, pi->app_data.data_len);
+ tvb_set_free_cb(new_tvb, g_free);
+ /* tvb_set_child_real_data_tvbuff(tvb, new_tvb); */
- /* find out a dissector using server port*/
- if (association && association->handle) {
- ssl_debug_printf("dissect_ssl3_record found association %p\n", association);
- ssl_print_text_data("decrypted app data",pi->app_data.data,
- pi->app_data.data_len);
+ add_new_data_source(pinfo, new_tvb, "Decrypted DTLS data");
+
+ /* find out a dissector using server port*/
+ if (association && association->handle) {
+ ssl_debug_printf("dissect_dtls_record found association %p\n", association);
+ ssl_print_text_data("decrypted app data",pi->app_data.data,
+ pi->app_data.data_len);
- call_dissector(association->handle, new_tvb, pinfo, dtls_record_tree);
- }
- /* add raw decrypted data only if a decoder is not found*/
- else
- proto_tree_add_string(dtls_record_tree, hf_dtls_record_appdata_decrypted, tvb,
- offset, pi->app_data.data_len, (char*) pi->app_data.data);
- }
- else {
- tvb_ensure_bytes_exist(tvb, offset, record_length);
- proto_tree_add_item(dtls_record_tree, hf_dtls_record_appdata, tvb,
- offset, record_length, 0);
- }
- break;
-
- default:
- /* shouldn't get here since we check above for valid types */
- if (check_col(pinfo->cinfo, COL_INFO))
- col_append_str(pinfo->cinfo, COL_INFO, "Bad SSLv3 Content Type");
- break;
- }
- offset += record_length; /* skip to end of record */
+ call_dissector(association->handle, new_tvb, pinfo, top_tree);
+ }
+ }
+ break;
- return offset;
+ default:
+ /* shouldn't get here since we check above for valid types */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "Bad DTLS Content Type");
+ break;
+ }
+ offset += record_length; /* skip to end of record */
+
+ return offset;
}
/* dissects the change cipher spec procotol, filling in the tree */
static void
-dissect_ssl3_change_cipher_spec(tvbuff_t *tvb,
+dissect_dtls_change_cipher_spec(tvbuff_t *tvb,
proto_tree *tree, guint32 offset,
guint* conv_version, guint8 content_type)
{
- /*
- * struct {
- * enum { change_cipher_spec(1), (255) } type;
- * } ChangeCipherSpec;
- *
- */
- if (tree)
+ /*
+ * struct {
+ * enum { change_cipher_spec(1), (255) } type;
+ * } ChangeCipherSpec;
+ *
+ */
+ if (tree)
{
- proto_item_set_text(tree,
- "%s Record Layer: %s Protocol: Change Cipher Spec",
- ssl_version_short_names[*conv_version],
- val_to_str(content_type, ssl_31_content_type, "unknown"));
- proto_tree_add_item(tree, hf_dtls_change_cipher_spec, tvb,
- offset++, 1, FALSE);
+ proto_item_set_text(tree,
+ "%s Record Layer: %s Protocol: Change Cipher Spec",
+ ssl_version_short_names[*conv_version],
+ val_to_str(content_type, ssl_31_content_type, "unknown"));
+ proto_tree_add_item(tree, hf_dtls_change_cipher_spec, tvb,
+ offset++, 1, FALSE);
}
}
/* dissects the alert message, filling in the tree */
static void
-dissect_ssl3_alert(tvbuff_t *tvb, packet_info *pinfo,
+dissect_dtls_alert(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, guint32 offset,
guint* conv_version)
{
- /* struct {
- * AlertLevel level;
- * AlertDescription description;
- * } Alert;
- */
- proto_tree *ti;
- proto_tree *ssl_alert_tree = NULL;
- const gchar *level;
- const gchar *desc;
- guint8 byte;
+ /* struct {
+ * AlertLevel level;
+ * AlertDescription description;
+ * } Alert;
+ */
+ proto_tree *ti;
+ proto_tree *ssl_alert_tree;
+ const gchar *level;
+ const gchar *desc;
+ guint8 byte;
+ ssl_alert_tree = NULL;
- if (tree)
+ if (tree)
{
- ti = proto_tree_add_item(tree, hf_dtls_alert_message, tvb,
- offset, 2, 0);
- ssl_alert_tree = proto_item_add_subtree(ti, ett_dtls_alert);
+ ti = proto_tree_add_item(tree, hf_dtls_alert_message, tvb,
+ offset, 2, 0);
+ ssl_alert_tree = proto_item_add_subtree(ti, ett_dtls_alert);
}
- /*
- * set the record layer label
- */
+ /*
+ * set the record layer label
+ */
- /* first lookup the names for the alert level and description */
- byte = tvb_get_guint8(tvb, offset); /* grab the level byte */
- level = match_strval(byte, ssl_31_alert_level);
+ /* first lookup the names for the alert level and description */
+ byte = tvb_get_guint8(tvb, offset); /* grab the level byte */
+ level = match_strval(byte, ssl_31_alert_level);
- byte = tvb_get_guint8(tvb, offset+1); /* grab the desc byte */
- desc = match_strval(byte, ssl_31_alert_description);
+ byte = tvb_get_guint8(tvb, offset+1); /* grab the desc byte */
+ desc = match_strval(byte, ssl_31_alert_description);
- /* now set the text in the record layer line */
- if (level && desc)
+ /* now set the text in the record layer line */
+ if (level && desc)
{
- if (check_col(pinfo->cinfo, COL_INFO))
- col_append_fstr(pinfo->cinfo, COL_INFO,
- "Alert (Level: %s, Description: %s)",
- level, desc);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO,
+ "Alert (Level: %s, Description: %s)",
+ level, desc);
}
- else
+ else
{
- if (check_col(pinfo->cinfo, COL_INFO))
- col_append_str(pinfo->cinfo, COL_INFO, "Encrypted Alert");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_str(pinfo->cinfo, COL_INFO, "Encrypted Alert");
}
- if (tree)
+ if (tree)
{
- if (level && desc)
+ if (level && desc)
{
- proto_item_set_text(tree, "%s Record Layer: Alert "
- "(Level: %s, Description: %s)",
- ssl_version_short_names[*conv_version],
- level, desc);
- proto_tree_add_item(ssl_alert_tree, hf_dtls_alert_message_level,
- tvb, offset++, 1, FALSE);
-
- proto_tree_add_item(ssl_alert_tree, hf_dtls_alert_message_description,
- tvb, offset++, 1, FALSE);
+ proto_item_set_text(tree, "%s Record Layer: Alert "
+ "(Level: %s, Description: %s)",
+ ssl_version_short_names[*conv_version],
+ level, desc);
+ proto_tree_add_item(ssl_alert_tree, hf_dtls_alert_message_level,
+ tvb, offset++, 1, FALSE);
+
+ proto_tree_add_item(ssl_alert_tree, hf_dtls_alert_message_description,
+ tvb, offset++, 1, FALSE);
}
- else
+ else
{
- proto_item_set_text(tree,
- "%s Record Layer: Encrypted Alert",
- ssl_version_short_names[*conv_version]);
- proto_item_set_text(ssl_alert_tree,
- "Alert Message: Encrypted Alert");
+ proto_item_set_text(tree,
+ "%s Record Layer: Encrypted Alert",
+ ssl_version_short_names[*conv_version]);
+ proto_item_set_text(ssl_alert_tree,
+ "Alert Message: Encrypted Alert");
}
}
}
@@ -1433,522 +911,528 @@ dissect_ssl3_alert(tvbuff_t *tvb, packet_info *pinfo,
/* dissects the handshake protocol, filling the tree */
static void
-dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
+dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, guint32 offset,
guint32 record_length, guint *conv_version,
SslDecryptSession* ssl, guint8 content_type)
{
- /* struct {
- * HandshakeType msg_type;
- * uint24 length;
- * uint16 message_seq; //new field
- * uint24 fragment_offset; //new field
- * uint24 fragment_length; //new field
- * select (HandshakeType) {
- * case hello_request: HelloRequest;
- * case client_hello: ClientHello;
- * case server_hello: ServerHello;
- * case hello_verify_request: HelloVerifyRequest; //new field
- * case certificate: Certificate;
- * case server_key_exchange: ServerKeyExchange;
- * case certificate_request: CertificateRequest;
- * case server_hello_done: ServerHelloDone;
- * case certificate_verify: CertificateVerify;
- * case client_key_exchange: ClientKeyExchange;
- * case finished: Finished;
- * } body;
- * } Handshake;
- */
- proto_tree *ti = NULL;
- proto_tree *ssl_hand_tree = NULL;
- const gchar *msg_type_str = NULL;
- guint8 msg_type;
- guint32 length;
- guint16 message_seq;
- guint32 fragment_offset;
- guint32 fragment_length;
-
- gboolean first_iteration = TRUE;
-
-
- /* just as there can be multiple records per packet, there
- * can be multiple messages per record as long as they have
- * the same content type
- *
- * we really only care about this for handshake messages
- */
+ /* struct {
+ * HandshakeType msg_type;
+ * uint24 length;
+ * uint16 message_seq; //new field
+ * uint24 fragment_offset; //new field
+ * uint24 fragment_length; //new field
+ * select (HandshakeType) {
+ * case hello_request: HelloRequest;
+ * case client_hello: ClientHello;
+ * case server_hello: ServerHello;
+ * case hello_verify_request: HelloVerifyRequest; //new field
+ * case certificate: Certificate;
+ * case server_key_exchange: ServerKeyExchange;
+ * case certificate_request: CertificateRequest;
+ * case server_hello_done: ServerHelloDone;
+ * case certificate_verify: CertificateVerify;
+ * case client_key_exchange: ClientKeyExchange;
+ * case finished: Finished;
+ * } body;
+ * } Handshake;
+ */
+ proto_tree *ti;
+ proto_tree *ssl_hand_tree;
+ const gchar *msg_type_str;
+ guint8 msg_type;
+ guint32 length;
+ guint16 message_seq;
+ guint32 fragment_offset;
+ guint32 fragment_length;
+ gboolean first_iteration;
+ ti = NULL;
+ ssl_hand_tree = NULL;
+ msg_type_str = NULL;
+ first_iteration = TRUE;
+
+ /* just as there can be multiple records per packet, there
+ * can be multiple messages per record as long as they have
+ * the same content type
+ *
+ * we really only care about this for handshake messages
+ */
- /* set record_length to the max offset */
- record_length += offset;
- while (offset < record_length)
- {
- msg_type = tvb_get_guint8(tvb, offset);
- msg_type_str = match_strval(msg_type, ssl_31_handshake_type);
- length = tvb_get_ntoh24(tvb, offset + 1);
- message_seq = tvb_get_ntohs(tvb,offset + 4);
- fragment_offset = tvb_get_ntoh24(tvb, offset + 6);
- fragment_length = tvb_get_ntoh24(tvb, offset + 9);
+ /* set record_length to the max offset */
+ record_length += offset;
+ while (offset < record_length)
+ {
+ msg_type = tvb_get_guint8(tvb, offset);
+ msg_type_str = match_strval(msg_type, ssl_31_handshake_type);
+ length = tvb_get_ntoh24(tvb, offset + 1);
+ message_seq = tvb_get_ntohs(tvb,offset + 4);
+ fragment_offset = tvb_get_ntoh24(tvb, offset + 6);
+ fragment_length = tvb_get_ntoh24(tvb, offset + 9);
- if (!msg_type_str && !first_iteration)
+ if (!msg_type_str && !first_iteration)
{
- /* only dissect / report messages if they're
- * either the first message in this record
- * or they're a valid message type
- */
- return;
+ /* only dissect / report messages if they're
+ * either the first message in this record
+ * or they're a valid message type
+ */
+ return;
}
- /* on second and later iterations, add comma to info col */
- if (!first_iteration)
+ /* on second and later iterations, add comma to info col */
+ if (!first_iteration)
{
- if (check_col(pinfo->cinfo, COL_INFO))
- col_append_fstr(pinfo->cinfo, COL_INFO, ", ");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", ");
}
- /*
- * Update our info string
- */
- if (check_col(pinfo->cinfo, COL_INFO))
- col_append_fstr(pinfo->cinfo, COL_INFO, "%s", (msg_type_str != NULL)
- ? msg_type_str : "Encrypted Handshake Message");
+ /*
+ * Update our info string
+ */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%s", (msg_type_str != NULL)
+ ? msg_type_str : "Encrypted Handshake Message");
- if (tree)
+ if (tree)
{
- /* set the label text on the record layer expanding node */
- if (first_iteration)
+ /* set the label text on the record layer expanding node */
+ if (first_iteration)
{
- proto_item_set_text(tree, "%s Record Layer: %s Protocol: %s",
- ssl_version_short_names[*conv_version],
- val_to_str(content_type, ssl_31_content_type, "unknown"),
- (msg_type_str!=NULL) ? msg_type_str :
- "Encrypted Handshake Message");
+ proto_item_set_text(tree, "%s Record Layer: %s Protocol: %s",
+ ssl_version_short_names[*conv_version],
+ val_to_str(content_type, ssl_31_content_type, "unknown"),
+ (msg_type_str!=NULL) ? msg_type_str :
+ "Encrypted Handshake Message");
}
- else
+ else
{
- proto_item_set_text(tree, "%s Record Layer: %s Protocol: %s",
- ssl_version_short_names[*conv_version],
- val_to_str(content_type, ssl_31_content_type, "unknown"),
- "Multiple Handshake Messages");
+ proto_item_set_text(tree, "%s Record Layer: %s Protocol: %s",
+ ssl_version_short_names[*conv_version],
+ val_to_str(content_type, ssl_31_content_type, "unknown"),
+ "Multiple Handshake Messages");
}
- /* add a subtree for the handshake protocol */
- ti = proto_tree_add_item(tree, hf_dtls_handshake_protocol, tvb,
- offset, length + 12, 0);
- ssl_hand_tree = proto_item_add_subtree(ti, ett_dtls_handshake);
+ /* add a subtree for the handshake protocol */
+ ti = proto_tree_add_item(tree, hf_dtls_handshake_protocol, tvb,
+ offset, length + 12, 0);
+ ssl_hand_tree = proto_item_add_subtree(ti, ett_dtls_handshake);
- if (ssl_hand_tree)
+ if (ssl_hand_tree)
{
- /* set the text label on the subtree node */
- proto_item_set_text(ssl_hand_tree, "Handshake Protocol: %s",
- (msg_type_str != NULL) ? msg_type_str :
- "Encrypted Handshake Message");
+ /* set the text label on the subtree node */
+ proto_item_set_text(ssl_hand_tree, "Handshake Protocol: %s",
+ (msg_type_str != NULL) ? msg_type_str :
+ "Encrypted Handshake Message");
}
}
- /* if we don't have a valid handshake type, just quit dissecting */
- if (!msg_type_str)
- return;
+ /* if we don't have a valid handshake type, just quit dissecting */
+ if (!msg_type_str)
+ return;
- /* PAOLO: if we are doing ssl decryption we must dissect some requests type */
- if (ssl_hand_tree || ssl)
+ /* if we are doing ssl decryption we must dissect some requests type */
+ if (ssl_hand_tree || ssl)
{
- /* add nodes for the message type and message length */
- if (ssl_hand_tree)
- proto_tree_add_item(ssl_hand_tree, hf_dtls_handshake_type,
- tvb, offset, 1, msg_type);
- offset++;
- if (ssl_hand_tree)
- proto_tree_add_uint(ssl_hand_tree, hf_dtls_handshake_length,
+ /* add nodes for the message type and message length */
+ if (ssl_hand_tree)
+ proto_tree_add_item(ssl_hand_tree, hf_dtls_handshake_type,
+ tvb, offset, 1, msg_type);
+ offset++;
+ if (ssl_hand_tree)
+ proto_tree_add_uint(ssl_hand_tree, hf_dtls_handshake_length,
tvb, offset, 3, length);
- offset += 3;
+ offset += 3;
- if (ssl_hand_tree)
- proto_tree_add_uint(ssl_hand_tree, hf_dtls_handshake_message_seq,
+ if (ssl_hand_tree)
+ proto_tree_add_uint(ssl_hand_tree, hf_dtls_handshake_message_seq,
tvb, offset, 2, message_seq);
- offset += 2;
- if (ssl_hand_tree)
- proto_tree_add_uint(ssl_hand_tree, hf_dtls_handshake_fragment_offset,
+ offset += 2;
+ if (ssl_hand_tree)
+ proto_tree_add_uint(ssl_hand_tree, hf_dtls_handshake_fragment_offset,
tvb, offset, 3, fragment_offset);
- offset += 3;
- if (ssl_hand_tree)
- proto_tree_add_uint(ssl_hand_tree, hf_dtls_handshake_fragment_length,
+ offset += 3;
+ if (ssl_hand_tree)
+ proto_tree_add_uint(ssl_hand_tree, hf_dtls_handshake_fragment_length,
tvb, offset, 3, fragment_length);
- offset += 3;
+ offset += 3;
- /* now dissect the handshake message, if necessary */
- switch (msg_type) {
- case SSL_HND_HELLO_REQUEST:
- /* hello_request has no fields, so nothing to do! */
- break;
+ /* now dissect the handshake message, if necessary */
+ switch (msg_type) {
+ case SSL_HND_HELLO_REQUEST:
+ /* hello_request has no fields, so nothing to do! */
+ break;
- case SSL_HND_CLIENT_HELLO:
- dissect_ssl3_hnd_cli_hello(tvb, ssl_hand_tree, offset, length, ssl);
- break;
+ case SSL_HND_CLIENT_HELLO:
+ dissect_dtls_hnd_cli_hello(tvb, ssl_hand_tree, offset, length, ssl);
+ break;
- case SSL_HND_HELLO_VERIFY_REQUEST:
- dissect_ssl3_hnd_hello_verify_request(tvb, ssl_hand_tree, offset, length, ssl);
- break;
+ case SSL_HND_HELLO_VERIFY_REQUEST:
+ dissect_dtls_hnd_hello_verify_request(tvb, ssl_hand_tree, offset, ssl);
+ break;
- case SSL_HND_SERVER_HELLO:
- dissect_ssl3_hnd_srv_hello(tvb, ssl_hand_tree, offset, length, ssl);
- break;
-
- case SSL_HND_CERTIFICATE:
- dissect_ssl3_hnd_cert(tvb, ssl_hand_tree, offset, pinfo);
- break;
-
- case SSL_HND_SERVER_KEY_EXCHG:
- /* unimplemented */
- break;
-
- case SSL_HND_CERT_REQUEST:
- dissect_ssl3_hnd_cert_req(tvb, ssl_hand_tree, offset);
- break;
-
- case SSL_HND_SVR_HELLO_DONE:
- /* server_hello_done has no fields, so nothing to do! */
- break;
-
- case SSL_HND_CERT_VERIFY:
- /* unimplemented */
- break;
-
- case SSL_HND_CLIENT_KEY_EXCHG:
- {
- /* PAOLO: here we can have all the data to build session key*/
- StringInfo encrypted_pre_master;
- int ret;
- unsigned encrlen = length, skip = 0;
-
- if (!ssl)
- break;
+ case SSL_HND_SERVER_HELLO:
+ dissect_dtls_hnd_srv_hello(tvb, ssl_hand_tree, offset, length, ssl);
+ break;
+
+ case SSL_HND_CERTIFICATE:
+ dissect_dtls_hnd_cert(tvb, ssl_hand_tree, offset, pinfo);
+ break;
+
+ case SSL_HND_SERVER_KEY_EXCHG:
+ /* unimplemented */
+ break;
+
+ case SSL_HND_CERT_REQUEST:
+ dissect_dtls_hnd_cert_req(tvb, ssl_hand_tree, offset);
+ break;
+
+ case SSL_HND_SVR_HELLO_DONE:
+ /* server_hello_done has no fields, so nothing to do! */
+ break;
+
+ case SSL_HND_CERT_VERIFY:
+ /* unimplemented */
+ break;
+
+ case SSL_HND_CLIENT_KEY_EXCHG:
+ {
+ /* here we can have all the data to build session key */
+ StringInfo encrypted_pre_master;
+ gint ret;
+ guint encrlen = length, skip;
+ skip = 0;
+
+ if (!ssl)
+ break;
- /* check for required session data */
- ssl_debug_printf("dissect_ssl3_handshake found SSL_HND_CLIENT_KEY_EXCHG state %X\n",
- ssl->state);
- if ((ssl->state & (SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION)) !=
- (SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION)) {
- ssl_debug_printf("dissect_ssl3_handshake not enough data to generate key (required %X)\n",
- (SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION));
- break;
- }
+ /* check for required session data */
+ ssl_debug_printf("dissect_dtls_handshake found SSL_HND_CLIENT_KEY_EXCHG state %X\n",
+ ssl->state);
+ if ((ssl->state & (SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION)) !=
+ (SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION)) {
+ ssl_debug_printf("dissect_dtls_handshake not enough data to generate key (required %X)\n",
+ (SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION));
+ break;
+ }
- encrypted_pre_master.data = se_alloc(encrlen);
- encrypted_pre_master.data_len = encrlen;
- tvb_memcpy(tvb, encrypted_pre_master.data, offset+skip, encrlen);
+ encrypted_pre_master.data = se_alloc(encrlen);
+ encrypted_pre_master.data_len = encrlen;
+ tvb_memcpy(tvb, encrypted_pre_master.data, offset+skip, encrlen);
- if (!ssl->private_key) {
- ssl_debug_printf("dissect_ssl3_handshake can't find private key\n");
- break;
- }
+ if (!ssl->private_key) {
+ ssl_debug_printf("dissect_dtls_handshake can't find private key\n");
+ break;
+ }
- /* go with ssl key processessing; encrypted_pre_master
- * will be used for master secret store*/
- ret = ssl_decrypt_pre_master_secret(ssl, &encrypted_pre_master, ssl->private_key);
- if (ret < 0) {
- ssl_debug_printf("dissect_ssl3_handshake can't decrypt pre master secret\n");
- break;
- }
- if (ssl_generate_keyring_material(ssl)<0) {
- ssl_debug_printf("dissect_ssl3_handshake can't generate keyring material\n");
- break;
- }
- ssl->state |= SSL_HAVE_SESSION_KEY;
- ssl_save_session(ssl);
- ssl_debug_printf("dissect_ssl3_handshake session keys succesfully generated\n");
- }
- break;
-
- case SSL_HND_FINISHED:
- dissect_ssl3_hnd_finished(tvb, ssl_hand_tree,
- offset, conv_version);
- break;
- }
+ /* go with ssl key processessing; encrypted_pre_master
+ * will be used for master secret store*/
+ ret = ssl_decrypt_pre_master_secret(ssl, &encrypted_pre_master, ssl->private_key);
+ if (ret < 0) {
+ ssl_debug_printf("dissect_dtls_handshake can't decrypt pre master secret\n");
+ break;
+ }
+ if (ssl_generate_keyring_material(ssl)<0) {
+ ssl_debug_printf("dissect_dtls_handshake can't generate keyring material\n");
+ break;
+ }
+ ssl->state |= SSL_HAVE_SESSION_KEY;
+ ssl_save_session(ssl, dtls_session_hash);
+ ssl_debug_printf("dissect_dtls_handshake session keys succesfully generated\n");
+ }
+ break;
+
+ case SSL_HND_FINISHED:
+ dissect_dtls_hnd_finished(tvb, ssl_hand_tree,
+ offset, conv_version);
+ break;
+ }
}
- else{
- offset += 12; /* skip the handshake header when handshake is not processed*/
- }
- offset += length;
- first_iteration = FALSE; /* set up for next pass, if any */
+ else{
+ offset += 12; /* skip the handshake header when handshake is not processed*/
+ }
+ offset += length;
+ first_iteration = FALSE; /* set up for next pass, if any */
}
}
-static int
-dissect_ssl3_hnd_hello_common(tvbuff_t *tvb, proto_tree *tree,
+static gint
+dissect_dtls_hnd_hello_common(tvbuff_t *tvb, proto_tree *tree,
guint32 offset, SslDecryptSession* ssl, gint from_server)
{
- /* show the client's random challenge */
- nstime_t gmt_unix_time;
- guint8 session_id_length = 0;
-
- if (ssl)
- {
- /* PAOLO: get proper peer information*/
- StringInfo* rnd;
- if (from_server)
- rnd = &ssl->server_random;
- else
- rnd = &ssl->client_random;
+ /* show the client's random challenge */
+ nstime_t gmt_unix_time;
+ guint8 session_id_length;
+ session_id_length = 0;
+ if (ssl)
+ {
+ /* get proper peer information*/
+ StringInfo* rnd;
+ if (from_server)
+ rnd = &ssl->server_random;
+ else
+ rnd = &ssl->client_random;
- /* get provided random for keyring generation*/
- tvb_memcpy(tvb, rnd->data, offset, 32);
- rnd->data_len = 32;
- if (from_server)
- ssl->state |= SSL_SERVER_RANDOM;
- else
- ssl->state |= SSL_CLIENT_RANDOM;
- ssl_debug_printf("dissect_ssl3_hnd_hello_common found random state %X\n",
- ssl->state);
+ /* get provided random for keyring generation*/
+ tvb_memcpy(tvb, rnd->data, offset, 32);
+ rnd->data_len = 32;
+ if (from_server)
+ ssl->state |= SSL_SERVER_RANDOM;
+ else
+ ssl->state |= SSL_CLIENT_RANDOM;
+ ssl_debug_printf("dissect_dtls_hnd_hello_common found random state %X\n",
+ ssl->state);
- session_id_length = tvb_get_guint8(tvb, offset + 32);
- /* check stored session id info */
- if (from_server && (session_id_length == ssl->session_id.data_len) &&
- (tvb_memeql(tvb, offset+33, ssl->session_id.data, session_id_length) == 0))
+ session_id_length = tvb_get_guint8(tvb, offset + 32);
+ /* check stored session id info */
+ if (from_server && (session_id_length == ssl->session_id.data_len) &&
+ (tvb_memeql(tvb, offset+33, ssl->session_id.data, session_id_length) == 0))
{
- /* clinet/server id match: try to restore a previous cached session*/
- ssl_restore_session(ssl);
+ /* clinet/server id match: try to restore a previous cached session*/
+ ssl_restore_session(ssl, dtls_session_hash);
}
- else {
- tvb_memcpy(tvb,ssl->session_id.data, offset+33, session_id_length);
- ssl->session_id.data_len = session_id_length;
- }
+ else {
+ tvb_memcpy(tvb,ssl->session_id.data, offset+33, session_id_length);
+ ssl->session_id.data_len = session_id_length;
+ }
}
- if (tree)
- {
- /* show the time */
- gmt_unix_time.secs = tvb_get_ntohl(tvb, offset);
- gmt_unix_time.nsecs = 0;
- proto_tree_add_time(tree, hf_dtls_handshake_random_time,
- tvb, offset, 4, &gmt_unix_time);
- offset += 4;
-
- /* show the random bytes */
- proto_tree_add_item(tree, hf_dtls_handshake_random_bytes,
- tvb, offset, 28, 0);
- offset += 28;
-
- /* show the session id */
- session_id_length = tvb_get_guint8(tvb, offset);
- proto_tree_add_item(tree, hf_dtls_handshake_session_id_len,
- tvb, offset++, 1, 0);
- if (session_id_length > 0)
+ if (tree)
+ {
+ /* show the time */
+ gmt_unix_time.secs = tvb_get_ntohl(tvb, offset);
+ gmt_unix_time.nsecs = 0;
+ proto_tree_add_time(tree, hf_dtls_handshake_random_time,
+ tvb, offset, 4, &gmt_unix_time);
+ offset += 4;
+
+ /* show the random bytes */
+ proto_tree_add_item(tree, hf_dtls_handshake_random_bytes,
+ tvb, offset, 28, 0);
+ offset += 28;
+
+ /* show the session id */
+ session_id_length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(tree, hf_dtls_handshake_session_id_len,
+ tvb, offset++, 1, 0);
+ if (session_id_length > 0)
{
- tvb_ensure_bytes_exist(tvb, offset, session_id_length);
- proto_tree_add_bytes_format(tree, hf_dtls_handshake_session_id,
- tvb, offset, session_id_length,
- tvb_get_ptr(tvb, offset, session_id_length),
- "Session ID (%u byte%s)",
- session_id_length,
- plurality(session_id_length, "", "s"));
- offset += session_id_length;
+ tvb_ensure_bytes_exist(tvb, offset, session_id_length);
+ proto_tree_add_bytes_format(tree, hf_dtls_handshake_session_id,
+ tvb, offset, session_id_length,
+ tvb_get_ptr(tvb, offset, session_id_length),
+ "Session ID (%u byte%s)",
+ session_id_length,
+ plurality(session_id_length, "", "s"));
+ offset += session_id_length;
}
}
- /* XXXX */
- return session_id_length+33;
+ /* XXXX */
+ return session_id_length+33;
}
-static int
-dissect_ssl3_hnd_hello_ext(tvbuff_t *tvb,
+static gint
+dissect_dtls_hnd_hello_ext(tvbuff_t *tvb,
proto_tree *tree, guint32 offset, guint32 left)
{
- guint16 extension_length;
- guint16 ext_type;
- guint16 ext_len;
- proto_item *pi;
- proto_tree *ext_tree;
-
- if (left < 2)
- return offset;
-
- extension_length = tvb_get_ntohs(tvb, offset);
- proto_tree_add_uint(tree, hf_dtls_handshake_extensions_len,
- tvb, offset, 2, extension_length);
- offset += 2;
- left -= 2;
-
- while (left >= 4)
+ guint16 extension_length;
+ guint16 ext_type;
+ guint16 ext_len;
+ proto_item *pi;
+ proto_tree *ext_tree;
+
+ if (left < 2)
+ return offset;
+
+ extension_length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_dtls_handshake_extensions_len,
+ tvb, offset, 2, extension_length);
+ offset += 2;
+ left -= 2;
+
+ while (left >= 4)
{
- ext_type = tvb_get_ntohs(tvb, offset);
- ext_len = tvb_get_ntohs(tvb, offset + 2);
-
- pi = proto_tree_add_text(tree, tvb, offset, 4 + ext_len,
- "Extension: %s",
- val_to_str(ext_type,
- tls_hello_extension_types,
- "Unknown %u"));
- ext_tree = proto_item_add_subtree(pi, ett_dtls_extension);
- if (!ext_tree)
- ext_tree = tree;
-
- proto_tree_add_uint(ext_tree, hf_dtls_handshake_extension_type,
- tvb, offset, 2, ext_type);
- offset += 2;
-
- proto_tree_add_uint(ext_tree, hf_dtls_handshake_extension_len,
- tvb, offset, 2, ext_len);
- offset += 2;
-
- proto_tree_add_bytes_format(ext_tree, hf_dtls_handshake_extension_data,
- tvb, offset, ext_len,
- tvb_get_ptr(tvb, offset, ext_len),
- "Data (%u byte%s)",
- ext_len, plurality(ext_len, "", "s"));
- offset += ext_len;
- left -= 2 + 2 + ext_len;
+ ext_type = tvb_get_ntohs(tvb, offset);
+ ext_len = tvb_get_ntohs(tvb, offset + 2);
+
+ pi = proto_tree_add_text(tree, tvb, offset, 4 + ext_len,
+ "Extension: %s",
+ val_to_str(ext_type,
+ tls_hello_extension_types,
+ "Unknown %u"));
+ ext_tree = proto_item_add_subtree(pi, ett_dtls_extension);
+ if (!ext_tree)
+ ext_tree = tree;
+
+ proto_tree_add_uint(ext_tree, hf_dtls_handshake_extension_type,
+ tvb, offset, 2, ext_type);
+ offset += 2;
+
+ proto_tree_add_uint(ext_tree, hf_dtls_handshake_extension_len,
+ tvb, offset, 2, ext_len);
+ offset += 2;
+
+ proto_tree_add_bytes_format(ext_tree, hf_dtls_handshake_extension_data,
+ tvb, offset, ext_len,
+ tvb_get_ptr(tvb, offset, ext_len),
+ "Data (%u byte%s)",
+ ext_len, plurality(ext_len, "", "s"));
+ offset += ext_len;
+ left -= 2 + 2 + ext_len;
}
- return offset;
+ return offset;
}
static void
-dissect_ssl3_hnd_cli_hello(tvbuff_t *tvb,
- proto_tree *tree, guint32 offset, guint32 length,
- SslDecryptSession*ssl)
+dissect_dtls_hnd_cli_hello(tvbuff_t *tvb,
+ proto_tree *tree, guint32 offset, guint32 length,
+ SslDecryptSession*ssl)
{
- /* struct {
- * ProtocolVersion client_version;
- * Random random;
- * SessionID session_id;
- * opaque cookie<0..32>; //new field
- * CipherSuite cipher_suites<2..2^16-1>;
- * CompressionMethod compression_methods<1..2^8-1>;
- * Extension client_hello_extension_list<0..2^16-1>;
- * } ClientHello;
- *
- */
- proto_tree *ti;
- proto_tree *cs_tree;
- guint16 cipher_suite_length = 0;
- guint8 compression_methods_length = 0;
- guint8 compression_method;
- guint16 start_offset = offset;
- guint8 cookie_length = 0;
-
- if (tree || ssl)
+ /* struct {
+ * ProtocolVersion client_version;
+ * Random random;
+ * SessionID session_id;
+ * opaque cookie<0..32>; //new field
+ * CipherSuite cipher_suites<2..2^16-1>;
+ * CompressionMethod compression_methods<1..2^8-1>;
+ * Extension client_hello_extension_list<0..2^16-1>;
+ * } ClientHello;
+ *
+ */
+ proto_tree *ti;
+ proto_tree *cs_tree;
+ guint16 cipher_suite_length;
+ guint8 compression_methods_length;
+ guint8 compression_method;
+ guint16 start_offset = offset;
+ guint8 cookie_length;
+ cipher_suite_length = 0;
+ compression_methods_length = 0;
+ cookie_length = 0;
+
+ if (tree || ssl)
{
- /* show the client version */
- if (tree)
- proto_tree_add_item(tree, hf_dtls_handshake_client_version, tvb,
+ /* show the client version */
+ if (tree)
+ proto_tree_add_item(tree, hf_dtls_handshake_client_version, tvb,
offset, 2, FALSE);
- offset += 2;
+ offset += 2;
- /* show the fields in common with server hello */
- offset += dissect_ssl3_hnd_hello_common(tvb, tree, offset, ssl, 0);
+ /* show the fields in common with server hello */
+ offset += dissect_dtls_hnd_hello_common(tvb, tree, offset, ssl, 0);
- /* look for a cookie */
- cookie_length = tvb_get_guint8(tvb, offset);
- if (!tree)
- return;
+ /* look for a cookie */
+ cookie_length = tvb_get_guint8(tvb, offset);
+ if (!tree)
+ return;
- proto_tree_add_uint(tree, hf_dtls_handshake_cookie_len,
- tvb, offset, 1, cookie_length);
- offset ++; /* skip opaque length */
+ proto_tree_add_uint(tree, hf_dtls_handshake_cookie_len,
+ tvb, offset, 1, cookie_length);
+ offset ++; /* skip opaque length */
- if (cookie_length > 0)
- {
- tvb_ensure_bytes_exist(tvb, offset, cookie_length);
- proto_tree_add_bytes_format(tree, hf_dtls_handshake_cookie,
- tvb, offset, cookie_length,
- tvb_get_ptr(tvb, offset, cookie_length),
- "Cookie (%u byte%s)",
- cookie_length,
- plurality(cookie_length, "", "s"));
- offset += cookie_length;
- }
+ if (cookie_length > 0)
+ {
+ tvb_ensure_bytes_exist(tvb, offset, cookie_length);
+ proto_tree_add_bytes_format(tree, hf_dtls_handshake_cookie,
+ tvb, offset, cookie_length,
+ tvb_get_ptr(tvb, offset, cookie_length),
+ "Cookie (%u byte%s)",
+ cookie_length,
+ plurality(cookie_length, "", "s"));
+ offset += cookie_length;
+ }
- /* tell the user how many cipher suites there are */
- cipher_suite_length = tvb_get_ntohs(tvb, offset);
+ /* tell the user how many cipher suites there are */
+ cipher_suite_length = tvb_get_ntohs(tvb, offset);
- proto_tree_add_uint(tree, hf_dtls_handshake_cipher_suites_len,
- tvb, offset, 2, cipher_suite_length);
- offset += 2; /* skip opaque length */
+ proto_tree_add_uint(tree, hf_dtls_handshake_cipher_suites_len,
+ tvb, offset, 2, cipher_suite_length);
+ offset += 2; /* skip opaque length */
- if (cipher_suite_length > 0)
+ if (cipher_suite_length > 0)
{
- tvb_ensure_bytes_exist(tvb, offset, cipher_suite_length);
- ti = proto_tree_add_none_format(tree,
- hf_dtls_handshake_cipher_suites,
- tvb, offset, cipher_suite_length,
- "Cipher Suites (%u suite%s)",
- cipher_suite_length / 2,
- plurality(cipher_suite_length/2, "", "s"));
-
- /* make this a subtree */
- cs_tree = proto_item_add_subtree(ti, ett_dtls_cipher_suites);
- if (!cs_tree)
+ tvb_ensure_bytes_exist(tvb, offset, cipher_suite_length);
+ ti = proto_tree_add_none_format(tree,
+ hf_dtls_handshake_cipher_suites,
+ tvb, offset, cipher_suite_length,
+ "Cipher Suites (%u suite%s)",
+ cipher_suite_length / 2,
+ plurality(cipher_suite_length/2, "", "s"));
+
+ /* make this a subtree */
+ cs_tree = proto_item_add_subtree(ti, ett_dtls_cipher_suites);
+ if (!cs_tree)
{
- cs_tree = tree; /* failsafe */
+ cs_tree = tree; /* failsafe */
}
- while (cipher_suite_length > 0)
+ while (cipher_suite_length > 0)
{
- proto_tree_add_item(cs_tree, hf_dtls_handshake_cipher_suite,
- tvb, offset, 2, FALSE);
- offset += 2;
- cipher_suite_length -= 2;
+ proto_tree_add_item(cs_tree, hf_dtls_handshake_cipher_suite,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ cipher_suite_length -= 2;
}
}
- /* tell the user how man compression methods there are */
- compression_methods_length = tvb_get_guint8(tvb, offset);
- proto_tree_add_uint(tree, hf_dtls_handshake_comp_methods_len,
- tvb, offset, 1, compression_methods_length);
- offset++;
+ /* tell the user how man compression methods there are */
+ compression_methods_length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_dtls_handshake_comp_methods_len,
+ tvb, offset, 1, compression_methods_length);
+ offset++;
- if (compression_methods_length > 0)
+ if (compression_methods_length > 0)
{
- tvb_ensure_bytes_exist(tvb, offset, compression_methods_length);
- ti = proto_tree_add_none_format(tree,
- hf_dtls_handshake_comp_methods,
- tvb, offset, compression_methods_length,
- "Compression Methods (%u method%s)",
- compression_methods_length,
- plurality(compression_methods_length,
- "", "s"));
-
- /* make this a subtree */
- cs_tree = proto_item_add_subtree(ti, ett_dtls_comp_methods);
- if (!cs_tree)
+ tvb_ensure_bytes_exist(tvb, offset, compression_methods_length);
+ ti = proto_tree_add_none_format(tree,
+ hf_dtls_handshake_comp_methods,
+ tvb, offset, compression_methods_length,
+ "Compression Methods (%u method%s)",
+ compression_methods_length,
+ plurality(compression_methods_length,
+ "", "s"));
+
+ /* make this a subtree */
+ cs_tree = proto_item_add_subtree(ti, ett_dtls_comp_methods);
+ if (!cs_tree)
{
- cs_tree = tree; /* failsafe */
+ cs_tree = tree; /* failsafe */
}
- while (compression_methods_length > 0)
+ while (compression_methods_length > 0)
{
- compression_method = tvb_get_guint8(tvb, offset);
- if (compression_method < 64)
- proto_tree_add_uint(cs_tree, hf_dtls_handshake_comp_method,
+ compression_method = tvb_get_guint8(tvb, offset);
+ if (compression_method < 64)
+ proto_tree_add_uint(cs_tree, hf_dtls_handshake_comp_method,
tvb, offset, 1, compression_method);
- else if (compression_method > 63 && compression_method < 193)
- proto_tree_add_text(cs_tree, tvb, offset, 1,
- "Compression Method: Reserved - to be assigned by IANA (%u)",
- compression_method);
- else
- proto_tree_add_text(cs_tree, tvb, offset, 1,
- "Compression Method: Private use range (%u)",
- compression_method);
- offset++;
- compression_methods_length--;
+ else if (compression_method > 63 && compression_method < 193)
+ proto_tree_add_text(cs_tree, tvb, offset, 1,
+ "Compression Method: Reserved - to be assigned by IANA (%u)",
+ compression_method);
+ else
+ proto_tree_add_text(cs_tree, tvb, offset, 1,
+ "Compression Method: Private use range (%u)",
+ compression_method);
+ offset++;
+ compression_methods_length--;
}
}
- if (length > offset - start_offset)
+ if (length > offset - start_offset)
{
- offset = dissect_ssl3_hnd_hello_ext(tvb, tree, offset,
- length -
- (offset - start_offset));
+ offset = dissect_dtls_hnd_hello_ext(tvb, tree, offset,
+ length -
+ (offset - start_offset));
}
}
}
-static void dissect_ssl3_hnd_hello_verify_request(tvbuff_t *tvb,
+static void dissect_dtls_hnd_hello_verify_request(tvbuff_t *tvb,
proto_tree *tree,
- guint32 offset, guint32 length,
+ guint32 offset,
SslDecryptSession* ssl)
{
/*
@@ -1958,10 +1442,9 @@ static void dissect_ssl3_hnd_hello_verify_request(tvbuff_t *tvb,
* } HelloVerifyRequest;
*/
- proto_tree *ti;
- proto_tree *cs_tree;
- guint8 cookie_length = 0;
-
+ guint8 cookie_length;
+ cookie_length = 0;
+
if (tree || ssl)
{
/* show the client version */
@@ -1996,139 +1479,140 @@ static void dissect_ssl3_hnd_hello_verify_request(tvbuff_t *tvb,
}
static void
-dissect_ssl3_hnd_srv_hello(tvbuff_t *tvb,
+dissect_dtls_hnd_srv_hello(tvbuff_t *tvb,
proto_tree *tree, guint32 offset, guint32 length, SslDecryptSession* ssl)
{
- /* struct {
- * ProtocolVersion server_version;
- * Random random;
- * SessionID session_id;
- * CipherSuite cipher_suite;
- * CompressionMethod compression_method;
- * Extension server_hello_extension_list<0..2^16-1>;
- * } ServerHello;
- */
- guint16 start_offset = offset;
+ /* struct {
+ * ProtocolVersion server_version;
+ * Random random;
+ * SessionID session_id;
+ * CipherSuite cipher_suite;
+ * CompressionMethod compression_method;
+ * Extension server_hello_extension_list<0..2^16-1>;
+ * } ServerHello;
+ */
+ guint16 start_offset;
+ start_offset = offset;
- if (tree || ssl)
+ if (tree || ssl)
{
- /* show the server version */
- if (tree)
- proto_tree_add_item(tree, hf_dtls_handshake_server_version, tvb,
+ /* show the server version */
+ if (tree)
+ proto_tree_add_item(tree, hf_dtls_handshake_server_version, tvb,
offset, 2, FALSE);
- offset += 2;
-
- /* first display the elements conveniently in
- * common with client hello
- */
- offset += dissect_ssl3_hnd_hello_common(tvb, tree, offset, ssl, 1);
-
- /* PAOLO: handle session cipher suite */
- if (ssl) {
- /* store selected cipher suite for decryption */
- ssl->cipher = tvb_get_ntohs(tvb, offset);
- if (ssl_find_cipher(ssl->cipher,&ssl->cipher_suite) < 0) {
- ssl_debug_printf("dissect_ssl3_hnd_srv_hello can't find cipher suite %X\n", ssl->cipher);
- goto no_cipher;
- }
+ offset += 2;
- ssl->state |= SSL_CIPHER;
- ssl_debug_printf("dissect_ssl3_hnd_srv_hello found cipher %X, state %X\n",
- ssl->cipher, ssl->state);
-
- /* if we have restored a session now we can have enought material
- * to build session key, check it out*/
- if ((ssl->state &
- (SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION|SSL_MASTER_SECRET)) !=
- (SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION|SSL_MASTER_SECRET)) {
- ssl_debug_printf("dissect_ssl3_hnd_srv_hello not enough data to generate key (required %X)\n",
- (SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION|SSL_MASTER_SECRET));
- goto no_cipher;
- }
+ /* first display the elements conveniently in
+ * common with client hello
+ */
+ offset += dissect_dtls_hnd_hello_common(tvb, tree, offset, ssl, 1);
+
+ /* PAOLO: handle session cipher suite */
+ if (ssl) {
+ /* store selected cipher suite for decryption */
+ ssl->cipher = tvb_get_ntohs(tvb, offset);
+ if (ssl_find_cipher(ssl->cipher,&ssl->cipher_suite) < 0) {
+ ssl_debug_printf("dissect_dtls_hnd_srv_hello can't find cipher suite %X\n", ssl->cipher);
+ goto no_cipher;
+ }
+
+ ssl->state |= SSL_CIPHER;
+ ssl_debug_printf("dissect_dtls_hnd_srv_hello found cipher %X, state %X\n",
+ ssl->cipher, ssl->state);
+
+ /* if we have restored a session now we can have enought material
+ * to build session key, check it out*/
+ if ((ssl->state &
+ (SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION|SSL_MASTER_SECRET)) !=
+ (SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION|SSL_MASTER_SECRET)) {
+ ssl_debug_printf("dissect_dtls_hnd_srv_hello not enough data to generate key (required %X)\n",
+ (SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION|SSL_MASTER_SECRET));
+ goto no_cipher;
+ }
- ssl_debug_printf("dissect_ssl3_hnd_srv_hello trying to generate keys\n");
- if (ssl_generate_keyring_material(ssl)<0) {
- ssl_debug_printf("dissect_ssl3_hnd_srv_hello can't generate keyring material\n");
- goto no_cipher;
- }
- ssl->state |= SSL_HAVE_SESSION_KEY;
- }
-no_cipher:
- if (!tree)
- return;
+ ssl_debug_printf("dissect_dtls_hnd_srv_hello trying to generate keys\n");
+ if (ssl_generate_keyring_material(ssl)<0) {
+ ssl_debug_printf("dissect_dtls_hnd_srv_hello can't generate keyring material\n");
+ goto no_cipher;
+ }
+ ssl->state |= SSL_HAVE_SESSION_KEY;
+ }
+ no_cipher:
+ if (!tree)
+ return;
- /* now the server-selected cipher suite */
- proto_tree_add_item(tree, hf_dtls_handshake_cipher_suite,
- tvb, offset, 2, FALSE);
- offset += 2;
+ /* now the server-selected cipher suite */
+ proto_tree_add_item(tree, hf_dtls_handshake_cipher_suite,
+ tvb, offset, 2, FALSE);
+ offset += 2;
- /* and the server-selected compression method */
- proto_tree_add_item(tree, hf_dtls_handshake_comp_method,
- tvb, offset, 1, FALSE);
- offset++;
+ /* and the server-selected compression method */
+ proto_tree_add_item(tree, hf_dtls_handshake_comp_method,
+ tvb, offset, 1, FALSE);
+ offset++;
- if (length > offset - start_offset)
+ if (length > offset - start_offset)
{
- offset = dissect_ssl3_hnd_hello_ext(tvb, tree, offset,
- length -
- (offset - start_offset));
+ offset = dissect_dtls_hnd_hello_ext(tvb, tree, offset,
+ length -
+ (offset - start_offset));
}
}
}
static void
-dissect_ssl3_hnd_cert(tvbuff_t *tvb,
+dissect_dtls_hnd_cert(tvbuff_t *tvb,
proto_tree *tree, guint32 offset, packet_info *pinfo)
{
- /* opaque ASN.1Cert<2^24-1>;
- *
- * struct {
- * ASN.1Cert certificate_list<1..2^24-1>;
- * } Certificate;
- */
- guint32 certificate_list_length;
- proto_tree *ti;
- proto_tree *subtree;
+ /* opaque ASN.1Cert<2^24-1>;
+ *
+ * struct {
+ * ASN.1Cert certificate_list<1..2^24-1>;
+ * } Certificate;
+ */
+ guint32 certificate_list_length;
+ proto_tree *ti;
+ proto_tree *subtree;
- if (tree)
+ if (tree)
{
- certificate_list_length = tvb_get_ntoh24(tvb, offset);
- proto_tree_add_uint(tree, hf_dtls_handshake_certificates_len,
- tvb, offset, 3, certificate_list_length);
- offset += 3; /* 24-bit length value */
+ certificate_list_length = tvb_get_ntoh24(tvb, offset);
+ proto_tree_add_uint(tree, hf_dtls_handshake_certificates_len,
+ tvb, offset, 3, certificate_list_length);
+ offset += 3; /* 24-bit length value */
- if (certificate_list_length > 0)
+ if (certificate_list_length > 0)
{
- tvb_ensure_bytes_exist(tvb, offset, certificate_list_length);
- ti = proto_tree_add_none_format(tree,
- hf_dtls_handshake_certificates,
- tvb, offset, certificate_list_length,
- "Certificates (%u byte%s)",
- certificate_list_length,
- plurality(certificate_list_length,
- "", "s"));
-
- /* make it a subtree */
- subtree = proto_item_add_subtree(ti, ett_dtls_certs);
- if (!subtree)
+ tvb_ensure_bytes_exist(tvb, offset, certificate_list_length);
+ ti = proto_tree_add_none_format(tree,
+ hf_dtls_handshake_certificates,
+ tvb, offset, certificate_list_length,
+ "Certificates (%u byte%s)",
+ certificate_list_length,
+ plurality(certificate_list_length,
+ "", "s"));
+
+ /* make it a subtree */
+ subtree = proto_item_add_subtree(ti, ett_dtls_certs);
+ if (!subtree)
{
- subtree = tree; /* failsafe */
+ subtree = tree; /* failsafe */
}
- /* iterate through each certificate */
- while (certificate_list_length > 0)
+ /* iterate through each certificate */
+ while (certificate_list_length > 0)
{
- /* get the length of the current certificate */
- guint32 cert_length = tvb_get_ntoh24(tvb, offset);
- certificate_list_length -= 3 + cert_length;
+ /* get the length of the current certificate */
+ guint32 cert_length = tvb_get_ntoh24(tvb, offset);
+ certificate_list_length -= 3 + cert_length;
- proto_tree_add_item(subtree, hf_dtls_handshake_certificate_len,
- tvb, offset, 3, FALSE);
- offset += 3;
+ proto_tree_add_item(subtree, hf_dtls_handshake_certificate_len,
+ tvb, offset, 3, FALSE);
+ offset += 3;
- dissect_x509af_Certificate(FALSE, tvb, offset, pinfo, subtree, hf_dtls_handshake_certificate);
- offset += cert_length;
+ dissect_x509af_Certificate(FALSE, tvb, offset, pinfo, subtree, hf_dtls_handshake_certificate);
+ offset += cert_length;
}
}
@@ -2136,97 +1620,99 @@ dissect_ssl3_hnd_cert(tvbuff_t *tvb,
}
static void
-dissect_ssl3_hnd_cert_req(tvbuff_t *tvb,
+dissect_dtls_hnd_cert_req(tvbuff_t *tvb,
proto_tree *tree, guint32 offset)
{
- /*
- * enum {
- * rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4),
- * (255)
- * } ClientCertificateType;
- *
- * opaque DistinguishedName<1..2^16-1>;
- *
- * struct {
- * ClientCertificateType certificate_types<1..2^8-1>;
- * DistinguishedName certificate_authorities<3..2^16-1>;
- * } CertificateRequest;
- *
- */
- proto_tree *ti;
- proto_tree *subtree;
- guint8 cert_types_count = 0;
- int dnames_length = 0;
+ /*
+ * enum {
+ * rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4),
+ * (255)
+ * } ClientCertificateType;
+ *
+ * opaque DistinguishedName<1..2^16-1>;
+ *
+ * struct {
+ * ClientCertificateType certificate_types<1..2^8-1>;
+ * DistinguishedName certificate_authorities<3..2^16-1>;
+ * } CertificateRequest;
+ *
+ */
+ proto_tree *ti;
+ proto_tree *subtree;
+ guint8 cert_types_count;
+ gint dnames_length;
+ cert_types_count = 0;
+ dnames_length = 0;
- if (tree)
+ if (tree)
{
- cert_types_count = tvb_get_guint8(tvb, offset);
- proto_tree_add_uint(tree, hf_dtls_handshake_cert_types_count,
- tvb, offset, 1, cert_types_count);
- offset++;
+ cert_types_count = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tree, hf_dtls_handshake_cert_types_count,
+ tvb, offset, 1, cert_types_count);
+ offset++;
- if (cert_types_count > 0)
+ if (cert_types_count > 0)
{
- ti = proto_tree_add_none_format(tree,
- hf_dtls_handshake_cert_types,
- tvb, offset, cert_types_count,
- "Certificate types (%u type%s)",
- cert_types_count,
- plurality(cert_types_count, "", "s"));
- subtree = proto_item_add_subtree(ti, ett_dtls_cert_types);
- if (!subtree)
+ ti = proto_tree_add_none_format(tree,
+ hf_dtls_handshake_cert_types,
+ tvb, offset, cert_types_count,
+ "Certificate types (%u type%s)",
+ cert_types_count,
+ plurality(cert_types_count, "", "s"));
+ subtree = proto_item_add_subtree(ti, ett_dtls_cert_types);
+ if (!subtree)
{
- subtree = tree;
+ subtree = tree;
}
- while (cert_types_count > 0)
+ while (cert_types_count > 0)
{
- proto_tree_add_item(subtree, hf_dtls_handshake_cert_type,
- tvb, offset, 1, FALSE);
- offset++;
- cert_types_count--;
+ proto_tree_add_item(subtree, hf_dtls_handshake_cert_type,
+ tvb, offset, 1, FALSE);
+ offset++;
+ cert_types_count--;
}
}
- dnames_length = tvb_get_ntohs(tvb, offset);
- proto_tree_add_uint(tree, hf_dtls_handshake_dnames_len,
- tvb, offset, 2, dnames_length);
- offset += 2;
+ dnames_length = tvb_get_ntohs(tvb, offset);
+ proto_tree_add_uint(tree, hf_dtls_handshake_dnames_len,
+ tvb, offset, 2, dnames_length);
+ offset += 2;
- if (dnames_length > 0)
+ if (dnames_length > 0)
{
- tvb_ensure_bytes_exist(tvb, offset, dnames_length);
- ti = proto_tree_add_none_format(tree,
- hf_dtls_handshake_dnames,
- tvb, offset, dnames_length,
- "Distinguished Names (%d byte%s)",
- dnames_length,
- plurality(dnames_length, "", "s"));
- subtree = proto_item_add_subtree(ti, ett_dtls_dnames);
- if (!subtree)
+ tvb_ensure_bytes_exist(tvb, offset, dnames_length);
+ ti = proto_tree_add_none_format(tree,
+ hf_dtls_handshake_dnames,
+ tvb, offset, dnames_length,
+ "Distinguished Names (%d byte%s)",
+ dnames_length,
+ plurality(dnames_length, "", "s"));
+ subtree = proto_item_add_subtree(ti, ett_dtls_dnames);
+ if (!subtree)
{
- subtree = tree;
+ subtree = tree;
}
- while (dnames_length > 0)
+ while (dnames_length > 0)
{
- /* get the length of the current certificate */
- guint16 name_length = tvb_get_ntohs(tvb, offset);
- dnames_length -= 2 + name_length;
-
- proto_tree_add_item(subtree, hf_dtls_handshake_dname_len,
- tvb, offset, 2, FALSE);
- offset += 2;
-
- tvb_ensure_bytes_exist(tvb, offset, name_length);
- proto_tree_add_bytes_format(subtree,
- hf_dtls_handshake_dname,
- tvb, offset, name_length,
- tvb_get_ptr(tvb, offset, name_length),
- "Distinguished Name (%u byte%s)",
- name_length,
- plurality(name_length, "", "s"));
- offset += name_length;
+ /* get the length of the current certificate */
+ guint16 name_length = tvb_get_ntohs(tvb, offset);
+ dnames_length -= 2 + name_length;
+
+ proto_tree_add_item(subtree, hf_dtls_handshake_dname_len,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+
+ tvb_ensure_bytes_exist(tvb, offset, name_length);
+ proto_tree_add_bytes_format(subtree,
+ hf_dtls_handshake_dname,
+ tvb, offset, name_length,
+ tvb_get_ptr(tvb, offset, name_length),
+ "Distinguished Name (%u byte%s)",
+ name_length,
+ plurality(name_length, "", "s"));
+ offset += name_length;
}
}
}
@@ -2234,997 +1720,30 @@ dissect_ssl3_hnd_cert_req(tvbuff_t *tvb,
}
static void
-dissect_ssl3_hnd_finished(tvbuff_t *tvb,
+dissect_dtls_hnd_finished(tvbuff_t *tvb,
proto_tree *tree, guint32 offset,
guint* conv_version)
{
- /* For TLS:
- * struct {
- * opaque verify_data[12];
- * } Finished;
- *
- * For SSLv3:
- * struct {
- * opaque md5_hash[16];
- * opaque sha_hash[20];
- * } Finished;
- */
-
- /* this all needs a tree, so bail if we don't have one */
- if (!tree)
- {
- return;
- }
-
- switch(*conv_version) {
- case SSL_VER_DTLS:
- case SSL_VER_TLS:
- proto_tree_add_item(tree, hf_dtls_handshake_finished,
- tvb, offset, 12, FALSE);
- break;
-
- case SSL_VER_SSLv3:
- proto_tree_add_item(tree, hf_dtls_handshake_md5_hash,
- tvb, offset, 16, FALSE);
- offset += 16;
- proto_tree_add_item(tree, hf_dtls_handshake_sha_hash,
- tvb, offset, 20, FALSE);
- offset += 20;
- break;
- }
-}
-
-/*********************************************************************
- *
- * SSL version 2 Dissectors
- *
- *********************************************************************/
-
-
-/* record layer dissector */
-static int
-dissect_ssl2_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
- guint32 offset, guint* conv_version,
- gboolean *need_desegmentation,
- SslDecryptSession* ssl)
-{
- guint32 initial_offset = offset;
- guint8 byte = 0;
- guint8 record_length_length = 0;
- guint32 record_length = 0;
- gint is_escape = -1;
- gint16 padding_length = -1;
- guint8 msg_type = 0;
- const gchar *msg_type_str = NULL;
- guint32 available_bytes = 0;
-
- proto_tree *ti;
- proto_tree *dtls_record_tree = NULL;
-
- /* pull first byte; if high bit is set, then record
- * length is three bytes due to padding; otherwise
- * record length is two bytes
- */
- byte = tvb_get_guint8(tvb, offset);
- record_length_length = (byte & 0x80) ? 2 : 3;
-
- /*
- * Can we do reassembly?
- */
- available_bytes = tvb_length_remaining(tvb, offset);
-
- if (ssl_desegment && pinfo->can_desegment) {
- /*
- * Yes - is the record header split across segment boundaries?
- */
- if (available_bytes < record_length_length) {
- /*
- * Yes. Tell the TCP dissector where the data for this
- * message starts in the data it handed us, and how many
- * more bytes we need, and return.
- */
- pinfo->desegment_offset = offset;
- pinfo->desegment_len = record_length_length - available_bytes;
- *need_desegmentation = TRUE;
- return offset;
- }
- }
-
- /* parse out the record length */
- switch(record_length_length) {
- case 2: /* two-byte record length */
- record_length = (byte & 0x7f) << 8;
- byte = tvb_get_guint8(tvb, offset + 1);
- record_length += byte;
- break;
- case 3: /* three-byte record length */
- is_escape = (byte & 0x40) ? TRUE : FALSE;
- record_length = (byte & 0x3f) << 8;
- byte = tvb_get_guint8(tvb, offset + 1);
- record_length += byte;
- byte = tvb_get_guint8(tvb, offset + 2);
- padding_length = byte;
- }
-
- /*
- * Can we do reassembly?
- */
- if (ssl_desegment && pinfo->can_desegment) {
- /*
- * Yes - is the record split across segment boundaries?
- */
- if (available_bytes < (record_length_length + record_length)) {
- /*
- * Yes. Tell the TCP dissector where the data for this
- * message starts in the data it handed us, and how many
- * more bytes we need, and return.
- */
- pinfo->desegment_offset = offset;
- pinfo->desegment_len = (record_length_length + record_length)
- - available_bytes;
- *need_desegmentation = TRUE;
- return offset;
- }
- }
- offset += record_length_length;
-
- /* add the record layer subtree header */
- ti = proto_tree_add_item(tree, hf_ssl2_record, tvb, initial_offset,
- record_length_length + record_length, 0);
- dtls_record_tree = proto_item_add_subtree(ti, ett_dtls_record);
-
- /* pull the msg_type so we can bail if it's unknown */
- msg_type = tvb_get_guint8(tvb, initial_offset + record_length_length);
-
- /* if we get a server_hello or later handshake in v2, then set
- * this to sslv2
- */
- if (*conv_version == SSL_VER_UNKNOWN)
- {
- if (ssl_looks_like_valid_pct_handshake(tvb,
- (initial_offset +
- record_length_length),
- record_length)) {
- *conv_version = SSL_VER_PCT;
- /*ssl_set_conv_version(pinfo, ssl->version);*/
- }
- else if (msg_type >= 2 && msg_type <= 8)
- {
- *conv_version = SSL_VER_SSLv2;
- /*ssl_set_conv_version(pinfo, ssl->version);*/
- }
- }
-
- /* if we get here, but don't have a version set for the
- * conversation, then set a version for just this frame
- * (e.g., on a client hello)
- */
- if (check_col(pinfo->cinfo, COL_PROTOCOL))
- {
- col_set_str(pinfo->cinfo, COL_PROTOCOL,
- (*conv_version == SSL_VER_PCT) ? "PCT" : "SSLv2");
- }
-
- /* see if the msg_type is valid; if not the payload is
- * probably encrypted, so note that fact and bail
- */
- msg_type_str = match_strval(msg_type,
- (*conv_version == SSL_VER_PCT)
- ? pct_msg_types : ssl_20_msg_types);
- if (!msg_type_str
- || ((*conv_version != SSL_VER_PCT) &&
- !ssl_looks_like_valid_v2_handshake(tvb, initial_offset
- + record_length_length,
- record_length))
- || ((*conv_version == SSL_VER_PCT) &&
- !ssl_looks_like_valid_pct_handshake(tvb, initial_offset
- + record_length_length,
- record_length)))
- {
- if (dtls_record_tree)
- {
- proto_item_set_text(dtls_record_tree, "%s Record Layer: %s",
- (*conv_version == SSL_VER_PCT)
- ? "PCT" : "SSLv2",
- "Encrypted Data");
- }
- if (check_col(pinfo->cinfo, COL_INFO))
- col_append_str(pinfo->cinfo, COL_INFO, "Encrypted Data");
- return initial_offset + record_length_length + record_length;
- }
- else
- {
- if (check_col(pinfo->cinfo, COL_INFO))
- col_append_str(pinfo->cinfo, COL_INFO, msg_type_str);
-
- if (dtls_record_tree)
- {
- proto_item_set_text(dtls_record_tree, "%s Record Layer: %s",
- (*conv_version == SSL_VER_PCT)
- ? "PCT" : "SSLv2",
- msg_type_str);
- }
- }
-
- /* We have a valid message type, so move foward, filling in the
- * tree by adding the length, is_escape boolean and padding_length,
- * if present in the original packet
- */
- if (dtls_record_tree)
- {
- /* add the record length */
- tvb_ensure_bytes_exist(tvb, offset, record_length_length);
- ti = proto_tree_add_uint (dtls_record_tree,
- hf_dtls_record_length, tvb,
- initial_offset, record_length_length,
- record_length);
- }
- if (dtls_record_tree && is_escape != -1)
- {
- proto_tree_add_boolean(dtls_record_tree,
- hf_ssl2_record_is_escape, tvb,
- initial_offset, 1, is_escape);
- }
- if (dtls_record_tree && padding_length != -1)
- {
- proto_tree_add_uint(dtls_record_tree,
- hf_ssl2_record_padding_length, tvb,
- initial_offset + 2, 1, padding_length);
- }
-
- /*
- * dissect the record data
- */
-
- /* jump forward to the start of the record data */
- offset = initial_offset + record_length_length;
-
- /* add the message type */
- if (dtls_record_tree)
- {
- proto_tree_add_item(dtls_record_tree,
- (*conv_version == SSL_VER_PCT)
- ? hf_pct_msg_type : hf_ssl2_msg_type,
- tvb, offset, 1, 0);
- }
- offset++; /* move past msg_type byte */
-
- if (*conv_version != SSL_VER_PCT)
- {
- /* dissect the message (only handle client hello right now) */
- switch (msg_type) {
- case SSL2_HND_CLIENT_HELLO:
- dissect_ssl2_hnd_client_hello(tvb, dtls_record_tree, offset, ssl);
- break;
-
- case SSL2_HND_CLIENT_MASTER_KEY:
- dissect_ssl2_hnd_client_master_key(tvb, dtls_record_tree, offset);
- break;
-
- case SSL2_HND_SERVER_HELLO:
- dissect_ssl2_hnd_server_hello(tvb, dtls_record_tree, offset, pinfo);
- break;
-
- case SSL2_HND_ERROR:
- case SSL2_HND_CLIENT_FINISHED:
- case SSL2_HND_SERVER_VERIFY:
- case SSL2_HND_SERVER_FINISHED:
- case SSL2_HND_REQUEST_CERTIFICATE:
- case SSL2_HND_CLIENT_CERTIFICATE:
- /* unimplemented */
- break;
-
- default: /* unknown */
- break;
- }
- }
- else
- {
- /* dissect the message */
- switch (msg_type) {
- case PCT_MSG_CLIENT_HELLO:
- dissect_pct_msg_client_hello(tvb, dtls_record_tree, offset);
- break;
- case PCT_MSG_SERVER_HELLO:
- dissect_pct_msg_server_hello(tvb, dtls_record_tree, offset, pinfo);
- break;
- case PCT_MSG_CLIENT_MASTER_KEY:
- dissect_pct_msg_client_master_key(tvb, dtls_record_tree, offset);
- break;
- case PCT_MSG_SERVER_VERIFY:
- dissect_pct_msg_server_verify(tvb, dtls_record_tree, offset);
- break;
- case PCT_MSG_ERROR:
- dissect_pct_msg_error(tvb, dtls_record_tree, offset);
- break;
-
- default: /* unknown */
- break;
- }
- }
- return (initial_offset + record_length_length + record_length);
-}
-
-static void
-dissect_ssl2_hnd_client_hello(tvbuff_t *tvb,
- proto_tree *tree, guint32 offset,
- SslDecryptSession* ssl)
-{
- /* struct {
- * uint8 msg_type;
- * Version version;
- * uint16 cipher_spec_length;
- * uint16 session_id_length;
- * uint16 challenge_length;
- * V2CipherSpec cipher_specs[V2ClientHello.cipher_spec_length];
- * opaque session_id[V2ClientHello.session_id_length];
- * Random challenge;
- * } V2ClientHello;
- *
- * Note: when we get here, offset's already pointing at Version
- *
- */
- guint16 version;
- guint16 cipher_spec_length;
- guint16 session_id_length;
- guint16 challenge_length;
-
- proto_tree *ti;
- proto_tree *cs_tree=0;
-
- version = tvb_get_ntohs(tvb, offset);
- if (!ssl_is_valid_ssl_version(version))
- {
- /* invalid version; probably encrypted data */
- return;
- }
-
- if (tree || ssl)
- {
- /* show the version */
- if (tree)
- proto_tree_add_item(tree, hf_dtls_record_version, tvb,
- offset, 2, FALSE);
- offset += 2;
-
- cipher_spec_length = tvb_get_ntohs(tvb, offset);
- if (tree)
- proto_tree_add_item(tree, hf_ssl2_handshake_cipher_spec_len,
- tvb, offset, 2, FALSE);
- offset += 2;
-
- session_id_length = tvb_get_ntohs(tvb, offset);
- if (tree)
- proto_tree_add_item(tree, hf_ssl2_handshake_session_id_len,
- tvb, offset, 2, FALSE);
- offset += 2;
-
- challenge_length = tvb_get_ntohs(tvb, offset);
- if (tree)
- proto_tree_add_item(tree, hf_ssl2_handshake_challenge_len,
- tvb, offset, 2, FALSE);
- offset += 2;
-
- if (tree)
- {
- /* tell the user how many cipher specs they've won */
- tvb_ensure_bytes_exist(tvb, offset, cipher_spec_length);
- ti = proto_tree_add_none_format(tree, hf_dtls_handshake_cipher_suites,
- tvb, offset, cipher_spec_length,
- "Cipher Specs (%u specs)",
- cipher_spec_length/3);
-
- /* make this a subtree and expand the actual specs below */
- cs_tree = proto_item_add_subtree(ti, ett_dtls_cipher_suites);
- if (!cs_tree)
- {
- cs_tree = tree; /* failsafe */
- }
- }
-
- /* iterate through the cipher specs, showing them */
- while (cipher_spec_length > 0)
- {
- if (cs_tree)
- proto_tree_add_item(cs_tree, hf_ssl2_handshake_cipher_spec,
- tvb, offset, 3, FALSE);
- offset += 3; /* length of one cipher spec */
- cipher_spec_length -= 3;
- }
-
- /* if there's a session id, show it */
- if (session_id_length > 0)
- {
- if (tree)
- {
- tvb_ensure_bytes_exist(tvb, offset, session_id_length);
- proto_tree_add_bytes_format(tree,
- hf_dtls_handshake_session_id,
- tvb, offset, session_id_length,
- tvb_get_ptr(tvb, offset, session_id_length),
- "Session ID (%u byte%s)",
- session_id_length,
- plurality(session_id_length, "", "s"));
- }
-
- /* PAOLO: get session id and reset session state for key [re]negotiation */
- if (ssl)
- {
- tvb_memcpy(tvb,ssl->session_id.data, offset, session_id_length);
- ssl->session_id.data_len = session_id_length;
- ssl->state &= ~(SSL_HAVE_SESSION_KEY|SSL_MASTER_SECRET|
- SSL_CIPHER|SSL_SERVER_RANDOM);
- }
- offset += session_id_length;
- }
-
- /* if there's a challenge, show it */
- if (challenge_length > 0)
- {
- tvb_ensure_bytes_exist(tvb, offset, challenge_length);
-
- if (tree)
- proto_tree_add_item(tree, hf_ssl2_handshake_challenge,
- tvb, offset, challenge_length, 0);
- if (ssl)
- {
- /* PAOLO: get client random data; we get at most 32 bytes from
- challenge */
- int max = challenge_length > 32? 32: challenge_length;
-
- ssl_debug_printf("client random len: %d padded to 32\n",
- challenge_length);
-
- /* client random is padded with zero and 'right' aligned */
- memset(ssl->client_random.data, 0, 32 - max);
- tvb_memcpy(tvb, &ssl->client_random.data[32 - max], offset, max);
- ssl->client_random.data_len = 32;
- ssl->state |= SSL_CLIENT_RANDOM;
-
- }
- offset += challenge_length;
- }
- }
-}
-
-static void
-dissect_pct_msg_client_hello(tvbuff_t *tvb,
- proto_tree *tree, guint32 offset)
-{
- guint16 CH_CLIENT_VERSION, CH_OFFSET, CH_CIPHER_SPECS_LENGTH, CH_HASH_SPECS_LENGTH, CH_CERT_SPECS_LENGTH, CH_EXCH_SPECS_LENGTH, CH_KEY_ARG_LENGTH;
- proto_item *CH_CIPHER_SPECS_ti, *CH_HASH_SPECS_ti, *CH_CERT_SPECS_ti, *CH_EXCH_SPECS_ti;
- proto_tree *CH_CIPHER_SPECS_tree, *CH_HASH_SPECS_tree, *CH_CERT_SPECS_tree, *CH_EXCH_SPECS_tree;
- gint i;
-
- CH_CLIENT_VERSION = tvb_get_ntohs(tvb, offset);
- if(CH_CLIENT_VERSION != PCT_VERSION_1)
- proto_tree_add_text(tree, tvb, offset, 2, "Client Version, should be %x in PCT version 1", PCT_VERSION_1);
- else
- proto_tree_add_text(tree, tvb, offset, 2, "Client Version (%x)", PCT_VERSION_1);
- offset += 2;
-
- proto_tree_add_text(tree, tvb, offset, 1, "PAD");
- offset += 1;
-
- proto_tree_add_text(tree, tvb, offset, 32, "Client Session ID Data (32 bytes)");
- offset += 32;
-
- proto_tree_add_text(tree, tvb, offset, 32, "Challange Data(32 bytes)");
- offset += 32;
-
- CH_OFFSET = tvb_get_ntohs(tvb, offset);
- if(CH_OFFSET != PCT_CH_OFFSET_V1)
- proto_tree_add_text(tree, tvb, offset, 2, "CH_OFFSET: %d, should be %d in PCT version 1", CH_OFFSET, PCT_CH_OFFSET_V1);
- else
- proto_tree_add_text(tree, tvb, offset, 2, "CH_OFFSET: %d", CH_OFFSET);
- offset += 2;
-
- CH_CIPHER_SPECS_LENGTH = tvb_get_ntohs(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 2, "CIPHER_SPECS Length: %d", CH_CIPHER_SPECS_LENGTH);
- offset += 2;
-
- CH_HASH_SPECS_LENGTH = tvb_get_ntohs(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 2, "HASH_SPECS Length: %d", CH_HASH_SPECS_LENGTH);
- offset += 2;
-
- CH_CERT_SPECS_LENGTH = tvb_get_ntohs(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 2, "CERT_SPECS Length: %d", CH_CERT_SPECS_LENGTH);
- offset += 2;
-
- CH_EXCH_SPECS_LENGTH = tvb_get_ntohs(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 2, "EXCH_SPECS Length: %d", CH_EXCH_SPECS_LENGTH);
- offset += 2;
-
- CH_KEY_ARG_LENGTH = tvb_get_ntohs(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 2, "IV Length: %d", CH_KEY_ARG_LENGTH);
- offset += 2;
-
- if(CH_CIPHER_SPECS_LENGTH) {
- tvb_ensure_bytes_exist(tvb, offset, CH_CIPHER_SPECS_LENGTH);
- CH_CIPHER_SPECS_ti = proto_tree_add_item(tree, hf_pct_handshake_cipher_spec, tvb, offset, CH_CIPHER_SPECS_LENGTH, FALSE);
- CH_CIPHER_SPECS_tree = proto_item_add_subtree(CH_CIPHER_SPECS_ti, ett_pct_cipher_suites);
-
- for(i=0; i<(CH_CIPHER_SPECS_LENGTH/4); i++) {
- proto_tree_add_item(CH_CIPHER_SPECS_tree, hf_pct_handshake_cipher, tvb, offset, 2, FALSE);
- offset += 2;
- proto_tree_add_text(CH_CIPHER_SPECS_tree, tvb, offset, 1, "Encryption key length: %d", tvb_get_guint8(tvb, offset));
- offset += 1;
- proto_tree_add_text(CH_CIPHER_SPECS_tree, tvb, offset, 1, "MAC key length in bits: %d", tvb_get_guint8(tvb, offset) + 64);
- offset += 1;
- }
- }
-
- if(CH_HASH_SPECS_LENGTH) {
- tvb_ensure_bytes_exist(tvb, offset, CH_HASH_SPECS_LENGTH);
- CH_HASH_SPECS_ti = proto_tree_add_item(tree, hf_pct_handshake_hash_spec, tvb, offset, CH_HASH_SPECS_LENGTH, FALSE);
- CH_HASH_SPECS_tree = proto_item_add_subtree(CH_HASH_SPECS_ti, ett_pct_hash_suites);
-
- for(i=0; i<(CH_HASH_SPECS_LENGTH/2); i++) {
- proto_tree_add_item(CH_HASH_SPECS_tree, hf_pct_handshake_hash, tvb, offset, 2, FALSE);
- offset += 2;
- }
- }
-
- if(CH_CERT_SPECS_LENGTH) {
- tvb_ensure_bytes_exist(tvb, offset, CH_CERT_SPECS_LENGTH);
- CH_CERT_SPECS_ti = proto_tree_add_item(tree, hf_pct_handshake_cert_spec, tvb, offset, CH_CERT_SPECS_LENGTH, FALSE);
- CH_CERT_SPECS_tree = proto_item_add_subtree(CH_CERT_SPECS_ti, ett_pct_cert_suites);
-
- for(i=0; i< (CH_CERT_SPECS_LENGTH/2); i++) {
- proto_tree_add_item(CH_CERT_SPECS_tree, hf_pct_handshake_cert, tvb, offset, 2, FALSE);
- offset += 2;
- }
- }
-
- if(CH_EXCH_SPECS_LENGTH) {
- tvb_ensure_bytes_exist(tvb, offset, CH_EXCH_SPECS_LENGTH);
- CH_EXCH_SPECS_ti = proto_tree_add_item(tree, hf_pct_handshake_exch_spec, tvb, offset, CH_EXCH_SPECS_LENGTH, FALSE);
- CH_EXCH_SPECS_tree = proto_item_add_subtree(CH_EXCH_SPECS_ti, ett_pct_exch_suites);
-
- for(i=0; i<(CH_EXCH_SPECS_LENGTH/2); i++) {
- proto_tree_add_item(CH_EXCH_SPECS_tree, hf_pct_handshake_exch, tvb, offset, 2, FALSE);
- offset += 2;
- }
- }
-
- if(CH_KEY_ARG_LENGTH) {
- tvb_ensure_bytes_exist(tvb, offset, CH_KEY_ARG_LENGTH);
- proto_tree_add_text(tree, tvb, offset, CH_KEY_ARG_LENGTH, "IV data (%d bytes)", CH_KEY_ARG_LENGTH);
- offset += CH_KEY_ARG_LENGTH;
- }
-}
-
-static void
-dissect_pct_msg_server_hello(tvbuff_t *tvb, proto_tree *tree, guint32 offset, packet_info *pinfo)
-{
-/* structure:
-char SH_MSG_SERVER_HELLO
-char SH_PAD
-char SH_SERVER_VERSION_MSB
-char SH_SERVER_VERSION_LSB
-char SH_RESTART_SESSION_OK
-char SH_CLIENT_AUTH_REQ
-char SH_CIPHER_SPECS_DATA[4]
-char SH_HASH_SPECS_DATA[2]
-char SH_CERT_SPECS_DATA[2]
-char SH_EXCH_SPECS_DATA[2]
-char SH_CONNECTION_ID_DATA[32]
-char SH_CERTIFICATE_LENGTH_MSB
-char SH_CERTIFICATE_LENGTH_LSB
-char SH_CLIENT_CERT_SPECS_LENGTH_MSB
-char SH_CLIENT_CERT_SPECS_LENGTH_LSB
-char SH_CLIENT_SIG_SPECS_LENGTH_MSB
-char SH_CLIENT_SIG_SPECS_LENGTH_LSB
-char SH_RESPONSE_LENGTH_MSB
-char SH_RESPONSE_LENGTH_LSB
-char SH_CERTIFICATE_DATA[MSB<<8|LSB]
-char SH_CLIENT_CERT_SPECS_DATA[MSB<<8|LSB]
-char SH_CLIENT_SIG_SPECS_DATA[MSB<<8|LSB]
-char SH_RESPONSE_DATA[MSB<<8|LSB]
-
-*/
-
- guint16 SH_SERVER_VERSION, SH_CERT_LENGTH, SH_CERT_SPECS_LENGTH, SH_CLIENT_SIG_LENGTH, SH_RESPONSE_LENGTH;
-
- proto_tree_add_text(tree, tvb, offset, 1, "PAD");
- offset += 1;
-
- SH_SERVER_VERSION = tvb_get_ntohs(tvb, offset);
- if(SH_SERVER_VERSION != PCT_VERSION_1)
- proto_tree_add_text(tree, tvb, offset, 2, "Server Version, should be %x in PCT version 1", PCT_VERSION_1);
- else
- proto_tree_add_text(tree, tvb, offset, 2, "Server Version (%x)", PCT_VERSION_1);
- offset += 2;
-
- proto_tree_add_text(tree, tvb, offset, 1, "SH_RESTART_SESSION_OK flag");
- offset += 1;
-
- proto_tree_add_text(tree, tvb, offset, 1, "SH_CLIENT_AUTH_REQ flag");
- offset += 1;
-
- proto_tree_add_item(tree, hf_pct_handshake_cipher, tvb, offset, 2, FALSE);
- offset += 2;
- proto_tree_add_text(tree, tvb, offset, 1, "Encryption key length: %d", tvb_get_guint8(tvb, offset));
- offset += 1;
- proto_tree_add_text(tree, tvb, offset, 1, "MAC key length in bits: %d", tvb_get_guint8(tvb, offset) + 64);
- offset += 1;
-
- proto_tree_add_item(tree, hf_pct_handshake_hash, tvb, offset, 2, FALSE);
- offset += 2;
-
- proto_tree_add_item(tree, hf_pct_handshake_cert, tvb, offset, 2, FALSE);
- offset += 2;
-
- proto_tree_add_item(tree, hf_pct_handshake_exch, tvb, offset, 2, FALSE);
- offset += 2;
-
- proto_tree_add_text(tree, tvb, offset, 32, "Connection ID Data (32 bytes)");
- offset += 32;
-
- SH_CERT_LENGTH = tvb_get_ntohs(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 2, "Server Certificate Length: %d", SH_CERT_LENGTH);
- offset += 2;
-
- SH_CERT_SPECS_LENGTH = tvb_get_ntohs(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 2, "Client CERT_SPECS Length: %d", SH_CERT_SPECS_LENGTH);
- offset += 2;
-
- SH_CLIENT_SIG_LENGTH = tvb_get_ntohs(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 2, "Client SIG_SPECS Length: %d", SH_CLIENT_SIG_LENGTH);
- offset += 2;
-
- SH_RESPONSE_LENGTH = tvb_get_ntohs(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 2, "Response Length: %d", SH_RESPONSE_LENGTH);
- offset += 2;
-
- if(SH_CERT_LENGTH) {
- dissect_x509af_Certificate(FALSE, tvb, offset, pinfo, tree, hf_pct_handshake_server_cert);
- offset += SH_CERT_LENGTH;
- }
-
- if(SH_CERT_SPECS_LENGTH) {
- tvb_ensure_bytes_exist(tvb, offset, SH_CERT_SPECS_LENGTH);
- proto_tree_add_text(tree, tvb, offset, SH_CERT_SPECS_LENGTH, "Client CERT_SPECS (%d bytes)", SH_CERT_SPECS_LENGTH);
- offset += SH_CERT_SPECS_LENGTH;
- }
-
- if(SH_CLIENT_SIG_LENGTH) {
- tvb_ensure_bytes_exist(tvb, offset, SH_CLIENT_SIG_LENGTH);
- proto_tree_add_text(tree, tvb, offset, SH_CLIENT_SIG_LENGTH, "Client Signature (%d bytes)", SH_CLIENT_SIG_LENGTH);
- offset += SH_CLIENT_SIG_LENGTH;
- }
-
- if(SH_RESPONSE_LENGTH) {
- tvb_ensure_bytes_exist(tvb, offset, SH_RESPONSE_LENGTH);
- proto_tree_add_text(tree, tvb, offset, SH_RESPONSE_LENGTH, "Server Response (%d bytes)", SH_RESPONSE_LENGTH);
- offset += SH_RESPONSE_LENGTH;
- }
-
-}
-
-static void
-dissect_pct_msg_client_master_key(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
-{
- guint16 CMK_CLEAR_KEY_LENGTH, CMK_ENCRYPTED_KEY_LENGTH, CMK_KEY_ARG_LENGTH, CMK_VERIFY_PRELUDE, CMK_CLIENT_CERT_LENGTH, CMK_RESPONSE_LENGTH;
-
- proto_tree_add_text(tree, tvb, offset, 1, "PAD");
- offset += 1;
-
- proto_tree_add_item(tree, hf_pct_handshake_cert, tvb, offset, 2, FALSE);
- offset += 2;
-
- proto_tree_add_item(tree, hf_pct_handshake_sig, tvb, offset, 2, FALSE);
- offset += 2;
-
- CMK_CLEAR_KEY_LENGTH = tvb_get_ntohs(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 2, "Clear Key Length: %d",CMK_CLEAR_KEY_LENGTH);
- offset += 2;
-
- CMK_ENCRYPTED_KEY_LENGTH = tvb_get_ntohs(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 2, "Encrypted Key Length: %d",CMK_ENCRYPTED_KEY_LENGTH);
- offset += 2;
-
- CMK_KEY_ARG_LENGTH= tvb_get_ntohs(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 2, "IV Length: %d",CMK_KEY_ARG_LENGTH);
- offset += 2;
-
- CMK_VERIFY_PRELUDE = tvb_get_ntohs(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 2, "Verify Prelude Length: %d",CMK_VERIFY_PRELUDE);
- offset += 2;
-
- CMK_CLIENT_CERT_LENGTH = tvb_get_ntohs(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 2, "Client Cert Length: %d",CMK_CLIENT_CERT_LENGTH);
- offset += 2;
-
- CMK_RESPONSE_LENGTH = tvb_get_ntohs(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 2, "Response Length: %d",CMK_RESPONSE_LENGTH);
- offset += 2;
-
- if(CMK_CLEAR_KEY_LENGTH) {
- tvb_ensure_bytes_exist(tvb, offset, CMK_CLEAR_KEY_LENGTH);
- proto_tree_add_text(tree, tvb, offset, CMK_CLEAR_KEY_LENGTH, "Clear Key data (%d bytes)", CMK_CLEAR_KEY_LENGTH);
- offset += CMK_CLEAR_KEY_LENGTH;
- }
- if(CMK_ENCRYPTED_KEY_LENGTH) {
- tvb_ensure_bytes_exist(tvb, offset, CMK_ENCRYPTED_KEY_LENGTH);
- proto_tree_add_text(tree, tvb, offset, CMK_ENCRYPTED_KEY_LENGTH, "Encrypted Key data (%d bytes)", CMK_ENCRYPTED_KEY_LENGTH);
- offset += CMK_ENCRYPTED_KEY_LENGTH;
- }
- if(CMK_KEY_ARG_LENGTH) {
- tvb_ensure_bytes_exist(tvb, offset, CMK_KEY_ARG_LENGTH);
- proto_tree_add_text(tree, tvb, offset, CMK_KEY_ARG_LENGTH, "IV data (%d bytes)", CMK_KEY_ARG_LENGTH);
- offset += CMK_KEY_ARG_LENGTH;
- }
- if(CMK_VERIFY_PRELUDE) {
- tvb_ensure_bytes_exist(tvb, offset, CMK_VERIFY_PRELUDE);
- proto_tree_add_text(tree, tvb, offset, CMK_VERIFY_PRELUDE, "Verify Prelude data (%d bytes)", CMK_VERIFY_PRELUDE);
- offset += CMK_VERIFY_PRELUDE;
- }
- if(CMK_CLIENT_CERT_LENGTH) {
- tvb_ensure_bytes_exist(tvb, offset, CMK_CLIENT_CERT_LENGTH);
- proto_tree_add_text(tree, tvb, offset, CMK_CLIENT_CERT_LENGTH, "Client Certificate data (%d bytes)", CMK_CLIENT_CERT_LENGTH);
- offset += CMK_CLIENT_CERT_LENGTH;
- }
- if(CMK_RESPONSE_LENGTH) {
- tvb_ensure_bytes_exist(tvb, offset, CMK_RESPONSE_LENGTH);
- proto_tree_add_text(tree, tvb, offset, CMK_RESPONSE_LENGTH, "Response data (%d bytes)", CMK_RESPONSE_LENGTH);
- offset += CMK_RESPONSE_LENGTH;
- }
-}
-
-static void
-dissect_pct_msg_server_verify(tvbuff_t *tvb,
- proto_tree *tree, guint32 offset)
-{
- guint16 SV_RESPONSE_LENGTH;
-
- proto_tree_add_text(tree, tvb, offset, 1, "PAD");
- offset += 1;
-
- proto_tree_add_text(tree, tvb, offset, 32, "Server Session ID data (32 bytes)");
- offset += 32;
-
- SV_RESPONSE_LENGTH = tvb_get_ntohs(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 2, "Server Response Length: %d", SV_RESPONSE_LENGTH);
- offset += 2;
-
- if(SV_RESPONSE_LENGTH) {
- tvb_ensure_bytes_exist(tvb, offset, SV_RESPONSE_LENGTH);
- proto_tree_add_text(tree, tvb, offset, SV_RESPONSE_LENGTH, "Server Response (%d bytes)", SV_RESPONSE_LENGTH);
- offset += SV_RESPONSE_LENGTH;
- }
-}
-
-static void
-dissect_pct_msg_error(tvbuff_t *tvb,
- proto_tree *tree, guint32 offset)
-{
- guint16 ERROR_CODE, INFO_LEN;
-
- ERROR_CODE = tvb_get_ntohs(tvb, offset);
- proto_tree_add_item(tree, hf_pct_msg_error_type, tvb, offset, 2, FALSE);
- offset += 2;
-
- INFO_LEN = tvb_get_ntohs(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 2, "Eror Information Length: %d", INFO_LEN);
- offset += 2;
- if (ERROR_CODE == PCT_ERR_SPECS_MISMATCH && INFO_LEN == 6)
- {
- proto_tree_add_text(tree, tvb, offset, 1, "SPECS_MISMATCH_CIPHER");
- offset += 1;
- proto_tree_add_text(tree, tvb, offset, 1, "SPECS_MISMATCH_HASH");
- offset += 1;
- proto_tree_add_text(tree, tvb, offset, 1, "SPECS_MISMATCH_CERT");
- offset += 1;
- proto_tree_add_text(tree, tvb, offset, 1, "SPECS_MISMATCH_EXCH");
- offset += 1;
- proto_tree_add_text(tree, tvb, offset, 1, "SPECS_MISMATCH_CLIENT_CERT");
- offset += 1;
- proto_tree_add_text(tree, tvb, offset, 1, "SPECS_MISMATCH_CLIENT_SIG");
- offset += 1;
- }
- else if(INFO_LEN) {
- proto_tree_add_text(tree, tvb, offset, INFO_LEN, "Error Information dta (%d bytes)", INFO_LEN);
- offset += INFO_LEN;
- }
-}
-
-static void
-dissect_ssl2_hnd_client_master_key(tvbuff_t *tvb,
- proto_tree *tree, guint32 offset)
-{
- /* struct {
- * uint8 msg_type;
- * V2Cipherspec cipher;
- * uint16 clear_key_length;
- * uint16 encrypted_key_length;
- * uint16 key_arg_length;
- * opaque clear_key_data[V2ClientMasterKey.clear_key_length];
- * opaque encrypted_key_data[V2ClientMasterKey.encrypted_key_length];
- * opaque key_arg_data[V2ClientMasterKey.key_arg_length];
- * } V2ClientMasterKey;
- *
- * Note: when we get here, offset's already pointing at cipher
- */
- guint16 clear_key_length;
- guint16 encrypted_key_length;
- guint16 key_arg_length;
-
- /* at this point, everything we do involves the tree,
- * so quit now if we don't have one ;-)
- */
- if (!tree)
- {
- return;
- }
-
- /* show the selected cipher */
- proto_tree_add_item(tree, hf_ssl2_handshake_cipher_spec,
- tvb, offset, 3, FALSE);
- offset += 3;
-
- /* get the fixed fields */
- clear_key_length = tvb_get_ntohs(tvb, offset);
- proto_tree_add_item(tree, hf_ssl2_handshake_clear_key_len,
- tvb, offset, 2, FALSE);
- offset += 2;
-
- encrypted_key_length = tvb_get_ntohs(tvb, offset);
- proto_tree_add_item(tree, hf_ssl2_handshake_enc_key_len,
- tvb, offset, 2, FALSE);
- offset += 2;
-
- key_arg_length = tvb_get_ntohs(tvb, offset);
- proto_tree_add_item(tree, hf_ssl2_handshake_key_arg_len,
- tvb, offset, 2, FALSE);
- offset += 2;
-
- /* show the variable length fields */
- if (clear_key_length > 0)
- {
- tvb_ensure_bytes_exist(tvb, offset, clear_key_length);
- proto_tree_add_item(tree, hf_ssl2_handshake_clear_key,
- tvb, offset, clear_key_length, FALSE);
- offset += clear_key_length;
- }
-
- if (encrypted_key_length > 0)
- {
- tvb_ensure_bytes_exist(tvb, offset, encrypted_key_length);
- proto_tree_add_item(tree, hf_ssl2_handshake_enc_key,
- tvb, offset, encrypted_key_length, FALSE);
- offset += encrypted_key_length;
- }
-
- if (key_arg_length > 0)
- {
- tvb_ensure_bytes_exist(tvb, offset, key_arg_length);
- proto_tree_add_item(tree, hf_ssl2_handshake_key_arg,
- tvb, offset, key_arg_length, FALSE);
- offset += key_arg_length;
- }
-
-}
-
-static void
-dissect_ssl2_hnd_server_hello(tvbuff_t *tvb,
- proto_tree *tree, guint32 offset, packet_info *pinfo)
-{
- /* struct {
- * uint8 msg_type;
- * uint8 session_id_hit;
- * uint8 certificate_type;
- * uint16 server_version;
- * uint16 certificate_length;
- * uint16 cipher_specs_length;
- * uint16 connection_id_length;
- * opaque certificate_data[V2ServerHello.certificate_length];
- * opaque cipher_specs_data[V2ServerHello.cipher_specs_length];
- * opaque connection_id_data[V2ServerHello.connection_id_length];
- * } V2ServerHello;
- *
- * Note: when we get here, offset's already pointing at session_id_hit
- */
- guint16 certificate_length;
- guint16 cipher_spec_length;
- guint16 connection_id_length;
- guint16 version;
- proto_tree *ti;
- proto_tree *subtree;
-
- /* everything we do only makes sense with a tree, so
- * quit now if we don't have one
- */
- if (!tree)
- {
- return;
- }
-
- version = tvb_get_ntohs(tvb, offset + 2);
- if (!ssl_is_valid_ssl_version(version))
- {
- /* invalid version; probably encrypted data */
- return;
- }
-
-
- /* is there a hit? */
- proto_tree_add_item(tree, hf_ssl2_handshake_session_id_hit,
- tvb, offset, 1, FALSE);
- offset++;
-
- /* what type of certificate is this? */
- proto_tree_add_item(tree, hf_ssl2_handshake_cert_type,
- tvb, offset, 1, FALSE);
- offset++;
-
- /* now the server version */
- proto_tree_add_item(tree, hf_dtls_handshake_server_version,
- tvb, offset, 2, FALSE);
- offset += 2;
-
- /* get the fixed fields */
- certificate_length = tvb_get_ntohs(tvb, offset);
- proto_tree_add_uint(tree, hf_dtls_handshake_certificate_len,
- tvb, offset, 2, certificate_length);
- offset += 2;
-
- cipher_spec_length = tvb_get_ntohs(tvb, offset);
- proto_tree_add_uint(tree, hf_ssl2_handshake_cipher_spec_len,
- tvb, offset, 2, cipher_spec_length);
- offset += 2;
-
- connection_id_length = tvb_get_ntohs(tvb, offset);
- proto_tree_add_uint(tree, hf_ssl2_handshake_connection_id_len,
- tvb, offset, 2, connection_id_length);
- offset += 2;
-
- /* now the variable length fields */
- if (certificate_length > 0)
- {
- dissect_x509af_Certificate(FALSE, tvb, offset, pinfo, tree, hf_dtls_handshake_certificate);
- offset += certificate_length;
- }
-
- if (cipher_spec_length > 0)
- {
- /* provide a collapsing node for the cipher specs */
- tvb_ensure_bytes_exist(tvb, offset, cipher_spec_length);
- ti = proto_tree_add_none_format(tree,
- hf_dtls_handshake_cipher_suites,
- tvb, offset, cipher_spec_length,
- "Cipher Specs (%u spec%s)",
- cipher_spec_length/3,
- plurality(cipher_spec_length/3, "", "s"));
- subtree = proto_item_add_subtree(ti, ett_dtls_cipher_suites);
- if (!subtree)
- {
- subtree = tree;
- }
-
- /* iterate through the cipher specs */
- while (cipher_spec_length > 0)
- {
- proto_tree_add_item(subtree, hf_ssl2_handshake_cipher_spec,
- tvb, offset, 3, FALSE);
- offset += 3;
- cipher_spec_length -= 3;
- }
- }
+ /*
+ * struct {
+ * opaque verify_data[12];
+ * } Finished;
+ */
- if (connection_id_length > 0)
+ /* this all needs a tree, so bail if we don't have one */
+ if (!tree)
{
- tvb_ensure_bytes_exist(tvb, offset, connection_id_length);
- proto_tree_add_item(tree, hf_ssl2_handshake_connection_id,
- tvb, offset, connection_id_length, FALSE);
- offset += connection_id_length;
+ return;
}
+ switch(*conv_version) {
+ case SSL_VER_DTLS:
+ proto_tree_add_item(tree, hf_dtls_handshake_finished,
+ tvb, offset, 12, FALSE);
+ break;
+ }
}
-
-
-
/*********************************************************************
*
* Support Functions
@@ -3234,316 +1753,103 @@ dissect_ssl2_hnd_server_hello(tvbuff_t *tvb,
static void
ssl_set_conv_version(packet_info *pinfo, guint version)
{
- conversation_t *conversation;
+ conversation_t *conversation;
- if (pinfo->fd->flags.visited)
+ if (pinfo->fd->flags.visited)
{
- /* We've already processed this frame; no need to do any more
- * work on it.
- */
- return;
+ /* We've already processed this frame; no need to do any more
+ * work on it.
+ */
+ return;
}
- conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
- pinfo->srcport, pinfo->destport, 0);
+ conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
- if (conversation == NULL)
+ if (conversation == NULL)
{
- /* create a new conversation */
- conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
- pinfo->srcport, pinfo->destport, 0);
+ /* create a new conversation */
+ conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
+ pinfo->srcport, pinfo->destport, 0);
}
- if (conversation_get_proto_data(conversation, proto_dtls) != NULL)
+ if (conversation_get_proto_data(conversation, proto_dtls) != NULL)
{
- /* get rid of the current data */
- conversation_delete_proto_data(conversation, proto_dtls);
+ /* get rid of the current data */
+ conversation_delete_proto_data(conversation, proto_dtls);
}
- conversation_add_proto_data(conversation, proto_dtls, GINT_TO_POINTER(version));
+ conversation_add_proto_data(conversation, proto_dtls, GINT_TO_POINTER(version));
}
#endif
-static int
-ssl_is_valid_handshake_type(guint8 type)
-{
-
- switch (type) {
- case SSL_HND_HELLO_REQUEST:
- case SSL_HND_CLIENT_HELLO:
- case SSL_HND_SERVER_HELLO:
- case SSL_HND_HELLO_VERIFY_REQUEST:
- case SSL_HND_CERTIFICATE:
- case SSL_HND_SERVER_KEY_EXCHG:
- case SSL_HND_CERT_REQUEST:
- case SSL_HND_SVR_HELLO_DONE:
- case SSL_HND_CERT_VERIFY:
- case SSL_HND_CLIENT_KEY_EXCHG:
- case SSL_HND_FINISHED:
- return 1;
- }
- return 0;
-}
-
-static int
-ssl_is_valid_content_type(guint8 type)
-{
- if (type >= 0x14 && type <= 0x17)
- {
- return 1;
- }
-
- return 0;
-}
-
-static int
-ssl_is_valid_ssl_version(guint16 version)
-{
- const gchar *version_str = match_strval(version, ssl_versions);
- return version_str != NULL;
-}
-
-static int
-ssl_is_authoritative_version_message(guint8 content_type,
- guint8 next_byte)
-{
- if (content_type == SSL_ID_HANDSHAKE
- && ssl_is_valid_handshake_type(next_byte))
- {
- return (next_byte != SSL_HND_CLIENT_HELLO);
- }
- else if (ssl_is_valid_content_type(content_type)
- && content_type != SSL_ID_HANDSHAKE)
- {
- return 1;
- }
- return 0;
-}
-
-static int
-ssl_is_v2_client_hello(tvbuff_t *tvb, guint32 offset)
+static gint
+dtls_is_valid_handshake_type(guint8 type)
{
- guint8 byte;
-
- byte = tvb_get_guint8(tvb, offset);
- if (byte != 0x80) /* v2 client hello should start this way */
- {
- return 0;
- }
- byte = tvb_get_guint8(tvb, offset+2);
- if (byte != 0x01) /* v2 client hello msg type */
- {
- return 0;
- }
-
- /* 1 in 2^16 of being right; improve later if necessary */
+ switch (type) {
+ case SSL_HND_HELLO_REQUEST:
+ case SSL_HND_CLIENT_HELLO:
+ case SSL_HND_SERVER_HELLO:
+ case SSL_HND_HELLO_VERIFY_REQUEST:
+ case SSL_HND_CERTIFICATE:
+ case SSL_HND_SERVER_KEY_EXCHG:
+ case SSL_HND_CERT_REQUEST:
+ case SSL_HND_SVR_HELLO_DONE:
+ case SSL_HND_CERT_VERIFY:
+ case SSL_HND_CLIENT_KEY_EXCHG:
+ case SSL_HND_FINISHED:
return 1;
+ }
+ return 0;
}
-/* this applies a heuristic to determine whether
- * or not the data beginning at offset looks like a
- * valid sslv2 record. this isn't really possible,
- * but we'll try to do a reasonable job anyway.
- */
-static int
-ssl_looks_like_sslv2(tvbuff_t *tvb, guint32 offset)
+static gint
+dtls_is_authoritative_version_message(guint8 content_type,
+ guint8 next_byte)
{
- /* here's the current approach:
- *
- * we only try to catch unencrypted handshake messages, so we can
- * assume that there is not padding. This means that the
- * first byte must be >= 0x80 and there must be a valid sslv2
- * msg_type in the third byte
- */
-
- /* get the first byte; must have high bit set */
- guint8 byte = tvb_get_guint8(tvb, offset);
- if (byte < 0x80)
+ if (content_type == SSL_ID_HANDSHAKE
+ && dtls_is_valid_handshake_type(next_byte))
{
- return 0;
+ return (next_byte != SSL_HND_CLIENT_HELLO);
}
-
- /* get the supposed msg_type byte; since we only care about
- * unencrypted handshake messages (we can't tell the type for
- * encrypted messages), we just check against that list
- */
- byte = tvb_get_guint8(tvb, offset + 2);
- switch(byte) {
- case SSL2_HND_ERROR:
- case SSL2_HND_CLIENT_HELLO:
- case SSL2_HND_CLIENT_MASTER_KEY:
- case SSL2_HND_SERVER_HELLO:
- case PCT_MSG_CLIENT_MASTER_KEY:
- case PCT_MSG_ERROR:
- return 1;
+ else if (ssl_is_valid_content_type(content_type)
+ && content_type != SSL_ID_HANDSHAKE)
+ {
+ return 1;
}
- return 0;
+ return 0;
}
/* this applies a heuristic to determine whether
* or not the data beginning at offset looks like a
- * valid sslv3 record. this is somewhat more reliable
- * than sslv2 due to the structure of the v3 protocol
+ * valid dtls record.
*/
-static int
-ssl_looks_like_sslv3(tvbuff_t *tvb, guint32 offset)
+static gint
+looks_like_dtls(tvbuff_t *tvb, guint32 offset)
{
- /* have to have a valid content type followed by a valid
- * protocol version
- */
- guint8 byte;
- guint16 version;
+ /* have to have a valid content type followed by a valid
+ * protocol version
+ */
+ guint8 byte;
+ guint16 version;
- /* see if the first byte is a valid content type */
- byte = tvb_get_guint8(tvb, offset);
- if (!ssl_is_valid_content_type(byte))
+ /* see if the first byte is a valid content type */
+ byte = tvb_get_guint8(tvb, offset);
+ if (!ssl_is_valid_content_type(byte))
{
- return 0;
+ return 0;
}
- /* now check to see if the version byte appears valid */
- version = tvb_get_ntohs(tvb, offset + 1);
- if (version != DTLSV1DOT0_VERSION)
+ /* now check to see if the version byte appears valid */
+ version = tvb_get_ntohs(tvb, offset + 1);
+ if (version != DTLSV1DOT0_VERSION)
{
- return 0;
- }
-
- return 1;
-}
-
-/* applies a heuristic to determine whether
- * or not the data beginning at offset looks
- * like a valid, unencrypted v2 handshake message.
- * since it isn't possible to completely tell random
- * data apart from a valid message without state,
- * we try to help the odds.
- */
-static int
-ssl_looks_like_valid_v2_handshake(tvbuff_t *tvb, guint32 offset,
- guint32 record_length)
-{
- /* first byte should be a msg_type.
- *
- * - we know we only see client_hello, client_master_key,
- * and server_hello in the clear, so check to see if
- * msg_type is one of those (this gives us a 3 in 2^8
- * chance of saying yes with random payload)
- *
- * - for those three types that we know about, do some
- * further validation to reduce the chance of an error
- */
- guint8 msg_type;
- guint16 version;
- guint32 sum;
-
- /* fetch the msg_type */
- msg_type = tvb_get_guint8(tvb, offset);
-
- switch (msg_type) {
- case SSL2_HND_CLIENT_HELLO:
- /* version follows msg byte, so verify that this is valid */
- version = tvb_get_ntohs(tvb, offset+1);
- return ssl_is_valid_ssl_version(version);
- break;
-
- case SSL2_HND_SERVER_HELLO:
- /* version is three bytes after msg_type */
- version = tvb_get_ntohs(tvb, offset+3);
- return ssl_is_valid_ssl_version(version);
- break;
-
- case SSL2_HND_CLIENT_MASTER_KEY:
- /* sum of clear_key_length, encrypted_key_length, and key_arg_length
- * must be less than record length
- */
- sum = tvb_get_ntohs(tvb, offset + 4); /* clear_key_length */
- sum += tvb_get_ntohs(tvb, offset + 6); /* encrypted_key_length */
- sum += tvb_get_ntohs(tvb, offset + 8); /* key_arg_length */
- if (sum > record_length)
- {
- return 0;
- }
- return 1;
- break;
-
- default:
- return 0;
+ return 0;
}
- return 0;
-}
-
-/* applies a heuristic to determine whether
- * or not the data beginning at offset looks
- * like a valid, unencrypted v2 handshake message.
- * since it isn't possible to completely tell random
- * data apart from a valid message without state,
- * we try to help the odds.
- */
-static int
-ssl_looks_like_valid_pct_handshake(tvbuff_t *tvb, guint32 offset,
- guint32 record_length)
-{
- /* first byte should be a msg_type.
- *
- * - we know we only see client_hello, client_master_key,
- * and server_hello in the clear, so check to see if
- * msg_type is one of those (this gives us a 3 in 2^8
- * chance of saying yes with random payload)
- *
- * - for those three types that we know about, do some
- * further validation to reduce the chance of an error
- */
- guint8 msg_type;
- guint16 version;
- guint32 sum;
-
- /* fetch the msg_type */
- msg_type = tvb_get_guint8(tvb, offset);
-
- switch (msg_type) {
- case PCT_MSG_CLIENT_HELLO:
- /* version follows msg byte, so verify that this is valid */
- version = tvb_get_ntohs(tvb, offset+1);
- return version == PCT_VERSION_1;
- break;
-
- case PCT_MSG_SERVER_HELLO:
- /* version is one byte after msg_type */
- version = tvb_get_ntohs(tvb, offset+2);
- return version == PCT_VERSION_1;
- break;
-
- case PCT_MSG_CLIENT_MASTER_KEY:
- /* sum of various length fields must be less than record length */
- sum = tvb_get_ntohs(tvb, offset + 6); /* clear_key_length */
- sum += tvb_get_ntohs(tvb, offset + 8); /* encrypted_key_length */
- sum += tvb_get_ntohs(tvb, offset + 10); /* key_arg_length */
- sum += tvb_get_ntohs(tvb, offset + 12); /* verify_prelude_length */
- sum += tvb_get_ntohs(tvb, offset + 14); /* client_cert_length */
- sum += tvb_get_ntohs(tvb, offset + 16); /* response_length */
- if (sum > record_length)
- {
- return 0;
- }
- return 1;
- break;
-
- case PCT_MSG_SERVER_VERIFY:
- /* record is 36 bytes longer than response_length */
- sum = tvb_get_ntohs(tvb, offset + 34); /* response_length */
- if ((sum + 36) == record_length)
- return 1;
- else
- return 0;
- break;
- default:
- return 0;
- }
- return 0;
+ return 1;
}
-
/*********************************************************************
*
* Standard Ethereal Protocol Registration and housekeeping
@@ -3553,308 +1859,300 @@ void
proto_register_dtls(void)
{
- /* Setup list of header fields See Section 1.6.1 for details*/
- static hf_register_info hf[] = {
- { &hf_dtls_record,
- { "Record Layer", "dtls.record",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "Record layer", HFILL }
- },
- { &hf_dtls_record_content_type,
- { "Content Type", "dtls.record.content_type",
- FT_UINT8, BASE_DEC, VALS(ssl_31_content_type), 0x0,
- "Content type", HFILL}
- },
- { &hf_dtls_record_version,
- { "Version", "dtls.record.version",
- FT_UINT16, BASE_HEX, VALS(ssl_versions), 0x0,
- "Record layer version.", HFILL }
- },
- { &hf_dtls_record_epoch,
- { "Epoch", "dtls.record.epoch",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "Epoch", HFILL }
- },
- { &hf_dtls_record_sequence_number,
- { "Sequence Number", "dtls.record.sequence_number",
- FT_DOUBLE, BASE_DEC, NULL, 0x0,
- "Sequence Number", HFILL }
- },
- { &hf_dtls_record_length,
- { "Length", "dtls.record.length",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "Length of DTLS record data", HFILL }
- },
- { &hf_dtls_record_appdata,
- { "Application Data", "dtls.app_data",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "Payload is application data", HFILL }
- },
- { &hf_dtls_record_appdata_decrypted,
- { "Application Data decrypted", "dtls.app_data_decrypted",
- FT_STRING, BASE_NONE, NULL, 0x0,
- "Payload is decrypted application data", HFILL }
- },
- { &hf_dtls_change_cipher_spec,
- { "Change Cipher Spec Message", "dtls.change_cipher_spec",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "Signals a change in cipher specifications", HFILL }
- },
- { & hf_dtls_alert_message,
- { "Alert Message", "dtls.alert_message",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "Alert message", HFILL }
- },
- { & hf_dtls_alert_message_level,
- { "Level", "dtls.alert_message.level",
- FT_UINT8, BASE_DEC, VALS(ssl_31_alert_level), 0x0,
- "Alert message level", HFILL }
- },
- { &hf_dtls_alert_message_description,
- { "Description", "dtls.alert_message.desc",
- FT_UINT8, BASE_DEC, VALS(ssl_31_alert_description), 0x0,
- "Alert message description", HFILL }
- },
- { &hf_dtls_handshake_protocol,
- { "Handshake Protocol", "dtls.handshake",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "Handshake protocol message", HFILL}
- },
- { &hf_dtls_handshake_type,
- { "Handshake Type", "dtls.handshake.type",
- FT_UINT8, BASE_DEC, VALS(ssl_31_handshake_type), 0x0,
- "Type of handshake message", HFILL}
- },
- { &hf_dtls_handshake_length,
- { "Length", "dtls.handshake.length",
- FT_UINT24, BASE_DEC, NULL, 0x0,
- "Length of handshake message", HFILL }
- },
- { &hf_dtls_handshake_message_seq,
- { "Message Sequence", "dtls.handshake.message_seq",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "Message sequence of handshake message", HFILL }
- },
- { &hf_dtls_handshake_fragment_offset,
- { "Fragment Offset", "dtls.handshake.fragment_offset",
- FT_UINT24, BASE_DEC, NULL, 0x0,
- "Fragment offset of handshake message", HFILL }
- },
- { &hf_dtls_handshake_fragment_length,
- { "Fragment Length", "dtls.handshake.fragment_length",
- FT_UINT24, BASE_DEC, NULL, 0x0,
- "Fragment length of handshake message", HFILL }
- },
- { &hf_dtls_handshake_client_version,
- { "Version", "dtls.handshake.version",
- FT_UINT16, BASE_HEX, VALS(ssl_versions), 0x0,
- "Maximum version supported by client", HFILL }
- },
- { &hf_dtls_handshake_server_version,
- { "Version", "dtls.handshake.version",
- FT_UINT16, BASE_HEX, VALS(ssl_versions), 0x0,
- "Version selected by server", HFILL }
- },
- { &hf_dtls_handshake_random_time,
- { "Random.gmt_unix_time", "dtls.handshake.random_time",
- FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
- "Unix time field of random structure", HFILL }
- },
- { &hf_dtls_handshake_random_bytes,
- { "Random.bytes", "dtls.handshake.random",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "Random challenge used to authenticate server", HFILL }
- },
- { &hf_dtls_handshake_cipher_suites_len,
- { "Cipher Suites Length", "dtls.handshake.cipher_suites_length",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "Length of cipher suites field", HFILL }
- },
- { &hf_dtls_handshake_cipher_suites,
- { "Cipher Suites", "dtls.handshake.ciphersuites",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "List of cipher suites supported by client", HFILL }
- },
- { &hf_dtls_handshake_cipher_suite,
- { "Cipher Suite", "dtls.handshake.ciphersuite",
- FT_UINT16, BASE_HEX, VALS(ssl_31_ciphersuite), 0x0,
- "Cipher suite", HFILL }
- },
- { &hf_dtls_handshake_cookie_len,
- { "Cookie Length", "dtls.handshake.cookie_length",
- FT_UINT8, BASE_DEC, NULL, 0x0,
- "Length of the cookie field", HFILL }
- },
- { &hf_dtls_handshake_cookie,
- { "Cookie", "dtls.handshake.cookie",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "Cookie", HFILL }
- },
- { &hf_dtls_handshake_session_id,
- { "Session ID", "dtls.handshake.session_id",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "Identifies the DTLS session, allowing later resumption", HFILL }
- },
- { &hf_dtls_handshake_comp_methods_len,
- { "Compression Methods Length", "dtls.handshake.comp_methods_length",
- FT_UINT8, BASE_DEC, NULL, 0x0,
- "Length of compression methods field", HFILL }
- },
- { &hf_dtls_handshake_comp_methods,
- { "Compression Methods", "dtls.handshake.comp_methods",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "List of compression methods supported by client", HFILL }
- },
- { &hf_dtls_handshake_comp_method,
- { "Compression Method", "dtls.handshake.comp_method",
- FT_UINT8, BASE_DEC, VALS(ssl_31_compression_method), 0x0,
- "Compression Method", HFILL }
- },
- { &hf_dtls_handshake_extensions_len,
- { "Extensions Length", "dtls.handshake.extensions_length",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "Length of hello extensions", HFILL }
- },
- { &hf_dtls_handshake_extension_type,
- { "Type", "dtls.handshake.extension.type",
- FT_UINT16, BASE_HEX, VALS(tls_hello_extension_types), 0x0,
- "Hello extension type", HFILL }
- },
- { &hf_dtls_handshake_extension_len,
- { "Length", "dtls.handshake.extension.len",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "Length of a hello extension", HFILL }
- },
- { &hf_dtls_handshake_extension_data,
- { "Data", "dtls.handshake.extension.data",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "Hello Extension data", HFILL }
- },
- { &hf_dtls_handshake_certificates_len,
- { "Certificates Length", "dtls.handshake.certificates_length",
- FT_UINT24, BASE_DEC, NULL, 0x0,
- "Length of certificates field", HFILL }
- },
- { &hf_dtls_handshake_certificates,
- { "Certificates", "dtls.handshake.certificates",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "List of certificates", HFILL }
- },
- { &hf_dtls_handshake_certificate,
- { "Certificate", "dtls.handshake.certificate",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "Certificate", HFILL }
- },
- { &hf_dtls_handshake_certificate_len,
- { "Certificate Length", "dtls.handshake.certificate_length",
- FT_UINT24, BASE_DEC, NULL, 0x0,
- "Length of certificate", HFILL }
- },
- { &hf_dtls_handshake_cert_types_count,
- { "Certificate types count", "dtls.handshake.cert_types_count",
- FT_UINT8, BASE_DEC, NULL, 0x0,
- "Count of certificate types", HFILL }
- },
- { &hf_dtls_handshake_cert_types,
- { "Certificate types", "dtls.handshake.cert_types",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "List of certificate types", HFILL }
- },
- { &hf_dtls_handshake_cert_type,
- { "Certificate type", "dtls.handshake.cert_type",
- FT_UINT8, BASE_DEC, VALS(ssl_31_client_certificate_type), 0x0,
- "Certificate type", HFILL }
- },
- { &hf_dtls_handshake_finished,
- { "Verify Data", "dtls.handshake.verify_data",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "Opaque verification data", HFILL }
- },
- { &hf_dtls_handshake_md5_hash,
- { "MD5 Hash", "dtls.handshake.md5_hash",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "Hash of messages, master_secret, etc.", HFILL }
- },
- { &hf_dtls_handshake_sha_hash,
- { "SHA-1 Hash", "dtls.handshake.sha_hash",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "Hash of messages, master_secret, etc.", HFILL }
- },
- { &hf_dtls_handshake_session_id_len,
- { "Session ID Length", "dtls.handshake.session_id_length",
- FT_UINT8, BASE_DEC, NULL, 0x0,
- "Length of session ID field", HFILL }
- },
- { &hf_dtls_handshake_dnames_len,
- { "Distinguished Names Length", "dtls.handshake.dnames_len",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "Length of list of CAs that server trusts", HFILL }
- },
- { &hf_dtls_handshake_dnames,
- { "Distinguished Names", "dtls.handshake.dnames",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "List of CAs that server trusts", HFILL }
- },
- { &hf_dtls_handshake_dname_len,
- { "Distinguished Name Length", "dtls.handshake.dname_len",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "Length of distinguished name", HFILL }
- },
- { &hf_dtls_handshake_dname,
- { "Distinguished Name", "dtls.handshake.dname",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "Distinguished name of a CA that server trusts", HFILL }
- },
- };
-
- /* Setup protocol subtree array */
- static gint *ett[] = {
- &ett_dtls,
- &ett_dtls_record,
- &ett_dtls_alert,
- &ett_dtls_handshake,
- &ett_dtls_cipher_suites,
- &ett_dtls_comp_methods,
- &ett_dtls_extension,
- &ett_dtls_certs,
- &ett_dtls_cert_types,
- &ett_dtls_dnames,
- };
-
- /* Register the protocol name and description */
- proto_dtls = proto_register_protocol("Datagram Transport Layer Security",
- "DTLS", "dtls");
-
- /* Required function calls to register the header fields and
- * subtrees used */
- proto_register_field_array(proto_dtls, hf, array_length(hf));
- proto_register_subtree_array(ett, array_length(ett));
-
- {
- module_t *dtls_module = prefs_register_protocol(proto_dtls, ssl_parse);
- prefs_register_string_preference(dtls_module, "keys_list", "RSA keys list",
- "comma separated list of private RSA keys used for DTLS decryption; "
- "each list entry must be in the form of <ip>:<port>:<key_file_name>"
- "<key_file_name> is the local file name of the RSA private key used by the specified server\n",
- (const char **)&dtls_keys_list);
- prefs_register_string_preference(dtls_module, "ports_list", "DTLS ports list",
- "comma separated list of tcp ports numbers to be dissectes as DTLS; "
- "each list entry must be in the form of <port>:<clear-text-port>"
- "<clear-text-port> is the port numbert associated with the protocol tunneled over DTLS for this port\n",
- (const char **)&dtls_ports_list);
- prefs_register_string_preference(dtls_module, "debug_file", "DTLS debug file",
- "redirect dtls debug to file name; leave empty to disable debug, "
- "use \"" SSL_DEBUG_USE_STDERR "\" to redirect output to stderr\n",
- (const char **)&dtls_debug_file_name);
- }
+ /* Setup list of header fields See Section 1.6.1 for details*/
+ static hf_register_info hf[] = {
+ { &hf_dtls_record,
+ { "Record Layer", "dtls.record",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Record layer", HFILL }
+ },
+ { &hf_dtls_record_content_type,
+ { "Content Type", "dtls.record.content_type",
+ FT_UINT8, BASE_DEC, VALS(ssl_31_content_type), 0x0,
+ "Content type", HFILL}
+ },
+ { &hf_dtls_record_version,
+ { "Version", "dtls.record.version",
+ FT_UINT16, BASE_HEX, VALS(ssl_versions), 0x0,
+ "Record layer version.", HFILL }
+ },
+ { &hf_dtls_record_epoch,
+ { "Epoch", "dtls.record.epoch",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Epoch", HFILL }
+ },
+ { &hf_dtls_record_sequence_number,
+ { "Sequence Number", "dtls.record.sequence_number",
+ FT_DOUBLE, BASE_DEC, NULL, 0x0,
+ "Sequence Number", HFILL }
+ },
+ { &hf_dtls_record_length,
+ { "Length", "dtls.record.length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of DTLS record data", HFILL }
+ },
+ { &hf_dtls_record_appdata,
+ { "Encrypted Application Data", "dtls.app_data",
+ FT_BYTES, BASE_HEX, NULL, 0x0,
+ "Payload is encrypted application data", HFILL }
+ },
+ { &hf_dtls_change_cipher_spec,
+ { "Change Cipher Spec Message", "dtls.change_cipher_spec",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Signals a change in cipher specifications", HFILL }
+ },
+ { & hf_dtls_alert_message,
+ { "Alert Message", "dtls.alert_message",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Alert message", HFILL }
+ },
+ { & hf_dtls_alert_message_level,
+ { "Level", "dtls.alert_message.level",
+ FT_UINT8, BASE_DEC, VALS(ssl_31_alert_level), 0x0,
+ "Alert message level", HFILL }
+ },
+ { &hf_dtls_alert_message_description,
+ { "Description", "dtls.alert_message.desc",
+ FT_UINT8, BASE_DEC, VALS(ssl_31_alert_description), 0x0,
+ "Alert message description", HFILL }
+ },
+ { &hf_dtls_handshake_protocol,
+ { "Handshake Protocol", "dtls.handshake",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Handshake protocol message", HFILL}
+ },
+ { &hf_dtls_handshake_type,
+ { "Handshake Type", "dtls.handshake.type",
+ FT_UINT8, BASE_DEC, VALS(ssl_31_handshake_type), 0x0,
+ "Type of handshake message", HFILL}
+ },
+ { &hf_dtls_handshake_length,
+ { "Length", "dtls.handshake.length",
+ FT_UINT24, BASE_DEC, NULL, 0x0,
+ "Length of handshake message", HFILL }
+ },
+ { &hf_dtls_handshake_message_seq,
+ { "Message Sequence", "dtls.handshake.message_seq",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Message sequence of handshake message", HFILL }
+ },
+ { &hf_dtls_handshake_fragment_offset,
+ { "Fragment Offset", "dtls.handshake.fragment_offset",
+ FT_UINT24, BASE_DEC, NULL, 0x0,
+ "Fragment offset of handshake message", HFILL }
+ },
+ { &hf_dtls_handshake_fragment_length,
+ { "Fragment Length", "dtls.handshake.fragment_length",
+ FT_UINT24, BASE_DEC, NULL, 0x0,
+ "Fragment length of handshake message", HFILL }
+ },
+ { &hf_dtls_handshake_client_version,
+ { "Version", "dtls.handshake.version",
+ FT_UINT16, BASE_HEX, VALS(ssl_versions), 0x0,
+ "Maximum version supported by client", HFILL }
+ },
+ { &hf_dtls_handshake_server_version,
+ { "Version", "dtls.handshake.version",
+ FT_UINT16, BASE_HEX, VALS(ssl_versions), 0x0,
+ "Version selected by server", HFILL }
+ },
+ { &hf_dtls_handshake_random_time,
+ { "Random.gmt_unix_time", "dtls.handshake.random_time",
+ FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x0,
+ "Unix time field of random structure", HFILL }
+ },
+ { &hf_dtls_handshake_random_bytes,
+ { "Random.bytes", "dtls.handshake.random",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Random challenge used to authenticate server", HFILL }
+ },
+ { &hf_dtls_handshake_cipher_suites_len,
+ { "Cipher Suites Length", "dtls.handshake.cipher_suites_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of cipher suites field", HFILL }
+ },
+ { &hf_dtls_handshake_cipher_suites,
+ { "Cipher Suites", "dtls.handshake.ciphersuites",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "List of cipher suites supported by client", HFILL }
+ },
+ { &hf_dtls_handshake_cipher_suite,
+ { "Cipher Suite", "dtls.handshake.ciphersuite",
+ FT_UINT16, BASE_HEX, VALS(ssl_31_ciphersuite), 0x0,
+ "Cipher suite", HFILL }
+ },
+ { &hf_dtls_handshake_cookie_len,
+ { "Cookie Length", "dtls.handshake.cookie_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Length of the cookie field", HFILL }
+ },
+ { &hf_dtls_handshake_cookie,
+ { "Cookie", "dtls.handshake.cookie",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Cookie", HFILL }
+ },
+ { &hf_dtls_handshake_session_id,
+ { "Session ID", "dtls.handshake.session_id",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Identifies the DTLS session, allowing later resumption", HFILL }
+ },
+ { &hf_dtls_handshake_comp_methods_len,
+ { "Compression Methods Length", "dtls.handshake.comp_methods_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Length of compression methods field", HFILL }
+ },
+ { &hf_dtls_handshake_comp_methods,
+ { "Compression Methods", "dtls.handshake.comp_methods",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "List of compression methods supported by client", HFILL }
+ },
+ { &hf_dtls_handshake_comp_method,
+ { "Compression Method", "dtls.handshake.comp_method",
+ FT_UINT8, BASE_DEC, VALS(ssl_31_compression_method), 0x0,
+ "Compression Method", HFILL }
+ },
+ { &hf_dtls_handshake_extensions_len,
+ { "Extensions Length", "dtls.handshake.extensions_length",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of hello extensions", HFILL }
+ },
+ { &hf_dtls_handshake_extension_type,
+ { "Type", "dtls.handshake.extension.type",
+ FT_UINT16, BASE_HEX, VALS(tls_hello_extension_types), 0x0,
+ "Hello extension type", HFILL }
+ },
+ { &hf_dtls_handshake_extension_len,
+ { "Length", "dtls.handshake.extension.len",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of a hello extension", HFILL }
+ },
+ { &hf_dtls_handshake_extension_data,
+ { "Data", "dtls.handshake.extension.data",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Hello Extension data", HFILL }
+ },
+ { &hf_dtls_handshake_certificates_len,
+ { "Certificates Length", "dtls.handshake.certificates_length",
+ FT_UINT24, BASE_DEC, NULL, 0x0,
+ "Length of certificates field", HFILL }
+ },
+ { &hf_dtls_handshake_certificates,
+ { "Certificates", "dtls.handshake.certificates",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "List of certificates", HFILL }
+ },
+ { &hf_dtls_handshake_certificate,
+ { "Certificate", "dtls.handshake.certificate",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Certificate", HFILL }
+ },
+ { &hf_dtls_handshake_certificate_len,
+ { "Certificate Length", "dtls.handshake.certificate_length",
+ FT_UINT24, BASE_DEC, NULL, 0x0,
+ "Length of certificate", HFILL }
+ },
+ { &hf_dtls_handshake_cert_types_count,
+ { "Certificate types count", "dtls.handshake.cert_types_count",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Count of certificate types", HFILL }
+ },
+ { &hf_dtls_handshake_cert_types,
+ { "Certificate types", "dtls.handshake.cert_types",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "List of certificate types", HFILL }
+ },
+ { &hf_dtls_handshake_cert_type,
+ { "Certificate type", "dtls.handshake.cert_type",
+ FT_UINT8, BASE_DEC, VALS(ssl_31_client_certificate_type), 0x0,
+ "Certificate type", HFILL }
+ },
+ { &hf_dtls_handshake_finished,
+ { "Verify Data", "dtls.handshake.verify_data",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Opaque verification data", HFILL }
+ },
+ { &hf_dtls_handshake_md5_hash,
+ { "MD5 Hash", "dtls.handshake.md5_hash",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Hash of messages, master_secret, etc.", HFILL }
+ },
+ { &hf_dtls_handshake_sha_hash,
+ { "SHA-1 Hash", "dtls.handshake.sha_hash",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "Hash of messages, master_secret, etc.", HFILL }
+ },
+ { &hf_dtls_handshake_session_id_len,
+ { "Session ID Length", "dtls.handshake.session_id_length",
+ FT_UINT8, BASE_DEC, NULL, 0x0,
+ "Length of session ID field", HFILL }
+ },
+ { &hf_dtls_handshake_dnames_len,
+ { "Distinguished Names Length", "dtls.handshake.dnames_len",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of list of CAs that server trusts", HFILL }
+ },
+ { &hf_dtls_handshake_dnames,
+ { "Distinguished Names", "dtls.handshake.dnames",
+ FT_NONE, BASE_NONE, NULL, 0x0,
+ "List of CAs that server trusts", HFILL }
+ },
+ { &hf_dtls_handshake_dname_len,
+ { "Distinguished Name Length", "dtls.handshake.dname_len",
+ FT_UINT16, BASE_DEC, NULL, 0x0,
+ "Length of distinguished name", HFILL }
+ },
+ { &hf_dtls_handshake_dname,
+ { "Distinguished Name", "dtls.handshake.dname",
+ FT_BYTES, BASE_NONE, NULL, 0x0,
+ "Distinguished name of a CA that server trusts", HFILL }
+ },
+ };
+
+ /* Setup protocol subtree array */
+ static gint *ett[] = {
+ &ett_dtls,
+ &ett_dtls_record,
+ &ett_dtls_alert,
+ &ett_dtls_handshake,
+ &ett_dtls_cipher_suites,
+ &ett_dtls_comp_methods,
+ &ett_dtls_extension,
+ &ett_dtls_certs,
+ &ett_dtls_cert_types,
+ &ett_dtls_dnames,
+ };
+
+ /* Register the protocol name and description */
+ proto_dtls = proto_register_protocol("Datagram Transport Layer Security",
+ "DTLS", "dtls");
+
+ /* Required function calls to register the header fields and
+ * subtrees used */
+ proto_register_field_array(proto_dtls, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ {
+ module_t *dtls_module = prefs_register_protocol(proto_dtls, dtls_parse);
+#ifdef HAVE_LIBGNUTLS
+ prefs_register_string_preference(dtls_module, "keys_list", "RSA keys list",
+ "semicolon separated list of private RSA keys used for DTLS decryption; "
+ "each list entry must be in the form of <ip>,<port>,<protocol>,<key_file_name>"
+ "<key_file_name> is the local file name of the RSA private key used by the specified server\n",
+ (const gchar **)&dtls_keys_list);
+ prefs_register_string_preference(dtls_module, "debug_file", "DTLS debug file",
+ "redirect dtls debug to file name; leave empty to disable debug, "
+ "use \"" SSL_DEBUG_USE_STDERR "\" to redirect output to stderr\n",
+ (const gchar **)&dtls_debug_file_name);
+#endif
+ }
- register_dissector("dtls", dissect_dtls, proto_dtls);
+ register_dissector("dtls", dissect_dtls, proto_dtls);
- register_init_routine(ssl_init);
- ssl_lib_init();
- dtls_tap = register_tap("dtls");
- ssl_debug_printf("proto_register_dtls: registered tap %s:%d\n",
- "dtls", dtls_tap);
+ register_init_routine(dtls_init);
+ ssl_lib_init();
+ dtls_tap = register_tap("dtls");
+ ssl_debug_printf("proto_register_dtls: registered tap %s:%d\n",
+ "dtls", dtls_tap);
}
/* If this dissector uses sub-dissector registration add a registration
@@ -3864,8 +2162,8 @@ proto_register_dtls(void)
void
proto_reg_handoff_dtls(void)
{
- dtls_handle = find_dissector("dtls");
+ dtls_handle = find_dissector("dtls");
- /* add now dissector to default ports.*/
- ssl_parse();
+ /* add now dissector to default ports.*/
+ dtls_parse();
}
diff --git a/epan/dissectors/packet-ssl-utils.c b/epan/dissectors/packet-ssl-utils.c
index 35ceb11260..bc319b8a8b 100644
--- a/epan/dissectors/packet-ssl-utils.c
+++ b/epan/dissectors/packet-ssl-utils.c
@@ -29,8 +29,10 @@
#include <string.h>
#include "packet-ssl-utils.h"
+#include <epan/emem.h>
+
void
-ssl_data_set(StringInfo* str, unsigned char* data, unsigned int len)
+ssl_data_set(StringInfo* str, guchar* data, guint len)
{
memcpy(str->data, data, len);
str->data_len = len;
@@ -42,21 +44,23 @@ ssl_data_set(StringInfo* str, unsigned char* data, unsigned int len)
#define SSL_HMAC gcry_md_hd_t
static inline void
-ssl_hmac_init(SSL_HMAC* md, const void * key, int len, int algo)
+ssl_hmac_init(SSL_HMAC* md, const void * key, gint len, gint algo)
{
gcry_md_open(md,algo, GCRY_MD_FLAG_HMAC);
gcry_md_setkey (*(md), key, len);
}
static inline void
-ssl_hmac_update(SSL_HMAC* md, const void* data, int len)
+ssl_hmac_update(SSL_HMAC* md, const void* data, gint len)
{
gcry_md_write(*(md), data, len);
}
static inline void
-ssl_hmac_final(SSL_HMAC* md, unsigned char* data, unsigned int* datalen)
+ssl_hmac_final(SSL_HMAC* md, guchar* data, guint* datalen)
{
- int algo = gcry_md_get_algo (*(md));
- unsigned int len = gcry_md_get_algo_dlen(algo);
+ gint algo;
+ guint len;
+ algo = gcry_md_get_algo (*(md));
+ len = gcry_md_get_algo_dlen(algo);
memcpy(data, gcry_md_read(*(md), algo), len);
*datalen =len;
}
@@ -70,20 +74,22 @@ ssl_hmac_cleanup(SSL_HMAC* md)
#define SSL_MD gcry_md_hd_t
static inline void
-ssl_md_init(SSL_MD* md, int algo)
+ssl_md_init(SSL_MD* md, gint algo)
{
gcry_md_open(md,algo, 0);
}
static inline void
-ssl_md_update(SSL_MD* md, unsigned char* data, int len)
+ssl_md_update(SSL_MD* md, guchar* data, gint len)
{
gcry_md_write(*(md), data, len);
}
static inline void
-ssl_md_final(SSL_MD* md, unsigned char* data, unsigned int* datalen)
+ssl_md_final(SSL_MD* md, guchar* data, guint* datalen)
{
- int algo = gcry_md_get_algo (*(md));
- int len = gcry_md_get_algo_dlen (algo);
+ gint algo;
+ gint len;
+ algo = gcry_md_get_algo (*(md));
+ len = gcry_md_get_algo_dlen (algo);
memcpy(data, gcry_md_read(*(md), algo), len);
*datalen = len;
}
@@ -103,12 +109,12 @@ ssl_sha_init(SSL_SHA_CTX* md)
gcry_md_open(md,GCRY_MD_SHA1, 0);
}
static inline void
-ssl_sha_update(SSL_SHA_CTX* md, unsigned char* data, int len)
+ssl_sha_update(SSL_SHA_CTX* md, guchar* data, gint len)
{
gcry_md_write(*(md), data, len);
}
static inline void
-ssl_sha_final(unsigned char* buf, SSL_SHA_CTX* md)
+ssl_sha_final(guchar* buf, SSL_SHA_CTX* md)
{
memcpy(buf, gcry_md_read(*(md), GCRY_MD_SHA1),
gcry_md_get_algo_dlen(GCRY_MD_SHA1));
@@ -119,18 +125,18 @@ ssl_sha_cleanup(SSL_SHA_CTX* md)
gcry_md_close(*(md));
}
-static inline int
+static inline gint
ssl_md5_init(SSL_MD5_CTX* md)
{
return gcry_md_open(md,GCRY_MD_MD5, 0);
}
static inline void
-ssl_md5_update(SSL_MD5_CTX* md, unsigned char* data, int len)
+ssl_md5_update(SSL_MD5_CTX* md, guchar* data, gint len)
{
gcry_md_write(*(md), data, len);
}
static inline void
-ssl_md5_final(unsigned char* buf, SSL_MD5_CTX* md)
+ssl_md5_final(guchar* buf, SSL_MD5_CTX* md)
{
memcpy(buf, gcry_md_read(*(md), GCRY_MD_MD5),
gcry_md_get_algo_dlen(GCRY_MD_MD5));
@@ -141,13 +147,14 @@ ssl_md5_cleanup(SSL_MD5_CTX* md)
gcry_md_close(*(md));
}
-static int
-ssl_cipher_setiv(gcry_cipher_hd_t *cipher,unsigned char* iv, int iv_len)
+static gint
+ssl_cipher_setiv(gcry_cipher_hd_t *cipher,guchar* iv, gint iv_len)
{
- unsigned char * ivp;
- int ret=0;
- int i;
+ /* guchar * ivp; */
+ gint ret;
+ /* gint i; */
gcry_cipher_hd_t c;
+ ret=0;
c=(gcry_cipher_hd_t)*cipher;
ssl_debug_printf("--------------------------------------------------------------------");
@@ -169,15 +176,13 @@ ssl_cipher_setiv(gcry_cipher_hd_t *cipher,unsigned char* iv, int iv_len)
return ret;
}
/* stream cipher abstraction layer*/
-static int
-ssl_cipher_init(gcry_cipher_hd_t *cipher, int algo, unsigned char* sk,
- unsigned char* iv, int mode)
-{
- int gcry_modes[]={
- GCRY_CIPHER_MODE_STREAM,
- GCRY_CIPHER_MODE_CBC
- };
- int err = gcry_cipher_open(cipher, algo, gcry_modes[mode], 0);
+static gint
+ssl_cipher_init(gcry_cipher_hd_t *cipher, gint algo, guchar* sk,
+ guchar* iv, gint mode)
+{
+ gint gcry_modes[]={GCRY_CIPHER_MODE_STREAM,GCRY_CIPHER_MODE_CBC};
+ gint err;
+ err = gcry_cipher_open(cipher, algo, gcry_modes[mode], 0);
if (err !=0)
return -1;
err = gcry_cipher_setkey(*(cipher), sk, gcry_cipher_get_algo_keylen (algo));
@@ -188,19 +193,19 @@ ssl_cipher_init(gcry_cipher_hd_t *cipher, int algo, unsigned char* sk,
return -1;
return 0;
}
-static inline int
-ssl_cipher_decrypt(gcry_cipher_hd_t *cipher, unsigned char * out, int outl,
- const unsigned char * in,int inl)
+static inline gint
+ssl_cipher_decrypt(gcry_cipher_hd_t *cipher, guchar * out, gint outl,
+ const guchar * in, gint inl)
{
return gcry_cipher_decrypt ( *(cipher), out, outl, in, inl);
}
-static inline int
-ssl_get_digest_by_name(const char*name)
+static inline gint
+ssl_get_digest_by_name(const gchar*name)
{
return gcry_md_map_name(name);
}
-static inline int
-ssl_get_cipher_by_name(const char* name)
+static inline gint
+ssl_get_cipher_by_name(const gchar* name)
{
return gcry_cipher_map_name(name);
}
@@ -213,28 +218,30 @@ ssl_cipher_cleanup(gcry_cipher_hd_t *cipher)
}
/* private key abstraction layer */
-static inline int
+static inline gint
ssl_get_key_len(SSL_PRIVATE_KEY* pk) {return gcry_pk_get_nbits (pk); }
gcry_err_code_t
_gcry_rsa_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
- gcry_mpi_t *skey, int flags);
+ gcry_mpi_t *skey, gint flags);
#define PUBKEY_FLAG_NO_BLINDING (1 << 0)
/* decrypt data with private key. Store decrypted data directly into input
* buffer */
int
-ssl_private_decrypt(unsigned int len, unsigned char* encr_data, SSL_PRIVATE_KEY* pk)
+ssl_private_decrypt(guint len, guchar* encr_data, SSL_PRIVATE_KEY* pk)
{
- int rc;
- size_t decr_len = 0;
+ gint rc;
+ size_t decr_len;
gcry_sexp_t s_data, s_plain;
gcry_mpi_t encr_mpi;
- size_t i, encr_len = len;
- unsigned char* decr_data_ptr;
- gcry_mpi_t text=NULL;
-
+ size_t i, encr_len;
+ guchar* decr_data_ptr;
+ gcry_mpi_t text;
+ decr_len = 0;
+ encr_len = len;
+ text=NULL;
/* build up a mpi rappresentation for encrypted data */
rc = gcry_mpi_scan(&encr_mpi, GCRYMPI_FMT_USG,encr_data, encr_len, &encr_len);
if (rc != 0 ) {
@@ -349,8 +356,8 @@ out:
}
/* stringinfo interface */
-static int
-ssl_data_alloc(StringInfo* str, unsigned int len)
+static gint
+ssl_data_alloc(StringInfo* str, guint len)
{
str->data = g_malloc(len);
if (!str->data)
@@ -363,12 +370,12 @@ ssl_data_alloc(StringInfo* str, unsigned int len)
ssl3_prf(secret,usage,rnd1,rnd2,out): \
tls_prf(secret,usage,rnd1,rnd2,out))
-static const char *digests[]={
+static const gchar *digests[]={
"MD5",
"SHA1"
};
-static const char *ciphers[]={
+static const gchar *ciphers[]={
"DES",
"3DES",
"ARCFOUR", /* gnutls does not support rc4, but this should be 100% compatible*/
@@ -438,17 +445,20 @@ ssl_find_cipher(int num,SslCipherSuite* cs)
return -1;
}
-static int
+static gint
tls_hash(StringInfo* secret,
- StringInfo* seed, int md, StringInfo* out)
+ StringInfo* seed, gint md, StringInfo* out)
{
- guint8 *ptr=out->data;
- unsigned int left=out->data_len;
- int tocpy;
+ guint8 *ptr;
+ guint left;
+ gint tocpy;
guint8 *A;
guint8 _A[20],tmp[20];
- unsigned int A_l,tmp_l;
+ guint A_l,tmp_l;
SSL_HMAC hm;
+ ptr=out->data;
+ left=out->data_len;
+
ssl_print_string("tls_hash: hash secret", secret);
ssl_print_string("tls_hash: hash seed", seed);
@@ -478,16 +488,18 @@ tls_hash(StringInfo* secret,
return (0);
}
-static int
-tls_prf(StringInfo* secret, const char *usage,
+static gint
+tls_prf(StringInfo* secret, const gchar *usage,
StringInfo* rnd1, StringInfo* rnd2, StringInfo* out)
{
StringInfo seed, sha_out, md5_out;
guint8 *ptr;
StringInfo s1, s2;
- unsigned int i,s_l, r=-1;
- int usage_len = strlen(usage);
-
+ guint i,s_l, r;
+ gint usage_len;
+ r=-1;
+ usage_len = strlen(usage);
+
/* initalize buffer for sha, md5 random seed*/
if (ssl_data_alloc(&sha_out, MAX(out->data_len,20)) < 0)
return -1;
@@ -536,7 +548,7 @@ free_sha:
return r;
}
-static int
+static gint
ssl3_generate_export_iv(StringInfo* r1,
StringInfo* r2, StringInfo* out)
{
@@ -555,23 +567,23 @@ ssl3_generate_export_iv(StringInfo* r1,
return(0);
}
-static int
-ssl3_prf(StringInfo* secret, const char* usage,
+static gint
+ssl3_prf(StringInfo* secret, const gchar* usage,
StringInfo* r1,
StringInfo* r2,StringInfo* out)
{
SSL_MD5_CTX md5;
SSL_SHA_CTX sha;
StringInfo *rnd1,*rnd2;
- unsigned int off;
- int i=0,j;
+ guint off;
+ gint i=0,j;
guint8 buf[20];
rnd1=r1; rnd2=r2;
for(off=0;off<out->data_len;off+=16){
- unsigned char outbuf[16];
- int tocpy;
+ guchar outbuf[16];
+ gint tocpy;
i++;
ssl_debug_printf("ssl3_prf: sha1_hash(%d)\n",i);
@@ -611,12 +623,12 @@ ssl3_prf(StringInfo* secret, const char* usage,
return(0);
}
-static int
+static gint
ssl_create_decoder(SslDecoder *dec, SslCipherSuite *cipher_suite,
guint8 *mk, guint8 *sk, guint8 *iv)
{
- int ciph=0;
-
+ gint ciph;
+ ciph=0;
/* Find the SSLeay cipher */
if(cipher_suite->enc!=ENC_NULL) {
ssl_debug_printf("ssl_create_decoder CIPHER: %s\n", ciphers[cipher_suite->enc-0x30]);
@@ -654,7 +666,7 @@ ssl_generate_keyring_material(SslDecryptSession*ssl_session)
StringInfo key_block;
guint8 _iv_c[MAX_BLOCK_SIZE],_iv_s[MAX_BLOCK_SIZE];
guint8 _key_c[MAX_KEY_SIZE],_key_s[MAX_KEY_SIZE];
- int needed;
+ gint needed;
guint8 *ptr,*c_wk,*s_wk,*c_mk,*s_mk,*c_iv = _iv_c,*s_iv = _iv_s;
/* if master_key is not yet generate, create it now*/
@@ -864,7 +876,7 @@ int
ssl_decrypt_pre_master_secret(SslDecryptSession*ssl_session,
StringInfo* entrypted_pre_master, SSL_PRIVATE_KEY *pk)
{
- int i;
+ gint i;
if(ssl_session->cipher_suite.kex!=KEX_RSA) {
ssl_debug_printf("ssl_decrypt_pre_master_secret key %d diferent from KEX_RSA(%d)\n",
@@ -898,7 +910,7 @@ ssl_decrypt_pre_master_secret(SslDecryptSession*ssl_session,
/* convert network byte order 32 byte number to right-aligned host byte order *
* 8 bytes buffer */
-static int fmt_seq(guint32 num, guint8* buf)
+static gint fmt_seq(guint32 num, guint8* buf)
{
guint32 netnum;
@@ -909,12 +921,12 @@ static int fmt_seq(guint32 num, guint8* buf)
return(0);
}
-static int
-tls_check_mac(SslDecoder*decoder, int ct,int ver, guint8* data,
+static gint
+tls_check_mac(SslDecoder*decoder, gint ct, gint ver, guint8* data,
guint32 datalen, guint8* mac)
{
SSL_HMAC hm;
- int md;
+ gint md;
guint32 len;
guint8 buf[20];
@@ -958,10 +970,10 @@ ssl3_check_mac(SslDecoder*decoder,int ct,guint8* data,
guint32 datalen, guint8* mac)
{
SSL_MD mc;
- int md;
+ gint md;
guint32 len;
guint8 buf[64],dgst[20];
- int pad_ct;
+ gint pad_ct;
pad_ct=(decoder->cipher_suite->dig==DIG_SHA)?40:48;
@@ -1014,12 +1026,12 @@ ssl3_check_mac(SslDecoder*decoder,int ct,guint8* data,
}
#if 0
-static int
-dtls_check_mac(SslDecoder*decoder, int ct,int ver, guint8* data,
+static gint
+dtls_check_mac(SslDecoder*decoder, gint ct,int ver, guint8* data,
guint32 datalen, guint8* mac)
{
SSL_HMAC hm;
- int md;
+ gint md;
guint32 len;
guint8 buf[20];
guint32 netnum;
@@ -1060,10 +1072,10 @@ dtls_check_mac(SslDecoder*decoder, int ct,int ver, guint8* data,
int
-ssl_decrypt_record(SslDecryptSession*ssl,SslDecoder* decoder, int ct,
- const unsigned char* in, int inl,unsigned char*out,int* outl)
+ssl_decrypt_record(SslDecryptSession*ssl,SslDecoder* decoder, gint ct,
+ const guchar* in, gint inl, guchar*out, gint* outl)
{
- int pad, worklen;
+ gint pad, worklen;
guint8 *mac;
@@ -1134,9 +1146,9 @@ ssl_decrypt_record(SslDecryptSession*ssl,SslDecoder* decoder, int ct,
/* old relase of gnutls does not define the appropriate macros, so get
* them from the string*/
static void
-ssl_get_version(int* major, int* minor, int* patch)
+ssl_get_version(gint* major, gint* minor, gint* patch)
{
- const char* str = gnutls_check_version(NULL);
+ const gchar* str = gnutls_check_version(NULL);
ssl_debug_printf("ssl_get_version: %s\n", str);
sscanf(str, "%d.%d.%d", major, minor, patch);
@@ -1153,9 +1165,9 @@ ssl_load_key(FILE* fp)
struct gnutls_x509_privkey_int* priv_key;
gnutls_datum key;
gnutls_datum m, e, d, p,q, u;
- int size, major, minor, patch;
- unsigned int bytes;
- unsigned int tmp_size;
+ gint size, major, minor, patch;
+ guint bytes;
+ guint tmp_size;
#ifdef SSL_FAST
gcry_mpi_t* rsa_params = g_malloc(sizeof(gcry_mpi_t)*6);
#else
@@ -1260,7 +1272,7 @@ ssl_load_key(FILE* fp)
return rsa_params;
#else
{
- int i;
+ gint i;
for (i=0; i< 6; i++)
gcry_mpi_release(rsa_params[i]);
}
@@ -1271,7 +1283,7 @@ ssl_load_key(FILE* fp)
void ssl_free_key(SSL_PRIVATE_KEY* key)
{
#if SSL_FAST
- int i;
+ gint i;
for (i=0; i< 6; i++)
gcry_mpi_release(key[i]);
#else
@@ -1329,8 +1341,8 @@ ssl_decrypt_pre_master_secret(SslDecryptSession* ssl_session,
}
int
-ssl_decrypt_record(SslDecryptSession*ssl,SslDecoder* decoder, int ct,
- const unsigned char* in, int inl,unsigned char*out,int* outl)
+ssl_decrypt_record(SslDecryptSession*ssl, SslDecoder* decoder, gint ct,
+ const guchar* in, gint inl, guchar*out, gint* outl)
{
ssl_debug_printf("ssl_decrypt_record: impossible without gnutls. ssl %p"
"decoder %p ct %d, in %p inl %d out %p outl %p\n", ssl, decoder, ct,
@@ -1345,7 +1357,7 @@ void
ssl_session_init(SslDecryptSession* ssl_session)
{
ssl_debug_printf("ssl_session_init: initializing ptr %p size %lu\n",
- ssl_session, (unsigned long)sizeof(SslDecryptSession));
+ ssl_session, (gulong)sizeof(SslDecryptSession));
ssl_session->master_secret.data = ssl_session->_master_secret;
ssl_session->session_id.data = ssl_session->_session_id;
@@ -1356,6 +1368,359 @@ ssl_session_init(SslDecryptSession* ssl_session)
ssl_session->app_data_segment.data_len=0;
}
+/* Hash Functions for TLS/DTLS sessions table and private keys table*/
+gint
+ssl_equal (gconstpointer v, gconstpointer v2)
+{
+ const StringInfo *val1;
+ const StringInfo *val2;
+ val1 = (const StringInfo *)v;
+ val2 = (const StringInfo *)v2;
+
+ if (val1->data_len == val2->data_len &&
+ !memcmp(val1->data, val2->data, val2->data_len)) {
+ return 1;
+ }
+ return 0;
+}
+
+guint
+ssl_hash (gconstpointer v)
+{
+ guint l,hash;
+ StringInfo* id;
+ guint* cur;
+ hash = 0;
+ id = (StringInfo*) v;
+ cur = (guint*) id->data;
+
+ for (l=4; (l<id->data_len); l+=4, cur++)
+ hash = hash ^ (*cur);
+
+ return hash;
+}
+
+gint
+ssl_private_key_equal (gconstpointer v, gconstpointer v2)
+{
+ const SslService *val1;
+ const SslService *val2;
+ val1 = (const SslService *)v;
+ val2 = (const SslService *)v2;
+
+ if ((val1->port == val2->port) &&
+ ! CMP_ADDRESS(&val1->addr, &val2->addr)) {
+ return 1;
+ }
+ return 0;
+}
+
+guint
+ssl_private_key_hash (gconstpointer v)
+{
+ const SslService *key;
+ guint l, hash, len ;
+ guint* cur;
+ key = (const SslService *)v;
+ hash = key->port;
+ len = key->addr.len;
+ cur = (guint*) key->addr.data;
+
+ for (l=4; (l<len); l+=4, cur++)
+ hash = hash ^ (*cur);
+
+ return hash;
+}
+
+/* private key table entries have a scope 'larger' then packet capture,
+ * so we can't relay on se_alloc** function */
+void
+ssl_private_key_free(gpointer id, gpointer key, gpointer dummy _U_)
+{
+ g_free(id);
+ ssl_free_key((SSL_PRIVATE_KEY*) key);
+}
+
+/* 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)
+{
+
+ SslAssociation* assoc;
+ assoc = g_malloc(sizeof(SslAssociation));
+
+ assoc->info=g_malloc(strlen(protocol)+1);
+ strcpy(assoc->info, protocol);
+ assoc->ssl_port = port;
+
+ assoc->handle = find_dissector(protocol);
+
+ ssl_debug_printf("association_add port %d protocol %s handle %p\n",
+ port, protocol, assoc->handle);
+
+
+ if(!assoc->handle){
+ fprintf(stderr, "association_add() could not find handle for protocol:%s\n",protocol);
+ } else {
+ if(tcp)
+ dissector_add("tcp.port", port, handle);
+ else
+ dissector_add("udp.port", port, handle);
+ g_tree_insert(associations, (gpointer)port, assoc);
+ }
+}
+
+
+gint
+ssl_association_cmp(gconstpointer a, gconstpointer b)
+{
+ return (gint)a-(gint)b;
+}
+
+SslAssociation*
+ssl_association_find(GTree * associations, guint port)
+{
+ register SslAssociation* ret;
+ ret = g_tree_lookup(associations, (gpointer)port);
+
+ ssl_debug_printf("association_find: port %d found %p\n", port, ret);
+ return ret;
+}
+
+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;
+}
+
+gint
+ssl_association_remove_handle_udp (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;
+}
+
+int
+ssl_packet_from_server(GTree* associations, guint port)
+{
+ register gint ret;
+ ret = ssl_association_find(associations, port) != 0;
+
+ ssl_debug_printf("packet_from_server: is from server %d\n", ret);
+ return ret;
+}
+
+/* add to packet data a newly allocated tvb with the specified real data*/
+void
+ssl_add_record_info(gint proto, packet_info *pinfo, guchar* data, gint data_len, gint record_id)
+{
+ guchar* real_data;
+ SslRecordInfo* rec;
+ SslPacketInfo* pi;
+ real_data = se_alloc(data_len);
+ rec = se_alloc(sizeof(SslRecordInfo));
+ pi = p_get_proto_data(pinfo->fd, proto);
+
+ if (!pi)
+ {
+ pi = se_alloc0(sizeof(SslPacketInfo));
+ p_add_proto_data(pinfo->fd, proto,pi);
+ }
+
+ rec->id = record_id;
+ rec->tvb = tvb_new_real_data(real_data, data_len, data_len);
+ memcpy(real_data, data, data_len);
+
+ /* head insertion */
+ rec->next= pi->handshake_data;
+ pi->handshake_data = rec;
+}
+
+
+/* search in packet data the tvbuff associated to the specified id */
+tvbuff_t*
+ssl_get_record_info(int proto, packet_info *pinfo, gint record_id)
+{
+ SslRecordInfo* rec;
+ SslPacketInfo* pi;
+ pi = p_get_proto_data(pinfo->fd, proto);
+
+ if (!pi)
+ return NULL;
+
+ for (rec = pi->handshake_data; rec; rec = rec->next)
+ if (rec->id == record_id)
+ return rec->tvb;
+
+ return NULL;
+}
+
+/* initialize/reset per capture state data (ssl sessions cache) */
+void
+ssl_common_init(GHashTable **session_hash , StringInfo * decrypted_data)
+{
+ if (*session_hash)
+ g_hash_table_destroy(*session_hash);
+ *session_hash = g_hash_table_new(ssl_hash, ssl_equal);
+ if (decrypted_data->data)
+ g_free(decrypted_data->data);
+ decrypted_data->data = g_malloc0(32);
+ decrypted_data->data_len = 32;
+}
+
+/* parse ssl related preferences (private keys and ports association strings) */
+void
+ssl_parse_key_list(const gchar * keys_list, GHashTable *key_hash, GTree* associations, dissector_handle_t handle, gboolean tcp)
+{
+ gchar* end;
+ gchar* start;
+ gchar* tmp;
+ guchar* ip;
+ SslService* service;
+ SSL_PRIVATE_KEY * private_key;
+ FILE* fp;
+
+ start = strdup(keys_list);
+ tmp = start;
+ ssl_debug_printf("ssl_init keys string %s\n", start);
+ do {
+ gchar* addr, *port, *protocol, *filename;
+
+ addr = start;
+ /* split ip/file couple with ';' separator*/
+ end = strchr(start, ';');
+ if (end) {
+ *end = 0;
+ start = end+1;
+ }
+
+ /* for each entry split ip, port, protocol, filename with ',' separator */
+ ssl_debug_printf("ssl_init found host entry %s\n", addr);
+ port = strchr(addr, ',');
+ if (!port)
+ {
+ ssl_debug_printf("ssl_init entry malformed can't find port in %s\n", addr);
+ break;
+ }
+ *port = 0;
+ port++;
+
+ protocol = strchr(port,',');
+ if (!protocol)
+ {
+ ssl_debug_printf("ssl_init entry malformed can't find protocol in %s\n", port);
+ break;
+ }
+ *protocol=0;
+ protocol++;
+
+ filename = strchr(protocol,',');
+ if (!filename)
+ {
+ ssl_debug_printf("ssl_init entry malformed can't find filename in %s\n", port);
+ break;
+ }
+ *filename=0;
+ filename++;
+
+ /* convert ip and port string to network rappresentation*/
+ service = g_malloc(sizeof(SslService) + 4);
+ service->addr.type = AT_IPv4;
+ service->addr.len = 4;
+ service->addr.data = ip = ((guchar*)service) + sizeof(SslService);
+ sscanf(addr, "%hhu.%hhu.%hhu.%hhu", &ip[0], &ip[1], &ip[2], &ip[3]);
+ service->port = atoi(port);
+ ssl_debug_printf("ssl_init addr %hhu.%hhu.%hhu.%hhu port %d filename %s\n",
+ ip[0], ip[1], ip[2], ip[3], service->port, filename);
+
+ /* try to load pen file*/
+ fp = fopen(filename, "rb");
+ if (!fp) {
+ fprintf(stderr, "can't open file %s \n",filename);
+ break;
+ }
+
+ private_key = ssl_load_key(fp);
+ if (!private_key) {
+ fprintf(stderr,"can't load private key from %s\n",
+ filename);
+ break;
+ }
+ fclose(fp);
+
+ ssl_debug_printf("ssl_init private key file %s successfully loaded\n",
+ filename);
+ g_hash_table_insert(key_hash, service, private_key);
+
+ ssl_association_add(associations, handle, atoi(port), protocol, tcp);
+
+ } while (end != NULL);
+ free(tmp);
+}
+
+/* store master secret into session data cache */
+void
+ssl_save_session(SslDecryptSession* ssl, GHashTable *session_hash)
+{
+ /* allocate stringinfo chunks for session id and master secret data*/
+ StringInfo* session_id;
+ StringInfo* master_secret;
+ session_id = se_alloc0(sizeof(StringInfo) + ssl->session_id.data_len);
+ master_secret = se_alloc0(48 + sizeof(StringInfo));
+
+ master_secret->data = ((guchar*)master_secret+sizeof(StringInfo));
+ session_id->data = ((guchar*)session_id+sizeof(StringInfo));
+
+ ssl_data_set(session_id, ssl->session_id.data, ssl->session_id.data_len);
+ ssl_data_set(master_secret, ssl->master_secret.data, ssl->master_secret.data_len);
+ g_hash_table_insert(session_hash, session_id, master_secret);
+ ssl_print_string("ssl_save_session stored session id", session_id);
+ ssl_print_string("ssl_save_session stored master secret", master_secret);
+}
+
+void
+ssl_restore_session(SslDecryptSession* ssl, GHashTable *session_hash)
+{
+ StringInfo* ms;
+ ms = g_hash_table_lookup(session_hash, &ssl->session_id);
+
+ if (!ms) {
+ ssl_debug_printf("ssl_restore_session can't find stored session\n");
+ return;
+ }
+ ssl_data_set(&ssl->master_secret, ms->data, ms->data_len);
+ ssl->state |= SSL_MASTER_SECRET;
+ ssl_debug_printf("ssl_restore_session master key retrived\n");
+}
+
+int
+ssl_is_valid_content_type(guint8 type)
+{
+ if (type >= 0x14 && type <= 0x17)
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
#ifdef SSL_DECRYPT_DEBUG
static FILE* ssl_debug_file=NULL;
@@ -1363,9 +1728,11 @@ static FILE* ssl_debug_file=NULL;
void
ssl_set_debug(char* name)
{
- static int debug_file_must_be_closed = 0;
- int use_stderr = name?(strcmp(name, SSL_DEBUG_USE_STDERR) == 0):0;
-
+ static gint debug_file_must_be_closed;
+ gint use_stderr;
+ debug_file_must_be_closed = 0;
+ use_stderr = name?(strcmp(name, SSL_DEBUG_USE_STDERR) == 0):0;
+
if (debug_file_must_be_closed)
fclose(ssl_debug_file);
if (use_stderr)
@@ -1380,10 +1747,12 @@ ssl_set_debug(char* name)
void
-ssl_debug_printf(const char* fmt, ...)
+ssl_debug_printf(const gchar* fmt, ...)
{
va_list ap;
- int ret=0;
+ gint ret;
+ ret=0;
+
if (!ssl_debug_file)
return;
@@ -1394,9 +1763,9 @@ ssl_debug_printf(const char* fmt, ...)
}
void
-ssl_print_text_data(const char* name, const unsigned char* data, int len)
+ssl_print_text_data(const gchar* name, const guchar* data, gint len)
{
- int i;
+ gint i;
if (!ssl_debug_file)
return;
fprintf(ssl_debug_file,"%s: ",name);
@@ -1408,9 +1777,9 @@ ssl_print_text_data(const char* name, const unsigned char* data, int len)
}
void
-ssl_print_data(const char* name, const unsigned char* data, int len)
+ssl_print_data(const gchar* name, const guchar* data, gint len)
{
- int i;
+ gint i;
if (!ssl_debug_file)
return;
fprintf(ssl_debug_file,"%s[%d]:\n",name, len);
@@ -1424,7 +1793,7 @@ ssl_print_data(const char* name, const unsigned char* data, int len)
}
void
-ssl_print_string(const char* name, const StringInfo* data)
+ssl_print_string(const gchar* name, const StringInfo* data)
{
ssl_print_data(name, data->data, data->data_len);
}
diff --git a/epan/dissectors/packet-ssl-utils.h b/epan/dissectors/packet-ssl-utils.h
index decd2f9be9..bc9cd47871 100644
--- a/epan/dissectors/packet-ssl-utils.h
+++ b/epan/dissectors/packet-ssl-utils.h
@@ -37,6 +37,8 @@
#include <gnutls/x509.h>
#include <gnutls/openssl.h>
+#include <epan/conversation.h>
+
/* #define SSL_FAST 1 */
#define SSL_DECRYPT_DEBUG
@@ -552,8 +554,8 @@ static const value_string tls_hello_extension_types[] = {
};
typedef struct _StringInfo {
- unsigned char* data;
- unsigned int data_len;
+ guchar* data;
+ guint data_len;
} StringInfo;
#define SSL_WRITE_KEY 1
@@ -576,22 +578,22 @@ typedef struct _StringInfo {
#define SSL_DEBUG_USE_STDERR "-"
typedef struct _SslCipherSuite {
- int number;
- int kex;
- int sig;
- int enc;
- int block;
- int bits;
- int eff_bits;
- int dig;
- int dig_len;
- int export;
- int mode;
+ gint number;
+ gint kex;
+ gint sig;
+ gint enc;
+ gint block;
+ gint bits;
+ gint eff_bits;
+ gint dig;
+ gint dig_len;
+ gint export;
+ gint mode;
} SslCipherSuite;
typedef struct _SslDecoder {
SslCipherSuite* cipher_suite;
- unsigned char _mac_key[20];
+ guchar _mac_key[20];
StringInfo mac_key;
SSL_CIPHER_CTX evp;
guint32 seq;
@@ -621,7 +623,7 @@ struct tvbuff;
typedef struct _SslRecordInfo {
struct tvbuff* tvb;
- int id;
+ gint id;
struct _SslRecordInfo* next;
} SslRecordInfo;
@@ -631,18 +633,18 @@ typedef struct {
} SslPacketInfo;
typedef struct _SslDecryptSession {
- unsigned char _master_secret[48];
- unsigned char _session_id[256];
- unsigned char _client_random[32];
- unsigned char _server_random[32];
+ guchar _master_secret[48];
+ guchar _session_id[256];
+ guchar _client_random[32];
+ guchar _server_random[32];
StringInfo session_id;
StringInfo server_random;
StringInfo client_random;
StringInfo master_secret;
StringInfo pre_master_secret;
- int cipher;
- int state;
+ gint cipher;
+ gint state;
SslCipherSuite cipher_suite;
SslDecoder server;
SslDecoder client;
@@ -653,6 +655,18 @@ typedef struct _SslDecryptSession {
} SslDecryptSession;
+typedef struct _SslAssociation {
+ guint ssl_port;
+ dissector_handle_t handle;
+ gchar* info;
+} SslAssociation;
+
+typedef struct _SslService {
+ address addr;
+ guint port;
+} SslService;
+
+
/** Initialize decryption engine/ssl layer. To be called once per execution */
extern void
ssl_lib_init(void);
@@ -668,7 +682,7 @@ ssl_session_init(SslDecryptSession* ssl);
@param src the data source
@param len the source data len */
extern void
-ssl_data_set(StringInfo* buf, unsigned char* src, unsigned int len);
+ssl_data_set(StringInfo* buf, guchar* src, guint len);
/** Load an RSA private key from specified file
@param fp the file that contain the key data
@@ -685,14 +699,14 @@ ssl_free_key(SSL_PRIVATE_KEY* key);
@param num the id of the cipher suite to be searched
@param cs pointer to the cipher suite struct to be filled
@return 0 if the cipher suite is found, -1 elsewhere */
-extern int
+extern gint
ssl_find_cipher(int num,SslCipherSuite* cs);
/* Expand the pre_master_secret to generate all the session information
* (master secret, session keys, ivs)
@param ssl_session the store for all the session data
@return 0 on success */
-extern int
+extern gint
ssl_generate_keyring_material(SslDecryptSession*ssl_session);
/* Try to decrypt in place the encrypted pre_master_secret
@@ -700,7 +714,7 @@ ssl_generate_keyring_material(SslDecryptSession*ssl_session);
@param entrypted_pre_master the rsa encrypted pre_master_secret
@param pk the private key to be used for decryption
@return 0 on success */
-extern int
+extern gint
ssl_decrypt_pre_master_secret(SslDecryptSession*ssl_session,
StringInfo* entrypted_pre_master, SSL_PRIVATE_KEY *pk);
@@ -713,26 +727,93 @@ ssl_decrypt_pre_master_secret(SslDecryptSession*ssl_session,
@param out a pointer to the store for the decrypted data
@param outl the decrypted data len
@return 0 on success */
-extern int
-ssl_decrypt_record(SslDecryptSession*ssl,SslDecoder* decoder, int ct,
- const unsigned char* in, int inl,unsigned char*out,int* outl);
+extern gint
+ssl_decrypt_record(SslDecryptSession*ssl,SslDecoder* decoder, gint ct,
+ const guchar* in, gint inl,guchar*out,gint* outl);
+
+
+/* Common part bitween SSL and DTLS dissectors */
+/* Hash Functions for TLS/DTLS sessions table and private keys table */
+extern gint
+ssl_equal (gconstpointer v, gconstpointer v2);
+
+extern guint
+ssl_hash (gconstpointer v);
+
+extern gint
+ssl_private_key_equal (gconstpointer v, gconstpointer v2);
+
+extern guint
+ssl_private_key_hash (gconstpointer v);
+
+/* private key table entries have a scope 'larger' then packet capture,
+ * so we can't relay on se_alloc** function */
+extern void
+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);
+
+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_);
+
+extern gint
+ssl_association_remove_handle_udp (gpointer key _U_,
+ gpointer data, gpointer user_data _U_);
+
+extern gint
+ssl_packet_from_server(GTree* associations, guint port);
+
+/* add to packet data a newly allocated tvb with the specified real data*/
+extern void
+ssl_add_record_info(gint proto, packet_info *pinfo, guchar* data, gint data_len, gint record_id);
+
+/* search in packet data the tvbuff associated to the specified id */
+extern tvbuff_t*
+ssl_get_record_info(gint proto, packet_info *pinfo, gint record_id);
+
+/* initialize/reset per capture state data (ssl sessions cache) */
+extern void
+ssl_common_init(GHashTable **session_hash , StringInfo * decrypted_data);
+
+/* parse ssl related preferences (private keys and ports association strings) */
+extern void
+ssl_parse_key_list(const gchar * keys_list, GHashTable *key_hash, GTree* associations, dissector_handle_t handle, gboolean tcp);
+
+/* store master secret into session data cache */
+extern void
+ssl_save_session(SslDecryptSession* ssl, GHashTable *session_hash);
+
+extern void
+ssl_restore_session(SslDecryptSession* ssl, GHashTable *session_hash);
+
+extern gint
+ssl_is_valid_content_type(guint8 type);
#ifdef SSL_DECRYPT_DEBUG
extern void
-ssl_debug_printf(const char* fmt,...) GNUC_FORMAT_CHECK(printf,1,2);
+ssl_debug_printf(const gchar* fmt,...) GNUC_FORMAT_CHECK(printf,1,2);
extern void
-ssl_print_data(const char* name, const unsigned char* data, int len);
+ssl_print_data(const gchar* name, const guchar* data, gint len);
extern void
-ssl_print_string(const char* name, const StringInfo* data);
+ssl_print_string(const gchar* name, const StringInfo* data);
extern void
-ssl_print_text_data(const char* name, const unsigned char* data, int len);
+ssl_print_text_data(const gchar* name, const guchar* data, gint len);
extern void
-ssl_set_debug(char* name);
+ssl_set_debug(gchar* name);
#else
/* No debug: nullify debug operation*/
static inline void GNUC_FORMAT_CHECK(printf,1,2)
-ssl_debug_printf(const char* fmt _U_,...)
+ssl_debug_printf(const gchar* fmt _U_,...)
{
}
#define ssl_print_data(a, b, c)
diff --git a/epan/dissectors/packet-ssl.c b/epan/dissectors/packet-ssl.c
index f5af1f3d4c..9e1f382dc1 100644
--- a/epan/dissectors/packet-ssl.c
+++ b/epan/dissectors/packet-ssl.c
@@ -128,81 +128,81 @@ static proto_tree *top_tree;
*********************************************************************/
/* Initialize the protocol and registered fields */
-static int ssl_tap = -1;
-static int proto_ssl = -1;
-static int hf_ssl_record = -1;
-static int hf_ssl_record_content_type = -1;
-static int hf_ssl_record_version = -1;
-static int hf_ssl_record_length = -1;
-static int hf_ssl_record_appdata = -1;
-static int hf_ssl2_record = -1;
-static int hf_ssl2_record_is_escape = -1;
-static int hf_ssl2_record_padding_length = -1;
-static int hf_ssl2_msg_type = -1;
-static int hf_pct_msg_type = -1;
-static int hf_ssl_change_cipher_spec = -1;
-static int hf_ssl_alert_message = -1;
-static int hf_ssl_alert_message_level = -1;
-static int hf_ssl_alert_message_description = -1;
-static int hf_ssl_handshake_protocol = -1;
-static int hf_ssl_handshake_type = -1;
-static int hf_ssl_handshake_length = -1;
-static int hf_ssl_handshake_client_version = -1;
-static int hf_ssl_handshake_server_version = -1;
-static int hf_ssl_handshake_random_time = -1;
-static int hf_ssl_handshake_random_bytes = -1;
-static int hf_ssl_handshake_cipher_suites_len = -1;
-static int hf_ssl_handshake_cipher_suites = -1;
-static int hf_ssl_handshake_cipher_suite = -1;
-static int hf_ssl_handshake_session_id = -1;
-static int hf_ssl_handshake_comp_methods_len = -1;
-static int hf_ssl_handshake_comp_methods = -1;
-static int hf_ssl_handshake_comp_method = -1;
-static int hf_ssl_handshake_extensions_len = -1;
-static int hf_ssl_handshake_extension_type = -1;
-static int hf_ssl_handshake_extension_len = -1;
-static int hf_ssl_handshake_extension_data = -1;
-static int hf_ssl_handshake_certificates_len = -1;
-static int hf_ssl_handshake_certificates = -1;
-static int hf_ssl_handshake_certificate = -1;
-static int hf_ssl_handshake_certificate_len = -1;
-static int hf_ssl_handshake_cert_types_count = -1;
-static int hf_ssl_handshake_cert_types = -1;
-static int hf_ssl_handshake_cert_type = -1;
-static int hf_ssl_handshake_finished = -1;
-static int hf_ssl_handshake_md5_hash = -1;
-static int hf_ssl_handshake_sha_hash = -1;
-static int hf_ssl_handshake_session_id_len = -1;
-static int hf_ssl_handshake_dnames_len = -1;
-static int hf_ssl_handshake_dnames = -1;
-static int hf_ssl_handshake_dname_len = -1;
-static int hf_ssl_handshake_dname = -1;
-static int hf_ssl2_handshake_cipher_spec_len = -1;
-static int hf_ssl2_handshake_session_id_len = -1;
-static int hf_ssl2_handshake_challenge_len = -1;
-static int hf_ssl2_handshake_cipher_spec = -1;
-static int hf_ssl2_handshake_challenge = -1;
-static int hf_ssl2_handshake_clear_key_len = -1;
-static int hf_ssl2_handshake_enc_key_len = -1;
-static int hf_ssl2_handshake_key_arg_len = -1;
-static int hf_ssl2_handshake_clear_key = -1;
-static int hf_ssl2_handshake_enc_key = -1;
-static int hf_ssl2_handshake_key_arg = -1;
-static int hf_ssl2_handshake_session_id_hit = -1;
-static int hf_ssl2_handshake_cert_type = -1;
-static int hf_ssl2_handshake_connection_id_len = -1;
-static int hf_ssl2_handshake_connection_id = -1;
-static int hf_pct_handshake_cipher_spec = -1;
-static int hf_pct_handshake_hash_spec = -1;
-static int hf_pct_handshake_cert_spec = -1;
-static int hf_pct_handshake_cert = -1;
-static int hf_pct_handshake_server_cert = -1;
-static int hf_pct_handshake_exch_spec = -1;
-static int hf_pct_handshake_hash = -1;
-static int hf_pct_handshake_cipher = -1;
-static int hf_pct_handshake_exch = -1;
-static int hf_pct_handshake_sig = -1;
-static int hf_pct_msg_error_type = -1;
+static gint ssl_tap = -1;
+static gint proto_ssl = -1;
+static gint hf_ssl_record = -1;
+static gint hf_ssl_record_content_type = -1;
+static gint hf_ssl_record_version = -1;
+static gint hf_ssl_record_length = -1;
+static gint hf_ssl_record_appdata = -1;
+static gint hf_ssl2_record = -1;
+static gint hf_ssl2_record_is_escape = -1;
+static gint hf_ssl2_record_padding_length = -1;
+static gint hf_ssl2_msg_type = -1;
+static gint hf_pct_msg_type = -1;
+static gint hf_ssl_change_cipher_spec = -1;
+static gint hf_ssl_alert_message = -1;
+static gint hf_ssl_alert_message_level = -1;
+static gint hf_ssl_alert_message_description = -1;
+static gint hf_ssl_handshake_protocol = -1;
+static gint hf_ssl_handshake_type = -1;
+static gint hf_ssl_handshake_length = -1;
+static gint hf_ssl_handshake_client_version = -1;
+static gint hf_ssl_handshake_server_version = -1;
+static gint hf_ssl_handshake_random_time = -1;
+static gint hf_ssl_handshake_random_bytes = -1;
+static gint hf_ssl_handshake_cipher_suites_len = -1;
+static gint hf_ssl_handshake_cipher_suites = -1;
+static gint hf_ssl_handshake_cipher_suite = -1;
+static gint hf_ssl_handshake_session_id = -1;
+static gint hf_ssl_handshake_comp_methods_len = -1;
+static gint hf_ssl_handshake_comp_methods = -1;
+static gint hf_ssl_handshake_comp_method = -1;
+static gint hf_ssl_handshake_extensions_len = -1;
+static gint hf_ssl_handshake_extension_type = -1;
+static gint hf_ssl_handshake_extension_len = -1;
+static gint hf_ssl_handshake_extension_data = -1;
+static gint hf_ssl_handshake_certificates_len = -1;
+static gint hf_ssl_handshake_certificates = -1;
+static gint hf_ssl_handshake_certificate = -1;
+static gint hf_ssl_handshake_certificate_len = -1;
+static gint hf_ssl_handshake_cert_types_count = -1;
+static gint hf_ssl_handshake_cert_types = -1;
+static gint hf_ssl_handshake_cert_type = -1;
+static gint hf_ssl_handshake_finished = -1;
+static gint hf_ssl_handshake_md5_hash = -1;
+static gint hf_ssl_handshake_sha_hash = -1;
+static gint hf_ssl_handshake_session_id_len = -1;
+static gint hf_ssl_handshake_dnames_len = -1;
+static gint hf_ssl_handshake_dnames = -1;
+static gint hf_ssl_handshake_dname_len = -1;
+static gint hf_ssl_handshake_dname = -1;
+static gint hf_ssl2_handshake_cipher_spec_len = -1;
+static gint hf_ssl2_handshake_session_id_len = -1;
+static gint hf_ssl2_handshake_challenge_len = -1;
+static gint hf_ssl2_handshake_cipher_spec = -1;
+static gint hf_ssl2_handshake_challenge = -1;
+static gint hf_ssl2_handshake_clear_key_len = -1;
+static gint hf_ssl2_handshake_enc_key_len = -1;
+static gint hf_ssl2_handshake_key_arg_len = -1;
+static gint hf_ssl2_handshake_clear_key = -1;
+static gint hf_ssl2_handshake_enc_key = -1;
+static gint hf_ssl2_handshake_key_arg = -1;
+static gint hf_ssl2_handshake_session_id_hit = -1;
+static gint hf_ssl2_handshake_cert_type = -1;
+static gint hf_ssl2_handshake_connection_id_len = -1;
+static gint hf_ssl2_handshake_connection_id = -1;
+static gint hf_pct_handshake_cipher_spec = -1;
+static gint hf_pct_handshake_hash_spec = -1;
+static gint hf_pct_handshake_cert_spec = -1;
+static gint hf_pct_handshake_cert = -1;
+static gint hf_pct_handshake_server_cert = -1;
+static gint hf_pct_handshake_exch_spec = -1;
+static gint hf_pct_handshake_hash = -1;
+static gint hf_pct_handshake_cipher = -1;
+static gint hf_pct_handshake_exch = -1;
+static gint hf_pct_handshake_sig = -1;
+static gint hf_pct_msg_error_type = -1;
/* Initialize the subtree pointers */
static gint ett_ssl = -1;
@@ -220,194 +220,21 @@ static gint ett_pct_hash_suites = -1;
static gint ett_pct_cert_suites = -1;
static gint ett_pct_exch_suites = -1;
-typedef struct {
- unsigned int ssl_port;
- dissector_handle_t handle;
- char* info;
-} SslAssociation;
-
-static char* ssl_keys_list = NULL;
-static char* ssl_debug_file_name = NULL;
-
-typedef struct _SslService {
- address addr;
- guint port;
-} SslService;
-
static GHashTable *ssl_session_hash = NULL;
static GHashTable *ssl_key_hash = NULL;
static GTree* ssl_associations = NULL;
static dissector_handle_t ssl_handle = NULL;
static StringInfo ssl_decrypted_data = {NULL, 0};
-static int ssl_decrypted_data_avail = 0;
-
-/* Hash Functions for ssl sessions table and private keys table*/
-static gint
-ssl_equal (gconstpointer v, gconstpointer v2)
-{
- const StringInfo *val1 = (const StringInfo *)v;
- const StringInfo *val2 = (const StringInfo *)v2;
-
- if (val1->data_len == val2->data_len &&
- !memcmp(val1->data, val2->data, val2->data_len)) {
- return 1;
- }
- return 0;
-}
-
-static guint
-ssl_hash (gconstpointer v)
-{
- guint l,hash = 0;
- StringInfo* id = (StringInfo*) v;
- guint* cur = (guint*) id->data;
- for (l=4; (l<id->data_len); l+=4, cur++)
- hash = hash ^ (*cur);
-
- return hash;
-}
-
-static gint
-ssl_private_key_equal (gconstpointer v, gconstpointer v2)
-{
- const SslService *val1 = (const SslService *)v;
- const SslService *val2 = (const SslService *)v2;
-
- if ((val1->port == val2->port) &&
- ! CMP_ADDRESS(&val1->addr, &val2->addr)) {
- return 1;
- }
- return 0;
-}
-
-static guint
-ssl_private_key_hash (gconstpointer v)
-{
- const SslService *key = (const SslService *)v;
- guint l,hash = key->port, len = key->addr.len;
-
- guint* cur = (guint*) key->addr.data;
- for (l=4; (l<len); l+=4, cur++)
- hash = hash ^ (*cur);
-
- return hash;
-}
+static gint ssl_decrypted_data_avail = 0;
-/* private key table entries have a scope 'larger' then packet capture,
- * so we can't relay on se_alloc** function */
-static void
-ssl_private_key_free(gpointer id, gpointer key, gpointer dummy _U_)
-{
- g_free(id);
- ssl_free_key((SSL_PRIVATE_KEY*) key);
-}
-
-/* handling of association between ssl ports and clear text protocol */
-static void
-ssl_association_add(unsigned int port, char *protocol)
-{
- SslAssociation* assoc = g_malloc(sizeof(SslAssociation));
-
- assoc->info=g_malloc(strlen(protocol)+1);
- strcpy(assoc->info, protocol);
- assoc->ssl_port = port;
- assoc->handle = find_dissector(protocol);
-
- ssl_debug_printf("ssl_association_add port %d protocol %s handle %p\n",
- port, protocol, assoc->handle);
-
- if(!assoc->handle){
- fprintf(stderr, "ssl_association_add() could not find handle for protocol:%s\n",protocol);
- } else {
- dissector_add("tcp.port", port, ssl_handle);
- g_tree_insert(ssl_associations, (gpointer)port, assoc);
- }
-}
-
-static gint
-ssl_association_cmp(gconstpointer a, gconstpointer b)
-{
- return (gint)a-(gint)b;
-}
-
-static inline
-SslAssociation* ssl_association_find(unsigned int port)
-{
- register SslAssociation* ret = g_tree_lookup(ssl_associations, (gpointer)port);
- ssl_debug_printf("ssl_association_find: port %d found %p\n", port, ret);
- return ret;
-}
-
-static gint
-ssl_association_remove_handle (gpointer key _U_,
- gpointer data, gpointer user_data _U_)
-{
- SslAssociation* assoc = (SslAssociation*) data;
- ssl_debug_printf("ssl_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;
-}
-
-static inline int
-ssl_packet_from_server(unsigned int port)
-{
- register int ret = ssl_association_find(port) != 0;
- ssl_debug_printf("ssl_packet_from_server: is from server %d\n", ret);
- return ret;
-}
-
-/* add to packet data a newly allocated tvb with the specified real data*/
-static void
-ssl_add_record_info(packet_info *pinfo, unsigned char* data, int data_len, int record_id)
-{
- unsigned char* real_data = se_alloc(data_len);
- SslRecordInfo* rec = se_alloc(sizeof(SslRecordInfo));
- SslPacketInfo* pi = p_get_proto_data(pinfo->fd, proto_ssl);
- if (!pi)
- {
- pi = se_alloc0(sizeof(SslPacketInfo));
- p_add_proto_data(pinfo->fd, proto_ssl,pi);
- }
-
- rec->id = record_id;
- rec->tvb = tvb_new_real_data(real_data, data_len, data_len);
- memcpy(real_data, data, data_len);
-
- /* head insertion */
- rec->next= pi->handshake_data;
- pi->handshake_data = rec;
-}
-
-/* search in packet data the tvbuff associated to the specified id */
-static tvbuff_t*
-ssl_get_record_info(packet_info *pinfo, int record_id)
-{
- SslRecordInfo* rec;
- SslPacketInfo* pi = p_get_proto_data(pinfo->fd, proto_ssl);
- if (!pi)
- return NULL;
-
- for (rec = pi->handshake_data; rec; rec = rec->next)
- if (rec->id == record_id)
- return rec->tvb;
-
- return NULL;
-}
+static gchar* ssl_keys_list = NULL;
+static gchar* ssl_debug_file_name = NULL;
/* initialize/reset per capture state data (ssl sessions cache) */
static void
ssl_init(void)
{
- if (ssl_session_hash)
- g_hash_table_destroy(ssl_session_hash);
- ssl_session_hash = g_hash_table_new(ssl_hash, ssl_equal);
- if (ssl_decrypted_data.data)
- g_free(ssl_decrypted_data.data);
- ssl_decrypted_data.data = g_malloc0(32);
- ssl_decrypted_data.data_len = 32;
+ ssl_common_init(&ssl_session_hash, &ssl_decrypted_data);
}
/* parse ssl related preferences (private keys and ports association strings) */
@@ -421,7 +248,7 @@ ssl_parse(void)
}
if (ssl_associations)
{
- g_tree_traverse(ssl_associations, ssl_association_remove_handle, G_IN_ORDER, NULL);
+ g_tree_traverse(ssl_associations, ssl_association_remove_handle_tcp, G_IN_ORDER, NULL);
g_tree_destroy(ssl_associations);
}
@@ -431,136 +258,29 @@ ssl_parse(void)
if (ssl_keys_list && (ssl_keys_list[0] != 0))
{
- char* end;
- char* start = strdup(ssl_keys_list);
- char* tmp = start;
-
- ssl_debug_printf("ssl_init keys string %s\n", start);
- do {
- char* addr, *port, *protocol, *filename;
- unsigned char* ip;
- SslService* service;
- SSL_PRIVATE_KEY * private_key;
- FILE* fp;
-
- addr = start;
- /* split ip/file couple with ';' separator*/
- end = strchr(start, ';');
- if (end) {
- *end = 0;
- start = end+1;
- }
-
- /* for each entry split ip, port, protocol, filename with ',' separator */
- ssl_debug_printf("ssl_init found host entry %s\n", addr);
- port = strchr(addr, ',');
- if (!port)
- {
- ssl_debug_printf("ssl_init entry malformed can't find port in %s\n", addr);
- break;
- }
- *port = 0;
- port++;
-
- protocol = strchr(port,',');
- if (!protocol)
- {
- ssl_debug_printf("ssl_init entry malformed can't find protocol in %s\n", port);
- break;
- }
- *protocol=0;
- protocol++;
-
- filename = strchr(protocol,',');
- if (!filename)
- {
- ssl_debug_printf("ssl_init entry malformed can't find filename in %s\n", port);
- break;
- }
- *filename=0;
- filename++;
-
- /* convert ip and port string to network rappresentation*/
- service = g_malloc(sizeof(SslService) + 4);
- service->addr.type = AT_IPv4;
- service->addr.len = 4;
- service->addr.data = ip = ((unsigned char*)service) + sizeof(SslService);
- sscanf(addr, "%hhu.%hhu.%hhu.%hhu", &ip[0], &ip[1], &ip[2], &ip[3]);
- service->port = atoi(port);
- ssl_debug_printf("ssl_init addr %hhu.%hhu.%hhu.%hhu port %d filename %s\n",
- ip[0], ip[1], ip[2], ip[3], service->port, filename);
-
- /* try to load pen file*/
- fp = fopen(filename, "rb");
- if (!fp) {
- fprintf(stderr, "can't open file %s \n",filename);
- break;
- }
-
- private_key = ssl_load_key(fp);
- if (!private_key) {
- fprintf(stderr,"can't load private key from %s\n",
- filename);
- break;
- }
- fclose(fp);
-
- ssl_debug_printf("ssl_init private key file %s successfully loaded\n",
- filename);
- g_hash_table_insert(ssl_key_hash, service, private_key);
-
- ssl_association_add(atoi(port), protocol);
-
- } while (end != NULL);
- free(tmp);
+ ssl_parse_key_list(ssl_keys_list,ssl_key_hash,ssl_associations,ssl_handle,TRUE);
}
ssl_set_debug(ssl_debug_file_name);
/* [re] add ssl dissection to defaults ports */
- ssl_association_add(443, "http");
- ssl_association_add(636, "ldap");
- ssl_association_add(993, "imap");
- ssl_association_add(995, "pop");
+ 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);
}
-/* store master secret into session data cache */
-static void
-ssl_save_session(SslDecryptSession* ssl)
-{
- /* allocate stringinfo chunks for session id and master secret data*/
- StringInfo* session_id = se_alloc0(sizeof(StringInfo) + ssl->session_id.data_len);
- StringInfo* master_secret = se_alloc0(48 + sizeof(StringInfo));
-
- master_secret->data = ((unsigned char*)master_secret+sizeof(StringInfo));
- session_id->data = ((unsigned char*)session_id+sizeof(StringInfo));
-
- ssl_data_set(session_id, ssl->session_id.data, ssl->session_id.data_len);
- ssl_data_set(master_secret, ssl->master_secret.data, ssl->master_secret.data_len);
- g_hash_table_insert(ssl_session_hash, session_id, master_secret);
- ssl_print_string("ssl_save_session stored session id", session_id);
- ssl_print_string("ssl_save_session stored master secret", master_secret);
-}
-
-static void
-ssl_restore_session(SslDecryptSession* ssl)
-{
- StringInfo* ms = g_hash_table_lookup(ssl_session_hash, &ssl->session_id);
- if (!ms) {
- ssl_debug_printf("ssl_restore_session can't find stored session\n");
- return;
- }
- ssl_data_set(&ssl->master_secret, ms->data, ms->data_len);
- ssl->state |= SSL_MASTER_SECRET;
- ssl_debug_printf("ssl_restore_session master key retrived\n");
-}
/* function that save app_data during sub protocol reassembling */
static void
-ssl_add_app_data(SslDecryptSession* ssl, unsigned char* data, int data_len){
- StringInfo * app=&ssl->app_data_segment;
+ssl_add_app_data(SslDecryptSession* ssl, guchar* data, gint data_len){
+ StringInfo * app;
+ app=&ssl->app_data_segment;
+
if(app->data_len!=0){
- unsigned char* tmp=g_malloc(app->data_len);
- int tmp_len=app->data_len;
+ guchar* tmp;
+ gint tmp_len;
+ tmp=g_malloc(app->data_len);
+ tmp_len=app->data_len;
memcpy(tmp,app->data,app->data_len);
if(app->data!=NULL)
g_free(app->data);
@@ -572,7 +292,7 @@ ssl_add_app_data(SslDecryptSession* ssl, unsigned char* data, int data_len){
memcpy(app->data+tmp_len, data,data_len);
}
else{
- //it's new
+ /* it's new */
if(app->data!=NULL)
g_free(app->data);
app->data=g_malloc(data_len);
@@ -592,8 +312,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(pinfo->srcport);
- association = association ? association: ssl_association_find(pinfo->destport);
+ association = ssl_association_find(ssl_associations, pinfo->srcport);
+ association = association ? association: ssl_association_find(ssl_associations, pinfo->destport);
/* create a copy of packet_info */
pp=g_malloc(sizeof(packet_info));
memcpy(pp, pinfo, sizeof(packet_info));
@@ -686,7 +406,7 @@ ssl_desegment_ssl_app_data(SslDecryptSession * ssl, packet_info *pinfo){
*
*/
/* record layer dissector */
-static int dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
+static gint dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, guint32 offset,
guint *conv_version,
gboolean *need_desegmentation,
@@ -740,7 +460,7 @@ static void dissect_ssl3_hnd_finished(tvbuff_t *tvb,
*/
/* record layer dissector */
-static int dissect_ssl2_record(tvbuff_t *tvb, packet_info *pinfo,
+static gint dissect_ssl2_record(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, guint32 offset,
guint *conv_version,
gboolean *need_desegmentation,
@@ -786,18 +506,17 @@ static void dissect_pct_msg_error(tvbuff_t *tvb,
*
*/
/*static void ssl_set_conv_version(packet_info *pinfo, guint version);*/
-static int ssl_is_valid_handshake_type(guint8 type);
-static int ssl_is_valid_content_type(guint8 type);
-static int ssl_is_valid_ssl_version(guint16 version);
-static int ssl_is_authoritative_version_message(guint8 content_type,
+static gint ssl_is_valid_handshake_type(guint8 type);
+static gint ssl_is_valid_ssl_version(guint16 version);
+static gint ssl_is_authoritative_version_message(guint8 content_type,
guint8 next_byte);
-static int ssl_is_v2_client_hello(tvbuff_t *tvb, guint32 offset);
-static int ssl_looks_like_sslv2(tvbuff_t *tvb, guint32 offset);
-static int ssl_looks_like_sslv3(tvbuff_t *tvb, guint32 offset);
-static int ssl_looks_like_valid_v2_handshake(tvbuff_t *tvb,
+static gint ssl_is_v2_client_hello(tvbuff_t *tvb, guint32 offset);
+static gint ssl_looks_like_sslv2(tvbuff_t *tvb, guint32 offset);
+static gint ssl_looks_like_sslv3(tvbuff_t *tvb, guint32 offset);
+static gint ssl_looks_like_valid_v2_handshake(tvbuff_t *tvb,
guint32 offset,
guint32 record_length);
-static int ssl_looks_like_valid_pct_handshake(tvbuff_t *tvb,
+static gint ssl_looks_like_valid_pct_handshake(tvbuff_t *tvb,
guint32 offset,
guint32 record_length);
/*********************************************************************
@@ -814,13 +533,18 @@ dissect_ssl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
conversation_t *conversation;
void *conv_data;
- proto_item *ti = NULL;
- proto_tree *ssl_tree = NULL;
- guint32 offset = 0;
- gboolean first_record_in_frame = TRUE;
+ proto_item *ti;
+ proto_tree *ssl_tree;
+ guint32 offset;
+ gboolean first_record_in_frame;
gboolean need_desegmentation;
- SslDecryptSession* ssl_session = NULL;
+ SslDecryptSession* ssl_session;
guint* conv_version;
+ ti = NULL;
+ ssl_tree = NULL;
+ offset = 0;
+ first_record_in_frame = TRUE;
+ ssl_session = NULL;
top_tree=tree;
@@ -838,6 +562,7 @@ dissect_ssl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
*/
conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype,
pinfo->srcport, pinfo->destport, 0);
+
if (!conversation)
{
/* create a new conversation */
@@ -859,7 +584,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(pinfo->srcport)) {
+ if (ssl_packet_from_server(ssl_associations, pinfo->srcport)) {
dummy.addr = pinfo->src;
dummy.port = pinfo->srcport;
}
@@ -895,7 +620,6 @@ dissect_ssl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
col_set_str(pinfo->cinfo, COL_PROTOCOL, "SSL");
}
-
/* clear the the info column */
if (check_col(pinfo->cinfo, COL_INFO))
col_clear(pinfo->cinfo, COL_INFO);
@@ -1022,15 +746,15 @@ dissect_ssl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
tap_queue_packet(ssl_tap, pinfo, (gpointer)proto_ssl);
}
-static int
+static gint
decrypt_ssl3_record(tvbuff_t *tvb, packet_info *pinfo, guint32 offset,
guint32 record_length, guint8 content_type, SslDecryptSession* ssl,
gboolean save_plaintext)
{
- int ret = 0;
- int direction;
+ gint ret;
+ gint direction;
SslDecoder* decoder;
-
+ ret = 0;
/* if we can decrypt and decryption have success
* add decrypted data to this packet info*/
ssl_debug_printf("decrypt_ssl3_record: app_data len %d ssl state %X\n",
@@ -1041,7 +765,7 @@ decrypt_ssl3_record(tvbuff_t *tvb, packet_info *pinfo, guint32 offset,
}
/* retrive decoder for this packet direction*/
- if ((direction = ssl_packet_from_server(pinfo->srcport)) != 0) {
+ if ((direction = ssl_packet_from_server(ssl_associations, pinfo->srcport)) != 0) {
ssl_debug_printf("decrypt_ssl3_record: using server decoder\n");
decoder = &ssl->server;
}
@@ -1070,7 +794,8 @@ decrypt_ssl3_record(tvbuff_t *tvb, packet_info *pinfo, guint32 offset,
ret = 1;
if (ret && save_plaintext)
{
- SslPacketInfo* pi = p_get_proto_data(pinfo->fd, proto_ssl);
+ SslPacketInfo* pi;
+ pi = p_get_proto_data(pinfo->fd, proto_ssl);
if (!pi)
{
ssl_debug_printf("decrypt_ssl3_record: allocating app_data %d "
@@ -1082,7 +807,7 @@ decrypt_ssl3_record(tvbuff_t *tvb, packet_info *pinfo, guint32 offset,
memcpy(pi->app_data.data, ssl_decrypted_data.data, ssl_decrypted_data_avail);
}
else {
- unsigned char* store;
+ guchar* store;
/* update previus record*/
ssl_debug_printf("decrypt_ssl3_record: reallocating app_data "
"%d bytes for app data (total %d appdata bytes)\n",
@@ -1114,7 +839,7 @@ decrypt_ssl3_record(tvbuff_t *tvb, packet_info *pinfo, guint32 offset,
* SSL version 3 and TLS Dissection Routines
*
*********************************************************************/
-static int
+static gint
dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, guint32 offset,
guint *conv_version, gboolean *need_desegmentation,
@@ -1143,12 +868,14 @@ dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
guint16 version;
guint8 content_type;
guint8 next_byte;
- proto_tree *ti = NULL;
- proto_tree *ssl_record_tree = NULL;
- guint32 available_bytes = 0;
+ proto_tree *ti;
+ proto_tree *ssl_record_tree;
+ guint32 available_bytes;
SslPacketInfo* pi;
SslAssociation* association;
-
+ ti = NULL;
+ ssl_record_tree = NULL;
+ available_bytes = 0;
available_bytes = tvb_length_remaining(tvb, offset);
@@ -1319,14 +1046,15 @@ dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
break;
case SSL_ID_ALERT:
{
- tvbuff_t* decrypted=0;
+ tvbuff_t* decrypted;
+ decrypted=0;
if (ssl&&decrypt_ssl3_record(tvb, pinfo, offset,
record_length, content_type, ssl, FALSE))
- ssl_add_record_info(pinfo, ssl_decrypted_data.data,
+ ssl_add_record_info(proto_ssl, pinfo, ssl_decrypted_data.data,
ssl_decrypted_data_avail, offset);
/* try to retrive and use decrypted alert record, if any. */
- decrypted = ssl_get_record_info(pinfo, offset);
+ decrypted = ssl_get_record_info(proto_ssl, pinfo, offset);
if (decrypted)
dissect_ssl3_alert(decrypted, pinfo, ssl_record_tree, 0,
conv_version);
@@ -1337,18 +1065,19 @@ dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
}
case SSL_ID_HANDSHAKE:
{
- tvbuff_t* decrypted=0;
+ tvbuff_t* decrypted;
+ decrypted=0;
/* try to decrypt handshake record, if possible. Store decrypted
* record for later usage. The offset is used as 'key' to itentify
* this record into the packet (we can have multiple handshake records
* in the same frame) */
if (ssl && decrypt_ssl3_record(tvb, pinfo, offset,
record_length, content_type, ssl, FALSE))
- ssl_add_record_info(pinfo, ssl_decrypted_data.data,
+ ssl_add_record_info(proto_ssl, pinfo, ssl_decrypted_data.data,
ssl_decrypted_data_avail, offset);
/* try to retrive and use decrypted handshake record, if any. */
- decrypted = ssl_get_record_info(pinfo, offset);
+ decrypted = ssl_get_record_info(proto_ssl, pinfo, offset);
if (decrypted)
dissect_ssl3_handshake(decrypted, pinfo, ssl_record_tree, 0,
decrypted->length, conv_version, ssl, content_type);
@@ -1378,8 +1107,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(pinfo->srcport);
- association = association ? association: ssl_association_find(pinfo->destport);
+ association = ssl_association_find(ssl_associations, pinfo->srcport);
+ association = association ? association: ssl_association_find(ssl_associations, pinfo->destport);
proto_item_set_text(ssl_record_tree,
"%s Record Layer: %s Protocol: %s",
@@ -1468,11 +1197,11 @@ dissect_ssl3_alert(tvbuff_t *tvb, packet_info *pinfo,
* } Alert;
*/
proto_tree *ti;
- proto_tree *ssl_alert_tree = NULL;
+ proto_tree *ssl_alert_tree;
const gchar *level;
const gchar *desc;
guint8 byte;
-
+ ssl_alert_tree = NULL;
if (tree)
{
ti = proto_tree_add_item(tree, hf_ssl_alert_message, tvb,
@@ -1555,13 +1284,16 @@ dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
* } body;
* } Handshake;
*/
- proto_tree *ti = NULL;
- proto_tree *ssl_hand_tree = NULL;
- const gchar *msg_type_str = NULL;
+ proto_tree *ti;
+ proto_tree *ssl_hand_tree;
+ const gchar *msg_type_str;
guint8 msg_type;
guint32 length;
- gboolean first_iteration = TRUE;
-
+ gboolean first_iteration;
+ ti = NULL;
+ ssl_hand_tree = NULL;
+ msg_type_str = NULL;
+ first_iteration = TRUE;
/* just as there can be multiple records per packet, there
* can be multiple messages per record as long as they have
@@ -1691,9 +1423,11 @@ dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
{
/* PAOLO: here we can have all the data to build session key*/
StringInfo encrypted_pre_master;
- int ret;
- unsigned encrlen = length, skip = 0;
-
+ gint ret;
+ guint encrlen, skip;
+ encrlen = length;
+ skip = 0;
+
if (!ssl)
break;
@@ -1742,7 +1476,7 @@ dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
break;
}
ssl->state |= SSL_HAVE_SESSION_KEY;
- ssl_save_session(ssl);
+ ssl_save_session(ssl, ssl_session_hash);
ssl_debug_printf("dissect_ssl3_handshake session keys succesfully generated\n");
}
break;
@@ -1762,13 +1496,14 @@ dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
}
}
-static int
+static gint
dissect_ssl3_hnd_hello_common(tvbuff_t *tvb, proto_tree *tree,
guint32 offset, SslDecryptSession* ssl, gint from_server)
{
/* show the client's random challenge */
nstime_t gmt_unix_time;
- guint8 session_id_length = 0;
+ guint8 session_id_length;
+ session_id_length = 0;
if (ssl)
{
@@ -1795,7 +1530,7 @@ dissect_ssl3_hnd_hello_common(tvbuff_t *tvb, proto_tree *tree,
(tvb_memeql(tvb, offset+33, ssl->session_id.data, session_id_length) == 0))
{
/* clinet/server id match: try to restore a previous cached session*/
- ssl_restore_session(ssl);
+ ssl_restore_session(ssl, ssl_session_hash);
}
else {
tvb_memcpy(tvb,ssl->session_id.data, offset+33, session_id_length);
@@ -1839,7 +1574,7 @@ dissect_ssl3_hnd_hello_common(tvbuff_t *tvb, proto_tree *tree,
return session_id_length+33;
}
-static int
+static gint
dissect_ssl3_hnd_hello_ext(tvbuff_t *tvb,
proto_tree *tree, guint32 offset, guint32 left)
{
@@ -1909,10 +1644,13 @@ dissect_ssl3_hnd_cli_hello(tvbuff_t *tvb,
*/
proto_tree *ti;
proto_tree *cs_tree;
- guint16 cipher_suite_length = 0;
- guint8 compression_methods_length = 0;
+ guint16 cipher_suite_length;
+ guint8 compression_methods_length;
guint8 compression_method;
- guint16 start_offset = offset;
+ guint16 start_offset;
+ cipher_suite_length = 0;
+ compression_methods_length = 0;
+ start_offset = offset;
if (tree || ssl)
{
@@ -2024,7 +1762,8 @@ dissect_ssl3_hnd_srv_hello(tvbuff_t *tvb,
* Extension server_hello_extension_list<0..2^16-1>;
* } ServerHello;
*/
- guint16 start_offset = offset;
+ guint16 start_offset;
+ start_offset = offset;
if (tree || ssl)
{
@@ -2136,7 +1875,8 @@ dissect_ssl3_hnd_cert(tvbuff_t *tvb,
while (certificate_list_length > 0)
{
/* get the length of the current certificate */
- guint32 cert_length = tvb_get_ntoh24(tvb, offset);
+ guint32 cert_length;
+ cert_length = tvb_get_ntoh24(tvb, offset);
certificate_list_length -= 3 + cert_length;
proto_tree_add_item(subtree, hf_ssl_handshake_certificate_len,
@@ -2171,8 +1911,10 @@ dissect_ssl3_hnd_cert_req(tvbuff_t *tvb,
*/
proto_tree *ti;
proto_tree *subtree;
- guint8 cert_types_count = 0;
- int dnames_length = 0;
+ guint8 cert_types_count;
+ gint dnames_length;
+ cert_types_count = 0;
+ dnames_length = 0;
if (tree)
{
@@ -2227,7 +1969,8 @@ dissect_ssl3_hnd_cert_req(tvbuff_t *tvb,
while (dnames_length > 0)
{
/* get the length of the current certificate */
- guint16 name_length = tvb_get_ntohs(tvb, offset);
+ guint16 name_length;
+ name_length = tvb_get_ntohs(tvb, offset);
dnames_length -= 2 + name_length;
proto_tree_add_item(subtree, hf_ssl_handshake_dname_len,
@@ -2298,24 +2041,34 @@ dissect_ssl3_hnd_finished(tvbuff_t *tvb,
/* record layer dissector */
-static int
+static gint
dissect_ssl2_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
guint32 offset, guint* conv_version,
gboolean *need_desegmentation,
SslDecryptSession* ssl)
{
- guint32 initial_offset = offset;
- guint8 byte = 0;
- guint8 record_length_length = 0;
- guint32 record_length = 0;
- gint is_escape = -1;
- gint16 padding_length = -1;
- guint8 msg_type = 0;
- const gchar *msg_type_str = NULL;
- guint32 available_bytes = 0;
-
+ guint32 initial_offset;
+ guint8 byte;
+ guint8 record_length_length;
+ guint32 record_length;
+ gint is_escape;
+ gint16 padding_length;
+ guint8 msg_type;
+ const gchar *msg_type_str;
+ guint32 available_bytes;
proto_tree *ti;
- proto_tree *ssl_record_tree = NULL;
+ proto_tree *ssl_record_tree;
+
+ initial_offset = offset;
+ byte = 0;
+ record_length_length = 0;
+ record_length = 0;
+ is_escape = -1;
+ padding_length = -1;
+ msg_type = 0;
+ msg_type_str = NULL;
+ available_bytes = 0;
+ ssl_record_tree = NULL;
/* pull first byte; if high bit is set, then record
* length is three bytes due to padding; otherwise
@@ -2586,7 +2339,8 @@ dissect_ssl2_hnd_client_hello(tvbuff_t *tvb,
guint16 challenge_length;
proto_tree *ti;
- proto_tree *cs_tree=0;
+ proto_tree *cs_tree;
+ cs_tree=0;
version = tvb_get_ntohs(tvb, offset);
if (!ssl_is_valid_ssl_version(version))
@@ -2686,8 +2440,9 @@ dissect_ssl2_hnd_client_hello(tvbuff_t *tvb,
{
/* PAOLO: get client random data; we get at most 32 bytes from
challenge */
- int max = challenge_length > 32? 32: challenge_length;
-
+ gint max;
+ max = challenge_length > 32? 32: challenge_length;
+
ssl_debug_printf("client random len: %d padded to 32\n",
challenge_length);
@@ -3279,7 +3034,7 @@ ssl_set_conv_version(packet_info *pinfo, guint version)
}
#endif
-static int
+static gint
ssl_is_valid_handshake_type(guint8 type)
{
@@ -3299,25 +3054,15 @@ ssl_is_valid_handshake_type(guint8 type)
return 0;
}
-static int
-ssl_is_valid_content_type(guint8 type)
-{
- if (type >= 0x14 && type <= 0x17)
- {
- return 1;
- }
-
- return 0;
-}
-
-static int
+static gint
ssl_is_valid_ssl_version(guint16 version)
{
- const gchar *version_str = match_strval(version, ssl_versions);
+ const gchar *version_str;
+ version_str = match_strval(version, ssl_versions);
return version_str != NULL;
}
-static int
+static gint
ssl_is_authoritative_version_message(guint8 content_type,
guint8 next_byte)
{
@@ -3334,7 +3079,7 @@ ssl_is_authoritative_version_message(guint8 content_type,
return 0;
}
-static int
+static gint
ssl_is_v2_client_hello(tvbuff_t *tvb, guint32 offset)
{
guint8 byte;
@@ -3360,7 +3105,7 @@ ssl_is_v2_client_hello(tvbuff_t *tvb, guint32 offset)
* valid sslv2 record. this isn't really possible,
* but we'll try to do a reasonable job anyway.
*/
-static int
+static gint
ssl_looks_like_sslv2(tvbuff_t *tvb, guint32 offset)
{
/* here's the current approach:
@@ -3372,7 +3117,9 @@ ssl_looks_like_sslv2(tvbuff_t *tvb, guint32 offset)
*/
/* get the first byte; must have high bit set */
- guint8 byte = tvb_get_guint8(tvb, offset);
+ guint8 byte;
+ byte = tvb_get_guint8(tvb, offset);
+
if (byte < 0x80)
{
return 0;
@@ -3400,7 +3147,7 @@ ssl_looks_like_sslv2(tvbuff_t *tvb, guint32 offset)
* valid sslv3 record. this is somewhat more reliable
* than sslv2 due to the structure of the v3 protocol
*/
-static int
+static gint
ssl_looks_like_sslv3(tvbuff_t *tvb, guint32 offset)
{
/* have to have a valid content type followed by a valid
@@ -3433,7 +3180,7 @@ ssl_looks_like_sslv3(tvbuff_t *tvb, guint32 offset)
* data apart from a valid message without state,
* we try to help the odds.
*/
-static int
+static gint
ssl_looks_like_valid_v2_handshake(tvbuff_t *tvb, guint32 offset,
guint32 record_length)
{
@@ -3494,7 +3241,7 @@ ssl_looks_like_valid_v2_handshake(tvbuff_t *tvb, guint32 offset,
* data apart from a valid message without state,
* we try to help the odds.
*/
-static int
+static gint
ssl_looks_like_valid_pct_handshake(tvbuff_t *tvb, guint32 offset,
guint32 record_length)
{
@@ -3983,11 +3730,11 @@ proto_register_ssl(void)
"semicolon separated list of private RSA keys used for SSL decryption; "
"each list entry must be in the form of <ip>,<port>,<protocol>,<key_file_name>"
"<key_file_name> is the local file name of the RSA private key used by the specified server\n",
- (const char **)&ssl_keys_list);
+ (const gchar **)&ssl_keys_list);
prefs_register_string_preference(ssl_module, "debug_file", "SSL debug file",
"redirect ssl debug to file name; leave empty to disable debug, "
"use \"" SSL_DEBUG_USE_STDERR "\" to redirect output to stderr\n",
- (const char **)&ssl_debug_file_name);
+ (const gchar **)&ssl_debug_file_name);
#endif
}