aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-ssl.c
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2011-04-26 21:59:11 +0000
committerGerald Combs <gerald@wireshark.org>2011-04-26 21:59:11 +0000
commitc6fecb57b0641d83c00f8c07d7b75125ad9c81c3 (patch)
tree85d7982fbcded140cf5573aa8376dbd89a05ba70 /epan/dissectors/packet-ssl.c
parent6eae60aa2f50e5d18c784b74d2ae70182c2d0566 (diff)
From Ivan Sy via bug 3343:
- Support for DTLS and SSL RSA keys list using User Accessible Table - Support for IPv6 SSL as posted by bug#3343 comment#1 - 'any' and 'anyipv4' for IPv4 wildcard - 'anyipv6' for IPv6 wildcard - UAT fields validation. From me: - Update paramaters to match UAT API changes. - Change the UAT filename. - Fix buffer overflow for IPv6 addresses. - Allow the use of hostnames along with numeric addresses. - Don't convert strings to addresses twice. - Don't use the same variable name for different data types. - Make "any" mean "any IPv4 or any IPv6". - Bend the concept of obsolete preferences slightly so that we can convert and old-style key list to a UAT. - Clean up whitespace. - Don't point to a User's Guide section for now; it may make more sense to keep using the wiki page. SSL dissector changes have been tested. DTLS dissector changes have not. svn path=/trunk/; revision=36875
Diffstat (limited to 'epan/dissectors/packet-ssl.c')
-rw-r--r--epan/dissectors/packet-ssl.c224
1 files changed, 163 insertions, 61 deletions
diff --git a/epan/dissectors/packet-ssl.c b/epan/dissectors/packet-ssl.c
index 39959e02c0..9114606551 100644
--- a/epan/dissectors/packet-ssl.c
+++ b/epan/dissectors/packet-ssl.c
@@ -129,7 +129,10 @@
#include "packet-ssl.h"
#include "packet-ssl-utils.h"
#include <wsutil/file_util.h>
+#include <epan/uat.h>
+static ssldecrypt_assoc_t *sslkeylist_uats = NULL;
+static guint nssldecrypt = 0;
static gboolean ssl_desegment = TRUE;
static gboolean ssl_desegment_app_data = TRUE;
@@ -294,6 +297,7 @@ static StringInfo ssl_compressed_data = {NULL, 0};
static StringInfo ssl_decrypted_data = {NULL, 0};
static gint ssl_decrypted_data_avail = 0;
+static uat_t *ssldecrypt_uat = NULL;
static gchar* ssl_keys_list = NULL;
static gchar* ssl_psk = NULL;
@@ -318,9 +322,20 @@ ssl_fragment_init(void)
static void
ssl_init(void)
{
+ module_t *ssl_module = prefs_find_module("ssl");
+ pref_t *keys_list_pref;
+
ssl_common_init(&ssl_session_hash, &ssl_decrypted_data, &ssl_compressed_data);
ssl_fragment_init();
ssl_debug_flush();
+
+ /* We should have loaded "keys_list" by now. Mark it obsolete */
+ if (ssl_module) {
+ keys_list_pref = prefs_find_preference(ssl_module, "keys_list");
+ if (! prefs_get_preference_obsolete(keys_list_pref)) {
+ prefs_set_preference_obsolete(keys_list_pref);
+ }
+ }
}
/* parse ssl related preferences (private keys and ports association strings) */
@@ -329,12 +344,9 @@ ssl_parse(void)
{
ep_stack_t tmp_stack;
SslAssociation *tmp_assoc;
- FILE *ssl_keys_file;
- struct stat statb;
- size_t size;
- gchar *tmp_buf;
- size_t nbytes;
- gboolean read_failed;
+ guint i;
+ gchar **old_keys, **parts, *err;
+ GString *uat_entry = g_string_new("");
ssl_set_debug(ssl_debug_file_name);
@@ -354,30 +366,32 @@ ssl_parse(void)
/* parse private keys string, load available keys and put them in key hash*/
ssl_key_hash = g_hash_table_new(ssl_private_key_hash,ssl_private_key_equal);
- if (ssl_keys_list && (ssl_keys_list[0] != 0))
- {
- if (file_exists(ssl_keys_list)) {
- if ((ssl_keys_file = ws_fopen(ssl_keys_list, "r"))) {
- read_failed = FALSE;
- fstat(fileno(ssl_keys_file), &statb);
- size = (size_t)statb.st_size;
- tmp_buf = ep_alloc0(size + 1);
- nbytes = fread(tmp_buf, 1, size, ssl_keys_file);
- if (ferror(ssl_keys_file)) {
- report_read_failure(ssl_keys_list, errno);
- read_failed = TRUE;
+ /* Import old-style keys */
+ if (ssldecrypt_uat && ssl_keys_list && ssl_keys_list[0]) {
+ old_keys = g_strsplit(ssl_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(ssldecrypt_uat, uat_entry->str, &err)) {
+ ssl_debug_printf("ssl_parse: Can't load UAT string %s: %s\n",
+ uat_entry->str, err);
}
- fclose(ssl_keys_file);
- tmp_buf[nbytes] = '\0';
- if (!read_failed)
- ssl_parse_key_list(tmp_buf,ssl_key_hash,ssl_associations,ssl_handle,TRUE);
- } else {
- report_open_failure(ssl_keys_list, errno, FALSE);
}
- } else {
- ssl_parse_key_list(ssl_keys_list,ssl_key_hash,ssl_associations,ssl_handle,TRUE);
+ g_strfreev(parts);
}
+ g_strfreev(old_keys);
}
+ g_string_free(uat_entry, TRUE);
+
+ if (nssldecrypt > 0) {
+ for (i = 0; i < nssldecrypt; i++) {
+ ssldecrypt_assoc_t *ssl_uat = &(sslkeylist_uats[i]);
+ ssl_parse_key_list(ssl_uat, ssl_key_hash, ssl_associations, ssl_handle, TRUE);
+ }
+ }
+
ssl_debug_flush();
}
@@ -832,20 +846,20 @@ again:
* the pdu).
*/
if ((msp = se_tree_lookup32(flow->multisegment_pdus, seq))) {
- const char* str;
-
- if (msp->first_frame == PINFO_FD_NUM(pinfo)) {
- str = "";
- col_set_str(pinfo->cinfo, COL_INFO, "[SSL segment of a reassembled PDU]");
- } else {
- str = "Retransmitted ";
- }
-
- nbytes = tvb_reported_length_remaining(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, nbytes,
- "%sSSL segment data (%u byte%s)",
- str, nbytes, plurality(nbytes, "", "s"));
- return;
+ const char* str;
+
+ if (msp->first_frame == PINFO_FD_NUM(pinfo)) {
+ str = "";
+ col_set_str(pinfo->cinfo, COL_INFO, "[SSL segment of a reassembled PDU]");
+ } else {
+ str = "Retransmitted ";
+ }
+
+ nbytes = tvb_reported_length_remaining(tvb, offset);
+ proto_tree_add_text(tree, tvb, offset, nbytes,
+ "%sSSL segment data (%u byte%s)",
+ str, nbytes, plurality(nbytes, "", "s"));
+ return;
}
/* Else, find the most previous PDU starting before this sequence number */
@@ -946,7 +960,7 @@ again:
/* create a new TVB structure for desegmented data */
next_tvb = tvb_new_child_real_data(tvb, ipfd_head->data,
ipfd_head->datalen,
- ipfd_head->datalen);
+ ipfd_head->datalen);
/* add desegmented data to the data source list */
add_new_data_source(pinfo, next_tvb, "Reassembled SSL");
@@ -1030,7 +1044,7 @@ again:
* a higher-level PDU, but the data at the
* end of this segment started a higher-level
* PDU but didn't complete it.
- *
+ *
* If so, we have to create some structures
* in our table, but this is something we
* only do the first time we see this packet.
@@ -1042,12 +1056,12 @@ again:
/* The stuff we couldn't dissect
* must have come from this segment,
* so it's all in "tvb".
- *
+ *
* "pinfo->desegment_offset" is
* relative to the beginning of
* "next_tvb"; we want an offset
* relative to the beginning of "tvb".
- *
+ *
* First, compute the offset relative
* to the *end* of "next_tvb" - i.e.,
* the number of bytes before the end
@@ -1067,7 +1081,7 @@ again:
* is also the offset relative to
* the end of "tvb" of the byte at
* which we stopped.
- *
+ *
* Convert that back into an offset
* relative to the beginninng of
* "tvb", by taking the length of
@@ -1104,19 +1118,19 @@ again:
if (((nxtseq - deseg_seq) <= 1024*1024)
&& (!PINFO_FD_VISITED(pinfo))) {
- if(pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
- /* The subdissector asked to reassemble using the
+ if(pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
+ /* The subdissector asked to reassemble using the
* entire next segment.
* Just ask reassembly for one more byte
* but set this msp flag so we can pick it up
* above.
*/
- msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
- deseg_seq, nxtseq+1, flow->multisegment_pdus);
+ msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
+ deseg_seq, nxtseq+1, flow->multisegment_pdus);
msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
} else {
msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
- deseg_seq, nxtseq+pinfo->desegment_len, flow->multisegment_pdus);
+ deseg_seq, nxtseq+pinfo->desegment_len, flow->multisegment_pdus);
}
/* add this segment as the first one for this new pdu */
@@ -2828,7 +2842,7 @@ dissect_ssl2_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
* that will break reassembly.
*/
pinfo->desegment_offset = offset;
- pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
+ pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
*need_desegmentation = TRUE;
return offset;
}
@@ -4191,6 +4205,48 @@ ssl_looks_like_valid_pct_handshake(tvbuff_t *tvb, const guint32 offset,
return ret;
}
+/* UAT */
+
+static void
+ssldecrypt_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);
+}
+
+static void
+ssldecrypt_update_cb(void* r _U_, const char** err)
+{
+ if (err)
+ *err = NULL;
+ return;
+}
+
+static void*
+ssldecrypt_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)
/*********************************************************************
*
@@ -4723,6 +4779,48 @@ proto_register_ssl(void)
{
module_t *ssl_module = prefs_register_protocol(proto_ssl, proto_reg_handoff_ssl);
+
+#ifdef HAVE_LIBGNUTLS
+
+ static uat_field_t sslkeylist_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, "Private keyfile."),
+ UAT_FLD_CSTRING_OTHER(sslkeylist_uats, password,"Password", ssldecrypt_uat_fld_password_chk_cb, "Password (for PCKS#12 keyfile)"),
+ UAT_END_FIELDS
+ };
+
+ ssldecrypt_uat = uat_new("SSL Decrypt",
+ sizeof(ssldecrypt_assoc_t),
+ "ssl_keys", /* filename */
+ TRUE, /* from_profile */
+ (void*) &sslkeylist_uats, /* data_ptr */
+ &nssldecrypt, /* numitems_ptr */
+ UAT_CAT_FFMT, /* category */
+ NULL, /* Help section (currently a wiki page) */
+ ssldecrypt_copy_cb,
+ ssldecrypt_update_cb,
+ ssldecrypt_free_cb,
+ NULL,
+ sslkeylist_uats_flds);
+
+ prefs_register_uat_preference(ssl_module, "key_table",
+ "RSA keys list",
+ "A table of RSA keys for SSL decryption",
+ ssldecrypt_uat);
+
+ prefs_register_string_preference(ssl_module, "debug_file", "SSL debug file",
+ "Redirect SSL debug to file name; leave empty to disable debugging, "
+ "or use \"" SSL_DEBUG_USE_STDERR "\" to redirect output to stderr\n",
+ (const gchar **)&ssl_debug_file_name);
+
+ prefs_register_string_preference(ssl_module, "keys_list", "RSA keys list (deprecated)",
+ "Semicolon-separated list of private RSA keys used for SSL decryption. "
+ "Used by versions of Wireshark prior to 1.6",
+ (const gchar **)&ssl_keys_list);
+#endif
+
prefs_register_bool_preference(ssl_module,
"desegment_ssl_records",
"Reassemble SSL records spanning multiple TCP segments",
@@ -4735,22 +4833,13 @@ proto_register_ssl(void)
"Whether the SSL dissector should reassemble SSL Application Data spanning multiple SSL records. ",
&ssl_desegment_app_data);
#ifdef HAVE_LIBGNUTLS
- prefs_register_string_preference(ssl_module, "keys_list", "RSA keys list",
- "Semicolon-separated list of private RSA keys used for SSL decryption; "
- "each list entry must be in the form of <ip>,<port>,<protocol>,<key_file_name>. "
- "<key_file_name> is the local file name of the RSA private key used by the specified server "
- "(or name of the file containing such a list)",
- (const gchar **)&ssl_keys_list);
- prefs_register_string_preference(ssl_module, "debug_file", "SSL debug file",
- "Redirect SSL debug to file name; leave empty to disable debugging, "
- "or use \"" SSL_DEBUG_USE_STDERR "\" to redirect output to stderr\n",
- (const gchar **)&ssl_debug_file_name);
prefs_register_string_preference(ssl_module, "psk", "Pre-Shared-Key",
"Pre-Shared-Key as HEX string, should be 0 to 16 bytes",
(const gchar **)&ssl_psk);
#endif
}
+
register_dissector("ssl", dissect_ssl, proto_ssl);
ssl_handle = find_dissector("ssl");
@@ -4798,3 +4887,16 @@ ssl_dissector_delete(guint port, const gchar *protocol, gboolean tcp)
ssl_association_remove(ssl_associations, assoc);
}
}
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */