2006-06-27 13:36:10 +00:00
|
|
|
/* packet-dtls.c
|
|
|
|
* Routines for dtls dissection
|
|
|
|
* Copyright (c) 2006, Authesserre Samuel <sauthess@gmail.com>
|
2007-11-05 23:05:20 +00:00
|
|
|
* Copyright (c) 2007, Mikael Magnusson <mikma@users.sourceforge.net>
|
2006-06-27 13:36:10 +00:00
|
|
|
*
|
|
|
|
* $Id$
|
|
|
|
*
|
2006-08-02 08:15:51 +00:00
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
2006-06-27 13:36:10 +00:00
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*
|
2006-08-02 08:15:51 +00:00
|
|
|
*
|
|
|
|
* DTLS dissection and decryption.
|
|
|
|
* See RFC 4347 for details about DTLS specs.
|
|
|
|
*
|
2007-03-24 13:21:08 +00:00
|
|
|
* Notes :
|
2006-08-02 08:15:51 +00:00
|
|
|
* 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.
|
|
|
|
*
|
2007-11-05 23:05:20 +00:00
|
|
|
* It was developped to dissect and decrypt OpenSSL v 0.9.8f DTLS implementation.
|
2006-08-02 08:15:51 +00:00
|
|
|
* It is limited to this implementation while there is no complete implementation.
|
2007-03-24 13:21:08 +00:00
|
|
|
*
|
2006-08-02 08:15:51 +00:00
|
|
|
* Implemented :
|
|
|
|
* - DTLS dissection
|
|
|
|
* - DTLS decryption (openssl one)
|
2007-03-24 13:21:08 +00:00
|
|
|
*
|
2006-08-02 08:15:51 +00:00
|
|
|
* Todo :
|
2007-03-24 13:21:08 +00:00
|
|
|
* - activate correct Mac calculation when openssl will be corrected
|
|
|
|
* (or if an other implementation works),
|
2006-08-02 08:15:51 +00:00
|
|
|
* 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)
|
2006-06-27 13:36:10 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2009-11-23 18:47:52 +00:00
|
|
|
#ifdef HAVE_SYS_TYPES_H
|
2006-08-02 08:15:51 +00:00
|
|
|
#include <sys/types.h>
|
2009-11-23 18:47:52 +00:00
|
|
|
#endif
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
#ifdef HAVE_SYS_SOCKET_H
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#endif
|
|
|
|
|
2008-10-27 01:39:32 +00:00
|
|
|
#ifdef HAVE_WINSOCK2_H
|
2008-10-24 00:42:09 +00:00
|
|
|
#include <winsock2.h>
|
|
|
|
#endif
|
|
|
|
|
2006-06-27 13:36:10 +00:00
|
|
|
#include <glib.h>
|
|
|
|
|
|
|
|
#include <epan/conversation.h>
|
|
|
|
#include <epan/prefs.h>
|
2007-05-13 20:58:29 +00:00
|
|
|
#include <epan/asn1.h>
|
2006-06-27 13:36:10 +00:00
|
|
|
#include <epan/dissectors/packet-x509af.h>
|
|
|
|
#include <epan/emem.h>
|
|
|
|
#include <epan/tap.h>
|
2007-11-05 23:05:20 +00:00
|
|
|
#include <epan/reassemble.h>
|
2010-05-28 20:19:55 +00:00
|
|
|
#ifdef NEED_INET_V6DEFS_H
|
|
|
|
#include "wsutil/inet_v6defs.h"
|
|
|
|
#endif
|
2006-06-27 13:36:10 +00:00
|
|
|
#include "packet-ssl-utils.h"
|
2011-04-26 21:59:11 +00:00
|
|
|
#include <wsutil/file_util.h>
|
|
|
|
#include <epan/uat.h>
|
|
|
|
|
|
|
|
/* DTLS User Access Table */
|
|
|
|
static ssldecrypt_assoc_t *dtlskeylist_uats = NULL;
|
|
|
|
static guint ndtlsdecrypt = 0;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* 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;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
|
|
|
/*********************************************************************
|
|
|
|
*
|
|
|
|
* Protocol Constants, Variables, Data Structures
|
|
|
|
*
|
|
|
|
*********************************************************************/
|
|
|
|
|
|
|
|
/* Initialize the protocol and registered fields */
|
2006-08-02 08:15:51 +00:00
|
|
|
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;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2009-10-16 21:17:57 +00:00
|
|
|
static gint hf_dtls_fragments = -1;
|
|
|
|
static gint hf_dtls_fragment = -1;
|
|
|
|
static gint hf_dtls_fragment_overlap = -1;
|
2007-11-05 23:05:20 +00:00
|
|
|
static gint hf_dtls_fragment_overlap_conflicts = -1;
|
2009-10-16 21:17:57 +00:00
|
|
|
static gint hf_dtls_fragment_multiple_tails = -1;
|
2007-11-05 23:05:20 +00:00
|
|
|
static gint hf_dtls_fragment_too_long_fragment = -1;
|
2009-10-16 21:17:57 +00:00
|
|
|
static gint hf_dtls_fragment_error = -1;
|
2011-01-30 21:01:07 +00:00
|
|
|
static gint hf_dtls_fragment_count = -1;
|
2009-10-16 21:17:57 +00:00
|
|
|
static gint hf_dtls_reassembled_in = -1;
|
2010-02-02 16:01:52 +00:00
|
|
|
static gint hf_dtls_reassembled_length = -1;
|
2007-11-05 23:05:20 +00:00
|
|
|
|
2006-06-27 13:36:10 +00:00
|
|
|
/* Initialize the subtree pointers */
|
|
|
|
static gint ett_dtls = -1;
|
|
|
|
static gint ett_dtls_record = -1;
|
|
|
|
static gint ett_dtls_alert = -1;
|
|
|
|
static gint ett_dtls_handshake = -1;
|
|
|
|
static gint ett_dtls_cipher_suites = -1;
|
|
|
|
static gint ett_dtls_comp_methods = -1;
|
|
|
|
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;
|
|
|
|
|
2007-11-05 23:05:20 +00:00
|
|
|
static gint ett_dtls_fragment = -1;
|
|
|
|
static gint ett_dtls_fragments = -1;
|
|
|
|
|
2009-10-16 21:17:57 +00:00
|
|
|
static GHashTable *dtls_session_hash = NULL;
|
|
|
|
static GHashTable *dtls_key_hash = NULL;
|
2007-11-05 23:05:20 +00:00
|
|
|
static GHashTable *dtls_fragment_table = NULL;
|
2006-08-02 08:15:51 +00:00
|
|
|
static GTree* dtls_associations = NULL;
|
2009-10-16 21:17:57 +00:00
|
|
|
static dissector_handle_t dtls_handle = NULL;
|
2007-04-10 15:12:48 +00:00
|
|
|
static StringInfo dtls_compressed_data = {NULL, 0};
|
2009-10-16 21:17:57 +00:00
|
|
|
static StringInfo dtls_decrypted_data = {NULL, 0};
|
|
|
|
static gint dtls_decrypted_data_avail = 0;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2011-04-26 21:59:11 +00:00
|
|
|
static uat_t *dtlsdecrypt_uat = NULL;
|
2006-08-02 08:15:51 +00:00
|
|
|
static gchar* dtls_keys_list = NULL;
|
2006-08-26 00:05:26 +00:00
|
|
|
#ifdef HAVE_LIBGNUTLS
|
2006-08-02 08:15:51 +00:00
|
|
|
static gchar* dtls_debug_file_name = NULL;
|
2006-08-26 00:05:26 +00:00
|
|
|
#endif
|
2006-06-27 13:36:10 +00:00
|
|
|
|
From Michael Chen via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5863 :
1. Reload framing protocol no longer encapsulates the Reload message, instead
the latter is in its own tree following Reload framing, much like IP, UDP, etc.
2. Similarly, DTLS no longer encapsulates its data payload if the payload can
be dissected. The recognized payload is in its own tree following the DTLS,
much like IP, UDP, etc.
4. DTLS now has its own heuristic table for dissecting its payload, and
reload-framing is added to this DTLS heuristic table.
6. DTLS will try to dissect its payload if the agreed upon cipher is
RSA-NULL-MD5 (0x0001) or RSA-NULL-SHA (0x0002), even when DTLS is not
configured with the client/server private keys.
Still to do: make DTLS a heuristic dissector on top of UDP (item 3 in the bug).
svn path=/trunk/; revision=37110
2011-05-13 02:48:08 +00:00
|
|
|
static heur_dissector_list_t heur_subdissector_list;
|
|
|
|
|
2007-11-05 23:05:20 +00:00
|
|
|
static const fragment_items dtls_frag_items = {
|
2009-10-16 21:17:57 +00:00
|
|
|
/* Fragment subtrees */
|
|
|
|
&ett_dtls_fragment,
|
|
|
|
&ett_dtls_fragments,
|
|
|
|
/* Fragment fields */
|
|
|
|
&hf_dtls_fragments,
|
|
|
|
&hf_dtls_fragment,
|
|
|
|
&hf_dtls_fragment_overlap,
|
|
|
|
&hf_dtls_fragment_overlap_conflicts,
|
|
|
|
&hf_dtls_fragment_multiple_tails,
|
|
|
|
&hf_dtls_fragment_too_long_fragment,
|
|
|
|
&hf_dtls_fragment_error,
|
2011-01-30 21:01:07 +00:00
|
|
|
&hf_dtls_fragment_count,
|
2009-10-16 21:17:57 +00:00
|
|
|
/* Reassembled in field */
|
|
|
|
&hf_dtls_reassembled_in,
|
2010-02-02 16:01:52 +00:00
|
|
|
/* Reassembled length field */
|
|
|
|
&hf_dtls_reassembled_length,
|
2009-10-16 21:17:57 +00:00
|
|
|
/* Tag */
|
|
|
|
"Message fragments"
|
2007-11-05 23:05:20 +00:00
|
|
|
};
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* initialize/reset per capture state data (dtls sessions cache) */
|
2007-03-24 13:21:08 +00:00
|
|
|
static void
|
2006-08-02 08:15:51 +00:00
|
|
|
dtls_init(void)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2011-04-26 21:59:11 +00:00
|
|
|
module_t *dtls_module = prefs_find_module("dtls");
|
|
|
|
pref_t *keys_list_pref;
|
|
|
|
|
2007-04-10 15:12:48 +00:00
|
|
|
ssl_common_init(&dtls_session_hash, &dtls_decrypted_data, &dtls_compressed_data);
|
2007-11-05 23:05:20 +00:00
|
|
|
fragment_table_init (&dtls_fragment_table);
|
2011-04-26 21:59:11 +00:00
|
|
|
|
|
|
|
/* We should have loaded "keys_list" by now. Mark it obsolete */
|
|
|
|
if (dtls_module) {
|
|
|
|
keys_list_pref = prefs_find_preference(dtls_module, "keys_list");
|
|
|
|
if (! prefs_get_preference_obsolete(keys_list_pref)) {
|
|
|
|
prefs_set_preference_obsolete(keys_list_pref);
|
|
|
|
}
|
|
|
|
}
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* parse dtls related preferences (private keys and ports association strings) */
|
2007-03-24 13:21:08 +00:00
|
|
|
static void
|
2006-08-02 08:15:51 +00:00
|
|
|
dtls_parse(void)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-25 08:07:26 +00:00
|
|
|
ep_stack_t tmp_stack;
|
|
|
|
SslAssociation *tmp_assoc;
|
2011-04-26 21:59:11 +00:00
|
|
|
guint i;
|
|
|
|
gchar **old_keys, **parts, *err;
|
|
|
|
GString *uat_entry = g_string_new("");
|
2006-08-25 08:07:26 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
if (dtls_key_hash)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
g_hash_table_foreach(dtls_key_hash, ssl_private_key_free, NULL);
|
|
|
|
g_hash_table_destroy(dtls_key_hash);
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
2006-08-25 08:07:26 +00:00
|
|
|
|
|
|
|
/* remove only associations created from key list */
|
|
|
|
tmp_stack = ep_stack_new();
|
2008-05-05 20:03:15 +00:00
|
|
|
g_tree_foreach(dtls_associations, ssl_assoc_from_key_list, tmp_stack);
|
2006-08-26 00:05:26 +00:00
|
|
|
while ((tmp_assoc = ep_stack_pop(tmp_stack)) != NULL) {
|
2006-08-25 08:07:26 +00:00
|
|
|
ssl_association_remove(dtls_associations, tmp_assoc);
|
|
|
|
}
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2011-04-26 21:59:11 +00:00
|
|
|
/* Import old-style keys */
|
|
|
|
if (dtlsdecrypt_uat && dtls_keys_list && dtls_keys_list[0]) {
|
|
|
|
old_keys = g_strsplit(dtls_keys_list, ";", 0);
|
|
|
|
for (i = 0; old_keys[i] != NULL; i++) {
|
|
|
|
parts = g_strsplit(old_keys[i], ",", 4);
|
|
|
|
if (parts[0] && parts[1] && parts[2] && parts[3]) {
|
|
|
|
g_string_printf(uat_entry, "\"%s\",\"%s\",\"%s\",\"%s\",\"\"",
|
|
|
|
parts[0], parts[1], parts[2], parts[3]);
|
|
|
|
if (!uat_load_str(dtlsdecrypt_uat, uat_entry->str, &err)) {
|
|
|
|
ssl_debug_printf("dtls_parse: Can't load UAT string %s: %s\n",
|
|
|
|
uat_entry->str, err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_strfreev(parts);
|
|
|
|
}
|
|
|
|
g_strfreev(old_keys);
|
|
|
|
}
|
|
|
|
g_string_free(uat_entry, TRUE);
|
|
|
|
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* 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);
|
2007-03-24 13:21:08 +00:00
|
|
|
|
From Michael Chen via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5863 :
1. Reload framing protocol no longer encapsulates the Reload message, instead
the latter is in its own tree following Reload framing, much like IP, UDP, etc.
2. Similarly, DTLS no longer encapsulates its data payload if the payload can
be dissected. The recognized payload is in its own tree following the DTLS,
much like IP, UDP, etc.
4. DTLS now has its own heuristic table for dissecting its payload, and
reload-framing is added to this DTLS heuristic table.
6. DTLS will try to dissect its payload if the agreed upon cipher is
RSA-NULL-MD5 (0x0001) or RSA-NULL-SHA (0x0002), even when DTLS is not
configured with the client/server private keys.
Still to do: make DTLS a heuristic dissector on top of UDP (item 3 in the bug).
svn path=/trunk/; revision=37110
2011-05-13 02:48:08 +00:00
|
|
|
ssl_set_debug(dtls_debug_file_name);
|
|
|
|
|
2011-04-26 21:59:11 +00:00
|
|
|
if (ndtlsdecrypt > 0)
|
|
|
|
{
|
|
|
|
for (i = 0; i < ndtlsdecrypt; i++)
|
|
|
|
{
|
|
|
|
ssldecrypt_assoc_t *d = &(dtlskeylist_uats[i]);
|
|
|
|
ssl_parse_key_list(d, dtls_key_hash, dtls_associations, dtls_handle, FALSE);
|
|
|
|
}
|
|
|
|
}
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2008-11-17 21:44:42 +00:00
|
|
|
dissector_add_handle("sctp.port", dtls_handle);
|
|
|
|
dissector_add_handle("udp.port", dtls_handle);
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2006-08-02 08:15:51 +00:00
|
|
|
* DTLS Dissection Routines
|
2006-06-27 13:36:10 +00:00
|
|
|
*
|
|
|
|
*/
|
2006-08-02 08:15:51 +00:00
|
|
|
|
2006-06-27 13:36:10 +00:00
|
|
|
/* record layer dissector */
|
2006-08-02 08:15:51 +00:00
|
|
|
static gint dissect_dtls_record(tvbuff_t *tvb, packet_info *pinfo,
|
2009-10-16 21:17:57 +00:00
|
|
|
proto_tree *tree, guint32 offset,
|
|
|
|
guint *conv_version,
|
|
|
|
SslDecryptSession *conv_data);
|
2006-06-27 13:36:10 +00:00
|
|
|
|
|
|
|
/* change cipher spec dissector */
|
2006-08-02 08:15:51 +00:00
|
|
|
static void dissect_dtls_change_cipher_spec(tvbuff_t *tvb,
|
2006-06-27 13:36:10 +00:00
|
|
|
proto_tree *tree,
|
|
|
|
guint32 offset,
|
|
|
|
guint *conv_version, guint8 content_type);
|
|
|
|
|
|
|
|
/* alert message dissector */
|
2006-08-02 08:15:51 +00:00
|
|
|
static void dissect_dtls_alert(tvbuff_t *tvb, packet_info *pinfo,
|
2006-06-27 13:36:10 +00:00
|
|
|
proto_tree *tree, guint32 offset,
|
|
|
|
guint *conv_version);
|
|
|
|
|
|
|
|
/* handshake protocol dissector */
|
2006-08-02 08:15:51 +00:00
|
|
|
static void dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo,
|
2006-06-27 13:36:10 +00:00
|
|
|
proto_tree *tree, guint32 offset,
|
|
|
|
guint32 record_length,
|
|
|
|
guint *conv_version,
|
|
|
|
SslDecryptSession *conv_data, guint8 content_type);
|
|
|
|
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
static void dissect_dtls_hnd_cli_hello(tvbuff_t *tvb,
|
2006-06-27 13:36:10 +00:00
|
|
|
proto_tree *tree,
|
2007-03-24 13:21:08 +00:00
|
|
|
guint32 offset, guint32 length,
|
2006-06-27 13:36:10 +00:00
|
|
|
SslDecryptSession* ssl);
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
static void dissect_dtls_hnd_hello_verify_request(tvbuff_t *tvb,
|
2009-10-16 21:17:57 +00:00
|
|
|
proto_tree *tree,
|
|
|
|
guint32 offset,
|
|
|
|
SslDecryptSession* ssl);
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
static void dissect_dtls_hnd_srv_hello(tvbuff_t *tvb,
|
2006-06-27 13:36:10 +00:00
|
|
|
proto_tree *tree,
|
2007-03-24 13:21:08 +00:00
|
|
|
guint32 offset, guint32 length,
|
2006-06-27 13:36:10 +00:00
|
|
|
SslDecryptSession* ssl);
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
static void dissect_dtls_hnd_cert(tvbuff_t *tvb,
|
2006-06-27 13:36:10 +00:00
|
|
|
proto_tree *tree, guint32 offset, packet_info *pinfo);
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
static void dissect_dtls_hnd_cert_req(tvbuff_t *tvb,
|
2006-06-27 13:36:10 +00:00
|
|
|
proto_tree *tree,
|
|
|
|
guint32 offset);
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
static void dissect_dtls_hnd_finished(tvbuff_t *tvb,
|
2006-06-27 13:36:10 +00:00
|
|
|
proto_tree *tree,
|
|
|
|
guint32 offset,
|
|
|
|
guint* conv_version);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Support Functions
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
/*static void ssl_set_conv_version(packet_info *pinfo, guint version);*/
|
2006-08-02 08:15:51 +00:00
|
|
|
static gint dtls_is_valid_handshake_type(guint8 type);
|
|
|
|
|
|
|
|
static gint dtls_is_authoritative_version_message(guint8 content_type,
|
2009-10-16 21:17:57 +00:00
|
|
|
guint8 next_byte);
|
2006-08-02 08:15:51 +00:00
|
|
|
static gint looks_like_dtls(tvbuff_t *tvb, guint32 offset);
|
|
|
|
|
2006-06-27 13:36:10 +00:00
|
|
|
/*********************************************************************
|
|
|
|
*
|
|
|
|
* Main dissector
|
|
|
|
*
|
|
|
|
*********************************************************************/
|
|
|
|
/*
|
|
|
|
* Code to actually dissect the packets
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
dissect_dtls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
|
|
{
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
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
|
|
|
|
*/
|
2010-05-13 18:28:34 +00:00
|
|
|
conversation = find_or_create_conversation(pinfo);
|
2006-08-02 08:15:51 +00:00
|
|
|
conv_data = conversation_get_proto_data(conversation, proto_dtls);
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* manage dtls decryption data */
|
2007-03-24 13:21:08 +00:00
|
|
|
/*get a valid ssl session pointer*/
|
2006-08-02 08:15:51 +00:00
|
|
|
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);
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* we need to know witch side of conversation is speaking */
|
2009-08-13 09:07:03 +00:00
|
|
|
if (ssl_packet_from_server(ssl_session, dtls_associations, pinfo)) {
|
2006-08-02 08:15:51 +00:00
|
|
|
dummy.addr = pinfo->src;
|
|
|
|
dummy.port = pinfo->srcport;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
dummy.addr = pinfo->dst;
|
|
|
|
dummy.port = pinfo->destport;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
2007-04-25 22:33:47 +00:00
|
|
|
ssl_debug_printf("dissect_dtls server %s:%d\n",
|
2009-10-16 21:17:57 +00:00
|
|
|
ep_address_to_str(&dummy.addr),dummy.port);
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* try to retrive private key for this service. Do it now 'cause pinfo
|
2007-03-24 13:21:08 +00:00
|
|
|
* is not always available
|
2006-08-02 08:15:51 +00:00
|
|
|
* 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);
|
2007-03-24 13:21:08 +00:00
|
|
|
if (!ssl_session->private_key)
|
2006-08-02 08:15:51 +00:00
|
|
|
ssl_debug_printf("dissect_dtls can't find private key for this server!\n");
|
|
|
|
}
|
|
|
|
conv_version= & ssl_session->version;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2007-03-24 13:21:08 +00:00
|
|
|
/* try decryption only the first time we see this packet
|
From Michael Chen via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5863 :
1. Reload framing protocol no longer encapsulates the Reload message, instead
the latter is in its own tree following Reload framing, much like IP, UDP, etc.
2. Similarly, DTLS no longer encapsulates its data payload if the payload can
be dissected. The recognized payload is in its own tree following the DTLS,
much like IP, UDP, etc.
4. DTLS now has its own heuristic table for dissecting its payload, and
reload-framing is added to this DTLS heuristic table.
6. DTLS will try to dissect its payload if the agreed upon cipher is
RSA-NULL-MD5 (0x0001) or RSA-NULL-SHA (0x0002), even when DTLS is not
configured with the client/server private keys.
Still to do: make DTLS a heuristic dissector on top of UDP (item 3 in the bug).
svn path=/trunk/; revision=37110
2011-05-13 02:48:08 +00:00
|
|
|
* (to keep cipher synchronized) */
|
|
|
|
if (pinfo->fd->flags.visited)
|
2007-03-24 13:21:08 +00:00
|
|
|
ssl_session = NULL;
|
2006-08-02 08:15:51 +00:00
|
|
|
|
|
|
|
/* Initialize the protocol column; we'll set it later when we
|
2007-03-24 13:21:08 +00:00
|
|
|
* figure out what flavor of DTLS it is (actually only one
|
2006-08-02 08:15:51 +00:00
|
|
|
version exists). */
|
2009-08-09 07:59:51 +00:00
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "DTLS");
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* clear the the info column */
|
2009-08-09 07:36:13 +00:00
|
|
|
col_clear(pinfo->cinfo, COL_INFO);
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* Create display subtree for SSL as a whole */
|
|
|
|
if (tree)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
ti = proto_tree_add_item(tree, proto_dtls, tvb, 0, -1, FALSE);
|
|
|
|
dtls_tree = proto_item_add_subtree(ti, ett_dtls);
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* iterate through the records in this tvbuff */
|
|
|
|
while (tvb_reported_length_remaining(tvb, offset) != 0)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
/* on second and subsequent records per frame
|
|
|
|
* add a delimiter on info column
|
|
|
|
*/
|
2010-01-13 20:32:01 +00:00
|
|
|
if (!first_record_in_frame)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
col_append_str(pinfo->cinfo, COL_INFO, ", ");
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* first try to dispatch off the cached version
|
|
|
|
* known to be associated with the conversation
|
|
|
|
*/
|
|
|
|
switch(*conv_version) {
|
|
|
|
case SSL_VER_DTLS:
|
2009-10-16 21:17:57 +00:00
|
|
|
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
|
|
|
|
*/
|
2006-08-02 08:15:51 +00:00
|
|
|
default:
|
2009-10-16 21:17:57 +00:00
|
|
|
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);
|
|
|
|
col_append_str(pinfo->cinfo, COL_INFO,
|
|
|
|
"Continuation Data");
|
|
|
|
|
|
|
|
/* Set the protocol column */
|
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "DTLS");
|
|
|
|
}
|
|
|
|
break;
|
2006-08-02 08:15:51 +00:00
|
|
|
}
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* set up for next record in frame, if any */
|
|
|
|
first_record_in_frame = FALSE;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
2007-04-18 04:13:50 +00:00
|
|
|
|
|
|
|
tap_queue_packet(dtls_tap, pinfo, NULL);
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
static gint
|
2007-03-24 13:21:08 +00:00
|
|
|
decrypt_dtls_record(tvbuff_t *tvb, packet_info *pinfo, guint32 offset,
|
2009-10-16 21:17:57 +00:00
|
|
|
guint32 record_length, guint8 content_type, SslDecryptSession* ssl,
|
|
|
|
gboolean save_plaintext)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
gint ret;
|
|
|
|
SslDecoder* decoder;
|
2007-03-24 13:21:08 +00:00
|
|
|
ret = 0;
|
2006-08-02 08:15:51 +00:00
|
|
|
|
|
|
|
/* if we can decrypt and decryption have success
|
|
|
|
* add decrypted data to this packet info */
|
2010-02-19 07:43:26 +00:00
|
|
|
ssl_debug_printf("decrypt_dtls_record: app_data len %d, ssl state %X\n",
|
2009-10-16 21:17:57 +00:00
|
|
|
record_length, ssl->state);
|
From Michael Chen via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5863 :
1. Reload framing protocol no longer encapsulates the Reload message, instead
the latter is in its own tree following Reload framing, much like IP, UDP, etc.
2. Similarly, DTLS no longer encapsulates its data payload if the payload can
be dissected. The recognized payload is in its own tree following the DTLS,
much like IP, UDP, etc.
4. DTLS now has its own heuristic table for dissecting its payload, and
reload-framing is added to this DTLS heuristic table.
6. DTLS will try to dissect its payload if the agreed upon cipher is
RSA-NULL-MD5 (0x0001) or RSA-NULL-SHA (0x0002), even when DTLS is not
configured with the client/server private keys.
Still to do: make DTLS a heuristic dissector on top of UDP (item 3 in the bug).
svn path=/trunk/; revision=37110
2011-05-13 02:48:08 +00:00
|
|
|
if (!ssl || (!save_plaintext && !(ssl->state & SSL_HAVE_SESSION_KEY))) {
|
2006-08-02 08:15:51 +00:00
|
|
|
ssl_debug_printf("decrypt_dtls_record: no session key\n");
|
|
|
|
return ret;
|
|
|
|
}
|
2007-03-24 13:21:08 +00:00
|
|
|
|
|
|
|
/* retrive decoder for this packet direction */
|
2011-04-18 15:29:25 +00:00
|
|
|
if (ssl_packet_from_server(ssl, dtls_associations, pinfo) != 0) {
|
2006-08-02 08:15:51 +00:00
|
|
|
ssl_debug_printf("decrypt_dtls_record: using server decoder\n");
|
2007-04-10 15:12:48 +00:00
|
|
|
decoder = ssl->server;
|
2006-08-02 08:15:51 +00:00
|
|
|
}
|
2007-03-24 13:21:08 +00:00
|
|
|
else {
|
2006-08-02 08:15:51 +00:00
|
|
|
ssl_debug_printf("decrypt_dtls_record: using client decoder\n");
|
2007-04-10 15:12:48 +00:00
|
|
|
decoder = ssl->client;
|
2006-08-02 08:15:51 +00:00
|
|
|
}
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* ensure we have enough storage space for decrypted data */
|
|
|
|
if (record_length > dtls_decrypted_data.data_len)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
ssl_debug_printf("decrypt_dtls_record: allocating %d bytes"
|
2009-10-16 21:17:57 +00:00
|
|
|
" for decrypt data (old len %d)\n",
|
|
|
|
record_length + 32, dtls_decrypted_data.data_len);
|
2007-03-24 13:21:08 +00:00
|
|
|
dtls_decrypted_data.data = g_realloc(dtls_decrypted_data.data,
|
2009-10-16 21:17:57 +00:00
|
|
|
record_length + 32);
|
2006-08-02 08:15:51 +00:00
|
|
|
dtls_decrypted_data.data_len = record_length + 32;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
2007-03-24 13:21:08 +00:00
|
|
|
|
|
|
|
/* run decryption and add decrypted payload to protocol data, if decryption
|
2006-08-02 08:15:51 +00:00
|
|
|
* is successful*/
|
2007-03-24 13:21:08 +00:00
|
|
|
dtls_decrypted_data_avail = dtls_decrypted_data.data_len;
|
From Michael Chen via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5863 :
1. Reload framing protocol no longer encapsulates the Reload message, instead
the latter is in its own tree following Reload framing, much like IP, UDP, etc.
2. Similarly, DTLS no longer encapsulates its data payload if the payload can
be dissected. The recognized payload is in its own tree following the DTLS,
much like IP, UDP, etc.
4. DTLS now has its own heuristic table for dissecting its payload, and
reload-framing is added to this DTLS heuristic table.
6. DTLS will try to dissect its payload if the agreed upon cipher is
RSA-NULL-MD5 (0x0001) or RSA-NULL-SHA (0x0002), even when DTLS is not
configured with the client/server private keys.
Still to do: make DTLS a heuristic dissector on top of UDP (item 3 in the bug).
svn path=/trunk/; revision=37110
2011-05-13 02:48:08 +00:00
|
|
|
if (ssl->state & SSL_HAVE_SESSION_KEY) {
|
|
|
|
if (ssl_decrypt_record(ssl, decoder, content_type, tvb_get_ptr(tvb, offset, record_length),
|
|
|
|
record_length, &dtls_compressed_data, &dtls_decrypted_data, &dtls_decrypted_data_avail) == 0)
|
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
else if (ssl->cipher == 0x0001 || ssl->cipher == 0x0002) {
|
|
|
|
/* Non-encrypting cipher RSA-NULL-MD5 or RSA-NULL-SHA */
|
|
|
|
memcpy(dtls_decrypted_data.data, tvb_get_ptr(tvb, offset, record_length), record_length);
|
|
|
|
dtls_decrypted_data_avail = dtls_decrypted_data.data_len = record_length;
|
2006-08-02 08:15:51 +00:00
|
|
|
ret = 1;
|
From Michael Chen via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5863 :
1. Reload framing protocol no longer encapsulates the Reload message, instead
the latter is in its own tree following Reload framing, much like IP, UDP, etc.
2. Similarly, DTLS no longer encapsulates its data payload if the payload can
be dissected. The recognized payload is in its own tree following the DTLS,
much like IP, UDP, etc.
4. DTLS now has its own heuristic table for dissecting its payload, and
reload-framing is added to this DTLS heuristic table.
6. DTLS will try to dissect its payload if the agreed upon cipher is
RSA-NULL-MD5 (0x0001) or RSA-NULL-SHA (0x0002), even when DTLS is not
configured with the client/server private keys.
Still to do: make DTLS a heuristic dissector on top of UDP (item 3 in the bug).
svn path=/trunk/; revision=37110
2011-05-13 02:48:08 +00:00
|
|
|
}
|
2006-08-02 08:15:51 +00:00
|
|
|
|
From Michael Chen via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5863 :
1. Reload framing protocol no longer encapsulates the Reload message, instead
the latter is in its own tree following Reload framing, much like IP, UDP, etc.
2. Similarly, DTLS no longer encapsulates its data payload if the payload can
be dissected. The recognized payload is in its own tree following the DTLS,
much like IP, UDP, etc.
4. DTLS now has its own heuristic table for dissecting its payload, and
reload-framing is added to this DTLS heuristic table.
6. DTLS will try to dissect its payload if the agreed upon cipher is
RSA-NULL-MD5 (0x0001) or RSA-NULL-SHA (0x0002), even when DTLS is not
configured with the client/server private keys.
Still to do: make DTLS a heuristic dissector on top of UDP (item 3 in the bug).
svn path=/trunk/; revision=37110
2011-05-13 02:48:08 +00:00
|
|
|
if (ret && save_plaintext) {
|
2011-05-27 03:06:50 +00:00
|
|
|
ssl_add_data_info(proto_dtls, pinfo, dtls_decrypted_data.data, dtls_decrypted_data_avail, tvb_raw_offset(tvb)+offset, 0);
|
From Michael Chen via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5863 :
1. Reload framing protocol no longer encapsulates the Reload message, instead
the latter is in its own tree following Reload framing, much like IP, UDP, etc.
2. Similarly, DTLS no longer encapsulates its data payload if the payload can
be dissected. The recognized payload is in its own tree following the DTLS,
much like IP, UDP, etc.
4. DTLS now has its own heuristic table for dissecting its payload, and
reload-framing is added to this DTLS heuristic table.
6. DTLS will try to dissect its payload if the agreed upon cipher is
RSA-NULL-MD5 (0x0001) or RSA-NULL-SHA (0x0002), even when DTLS is not
configured with the client/server private keys.
Still to do: make DTLS a heuristic dissector on top of UDP (item 3 in the bug).
svn path=/trunk/; revision=37110
2011-05-13 02:48:08 +00:00
|
|
|
}
|
2007-01-12 10:25:03 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
return ret;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*********************************************************************
|
|
|
|
*
|
2006-08-02 08:15:51 +00:00
|
|
|
* DTLS Dissection Routines
|
2006-06-27 13:36:10 +00:00
|
|
|
*
|
|
|
|
*********************************************************************/
|
2006-08-02 08:15:51 +00:00
|
|
|
static gint
|
|
|
|
dissect_dtls_record(tvbuff_t *tvb, packet_info *pinfo,
|
2006-06-27 13:36:10 +00:00
|
|
|
proto_tree *tree, guint32 offset,
|
2006-08-02 08:15:51 +00:00
|
|
|
guint *conv_version,
|
2006-06-27 13:36:10 +00:00
|
|
|
SslDecryptSession* ssl)
|
|
|
|
{
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/*
|
|
|
|
* 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;
|
2007-03-24 13:21:08 +00:00
|
|
|
gint64 sequence_number_temp;
|
2006-08-02 08:15:51 +00:00
|
|
|
guint8 content_type;
|
|
|
|
guint8 next_byte;
|
|
|
|
proto_tree *ti;
|
|
|
|
proto_tree *dtls_record_tree;
|
|
|
|
guint32 available_bytes;
|
|
|
|
SslAssociation* association;
|
2007-01-12 10:25:03 +00:00
|
|
|
SslDataInfo *appl_data;
|
2006-08-02 08:15:51 +00:00
|
|
|
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;
|
2007-03-24 13:21:08 +00:00
|
|
|
sequence_number+=sequence_number_temp;
|
2006-08-02 08:15:51 +00:00
|
|
|
record_length = tvb_get_ntohs(tvb, offset + 11);
|
|
|
|
|
2007-03-24 13:21:08 +00:00
|
|
|
if(ssl){
|
2009-08-13 09:07:03 +00:00
|
|
|
if(ssl_packet_from_server(ssl, dtls_associations, pinfo)){
|
2007-04-10 15:12:48 +00:00
|
|
|
if (ssl->server) {
|
|
|
|
ssl->server->seq=(guint32)sequence_number;
|
|
|
|
ssl->server->epoch=epoch;
|
|
|
|
}
|
2006-08-02 08:15:51 +00:00
|
|
|
}
|
|
|
|
else{
|
2007-04-10 15:12:48 +00:00
|
|
|
if (ssl->client) {
|
|
|
|
ssl->client->seq=(guint32)sequence_number;
|
|
|
|
ssl->client->epoch=epoch;
|
|
|
|
}
|
2006-08-02 08:15:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!ssl_is_valid_content_type(content_type)) {
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2006-06-27 13:36:10 +00:00
|
|
|
/* if we don't have a valid content_type, there's no sense
|
|
|
|
* continuing any further
|
|
|
|
*/
|
2009-09-24 20:21:23 +00:00
|
|
|
col_append_str(pinfo->cinfo, COL_INFO, "Continuation Data");
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* Set the protocol column */
|
2009-08-09 07:59:51 +00:00
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "DTLS");
|
2006-08-02 08:15:51 +00:00
|
|
|
return offset + 13 + record_length;
|
2007-03-24 13:21:08 +00:00
|
|
|
}
|
2006-08-02 08:15:51 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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,
|
2009-10-16 21:17:57 +00:00
|
|
|
offset, 13 + record_length, 0);
|
2006-08-02 08:15:51 +00:00
|
|
|
dtls_record_tree = proto_item_add_subtree(ti, ett_dtls_record);
|
|
|
|
}
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
if (dtls_record_tree)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* show the one-byte content type */
|
|
|
|
proto_tree_add_item(dtls_record_tree, hf_dtls_record_content_type,
|
2009-10-16 21:17:57 +00:00
|
|
|
tvb, offset, 1, FALSE);
|
2006-08-02 08:15:51 +00:00
|
|
|
offset++;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* add the version */
|
|
|
|
proto_tree_add_item(dtls_record_tree, hf_dtls_record_version, tvb,
|
2009-10-16 21:17:57 +00:00
|
|
|
offset, 2, FALSE);
|
2006-08-02 08:15:51 +00:00
|
|
|
offset += 2;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* show epoch */
|
|
|
|
proto_tree_add_uint(dtls_record_tree, hf_dtls_record_epoch, tvb, offset, 2, epoch);
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
offset += 2;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* add sequence_number */
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
proto_tree_add_double(dtls_record_tree, hf_dtls_record_sequence_number, tvb, offset, 6, sequence_number);
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
offset += 6;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* add the length */
|
|
|
|
proto_tree_add_uint(dtls_record_tree, hf_dtls_record_length, tvb,
|
2009-10-16 21:17:57 +00:00
|
|
|
offset, 2, record_length);
|
2006-08-02 08:15:51 +00:00
|
|
|
offset += 2; /* move past length field itself */
|
2006-06-27 13:36:10 +00:00
|
|
|
|
|
|
|
}
|
2006-08-02 08:15:51 +00:00
|
|
|
else
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
/* if no GUI tree, then just skip over those fields */
|
|
|
|
offset += 13;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/*
|
|
|
|
* 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))
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2007-11-05 23:05:20 +00:00
|
|
|
if (version == DTLSV1DOT0_VERSION ||
|
2009-10-16 21:17:57 +00:00
|
|
|
version == DTLSV1DOT0_VERSION_NOT)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2009-10-16 21:17:57 +00:00
|
|
|
*conv_version = SSL_VER_DTLS;
|
|
|
|
if (ssl) {
|
|
|
|
ssl->version_netorder = version;
|
|
|
|
ssl->state |= SSL_VERSION;
|
|
|
|
}
|
|
|
|
/*ssl_set_conv_version(pinfo, ssl->version);*/
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
}
|
2006-08-02 08:15:51 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_PROTOCOL))
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
if (version == DTLSV1DOT0_VERSION)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL,
|
2010-02-19 07:43:26 +00:00
|
|
|
val_to_str_const(SSL_VER_DTLS, ssl_version_short_names, "SSL"));
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
2006-08-02 08:15:51 +00:00
|
|
|
else
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL,"DTLS");
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/*
|
|
|
|
* now dissect the next layer
|
|
|
|
*/
|
|
|
|
ssl_debug_printf("dissect_dtls_record: content_type %d\n",content_type);
|
2007-03-24 13:21:08 +00:00
|
|
|
|
|
|
|
/* PAOLO try to decrypt each record (we must keep ciphers "in sync")
|
2006-08-02 08:15:51 +00:00
|
|
|
* store plain text only for app data */
|
|
|
|
|
|
|
|
switch (content_type) {
|
|
|
|
case SSL_ID_CHG_CIPHER_SPEC:
|
2009-09-24 20:21:23 +00:00
|
|
|
col_append_str(pinfo->cinfo, COL_INFO, "Change Cipher Spec");
|
2006-08-02 08:15:51 +00:00
|
|
|
dissect_dtls_change_cipher_spec(tvb, dtls_record_tree,
|
2009-10-16 21:17:57 +00:00
|
|
|
offset, conv_version, content_type);
|
2006-08-02 08:15:51 +00:00
|
|
|
break;
|
|
|
|
case SSL_ID_ALERT:
|
|
|
|
{
|
|
|
|
tvbuff_t* decrypted;
|
|
|
|
decrypted = 0;
|
2007-03-24 13:21:08 +00:00
|
|
|
if (ssl&&decrypt_dtls_record(tvb, pinfo, offset,
|
2009-10-16 21:17:57 +00:00
|
|
|
record_length, content_type, ssl, FALSE))
|
|
|
|
ssl_add_record_info(proto_dtls, pinfo, dtls_decrypted_data.data,
|
|
|
|
dtls_decrypted_data_avail, offset);
|
2006-08-02 08:15:51 +00:00
|
|
|
|
|
|
|
/* try to retrive and use decrypted alert record, if any. */
|
|
|
|
decrypted = ssl_get_record_info(proto_dtls, pinfo, offset);
|
|
|
|
if (decrypted)
|
2009-10-16 21:17:57 +00:00
|
|
|
dissect_dtls_alert(decrypted, pinfo, dtls_record_tree, 0,
|
|
|
|
conv_version);
|
2006-08-02 08:15:51 +00:00
|
|
|
else
|
2009-10-16 21:17:57 +00:00
|
|
|
dissect_dtls_alert(tvb, pinfo, dtls_record_tree, offset,
|
|
|
|
conv_version);
|
2006-08-02 08:15:51 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SSL_ID_HANDSHAKE:
|
|
|
|
{
|
|
|
|
tvbuff_t* decrypted;
|
|
|
|
decrypted = 0;
|
2007-03-24 13:21:08 +00:00
|
|
|
/* try to decrypt handshake record, if possible. Store decrypted
|
2006-08-02 08:15:51 +00:00
|
|
|
* 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) */
|
2007-03-24 13:21:08 +00:00
|
|
|
if (ssl && decrypt_dtls_record(tvb, pinfo, offset,
|
2009-10-16 21:17:57 +00:00
|
|
|
record_length, content_type, ssl, FALSE))
|
|
|
|
ssl_add_record_info(proto_dtls, pinfo, dtls_decrypted_data.data,
|
|
|
|
dtls_decrypted_data_avail, offset);
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* try to retrive and use decrypted handshake record, if any. */
|
|
|
|
decrypted = ssl_get_record_info(proto_dtls, pinfo, offset);
|
|
|
|
if (decrypted)
|
2009-10-16 21:17:57 +00:00
|
|
|
dissect_dtls_handshake(decrypted, pinfo, dtls_record_tree, 0,
|
2011-05-27 03:06:50 +00:00
|
|
|
tvb_length(decrypted), conv_version, ssl, content_type);
|
2007-03-24 13:21:08 +00:00
|
|
|
else
|
2009-10-16 21:17:57 +00:00
|
|
|
dissect_dtls_handshake(tvb, pinfo, dtls_record_tree, offset,
|
2006-06-27 13:36:10 +00:00
|
|
|
record_length, conv_version, ssl, content_type);
|
2006-08-02 08:15:51 +00:00
|
|
|
break;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
2006-08-02 08:15:51 +00:00
|
|
|
case SSL_ID_APP_DATA:
|
|
|
|
if (ssl)
|
2007-03-24 13:21:08 +00:00
|
|
|
decrypt_dtls_record(tvb, pinfo, offset,
|
2009-10-16 21:17:57 +00:00
|
|
|
record_length, content_type, ssl, TRUE);
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* show on info colum what we are decoding */
|
2009-09-24 20:21:23 +00:00
|
|
|
col_append_str(pinfo->cinfo, COL_INFO, "Application Data");
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
if (!dtls_record_tree)
|
|
|
|
break;
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* we need dissector information when the selected packet is shown.
|
|
|
|
* ssl session pointer is NULL at that time, so we can't access
|
2007-03-24 13:21:08 +00:00
|
|
|
* info cached there*/
|
2006-08-25 08:07:26 +00:00
|
|
|
association = ssl_association_find(dtls_associations, pinfo->srcport, pinfo->ptype == PT_TCP);
|
|
|
|
association = association ? association: ssl_association_find(dtls_associations, pinfo->destport, pinfo->ptype == PT_TCP);
|
2006-08-02 08:15:51 +00:00
|
|
|
|
|
|
|
proto_item_set_text(dtls_record_tree,
|
2009-10-16 21:17:57 +00:00
|
|
|
"%s Record Layer: %s Protocol: %s",
|
2010-02-19 07:43:26 +00:00
|
|
|
val_to_str_const(*conv_version, ssl_version_short_names, "SSL"),
|
2009-10-16 21:17:57 +00:00
|
|
|
val_to_str(content_type, ssl_31_content_type, "unknown"),
|
|
|
|
association?association->info:"Application Data");
|
2007-03-24 13:21:08 +00:00
|
|
|
|
|
|
|
/* show decrypted data info, if available */
|
2011-05-27 03:06:50 +00:00
|
|
|
appl_data = ssl_get_data_info(proto_dtls, pinfo, tvb_raw_offset(tvb)+offset);
|
2007-01-12 10:25:03 +00:00
|
|
|
if (appl_data && (appl_data->plain_data.data_len > 0))
|
2006-08-02 08:15:51 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
tvbuff_t *next_tvb;
|
From Michael Chen via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5863 :
1. Reload framing protocol no longer encapsulates the Reload message, instead
the latter is in its own tree following Reload framing, much like IP, UDP, etc.
2. Similarly, DTLS no longer encapsulates its data payload if the payload can
be dissected. The recognized payload is in its own tree following the DTLS,
much like IP, UDP, etc.
4. DTLS now has its own heuristic table for dissecting its payload, and
reload-framing is added to this DTLS heuristic table.
6. DTLS will try to dissect its payload if the agreed upon cipher is
RSA-NULL-MD5 (0x0001) or RSA-NULL-SHA (0x0002), even when DTLS is not
configured with the client/server private keys.
Still to do: make DTLS a heuristic dissector on top of UDP (item 3 in the bug).
svn path=/trunk/; revision=37110
2011-05-13 02:48:08 +00:00
|
|
|
gboolean dissected;
|
2009-10-16 21:17:57 +00:00
|
|
|
/* try to dissect decrypted data*/
|
|
|
|
ssl_debug_printf("dissect_dtls_record decrypted len %d\n",
|
|
|
|
appl_data->plain_data.data_len);
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2009-10-16 21:17:57 +00:00
|
|
|
/* create a new TVB structure for desegmented data */
|
|
|
|
next_tvb = tvb_new_child_real_data(tvb, appl_data->plain_data.data, appl_data->plain_data.data_len, appl_data->plain_data.data_len);
|
2007-01-12 10:25:03 +00:00
|
|
|
|
2009-10-16 21:17:57 +00:00
|
|
|
add_new_data_source(pinfo, next_tvb, "Decrypted DTLS data");
|
2006-08-02 08:15:51 +00:00
|
|
|
|
2009-10-16 21:17:57 +00:00
|
|
|
/* find out a dissector using server port*/
|
|
|
|
if (association && association->handle) {
|
|
|
|
ssl_debug_printf("dissect_dtls_record found association %p\n", (void *)association);
|
|
|
|
ssl_print_text_data("decrypted app data",appl_data->plain_data.data, appl_data->plain_data.data_len);
|
2007-03-24 13:21:08 +00:00
|
|
|
|
From Michael Chen via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5863 :
1. Reload framing protocol no longer encapsulates the Reload message, instead
the latter is in its own tree following Reload framing, much like IP, UDP, etc.
2. Similarly, DTLS no longer encapsulates its data payload if the payload can
be dissected. The recognized payload is in its own tree following the DTLS,
much like IP, UDP, etc.
4. DTLS now has its own heuristic table for dissecting its payload, and
reload-framing is added to this DTLS heuristic table.
6. DTLS will try to dissect its payload if the agreed upon cipher is
RSA-NULL-MD5 (0x0001) or RSA-NULL-SHA (0x0002), even when DTLS is not
configured with the client/server private keys.
Still to do: make DTLS a heuristic dissector on top of UDP (item 3 in the bug).
svn path=/trunk/; revision=37110
2011-05-13 02:48:08 +00:00
|
|
|
dissected = call_dissector_only(association->handle, next_tvb, pinfo, top_tree);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* try heuristic subdissectors */
|
|
|
|
dissected = dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, top_tree);
|
2009-10-16 21:17:57 +00:00
|
|
|
}
|
From Michael Chen via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5863 :
1. Reload framing protocol no longer encapsulates the Reload message, instead
the latter is in its own tree following Reload framing, much like IP, UDP, etc.
2. Similarly, DTLS no longer encapsulates its data payload if the payload can
be dissected. The recognized payload is in its own tree following the DTLS,
much like IP, UDP, etc.
4. DTLS now has its own heuristic table for dissecting its payload, and
reload-framing is added to this DTLS heuristic table.
6. DTLS will try to dissect its payload if the agreed upon cipher is
RSA-NULL-MD5 (0x0001) or RSA-NULL-SHA (0x0002), even when DTLS is not
configured with the client/server private keys.
Still to do: make DTLS a heuristic dissector on top of UDP (item 3 in the bug).
svn path=/trunk/; revision=37110
2011-05-13 02:48:08 +00:00
|
|
|
if (dissected)
|
|
|
|
break;
|
2007-03-24 13:21:08 +00:00
|
|
|
}
|
From Michael Chen via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5863 :
1. Reload framing protocol no longer encapsulates the Reload message, instead
the latter is in its own tree following Reload framing, much like IP, UDP, etc.
2. Similarly, DTLS no longer encapsulates its data payload if the payload can
be dissected. The recognized payload is in its own tree following the DTLS,
much like IP, UDP, etc.
4. DTLS now has its own heuristic table for dissecting its payload, and
reload-framing is added to this DTLS heuristic table.
6. DTLS will try to dissect its payload if the agreed upon cipher is
RSA-NULL-MD5 (0x0001) or RSA-NULL-SHA (0x0002), even when DTLS is not
configured with the client/server private keys.
Still to do: make DTLS a heuristic dissector on top of UDP (item 3 in the bug).
svn path=/trunk/; revision=37110
2011-05-13 02:48:08 +00:00
|
|
|
|
|
|
|
proto_tree_add_item(dtls_record_tree, hf_dtls_record_appdata, tvb,
|
|
|
|
offset, record_length, 0);
|
2006-08-02 08:15:51 +00:00
|
|
|
break;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
default:
|
|
|
|
/* shouldn't get here since we check above for valid types */
|
2009-09-24 20:21:23 +00:00
|
|
|
col_append_str(pinfo->cinfo, COL_INFO, "Bad DTLS Content Type");
|
2006-08-02 08:15:51 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
offset += record_length; /* skip to end of record */
|
|
|
|
|
|
|
|
return offset;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* dissects the change cipher spec procotol, filling in the tree */
|
|
|
|
static void
|
2006-08-02 08:15:51 +00:00
|
|
|
dissect_dtls_change_cipher_spec(tvbuff_t *tvb,
|
2006-06-27 13:36:10 +00:00
|
|
|
proto_tree *tree, guint32 offset,
|
|
|
|
guint* conv_version, guint8 content_type)
|
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
/*
|
|
|
|
* struct {
|
|
|
|
* enum { change_cipher_spec(1), (255) } type;
|
|
|
|
* } ChangeCipherSpec;
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
if (tree)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
proto_item_set_text(tree,
|
2009-10-16 21:17:57 +00:00
|
|
|
"%s Record Layer: %s Protocol: Change Cipher Spec",
|
2010-02-19 07:43:26 +00:00
|
|
|
val_to_str_const(*conv_version, ssl_version_short_names, "SSL"),
|
2009-10-16 21:17:57 +00:00
|
|
|
val_to_str(content_type, ssl_31_content_type, "unknown"));
|
2006-08-02 08:15:51 +00:00
|
|
|
proto_tree_add_item(tree, hf_dtls_change_cipher_spec, tvb,
|
2009-10-16 21:17:57 +00:00
|
|
|
offset++, 1, FALSE);
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* dissects the alert message, filling in the tree */
|
|
|
|
static void
|
2006-08-02 08:15:51 +00:00
|
|
|
dissect_dtls_alert(tvbuff_t *tvb, packet_info *pinfo,
|
2006-06-27 13:36:10 +00:00
|
|
|
proto_tree *tree, guint32 offset,
|
|
|
|
guint* conv_version)
|
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
/* 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;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
if (tree)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
ti = proto_tree_add_item(tree, hf_dtls_alert_message, tvb,
|
2009-10-16 21:17:57 +00:00
|
|
|
offset, 2, 0);
|
2006-08-02 08:15:51 +00:00
|
|
|
ssl_alert_tree = proto_item_add_subtree(ti, ett_dtls_alert);
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/*
|
|
|
|
* set the record layer label
|
|
|
|
*/
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* 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);
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
byte = tvb_get_guint8(tvb, offset+1); /* grab the desc byte */
|
|
|
|
desc = match_strval(byte, ssl_31_alert_description);
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* now set the text in the record layer line */
|
|
|
|
if (level && desc)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
2009-10-16 21:17:57 +00:00
|
|
|
col_append_fstr(pinfo->cinfo, COL_INFO,
|
|
|
|
"Alert (Level: %s, Description: %s)",
|
|
|
|
level, desc);
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
2006-08-02 08:15:51 +00:00
|
|
|
else
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-09-24 20:21:23 +00:00
|
|
|
col_append_str(pinfo->cinfo, COL_INFO, "Encrypted Alert");
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
if (tree)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
if (level && desc)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
proto_item_set_text(tree, "%s Record Layer: Alert "
|
|
|
|
"(Level: %s, Description: %s)",
|
2010-02-19 07:43:26 +00:00
|
|
|
val_to_str_const(*conv_version, ssl_version_short_names, "SSL"),
|
2009-10-16 21:17:57 +00:00
|
|
|
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);
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
2006-08-02 08:15:51 +00:00
|
|
|
else
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
proto_item_set_text(tree,
|
|
|
|
"%s Record Layer: Encrypted Alert",
|
2010-02-19 07:43:26 +00:00
|
|
|
val_to_str_const(*conv_version, ssl_version_short_names, "SSL"));
|
2009-10-16 21:17:57 +00:00
|
|
|
proto_item_set_text(ssl_alert_tree,
|
|
|
|
"Alert Message: Encrypted Alert");
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* dissects the handshake protocol, filling the tree */
|
|
|
|
static void
|
2006-08-02 08:15:51 +00:00
|
|
|
dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo,
|
2006-06-27 13:36:10 +00:00
|
|
|
proto_tree *tree, guint32 offset,
|
|
|
|
guint32 record_length, guint *conv_version,
|
|
|
|
SslDecryptSession* ssl, guint8 content_type)
|
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
/* 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
|
|
|
|
*/
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* set record_length to the max offset */
|
|
|
|
record_length += offset;
|
2007-11-05 23:05:20 +00:00
|
|
|
for (; offset < record_length; offset += fragment_length,
|
2009-10-16 21:17:57 +00:00
|
|
|
first_iteration = FALSE) /* set up for next pass, if any */
|
2006-08-02 08:15:51 +00:00
|
|
|
{
|
2007-11-05 23:05:20 +00:00
|
|
|
fragment_data *frag_msg = NULL;
|
|
|
|
tvbuff_t *new_tvb = NULL;
|
2008-06-25 03:05:19 +00:00
|
|
|
const gchar *frag_str = NULL;
|
2007-11-05 23:05:20 +00:00
|
|
|
gboolean fragmented;
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
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);
|
2007-11-05 23:05:20 +00:00
|
|
|
fragmented = fragment_length != length;
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
if (!msg_type_str && !first_iteration)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
/* only dissect / report messages if they're
|
|
|
|
* either the first message in this record
|
|
|
|
* or they're a valid message type
|
|
|
|
*/
|
|
|
|
return;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* on second and later iterations, add comma to info col */
|
|
|
|
if (!first_iteration)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
col_append_str(pinfo->cinfo, COL_INFO, ", ");
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/*
|
|
|
|
* Update our info string
|
|
|
|
*/
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
2009-10-16 21:17:57 +00:00
|
|
|
col_append_str(pinfo->cinfo, COL_INFO, (msg_type_str != NULL)
|
|
|
|
? msg_type_str : "Encrypted Handshake Message");
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2007-11-05 23:05:20 +00:00
|
|
|
/* Handle fragments of known message type */
|
|
|
|
if (fragmented)
|
2009-10-16 21:17:57 +00:00
|
|
|
{
|
|
|
|
gboolean frag_hand;
|
|
|
|
|
|
|
|
switch (msg_type) {
|
|
|
|
case SSL_HND_HELLO_REQUEST:
|
|
|
|
case SSL_HND_CLIENT_HELLO:
|
|
|
|
case SSL_HND_HELLO_VERIFY_REQUEST:
|
|
|
|
case SSL_HND_SERVER_HELLO:
|
|
|
|
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:
|
|
|
|
frag_hand = TRUE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Ignore encrypted handshake messages */
|
|
|
|
frag_hand = FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (frag_hand) {
|
|
|
|
/* Fragmented handshake message */
|
|
|
|
pinfo->fragmented = TRUE;
|
2010-10-27 18:26:54 +00:00
|
|
|
|
2011-06-02 17:12:13 +00:00
|
|
|
/* Don't pass the reassembly code data that doesn't exist */
|
|
|
|
tvb_ensure_bytes_exist(tvb, offset, fragment_length);
|
2010-10-27 18:26:54 +00:00
|
|
|
|
2009-10-16 21:17:57 +00:00
|
|
|
frag_msg = fragment_add(tvb, offset+12, pinfo, message_seq,
|
|
|
|
dtls_fragment_table,
|
|
|
|
fragment_offset, fragment_length, TRUE);
|
|
|
|
fragment_set_tot_len(pinfo, message_seq, dtls_fragment_table,
|
|
|
|
length);
|
|
|
|
|
|
|
|
if (frag_msg && (fragment_length + fragment_offset) == length)
|
|
|
|
{
|
|
|
|
/* Reassembled */
|
|
|
|
new_tvb = process_reassembled_data(tvb, offset+12, pinfo,
|
2010-02-06 18:20:21 +00:00
|
|
|
"Reassembled DTLS",
|
2009-10-16 21:17:57 +00:00
|
|
|
frag_msg,
|
|
|
|
&dtls_frag_items,
|
|
|
|
NULL, tree);
|
|
|
|
frag_str = " (Reassembled)";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
frag_str = " (Fragment)";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
|
|
col_append_str(pinfo->cinfo, COL_INFO, frag_str);
|
|
|
|
}
|
|
|
|
}
|
2007-11-05 23:05:20 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
if (tree)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
/* set the label text on the record layer expanding node */
|
|
|
|
if (first_iteration)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
proto_item_set_text(tree, "%s Record Layer: %s Protocol: %s%s",
|
2010-02-19 07:43:26 +00:00
|
|
|
val_to_str_const(*conv_version, ssl_version_short_names, "SSL"),
|
2009-10-16 21:17:57 +00:00
|
|
|
val_to_str(content_type, ssl_31_content_type, "unknown"),
|
|
|
|
(msg_type_str!=NULL) ? msg_type_str :
|
|
|
|
"Encrypted Handshake Message",
|
|
|
|
(frag_str!=NULL) ? frag_str : "");
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
2009-10-16 21:17:57 +00:00
|
|
|
else
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
proto_item_set_text(tree, "%s Record Layer: %s Protocol: %s%s",
|
2010-02-19 07:43:26 +00:00
|
|
|
val_to_str_const(*conv_version, ssl_version_short_names, "SSL"),
|
2009-10-16 21:17:57 +00:00
|
|
|
val_to_str(content_type, ssl_31_content_type, "unknown"),
|
|
|
|
"Multiple Handshake Messages",
|
|
|
|
(frag_str!=NULL) ? frag_str : "");
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
2009-10-16 21:17:57 +00:00
|
|
|
/* add a subtree for the handshake protocol */
|
|
|
|
ti = proto_tree_add_item(tree, hf_dtls_handshake_protocol, tvb,
|
|
|
|
offset, fragment_length + 12, 0);
|
|
|
|
ssl_hand_tree = proto_item_add_subtree(ti, ett_dtls_handshake);
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2009-10-16 21:17:57 +00:00
|
|
|
if (ssl_hand_tree)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
/* set the text label on the subtree node */
|
|
|
|
proto_item_set_text(ssl_hand_tree, "Handshake Protocol: %s%s",
|
|
|
|
(msg_type_str != NULL) ? msg_type_str :
|
|
|
|
"Encrypted Handshake Message",
|
|
|
|
(frag_str!=NULL) ? frag_str : "");
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* if we don't have a valid handshake type, just quit dissecting */
|
|
|
|
if (!msg_type_str)
|
2009-10-16 21:17:57 +00:00
|
|
|
return;
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* if we are doing ssl decryption we must dissect some requests type */
|
|
|
|
if (ssl_hand_tree || ssl)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
tvbuff_t *sub_tvb = NULL;
|
|
|
|
|
|
|
|
/* 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,
|
2006-06-27 13:36:10 +00:00
|
|
|
tvb, offset, 3, length);
|
2009-10-16 21:17:57 +00:00
|
|
|
offset += 3;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2009-10-16 21:17:57 +00:00
|
|
|
if (ssl_hand_tree)
|
|
|
|
proto_tree_add_uint(ssl_hand_tree, hf_dtls_handshake_message_seq,
|
2006-06-27 13:36:10 +00:00
|
|
|
tvb, offset, 2, message_seq);
|
2009-10-16 21:17:57 +00:00
|
|
|
offset += 2;
|
|
|
|
if (ssl_hand_tree)
|
|
|
|
proto_tree_add_uint(ssl_hand_tree, hf_dtls_handshake_fragment_offset,
|
2006-06-27 13:36:10 +00:00
|
|
|
tvb, offset, 3, fragment_offset);
|
2009-10-16 21:17:57 +00:00
|
|
|
offset += 3;
|
|
|
|
if (ssl_hand_tree)
|
|
|
|
proto_tree_add_uint(ssl_hand_tree, hf_dtls_handshake_fragment_length,
|
2006-06-27 13:36:10 +00:00
|
|
|
tvb, offset, 3, fragment_length);
|
2009-10-16 21:17:57 +00:00
|
|
|
offset += 3;
|
|
|
|
|
|
|
|
if (fragmented && !new_tvb)
|
|
|
|
{
|
|
|
|
/* Skip fragmented messages not reassembled yet */
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (new_tvb)
|
|
|
|
{
|
|
|
|
sub_tvb = new_tvb;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sub_tvb = tvb_new_subset(tvb, offset, fragment_length,
|
|
|
|
fragment_length);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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_dtls_hnd_cli_hello(sub_tvb, ssl_hand_tree, 0, length, ssl);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SSL_HND_HELLO_VERIFY_REQUEST:
|
|
|
|
dissect_dtls_hnd_hello_verify_request(sub_tvb, ssl_hand_tree, 0, ssl);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SSL_HND_SERVER_HELLO:
|
|
|
|
dissect_dtls_hnd_srv_hello(sub_tvb, ssl_hand_tree, 0, length, ssl);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SSL_HND_CERTIFICATE:
|
|
|
|
dissect_dtls_hnd_cert(sub_tvb, ssl_hand_tree, 0, pinfo);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SSL_HND_SERVER_KEY_EXCHG:
|
|
|
|
/* unimplemented */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SSL_HND_CERT_REQUEST:
|
|
|
|
dissect_dtls_hnd_cert_req(sub_tvb, ssl_hand_tree, 0);
|
|
|
|
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;
|
2006-08-02 08:15:51 +00:00
|
|
|
skip = 0;
|
|
|
|
|
2009-10-16 21:17:57 +00:00
|
|
|
if (!ssl)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* check for required session data */
|
2010-02-19 07:43:26 +00:00
|
|
|
ssl_debug_printf("dissect_dtls_handshake found SSL_HND_CLIENT_KEY_EXCHG, state %X\n",
|
2009-10-16 21:17:57 +00:00
|
|
|
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)) {
|
2010-02-19 07:43:26 +00:00
|
|
|
ssl_debug_printf("dissect_dtls_handshake not enough data to generate key (required state %X)\n",
|
2009-10-16 21:17:57 +00:00
|
|
|
(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);
|
|
|
|
|
|
|
|
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_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 successfully generated\n");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SSL_HND_FINISHED:
|
|
|
|
dissect_dtls_hnd_finished(sub_tvb, ssl_hand_tree,
|
|
|
|
0, conv_version);
|
|
|
|
break;
|
|
|
|
}
|
2006-06-27 13:36:10 +00:00
|
|
|
|
|
|
|
}
|
2006-08-02 08:15:51 +00:00
|
|
|
else{
|
2009-10-16 21:17:57 +00:00
|
|
|
offset += 12; /* skip the handshake header when handshake is not processed*/
|
2006-08-02 08:15:51 +00:00
|
|
|
}
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
static gint
|
|
|
|
dissect_dtls_hnd_hello_common(tvbuff_t *tvb, proto_tree *tree,
|
2006-06-27 13:36:10 +00:00
|
|
|
guint32 offset, SslDecryptSession* ssl, gint from_server)
|
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
/* show the client's random challenge */
|
|
|
|
nstime_t gmt_unix_time;
|
|
|
|
guint8 session_id_length;
|
|
|
|
session_id_length = 0;
|
2007-03-24 13:21:08 +00:00
|
|
|
if (ssl)
|
2006-08-02 08:15:51 +00:00
|
|
|
{
|
|
|
|
/* get proper peer information*/
|
|
|
|
StringInfo* rnd;
|
2007-03-24 13:21:08 +00:00
|
|
|
if (from_server)
|
2009-10-16 21:17:57 +00:00
|
|
|
rnd = &ssl->server_random;
|
2007-03-24 13:21:08 +00:00
|
|
|
else
|
2009-10-16 21:17:57 +00:00
|
|
|
rnd = &ssl->client_random;
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* get provided random for keyring generation*/
|
|
|
|
tvb_memcpy(tvb, rnd->data, offset, 32);
|
|
|
|
rnd->data_len = 32;
|
|
|
|
if (from_server)
|
2009-10-16 21:17:57 +00:00
|
|
|
ssl->state |= SSL_SERVER_RANDOM;
|
2006-08-02 08:15:51 +00:00
|
|
|
else
|
2009-10-16 21:17:57 +00:00
|
|
|
ssl->state |= SSL_CLIENT_RANDOM;
|
2007-03-24 13:21:08 +00:00
|
|
|
ssl_debug_printf("dissect_dtls_hnd_hello_common found random state %X\n",
|
2009-10-16 21:17:57 +00:00
|
|
|
ssl->state);
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
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) &&
|
2009-10-16 21:17:57 +00:00
|
|
|
(tvb_memeql(tvb, offset+33, ssl->session_id.data, session_id_length) == 0))
|
2007-03-24 13:21:08 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
/* clinet/server id match: try to restore a previous cached session*/
|
|
|
|
ssl_restore_session(ssl, dtls_session_hash);
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
2006-08-02 08:15:51 +00:00
|
|
|
else {
|
2009-10-16 21:17:57 +00:00
|
|
|
tvb_memcpy(tvb,ssl->session_id.data, offset+33, session_id_length);
|
|
|
|
ssl->session_id.data_len = session_id_length;
|
2007-03-24 13:21:08 +00:00
|
|
|
}
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
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,
|
2009-10-16 21:17:57 +00:00
|
|
|
tvb, offset, 4, &gmt_unix_time);
|
2006-08-02 08:15:51 +00:00
|
|
|
offset += 4;
|
|
|
|
|
|
|
|
/* show the random bytes */
|
|
|
|
proto_tree_add_item(tree, hf_dtls_handshake_random_bytes,
|
2009-10-16 21:17:57 +00:00
|
|
|
tvb, offset, 28, 0);
|
2006-08-02 08:15:51 +00:00
|
|
|
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,
|
2009-10-16 21:17:57 +00:00
|
|
|
tvb, offset++, 1, 0);
|
2006-08-02 08:15:51 +00:00
|
|
|
if (session_id_length > 0)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
proto_tree_add_bytes_format(tree, hf_dtls_handshake_session_id,
|
|
|
|
tvb, offset, session_id_length,
|
Modify proto_tree_add_bytes_format() and proto_tree_add_bytes_format_value()
so that if the start_ptr is NULL the bytes are extracted from the given TVB
using the given offset and length.
Replace a bunch of:
proto_tree_add_bytes_format*(tree, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), [...])
with:
proto_tree_add_bytes_format*(tree, hf, tvb, offset, length, NULL, [...])
svn path=/trunk/; revision=35896
2011-02-10 16:31:00 +00:00
|
|
|
NULL, "Session ID (%u byte%s)",
|
2009-10-16 21:17:57 +00:00
|
|
|
session_id_length,
|
|
|
|
plurality(session_id_length, "", "s"));
|
|
|
|
offset += session_id_length;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* XXXX */
|
|
|
|
return session_id_length+33;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
static gint
|
|
|
|
dissect_dtls_hnd_hello_ext(tvbuff_t *tvb,
|
2006-06-27 13:36:10 +00:00
|
|
|
proto_tree *tree, guint32 offset, guint32 left)
|
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
guint16 extension_length;
|
|
|
|
guint16 ext_type;
|
|
|
|
guint16 ext_len;
|
|
|
|
proto_item *pi;
|
|
|
|
proto_tree *ext_tree;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
if (left < 2)
|
2006-06-27 13:36:10 +00:00
|
|
|
return offset;
|
2006-08-02 08:15:51 +00:00
|
|
|
|
|
|
|
extension_length = tvb_get_ntohs(tvb, offset);
|
|
|
|
proto_tree_add_uint(tree, hf_dtls_handshake_extensions_len,
|
2009-10-16 21:17:57 +00:00
|
|
|
tvb, offset, 2, extension_length);
|
2006-08-02 08:15:51 +00:00
|
|
|
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,
|
2009-10-16 21:17:57 +00:00
|
|
|
"Extension: %s",
|
|
|
|
val_to_str(ext_type,
|
|
|
|
tls_hello_extension_types,
|
|
|
|
"Unknown %u"));
|
2006-08-02 08:15:51 +00:00
|
|
|
ext_tree = proto_item_add_subtree(pi, ett_dtls_extension);
|
|
|
|
if (!ext_tree)
|
2009-10-16 21:17:57 +00:00
|
|
|
ext_tree = tree;
|
2006-08-02 08:15:51 +00:00
|
|
|
|
|
|
|
proto_tree_add_uint(ext_tree, hf_dtls_handshake_extension_type,
|
2009-10-16 21:17:57 +00:00
|
|
|
tvb, offset, 2, ext_type);
|
2006-08-02 08:15:51 +00:00
|
|
|
offset += 2;
|
|
|
|
|
|
|
|
proto_tree_add_uint(ext_tree, hf_dtls_handshake_extension_len,
|
2009-10-16 21:17:57 +00:00
|
|
|
tvb, offset, 2, ext_len);
|
2006-08-02 08:15:51 +00:00
|
|
|
offset += 2;
|
|
|
|
|
|
|
|
proto_tree_add_bytes_format(ext_tree, hf_dtls_handshake_extension_data,
|
Modify proto_tree_add_bytes_format() and proto_tree_add_bytes_format_value()
so that if the start_ptr is NULL the bytes are extracted from the given TVB
using the given offset and length.
Replace a bunch of:
proto_tree_add_bytes_format*(tree, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), [...])
with:
proto_tree_add_bytes_format*(tree, hf, tvb, offset, length, NULL, [...])
svn path=/trunk/; revision=35896
2011-02-10 16:31:00 +00:00
|
|
|
tvb, offset, ext_len, NULL,
|
|
|
|
"Data (%u byte%s)", ext_len,
|
|
|
|
plurality(ext_len, "", "s"));
|
2006-08-02 08:15:51 +00:00
|
|
|
offset += ext_len;
|
|
|
|
left -= 2 + 2 + ext_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2006-08-02 08:15:51 +00:00
|
|
|
dissect_dtls_hnd_cli_hello(tvbuff_t *tvb,
|
2009-10-16 21:17:57 +00:00
|
|
|
proto_tree *tree, guint32 offset, guint32 length,
|
|
|
|
SslDecryptSession*ssl)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
/* 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)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
/* show the client version */
|
|
|
|
if (tree)
|
2009-10-16 21:17:57 +00:00
|
|
|
proto_tree_add_item(tree, hf_dtls_handshake_client_version, tvb,
|
2006-06-27 13:36:10 +00:00
|
|
|
offset, 2, FALSE);
|
2006-08-02 08:15:51 +00:00
|
|
|
offset += 2;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* show the fields in common with server hello */
|
|
|
|
offset += dissect_dtls_hnd_hello_common(tvb, tree, offset, ssl, 0);
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* look for a cookie */
|
|
|
|
cookie_length = tvb_get_guint8(tvb, offset);
|
|
|
|
if (!tree)
|
2009-10-16 21:17:57 +00:00
|
|
|
return;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
proto_tree_add_uint(tree, hf_dtls_handshake_cookie_len,
|
2009-10-16 21:17:57 +00:00
|
|
|
tvb, offset, 1, cookie_length);
|
2006-08-02 08:15:51 +00:00
|
|
|
offset ++; /* skip opaque length */
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
if (cookie_length > 0)
|
2009-10-16 21:17:57 +00:00
|
|
|
{
|
|
|
|
proto_tree_add_bytes_format(tree, hf_dtls_handshake_cookie,
|
|
|
|
tvb, offset, cookie_length,
|
Modify proto_tree_add_bytes_format() and proto_tree_add_bytes_format_value()
so that if the start_ptr is NULL the bytes are extracted from the given TVB
using the given offset and length.
Replace a bunch of:
proto_tree_add_bytes_format*(tree, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), [...])
with:
proto_tree_add_bytes_format*(tree, hf, tvb, offset, length, NULL, [...])
svn path=/trunk/; revision=35896
2011-02-10 16:31:00 +00:00
|
|
|
NULL, "Cookie (%u byte%s)",
|
2009-10-16 21:17:57 +00:00
|
|
|
cookie_length,
|
|
|
|
plurality(cookie_length, "", "s"));
|
|
|
|
offset += cookie_length;
|
|
|
|
}
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* tell the user how many cipher suites there are */
|
|
|
|
cipher_suite_length = tvb_get_ntohs(tvb, offset);
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
proto_tree_add_uint(tree, hf_dtls_handshake_cipher_suites_len,
|
2009-10-16 21:17:57 +00:00
|
|
|
tvb, offset, 2, cipher_suite_length);
|
2006-08-02 08:15:51 +00:00
|
|
|
offset += 2; /* skip opaque length */
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
if (cipher_suite_length > 0)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
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)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
cs_tree = tree; /* failsafe */
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
2009-10-16 21:17:57 +00:00
|
|
|
while (cipher_suite_length > 0)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
proto_tree_add_item(cs_tree, hf_dtls_handshake_cipher_suite,
|
|
|
|
tvb, offset, 2, FALSE);
|
|
|
|
offset += 2;
|
|
|
|
cipher_suite_length -= 2;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* 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,
|
2009-10-16 21:17:57 +00:00
|
|
|
tvb, offset, 1, compression_methods_length);
|
2006-08-02 08:15:51 +00:00
|
|
|
offset++;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
if (compression_methods_length > 0)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
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)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
cs_tree = tree; /* failsafe */
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
2009-10-16 21:17:57 +00:00
|
|
|
while (compression_methods_length > 0)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
compression_method = tvb_get_guint8(tvb, offset);
|
|
|
|
if (compression_method < 64)
|
|
|
|
proto_tree_add_uint(cs_tree, hf_dtls_handshake_comp_method,
|
2006-06-27 13:36:10 +00:00
|
|
|
tvb, offset, 1, compression_method);
|
2009-10-16 21:17:57 +00:00
|
|
|
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--;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
if (length > offset - start_offset)
|
2009-10-16 21:17:57 +00:00
|
|
|
{
|
|
|
|
offset = dissect_dtls_hnd_hello_ext(tvb, tree, offset,
|
|
|
|
length -
|
|
|
|
(offset - start_offset));
|
|
|
|
}
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-27 18:26:54 +00:00
|
|
|
static void
|
|
|
|
dissect_dtls_hnd_hello_verify_request(tvbuff_t *tvb, proto_tree *tree,
|
|
|
|
guint32 offset, SslDecryptSession* ssl)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2007-03-24 13:21:08 +00:00
|
|
|
/*
|
2006-06-27 13:36:10 +00:00
|
|
|
* struct {
|
|
|
|
* ProtocolVersion server_version;
|
|
|
|
* opaque cookie<0..32>;
|
|
|
|
* } HelloVerifyRequest;
|
|
|
|
*/
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
guint8 cookie_length;
|
2007-03-24 13:21:08 +00:00
|
|
|
cookie_length = 0;
|
2006-08-02 08:15:51 +00:00
|
|
|
|
2006-06-27 13:36:10 +00:00
|
|
|
if (tree || ssl)
|
|
|
|
{
|
|
|
|
/* show the client version */
|
|
|
|
if (tree)
|
2009-10-16 21:17:57 +00:00
|
|
|
proto_tree_add_item(tree, hf_dtls_handshake_server_version, tvb,
|
2006-06-27 13:36:10 +00:00
|
|
|
offset, 2, FALSE);
|
|
|
|
offset += 2;
|
|
|
|
|
|
|
|
|
|
|
|
/* look for a cookie */
|
|
|
|
cookie_length = tvb_get_guint8(tvb, offset);
|
|
|
|
if (!tree)
|
2009-10-16 21:17:57 +00:00
|
|
|
return;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
|
|
|
proto_tree_add_uint(tree, hf_dtls_handshake_cookie_len,
|
2009-10-16 21:17:57 +00:00
|
|
|
tvb, offset, 1, cookie_length);
|
2006-06-27 13:36:10 +00:00
|
|
|
offset ++; /* skip opaque length */
|
|
|
|
|
|
|
|
if (cookie_length > 0)
|
2009-10-16 21:17:57 +00:00
|
|
|
{
|
|
|
|
proto_tree_add_bytes_format(tree, hf_dtls_handshake_cookie,
|
|
|
|
tvb, offset, cookie_length,
|
Modify proto_tree_add_bytes_format() and proto_tree_add_bytes_format_value()
so that if the start_ptr is NULL the bytes are extracted from the given TVB
using the given offset and length.
Replace a bunch of:
proto_tree_add_bytes_format*(tree, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), [...])
with:
proto_tree_add_bytes_format*(tree, hf, tvb, offset, length, NULL, [...])
svn path=/trunk/; revision=35896
2011-02-10 16:31:00 +00:00
|
|
|
NULL, "Cookie (%u byte%s)",
|
2009-10-16 21:17:57 +00:00
|
|
|
cookie_length,
|
|
|
|
plurality(cookie_length, "", "s"));
|
|
|
|
offset += cookie_length;
|
|
|
|
}
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2006-08-02 08:15:51 +00:00
|
|
|
dissect_dtls_hnd_srv_hello(tvbuff_t *tvb,
|
2006-06-27 13:36:10 +00:00
|
|
|
proto_tree *tree, guint32 offset, guint32 length, SslDecryptSession* ssl)
|
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
/* 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;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
if (tree || ssl)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
/* show the server version */
|
|
|
|
if (tree)
|
2009-10-16 21:17:57 +00:00
|
|
|
proto_tree_add_item(tree, hf_dtls_handshake_server_version, tvb,
|
2006-06-27 13:36:10 +00:00
|
|
|
offset, 2, FALSE);
|
2006-08-02 08:15:51 +00:00
|
|
|
offset += 2;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* 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) {
|
2009-10-16 21:17:57 +00:00
|
|
|
/* 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)) {
|
2010-02-19 07:43:26 +00:00
|
|
|
ssl_debug_printf("dissect_dtls_hnd_srv_hello not enough data to generate key (required state %X)\n",
|
2009-10-16 21:17:57 +00:00
|
|
|
(SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION|SSL_MASTER_SECRET));
|
|
|
|
goto no_cipher;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2006-08-02 08:15:51 +00:00
|
|
|
}
|
|
|
|
no_cipher:
|
|
|
|
if (!tree)
|
2009-10-16 21:17:57 +00:00
|
|
|
return;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* now the server-selected cipher suite */
|
|
|
|
proto_tree_add_item(tree, hf_dtls_handshake_cipher_suite,
|
2009-10-16 21:17:57 +00:00
|
|
|
tvb, offset, 2, FALSE);
|
2006-08-02 08:15:51 +00:00
|
|
|
offset += 2;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* and the server-selected compression method */
|
|
|
|
proto_tree_add_item(tree, hf_dtls_handshake_comp_method,
|
2009-10-16 21:17:57 +00:00
|
|
|
tvb, offset, 1, FALSE);
|
2006-08-02 08:15:51 +00:00
|
|
|
offset++;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
if (length > offset - start_offset)
|
2009-10-16 21:17:57 +00:00
|
|
|
{
|
|
|
|
offset = dissect_dtls_hnd_hello_ext(tvb, tree, offset,
|
|
|
|
length -
|
|
|
|
(offset - start_offset));
|
|
|
|
}
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2006-08-02 08:15:51 +00:00
|
|
|
dissect_dtls_hnd_cert(tvbuff_t *tvb,
|
2006-06-27 13:36:10 +00:00
|
|
|
proto_tree *tree, guint32 offset, packet_info *pinfo)
|
|
|
|
{
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* 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;
|
2007-05-13 20:58:29 +00:00
|
|
|
asn1_ctx_t asn1_ctx;
|
|
|
|
asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
if (tree)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
certificate_list_length = tvb_get_ntoh24(tvb, offset);
|
|
|
|
proto_tree_add_uint(tree, hf_dtls_handshake_certificates_len,
|
2009-10-16 21:17:57 +00:00
|
|
|
tvb, offset, 3, certificate_list_length);
|
2006-08-02 08:15:51 +00:00
|
|
|
offset += 3; /* 24-bit length value */
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
if (certificate_list_length > 0)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
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)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
subtree = tree; /* failsafe */
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
2009-10-16 21:17:57 +00:00
|
|
|
/* iterate through each certificate */
|
|
|
|
while (certificate_list_length > 0)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
/* get the length of the current certificate */
|
|
|
|
guint32 cert_length = tvb_get_ntoh24(tvb, offset);
|
|
|
|
certificate_list_length -= 3 + cert_length;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2009-10-16 21:17:57 +00:00
|
|
|
proto_tree_add_item(subtree, hf_dtls_handshake_certificate_len,
|
|
|
|
tvb, offset, 3, FALSE);
|
|
|
|
offset += 3;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2009-10-16 21:17:57 +00:00
|
|
|
dissect_x509af_Certificate(FALSE, tvb, offset, &asn1_ctx, subtree, hf_dtls_handshake_certificate);
|
|
|
|
offset += cert_length;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2006-08-02 08:15:51 +00:00
|
|
|
dissect_dtls_hnd_cert_req(tvbuff_t *tvb,
|
2006-06-27 13:36:10 +00:00
|
|
|
proto_tree *tree, guint32 offset)
|
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
/*
|
|
|
|
* 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;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
if (tree)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
cert_types_count = tvb_get_guint8(tvb, offset);
|
|
|
|
proto_tree_add_uint(tree, hf_dtls_handshake_cert_types_count,
|
2009-10-16 21:17:57 +00:00
|
|
|
tvb, offset, 1, cert_types_count);
|
2006-08-02 08:15:51 +00:00
|
|
|
offset++;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
if (cert_types_count > 0)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
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)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
subtree = tree;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
2009-10-16 21:17:57 +00:00
|
|
|
while (cert_types_count > 0)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
proto_tree_add_item(subtree, hf_dtls_handshake_cert_type,
|
|
|
|
tvb, offset, 1, FALSE);
|
|
|
|
offset++;
|
|
|
|
cert_types_count--;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
dnames_length = tvb_get_ntohs(tvb, offset);
|
|
|
|
proto_tree_add_uint(tree, hf_dtls_handshake_dnames_len,
|
2009-10-16 21:17:57 +00:00
|
|
|
tvb, offset, 2, dnames_length);
|
2006-08-02 08:15:51 +00:00
|
|
|
offset += 2;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
if (dnames_length > 0)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
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)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
subtree = tree;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
2009-10-16 21:17:57 +00:00
|
|
|
while (dnames_length > 0)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2009-10-16 21:17:57 +00:00
|
|
|
/* 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;
|
|
|
|
|
|
|
|
proto_tree_add_bytes_format(subtree,
|
|
|
|
hf_dtls_handshake_dname,
|
Modify proto_tree_add_bytes_format() and proto_tree_add_bytes_format_value()
so that if the start_ptr is NULL the bytes are extracted from the given TVB
using the given offset and length.
Replace a bunch of:
proto_tree_add_bytes_format*(tree, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), [...])
with:
proto_tree_add_bytes_format*(tree, hf, tvb, offset, length, NULL, [...])
svn path=/trunk/; revision=35896
2011-02-10 16:31:00 +00:00
|
|
|
tvb, offset, name_length, NULL,
|
2009-10-16 21:17:57 +00:00
|
|
|
"Distinguished Name (%u byte%s)",
|
|
|
|
name_length,
|
|
|
|
plurality(name_length, "", "s"));
|
|
|
|
offset += name_length;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2010-10-27 18:26:54 +00:00
|
|
|
dissect_dtls_hnd_finished(tvbuff_t *tvb, proto_tree *tree, guint32 offset,
|
2006-06-27 13:36:10 +00:00
|
|
|
guint* conv_version)
|
|
|
|
{
|
2007-03-24 13:21:08 +00:00
|
|
|
/*
|
2006-08-02 08:15:51 +00:00
|
|
|
* struct {
|
|
|
|
* opaque verify_data[12];
|
|
|
|
* } Finished;
|
|
|
|
*/
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* this all needs a tree, so bail if we don't have one */
|
|
|
|
if (!tree)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
return;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
switch(*conv_version) {
|
|
|
|
case SSL_VER_DTLS:
|
|
|
|
proto_tree_add_item(tree, hf_dtls_handshake_finished,
|
2009-10-16 21:17:57 +00:00
|
|
|
tvb, offset, 12, FALSE);
|
2006-08-02 08:15:51 +00:00
|
|
|
break;
|
|
|
|
}
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*********************************************************************
|
|
|
|
*
|
|
|
|
* Support Functions
|
|
|
|
*
|
|
|
|
*********************************************************************/
|
|
|
|
#if 0
|
|
|
|
static void
|
|
|
|
ssl_set_conv_version(packet_info *pinfo, guint version)
|
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
conversation_t *conversation;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
if (pinfo->fd->flags.visited)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
/* We've already processed this frame; no need to do any more
|
|
|
|
* work on it.
|
|
|
|
*/
|
|
|
|
return;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
2010-05-13 18:28:34 +00:00
|
|
|
conversation = find_or_create_conversation(pinfo);
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
if (conversation_get_proto_data(conversation, proto_dtls) != NULL)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
/* get rid of the current data */
|
|
|
|
conversation_delete_proto_data(conversation, proto_dtls);
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
2006-08-02 08:15:51 +00:00
|
|
|
conversation_add_proto_data(conversation, proto_dtls, GINT_TO_POINTER(version));
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
static gint
|
|
|
|
dtls_is_valid_handshake_type(guint8 type)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
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:
|
2006-06-27 13:36:10 +00:00
|
|
|
return 1;
|
2006-08-02 08:15:51 +00:00
|
|
|
}
|
|
|
|
return 0;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
static gint
|
2010-10-27 18:26:54 +00:00
|
|
|
dtls_is_authoritative_version_message(guint8 content_type, guint8 next_byte)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
if (content_type == SSL_ID_HANDSHAKE
|
|
|
|
&& dtls_is_valid_handshake_type(next_byte))
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
return (next_byte != SSL_HND_CLIENT_HELLO);
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
2006-08-02 08:15:51 +00:00
|
|
|
else if (ssl_is_valid_content_type(content_type)
|
2009-10-16 21:17:57 +00:00
|
|
|
&& content_type != SSL_ID_HANDSHAKE)
|
2006-08-02 08:15:51 +00:00
|
|
|
{
|
|
|
|
return 1;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
2006-08-02 08:15:51 +00:00
|
|
|
return 0;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* this applies a heuristic to determine whether
|
|
|
|
* or not the data beginning at offset looks like a
|
2006-08-02 08:15:51 +00:00
|
|
|
* valid dtls record.
|
2006-06-27 13:36:10 +00:00
|
|
|
*/
|
2006-08-02 08:15:51 +00:00
|
|
|
static gint
|
|
|
|
looks_like_dtls(tvbuff_t *tvb, guint32 offset)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
/* have to have a valid content type followed by a valid
|
|
|
|
* protocol version
|
|
|
|
*/
|
|
|
|
guint8 byte;
|
|
|
|
guint16 version;
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* see if the first byte is a valid content type */
|
|
|
|
byte = tvb_get_guint8(tvb, offset);
|
|
|
|
if (!ssl_is_valid_content_type(byte))
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
return 0;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* now check to see if the version byte appears valid */
|
|
|
|
version = tvb_get_ntohs(tvb, offset + 1);
|
2007-11-05 23:05:20 +00:00
|
|
|
if (version != DTLSV1DOT0_VERSION && version != DTLSV1DOT0_VERSION_NOT)
|
2006-06-27 13:36:10 +00:00
|
|
|
{
|
2006-08-02 08:15:51 +00:00
|
|
|
return 0;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
return 1;
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
2011-04-26 21:59:11 +00:00
|
|
|
/* UAT */
|
|
|
|
|
2011-04-26 22:56:22 +00:00
|
|
|
#ifdef HAVE_LIBGNUTLS
|
2011-04-26 21:59:11 +00:00
|
|
|
static void
|
|
|
|
dtlsdecrypt_free_cb(void* r)
|
|
|
|
{
|
|
|
|
ssldecrypt_assoc_t* h = r;
|
|
|
|
|
|
|
|
g_free(h->ipaddr);
|
|
|
|
g_free(h->port);
|
|
|
|
g_free(h->protocol);
|
|
|
|
g_free(h->keyfile);
|
|
|
|
g_free(h->password);
|
|
|
|
}
|
2011-04-26 22:56:22 +00:00
|
|
|
#endif
|
2011-04-26 21:59:11 +00:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
static void
|
|
|
|
dtlsdecrypt_update_cb(void* r _U_, const char** err _U_)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-04-26 22:56:22 +00:00
|
|
|
#ifdef HAVE_LIBGNUTLS
|
2011-04-26 21:59:11 +00:00
|
|
|
static void *
|
|
|
|
dtlsdecrypt_copy_cb(void* dest, const void* orig, size_t len _U_)
|
|
|
|
{
|
|
|
|
const ssldecrypt_assoc_t* o = orig;
|
|
|
|
ssldecrypt_assoc_t* d = dest;
|
|
|
|
|
|
|
|
d->ipaddr = g_strdup(o->ipaddr);
|
|
|
|
d->port = g_strdup(o->port);
|
|
|
|
d->protocol = g_strdup(o->protocol);
|
|
|
|
d->keyfile = g_strdup(o->keyfile);
|
|
|
|
d->password = g_strdup(o->password);
|
|
|
|
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
UAT_CSTRING_CB_DEF(sslkeylist_uats,ipaddr,ssldecrypt_assoc_t)
|
|
|
|
UAT_CSTRING_CB_DEF(sslkeylist_uats,port,ssldecrypt_assoc_t)
|
|
|
|
UAT_CSTRING_CB_DEF(sslkeylist_uats,protocol,ssldecrypt_assoc_t)
|
|
|
|
UAT_CSTRING_CB_DEF(sslkeylist_uats,keyfile,ssldecrypt_assoc_t)
|
|
|
|
UAT_CSTRING_CB_DEF(sslkeylist_uats,password,ssldecrypt_assoc_t)
|
2011-04-26 22:56:22 +00:00
|
|
|
#endif
|
2011-04-26 21:59:11 +00:00
|
|
|
|
2006-06-27 13:36:10 +00:00
|
|
|
/*********************************************************************
|
|
|
|
*
|
2007-01-02 14:11:35 +00:00
|
|
|
* Standard Wireshark Protocol Registration and housekeeping
|
2006-06-27 13:36:10 +00:00
|
|
|
*
|
|
|
|
*********************************************************************/
|
|
|
|
void
|
|
|
|
proto_register_dtls(void)
|
|
|
|
{
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* Setup list of header fields See Section 1.6.1 for details*/
|
|
|
|
static hf_register_info hf[] = {
|
|
|
|
{ &hf_dtls_record,
|
|
|
|
{ "Record Layer", "dtls.record",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
2010-09-23 21:46:31 +00:00
|
|
|
NULL, HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_record_content_type,
|
|
|
|
{ "Content Type", "dtls.record.content_type",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT8, BASE_DEC, VALS(ssl_31_content_type), 0x0,
|
2010-09-23 21:46:31 +00:00
|
|
|
NULL, HFILL}
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_record_version,
|
|
|
|
{ "Version", "dtls.record.version",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT16, BASE_HEX, VALS(ssl_versions), 0x0,
|
|
|
|
"Record layer version.", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_record_epoch,
|
|
|
|
{ "Epoch", "dtls.record.epoch",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
|
|
NULL, HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_record_sequence_number,
|
|
|
|
{ "Sequence Number", "dtls.record.sequence_number",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_DOUBLE, BASE_NONE, NULL, 0x0,
|
|
|
|
NULL, HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_record_length,
|
|
|
|
{ "Length", "dtls.record.length",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
|
|
"Length of DTLS record data", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_record_appdata,
|
|
|
|
{ "Encrypted Application Data", "dtls.app_data",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
|
|
"Payload is encrypted application data", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_change_cipher_spec,
|
|
|
|
{ "Change Cipher Spec Message", "dtls.change_cipher_spec",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
|
|
"Signals a change in cipher specifications", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ & hf_dtls_alert_message,
|
|
|
|
{ "Alert Message", "dtls.alert_message",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
2010-09-24 02:51:40 +00:00
|
|
|
NULL, HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ & hf_dtls_alert_message_level,
|
|
|
|
{ "Level", "dtls.alert_message.level",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT8, BASE_DEC, VALS(ssl_31_alert_level), 0x0,
|
|
|
|
"Alert message level", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_alert_message_description,
|
|
|
|
{ "Description", "dtls.alert_message.desc",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT8, BASE_DEC, VALS(ssl_31_alert_description), 0x0,
|
|
|
|
"Alert message description", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_protocol,
|
|
|
|
{ "Handshake Protocol", "dtls.handshake",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
|
|
"Handshake protocol message", HFILL}
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_type,
|
|
|
|
{ "Handshake Type", "dtls.handshake.type",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT8, BASE_DEC, VALS(ssl_31_handshake_type), 0x0,
|
|
|
|
"Type of handshake message", HFILL}
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_length,
|
|
|
|
{ "Length", "dtls.handshake.length",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT24, BASE_DEC, NULL, 0x0,
|
|
|
|
"Length of handshake message", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_message_seq,
|
|
|
|
{ "Message Sequence", "dtls.handshake.message_seq",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
|
|
"Message sequence of handshake message", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_fragment_offset,
|
|
|
|
{ "Fragment Offset", "dtls.handshake.fragment_offset",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT24, BASE_DEC, NULL, 0x0,
|
|
|
|
"Fragment offset of handshake message", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_fragment_length,
|
|
|
|
{ "Fragment Length", "dtls.handshake.fragment_length",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT24, BASE_DEC, NULL, 0x0,
|
|
|
|
"Fragment length of handshake message", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_client_version,
|
|
|
|
{ "Version", "dtls.handshake.version",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT16, BASE_HEX, VALS(ssl_versions), 0x0,
|
|
|
|
"Maximum version supported by client", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_server_version,
|
|
|
|
{ "Version", "dtls.handshake.version",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT16, BASE_HEX, VALS(ssl_versions), 0x0,
|
|
|
|
"Version selected by server", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_random_time,
|
|
|
|
{ "Random.gmt_unix_time", "dtls.handshake.random_time",
|
2009-12-19 03:17:44 +00:00
|
|
|
FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0,
|
2009-10-16 21:17:57 +00:00
|
|
|
"Unix time field of random structure", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_random_bytes,
|
|
|
|
{ "Random.bytes", "dtls.handshake.random",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
|
|
"Random challenge used to authenticate server", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_cipher_suites_len,
|
|
|
|
{ "Cipher Suites Length", "dtls.handshake.cipher_suites_length",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
|
|
"Length of cipher suites field", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_cipher_suites,
|
|
|
|
{ "Cipher Suites", "dtls.handshake.ciphersuites",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
|
|
"List of cipher suites supported by client", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_cipher_suite,
|
|
|
|
{ "Cipher Suite", "dtls.handshake.ciphersuite",
|
2010-10-29 22:18:44 +00:00
|
|
|
FT_UINT16, BASE_HEX|BASE_EXT_STRING, &ssl_31_ciphersuite_ext, 0x0,
|
2010-09-23 21:46:31 +00:00
|
|
|
NULL, HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_cookie_len,
|
|
|
|
{ "Cookie Length", "dtls.handshake.cookie_length",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
|
|
"Length of the cookie field", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_cookie,
|
|
|
|
{ "Cookie", "dtls.handshake.cookie",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
|
|
NULL, HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_session_id,
|
|
|
|
{ "Session ID", "dtls.handshake.session_id",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
|
|
"Identifies the DTLS session, allowing later resumption", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_comp_methods_len,
|
|
|
|
{ "Compression Methods Length", "dtls.handshake.comp_methods_length",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
|
|
"Length of compression methods field", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_comp_methods,
|
|
|
|
{ "Compression Methods", "dtls.handshake.comp_methods",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
|
|
"List of compression methods supported by client", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_comp_method,
|
|
|
|
{ "Compression Method", "dtls.handshake.comp_method",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT8, BASE_DEC, VALS(ssl_31_compression_method), 0x0,
|
|
|
|
NULL, HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_extensions_len,
|
|
|
|
{ "Extensions Length", "dtls.handshake.extensions_length",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
|
|
"Length of hello extensions", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_extension_type,
|
|
|
|
{ "Type", "dtls.handshake.extension.type",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT16, BASE_HEX, VALS(tls_hello_extension_types), 0x0,
|
|
|
|
"Hello extension type", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_extension_len,
|
|
|
|
{ "Length", "dtls.handshake.extension.len",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
|
|
"Length of a hello extension", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_extension_data,
|
|
|
|
{ "Data", "dtls.handshake.extension.data",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
|
|
"Hello Extension data", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_certificates_len,
|
|
|
|
{ "Certificates Length", "dtls.handshake.certificates_length",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT24, BASE_DEC, NULL, 0x0,
|
|
|
|
"Length of certificates field", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_certificates,
|
|
|
|
{ "Certificates", "dtls.handshake.certificates",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
|
|
"List of certificates", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_certificate,
|
|
|
|
{ "Certificate", "dtls.handshake.certificate",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
|
|
NULL, HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_certificate_len,
|
|
|
|
{ "Certificate Length", "dtls.handshake.certificate_length",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT24, BASE_DEC, NULL, 0x0,
|
|
|
|
"Length of certificate", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_cert_types_count,
|
|
|
|
{ "Certificate types count", "dtls.handshake.cert_types_count",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
|
|
"Count of certificate types", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_cert_types,
|
|
|
|
{ "Certificate types", "dtls.handshake.cert_types",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
|
|
"List of certificate types", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_cert_type,
|
|
|
|
{ "Certificate type", "dtls.handshake.cert_type",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT8, BASE_DEC, VALS(ssl_31_client_certificate_type), 0x0,
|
|
|
|
NULL, HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_finished,
|
|
|
|
{ "Verify Data", "dtls.handshake.verify_data",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
|
|
"Opaque verification data", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_md5_hash,
|
|
|
|
{ "MD5 Hash", "dtls.handshake.md5_hash",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
|
|
"Hash of messages, master_secret, etc.", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_sha_hash,
|
|
|
|
{ "SHA-1 Hash", "dtls.handshake.sha_hash",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
|
|
"Hash of messages, master_secret, etc.", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_session_id_len,
|
|
|
|
{ "Session ID Length", "dtls.handshake.session_id_length",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT8, BASE_DEC, NULL, 0x0,
|
|
|
|
"Length of session ID field", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_dnames_len,
|
|
|
|
{ "Distinguished Names Length", "dtls.handshake.dnames_len",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
|
|
"Length of list of CAs that server trusts", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_dnames,
|
|
|
|
{ "Distinguished Names", "dtls.handshake.dnames",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_NONE, BASE_NONE, NULL, 0x0,
|
|
|
|
"List of CAs that server trusts", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_dname_len,
|
|
|
|
{ "Distinguished Name Length", "dtls.handshake.dname_len",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
|
|
"Length of distinguished name", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_handshake_dname,
|
|
|
|
{ "Distinguished Name", "dtls.handshake.dname",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_BYTES, BASE_NONE, NULL, 0x0,
|
|
|
|
"Distinguished name of a CA that server trusts", HFILL }
|
2006-08-02 08:15:51 +00:00
|
|
|
},
|
2007-11-05 23:05:20 +00:00
|
|
|
{ &hf_dtls_fragments,
|
|
|
|
{ "Message fragments", "dtls.fragments",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL }
|
2007-11-05 23:05:20 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_fragment,
|
|
|
|
{ "Message fragment", "dtls.fragment",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }
|
2007-11-05 23:05:20 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_fragment_overlap,
|
|
|
|
{ "Message fragment overlap", "dtls.fragment.overlap",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }
|
2007-11-05 23:05:20 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_fragment_overlap_conflicts,
|
|
|
|
{ "Message fragment overlapping with conflicting data",
|
2009-10-16 21:17:57 +00:00
|
|
|
"dtls.fragment.overlap.conflicts",
|
From Kovarththanan Rajaratnam via bug 3548:
(1) Trailing/leading spaces are removed from 'name's/'blurb's
(2) Duplicate 'blurb's are replaced with NULL
(3) Empty ("") 'blurb's are replaced with NULL
(4) BASE_NONE, NULL, 0x0 are used for 'display', 'strings' and 'bitmask' fields
for FT_NONE, FT_BYTES, FT_IPv4, FT_IPv6, FT_ABSOLUTE_TIME, FT_RELATIVE_TIME,
FT_PROTOCOL, FT_STRING and FT_STRINGZ field types
(5) Only allow non-zero value for 'display' if 'bitmask' is non-zero
svn path=/trunk/; revision=28770
2009-06-18 21:30:42 +00:00
|
|
|
FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }
|
2007-11-05 23:05:20 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_fragment_multiple_tails,
|
|
|
|
{ "Message has multiple tail fragments",
|
2009-10-16 21:17:57 +00:00
|
|
|
"dtls.fragment.multiple_tails",
|
|
|
|
FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }
|
2007-11-05 23:05:20 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_fragment_too_long_fragment,
|
|
|
|
{ "Message fragment too long", "dtls.fragment.too_long_fragment",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }
|
2007-11-05 23:05:20 +00:00
|
|
|
},
|
|
|
|
{ &hf_dtls_fragment_error,
|
|
|
|
{ "Message defragmentation error", "dtls.fragment.error",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }
|
2007-11-05 23:05:20 +00:00
|
|
|
},
|
2011-01-30 21:01:07 +00:00
|
|
|
{ &hf_dtls_fragment_count,
|
|
|
|
{ "Message fragment count", "dtls.fragment.error",
|
|
|
|
FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
|
|
|
|
},
|
2007-11-05 23:05:20 +00:00
|
|
|
{ &hf_dtls_reassembled_in,
|
|
|
|
{ "Reassembled in", "dtls.reassembled.in",
|
2009-10-16 21:17:57 +00:00
|
|
|
FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL }
|
2007-11-05 23:05:20 +00:00
|
|
|
},
|
2010-02-02 16:01:52 +00:00
|
|
|
{ &hf_dtls_reassembled_length,
|
2010-02-06 18:20:21 +00:00
|
|
|
{ "Reassembled DTLS length", "dtls.reassembled.length",
|
2010-02-02 16:01:52 +00:00
|
|
|
FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }
|
|
|
|
},
|
2006-08-02 08:15:51 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* 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,
|
2007-11-05 23:05:20 +00:00
|
|
|
&ett_dtls_fragment,
|
|
|
|
&ett_dtls_fragments,
|
2006-08-02 08:15:51 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Register the protocol name and description */
|
|
|
|
proto_dtls = proto_register_protocol("Datagram Transport Layer Security",
|
2009-10-16 21:17:57 +00:00
|
|
|
"DTLS", "dtls");
|
2006-08-02 08:15:51 +00:00
|
|
|
|
|
|
|
/* 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));
|
|
|
|
|
2006-08-26 00:05:26 +00:00
|
|
|
#ifdef HAVE_LIBGNUTLS
|
2006-08-02 08:15:51 +00:00
|
|
|
{
|
|
|
|
module_t *dtls_module = prefs_register_protocol(proto_dtls, dtls_parse);
|
2011-04-26 21:59:11 +00:00
|
|
|
|
|
|
|
static uat_field_t dtlskeylist_uats_flds[] = {
|
|
|
|
UAT_FLD_CSTRING_OTHER(sslkeylist_uats, ipaddr, "IP address", ssldecrypt_uat_fld_ip_chk_cb, "IPv4 or IPv6 address"),
|
|
|
|
UAT_FLD_CSTRING_OTHER(sslkeylist_uats, port, "Port", ssldecrypt_uat_fld_port_chk_cb, "Port Number"),
|
|
|
|
UAT_FLD_CSTRING_OTHER(sslkeylist_uats, protocol, "Protocol", ssldecrypt_uat_fld_protocol_chk_cb, "Protocol"),
|
|
|
|
UAT_FLD_CSTRING_OTHER(sslkeylist_uats, keyfile, "Key File", ssldecrypt_uat_fld_fileopen_chk_cb, "Path to the keyfile."),
|
|
|
|
UAT_FLD_CSTRING_OTHER(sslkeylist_uats, password," Password (p12 file)", ssldecrypt_uat_fld_password_chk_cb, "Password"),
|
|
|
|
UAT_END_FIELDS
|
|
|
|
};
|
|
|
|
|
|
|
|
dtlsdecrypt_uat = uat_new("DTLS RSA Keylist",
|
|
|
|
sizeof(ssldecrypt_assoc_t),
|
|
|
|
"dtlsdecrypttablefile", /* filename */
|
|
|
|
TRUE, /* from_profile */
|
|
|
|
(void*) &dtlskeylist_uats, /* data_ptr */
|
|
|
|
&ndtlsdecrypt, /* numitems_ptr */
|
|
|
|
UAT_CAT_FFMT, /* category */
|
|
|
|
"ChK12ProtocolsSection", /* TODO, need revision - help */
|
|
|
|
dtlsdecrypt_copy_cb,
|
|
|
|
NULL, /* dtlsdecrypt_update_cb? */
|
|
|
|
dtlsdecrypt_free_cb,
|
|
|
|
NULL,
|
|
|
|
dtlskeylist_uats_flds);
|
|
|
|
|
|
|
|
prefs_register_uat_preference(dtls_module, "cfg",
|
|
|
|
"RSA keys list",
|
|
|
|
"A table of RSA keys for DTLS decryption",
|
|
|
|
dtlsdecrypt_uat);
|
|
|
|
|
|
|
|
prefs_register_string_preference(dtls_module, "debug_file", "DTLS debug file",
|
2009-10-16 21:17:57 +00:00
|
|
|
"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);
|
2011-04-26 21:59:11 +00:00
|
|
|
|
|
|
|
prefs_register_string_preference(dtls_module, "keys_list", "RSA keys list (deprecated)",
|
|
|
|
"Semicolon-separated list of private RSA keys used for DTLS decryption. "
|
|
|
|
"Used by versions of Wireshark prior to 1.6",
|
|
|
|
(const gchar **)&dtls_keys_list);
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
}
|
2006-08-26 00:05:26 +00:00
|
|
|
#endif
|
2006-06-27 13:36:10 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
register_dissector("dtls", dissect_dtls, proto_dtls);
|
2006-08-25 08:07:26 +00:00
|
|
|
dtls_handle = find_dissector("dtls");
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2006-08-25 08:07:26 +00:00
|
|
|
dtls_associations = g_tree_new(ssl_association_cmp);
|
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
register_init_routine(dtls_init);
|
|
|
|
ssl_lib_init();
|
|
|
|
dtls_tap = register_tap("dtls");
|
|
|
|
ssl_debug_printf("proto_register_dtls: registered tap %s:%d\n",
|
2009-10-16 21:17:57 +00:00
|
|
|
"dtls", dtls_tap);
|
From Michael Chen via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5863 :
1. Reload framing protocol no longer encapsulates the Reload message, instead
the latter is in its own tree following Reload framing, much like IP, UDP, etc.
2. Similarly, DTLS no longer encapsulates its data payload if the payload can
be dissected. The recognized payload is in its own tree following the DTLS,
much like IP, UDP, etc.
4. DTLS now has its own heuristic table for dissecting its payload, and
reload-framing is added to this DTLS heuristic table.
6. DTLS will try to dissect its payload if the agreed upon cipher is
RSA-NULL-MD5 (0x0001) or RSA-NULL-SHA (0x0002), even when DTLS is not
configured with the client/server private keys.
Still to do: make DTLS a heuristic dissector on top of UDP (item 3 in the bug).
svn path=/trunk/; revision=37110
2011-05-13 02:48:08 +00:00
|
|
|
|
|
|
|
register_heur_dissector_list("dtls", &heur_subdissector_list);
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|
|
|
|
|
2011-06-01 18:34:41 +00:00
|
|
|
static gboolean
|
|
|
|
dissect_dtls_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
|
|
{
|
|
|
|
/* Stronger confirmation of DTLS packet is provided by verifying the
|
|
|
|
* payload length against the remainder of the UDP packet size. */
|
|
|
|
guint length = tvb_length(tvb);
|
|
|
|
guint offset = 0;
|
|
|
|
|
|
|
|
if (tvb_reported_length(tvb) == length) {
|
|
|
|
while (offset + 13 <= length && looks_like_dtls(tvb, offset)) {
|
|
|
|
/* Advance offset to the end of the current DTLS record */
|
|
|
|
offset += tvb_get_ntohs(tvb, offset + 11) + 13;
|
|
|
|
if (offset == length) {
|
|
|
|
dissect_dtls(tvb, pinfo, tree);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pinfo->fragmented && offset >= 13) {
|
|
|
|
dissect_dtls(tvb, pinfo, tree);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We've got a truncated packet - do our best with what we've got. */
|
|
|
|
while (tvb_length_remaining(tvb, offset) >= 3) {
|
|
|
|
if (!looks_like_dtls(tvb, offset))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
offset += 3;
|
|
|
|
if (tvb_length_remaining(tvb, offset) >= 10 ) {
|
|
|
|
offset += tvb_get_ntohs(tvb, offset + 8) + 10;
|
|
|
|
} else {
|
|
|
|
/* Dissect what we've got, which might be as little as 3 bytes. */
|
|
|
|
dissect_dtls(tvb, pinfo, tree);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
if (offset == length) {
|
|
|
|
/* Can this ever happen? Well, just in case ... */
|
|
|
|
dissect_dtls(tvb, pinfo, tree);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* One last check to see if the current offset is at least less than the
|
|
|
|
* original number of bytes present before truncation or we're dealing with
|
|
|
|
* a packet fragment that's also been truncated. */
|
|
|
|
if ((length >= 3) && (offset <= tvb_reported_length(tvb) || pinfo->fragmented)) {
|
|
|
|
dissect_dtls(tvb, pinfo, tree);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2006-06-27 13:36:10 +00:00
|
|
|
/* If this dissector uses sub-dissector registration add a registration
|
|
|
|
* routine. This format is required because a script is used to find
|
|
|
|
* these routines and create the code that calls these routines.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
proto_reg_handoff_dtls(void)
|
|
|
|
{
|
2007-03-24 13:21:08 +00:00
|
|
|
|
2006-08-02 08:15:51 +00:00
|
|
|
/* add now dissector to default ports.*/
|
|
|
|
dtls_parse();
|
2011-06-01 18:34:41 +00:00
|
|
|
|
|
|
|
heur_dissector_add("udp", dissect_dtls_heur, proto_dtls);
|
2006-06-27 13:36:10 +00:00
|
|
|
}
|