This fix now allows SASL/GSS-API with integrity only to be properly dissected
[metze/wireshark/wip.git] / asn1 / spnego / packet-spnego-template.c
index 9ec5b0fc3ad8f6cb637f7ff7249d5ae7dc7620fd..801ba66de7191ae9dd5d8a0393627151da531ad0 100644 (file)
@@ -7,8 +7,6 @@
  * Copyright 2005, Ronnie Sahlberg (krb decryption)
  * Copyright 2005, Anders Broman (converted to asn2wrs generated dissector)
  *
- * $Id$
- *
  * Wireshark - Network traffic analyzer
  * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
  *
  * 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.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 /* The heimdal code for decryption of GSSAPI wrappers using heimdal comes from
    Heimdal 1.6 and has been modified for wireshark's requirements.
 */
 
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
 
 #include <glib.h>
+
+#include <wsutil/rc4.h>
+
 #include <epan/packet.h>
 #include <epan/asn1.h>
 #include "packet-dcerpc.h"
 #include "packet-gssapi.h"
 #include "packet-kerberos.h"
-#include <epan/crypt/crypt-rc4.h>
 #include <epan/conversation.h>
-#include <epan/emem.h>
+#include <epan/wmem/wmem.h>
 #include <epan/asn1.h>
 
-#include <stdio.h>
 #include <string.h>
 
 #include "packet-ber.h"
 #define PSNAME "SPNEGO"
 #define PFNAME "spnego"
 
+void proto_register_spnego(void);
+void proto_reg_handoff_spnego(void);
+
 /* Initialize the protocol and registered fields */
 static int proto_spnego = -1;
 static int proto_spnego_krb5 = -1;
 
 
-static int hf_spnego = -1;
 static int hf_spnego_wraptoken = -1;
 static int hf_spnego_krb5_oid;
 static int hf_spnego_krb5 = -1;
@@ -89,23 +88,24 @@ gboolean saw_mechanism = FALSE;
 
 
 /* Initialize the subtree pointers */
-static gint ett_spnego;
-static gint ett_spnego_wraptoken;
+static gint ett_spnego = -1;
+static gint ett_spnego_wraptoken = -1;
 static gint ett_spnego_krb5 = -1;
 static gint ett_spnego_krb5_cfx_flags = -1;
 
 #include "packet-spnego-ett.c"
 
-static dissector_handle_t data_handle;
-
 /*
- * Unfortunately, we have to have a forward declaration of this,
+ * Unfortunately, we have to have forward declarations of thess,
  * as the code generated by asn2wrs includes a call before the
  * definition.
  */
