epan/dissectors/packet-xml.c no printf
[metze/wireshark/wip.git] / epan / dissectors / packet-xml.c
index 9faecd793b9ace1f2ecbdd29a19e190733a0ecae..4961f7a47f390ff98a98ae582d38c01f41ddd07f 100644 (file)
  * By Gerald Combs <gerald@wireshark.org>
  * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * SPDX-License-Identifier: GPL-2.0-or-later
  */
 
 #include "config.h"
 
 #include <string.h>
 #include <errno.h>
+#include <stdio.h>
 
 #include <epan/packet.h>
 #include <epan/tvbparse.h>
 #include <epan/dtd.h>
+#include <epan/proto_data.h>
 #include <wsutil/filesystem.h>
 #include <epan/prefs.h>
 #include <epan/expert.h>
 #include <epan/garrayfix.h>
+#include <epan/asn1.h>
 #include <wsutil/str_util.h>
-#include <wsutil/report_err.h>
+#include <wsutil/report_message.h>
+#include <wsutil/wsgcrypt.h>
+#include "packet-kerberos.h"
+#include "read_keytab_file.h"
 
 #include "packet-xml.h"
 
@@ -59,6 +53,7 @@ static int hf_comment = -1;
 static int hf_xmlpi = -1;
 static int hf_dtd_tag = -1;
 static int hf_doctype = -1;
+static int hf_cdatasection = -1;
 
 static expert_field ei_xml_closing_unopened_tag = EI_INIT;
 static expert_field ei_xml_closing_unopened_xmpli_tag = EI_INIT;
@@ -66,14 +61,15 @@ static expert_field ei_xml_unrecognized_text = EI_INIT;
 
 /* dissector handles */
 static dissector_handle_t xml_handle;
+static dissector_handle_t gssapi_handle;
 
 /* parser definitions */
 static tvbparse_wanted_t *want;
 static tvbparse_wanted_t *want_ignore;
 static tvbparse_wanted_t *want_heur;
 
-static GHashTable *xmpli_names;
-static GHashTable *media_types;
+static wmem_map_t *xmpli_names;
+static wmem_map_t *media_types;
 
 static xml_ns_t xml_ns     = {"xml",     "/", -1, -1, -1, NULL, NULL, NULL};
 static xml_ns_t unknown_ns = {"unknown", "?", -1, -1, -1, NULL, NULL, NULL};
@@ -81,9 +77,6 @@ static xml_ns_t *root_ns;
 
 static gboolean pref_heuristic_unicode    = FALSE;
 
-static range_t *global_xml_tcp_range = NULL;
-static range_t *xml_tcp_range        = NULL;
-
 
 #define XML_CDATA       -1000
 #define XML_SCOPED_NAME -1001