-static int dissect_spnego_PrincipalSeq(gboolean implicit_tag, tvbuff_t *tvb,
+static int dissect_spnego_NegTokenInit(gboolean implicit_tag, tvbuff_t *tvb,
                                        int offset, asn1_ctx_t *actx _U_,
                                        proto_tree *tree, int hf_index);
+static int dissect_spnego_NegTokenInit2(gboolean implicit_tag, tvbuff_t *tvb,
+                                        int offset, asn1_ctx_t *actx _U_,
+                                        proto_tree *tree, int hf_index);
 
 #include "packet-spnego-fn.c"
 /*
@@ -183,9 +183,8 @@ dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        int offset = 0;
        guint16 token_id;
        const char *oid;
-       gssapi_oid_value *value;
        tvbuff_t *krb5_tvb;
-       gint8 class;
+       gint8 ber_class;
        gboolean pc, ind = 0;
        gint32 tag;
        guint32 len;
@@ -193,7 +192,7 @@ dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
 
        item = proto_tree_add_item(tree, hf_spnego_krb5, tvb, offset,
-                                  -1, FALSE);
+                                  -1, ENC_NA);
 
        subtree = proto_item_add_subtree(item, ett_spnego_krb5);
 
@@ -227,12 +226,12 @@ dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        /*
         * Get the first header ...
         */
-       get_ber_identifier(tvb, offset, &class, &pc, &tag);
-       if (class == BER_CLASS_APP && pc) {
+       get_ber_identifier(tvb, offset, &ber_class, &pc, &tag);
+       if (ber_class == BER_CLASS_APP && pc) {
            /*
             * [APPLICATION <tag>]
             */
-           offset = dissect_ber_identifier(pinfo, subtree, tvb, offset, &class, &pc, &tag);
+           offset = dissect_ber_identifier(pinfo, subtree, tvb, offset, &ber_class, &pc, &tag);
            offset = dissect_ber_length(pinfo, subtree, tvb, offset, &len, &ind);
 
            switch (tag) {
@@ -245,8 +244,6 @@ dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                /* Next, the OID */
                offset=dissect_ber_object_identifier_str(FALSE, &asn1_ctx, subtree, tvb, offset, hf_spnego_krb5_oid, &oid);
 
-               value = gssapi_lookup_oid_str(oid);
-
                token_id = tvb_get_letohs(tvb, offset);
                proto_tree_add_uint(subtree, hf_spnego_krb5_tok_id, tvb, offset, 2,
                                    token_id);
@@ -261,13 +258,13 @@ dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                 * No token ID - just dissect as a Kerberos message and
                 * return.
                 */
-               offset = dissect_kerberos_main(tvb, pinfo, subtree, FALSE, NULL);
+               dissect_kerberos_main(tvb, pinfo, subtree, FALSE, NULL);
                return;
 
            default:
                proto_tree_add_text(subtree, tvb, offset, 0,
                        "Unknown header (class=%d, pc=%d, tag=%d)",
-                       class, pc, tag);
+                       ber_class, pc, tag);
                goto done;
            }
        } else {
@@ -285,7 +282,7 @@ dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        case KRB_TOKEN_AP_REQ:
        case KRB_TOKEN_AP_REP:
        case KRB_TOKEN_AP_ERR:
-         krb5_tvb = tvb_new_subset(tvb, offset, -1, -1);
+         krb5_tvb = tvb_new_subset_remaining(tvb, offset);
          offset = dissect_kerberos_main(krb5_tvb, pinfo, subtree, FALSE, NULL);
          break;
 
@@ -320,7 +317,7 @@ dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 }
 
 #ifdef HAVE_KERBEROS
-#include <epan/crypt/crypt-md5.h>
+#include <wsutil/md5.h>
 
 #ifndef KEYTYPE_ARCFOUR_56
 # define KEYTYPE_ARCFOUR_56 24
@@ -331,9 +328,9 @@ dissect_spnego_krb5(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 #endif
 
 static int
-arcfour_mic_key(void *key_data, size_t key_size, int key_type,
-               void *cksum_data, size_t cksum_size,
-               void *key6_data)
+arcfour_mic_key(const guint8 *key_data, size_t key_size, int key_type,
+               const guint8 *cksum_data, size_t cksum_size,
+               guint8 *key6_data)
 {
     guint8 k5_data[16];
     guint8 T[4];
@@ -348,14 +345,14 @@ arcfour_mic_key(void *key_data, size_t key_size, int key_type,
                 L40, 14,
                 key_data,
                 key_size,
-               k5_data);
+               k5_data);
        memset(&k5_data[7], 0xAB, 9);
     } else {
        md5_hmac(
                 T, 4,
                 key_data,
                 key_size,
-               k5_data);
+               k5_data);
     }
 
     md5_hmac(
@@ -387,17 +384,17 @@ usage2arcfour(int usage)
 
 static int
 arcfour_mic_cksum(guint8 *key_data, int key_length,
-                 unsigned usage,
+                 unsigned int usage,
                  guint8 sgn_cksum[8],
-                 const void *v1, size_t l1,
-                 const void *v2, size_t l2,
-                 const void *v3, size_t l3)
+                 const guint8 *v1, size_t l1,
+                 const guint8 *v2, size_t l2,
+                 const guint8 *v3, size_t l3)
 {
-    const guint8 signature[] = "signaturekey";
+    static const guint8 signature[] = "signaturekey";
     guint8 ksign_c[16];
-    unsigned char t[4];
+    guint8 t[4];
     md5_state_t ms;
-    unsigned char digest[16];
+    guint8 digest[16];
     int rc4_usage;
     guint8 cksum[16];
 
@@ -426,12 +423,12 @@ arcfour_mic_cksum(guint8 *key_data, int key_length,
  * Verify padding of a gss wrapped message and return its length.
  */
 static int
-gssapi_verify_pad(unsigned char *wrapped_data, int wrapped_length,
-                  size_t datalen,
-                  size_t *padlen)
+gssapi_verify_pad(guint8 *wrapped_data, int wrapped_length,
+                  int datalen,
+                  int *padlen)
 {
-    unsigned char *pad;
-    size_t padlength;
+    guint8 *pad;
+    int padlength;
     int i;
 
     pad = wrapped_data + wrapped_length - 1;
@@ -458,15 +455,14 @@ decrypt_arcfour(packet_info *pinfo,
 {
     guint8 Klocaldata[16];
     int ret;
-    gint32 seq_number;
-    size_t datalen;
+    int datalen;
     guint8 k6_data[16];
     guint32 SND_SEQ[2];
     guint8 Confounder[8];
     guint8 cksum_data[8];
     int cmp;
     int conf_flag;
-    size_t padlen = 0;
+    int padlen = 0;
 
     datalen = tvb_length(pinfo->gssapi_encrypted_tvb);
 
@@ -483,7 +479,7 @@ decrypt_arcfour(packet_info *pinfo,
     }
 
     ret = arcfour_mic_key(key_value, key_size, key_type,
-                         (void *)tvb_get_ptr(pinfo->gssapi_wrap_tvb, 16, 8),
+                         tvb_get_ptr(pinfo->gssapi_wrap_tvb, 16, 8),
                          8, /* SGN_CKSUM */
                          k6_data);
     if (ret) {
@@ -494,13 +490,12 @@ decrypt_arcfour(packet_info *pinfo,
        rc4_state_struct rc4_state;
 
        crypt_rc4_init(&rc4_state, k6_data, sizeof(k6_data));
-       memcpy(SND_SEQ, (unsigned char *)tvb_get_ptr(pinfo->gssapi_wrap_tvb, 8, 8), 8);
-       crypt_rc4(&rc4_state, (unsigned char *)SND_SEQ, 8);
+       tvb_memcpy(pinfo->gssapi_wrap_tvb, SND_SEQ, 8, 8);
+       crypt_rc4(&rc4_state, (guint8 *)SND_SEQ, 8);
 
        memset(k6_data, 0, sizeof(k6_data));
     }
 
-    seq_number=g_ntohl(SND_SEQ[0]);
 
     if (SND_SEQ[1] != 0xFFFFFFFF && SND_SEQ[1] != 0x00000000) {
        return -6;
@@ -513,7 +508,7 @@ decrypt_arcfour(packet_info *pinfo,
            Klocaldata[i] = ((guint8 *)key_value)[i] ^ 0xF0;
     }
     ret = arcfour_mic_key(Klocaldata,sizeof(Klocaldata),key_type,
-                         (unsigned char *)SND_SEQ, 4,
+                         (const guint8 *)SND_SEQ, 4,
                          k6_data);
     memset(Klocaldata, 0, sizeof(Klocaldata));
     if (ret) {
@@ -524,14 +519,12 @@ decrypt_arcfour(packet_info *pinfo,
        rc4_state_struct rc4_state;
 
        crypt_rc4_init(&rc4_state, k6_data, sizeof(k6_data));
-       memcpy(Confounder, (unsigned char *)tvb_get_ptr(pinfo->gssapi_wrap_tvb, 24, 8), 8);
+       tvb_memcpy(pinfo->gssapi_wrap_tvb, Confounder, 24, 8);
        crypt_rc4(&rc4_state, Confounder, 8);
        memcpy(output_message_buffer, input_message_buffer, datalen);
        crypt_rc4(&rc4_state, output_message_buffer, datalen);
     } else {
-       memcpy(Confounder,
-               tvb_get_ptr(pinfo->gssapi_wrap_tvb, 24, 8),
-               8); /* Confounder */
+       tvb_memcpy(pinfo->gssapi_wrap_tvb, Confounder, 24, 8);
        memcpy(output_message_buffer,
                input_message_buffer,
                datalen);
@@ -560,9 +553,7 @@ decrypt_arcfour(packet_info *pinfo,
            return -10;
        }
 
-       cmp = memcmp(cksum_data,
-           tvb_get_ptr(pinfo->gssapi_wrap_tvb, 16, 8),
-           8); /* SGN_CKSUM */
+       cmp = tvb_memeql(pinfo->gssapi_wrap_tvb, 16, cksum_data, 8); /* SGN_CKSUM */
        if (cmp) {
            return -11;
        }
@@ -583,18 +574,9 @@ decrypt_gssapi_krb_arcfour_wrap(proto_tree *tree, packet_info *pinfo, tvbuff_t *
        int length;
        const guint8 *original_data;
 
-       static int omb_index=0;
-       static guint8 *omb_arr[4]={NULL,NULL,NULL,NULL};
-       static guint8 *cryptocopy=NULL; /* workaround for pre-0.6.1 heimdal bug */
+       guint8 *cryptocopy=NULL; /* workaround for pre-0.6.1 heimdal bug */
        guint8 *output_message_buffer;
 
-       omb_index++;
-       if(omb_index>=4){
-               omb_index=0;
-       }
-       output_message_buffer=omb_arr[omb_index];
-
-
        length=tvb_length(pinfo->gssapi_encrypted_tvb);
        original_data=tvb_get_ptr(pinfo->gssapi_encrypted_tvb, 0, length);
 
@@ -607,12 +589,8 @@ decrypt_gssapi_krb_arcfour_wrap(proto_tree *tree, packet_info *pinfo, tvbuff_t *
        /* XXX we should only do this for first time, then store somewhere */
        /* XXX We also need to re-read the keytab when the preference changes */
 
-       cryptocopy=ep_alloc(length);
-       if(output_message_buffer){
-               g_free(output_message_buffer);
-               output_message_buffer=NULL;
-       }
-       output_message_buffer=g_malloc(length);
+       cryptocopy=(guint8 *)wmem_alloc(wmem_packet_scope(), length);
+       output_message_buffer=(guint8 *)wmem_alloc(pinfo->pool, length);
 
        for(ek=enc_key_list;ek;ek=ek->next){
                /* shortcircuit and bail out if enctypes are not matching */
@@ -636,10 +614,9 @@ decrypt_gssapi_krb_arcfour_wrap(proto_tree *tree, packet_info *pinfo, tvbuff_t *
                                            );
                if (ret >= 0) {
                        proto_tree_add_text(tree, NULL, 0, 0, "[Decrypted using: %s]", ek->key_origin);
-                       pinfo->gssapi_decrypted_tvb=tvb_new_real_data(
+                       pinfo->gssapi_decrypted_tvb=tvb_new_child_real_data(tvb,
                                output_message_buffer,
                                ret, ret);
-                       tvb_set_child_real_data_tvbuff(tvb, pinfo->gssapi_decrypted_tvb);
                        add_new_data_source(pinfo, pinfo->gssapi_decrypted_tvb, "Decrypted GSS-Krb5");
                        return;
                }
@@ -649,9 +626,9 @@ decrypt_gssapi_krb_arcfour_wrap(proto_tree *tree, packet_info *pinfo, tvbuff_t *
 
 /* borrowed from heimdal */
 static int
-rrc_rotate(void *data, int len, guint16 rrc, int unrotate)
+rrc_rotate(guint8 *data, int len, guint16 rrc, int unrotate)
 {
-       u_char *tmp, buf[256];
+       guint8 *tmp, buf[256];
        size_t left;
 
        if (len == 0)
@@ -667,23 +644,23 @@ rrc_rotate(void *data, int len, guint16 rrc, int unrotate)
        if (rrc <= sizeof(buf)) {
                tmp = buf;
        } else {
-               tmp = malloc(rrc);
+               tmp = (guint8 *)g_malloc(rrc);
                if (tmp == NULL)
                        return -1;
        }
 
        if (unrotate) {
                memcpy(tmp, data, rrc);
-               memmove(data, (u_char *)data + rrc, left);
-               memcpy((u_char *)data + left, tmp, rrc);
+               memmove(data, data + rrc, left);
+               memcpy(data + left, tmp, rrc);
        } else {
-               memcpy(tmp, (u_char *)data + left, rrc);
-               memmove((u_char *)data + rrc, data, left);
+               memcpy(tmp, data + left, rrc);
+               memmove(data + rrc, data, left);
                memcpy(data, tmp, rrc);
        }
 
        if (rrc > sizeof(buf))
-               free(tmp);
+               g_free(tmp);
 
        return 0;
 }
@@ -695,39 +672,60 @@ rrc_rotate(void *data, int len, guint16 rrc, int unrotate)
 #define KRB5_KU_USAGE_INITIATOR_SIGN   25
 
 static void
-decrypt_gssapi_krb_cfx_wrap(proto_tree *tree _U_, packet_info *pinfo _U_, tvbuff_t *tvb _U_, guint16 ec _U_, guint16 rrc _U_, int keytype, unsigned int usage)
+decrypt_gssapi_krb_cfx_wrap(proto_tree *tree _U_,
+                           packet_info *pinfo,
+                           tvbuff_t *checksum_tvb,
+                           tvbuff_t *encrypted_tvb,
+                           guint16 ec,
+                           guint16 rrc,
+                           gboolean is_dce,
+                           int keytype,
+                           unsigned int usage)
 {
-       int res;
-       char *rotated;
-       char *output;
+       guint8 *rotated;
+       guint8 *output;
        int datalen;
+       tvbuff_t *next_tvb;
 
        /* dont do anything if we are not attempting to decrypt data */
        if(!krb_decrypt){
                return;
        }
 
-       rotated = ep_alloc(tvb_length(tvb));
+       datalen = tvb_length(checksum_tvb) + tvb_length(encrypted_tvb);
 
-       tvb_memcpy(tvb, rotated, 0, tvb_length(tvb));
-       res = rrc_rotate(rotated, tvb_length(tvb), rrc, TRUE);
+       rotated = (guint8 *)wmem_alloc(pinfo->pool, datalen);
 
-       output = decrypt_krb5_data(tree, pinfo, usage, tvb_length(tvb),
-                 rotated, keytype, &datalen);
+       tvb_memcpy(checksum_tvb, rotated,
+                  0, tvb_length(checksum_tvb));
+       tvb_memcpy(encrypted_tvb, rotated + tvb_length(checksum_tvb),
+                  0, tvb_length(encrypted_tvb));
+
+       if (is_dce) {
+               rrc += ec;
+       }
+
+       rrc_rotate(rotated, datalen, rrc, TRUE);
+
+       next_tvb=tvb_new_child_real_data(encrypted_tvb, rotated,
+                                        datalen, datalen);
+       add_new_data_source(pinfo, next_tvb, "GSSAPI CFX");
+
+       output = decrypt_krb5_data(tree, pinfo, usage, next_tvb,
+                 keytype, &datalen);
 
        if (output) {
-               char *outdata;
+               guint8 *outdata;
 
-               outdata = ep_alloc(tvb_length(tvb));
-               memcpy(outdata, output, tvb_length(tvb));
+               outdata = (guint8 *)g_memdup(output, tvb_length(encrypted_tvb));
                g_free(output);
 
-               pinfo->gssapi_decrypted_tvb=tvb_new_real_data(
+               pinfo->gssapi_decrypted_tvb=tvb_new_child_real_data(encrypted_tvb,
                        outdata,
-                       datalen-16,
-                       datalen-16);
-               tvb_set_child_real_data_tvbuff(tvb, pinfo->gssapi_decrypted_tvb);
+                       tvb_length(encrypted_tvb),
+                       tvb_length(encrypted_tvb));
                add_new_data_source(pinfo, pinfo->gssapi_decrypted_tvb, "Decrypted GSS-Krb5");
+               tvb_set_free_cb(pinfo->gssapi_decrypted_tvb, g_free);
                return;
        }
        return;
@@ -784,14 +782,14 @@ dissect_spnego_krb5_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo
        /* Encrypted sequence number */
 
        proto_tree_add_item(tree, hf_spnego_krb5_snd_seq, tvb, offset, 8,
-                           TRUE);
+                           ENC_NA);
 
        offset += 8;
 
        /* Checksum of plaintext padded data */
 
        proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset, 8,
-                           TRUE);
+                           ENC_NA);
 
        offset += 8;
 
@@ -808,7 +806,7 @@ dissect_spnego_krb5_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo
               we may need to make this an option. gal 17/2/06 */
            (sgn_alg == KRB_SGN_ALG_DES_MAC_MD5)) {
          proto_tree_add_item(tree, hf_spnego_krb5_confounder, tvb, offset, 8,
-                             TRUE);
+                             ENC_NA);
          offset += 8;
        }
 
@@ -897,14 +895,14 @@ dissect_spnego_krb5_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo _U
        /* Encrypted sequence number */
 
        proto_tree_add_item(tree, hf_spnego_krb5_snd_seq, tvb, offset, 8,
-                           TRUE);
+                           ENC_NA);
 
        offset += 8;
 
        /* Checksum of plaintext padded data */
 
        proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset, 8,
-                           TRUE);
+                           ENC_NA);
 
        offset += 8;
 
@@ -922,7 +920,7 @@ dissect_spnego_krb5_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinfo _U
        if (tvb_length_remaining(tvb, offset)) {
          if (sgn_alg == KRB_SGN_ALG_HMAC) {
            proto_tree_add_item(tree, hf_spnego_krb5_confounder, tvb, offset, 8,
-                             TRUE);
+                             ENC_NA);
 
            offset += 8;
          }
@@ -979,7 +977,9 @@ dissect_spnego_krb5_cfx_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo
 {
        guint8 flags;
        guint16 ec;
+#if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
        guint16 rrc;
+#endif
        int checksum_size;
        int start_offset=offset;
 
@@ -999,38 +999,67 @@ dissect_spnego_krb5_cfx_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo
        /* Skip the filler */
 
        proto_tree_add_item(tree, hf_spnego_krb5_filler, tvb, offset, 1,
-                           FALSE);
+                           ENC_NA);
        offset += 1;
 
        /* EC */
        ec = tvb_get_ntohs(tvb, offset);
        proto_tree_add_item(tree, hf_spnego_krb5_cfx_ec, tvb, offset, 2,
-                           FALSE);
+                           ENC_BIG_ENDIAN);
        offset += 2;
 
        /* RRC */
+#if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
        rrc = tvb_get_ntohs(tvb, offset);
+#endif
        proto_tree_add_item(tree, hf_spnego_krb5_cfx_rrc, tvb, offset, 2,
-                           FALSE);
+                           ENC_BIG_ENDIAN);
        offset += 2;
 
        /* sequence number */
 
        proto_tree_add_item(tree, hf_spnego_krb5_cfx_seq, tvb, offset, 8,
-                           FALSE);
+                           ENC_BIG_ENDIAN);
        offset += 8;
 
        /* Checksum of plaintext padded data */
 
        if (pinfo->gssapi_data_encrypted) {
                checksum_size = 44 + ec;
+
+               proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset,
+                                   checksum_size, ENC_NA);
+               offset += checksum_size;
+
        } else {
-               checksum_size = 12;
-       }
+               int inner_token_len = 0;
 
-       proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset,
-                           checksum_size, FALSE);
-       offset += checksum_size;
+               /*
+                * We know we have a wrap token, but we have to let the proto
+                * above us decode that, so hand it back in gssapi_wrap_tvb
+                * and put the checksum in the tree.
+                */
+
+               checksum_size = ec;
+
+               inner_token_len = tvb_reported_length_remaining(tvb, offset) -
+                                       ec;
+
+               pinfo->gssapi_wrap_tvb = tvb_new_subset(tvb, offset,
+                                               inner_token_len, inner_token_len);
+
+               offset += inner_token_len;
+
+               proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset,
+                                   checksum_size, ENC_NA);
+
+               /*
+                * Return an offset that puts our caller before the inner
+                * token. This is better than before, but we still see the
+                * checksum included in the LDAP query at times.
+                */
+               return offset - inner_token_len;
+       }
 
        if(pinfo->decrypt_gssapi_tvb){
                /* if the caller did not provide a tvb, then we just use
@@ -1063,21 +1092,25 @@ dissect_spnego_krb5_cfx_wrap_base(tvbuff_t *tvb, int offset, packet_info *pinfo
        }
 
 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
-       pinfo->gssapi_encrypted_tvb = tvb_new_subset(tvb, 16, -1, -1);
+{
+       tvbuff_t *checksum_tvb = tvb_new_subset(tvb, 16, checksum_size, checksum_size);
 
-       if (flags & 0x0002) {
+       if (pinfo->gssapi_data_encrypted) {
                if(pinfo->gssapi_encrypted_tvb){
                        decrypt_gssapi_krb_cfx_wrap(tree,
                                pinfo,
+                               checksum_tvb,
                                pinfo->gssapi_encrypted_tvb,
                                ec,
                                rrc,
+                               (pinfo->decrypt_gssapi_tvb==DECRYPT_GSSAPI_DCE)?TRUE:FALSE,
                                -1,
                                (flags & 0x0001)?
                                KRB5_KU_USAGE_ACCEPTOR_SEAL:
                                KRB5_KU_USAGE_INITIATOR_SEAL);
                }
        }
+}
 #endif /* HAVE_HEIMDAL_KERBEROS || HAVE_MIT_KERBEROS */
 
        /*
@@ -1113,13 +1146,13 @@ dissect_spnego_krb5_cfx_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinf
        /* Skip the filler */
 
        proto_tree_add_item(tree, hf_spnego_krb5_filler, tvb, offset, 5,
-                           FALSE);
+                           ENC_NA);
        offset += 5;
 
        /* sequence number */
 
        proto_tree_add_item(tree, hf_spnego_krb5_cfx_seq, tvb, offset, 8,
-                           FALSE);
+                           ENC_BIG_ENDIAN);
        offset += 8;
 
        /* Checksum of plaintext padded data */
@@ -1127,7 +1160,7 @@ dissect_spnego_krb5_cfx_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinf
        checksum_size = tvb_length_remaining(tvb, offset);
 
        proto_tree_add_item(tree, hf_spnego_krb5_sgn_cksum, tvb, offset,
-                           checksum_size, FALSE);
+                           checksum_size, ENC_NA);
        offset += checksum_size;
 
        /*
@@ -1148,14 +1181,14 @@ dissect_spnego_krb5_cfx_getmic_base(tvbuff_t *tvb, int offset, packet_info *pinf
  * getting it accepted.
  */
 static int
-dissect_spnego_krb5_wrap(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+dissect_spnego_krb5_wrap(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
 {
        proto_item *item;
        proto_tree *subtree;
        int offset = 0;
        guint16 token_id;
 
-       item = proto_tree_add_item(tree, hf_spnego_krb5, tvb, 0, -1, FALSE);
+       item = proto_tree_add_item(tree, hf_spnego_krb5, tvb, 0, -1, ENC_NA);
 
        subtree = proto_item_add_subtree(item, ett_spnego_krb5);
 
@@ -1208,7 +1241,7 @@ dissect_spnego_krb5_wrap(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree
 /* Spnego stuff from here */
 
 static int
-dissect_spnego_wrap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+dissect_spnego_wrap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
 {
        proto_item *item;
        proto_tree *subtree;
@@ -1216,7 +1249,7 @@ dissect_spnego_wrap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        asn1_ctx_t asn1_ctx;
        asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
 
-
+       MechType_oid = NULL;
 
        /*
         * We need this later, so lets get it now ...
@@ -1225,8 +1258,8 @@ dissect_spnego_wrap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
         */
 
 
-       item = proto_tree_add_item(tree, hf_spnego, tvb, offset,
-                                  -1, FALSE);
+       item = proto_tree_add_item(tree, proto_spnego, tvb, offset,
+                                  -1, ENC_NA);
 
        subtree = proto_item_add_subtree(item, ett_spnego);
        /*
@@ -1258,7 +1291,7 @@ dissect_spnego(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
         * It has to be per-frame as there can be more than one GSS-API
         * negotiation in a conversation.
         */
-       next_level_value = p_get_proto_data(pinfo->fd, proto_spnego);
+       next_level_value = (gssapi_oid_value *)p_get_proto_data(wmem_file_scope(), pinfo, proto_spnego, 0);
        if (!next_level_value && !pinfo->fd->flags.visited) {
            /*
             * No handle attached to this frame, but it's the first
@@ -1271,15 +1304,15 @@ dissect_spnego(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
                                             pinfo->destport, 0);
 
            if (conversation) {
-               next_level_value = conversation_get_proto_data(conversation,
+               next_level_value = (gssapi_oid_value *)conversation_get_proto_data(conversation,
                                                               proto_spnego);
                if (next_level_value)
-                   p_add_proto_data(pinfo->fd, proto_spnego, next_level_value);
+                   p_add_proto_data(wmem_file_scope(), pinfo, proto_spnego, 0, next_level_value);
            }
        }
 
-       item = proto_tree_add_item(parent_tree, hf_spnego, tvb, offset,
-                                  -1, FALSE);
+       item = proto_tree_add_item(parent_tree, proto_spnego, tvb, offset,
+                                  -1, ENC_NA);
 
        subtree = proto_item_add_subtree(item, ett_spnego);
 
@@ -1310,7 +1343,7 @@ dissect_spnego(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
         * as well. Naughty, naughty.
         *
         */
-       offset = dissect_spnego_NegotiationToken(FALSE, tvb, offset, &asn1_ctx, subtree, -1);
+       dissect_spnego_NegotiationToken(FALSE, tvb, offset, &asn1_ctx, subtree, -1);
 
 }
 
@@ -1319,19 +1352,16 @@ void proto_register_spnego(void) {
 
        /* List of fields */
        static hf_register_info hf[] = {
-               { &hf_spnego,
-                 { "SPNEGO", "spnego", FT_NONE, BASE_NONE, NULL, 0x0,
-                   "SPNEGO", HFILL }},
                { &hf_spnego_wraptoken,
                  { "wrapToken", "spnego.wraptoken",
                    FT_NONE, BASE_NONE, NULL, 0x0, "SPNEGO wrapToken",
                    HFILL}},
                { &hf_spnego_krb5,
                  { "krb5_blob", "spnego.krb5.blob", FT_BYTES,
-                   BASE_NONE, NULL, 0, "krb5_blob", HFILL }},
+                   BASE_NONE, NULL, 0, NULL, HFILL }},
                { &hf_spnego_krb5_oid,
                  { "KRB5 OID", "spnego.krb5_oid", FT_STRING,
-                   BASE_NONE, NULL, 0, "KRB5 OID", HFILL }},
+                   BASE_NONE, NULL, 0, NULL, HFILL }},
                { &hf_spnego_krb5_tok_id,
                  { "krb5_tok_id", "spnego.krb5.tok_id", FT_UINT16, BASE_HEX,
                    VALS(spnego_krb5_tok_id_vals), 0, "KRB5 Token Id", HFILL}},
@@ -1351,20 +1381,20 @@ void proto_register_spnego(void) {
                  { "krb5_confounder", "spnego.krb5.confounder", FT_BYTES, BASE_NONE,
                    NULL, 0, "KRB5 Confounder", HFILL}},
                { &hf_spnego_krb5_filler,
-                 { "krb5_filler", "spnego.krb5.filler", FT_BYTES, BASE_HEX,
+                 { "krb5_filler", "spnego.krb5.filler", FT_BYTES, BASE_NONE,
                    NULL, 0, "KRB5 Filler", HFILL}},
                { &hf_spnego_krb5_cfx_flags,
                  { "krb5_cfx_flags", "spnego.krb5.cfx_flags", FT_UINT8, BASE_HEX,
                    NULL, 0, "KRB5 CFX Flags", HFILL}},
                { &hf_spnego_krb5_cfx_flags_01,
                  { "SendByAcceptor", "spnego.krb5.send_by_acceptor", FT_BOOLEAN, 8,
-                   TFS (&flags_set_truth), 0x01, "", HFILL}},
+                   TFS (&tfs_set_notset), 0x01, NULL, HFILL}},
                { &hf_spnego_krb5_cfx_flags_02,
                  { "Sealed", "spnego.krb5.sealed", FT_BOOLEAN, 8,
-                   TFS (&flags_set_truth), 0x02, "", HFILL}},
+                   TFS (&tfs_set_notset), 0x02, NULL, HFILL}},
                { &hf_spnego_krb5_cfx_flags_04,
                  { "AcceptorSubkey", "spnego.krb5.acceptor_subkey", FT_BOOLEAN, 8,
-                   TFS (&flags_set_truth), 0x04, "", HFILL}},
+                   TFS (&tfs_set_notset), 0x04, NULL, HFILL}},
                { &hf_spnego_krb5_cfx_ec,
                  { "krb5_cfx_ec", "spnego.krb5.cfx_ec", FT_UINT16, BASE_DEC,
                    NULL, 0, "KRB5 CFX Extra Count", HFILL}},