@@ -99,12 +92,16 @@ static const gchar *default_media_types[] = {
     "text/vnd.wap.sl",
     "text/vnd.wap.co",
     "text/vnd.wap.emn",
+    "application/3gpp-ims+xml",
     "application/atom+xml",
     "application/auth-policy+xml",
     "application/ccmp+xml",
+    "application/conference-info+xml",          /*RFC4575*/
     "application/cpim-pidf+xml",
     "application/cpl+xml",
     "application/dds-web+xml",
+    "application/im-iscomposing+xml",           /*RFC3994*/
+    "application/load-control+xml",             /*RFC7200*/
     "application/mathml+xml",
     "application/media_control+xml",
     "application/note+xml",
@@ -117,8 +114,10 @@ static const gchar *default_media_types[] = {
     "application/rlmi+xml",
     "application/rls-services+xml",
     "application/rss+xml",
+    "application/rs-metadata+xml",
     "application/smil",
     "application/simple-filter+xml",
+    "application/simple-message-summary+xml",   /*RFC3842*/
     "application/simservs+xml",
     "application/soap+xml",
     "application/vnd.etsi.aoc+xml",
@@ -129,14 +128,67 @@ static const gchar *default_media_types[] = {
     "application/vnd.etsi.iptvsad-bc+xml",
     "application/vnd.etsi.iptvsad-cod+xml",
     "application/vnd.etsi.iptvsad-npvr+xml",
+    "application/vnd.etsi.iptvservice+xml",
+    "application/vnd.etsi.iptvsync+xml",
     "application/vnd.etsi.iptvueprofile+xml",
     "application/vnd.etsi.mcid+xml",
+    "application/vnd.etsi.overload-control-policy-dataset+xml",
+    "application/vnd.etsi.pstn+xml",
     "application/vnd.etsi.sci+xml",
     "application/vnd.etsi.simservs+xml",
+    "application/vnd.etsi.tsl+xml",
     "application/vnd.oma.xdm-apd+xml",
+    "application/vnd.oma.fnl+xml",
+    "application/vnd.oma.access-permissions-list+xml",
+    "application/vnd.oma.alias-principals-list+xml",
+    "application/upp-directory+xml",            /*OMA-ERELD-XDM-V2_2_1-20170124-A*/
+    "application/vnd.oma.xdm-hi+xml",
+    "application/vnd.oma.xdm-rhi+xml",
+    "application/vnd.oma.xdm-prefs+xml",
+    "application/vnd.oma.xdcp+xml",
+    "application/vnd.oma.bcast.associated-procedure-parameter+xml",
+    "application/vnd.oma.bcast.drm-trigger+xml",
+    "application/vnd.oma.bcast.imd+xml",
+    "application/vnd.oma.bcast.notification+xml",
+    "application/vnd.oma.bcast.sgdd+xml",
+    "application/vnd.oma.bcast.smartcard-trigger+xml",
+    "application/vnd.oma.bcast.sprov+xml",
+    "application/vnd.oma.cab-address-book+xml",
+    "application/vnd.oma.cab-feature-handler+xml",
+    "application/vnd.oma.cab-pcc+xml",
+    "application/vnd.oma.cab-subs-invite+xml",
+    "application/vnd.oma.cab-user-prefs+xml",
+    "application/vnd.oma.dd2+xml",
+    "application/vnd.oma.drm.risd+xml",
+    "application/vnd.oma.group-usage-list+xml",
+    "application/vnd.oma.pal+xml",
+    "application/vnd.oma.poc.detailed-progress-report+xml",
+    "application/vnd.oma.poc.final-report+xml",
+    "application/vnd.oma.poc.groups+xml",
+    "application/vnd.oma.poc.invocation-descriptor+xml",
+    "application/vnd.oma.poc.optimized-progress-report+xml",
+    "application/vnd.oma.scidm.messages+xml",
+    "application/vnd.oma.suppnot+xml",          /*OMA-ERELD-Presence_SIMPLE-V2_0-20120710-A*/
+    "application/vnd.oma.xcap-directory+xml",
+    "application/vnd.omads-email+xml",
+    "application/vnd.omads-file+xml",
+    "application/vnd.omads-folder+xml",
+    "application/vnd.3gpp.access-transfer-events+xml",
+    "application/vnd.3gpp.bsf+xml",
+    "application/vnd.3gpp.comm-div-info+xml",   /*3GPP TS 24.504  version 8.19.0*/
     "application/vnd.3gpp.cw+xml",
-    "application/vnd.3gpp.sms+xml"
-    "application/vnd.3gpp.SRVCC-info+xml",
+    "application/vnd.3gpp.iut+xml",             /*3GPP TS 24.337*/
+    "application/vnc.3gpp.iut-config+xml",      /*3GPP TS 24.337*/
+    "application/vnd.3gpp.mid-call+xml",
+    "application/vnd.3gpp-prose-pc3ch+xml",
+    "application/vnd.3gpp-prose+xml",
+    "application/vnd.3gpp.replication+xml",     /*3GPP TS 24.337*/
+    "application/vnd.3gpp.sms+xml",
+    "application/vnd.3gpp.srvcc-info+xml",
+    "application/vnd.3gpp.srvcc-ext+xml",
+    "application/vnd.3gpp.state-and-event-info+xml",
+    "application/vnd.3gpp.ussd+xml",
+    "application/vnd.3gpp2.bcmcsinfo+xml",
     "application/vnd.wv.csp+xml",
     "application/vnd.wv.csp.xml",
     "application/watcherinfo+xml",
@@ -150,10 +202,12 @@ static const gchar *default_media_types[] = {
     "application/xml-dtd",
     "application/xpidf+xml",
     "application/xslt+xml",
+    "application/x-crd+xml",
     "application/x-wms-logconnectstats",
     "application/x-wms-logplaystats",
     "application/x-wms-sendevent",
     "image/svg+xml",
+    "message/imdn+xml",                         /*RFC5438*/
 };
 
 static void insert_xml_frame(xml_frame_t *parent, xml_frame_t *new_child)
@@ -187,7 +241,7 @@ dissect_xml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
         g_ptr_array_free(stack, TRUE);
 
     stack = g_ptr_array_new();
-    current_frame                 = (xml_frame_t *)wmem_alloc(wmem_packet_scope(), sizeof(xml_frame_t));
+    current_frame                 = wmem_new(wmem_packet_scope(), xml_frame_t);
     current_frame->type           = XML_FRAME_ROOT;
     current_frame->name           = NULL;
     current_frame->name_orig_case = NULL;
@@ -198,18 +252,21 @@ dissect_xml(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
 
     tt = tvbparse_init(tvb, 0, -1, stack, want_ignore);
     current_frame->start_offset = 0;
+    current_frame->length = tvb_captured_length(tvb);
+
+    current_frame->decryption_keys = wmem_map_new(wmem_packet_scope(), g_str_hash, g_str_equal);
 
     root_ns = NULL;
 
     if (pinfo->match_string)
-        root_ns = (xml_ns_t *)g_hash_table_lookup(media_types, pinfo->match_string);
+        root_ns = (xml_ns_t *)wmem_map_lookup(media_types, pinfo->match_string);
 
     if (! root_ns ) {
         root_ns = &xml_ns;
         colinfo_str = "/XML";
     } else {
         char *colinfo_str_buf;
-        colinfo_str_buf = wmem_strdup_printf(wmem_packet_scope(), "/%s", root_ns->name);
+        colinfo_str_buf = wmem_strconcat(wmem_packet_scope(), "/", root_ns->name, NULL);
         ascii_strup_inplace(colinfo_str_buf);
         colinfo_str = colinfo_str_buf;
     }
@@ -237,9 +294,8 @@ static gboolean dissect_xml_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *
         return TRUE;
     } else if (pref_heuristic_unicode) {
         /* XXX - UCS-2, or UTF-16? */
-        const guint8 *data_str    = tvb_get_string_enc(NULL, tvb, 0, tvb_captured_length(tvb), ENC_UCS_2|ENC_LITTLE_ENDIAN);
+        const guint8 *data_str    = tvb_get_string_enc(pinfo->pool, tvb, 0, tvb_captured_length(tvb), ENC_UCS_2|ENC_LITTLE_ENDIAN);
         tvbuff_t     *unicode_tvb = tvb_new_child_real_data(tvb, data_str, tvb_captured_length(tvb)/2, tvb_captured_length(tvb)/2);
-        tvb_set_free_cb(unicode_tvb, g_free);
         if (tvbparse_peek(tvbparse_init(unicode_tvb, 0, -1, NULL, want_ignore), want_heur)) {
             add_new_data_source(pinfo, unicode_tvb, "UTF8");
             dissect_xml(unicode_tvb, pinfo, tree, data);
@@ -310,7 +366,8 @@ static void after_token(void *tvbparse_data, const void *wanted_data _U_, tvbpar
     int          hfid;
     gboolean     is_cdata      = FALSE;
     proto_item  *pi;
-    xml_frame_t *new_frame;
+    xml_frame_t *new_frame     = NULL;
+    gchar       *text          = NULL;
 
     if (tok->id == XML_CDATA) {
         hfid = current_frame->ns ? current_frame->ns->hf_cdata : xml_ns.hf_cdata;
@@ -323,11 +380,11 @@ static void after_token(void *tvbparse_data, const void *wanted_data _U_, tvbpar
 
     pi = proto_tree_add_item(current_frame->tree, hfid, tok->tvb, tok->offset, tok->len, ENC_UTF_8|ENC_NA);
 
-    proto_item_set_text(pi, "%s",
-                        tvb_format_text(tok->tvb, tok->offset, tok->len));
+    text = tvb_format_text(tok->tvb, tok->offset, tok->len);
+    proto_item_set_text(pi, "%s", text);
 
     if (is_cdata) {
-        new_frame                 = (xml_frame_t *)wmem_alloc(wmem_packet_scope(), sizeof(xml_frame_t));
+        new_frame                 = wmem_new(wmem_packet_scope(), xml_frame_t);
         new_frame->type           = XML_FRAME_CDATA;
         new_frame->name           = NULL;
         new_frame->name_orig_case = NULL;
@@ -337,9 +394,74 @@ static void after_token(void *tvbparse_data, const void *wanted_data _U_, tvbpar
         new_frame->last_item      = pi;
         new_frame->tree           = NULL;
         new_frame->start_offset   = tok->offset;
+        new_frame->length         = tok->len;
         new_frame->ns             = NULL;
         new_frame->pinfo          = current_frame->pinfo;
     }
+
+    if (new_frame != NULL &&
+        strcmp(current_frame->name_orig_case, "BinarySecurityToken") == 0)
+    {
+        xml_frame_t *value_type   = NULL;
+
+        value_type = xml_get_attrib(current_frame, "ValueType");
+        if (value_type != NULL) {
+            const gchar *s = "http://docs.oasis-open.org/wss/oasis-wss-kerberos-token-profile-1.1#GSS_Kerberosv5_AP_REQ";
+            size_t l = strlen(s);
+            gint c;
+            c = tvb_strneql(value_type->value, 0, s, l);
+            if (c == 0) {
+                tvbuff_t *ssp_tvb = base64_to_tvb(new_frame->value, text);
+                add_new_data_source(current_frame->pinfo, ssp_tvb, "GSSAPI Data");
+                call_dissector(gssapi_handle, ssp_tvb,
+                               current_frame->pinfo, current_frame->tree);
+            }
+        }
+    }
+
+    //printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    fflush(stdout);
+#if 0
+#ifdef HAVE_KERBEROS
+                if (!pinfo->fd->flags.visited && si->status == 0) {
+               enc_key_t *ek;
+
+               if (krb_decrypt) {
+                       read_keytab_file_from_preferences();
+               }
+
+               for (ek=enc_key_list;ek;ek=ek->next) {
+                       if (ek->fd_num == (int)pinfo->num) {
+                               break;
+                       }
+               }
+
+               if (ek != NULL) {
+                       smb2_sesid_info_t *sesid;
+                       guint8 custom_seskey[NTLMSSP_KEY_LEN] = { 0, };
+                       const guint8 *session_key;
+
+                       sesid = wmem_new(wmem_file_scope(), smb2_sesid_info_t);
+                       sesid->sesid = si->sesid;
+                       /* TODO: fill in the correct information */
+                       sesid->acct_name = NULL;
+                       sesid->domain_name = NULL;
+                       sesid->host_name = NULL;
+
+                       if (seskey_find_sid_key(si->sesid, custom_seskey)) {
+                               session_key = custom_seskey;
+                       } else {
+                               session_key = ek->keyvalue;
+                       }
+                       smb2_set_session_keys(sesid, session_key);
+                       sesid->server_port = pinfo->srcport;
+                       sesid->auth_frame = pinfo->num;
+                       sesid->tids = g_hash_table_new(smb2_tid_info_hash, smb2_tid_info_equal);
+                       g_hash_table_insert(si->conv->sesids, sesid, sesid);
+               }
+       }
+#endif
+#endif
 }
 
 static void before_xmpli(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
@@ -350,7 +472,7 @@ static void before_xmpli(void *tvbparse_data, const void *wanted_data _U_, tvbpa
     proto_tree      *pt;
     tvbparse_elem_t *name_tok      = tok->sub->next;
     gchar           *name          = tvb_get_string_enc(wmem_packet_scope(), name_tok->tvb, name_tok->offset, name_tok->len, ENC_ASCII);
-    xml_ns_t        *ns            = (xml_ns_t *)g_hash_table_lookup(xmpli_names, name);
+    xml_ns_t        *ns            = (xml_ns_t *)wmem_map_lookup(xmpli_names, name);
     xml_frame_t     *new_frame;
 
     int  hf_tag;
@@ -371,7 +493,7 @@ static void before_xmpli(void *tvbparse_data, const void *wanted_data _U_, tvbpa
 
     pt = proto_item_add_subtree(pi, ett);
 
-    new_frame                 = (xml_frame_t *)wmem_alloc(wmem_packet_scope(), sizeof(xml_frame_t));
+    new_frame                 = wmem_new(wmem_packet_scope(), xml_frame_t);
     new_frame->type           = XML_FRAME_XMPLI;
     new_frame->name           = name;
     new_frame->name_orig_case = name;
@@ -381,11 +503,14 @@ static void before_xmpli(void *tvbparse_data, const void *wanted_data _U_, tvbpa
     new_frame->last_item      = pi;
     new_frame->tree           = pt;
     new_frame->start_offset   = tok->offset;
+    new_frame->length         = tok->len;
     new_frame->ns             = ns;
     new_frame->pinfo          = current_frame->pinfo;
 
     g_ptr_array_add(stack, new_frame);
 
+    //printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, new_frame->name_orig_case);
+    //fflush(stdout);
 }
 
 static void after_xmlpi(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
@@ -401,6 +526,14 @@ static void after_xmlpi(void *tvbparse_data, const void *wanted_data _U_, tvbpar
         proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_closing_unopened_xmpli_tag,
             tok->tvb, tok->offset, tok->len);
     }
+    //printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    //fflush(stdout);
+    //fflush(stdout);
+    fflush(stdout);
+    fflush(stdout);
+    fflush(stdout);
+    fflush(stdout);
+    fflush(stdout);
 }
 
 static void before_tag(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
@@ -424,10 +557,10 @@ static void before_tag(void *tvbparse_data, const void *wanted_data _U_, tvbpars
         name           = (gchar *)tvb_get_string_enc(wmem_packet_scope(), leaf_tok->tvb, leaf_tok->offset, leaf_tok->len, ENC_ASCII);
         name_orig_case = name;
 
-        nameroot_ns = (xml_ns_t *)g_hash_table_lookup(xml_ns.elements, root_name);
+        nameroot_ns = (xml_ns_t *)wmem_map_lookup(xml_ns.elements, root_name);
 
         if(nameroot_ns) {
-            ns = (xml_ns_t *)g_hash_table_lookup(nameroot_ns->elements, name);
+            ns = (xml_ns_t *)wmem_map_lookup(nameroot_ns->elements, name);
             if (!ns) {
                 ns = &unknown_ns;
             }
@@ -441,10 +574,10 @@ static void before_tag(void *tvbparse_data, const void *wanted_data _U_, tvbpars
         ascii_strdown_inplace(name);
 
         if(current_frame->ns) {
-            ns = (xml_ns_t *)g_hash_table_lookup(current_frame->ns->elements, name);
+            ns = (xml_ns_t *)wmem_map_lookup(current_frame->ns->elements, name);
 
             if (!ns) {
-                if (! ( ns = (xml_ns_t *)g_hash_table_lookup(root_ns->elements, name) ) ) {
+                if (! ( ns = (xml_ns_t *)wmem_map_lookup(root_ns->elements, name) ) ) {
                     ns = &unknown_ns;
                 }
             }
@@ -460,7 +593,7 @@ static void before_tag(void *tvbparse_data, const void *wanted_data _U_, tvbpars
 
     pt = proto_item_add_subtree(pi, ns->ett);
 
-    new_frame = (xml_frame_t *)wmem_alloc(wmem_packet_scope(), sizeof(xml_frame_t));
+    new_frame = wmem_new(wmem_packet_scope(), xml_frame_t);
     new_frame->type           = XML_FRAME_TAG;
     new_frame->name           = name;
     new_frame->name_orig_case = name_orig_case;
@@ -470,11 +603,14 @@ static void before_tag(void *tvbparse_data, const void *wanted_data _U_, tvbpars
     new_frame->last_item      = pi;
     new_frame->tree           = pt;
     new_frame->start_offset   = tok->offset;
+    new_frame->length         = tok->len;
     new_frame->ns             = ns;
     new_frame->pinfo          = current_frame->pinfo;
 
     g_ptr_array_add(stack, new_frame);
 
+    //printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, new_frame->name_orig_case);
+    fflush(stdout);
 }
 
 static void after_open_tag(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok _U_)
@@ -483,6 +619,8 @@ static void after_open_tag(void *tvbparse_data, const void *wanted_data _U_, tvb
     xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1);
 
     proto_item_append_text(current_frame->last_item, ">");
+    //printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    fflush(stdout);
 }
 
 static void after_closed_tag(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
@@ -498,14 +636,43 @@ static void after_closed_tag(void *tvbparse_data, const void *wanted_data _U_, t
         proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_closing_unopened_tag,
                               tok->tvb, tok->offset, tok->len);
     }
+    //printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    fflush(stdout);
+}
+
+struct decryption_key {
+        gchar *id;
+        size_t key_length;
+        guint8 key[HASH_SHA1_LENGTH];
+};
+
+static void P_SHA1(const guint8 *Secret, guint32 Secret_len,
+                   const guint8 *Seed, guint32 Seed_len,
+                   guint8 Result[HASH_SHA1_LENGTH])
+{
+    gcry_md_hd_t  hd     = NULL;
+    guint8       *digest = NULL;
+
+    /*
+     * https://social.microsoft.com/Forums/en-US/c485d98b-6e0b-49e7-ab34-8ecf8d694d31/signing-soap-message-request-via-adfs?forum=crmdevelopment#6cee9fa8-dc24-4524-a5a2-c3d17e05d50e
+     */
+    gcry_md_open(&hd, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
+    gcry_md_setkey(hd, Secret, Secret_len);
+    gcry_md_write(hd, Seed, Seed_len);
+    digest = gcry_md_read(hd, GCRY_MD_SHA1);
+    memcpy(Result, digest, HASH_SHA1_LENGTH);
+
+    gcry_md_close(hd);
 }
 
 static void after_untag(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
 {
     GPtrArray   *stack         = (GPtrArray *)tvbparse_data;
     xml_frame_t *current_frame = (xml_frame_t *)g_ptr_array_index(stack, stack->len - 1);
+    xml_frame_t *top_frame = (xml_frame_t *)g_ptr_array_index(stack, 0);
 
     proto_item_set_len(current_frame->item, (tok->offset - current_frame->start_offset) + tok->len);
+    current_frame->length = (tok->offset - current_frame->start_offset) + tok->len;
 
     proto_tree_add_format_text(current_frame->tree, tok->tvb, tok->offset, tok->len);
 
@@ -515,6 +682,215 @@ static void after_untag(void *tvbparse_data, const void *wanted_data _U_, tvbpar
         proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_closing_unopened_tag,
             tok->tvb, tok->offset, tok->len);
     }
+    //printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    fflush(stdout);
+
+    if (current_frame->name_orig_case == NULL) {
+        return;
+    }
+
+#ifdef HAVE_KERBEROS
+    if (strcmp(current_frame->name_orig_case, "DerivedKeyToken") == 0) {
+        xml_frame_t *id_frame = xml_get_attrib(current_frame, "u:Id");
+        xml_frame_t *nonce_frame = xml_get_tag(current_frame, "Nonce");
+        xml_frame_t *nonce_cdata = NULL;
+        tvbuff_t *nonce_tvb = NULL;
+        enc_key_t *ek = NULL;
+        guint8 seed[64];
+        size_t seed_length = 16; // TODO
+        const size_t key_length = 16; //TODO
+
+        //printf("%s:%s:%u: DerivedKeyToken->Id[%p]\n", __FILE__, G_STRFUNC, __LINE__, id_frame);
+        //printf("%s:%s:%u: DerivedKeyToken->Nonce[%p]\n", __FILE__, G_STRFUNC, __LINE__, nonce_frame);
+    fflush(stdout);
+        if (id_frame != NULL && nonce_frame != NULL) {
+            nonce_cdata = xml_get_cdata(nonce_frame);
+        }
+        if (nonce_cdata != NULL) {
+    //printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    fflush(stdout);
+            gchar *text = tvb_format_text(nonce_cdata->value, 0,
+                                          tvb_reported_length(nonce_cdata->value));
+            nonce_tvb = base64_to_tvb(nonce_cdata->value, text);
+        }
+        if (nonce_tvb != NULL) {
+    //printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    fflush(stdout);
+
+            seed_length = tvb_reported_length(nonce_tvb);
+            seed_length = MIN(seed_length, sizeof(seed));
+            tvb_memcpy(nonce_tvb, seed, 0, seed_length);
+
+            if (krb_decrypt) {
+                read_keytab_file_from_preferences();
+            }
+
+            for (ek=enc_key_list;ek;ek=ek->next) {
+                if (ek->fd_num == (int)current_frame->pinfo->num) {
+                    break;
+                }
+            }
+        }
+    //printf("%s:%s:%u: ek[%p]\n", __FILE__, G_STRFUNC, __LINE__, ek);
+    fflush(stdout);
+        if (ek != NULL) {
+            struct decryption_key *key;
+
+            key = wmem_new0(wmem_packet_scope(), struct decryption_key);
+            key->id = wmem_strdup_printf(wmem_packet_scope(), "#%s",
+                                         tvb_format_text(id_frame->value, 0, tvb_reported_length(id_frame->value)));
+           P_SHA1(ek->keyvalue, ek->keylength, seed, seed_length, key->key);
+            key->key_length = key_length;
+
+           wmem_map_insert(top_frame->decryption_keys, key->id, key);
+    //printf("%s:%s:%u: key_id[%s] (%02x%02x%02x%02x...)\n", __FILE__, G_STRFUNC, __LINE__, key->id,
+       //                           key->key[0] & 0xFF, key->key[1] & 0xFF,
+       //                           key->key[2] & 0xFF, key->key[3] & 0xFF);
+    fflush(stdout);
+        }
+        //proto_item_append_text(current_frame->last_item, "(ek[%p])", ek);
+ //   printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    fflush(stdout);
+    }
+    if (strcmp(current_frame->name_orig_case, "CipherValue") == 0) {
+        xml_frame_t *encrypted_frame = current_frame->parent->parent;
+        xml_frame_t *key_info_frame = NULL;
+        xml_frame_t *token_frame = NULL;
+        xml_frame_t *reference_frame = NULL;
+        xml_frame_t *uri_frame = NULL;
+        const struct decryption_key *key = NULL;
+        xml_frame_t *cdata_frame = NULL;
+        tvbuff_t *crypt_tvb = NULL;
+        tvbuff_t *plain_tvb = NULL;
+
+  //      printf("%s:%s:%u: CipherValue->Parent->Parent[%p]\n", __FILE__, G_STRFUNC, __LINE__,
+  //              encrypted_frame);
+  //      printf("%s:%s:%u: CipherValue->Parent->Parent[%s]\n", __FILE__, G_STRFUNC, __LINE__,
+  //              encrypted_frame->name_orig_case);
+
+        key_info_frame = xml_get_tag(encrypted_frame, "KeyInfo");
+        if (key_info_frame != NULL) {
+            token_frame = xml_get_tag(key_info_frame, "SecurityTokenReference");
+        }
+        if (token_frame != NULL) {
+            reference_frame = xml_get_tag(token_frame, "Reference");
+        }
+        if (reference_frame != NULL) {
+            uri_frame = xml_get_attrib(reference_frame, "URI");
+        }
+
+        //printf("%s:%s:%u: key_info[%p] token[%p] reference[%p] uri[%p]\n", __FILE__, G_STRFUNC, __LINE__,
+        //       key_info_frame, token_frame, reference_frame, uri_frame);
+    fflush(stdout);
+        if (uri_frame != NULL) {
+            gchar *key_id = tvb_format_text(uri_frame->value, 0,
+                                            tvb_reported_length(uri_frame->value));
+
+
+        //printf("%s:%s:%u: URI[%s]\n", __FILE__, G_STRFUNC, __LINE__, key_id);
+    fflush(stdout);
+           key = (const struct decryption_key *)wmem_map_lookup(top_frame->decryption_keys, key_id);
+        }
+        if (key != NULL) {
+//    printf("%s:%s:%u: key_id[%s] (%02x%02x%02x%02x...)\n", __FILE__, G_STRFUNC, __LINE__, key->id,
+//                                  key->key[0] & 0xFF, key->key[1] & 0xFF,
+//                                  key->key[2] & 0xFF, key->key[3] & 0xFF);
+    fflush(stdout);
+            cdata_frame = xml_get_cdata(current_frame);
+        }
+        if (cdata_frame != NULL) {
+            gchar *text = tvb_format_text(cdata_frame->value, 0,
+                                          tvb_reported_length(cdata_frame->value));
+            crypt_tvb = base64_to_tvb(cdata_frame->value, text);
+        }
+        if (crypt_tvb != NULL) {
+               gcry_cipher_hd_t cipher_hd = NULL;
+                guint8 *data = NULL;
+                size_t data_length = tvb_reported_length(crypt_tvb);
+
+//    printf("%s:%s:%u: data_length[%zu]\n", __FILE__, G_STRFUNC, __LINE__, data_length);
+    fflush(stdout);
+               data = (guint8 *)tvb_memdup(wmem_packet_scope(),
+                                            crypt_tvb, 0, data_length);
+
+               /* Open the cipher. */
+               gcry_cipher_open(&cipher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CBC, 0);
+
+               gcry_cipher_setkey(cipher_hd, key->key, key->key_length);
+               //gcry_cipher_setctr(cipher_hd, A_1, NTLMSSP_KEY_LEN);
+               //gcry_cipher_encrypt(cipher_hd, plain_data, sti->size, NULL, 0);
+               //gcry_cipher_decrypt(cipher_hd, data, data_length, NULL, 0);
+               gcry_cipher_encrypt(cipher_hd, data, data_length, NULL, 0);
+               gcry_cipher_close(cipher_hd);
+
+               plain_tvb = tvb_new_child_real_data(crypt_tvb, data,
+                                                    data_length, data_length);
+                add_new_data_source(current_frame->pinfo, plain_tvb, "Decrypted Data");
+        }
+    }
+#endif
+#if 0
+        metze
+        strcmp(current_frame->name_orig_case, "BinarySecurityToken") == 0)
+        xml_frame_t *value_type   = NULL;
+
+        value_type = xml_get_attrib(current_frame, "ValueType");
+        if (value_type != NULL) {
+            const gchar *s = "http://docs.oasis-open.org/wss/oasis-wss-kerberos-token-profile-1.1#GSS_Kerberosv5_AP_REQ";
+            size_t l = strlen(s);
+            gint c;
+            c = tvb_strneql(value_type->value, 0, s, l);
+            if (c == 0) {
+                tvbuff_t *ssp_tvb = base64_to_tvb(new_frame->value, text);
+                add_new_data_source(current_frame->pinfo, ssp_tvb, "GSSAPI Data");
+                call_dissector(gssapi_handle, ssp_tvb,
+                               current_frame->pinfo, current_frame->tree);
+            }
+        }
+    }
+
+#ifdef HAVE_KERBEROS
+                if (!pinfo->fd->flags.visited && si->status == 0) {
+               enc_key_t *ek;
+
+               if (krb_decrypt) {
+                       read_keytab_file_from_preferences();
+               }
+
+               for (ek=enc_key_list;ek;ek=ek->next) {
+                       if (ek->fd_num == (int)pinfo->num) {
+                               break;
+                       }
+               }
+
+               if (ek != NULL) {
+                       smb2_sesid_info_t *sesid;
+                       guint8 custom_seskey[NTLMSSP_KEY_LEN] = { 0, };
+                       const guint8 *session_key;
+
+                       sesid = wmem_new(wmem_file_scope(), smb2_sesid_info_t);
+                       sesid->sesid = si->sesid;
+                       /* TODO: fill in the correct information */
+                       sesid->acct_name = NULL;
+                       sesid->domain_name = NULL;
+                       sesid->host_name = NULL;
+
+                       if (seskey_find_sid_key(si->sesid, custom_seskey)) {
+                               session_key = custom_seskey;
+                       } else {
+                               session_key = ek->keyvalue;
+                       }
+                       smb2_set_session_keys(sesid, session_key);
+                       sesid->server_port = pinfo->srcport;
+                       sesid->auth_frame = pinfo->num;
+                       sesid->tids = g_hash_table_new(smb2_tid_info_hash, smb2_tid_info_equal);
+                       g_hash_table_insert(si->conv->sesids, sesid, sesid);
+               }
+       }
+#endif
+#endif
+    //printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    fflush(stdout);
 }
 
 static void before_dtd_doctype(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
@@ -529,7 +905,7 @@ static void before_dtd_doctype(void *tvbparse_data, const void *wanted_data _U_,
 
     proto_item_set_text(dtd_item, "%s", tvb_format_text(tok->tvb, tok->offset, tok->len));
 
-    new_frame = (xml_frame_t *)wmem_alloc(wmem_packet_scope(), sizeof(xml_frame_t));
+    new_frame = wmem_new(wmem_packet_scope(), xml_frame_t);
     new_frame->type           = XML_FRAME_DTD_DOCTYPE;
     new_frame->name           = (gchar *)tvb_get_string_enc(wmem_packet_scope(), name_tok->tvb,
                                                                   name_tok->offset,
@@ -541,10 +917,13 @@ static void before_dtd_doctype(void *tvbparse_data, const void *wanted_data _U_,
     new_frame->last_item      = dtd_item;
     new_frame->tree           = proto_item_add_subtree(dtd_item, ett_dtd);
     new_frame->start_offset   = tok->offset;
+    new_frame->length         = tok->len;
     new_frame->ns             = NULL;
     new_frame->pinfo          = current_frame->pinfo;
 
     g_ptr_array_add(stack, new_frame);
+    //printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, new_frame->name_orig_case);
+    fflush(stdout);
 }
 
 static void pop_stack(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok _U_)
@@ -558,6 +937,8 @@ static void pop_stack(void *tvbparse_data, const void *wanted_data _U_, tvbparse
         proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_closing_unopened_tag,
             tok->tvb, tok->offset, tok->len);
     }
+    //printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    fflush(stdout);
 }
 
 static void after_dtd_close(void *tvbparse_data, const void *wanted_data _U_, tvbparse_elem_t *tok)
@@ -572,6 +953,8 @@ static void after_dtd_close(void *tvbparse_data, const void *wanted_data _U_, tv
         proto_tree_add_expert(current_frame->tree, current_frame->pinfo, &ei_xml_closing_unopened_tag,
             tok->tvb, tok->offset, tok->len);
     }
+    //printf("%s:%s:%u: name[%s]\n", __FILE__, G_STRFUNC, __LINE__, current_frame->name_orig_case);
+    fflush(stdout);
 }
 
 static void get_attrib_value(void *tvbparse_data _U_, const void *wanted_data _U_, tvbparse_elem_t *tok)
@@ -595,7 +978,7 @@ static void after_attrib(void *tvbparse_data, const void *wanted_data _U_, tvbpa
     name_orig_case = wmem_strdup(wmem_packet_scope(), name);
     ascii_strdown_inplace(name);
 
-    if(current_frame->ns && (hfidp = (int *)g_hash_table_lookup(current_frame->ns->attributes, name) )) {
+    if(current_frame->ns && (hfidp = (int *)wmem_map_lookup(current_frame->ns->attributes, name) )) {
         hfid  = *hfidp;
         value = value_part;
     } else {
@@ -608,7 +991,7 @@ static void after_attrib(void *tvbparse_data, const void *wanted_data _U_, tvbpa
 
     current_frame->last_item = pi;
 
-    new_frame = (xml_frame_t *)wmem_alloc(wmem_packet_scope(), sizeof(xml_frame_t));
+    new_frame = wmem_new(wmem_packet_scope(), xml_frame_t);
     new_frame->type           = XML_FRAME_ATTRIB;
     new_frame->name           = name;
     new_frame->name_orig_case = name_orig_case;
@@ -619,6 +1002,7 @@ static void after_attrib(void *tvbparse_data, const void *wanted_data _U_, tvbpa
     new_frame->last_item      = pi;
     new_frame->tree           = NULL;
     new_frame->start_offset   = tok->offset;
+    new_frame->length         = tok->len;
     new_frame->ns             = NULL;
     new_frame->pinfo          = current_frame->pinfo;
 
@@ -686,6 +1070,13 @@ static void init_xml_parser(void)
                                       TP_UNTIL_INCLUDE),
                                NULL);
 
+    tvbparse_wanted_t *want_cdatasection = tvbparse_set_seq(hf_cdatasection, NULL, NULL, after_token,
+                               tvbparse_string(-1, "<![CDATA[", NULL, NULL, NULL),
+                               tvbparse_until(-1, NULL, NULL, NULL,
+                                       tvbparse_string(-1, "]]>", NULL, NULL, NULL),
+                                       TP_UNTIL_INCLUDE),
+                                NULL);
+
     tvbparse_wanted_t *want_xmlpi = tvbparse_set_seq(hf_xmlpi, NULL, before_xmpli, NULL,
                              tvbparse_string(-1, "<?", NULL, NULL, NULL),
                              want_name,
@@ -757,6 +1148,7 @@ static void init_xml_parser(void)
 
     want = tvbparse_set_oneof(-1, NULL, NULL, NULL,
                   want_comment,
+                  want_cdatasection,
                   want_xmlpi,
                   want_closing_tag,
                   want_doctype_start,
@@ -769,6 +1161,7 @@ static void init_xml_parser(void)
 
     want_heur = tvbparse_set_oneof(-1, NULL, NULL, NULL,
                        want_comment,
+                       want_cdatasection,
                        want_xmlpi,
                        want_doctype_start,
                        want_dtd_tag,
@@ -778,30 +1171,30 @@ static void init_xml_parser(void)
 }
 
 
-static xml_ns_t *xml_new_namespace(GHashTable *hash, const gchar *name, ...)
+static xml_ns_t *xml_new_namespace(wmem_map_t *hash, const gchar *name, ...)
 {
-    xml_ns_t *ns = (xml_ns_t *)g_malloc(sizeof(xml_ns_t));
+    xml_ns_t *ns = wmem_new(wmem_epan_scope(), xml_ns_t);
     va_list   ap;
     gchar    *attr_name;
 
-    ns->name       = g_strdup(name);
+    ns->name       = wmem_strdup(wmem_epan_scope(), name);
     ns->hf_tag     = -1;
     ns->hf_cdata   = -1;
     ns->ett        = -1;
-    ns->attributes = g_hash_table_new(g_str_hash, g_str_equal);
-    ns->elements   = g_hash_table_new(g_str_hash, g_str_equal);
+    ns->attributes = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
+    ns->elements   = NULL;
 
     va_start(ap, name);
 
     while(( attr_name = va_arg(ap, gchar *) )) {
-        int *hfp = (int *)g_malloc(sizeof(int));
+        int *hfp = wmem_new(wmem_epan_scope(), int);
         *hfp = -1;
-        g_hash_table_insert(ns->attributes, g_strdup(attr_name), hfp);
+        wmem_map_insert(ns->attributes, wmem_strdup(wmem_epan_scope(), attr_name), hfp);
     };
 
     va_end(ap);
 
-    g_hash_table_insert(hash, ns->name, ns);
+    wmem_map_insert(hash, ns->name, ns);
 
     return ns;
 }
@@ -819,11 +1212,7 @@ static void add_xml_field(wmem_array_t *hfs, int *p_id, const gchar *name, const
     hfri.hfinfo.strings        = NULL;
     hfri.hfinfo.bitmask        = 0x0;
     hfri.hfinfo.blurb          = NULL;
-    hfri.hfinfo.id             = 0;
-    hfri.hfinfo.parent         = 0;
-    hfri.hfinfo.ref_type       = HF_REF_TYPE_NONE;
-    hfri.hfinfo.same_name_next = NULL;
-    hfri.hfinfo.same_name_prev_id = -1;
+    HFILL_INIT(hfri);
 
     wmem_array_append_one(hfs, hfri);
 }
@@ -831,7 +1220,7 @@ static void add_xml_field(wmem_array_t *hfs, int *p_id, const gchar *name, const
 static void add_xml_attribute_names(gpointer k, gpointer v, gpointer p)
 {
     struct _attr_reg_data *d = (struct _attr_reg_data *)p;
-    const gchar *basename = wmem_strdup_printf(wmem_epan_scope(), "%s.%s", d->basename, (gchar *)k);
+    const gchar *basename = wmem_strconcat(wmem_epan_scope(), d->basename, ".", (gchar *)k, NULL);
 
     add_xml_field(d->hf, (int*) v, (gchar *)k, basename);
 }
@@ -840,7 +1229,7 @@ static void add_xml_attribute_names(gpointer k, gpointer v, gpointer p)
 static void add_xmlpi_namespace(gpointer k _U_, gpointer v, gpointer p)
 {
     xml_ns_t *ns       = (xml_ns_t *)v;
-    const gchar *basename = wmem_strdup_printf(wmem_epan_scope(), "%s.%s", (gchar *)p, ns->name);
+    const gchar *basename = wmem_strconcat(wmem_epan_scope(), (gchar *)p, ".", ns->name, NULL);
     gint     *ett_p    = &(ns->ett);
     struct _attr_reg_data d;
 
@@ -851,7 +1240,7 @@ static void add_xmlpi_namespace(gpointer k _U_, gpointer v, gpointer p)
     d.basename = basename;
     d.hf = hf_arr;
 
-    g_hash_table_foreach(ns->attributes, add_xml_attribute_names, &d);
+    wmem_map_foreach(ns->attributes, add_xml_attribute_names, &d);
 
 }
 
@@ -867,6 +1256,7 @@ static void destroy_dtd_data(dtd_build_data_t *dtd_data)
     while(dtd_data->elements->len) {
         dtd_named_list_t *nl = (dtd_named_list_t *)g_ptr_array_remove_index_fast(dtd_data->elements, 0);
         g_ptr_array_free(nl->list, TRUE);
+        g_free(nl->name);
         g_free(nl);
     }
 
@@ -875,6 +1265,7 @@ static void destroy_dtd_data(dtd_build_data_t *dtd_data)
     while(dtd_data->attributes->len) {
         dtd_named_list_t *nl = (dtd_named_list_t *)g_ptr_array_remove_index_fast(dtd_data->attributes, 0);
         g_ptr_array_free(nl->list, TRUE);
+        g_free(nl->name);
         g_free(nl);
     }
 
@@ -885,35 +1276,35 @@ static void destroy_dtd_data(dtd_build_data_t *dtd_data)
 
 static void copy_attrib_item(gpointer k, gpointer v _U_, gpointer p)
 {
-    gchar      *key   = (gchar *)g_strdup((const gchar *)k);
-    int        *value = (int *)g_malloc(sizeof(int));
-    GHashTable *dst   = (GHashTable *)p;
+    gchar      *key   = (gchar *)wmem_strdup(wmem_epan_scope(), (const gchar *)k);
+    int        *value = wmem_new(wmem_epan_scope(), int);
+    wmem_map_t *dst   = (wmem_map_t *)p;
 
     *value = -1;
-    g_hash_table_insert(dst, key, value);
+    wmem_map_insert(dst, key, value);
 
 }
 
-static GHashTable *copy_attributes_hash(GHashTable *src)
+static wmem_map_t *copy_attributes_hash(wmem_map_t *src)
 {
-    GHashTable *dst = g_hash_table_new(g_str_hash, g_str_equal);
+    wmem_map_t *dst = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
 
-    g_hash_table_foreach(src, copy_attrib_item, dst);
+    wmem_map_foreach(src, copy_attrib_item, dst);
 
     return dst;
 }
 
 static xml_ns_t *duplicate_element(xml_ns_t *orig)
 {
-    xml_ns_t *new_item = (xml_ns_t *)g_malloc(sizeof(xml_ns_t));
+    xml_ns_t *new_item = wmem_new(wmem_epan_scope(), xml_ns_t);
     guint     i;
 
-    new_item->name          = g_strdup(orig->name);
+    new_item->name          = wmem_strdup(wmem_epan_scope(), orig->name);
     new_item->hf_tag        = -1;
     new_item->hf_cdata      = -1;
     new_item->ett           = -1;
     new_item->attributes    = copy_attributes_hash(orig->attributes);
-    new_item->elements      = g_hash_table_new(g_str_hash, g_str_equal);
+    new_item->elements      = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
     new_item->element_names = g_ptr_array_new();
 
     for(i=0; i < orig->element_names->len; i++) {
@@ -927,23 +1318,23 @@ static xml_ns_t *duplicate_element(xml_ns_t *orig)
 static gchar *fully_qualified_name(GPtrArray *hier, gchar *name, gchar *proto_name)
 {
     guint    i;
-    GString *s = g_string_new(proto_name);
+    wmem_strbuf_t *s = wmem_strbuf_new(wmem_epan_scope(), proto_name);
 
-    g_string_append(s, ".");
+    wmem_strbuf_append(s, ".");
 
     for (i = 1; i < hier->len; i++) {
-        g_string_append_printf(s, "%s.", (gchar *)g_ptr_array_index(hier, i));
+        wmem_strbuf_append_printf(s, "%s.", (gchar *)g_ptr_array_index(hier, i));
     }
 
-    g_string_append(s, name);
+    wmem_strbuf_append(s, name);
 
-    return g_string_free(s, FALSE);
+    return wmem_strbuf_finalize(s);;
 }
 
 
 static xml_ns_t *make_xml_hier(gchar      *elem_name,
                                xml_ns_t   *root,
-                               GHashTable *elements,
+                               wmem_map_t *elements,
                                GPtrArray  *hier,
                                GString    *error,
                                wmem_array_t *hfs,
@@ -962,7 +1353,7 @@ static xml_ns_t *make_xml_hier(gchar      *elem_name,
         return NULL;
     }
 
-    if (! ( orig = (xml_ns_t *)g_hash_table_lookup(elements, elem_name) )) {
+    if (! ( orig = (xml_ns_t *)wmem_map_lookup(elements, elem_name) )) {
         g_string_append_printf(error, "element '%s' is not defined\n", elem_name);
         return NULL;
     }
@@ -991,7 +1382,7 @@ static xml_ns_t *make_xml_hier(gchar      *elem_name,
     d.basename = fqn;
     d.hf = hfs;
 
-    g_hash_table_foreach(fresh->attributes, add_xml_attribute_names, &d);
+    wmem_map_foreach(fresh->attributes, add_xml_attribute_names, &d);
 
     while(fresh->element_names->len) {
         gchar *child_name = (gchar *)g_ptr_array_remove_index(fresh->element_names, 0);
@@ -1002,7 +1393,7 @@ static xml_ns_t *make_xml_hier(gchar      *elem_name,
         g_ptr_array_remove_index_fast(hier, hier->len - 1);
 
         if (child_element) {
-            g_hash_table_insert(fresh->elements, child_element->name, child_element);
+            wmem_map_insert(fresh->elements, child_element->name, child_element);
         }
     }
 
@@ -1011,35 +1402,20 @@ static xml_ns_t *make_xml_hier(gchar      *elem_name,
     return fresh;
 }
 
-static gboolean free_both(gpointer k, gpointer v, gpointer p _U_)
-{
-    g_free(k);
-    g_free(v);
-    return TRUE;
-}
-
-static gboolean free_elements(gpointer k _U_, gpointer v, gpointer p _U_)
+static void free_elements(gpointer k _U_, gpointer v, gpointer p _U_)
 {
     xml_ns_t *e = (xml_ns_t *)v;
 
-    g_free(e->name);
-    g_hash_table_foreach_remove(e->attributes, free_both, NULL);
-    g_hash_table_destroy(e->attributes);
-    g_hash_table_destroy(e->elements);
-
     while (e->element_names->len) {
         g_free(g_ptr_array_remove_index(e->element_names, 0));
     }
 
     g_ptr_array_free(e->element_names, TRUE);
-    g_free(e);
-
-    return TRUE;
 }
 
 static void register_dtd(dtd_build_data_t *dtd_data, GString *errors)
 {
-    GHashTable *elements      = g_hash_table_new(g_str_hash, g_str_equal);
+    wmem_map_t *elements      = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
     gchar      *root_name     = NULL;
     xml_ns_t   *root_element  = NULL;
     wmem_array_t *hfs;
@@ -1051,44 +1427,45 @@ static void register_dtd(dtd_build_data_t *dtd_data, GString *errors)
     /* we first populate elements with the those coming from the parser */
     while(dtd_data->elements->len) {
         dtd_named_list_t *nl      = (dtd_named_list_t *)g_ptr_array_remove_index(dtd_data->elements, 0);
-        xml_ns_t         *element = (xml_ns_t *)g_malloc(sizeof(xml_ns_t));
+        xml_ns_t         *element = wmem_new(wmem_epan_scope(), xml_ns_t);
 
         /* we will use the first element found as root in case no other one was given. */
         if (root_name == NULL)
-            root_name = g_strdup(nl->name);
+            root_name = wmem_strdup(wmem_epan_scope(), nl->name);
 
-        element->name          = nl->name;
+        element->name          = wmem_strdup(wmem_epan_scope(), nl->name);
         element->element_names = nl->list;
         element->hf_tag        = -1;
         element->hf_cdata      = -1;
         element->ett           = -1;
-        element->attributes    = g_hash_table_new(g_str_hash, g_str_equal);
-        element->elements      = g_hash_table_new(g_str_hash, g_str_equal);
+        element->attributes    = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
+        element->elements      = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
 
-        if( g_hash_table_lookup(elements, element->name) ) {
+        if( wmem_map_lookup(elements, element->name) ) {
             g_string_append_printf(errors, "element %s defined more than once\n", element->name);
             free_elements(NULL, element, NULL);
         } else {
-            g_hash_table_insert(elements, (gpointer)element->name, element);
-            g_ptr_array_add(element_names, g_strdup(element->name));
+            wmem_map_insert(elements, element->name, element);
+            g_ptr_array_add(element_names, wmem_strdup(wmem_epan_scope(), element->name));
         }
 
+        g_free(nl->name);
         g_free(nl);
     }
 
     /* then we add the attributes to its relative elements */
     while(dtd_data->attributes->len) {
         dtd_named_list_t *nl      = (dtd_named_list_t *)g_ptr_array_remove_index(dtd_data->attributes, 0);
-        xml_ns_t         *element = (xml_ns_t *)g_hash_table_lookup(elements, nl->name);
+        xml_ns_t         *element = (xml_ns_t *)wmem_map_lookup(elements, nl->name);
 
         if (element) {
             while(nl->list->len) {
                 gchar *name = (gchar *)g_ptr_array_remove_index(nl->list, 0);
-                int   *id_p = (int *)g_malloc(sizeof(int));
+                int   *id_p = wmem_new(wmem_epan_scope(), int);
 
                 *id_p = -1;
-                g_hash_table_insert(element->attributes, name, id_p);
-            }
+                wmem_map_insert(element->attributes, wmem_strdup(wmem_epan_scope(), name), id_p);
+                g_free(name);            }
         }
         else {
             g_string_append_printf(errors, "element %s is not defined\n", nl->name);
@@ -1101,8 +1478,8 @@ static void register_dtd(dtd_build_data_t *dtd_data, GString *errors)
 
     /* if a proto_root is defined in the dtd we'll use that as root */
     if( dtd_data->proto_root ) {
-        g_free(root_name);
-        root_name = g_strdup(dtd_data->proto_root);
+        wmem_free(wmem_epan_scope(), root_name);
+        root_name = wmem_strdup(wmem_epan_scope(), dtd_data->proto_root);
     }
 
     /* we use a stack with the names to avoid recurring infinitelly */
@@ -1115,7 +1492,7 @@ static void register_dtd(dtd_build_data_t *dtd_data, GString *errors)
     if( ! dtd_data->proto_name ) {
         hfs  = hf_arr;
         etts = ett_arr;
-        g_ptr_array_add(hier, g_strdup("xml"));
+        g_ptr_array_add(hier, wmem_strdup(wmem_epan_scope(), "xml"));
     } else {
         /*
          * if we were given a proto_name the namespace will be registered
@@ -1126,13 +1503,13 @@ static void register_dtd(dtd_build_data_t *dtd_data, GString *errors)
     }
 
     /* the root element of the dtd's namespace */
-    root_element = (xml_ns_t *)g_malloc(sizeof(xml_ns_t));
-    root_element->name          = g_strdup(root_name);
-    root_element->fqn           = dtd_data->proto_name ? g_strdup(dtd_data->proto_name) : root_element->name;
+    root_element = wmem_new(wmem_epan_scope(), xml_ns_t);
+    root_element->name          = wmem_strdup(wmem_epan_scope(), root_name);
+    root_element->fqn           = dtd_data->proto_name ? wmem_strdup(wmem_epan_scope(), dtd_data->proto_name) : root_element->name;
     root_element->hf_tag        = -1;
     root_element->hf_cdata      = -1;
     root_element->ett           = -1;
-    root_element->elements      = g_hash_table_new(g_str_hash, g_str_equal);
+    root_element->elements      = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
     root_element->element_names = element_names;
 
     /*
@@ -1145,9 +1522,9 @@ static void register_dtd(dtd_build_data_t *dtd_data, GString *errors)
 
         make_xml_hier(root_name, root_element, elements, hier, errors, hfs, etts, dtd_data->proto_name);
 
-        g_hash_table_insert(root_element->elements, (gpointer)root_element->name, root_element);
+        wmem_map_insert(root_element->elements, (gpointer)root_element->name, root_element);
 
-        orig_root = (xml_ns_t *)g_hash_table_lookup(elements, root_name);
+        orig_root = (xml_ns_t *)wmem_map_lookup(elements, root_name);
 
         /* if the root element was defined copy its attrlist to the child */
         if(orig_root) {
@@ -1157,9 +1534,9 @@ static void register_dtd(dtd_build_data_t *dtd_data, GString *errors)
             d.hf = hfs;
 
             root_element->attributes = copy_attributes_hash(orig_root->attributes);
-            g_hash_table_foreach(root_element->attributes, add_xml_attribute_names, &d);
+            wmem_map_foreach(root_element->attributes, add_xml_attribute_names, &d);
         } else {
-            root_element->attributes = g_hash_table_new(g_str_hash, g_str_equal);
+            root_element->attributes = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
         }
 
         /* we then create all the sub hierarchies to catch the recurred cases */
@@ -1168,20 +1545,18 @@ static void register_dtd(dtd_build_data_t *dtd_data, GString *errors)
         while(root_element->element_names->len) {
             curr_name = (gchar *)g_ptr_array_remove_index(root_element->element_names, 0);
 
-            if( ! g_hash_table_lookup(root_element->elements, curr_name) ) {
+            if( ! wmem_map_lookup(root_element->elements, curr_name) ) {
                 xml_ns_t *fresh = make_xml_hier(curr_name, root_element, elements, hier, errors,
                                               hfs, etts, dtd_data->proto_name);
-                g_hash_table_insert(root_element->elements, (gpointer)fresh->name, fresh);
+                wmem_map_insert(root_element->elements, (gpointer)fresh->name, fresh);
             }
-
-            g_free(curr_name);
         }
 
     } else {
         /* a flat namespace */
         g_ptr_array_add(hier, root_name);
 
-        root_element->attributes = g_hash_table_new(g_str_hash, g_str_equal);
+        root_element->attributes = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
 
         while(root_element->element_names->len) {
             xml_ns_t *fresh;
@@ -1189,7 +1564,7 @@ static void register_dtd(dtd_build_data_t *dtd_data, GString *errors)
             struct _attr_reg_data d;
 
             curr_name = (gchar *)g_ptr_array_remove_index(root_element->element_names, 0);
-            fresh       = duplicate_element((xml_ns_t *)g_hash_table_lookup(elements, curr_name));
+            fresh       = duplicate_element((xml_ns_t *)wmem_map_lookup(elements, curr_name));
             fresh->fqn  = fully_qualified_name(hier, curr_name, root_name);
 
             add_xml_field(hfs, &(fresh->hf_tag), curr_name, fresh->fqn);
@@ -1198,14 +1573,14 @@ static void register_dtd(dtd_build_data_t *dtd_data, GString *errors)
             d.basename = fresh->fqn;
             d.hf = hfs;
 
-            g_hash_table_foreach(fresh->attributes, add_xml_attribute_names, &d);
+            wmem_map_foreach(fresh->attributes, add_xml_attribute_names, &d);
 
             ett_p = &fresh->ett;
             g_array_append_val(etts, ett_p);
 
             g_ptr_array_free(fresh->element_names, TRUE);
 
-            g_hash_table_insert(root_element->elements, (gpointer)fresh->name, fresh);
+            wmem_map_insert(root_element->elements, (gpointer)fresh->name, fresh);
         }
     }
 
@@ -1219,39 +1594,37 @@ static void register_dtd(dtd_build_data_t *dtd_data, GString *errors)
      */
     if( dtd_data->proto_name ) {
         gint *ett_p;
+        gchar *full_name, *short_name;
 
-        if ( ! dtd_data->description) {
-            dtd_data->description = wmem_strdup(wmem_epan_scope(), root_name);
+        if (dtd_data->description) {
+            full_name = wmem_strdup(wmem_epan_scope(), dtd_data->description);
+        } else {
+            full_name = wmem_strdup(wmem_epan_scope(), root_name);
         }
+        short_name = wmem_strdup(wmem_epan_scope(), dtd_data->proto_name);
 
         ett_p = &root_element->ett;
         g_array_append_val(etts, ett_p);
 
         add_xml_field(hfs, &root_element->hf_cdata, root_element->name, root_element->fqn);
 
-        root_element->hf_tag = proto_register_protocol(dtd_data->description,
-                                                       dtd_data->proto_name,
-                                                       dtd_data->proto_name);
+        root_element->hf_tag = proto_register_protocol(full_name, short_name, short_name);
         proto_register_field_array(root_element->hf_tag, (hf_register_info*)wmem_array_get_raw(hfs), wmem_array_get_count(hfs));
         proto_register_subtree_array((gint **)g_array_data(etts), etts->len);
 
         if (dtd_data->media_type) {
-            g_hash_table_insert(media_types, dtd_data->media_type, root_element);
-            dtd_data->media_type = NULL;
+            gchar* media_type = wmem_strdup(wmem_epan_scope(), dtd_data->media_type);
+            wmem_map_insert(media_types, media_type, root_element);
         }
 
-        dtd_data->description = NULL;
-        dtd_data->proto_name  = NULL;
         g_array_free(etts, TRUE);
     }
 
-    g_hash_table_insert(xml_ns.elements, (gpointer)root_element->name, root_element);
-
-    g_hash_table_foreach_remove(elements, free_elements, NULL);
-    g_hash_table_destroy(elements);
+    wmem_map_insert(xml_ns.elements, root_element->name, root_element);
+    wmem_map_foreach(elements, free_elements, NULL);
 
     destroy_dtd_data(dtd_data);
-    g_free(root_name);
+    wmem_free(wmem_epan_scope(), root_name);
 }
 
 #  define DIRECTORY_T GDir
@@ -1263,27 +1636,22 @@ static void register_dtd(dtd_build_data_t *dtd_data, GString *errors)
 
 static void init_xml_names(void)
 {
-    xml_ns_t     *xmlpi_xml_ns;
     guint         i;
     DIRECTORY_T  *dir;
     const FILE_T *file;
     const gchar  *filename;
     gchar        *dirname;
 
-    GError **dummy = (GError **)g_malloc(sizeof(GError *));
+    GError **dummy = wmem_new(wmem_epan_scope(), GError *);
     *dummy = NULL;
 
-    xmpli_names = g_hash_table_new(g_str_hash, g_str_equal);
-    media_types = g_hash_table_new(g_str_hash, g_str_equal);
-
-    unknown_ns.elements = xml_ns.elements = g_hash_table_new(g_str_hash, g_str_equal);
-    unknown_ns.attributes = xml_ns.attributes = g_hash_table_new(g_str_hash, g_str_equal);
-
-    xmlpi_xml_ns = xml_new_namespace(xmpli_names, "xml", "version", "encoding", "standalone", NULL);
+    xmpli_names = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
+    media_types = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
 
-    g_hash_table_destroy(xmlpi_xml_ns->elements);
-    xmlpi_xml_ns->elements = NULL;
+    unknown_ns.elements = xml_ns.elements = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
+    unknown_ns.attributes = xml_ns.attributes = wmem_map_new(wmem_epan_scope(), g_str_hash, g_str_equal);
 
+    xml_new_namespace(xmpli_names, "xml", "version", "encoding", "standalone", NULL);
 
     dirname = get_persconffile_path("dtds", FALSE);
 
@@ -1344,22 +1712,14 @@ static void init_xml_names(void)
     g_free(dirname);
 
     for(i=0;i<array_length(default_media_types);i++) {
-        if( ! g_hash_table_lookup(media_types, default_media_types[i]) ) {
-            g_hash_table_insert(media_types, (gpointer)default_media_types[i], &xml_ns);
+        if( ! wmem_map_lookup(media_types, default_media_types[i]) ) {
+            wmem_map_insert(media_types, (gpointer)default_media_types[i], &xml_ns);
         }
     }
 
-    g_hash_table_foreach(xmpli_names, add_xmlpi_namespace, (gpointer)"xml.xmlpi");
+    wmem_map_foreach(xmpli_names, add_xmlpi_namespace, (gpointer)"xml.xmlpi");
 
-    g_free(dummy);
-}
-
-static void apply_prefs(void)
-{
-    dissector_delete_uint_range("tcp.port", xml_tcp_range, xml_handle);
-    g_free(xml_tcp_range);
-    xml_tcp_range = range_copy(global_xml_tcp_range);
-    dissector_add_uint_range("tcp.port", xml_tcp_range, xml_handle);
+    wmem_free(wmem_epan_scope(), dummy);
 }
 
 void
@@ -1378,6 +1738,11 @@ proto_register_xml(void)
            FT_STRING, BASE_NONE, NULL, 0,
            NULL, HFILL }
         },
+        { &hf_cdatasection,
+          {"CDATASection", "xml.cdatasection",
+           FT_STRING, BASE_NONE, NULL, 0,
+           NULL, HFILL }
+        },
         { &hf_comment,
           {"Comment", "xml.comment",
            FT_STRING, BASE_NONE, NULL, 0,
@@ -1439,12 +1804,9 @@ proto_register_xml(void)
     expert_xml = expert_register_protocol(xml_ns.hf_tag);
     expert_register_field_array(expert_xml, ei, array_length(ei));
 
-    xml_module = prefs_register_protocol(xml_ns.hf_tag, apply_prefs);
+    xml_module = prefs_register_protocol(xml_ns.hf_tag, NULL);
     prefs_register_obsolete_preference(xml_module, "heuristic");
     prefs_register_obsolete_preference(xml_module, "heuristic_tcp");
-    prefs_register_range_preference(xml_module, "tcp.port", "TCP Ports",
-                                    "TCP Ports range",
-                                    &global_xml_tcp_range, 65535);
     prefs_register_obsolete_preference(xml_module, "heuristic_udp");
     /* XXX - UCS-2, or UTF-16? */
     prefs_register_bool_preference(xml_module, "heuristic_unicode", "Use Unicode in heuristics",
@@ -1453,13 +1815,9 @@ proto_register_xml(void)
 
     g_array_free(ett_arr, TRUE);
 
-    register_dissector("xml", dissect_xml, xml_ns.hf_tag);
+    xml_handle = register_dissector("xml", dissect_xml, xml_ns.hf_tag);
 
     init_xml_parser();
-
-    xml_tcp_range = range_empty();
-
-
 }
 
 static void
@@ -1471,9 +1829,10 @@ add_dissector_media(gpointer k, gpointer v _U_, gpointer p _U_)
 void
 proto_reg_handoff_xml(void)
 {
-    xml_handle = find_dissector("xml");
+    wmem_map_foreach(media_types, add_dissector_media, NULL);
+    dissector_add_uint_range_with_preference("tcp.port", "", xml_handle);
 
-    g_hash_table_foreach(media_types, add_dissector_media, NULL);
+    gssapi_handle = find_dissector_add_dependency("gssapi", xml_ns.hf_tag);
 
     heur_dissector_add("http",  dissect_xml_heur, "XML in HTTP", "xml_http", xml_ns.hf_tag, HEURISTIC_DISABLE);
     heur_dissector_add("sip",   dissect_xml_heur, "XML in SIP", "xml_sip", xml_ns.hf_tag, HEURISTIC_DISABLE);