@@ -1414,9 +1444,8 @@ void proto_reg_handoff_spnego(void) {
 
        /* Register protocol with GSS-API module */
 
-       spnego_handle = create_dissector_handle(dissect_spnego, proto_spnego);
-       spnego_wrap_handle = new_create_dissector_handle(dissect_spnego_wrap,
-                                                        proto_spnego);
+        spnego_handle = find_dissector("spnego");
+       spnego_wrap_handle = new_create_dissector_handle(dissect_spnego_wrap,  proto_spnego);
        gssapi_init_oid("1.3.6.1.5.5.2", proto_spnego, ett_spnego,
            spnego_handle, spnego_wrap_handle,
            "SPNEGO - Simple Protected Negotiation");
@@ -1430,10 +1459,8 @@ void proto_reg_handoff_spnego(void) {
         * See the archive of <ietf-krb-wg@anl.gov> for the thread topic
         * SPNEGO implementation issues. 3-Dec-2002.
         */
-       spnego_krb5_handle = create_dissector_handle(dissect_spnego_krb5,
-                                                    proto_spnego_krb5);
-       spnego_krb5_wrap_handle = new_create_dissector_handle(dissect_spnego_krb5_wrap,
-                                                             proto_spnego_krb5);
+        spnego_krb5_handle = find_dissector("spnego-krb5");
+       spnego_krb5_wrap_handle = find_dissector("spnego-krb5-wrap");
        gssapi_init_oid("1.2.840.48018.1.2.2", proto_spnego_krb5, ett_spnego_krb5,
                        spnego_krb5_handle, spnego_krb5_wrap_handle,
                        "MS KRB5 - Microsoft Kerberos 5");
@@ -1444,8 +1471,4 @@ void proto_reg_handoff_spnego(void) {
                        spnego_krb5_handle, spnego_krb5_wrap_handle,
                        "KRB5 - Kerberos 5 - User to User");
 
-       /*
-        * Find the data handle for some calls
-        */
-       data_handle = find_dissector("data");
 }