For proto_tree_add_item(..., proto_xxx, ...)use ENC_NA as the encoding arg.
[obnox/wireshark/wip.git] / epan / dissectors / packet-ntlmssp.c
index 2a92862978370b913b9f6ae60cf3ba1e93698b11..abba774efb95028cd32db55c16d00a488200ad77 100644 (file)
@@ -53,7 +53,7 @@
 #include <epan/crypt/crypt-des.h>
 #include "packet-dcerpc.h"
 #include "packet-gssapi.h"
-#include <epan/crc32.h>
+#include <wsutil/crc32.h>
 
 #include "packet-ntlmssp.h"
 
@@ -75,8 +75,8 @@ static int ntlmssp_tap = -1;
 static const value_string ntlmssp_message_types[] = {
   { NTLMSSP_NEGOTIATE, "NTLMSSP_NEGOTIATE" },
   { NTLMSSP_CHALLENGE, "NTLMSSP_CHALLENGE" },
-  { NTLMSSP_AUTH, "NTLMSSP_AUTH" },
-  { NTLMSSP_UNKNOWN, "NTLMSSP_UNKNOWN" },
+  { NTLMSSP_AUTH,      "NTLMSSP_AUTH" },
+  { NTLMSSP_UNKNOWN,   "NTLMSSP_UNKNOWN" },
   { 0, NULL }
 };
 
@@ -93,13 +93,13 @@ static GHashTable* hash_packet = NULL;
  *
  * See also
  *
- *     http://davenport.sourceforge.net/ntlm.html
+ *      http://davenport.sourceforge.net/ntlm.html
  *
  * although that document says that:
  *
- *     0x00010000 is "Target Type Domain";
- *     0x00020000 is "Target Type Server"
- *     0x00040000 is "Target Type Share";
+ *      0x00010000 is "Target Type Domain";
+ *      0x00020000 is "Target Type Server"
+ *      0x00040000 is "Target Type Share";
  *
  * and that 0x00100000, 0x00200000, and 0x00400000 are
  * "Request Init Response", "Request Accept Response", and
@@ -111,38 +111,38 @@ static GHashTable* hash_packet = NULL;
  * http://msdn2.microsoft.com/en-us/library/cc236621.aspx
  *
  */
-#define NTLMSSP_NEGOTIATE_UNICODE          0x00000001
-#define NTLMSSP_NEGOTIATE_OEM              0x00000002
-#define NTLMSSP_REQUEST_TARGET             0x00000004
-#define NTLMSSP_NEGOTIATE_00000008         0x00000008
-#define NTLMSSP_NEGOTIATE_SIGN             0x00000010
-#define NTLMSSP_NEGOTIATE_SEAL             0x00000020
-#define NTLMSSP_NEGOTIATE_DATAGRAM         0x00000040
-#define NTLMSSP_NEGOTIATE_LM_KEY           0x00000080
-#define NTLMSSP_NEGOTIATE_00000100         0x00000100
-#define NTLMSSP_NEGOTIATE_NTLM             0x00000200
-#define NTLMSSP_NEGOTIATE_NT_ONLY          0x00000400
-#define NTLMSSP_NEGOTIATE_00000800         0x00000800
-#define NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED 0x00001000
+#define NTLMSSP_NEGOTIATE_UNICODE                  0x00000001
+#define NTLMSSP_NEGOTIATE_OEM                      0x00000002
+#define NTLMSSP_REQUEST_TARGET                     0x00000004
+#define NTLMSSP_NEGOTIATE_00000008                 0x00000008
+#define NTLMSSP_NEGOTIATE_SIGN                     0x00000010
+#define NTLMSSP_NEGOTIATE_SEAL                     0x00000020
+#define NTLMSSP_NEGOTIATE_DATAGRAM                 0x00000040
+#define NTLMSSP_NEGOTIATE_LM_KEY                   0x00000080
+#define NTLMSSP_NEGOTIATE_00000100                 0x00000100
+#define NTLMSSP_NEGOTIATE_NTLM                     0x00000200
+#define NTLMSSP_NEGOTIATE_NT_ONLY                  0x00000400
+#define NTLMSSP_NEGOTIATE_00000800                 0x00000800
+#define NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED      0x00001000
 #define NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED 0x00002000
-#define NTLMSSP_NEGOTIATE_00004000         0x00004000
-#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN      0x00008000
-#define NTLMSSP_TARGET_TYPE_DOMAIN         0x00010000
-#define NTLMSSP_TARGET_TYPE_SERVER         0x00020000
-#define NTLMSSP_TARGET_TYPE_SHARE          0x00040000
-#define NTLMSSP_NEGOTIATE_EXTENDED_SECURITY 0x00080000
-#define NTLMSSP_NEGOTIATE_IDENTIFY         0x00100000
-#define NTLMSSP_NEGOTIATE_00200000         0x00200000
-#define NTLMSSP_REQUEST_NON_NT_SESSION     0x00400000
-#define NTLMSSP_NEGOTIATE_TARGET_INFO      0x00800000
-#define NTLMSSP_NEGOTIATE_01000000         0x01000000
-#define NTLMSSP_NEGOTIATE_VERSION          0x02000000
-#define NTLMSSP_NEGOTIATE_04000000         0x04000000
-#define NTLMSSP_NEGOTIATE_08000000         0x08000000
-#define NTLMSSP_NEGOTIATE_10000000         0x10000000
-#define NTLMSSP_NEGOTIATE_128              0x20000000
-#define NTLMSSP_NEGOTIATE_KEY_EXCH         0x40000000
-#define NTLMSSP_NEGOTIATE_56               0x80000000
+#define NTLMSSP_NEGOTIATE_00004000                 0x00004000
+#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN              0x00008000
+#define NTLMSSP_TARGET_TYPE_DOMAIN                 0x00010000
+#define NTLMSSP_TARGET_TYPE_SERVER                 0x00020000
+#define NTLMSSP_TARGET_TYPE_SHARE                  0x00040000
+#define NTLMSSP_NEGOTIATE_EXTENDED_SECURITY        0x00080000
+#define NTLMSSP_NEGOTIATE_IDENTIFY                 0x00100000
+#define NTLMSSP_NEGOTIATE_00200000                 0x00200000
+#define NTLMSSP_REQUEST_NON_NT_SESSION             0x00400000
+#define NTLMSSP_NEGOTIATE_TARGET_INFO              0x00800000
+#define NTLMSSP_NEGOTIATE_01000000                 0x01000000
+#define NTLMSSP_NEGOTIATE_VERSION                  0x02000000
+#define NTLMSSP_NEGOTIATE_04000000                 0x04000000
+#define NTLMSSP_NEGOTIATE_08000000                 0x08000000
+#define NTLMSSP_NEGOTIATE_10000000                 0x10000000
+#define NTLMSSP_NEGOTIATE_128                      0x20000000
+#define NTLMSSP_NEGOTIATE_KEY_EXCH                 0x40000000
+#define NTLMSSP_NEGOTIATE_56                       0x80000000
 
 static int proto_ntlmssp = -1;
 static int hf_ntlmssp_auth = -1;
@@ -204,23 +204,47 @@ static int hf_ntlmssp_string_offset = -1;
 static int hf_ntlmssp_blob_len = -1;
 static int hf_ntlmssp_blob_maxlen = -1;
 static int hf_ntlmssp_blob_offset = -1;
+static int hf_ntlmssp_version = -1;
 static int hf_ntlmssp_version_major = -1;
 static int hf_ntlmssp_version_minor = -1;
 static int hf_ntlmssp_version_build_number = -1;
 static int hf_ntlmssp_version_ntlm_current_revision = -1;
-static int hf_ntlmssp_address_list = -1;
-static int hf_ntlmssp_address_list_len = -1;
-static int hf_ntlmssp_address_list_maxlen = -1;
-static int hf_ntlmssp_address_list_offset = -1;
-static int hf_ntlmssp_address_list_server_nb = -1;
-static int hf_ntlmssp_address_list_domain_nb = -1;
-static int hf_ntlmssp_address_list_server_dns = -1;
-static int hf_ntlmssp_address_list_domain_dns = -1;
-static int hf_ntlmssp_address_list_forest_dns = -1;
-static int hf_ntlmssp_address_list_terminator = -1;
-static int hf_ntlmssp_address_list_item_type = -1;
-static int hf_ntlmssp_address_list_item_len = -1;
-static int hf_ntlmssp_address_list_item_content = -1;
+
+static int hf_ntlmssp_challenge_target_info = -1;
+static int hf_ntlmssp_challenge_target_info_len = -1;
+static int hf_ntlmssp_challenge_target_info_maxlen = -1;
+static int hf_ntlmssp_challenge_target_info_offset = -1;
+
+static int hf_ntlmssp_challenge_target_info_item_type = -1;
+static int hf_ntlmssp_challenge_target_info_item_len = -1;
+
+static int hf_ntlmssp_challenge_target_info_end = -1;
+static int hf_ntlmssp_challenge_target_info_nb_computer_name = -1;
+static int hf_ntlmssp_challenge_target_info_nb_domain_name = -1;
+static int hf_ntlmssp_challenge_target_info_dns_computer_name = -1;
+static int hf_ntlmssp_challenge_target_info_dns_domain_name = -1;
+static int hf_ntlmssp_challenge_target_info_dns_tree_name = -1;
+static int hf_ntlmssp_challenge_target_info_flags = -1;
+static int hf_ntlmssp_challenge_target_info_timestamp = -1;
+static int hf_ntlmssp_challenge_target_info_restrictions = -1;
+static int hf_ntlmssp_challenge_target_info_target_name =-1;
+static int hf_ntlmssp_challenge_target_info_channel_bindings =-1;
+
+static int hf_ntlmssp_ntlmv2_response_item_type = -1;
+static int hf_ntlmssp_ntlmv2_response_item_len = -1;
+
+static int hf_ntlmssp_ntlmv2_response_end = -1;
+static int hf_ntlmssp_ntlmv2_response_nb_computer_name = -1;
+static int hf_ntlmssp_ntlmv2_response_nb_domain_name = -1;
+static int hf_ntlmssp_ntlmv2_response_dns_computer_name = -1;
+static int hf_ntlmssp_ntlmv2_response_dns_domain_name = -1;
+static int hf_ntlmssp_ntlmv2_response_dns_tree_name = -1;
+static int hf_ntlmssp_ntlmv2_response_flags = -1;
+static int hf_ntlmssp_ntlmv2_response_timestamp = -1;
+static int hf_ntlmssp_ntlmv2_response_restrictions = -1;
+static int hf_ntlmssp_ntlmv2_response_target_name =-1;
+static int hf_ntlmssp_ntlmv2_response_channel_bindings =-1;
+
 static int hf_ntlmssp_message_integrity_code = -1;
 static int hf_ntlmssp_verf = -1;
 static int hf_ntlmssp_verf_vers = -1;
@@ -230,6 +254,7 @@ static int hf_ntlmssp_verf_hmacmd5 = -1;
 static int hf_ntlmssp_verf_crc32 = -1;
 static int hf_ntlmssp_verf_sequence = -1;
 static int hf_ntlmssp_decrypted_payload = -1;
+
 static int hf_ntlmssp_ntlmv2_response = -1;
 static int hf_ntlmssp_ntlmv2_response_hmac = -1;
 static int hf_ntlmssp_ntlmv2_response_header = -1;
@@ -237,21 +262,16 @@ static int hf_ntlmssp_ntlmv2_response_reserved = -1;
 static int hf_ntlmssp_ntlmv2_response_time = -1;
 static int hf_ntlmssp_ntlmv2_response_chal = -1;
 static int hf_ntlmssp_ntlmv2_response_unknown = -1;
-static int hf_ntlmssp_ntlmv2_response_name = -1;
-static int hf_ntlmssp_ntlmv2_response_name_type = -1;
-static int hf_ntlmssp_ntlmv2_response_name_len = -1;
-static int hf_ntlmssp_ntlmv2_response_restriction = -1;
-static int hf_ntlmssp_ntlmv2_response_client_time = -1;
 
 static gint ett_ntlmssp = -1;
 static gint ett_ntlmssp_negotiate_flags = -1;
 static gint ett_ntlmssp_string = -1;
 static gint ett_ntlmssp_blob = -1;
 static gint ett_ntlmssp_version = -1;
-static gint ett_ntlmssp_address_list = -1;
-static gint ett_ntlmssp_address_list_item = -1;
+static gint ett_ntlmssp_challenge_target_info = -1;
+static gint ett_ntlmssp_challenge_target_info_item = -1;
 static gint ett_ntlmssp_ntlmv2_response = -1;
-static gint ett_ntlmssp_ntlmv2_response_name = -1;
+static gint ett_ntlmssp_ntlmv2_response_item = -1;
 
 /* Configuration variables */
 const char *gbl_nt_password = NULL;
@@ -299,8 +319,8 @@ static void printnbyte(const guint8* tab,int nb,const char* txt,const char* txt2
   }
   fprintf(stderr,"%s",txt2);
 }
-/*
- static void printnchar(const guint8* tab,int nb,char* txt,char* txt2)
+#if 0
+static void printnchar(const guint8* tab,int nb,char* txt,char* txt2)
 {
   int i=0;
   fprintf(stderr,"%s ",txt);
@@ -310,18 +330,21 @@ static void printnbyte(const guint8* tab,int nb,const char* txt,const char* txt2
   }
   fprintf(stderr,"%s",txt2);
 }
-*/
+#endif
 #else
 static void printnbyte(const guint8* tab _U_,int nb _U_, const char* txt _U_,const char* txt2 _U_)
 {
 }
 #endif
+
 /*
  * GSlist of decrypted payloads.
  */
 static GSList *decrypted_payloads;
 
-int LEBE_Convert(int value)
+#if 0
+static int
+LEBE_Convert(int value)
 {
   char a,b,c,d;
   /* Get each byte */
@@ -331,15 +354,18 @@ int LEBE_Convert(int value)
   d=(value&0xFF000000) >> 24;
   return (a << 24) | (b << 16) | (c << 8) | d;
 }
+#endif
+
 /*
   Perform a DES encryption with a 16 bit key and 8bit data item.
   It's in fact 3 susbsequent call to crypt_des_ecb with a 7 bit key.
   Missing bits for the key are replaced by 0;
   Returns output in response, which is expected to be 24 bytes.
 */
-static int crypt_des_ecb_long(guint8 *response,
-                                              const guint8 *key,
-                                              const guint8 *data)
+static int
+crypt_des_ecb_long(guint8 *response,
+                   const guint8 *key,
+                   const guint8 *data)
 {
   guint8 pw21[21]; /* 21 bytes place for the needed key */
 
@@ -354,14 +380,16 @@ static int crypt_des_ecb_long(guint8 *response,
 
   return 1;
 }
+
 /*
   Generate a challenge response, given an eight byte challenge and
   either the NT or the Lan Manager password hash (16 bytes).
   Returns output in response, which is expected to be 24 bytes.
 */
-static int ntlmssp_generate_challenge_response(guint8 *response,
-                                              const guint8 *passhash,
-                                              const guint8 *challenge)
+static int
+ntlmssp_generate_challenge_response(guint8 *response,
+                                    const guint8 *passhash,
+                                    const guint8 *challenge)
 {
   guint8 pw21[21]; /* Password hash padded to 21 bytes */
 
@@ -379,7 +407,8 @@ static int ntlmssp_generate_challenge_response(guint8 *response,
 
 
 /* Ultra simple ainsi to unicode converter, will only work for ascii password ...*/
-static void str_to_unicode(const char *nt_password, char *nt_password_unicode)
+static void
+str_to_unicode(const char *nt_password, char *nt_password_unicode)
 {
   size_t password_len = 0;
   size_t i;
@@ -440,62 +469,66 @@ get_keyexchange_key(unsigned char keyexchangekey[NTLMSSP_KEY_LEN],const unsigned
     }
   }
 }
+
 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
 static guint32
 get_md4pass_list(md4_pass** p_pass_list,const char* nt_password)
 {
 
-       guint32 nb_pass = 0;
-       enc_key_t *ek;
-       unsigned char nt_password_hash[NTLMSSP_KEY_LEN];
-       int password_len = 0;
-       char nt_password_unicode[256];
-       md4_pass* pass_list;
-       int i = 0;
-       if(!krb_decrypt){
-               pass_list=NULL;
-               return 0;
-       }
-       read_keytab_file_from_preferences();
-
-       for(ek=enc_key_list;ek;ek=ek->next){
-               if( ek->keylength == NTLMSSP_KEY_LEN ) {
-                       nb_pass++;
-               }
-       }
-       memset(nt_password_hash,0,NTLMSSP_KEY_LEN);
-       if (nt_password[0] != '\0' && ( strlen(nt_password) < 129 )) {
-               nb_pass++;
-               password_len = strlen(nt_password);
-               str_to_unicode(nt_password,nt_password_unicode);
-               crypt_md4(nt_password_hash,nt_password_unicode,password_len*2);
-       }
-       if( nb_pass == 0 ) {
-               /* Unable to calculate the session key without a password       or if password is more than 128 char ......*/
-               return 0;
-       }
-       i = 0;
-       *p_pass_list = ep_alloc(nb_pass*sizeof(md4_pass));
-       pass_list=*p_pass_list;
-
-       if( memcmp(nt_password_hash,gbl_zeros,NTLMSSP_KEY_LEN) != 0 ) {
-               memcpy(pass_list[i].md4,nt_password_hash,NTLMSSP_KEY_LEN);
-               i = 1;
-       }
-       for(ek=enc_key_list;ek;ek=ek->next){
-               if( ek->keylength == NTLMSSP_KEY_LEN ) {
-                       memcpy(pass_list[i].md4,ek->keyvalue,NTLMSSP_KEY_LEN);
-                       i++;
-               }
-       }
-       return nb_pass;
+  guint32 nb_pass = 0;
+  enc_key_t *ek;
+  unsigned char nt_password_hash[NTLMSSP_KEY_LEN];
+  int password_len = 0;
+  char nt_password_unicode[256];
+  md4_pass* pass_list;
+  int i = 0;
+  if(!krb_decrypt){
+    pass_list=NULL;
+    return 0;
+  }
+  read_keytab_file_from_preferences();
+
+  for(ek=enc_key_list;ek;ek=ek->next){
+    if( ek->keylength == NTLMSSP_KEY_LEN ) {
+      nb_pass++;
+    }
+  }
+  memset(nt_password_hash,0,NTLMSSP_KEY_LEN);
+  if (nt_password[0] != '\0' && ( strlen(nt_password) < 129 )) {
+    nb_pass++;
+    password_len = strlen(nt_password);
+    str_to_unicode(nt_password,nt_password_unicode);
+    crypt_md4(nt_password_hash,nt_password_unicode,password_len*2);
+  }
+  if( nb_pass == 0 ) {
+    /* Unable to calculate the session key without a password or if password is more than 128 char ......*/
+    return 0;
+  }
+  i = 0;
+  *p_pass_list = ep_alloc(nb_pass*sizeof(md4_pass));
+  pass_list=*p_pass_list;
+
+  if( memcmp(nt_password_hash,gbl_zeros,NTLMSSP_KEY_LEN) != 0 ) {
+    memcpy(pass_list[i].md4,nt_password_hash,NTLMSSP_KEY_LEN);
+    i = 1;
+  }
+  for(ek=enc_key_list;ek;ek=ek->next){
+    if( ek->keylength == NTLMSSP_KEY_LEN ) {
+      memcpy(pass_list[i].md4,ek->keyvalue,NTLMSSP_KEY_LEN);
+      i++;
+    }
+  }
+  return nb_pass;
 }
 #endif
-/* Create an NTLMSSP version 2
+
+/* Create an NTLMSSP version 2 key
  */
 static void
 create_ntlmssp_v2_key(const char *nt_password _U_, const guint8 *serverchallenge , const guint8 *clientchallenge ,
-                     guint8 *sessionkey ,const  guint8 *encryptedsessionkey , int flags , ntlmssp_blob ntlm_response, ntlmssp_blob lm_response _U_, ntlmssp_header_t *ntlmssph ) {
+                      guint8 *sessionkey ,const  guint8 *encryptedsessionkey , int flags ,
+                      const ntlmssp_blob *ntlm_response, const ntlmssp_blob *lm_response _U_, ntlmssp_header_t *ntlmssph )
+{
   char domain_name_unicode[256];
   char user_uppercase[256];
   char buf[512];
@@ -526,17 +559,17 @@ create_ntlmssp_v2_key(const char *nt_password _U_, const guint8 *serverchallenge
   memset(user_uppercase,0,256);
   user_len = strlen(ntlmssph->acct_name);
   if( user_len < 129 ) {
-     memset(buf,0,512);
-     str_to_unicode(ntlmssph->acct_name,buf);
-     for (j = 0; j < (2*user_len); j++) {
-       if( buf[j] != '\0' ) {
-         user_uppercase[j] = toupper(buf[j]);
-       }
-     }
+    memset(buf,0,512);
+    str_to_unicode(ntlmssph->acct_name,buf);
+    for (j = 0; j < (2*user_len); j++) {
+      if( buf[j] != '\0' ) {
+        user_uppercase[j] = toupper(buf[j]);
+      }
+    }
   }
   else {
-     /* Unable to calculate the session not enought space in buffer, note this is unlikely to happen but ......*/
-     return;
+    /* Unable to calculate the session not enought space in buffer, note this is unlikely to happen but ......*/
+    return;
   }
   domain_len = strlen(ntlmssph->domain_name);
   if( domain_len < 129 ) {
@@ -567,10 +600,10 @@ create_ntlmssp_v2_key(const char *nt_password _U_, const guint8 *serverchallenge
     /* NT proof = First NTLMSSP_KEY_LEN bytes of NT response */
     memset(buf,0,512);
     memcpy(buf,serverchallenge,8);
-    memcpy(buf+8,ntlm_response.contents+NTLMSSP_KEY_LEN,ntlm_response.length-NTLMSSP_KEY_LEN);
-    md5_hmac(buf,ntlm_response.length-8,ntowf,NTLMSSP_KEY_LEN,nt_proof);
+    memcpy(buf+8,ntlm_response->contents+NTLMSSP_KEY_LEN,ntlm_response->length-NTLMSSP_KEY_LEN);
+    md5_hmac(buf,ntlm_response->length-8,ntowf,NTLMSSP_KEY_LEN,nt_proof);
     printnbyte(nt_proof,NTLMSSP_KEY_LEN,"NT proof: ","\n");
-    if( !memcmp(nt_proof,ntlm_response.contents,NTLMSSP_KEY_LEN) ) {
+    if( !memcmp(nt_proof,ntlm_response->contents,NTLMSSP_KEY_LEN) ) {
       found = 1;
       break;
     }
@@ -603,7 +636,8 @@ create_ntlmssp_v2_key(const char *nt_password _U_, const guint8 *serverchallenge
  */
 static void
 create_ntlmssp_v1_key(const char *nt_password, const guint8 *serverchallenge, const guint8 *clientchallenge,
-                     guint8 *sessionkey,const  guint8 *encryptedsessionkey, int flags, const guint8 *ref_nt_challenge_response,const guint8 *ref_lm_challenge_response)
+                      guint8 *sessionkey,const  guint8 *encryptedsessionkey, int flags,
+                      const guint8 *ref_nt_challenge_response,const guint8 *ref_lm_challenge_response)
 {
   unsigned char lm_password_upper[NTLMSSP_KEY_LEN];
   unsigned char lm_password_hash[NTLMSSP_KEY_LEN];
@@ -654,7 +688,7 @@ create_ntlmssp_v1_key(const char *nt_password, const guint8 *serverchallenge, co
     crypt_des_ecb(lm_password_hash, lmhash_key, lm_password_upper, 1);
     crypt_des_ecb(lm_password_hash+8, lmhash_key, lm_password_upper+7, 1);
     ntlmssp_generate_challenge_response(lm_challenge_response,
-                                     lm_password_hash, serverchallenge);
+                                        lm_password_hash, serverchallenge);
     memcpy(sessionbasekey,lm_password_hash,NTLMSSP_KEY_LEN);
   }
   else {
@@ -731,6 +765,7 @@ create_ntlmssp_v1_key(const char *nt_password, const guint8 *serverchallenge, co
     memcpy(sessionkey,keyexchangekey,NTLMSSP_KEY_LEN);
   }
 }
+
 static void
 get_siging_key(guint8 *sign_key_server,guint8* sign_key_client,const guint8 key[NTLMSSP_KEY_LEN], int keylen)
 {
@@ -752,7 +787,8 @@ get_siging_key(guint8 *sign_key_server,guint8* sign_key_client,const guint8 key[
 /* We return either a 128 or 64 bit key
  */
 static void
-get_sealing_rc4key(const guint8 exportedsessionkey[NTLMSSP_KEY_LEN] ,const int flags ,int *keylen ,guint8 *clientsealkey ,guint8 *serversealkey)
+get_sealing_rc4key(const guint8 exportedsessionkey[NTLMSSP_KEY_LEN] ,const int flags ,int *keylen ,
+                   guint8 *clientsealkey ,guint8 *serversealkey)
 {
   md5_state_t md5state;
   md5_state_t md5state2;
@@ -811,7 +847,7 @@ get_sealing_rc4key(const guint8 exportedsessionkey[NTLMSSP_KEY_LEN] ,const int f
         clientsealkey[7]=0xb0;
       }
     }
-    serversealkey = memcpy(serversealkey,clientsealkey,*keylen);
+    memcpy(serversealkey,clientsealkey,*keylen);
   }
 }
 /* Create an NTLMSSP version 1 key.
@@ -831,10 +867,10 @@ get_sealing_rc4key(const guint8 exportedsessionkey[NTLMSSP_KEY_LEN] ,const int f
 */
 static int
 dissect_ntlmssp_string (tvbuff_t *tvb, int offset,
-                       proto_tree *ntlmssp_tree,
-                       gboolean unicode_strings,
-                       int string_hf, int *start, int *end,
-                       const char **stringp)
+                        proto_tree *ntlmssp_tree,
+                        gboolean unicode_strings,
+                        int string_hf, int *start, int *end,
+                        const char **stringp)
 {
   proto_tree *tree = NULL;
   proto_item *tf = NULL;
@@ -845,12 +881,12 @@ dissect_ntlmssp_string (tvbuff_t *tvb, int offset,
   int result_length;
   guint16 bc;
 
-  *start = (string_offset > offset+8 ? string_offset : tvb_reported_length(tvb));
+  *start = (string_offset > offset+8 ? string_offset : (signed)tvb_reported_length(tvb));
   if (0 == string_length) {
     *end = *start;
     if (ntlmssp_tree)
-           proto_tree_add_string(ntlmssp_tree, string_hf, tvb,
-                                 offset, 8, "NULL");
+      proto_tree_add_string(ntlmssp_tree, string_hf, tvb,
+                            offset, 8, "NULL");
     if (stringp != NULL)
       *stringp = "";
     return offset+8;
@@ -858,8 +894,8 @@ dissect_ntlmssp_string (tvbuff_t *tvb, int offset,
 
   bc = result_length = string_length;
   string_text = get_unicode_or_ascii_string(tvb, &string_offset,
-                                           unicode_strings, &result_length,
-                                           FALSE, TRUE, &bc);
+                                            unicode_strings, &result_length,
+                                            FALSE, TRUE, &bc);
 
   if (stringp != NULL) {
     if (!string_text) string_text = ""; /* Make sure we don't blow up later */
@@ -869,17 +905,17 @@ dissect_ntlmssp_string (tvbuff_t *tvb, int offset,
 
   if (ntlmssp_tree) {
     tf = proto_tree_add_string(ntlmssp_tree, string_hf, tvb,
-                              string_offset, result_length, string_text);
+                               string_offset, result_length, string_text);
     tree = proto_item_add_subtree(tf, ett_ntlmssp_string);
   }
   proto_tree_add_uint(tree, hf_ntlmssp_string_len,
-                     tvb, offset, 2, string_length);
+                      tvb, offset, 2, string_length);
   offset += 2;
   proto_tree_add_uint(tree, hf_ntlmssp_string_maxlen,
-                     tvb, offset, 2, string_maxlen);
+                      tvb, offset, 2, string_maxlen);
   offset += 2;
   proto_tree_add_uint(tree, hf_ntlmssp_string_offset,
-                     tvb, offset, 4, string_offset);
+                      tvb, offset, 4, string_offset);
   offset += 4;
 
   *end = string_offset + string_length;
@@ -895,8 +931,8 @@ dissect_ntlmssp_string (tvbuff_t *tvb, int offset,
 */
 static int
 dissect_ntlmssp_blob (tvbuff_t *tvb, int offset,
-                     proto_tree *ntlmssp_tree,
-                     int blob_hf, int *end, ntlmssp_blob *result)
+                      proto_tree *ntlmssp_tree,
+                      int blob_hf, int *end, ntlmssp_blob *result)
 {
   proto_item *tf = NULL;
   proto_tree *tree = NULL;
@@ -906,24 +942,24 @@ dissect_ntlmssp_blob (tvbuff_t *tvb, int offset,
   if (0 == blob_length) {
     *end = (blob_offset > ((guint)offset)+8 ? blob_offset : ((guint)offset)+8);
     if (ntlmssp_tree)
-           proto_tree_add_text(ntlmssp_tree, tvb, offset, 8, "%s: Empty",
-                               proto_registrar_get_name(blob_hf));
+      proto_tree_add_text(ntlmssp_tree, tvb, offset, 8, "%s: Empty",
+                          proto_registrar_get_name(blob_hf));
     return offset+8;
   }
 
   if (ntlmssp_tree) {
     tf = proto_tree_add_item (ntlmssp_tree, blob_hf, tvb,
-                             blob_offset, blob_length, FALSE);
+                              blob_offset, blob_length, FALSE);
     tree = proto_item_add_subtree(tf, ett_ntlmssp_blob);
   }
   proto_tree_add_uint(tree, hf_ntlmssp_blob_len,
-                     tvb, offset, 2, blob_length);
+                      tvb, offset, 2, blob_length);
   offset += 2;
   proto_tree_add_uint(tree, hf_ntlmssp_blob_maxlen,
-                     tvb, offset, 2, blob_maxlen);
+                      tvb, offset, 2, blob_maxlen);
   offset += 2;
   proto_tree_add_uint(tree, hf_ntlmssp_blob_offset,
-                     tvb, offset, 4, blob_offset);
+                      tvb, offset, 4, blob_offset);
   offset += 4;
 
   *end = blob_offset + blob_length;
@@ -934,11 +970,11 @@ dissect_ntlmssp_blob (tvbuff_t *tvb, int offset,
     if (blob_length < MAX_BLOB_SIZE)
     {
       tvb_memcpy(tvb, result->contents, blob_offset, blob_length);
-      if (blob_hf == hf_ntlmssp_auth_lmresponse && !(memcmp(tvb->real_data+blob_offset+8,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",NTLMSSP_KEY_LEN)))
+      if (blob_hf == hf_ntlmssp_auth_lmresponse && !(tvb_memeql(tvb, blob_offset+8, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", NTLMSSP_KEY_LEN)))
       {
         proto_tree_add_item (ntlmssp_tree,
-                      hf_ntlmssp_ntlm_client_challenge,
-                      tvb, blob_offset, 8, FALSE);
+                             hf_ntlmssp_ntlm_client_challenge,
+                             tvb, blob_offset, 8, ENC_NA);
       }
     }
   }
@@ -949,9 +985,9 @@ dissect_ntlmssp_blob (tvbuff_t *tvb, int offset,
   if (blob_hf == hf_ntlmssp_auth_ntresponse && blob_length > 24)
   {
     proto_tree_add_item (ntlmssp_tree,
-           hf_ntlmssp_ntlm_client_challenge,
-           tvb, blob_offset+32, 8, FALSE);
-         dissect_ntlmv2_response(tvb, tree, blob_offset, blob_length);
+                         hf_ntlmssp_ntlm_client_challenge,
+                         tvb, blob_offset+32, 8, ENC_NA);
+    dissect_ntlmv2_response(tvb, tree, blob_offset, blob_length);
   }
 
   return offset;
@@ -959,115 +995,115 @@ dissect_ntlmssp_blob (tvbuff_t *tvb, int offset,
 
 static int
 dissect_ntlmssp_negotiate_flags (tvbuff_t *tvb, int offset,
-                                proto_tree *ntlmssp_tree,
-                                guint32 negotiate_flags)
+                                 proto_tree *ntlmssp_tree,
+                                 guint32 negotiate_flags)
 {
   proto_tree *negotiate_flags_tree = NULL;
   proto_item *tf = NULL;
 
   if (ntlmssp_tree) {
     tf = proto_tree_add_uint (ntlmssp_tree,
-                             hf_ntlmssp_negotiate_flags,
-                             tvb, offset, 4, negotiate_flags);
+                              hf_ntlmssp_negotiate_flags,
+                              tvb, offset, 4, negotiate_flags);
     negotiate_flags_tree = proto_item_add_subtree (tf, ett_ntlmssp_negotiate_flags);
   }
 
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_80000000,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_80000000,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_40000000,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_40000000,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_20000000,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_20000000,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_10000000,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_10000000,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_8000000,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_8000000,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_4000000,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_4000000,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_2000000,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_2000000,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_1000000,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_1000000,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_800000,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_800000,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_400000,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_400000,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_200000,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_200000,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_100000,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_100000,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_80000,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_80000,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_40000,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_40000,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_20000,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_20000,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_10000,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_10000,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_8000,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_8000,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_4000,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_4000,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_2000,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_2000,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_1000,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_1000,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_800,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_800,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_400,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_400,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_200,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_200,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_100,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_100,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_80,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_80,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_40,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_40,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_20,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_20,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_10,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_10,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_08,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_08,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_04,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_04,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_02,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_02,
+                          tvb, offset, 4, negotiate_flags);
   proto_tree_add_boolean (negotiate_flags_tree,
-                         hf_ntlmssp_negotiate_flags_01,
-                         tvb, offset, 4, negotiate_flags);
+                          hf_ntlmssp_negotiate_flags_01,
+                          tvb, offset, 4, negotiate_flags);
 
   return (offset + 4);
 }
@@ -1075,11 +1111,11 @@ dissect_ntlmssp_negotiate_flags (tvbuff_t *tvb, int offset,
 /* Dissect "version" */
 
 /* From MS-NLMP:
-    0  Major Version Number    1 byte
-    1  Minor Version Number    1 byte
-    2  Build Number            short(LE)
+    0   Major Version Number    1 byte
+    1   Minor Version Number    1 byte
+    2   Build Number            short(LE)
     3   (Reserved)              3 bytes
-    4  NTLM Current Revision   1 byte
+    4   NTLM Current Revision   1 byte
 */
 
 static int
@@ -1089,12 +1125,12 @@ dissect_ntlmssp_version(tvbuff_t *tvb, int offset,
   if (ntlmssp_tree) {
     proto_item *tf;
     proto_tree *version_tree;
-    tf = proto_tree_add_text(ntlmssp_tree, tvb, offset, 8,
-                             "Version %u.%u (Build %u); NTLM Current Revision %u",
-                             tvb_get_guint8(tvb, offset),
-                             tvb_get_guint8(tvb, offset+1),
-                             tvb_get_letohs(tvb, offset+2),
-                             tvb_get_guint8(tvb, offset+7));
+    tf = proto_tree_add_none_format(ntlmssp_tree, hf_ntlmssp_version, tvb, offset, 8,
+                                    "Version %u.%u (Build %u); NTLM Current Revision %u",
+                                    tvb_get_guint8(tvb, offset),
+                                    tvb_get_guint8(tvb, offset+1),
+                                    tvb_get_letohs(tvb, offset+2),
+                                    tvb_get_guint8(tvb, offset+7));
     version_tree = proto_item_add_subtree (tf, ett_ntlmssp_version);
     proto_tree_add_item(version_tree, hf_ntlmssp_version_major                , tvb, offset  , 1, ENC_NA);
     proto_tree_add_item(version_tree, hf_ntlmssp_version_minor                , tvb, offset+1, 1, ENC_NA);
@@ -1107,182 +1143,243 @@ dissect_ntlmssp_version(tvbuff_t *tvb, int offset,
 /* Dissect a NTLM response. This is documented at
    http://ubiqx.org/cifs/SMB.html#SMB.8, para 2.8.5.3 */
 
-/* Name types */
-
+/* Attribute types */
 /*
  * XXX - the davenport document says that a type of 5 has been seen,
  * "apparently containing the 'parent' DNS domain for servers in
  * subdomains".
+ * XXX: MS-NLMP info is newer than Davenport info;
+ *      The attribute type list and the attribute names below are
+ *      based upon MS-NLMP.
  */
 
-#define NTLM_NAME_END        0x0000
-#define NTLM_NAME_NB_HOST    0x0001
-#define NTLM_NAME_NB_DOMAIN  0x0002
-#define NTLM_NAME_DNS_HOST   0x0003
-#define NTLM_NAME_DNS_DOMAIN 0x0004
-#define NTLM_NAME_DNS_FOREST 0x0005
-#define NTLM_NAME_CLIENT_TIME 0x0007
-#define NTLM_NAME_RESTRICTION 0x0008
+#define NTLM_TARGET_INFO_END               0x0000
+#define NTLM_TARGET_INFO_NB_COMPUTER_NAME  0x0001
+#define NTLM_TARGET_INFO_NB_DOMAIN_NAME    0x0002
+#define NTLM_TARGET_INFO_DNS_COMPUTER_NAME 0x0003
+#define NTLM_TARGET_INFO_DNS_DOMAIN_NAME   0x0004
+#define NTLM_TARGET_INFO_DNS_TREE_NAME     0x0005
+#define NTLM_TARGET_INFO_FLAGS             0x0006
+#define NTLM_TARGET_INFO_TIMESTAMP         0x0007
+#define NTLM_TARGET_INFO_RESTRICTIONS      0x0008
+#define NTLM_TARGET_INFO_TARGET_NAME       0x0009
+#define NTLM_TARGET_INFO_CHANNEL_BINDINGS  0x000A
+
+static const value_string ntlm_name_types[] = {
+  { NTLM_TARGET_INFO_END,               "End of list" },
+  { NTLM_TARGET_INFO_NB_COMPUTER_NAME,  "NetBIOS computer name" },
+  { NTLM_TARGET_INFO_NB_DOMAIN_NAME,    "NetBIOS domain name" },
+  { NTLM_TARGET_INFO_DNS_COMPUTER_NAME, "DNS computer name" },
+  { NTLM_TARGET_INFO_DNS_DOMAIN_NAME,   "DNS domain name" },
+  { NTLM_TARGET_INFO_DNS_TREE_NAME,     "DNS tree name" },
+  { NTLM_TARGET_INFO_FLAGS,             "Flags" },
+  { NTLM_TARGET_INFO_TIMESTAMP,         "Timestamp" },
+  { NTLM_TARGET_INFO_RESTRICTIONS,      "Restrictions" },
+  { NTLM_TARGET_INFO_TARGET_NAME,       "Target Name"},
+  { NTLM_TARGET_INFO_CHANNEL_BINDINGS,  "Channel Bindings"},
+  { 0, NULL }
+};
+
+/* The following *must* match the order of the list of attribute types   */
+/*  Assumption: values in the list are a sequence starting with 0 and    */
+/*  with no gaps allowing a direct access of the array by attribute type */
+static int *ntlmssp_hf_challenge_target_info_hf_ptr_array[] = {
+  &hf_ntlmssp_challenge_target_info_end,
+  &hf_ntlmssp_challenge_target_info_nb_computer_name,
+  &hf_ntlmssp_challenge_target_info_nb_domain_name,
+  &hf_ntlmssp_challenge_target_info_dns_computer_name,
+  &hf_ntlmssp_challenge_target_info_dns_domain_name,
+  &hf_ntlmssp_challenge_target_info_dns_tree_name,
+  &hf_ntlmssp_challenge_target_info_flags,
+  &hf_ntlmssp_challenge_target_info_timestamp,
+  &hf_ntlmssp_challenge_target_info_restrictions,
+  &hf_ntlmssp_challenge_target_info_target_name,
+  &hf_ntlmssp_challenge_target_info_channel_bindings
+};
 
+static int *ntlmssp_hf_ntlmv2_response_hf_ptr_array[] = {
+  &hf_ntlmssp_ntlmv2_response_end,
+  &hf_ntlmssp_ntlmv2_response_nb_computer_name,
+  &hf_ntlmssp_ntlmv2_response_nb_domain_name,
+  &hf_ntlmssp_ntlmv2_response_dns_computer_name,
+  &hf_ntlmssp_ntlmv2_response_dns_domain_name,
+  &hf_ntlmssp_ntlmv2_response_dns_tree_name,
+  &hf_ntlmssp_ntlmv2_response_flags,
+  &hf_ntlmssp_ntlmv2_response_timestamp,
+  &hf_ntlmssp_ntlmv2_response_restrictions,
+  &hf_ntlmssp_ntlmv2_response_target_name,
+  &hf_ntlmssp_ntlmv2_response_channel_bindings
+};
 
+typedef struct _tif {
+  gint  *ett;
+  int   *hf_item_type;
+  int   *hf_item_length;
+  int  **hf_attr_array_p;
+} tif_t;
+
+static tif_t ntlmssp_challenge_target_info_tif = {
+  &ett_ntlmssp_challenge_target_info_item,
+  &hf_ntlmssp_challenge_target_info_item_type,
+  &hf_ntlmssp_challenge_target_info_item_len,
+  ntlmssp_hf_challenge_target_info_hf_ptr_array
+};
 
-static const value_string ntlm_name_types[] = {
-       { NTLM_NAME_END, "End of list" },
-       { NTLM_NAME_NB_HOST, "NetBIOS host name" },
-       { NTLM_NAME_NB_DOMAIN, "NetBIOS domain name" },
-       { NTLM_NAME_DNS_HOST, "DNS host name" },
-       { NTLM_NAME_DNS_DOMAIN, "DNS domain name" },
-       { NTLM_NAME_DNS_FOREST, "DNS forest name" },
-
-       { NTLM_NAME_CLIENT_TIME, "Client Time" },
-       { NTLM_NAME_RESTRICTION, "Encoding restriction" },
-       { 0, NULL }
+static tif_t ntlmssp_ntlmv2_response_tif = {
+  &ett_ntlmssp_ntlmv2_response_item,
+  &hf_ntlmssp_ntlmv2_response_item_type,
+  &hf_ntlmssp_ntlmv2_response_item_len,
+  ntlmssp_hf_ntlmv2_response_hf_ptr_array
 };
 
+static void
+dissect_ntlmssp_target_info_list(tvbuff_t *tvb, proto_tree *tree,
+                                 guint32 target_info_offset, guint16 target_info_length,
+                                 tif_t *tif_p)
+{
+  guint32 item_offset;
+  guint16 item_type;
+  guint16 item_length;
+
+
+  /* Now enumerate through the individual items in the list */
+  item_offset = target_info_offset;
+
+  while (item_offset < (target_info_offset + target_info_length)) {
+    proto_item *target_info_tf;
+    proto_tree *target_info_tree;
+    guint32     content_offset;
+    guint16     content_length;
+    guint32     type_offset;
+    guint32     len_offset;
+
+    int **hf_array_p = tif_p->hf_attr_array_p;
+
+    /* Content type */
+    type_offset = item_offset;
+    item_type = tvb_get_letohs(tvb, type_offset);
+
+    /* Content length */
+    len_offset = type_offset + 2;
+    content_length = tvb_get_letohs(tvb, len_offset);
+
+    /* Content value */
+    content_offset = len_offset + 2;
+    item_length    = content_length + 4;
+
+    target_info_tf = proto_tree_add_text(tree, tvb, item_offset, item_length, "Attribute: %s",
+                                  val_to_str(item_type, ntlm_name_types, "Unknown (%d)"));
+
+    target_info_tree = proto_item_add_subtree (target_info_tf, *tif_p->ett);
+    proto_tree_add_item (target_info_tree, *tif_p->hf_item_type,    tvb, type_offset, 2, ENC_LITTLE_ENDIAN);
+    proto_tree_add_item (target_info_tree, *tif_p->hf_item_length,  tvb, len_offset,  2, ENC_LITTLE_ENDIAN);
+
+    switch (item_type) {
+    case NTLM_TARGET_INFO_NB_COMPUTER_NAME:
+    case NTLM_TARGET_INFO_NB_DOMAIN_NAME:
+    case NTLM_TARGET_INFO_DNS_COMPUTER_NAME:
+    case NTLM_TARGET_INFO_DNS_DOMAIN_NAME:
+    case NTLM_TARGET_INFO_DNS_TREE_NAME:
+    case NTLM_TARGET_INFO_TARGET_NAME:
+      if (content_length > 0) {
+        const gchar *text;
+
+        text = tvb_get_ephemeral_faked_unicode(tvb, content_offset, content_length / 2, TRUE);
+        proto_tree_add_string(target_info_tree, *hf_array_p[item_type],
+                              tvb, content_offset, content_length, text);
+        proto_item_append_text(target_info_tf, ": %s", text);
+      }
+      break;
+
+    case NTLM_TARGET_INFO_FLAGS:
+      proto_tree_add_item(target_info_tree, *hf_array_p[item_type],
+                          tvb, content_offset, content_length, ENC_LITTLE_ENDIAN);
+      break;
+
+    case NTLM_TARGET_INFO_TIMESTAMP:
+      dissect_nt_64bit_time(tvb, target_info_tree, content_offset, *hf_array_p[item_type]);
+      break;
+
+    case NTLM_TARGET_INFO_RESTRICTIONS:
+    case NTLM_TARGET_INFO_CHANNEL_BINDINGS:
+      proto_tree_add_item(target_info_tree, *hf_array_p[item_type],
+                          tvb, content_offset, content_length, ENC_NA);
+      break;
+
+    default:
+      break;
+    }
+
+    item_offset += item_length;
+  }
+}
+
 int
 dissect_ntlmv2_response(tvbuff_t *tvb, proto_tree *tree, int offset, int len)
 {
-       proto_item *ntlmv2_item = NULL;
-       proto_tree *ntlmv2_tree = NULL;
-  const guint8 *restriction_bytes;
-       /* Dissect NTLMv2 bits&pieces */
-
-       if (tree) {
-               ntlmv2_item = proto_tree_add_item(
-                       tree, hf_ntlmssp_ntlmv2_response, tvb,
-                       offset, len, TRUE);
-               ntlmv2_tree = proto_item_add_subtree(
-                       ntlmv2_item, ett_ntlmssp_ntlmv2_response);
-       }
-
-       proto_tree_add_item(
-               ntlmv2_tree, hf_ntlmssp_ntlmv2_response_hmac, tvb,
-               offset, 16, TRUE);
-
-       offset += 16;
-
-       proto_tree_add_item(
-               ntlmv2_tree, hf_ntlmssp_ntlmv2_response_header, tvb,
-               offset, 4, TRUE);
-
-       offset += 4;
-
-       proto_tree_add_item(
-               ntlmv2_tree, hf_ntlmssp_ntlmv2_response_reserved, tvb,
-               offset, 4, TRUE);
-
-       offset += 4;
-
-       offset = dissect_nt_64bit_time(
-               tvb, ntlmv2_tree, offset, hf_ntlmssp_ntlmv2_response_time);
-
-       proto_tree_add_item(
-               ntlmv2_tree, hf_ntlmssp_ntlmv2_response_chal, tvb,
-               offset, 8, TRUE);
-
-       offset += 8;
-
-       proto_tree_add_item(
-               ntlmv2_tree, hf_ntlmssp_ntlmv2_response_unknown, tvb,
-               offset, 4, TRUE);
-
-       offset += 4;
-
-       /* Variable length list of names */
-
-       while(1) {
-               guint16 name_type = tvb_get_letohs(tvb, offset);
-               guint16 name_len = tvb_get_letohs(tvb, offset + 2);
-               proto_tree *name_tree = NULL;
-               proto_item *name_item = NULL;
-               const char *name = NULL;
-
-               if (ntlmv2_tree) {
-                       name_item = proto_tree_add_item(
-                               ntlmv2_tree, hf_ntlmssp_ntlmv2_response_name,
-                               tvb, offset, 0, TRUE);
-                       name_tree = proto_item_add_subtree(
-                               name_item, ett_ntlmssp_ntlmv2_response_name);
-               }
-
-               /* Dissect name header */
-
-               proto_tree_add_item(
-                       name_tree, hf_ntlmssp_ntlmv2_response_name_type, tvb,
-                       offset, 2, TRUE);
-
-               offset += 2;
-
-               proto_tree_add_item(
-                       name_tree, hf_ntlmssp_ntlmv2_response_name_len, tvb,
-                       offset, 2, TRUE);
-
-               offset += 2;
-
-               /* Dissect name */
-
-               switch(name_type){
-               case NTLM_NAME_END:
-                       name = "NULL";
-                       proto_item_append_text(
-                               name_item, "%s",
-                               val_to_str(name_type, ntlm_name_types,
-                                          "Unknown"));
-                       break;
-               case NTLM_NAME_CLIENT_TIME:
-                       dissect_nt_64bit_time(
-                               tvb, name_tree, offset,
-                               hf_ntlmssp_ntlmv2_response_client_time);
-                       proto_item_append_text(
-                               name_item, "Client Time");
-                       break;
-    case NTLM_NAME_RESTRICTION:
-                       proto_item_append_text(
-                               name_item, "%s",
-                               val_to_str(name_type, ntlm_name_types,
-                                          "Unknown"));
-      restriction_bytes = tvb_get_ptr(tvb, offset,name_len);
-      proto_tree_add_bytes (name_tree,hf_ntlmssp_ntlmv2_response_restriction,tvb,offset,name_len,restriction_bytes);
-  break;
-               case NTLM_NAME_NB_HOST:
-               case NTLM_NAME_NB_DOMAIN:
-               case NTLM_NAME_DNS_HOST:
-               case NTLM_NAME_DNS_DOMAIN:
-               case NTLM_NAME_DNS_FOREST:
-               default:
-                       name = tvb_get_ephemeral_faked_unicode(
-                               tvb, offset, name_len / 2, TRUE);
-                       proto_tree_add_text(
-                               name_tree, tvb, offset, name_len,
-                               "Value: %s", name);
-                       proto_item_append_text(
-                               name_item, "%s, %s",
-                               val_to_str(name_type, ntlm_name_types,
-                                          "Unknown"), name);
-                       break;
-               }
-
-
-               offset += name_len;
-
-               proto_item_set_len(name_item, name_len + 4);
-
-               if (name_type == 0) /* End of list */
-                       break;
-       }
-
-       /*
-        * XXX - Windows puts 4 bytes of additional stuff here.
-        * Samba's smbclient doesn't.
-        * Both of them appear to be able to connect to W2K SMB
-        * servers.
-        * Should we display the rest of the response as an
-        * "extra data" item?
-        *
-        * XXX - we should also check whether we go past the length
-        * of the response.
-        */
-       return offset;
+  proto_item *ntlmv2_item = NULL;
+  proto_tree *ntlmv2_tree = NULL;
+  int         orig_offset;
+
+  /* Dissect NTLMv2 bits&pieces */
+  orig_offset = offset;
+
+  if (tree) {
+    ntlmv2_item = proto_tree_add_item(
+      tree, hf_ntlmssp_ntlmv2_response, tvb,
+      offset, len, ENC_NA);
+    ntlmv2_tree = proto_item_add_subtree(
+      ntlmv2_item, ett_ntlmssp_ntlmv2_response);
+  }
+
+  proto_tree_add_item(
+    ntlmv2_tree, hf_ntlmssp_ntlmv2_response_hmac, tvb,
+    offset, 16, ENC_NA);
+
+  offset += 16;
+
+  proto_tree_add_item(
+    ntlmv2_tree, hf_ntlmssp_ntlmv2_response_header, tvb,
+    offset, 4, ENC_LITTLE_ENDIAN);
+
+  offset += 4;
+
+  proto_tree_add_item(
+    ntlmv2_tree, hf_ntlmssp_ntlmv2_response_reserved, tvb,
+    offset, 4, ENC_LITTLE_ENDIAN);
+
+  offset += 4;
+
+  offset = dissect_nt_64bit_time(
+    tvb, ntlmv2_tree, offset, hf_ntlmssp_ntlmv2_response_time);
+
+  proto_tree_add_item(
+    ntlmv2_tree, hf_ntlmssp_ntlmv2_response_chal, tvb,
+    offset, 8, ENC_NA);
+
+  offset += 8;
+
+  proto_tree_add_item(
+    ntlmv2_tree, hf_ntlmssp_ntlmv2_response_unknown, tvb,
+    offset, 4, ENC_LITTLE_ENDIAN);
+
+  offset += 4;
+
+  /* Variable length list of attributes */
+  /*
+   * XXX - Windows puts one or more sets of 4 bytes of additional stuff (all zeros ?)
+   *        at the end of the attributes.
+   * Samba's smbclient doesn't.
+   * Both of them appear to be able to connect to W2K SMB
+   * servers.
+   * The additional stuff will be dissected as extra "end" attributes.
+   *
+   */
+  dissect_ntlmssp_target_info_list(tvb, ntlmv2_tree,
+                                   offset, len - (offset - orig_offset),
+                                   &ntlmssp_ntlmv2_response_tif);
+
+  return offset+len;
 }
 
 /* tapping into ntlmssph not yet implemented */
@@ -1298,7 +1395,7 @@ dissect_ntlmssp_negotiate (tvbuff_t *tvb, int offset, proto_tree *ntlmssp_tree,
   /* NTLMSSP Negotiate Flags */
   negotiate_flags = tvb_get_letohl (tvb, offset);
   offset = dissect_ntlmssp_negotiate_flags (tvb, offset, ntlmssp_tree,
-                                           negotiate_flags);
+                                            negotiate_flags);
 
   /*
    * XXX - the davenport document says that these might not be
@@ -1306,152 +1403,72 @@ dissect_ntlmssp_negotiate (tvbuff_t *tvb, int offset, proto_tree *ntlmssp_tree,
    * isn't enough to contain them.
    */
   offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, FALSE,
-                                 hf_ntlmssp_negotiate_domain,
-                                 &data_start, &data_end, NULL);
+                                  hf_ntlmssp_negotiate_domain,
+                                  &data_start, &data_end, NULL);
 
   offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, FALSE,
-                                 hf_ntlmssp_negotiate_workstation,
-                                 &item_start, &item_end, NULL);
+                                  hf_ntlmssp_negotiate_workstation,
+                                  &item_start, &item_end, NULL);
   data_start = MIN(data_start, item_start);
   data_end   = MAX(data_end,   item_end);
 
-  /* If there are more bytes before the data block dissect a version field */
+  /* If there are more bytes before the data block dissect a version field
+     if NTLMSSP_NEGOTIATE_VERSION is set in the flags (see MS-NLMP) */
   if (offset < data_start) {
-    offset = dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
+    if (negotiate_flags & NTLMSSP_NEGOTIATE_VERSION)
+      offset = dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
   }
   return data_end;
 }
 
 
 static int
-dissect_ntlmssp_address_list (tvbuff_t *tvb, int offset,
-                             proto_tree *ntlmssp_tree,
-                             int *end)
+dissect_ntlmssp_challenge_target_info_blob (tvbuff_t *tvb, int offset,
+                                            proto_tree *ntlmssp_tree,
+                                            int *end)
 {
-  guint16 list_length = tvb_get_letohs(tvb, offset);
-  guint16 list_maxlen = tvb_get_letohs(tvb, offset+2);
-  guint32 list_offset = tvb_get_letohl(tvb, offset+4);
-  guint16 item_type, item_length;
-  guint32 item_offset;
+  guint16 challenge_target_info_length = tvb_get_letohs(tvb, offset);
+  guint16 challenge_target_info_maxlen = tvb_get_letohs(tvb, offset+2);
+  guint32 challenge_target_info_offset = tvb_get_letohl(tvb, offset+4);
   proto_item *tf = NULL;
-  proto_tree *tree = NULL;
-  proto_item *addr_tf = NULL;
-  proto_tree *addr_tree = NULL;
+  proto_tree *challenge_target_info_tree = NULL;
 
-  /* the address list is just a blob */
-  if (0 == list_length) {
-    *end = (list_offset > ((guint)offset)+8 ? list_offset : ((guint)offset)+8);
+  /* the target info list is just a blob */
+  if (0 == challenge_target_info_length) {
+    *end = (challenge_target_info_offset > ((guint)offset)+8 ? challenge_target_info_offset : ((guint)offset)+8);
     if (ntlmssp_tree)
-           proto_tree_add_text(ntlmssp_tree, tvb, offset, 8,
-                               "Address List: Empty");
+      proto_tree_add_text(ntlmssp_tree, tvb, offset, 8,
+                          "Target Info List: Empty");
     return offset+8;
   }
 
   if (ntlmssp_tree) {
-    tf = proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_address_list, tvb,
-                             list_offset, list_length, FALSE);
-    tree = proto_item_add_subtree(tf, ett_ntlmssp_address_list);
+    tf = proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_challenge_target_info, tvb,
+                              challenge_target_info_offset, challenge_target_info_length, ENC_NA);
+    challenge_target_info_tree = proto_item_add_subtree(tf, ett_ntlmssp_challenge_target_info);
   }
-  proto_tree_add_uint(tree, hf_ntlmssp_address_list_len,
-                     tvb, offset, 2, list_length);
+  proto_tree_add_uint(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_len,
+                      tvb, offset, 2, challenge_target_info_length);
   offset += 2;
-  proto_tree_add_uint(tree, hf_ntlmssp_address_list_maxlen,
-                     tvb, offset, 2, list_maxlen);
+  proto_tree_add_uint(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_maxlen,
+                      tvb, offset, 2, challenge_target_info_maxlen);
   offset += 2;
-  proto_tree_add_uint(tree, hf_ntlmssp_address_list_offset,
-                     tvb, offset, 4, list_offset);
+  proto_tree_add_uint(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_offset,
+                      tvb, offset, 4, challenge_target_info_offset);
   offset += 4;
 
-  /* Now enumerate through the individual items in the list */
-  item_offset = list_offset;
-
-  while (item_offset < (list_offset + list_length)) {
-    const char *text=NULL;
-    guint32 content_offset;
-    guint16 content_length;
-    guint32 type_offset;
-    guint32 len_offset;
+  dissect_ntlmssp_target_info_list(tvb, challenge_target_info_tree,
+                                   challenge_target_info_offset, challenge_target_info_length,
+                                   &ntlmssp_challenge_target_info_tif);
 
-    /* Content type */
-    type_offset = item_offset;
-    item_type = tvb_get_letohs(tvb, type_offset);
-
-    /* Content length */
-    len_offset = type_offset + 2;
-    content_length = tvb_get_letohs(tvb, len_offset);
-
-    /* Content value */
-    content_offset = len_offset + 2;
-    item_length = content_length + 4;
-
-    /* Strings are always in Unicode regardless of the negotiated
-       string type. */
-    if (content_length > 0) {
-      guint16 bc;
-      int result_length;
-      int item_offset_int;
-
-      item_offset_int = content_offset;
-      bc = content_length;
-      text = get_unicode_or_ascii_string(tvb, &item_offset_int,
-                                        TRUE, &result_length,
-                                        FALSE, FALSE, &bc);
-    }
-
-    if (!text) text = ""; /* Make sure we don't blow up below */
-
-    switch(item_type) {
-    case NTLM_NAME_NB_HOST:
-      addr_tf = proto_tree_add_string(tree, hf_ntlmssp_address_list_server_nb,
-                                     tvb, item_offset, item_length, text);
-      break;
-    case NTLM_NAME_NB_DOMAIN:
-      addr_tf = proto_tree_add_string(tree, hf_ntlmssp_address_list_domain_nb,
-                                     tvb, item_offset, item_length, text);
-      break;
-    case NTLM_NAME_DNS_HOST:
-      addr_tf = proto_tree_add_string(tree, hf_ntlmssp_address_list_server_dns,
-                                     tvb, item_offset, item_length, text);
-      break;
-    case NTLM_NAME_DNS_DOMAIN:
-      addr_tf = proto_tree_add_string(tree, hf_ntlmssp_address_list_domain_dns,
-                                     tvb, item_offset, item_length, text);
-      break;
-    case NTLM_NAME_DNS_FOREST:
-      addr_tf = proto_tree_add_string(tree, hf_ntlmssp_address_list_forest_dns,
-                                     tvb, item_offset, item_length, text);
-      break;
-    case NTLM_NAME_END:
-      addr_tf = proto_tree_add_item(tree, hf_ntlmssp_address_list_terminator,
-                                   tvb, item_offset, item_length, TRUE);
-      break;
-    default:
-      addr_tf = proto_tree_add_text(tree, tvb, item_offset, item_length, "Unknown type:0x%04x", item_type);
-    }
-
-    /* Now show the actual bytes that made up the summary line */
-    addr_tree = proto_item_add_subtree (addr_tf,
-                                       ett_ntlmssp_address_list_item);
-    proto_tree_add_item (addr_tree, hf_ntlmssp_address_list_item_type,
-                        tvb, type_offset, 2, TRUE);
-    proto_tree_add_item (addr_tree, hf_ntlmssp_address_list_item_len,
-                        tvb, len_offset, 2, TRUE);
-    if (content_length > 0) {
-      proto_tree_add_string(addr_tree, hf_ntlmssp_address_list_item_content,
-                           tvb, content_offset, content_length, text);
-    }
-
-    item_offset += item_length;
-  }
-
-  *end = list_offset + list_length;
+  *end = challenge_target_info_offset + challenge_target_info_length;
   return offset;
 }
 
 /* tapping into ntlmssph not yet implemented */
 static int
 dissect_ntlmssp_challenge (tvbuff_t *tvb, packet_info *pinfo, int offset,
-                          proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph _U_)
+                           proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph _U_)
 {
   guint32 negotiate_flags;
   int item_start, item_end;
@@ -1478,19 +1495,19 @@ dissect_ntlmssp_challenge (tvbuff_t *tvb, packet_info *pinfo, int offset,
    * XXX - Original name "domain" changed to "target_name" to match MS-NLMP
    */
   offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree, unicode_strings,
-                        hf_ntlmssp_challenge_target_name,
-                        &item_start, &item_end, NULL);
+                                  hf_ntlmssp_challenge_target_name,
+                                  &item_start, &item_end, NULL);
   data_start = item_start;
   data_end = item_end;
 
   /* NTLMSSP Negotiate Flags */
   offset = dissect_ntlmssp_negotiate_flags (tvb, offset, ntlmssp_tree,
-                                           negotiate_flags);
+                                            negotiate_flags);
 
   /* NTLMSSP NT Lan Manager Challenge */
   proto_tree_add_item (ntlmssp_tree,
-                      hf_ntlmssp_ntlm_server_challenge,
-                      tvb, offset, 8, FALSE);
+                       hf_ntlmssp_ntlm_server_challenge,
+                       tvb, offset, 8, ENC_NA);
 
   /*
    * Store the flags and the RC4 state information with the conversation,
@@ -1548,17 +1565,17 @@ dissect_ntlmssp_challenge (tvbuff_t *tvb, packet_info *pinfo, int offset,
   /*
    * XXX - SSP key?  The davenport document says
    *
-   *   The context field is typically populated when Negotiate Local
-   *   Call is set. It contains an SSPI context handle, which allows
-   *   the client to "short-circuit" authentication and effectively
-   *   circumvent responding to the challenge. Physically, the context
-   *   is two long values. This is covered in greater detail later,
-   *   in the "Local Authentication" section.
+   *    The context field is typically populated when Negotiate Local
+   *    Call is set. It contains an SSPI context handle, which allows
+   *    the client to "short-circuit" authentication and effectively
+   *    circumvent responding to the challenge. Physically, the context
+   *    is two long values. This is covered in greater detail later,
+   *    in the "Local Authentication" section.
    *
    * It also says that that information may be omitted.
    */
   proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_reserved,
-                      tvb, offset, 8, FALSE);
+                       tvb, offset, 8, ENC_NA);
   offset += 8;
 
   /*
@@ -1572,15 +1589,17 @@ dissect_ntlmssp_challenge (tvbuff_t *tvb, packet_info *pinfo, int offset,
    * address list).
    */
   if (offset < data_start) {
-    offset = dissect_ntlmssp_address_list(tvb, offset, ntlmssp_tree, &item_end);
+    offset = dissect_ntlmssp_challenge_target_info_blob(tvb, offset, ntlmssp_tree, &item_end);
     /* XXX: This code assumes that the address list in the data block */
     /*      is always after the target name. Is this OK ?             */
     data_end = MAX(data_end, item_end);
   }
 
-  /* If there are more bytes before the data block dissect a version field */
+  /* If there are more bytes before the data block dissect a version field
+     if NTLMSSP_NEGOTIATE_VERSION is set in the flags (see MS-NLMP) */
   if (offset < data_start) {
-    offset = dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
+    if (negotiate_flags & NTLMSSP_NEGOTIATE_VERSION)
+      offset = dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
   }
 
   return MAX(offset, data_end);
@@ -1588,7 +1607,7 @@ dissect_ntlmssp_challenge (tvbuff_t *tvb, packet_info *pinfo, int offset,
 
 static int
 dissect_ntlmssp_auth (tvbuff_t *tvb, packet_info *pinfo, int offset,
-                     proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph)
+                      proto_tree *ntlmssp_tree, ntlmssp_header_t *ntlmssph)
 {
   int item_start, item_end;
   int data_start, data_end = 0;
@@ -1632,25 +1651,9 @@ dissect_ntlmssp_auth (tvbuff_t *tvb, packet_info *pinfo, int offset,
      * it means this is the first time we've dissected this frame, so
      * we should give it flag info.
      */
-#if 0
-    conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
-                                    pinfo->ptype, pinfo->srcport,
-                                    pinfo->destport, 0);
-    if (conversation != NULL) {
-      conv_ntlmssp_info = conversation_get_proto_data(conversation, proto_ntlmssp);
-      if (conv_ntlmssp_info != NULL) {
-       /*
-        * We have flag info; attach it to the frame.
-        */
-        /* XXX: The *conv_ntlmssp_info struct attached to the frame is the
-                same as the one attached to the conversation.
-                Is this what is indended ?  */
-       p_add_proto_data(pinfo->fd, proto_ntlmssp, conv_ntlmssp_info);
-      }
-    }
-#else /* XXX: Create conv_ntlmssp_info & etc if no previous CHALLENGE seen */
-      /*      so we'll have a place to store flags.                        */
-      /*      This is a bit brute-force but looks like it will be OK.      */
+    /* XXX: Create conv_ntlmssp_info & etc if no previous CHALLENGE seen */
+    /*      so we'll have a place to store flags.                        */
+    /*      This is a bit brute-force but looks like it will be OK.      */
     conversation = find_or_create_conversation(pinfo);
     conv_ntlmssp_info = conversation_get_proto_data(conversation, proto_ntlmssp);
     if (conv_ntlmssp_info == NULL) {
@@ -1661,7 +1664,6 @@ dissect_ntlmssp_auth (tvbuff_t *tvb, packet_info *pinfo, int offset,
             same as the one attached to the conversation. That is: *both* point to
             the exact same struct in memory.  Is this what is indended ?  */
     p_add_proto_data(pinfo->fd, proto_ntlmssp, conv_ntlmssp_info);
-#endif
   }
 
   if (conv_ntlmssp_info != NULL) {
@@ -1698,19 +1700,19 @@ dissect_ntlmssp_auth (tvbuff_t *tvb, packet_info *pinfo, int offset,
   /* Lan Manager response */
   data_start = tvb_get_letohl(tvb, offset+4);
   offset = dissect_ntlmssp_blob(tvb, offset, ntlmssp_tree,
-                               hf_ntlmssp_auth_lmresponse,
-                               &item_end,
-                               conv_ntlmssp_info == NULL ? NULL :
-                                   &conv_ntlmssp_info->lm_response);
+                                hf_ntlmssp_auth_lmresponse,
+                                &item_end,
+                                conv_ntlmssp_info == NULL ? NULL :
+                                &conv_ntlmssp_info->lm_response);
   data_end = MAX(data_end, item_end);
 
   /* NTLM response */
   item_start = tvb_get_letohl(tvb, offset+4);
   offset = dissect_ntlmssp_blob(tvb, offset, ntlmssp_tree,
-                               hf_ntlmssp_auth_ntresponse,
-                               &item_end,
-                               conv_ntlmssp_info == NULL ? NULL :
-                               &conv_ntlmssp_info->ntlm_response);
+                                hf_ntlmssp_auth_ntresponse,
+                                &item_end,
+                                conv_ntlmssp_info == NULL ? NULL :
+                                &conv_ntlmssp_info->ntlm_response);
   if( conv_ntlmssp_info != NULL && conv_ntlmssp_info->ntlm_response.length > 24 ) {
     memcpy(conv_ntlmssp_info->client_challenge,conv_ntlmssp_info->ntlm_response.contents+32,8);
   }
@@ -1731,9 +1733,9 @@ dissect_ntlmssp_auth (tvbuff_t *tvb, packet_info *pinfo, int offset,
   /* domain name */
   item_start = tvb_get_letohl(tvb, offset+4);
   offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
-                                 unicode_strings,
-                                 hf_ntlmssp_auth_domain,
-                                 &item_start, &item_end, &(ntlmssph->domain_name));
+                                  unicode_strings,
+                                  hf_ntlmssp_auth_domain,
+                                  &item_start, &item_end, &(ntlmssph->domain_name));
   /*ntlmssph->domain_name_len=item_end-item_start;*/
   data_start = MIN(data_start, item_start);
   data_end = MAX(data_end, item_end);
@@ -1741,23 +1743,22 @@ dissect_ntlmssp_auth (tvbuff_t *tvb, packet_info *pinfo, int offset,
   /* user name */
   item_start = tvb_get_letohl(tvb, offset+4);
   offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
-                                 unicode_strings,
-                                 hf_ntlmssp_auth_username,
-                                 &item_start, &item_end, &(ntlmssph->acct_name));
+                                  unicode_strings,
+                                  hf_ntlmssp_auth_username,
+                                  &item_start, &item_end, &(ntlmssph->acct_name));
   /*ntlmssph->acct_name_len=item_end-item_start;*/
   data_start = MIN(data_start, item_start);
   data_end = MAX(data_end, item_end);
 
-  if (check_col(pinfo->cinfo, COL_INFO))
-    col_append_fstr(pinfo->cinfo, COL_INFO, ", User: %s\\%s",
-                   ntlmssph->domain_name, ntlmssph->acct_name);
+  col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "User: %s\\%s",
+                  ntlmssph->domain_name, ntlmssph->acct_name);
 
   /* hostname */
   item_start = tvb_get_letohl(tvb, offset+4);
   offset = dissect_ntlmssp_string(tvb, offset, ntlmssp_tree,
-                                 unicode_strings,
-                                 hf_ntlmssp_auth_hostname,
-                                 &item_start, &item_end, &(ntlmssph->host_name));
+                                  unicode_strings,
+                                  hf_ntlmssp_auth_hostname,
+                                  &item_start, &item_end, &(ntlmssph->host_name));
   data_start = MIN(data_start, item_start);
   data_end = MAX(data_end, item_end);
 
@@ -1766,8 +1767,8 @@ dissect_ntlmssp_auth (tvbuff_t *tvb, packet_info *pinfo, int offset,
   if (offset < data_start) {
     /* Session Key */
     offset = dissect_ntlmssp_blob(tvb, offset, ntlmssp_tree,
-                                 hf_ntlmssp_auth_sesskey,
-                                 &item_end, &sessionblob);
+                                  hf_ntlmssp_auth_sesskey,
+                                  &item_end, &sessionblob);
     data_end = MAX(data_end, item_end);
   }
 
@@ -1782,11 +1783,14 @@ dissect_ntlmssp_auth (tvbuff_t *tvb, packet_info *pinfo, int offset,
     if ((conv_ntlmssp_info != NULL) && (conv_ntlmssp_info->flags == 0)) {
       conv_ntlmssp_info->flags = negotiate_flags;
     }
-  }
+  } else
+    negotiate_flags = 0;
 
-  /* If there are more bytes before the data block dissect a version field */
+  /* If there are more bytes before the data block dissect a version field
+     if NTLMSSP_NEGOTIATE_VERSION is set in the flags (see MS-NLMP) */
   if (offset < data_start) {
-    offset = dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
+    if (negotiate_flags & NTLMSSP_NEGOTIATE_VERSION)
+      offset = dissect_ntlmssp_version(tvb, offset, ntlmssp_tree);
   }
 
   /* If there are still more bytes before the data block dissect an MIC (message integrity_code) field */
@@ -1809,7 +1813,7 @@ dissect_ntlmssp_auth (tvbuff_t *tvb, packet_info *pinfo, int offset,
       {
         conv_ntlmssp_info->rc4_state_initialized = 0;
         if( conv_ntlmssp_info->is_auth_ntlm_v2 ) {
-          create_ntlmssp_v2_key(gbl_nt_password, conv_ntlmssp_info->server_challenge,conv_ntlmssp_info->client_challenge, sspkey,encryptedsessionkey,conv_ntlmssp_info->flags,conv_ntlmssp_info->ntlm_response,conv_ntlmssp_info->lm_response,ntlmssph);
+          create_ntlmssp_v2_key(gbl_nt_password, conv_ntlmssp_info->server_challenge,conv_ntlmssp_info->client_challenge, sspkey,encryptedsessionkey,conv_ntlmssp_info->flags,&conv_ntlmssp_info->ntlm_response,&conv_ntlmssp_info->lm_response,ntlmssph);
         }
         else
         {
@@ -1830,6 +1834,7 @@ dissect_ntlmssp_auth (tvbuff_t *tvb, packet_info *pinfo, int offset,
   }
   return MAX(offset, data_end);
 }
+
 static guint8*
 get_sign_key(packet_info *pinfo, int cryptpeer)
 {
@@ -1837,8 +1842,8 @@ get_sign_key(packet_info *pinfo, int cryptpeer)
   ntlmssp_info *conv_ntlmssp_info;
 
   conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
-                                  pinfo->ptype, pinfo->srcport,
-                                  pinfo->destport, 0);
+                                   pinfo->ptype, pinfo->srcport,
+                                   pinfo->destport, 0);
   if (conversation == NULL) {
     /* We don't have a conversation.  In this case, stop processing
        because we do not have enough info to decrypt the payload */
@@ -1847,24 +1852,25 @@ get_sign_key(packet_info *pinfo, int cryptpeer)
   else {
     /* We have a conversation, check for encryption state */
     conv_ntlmssp_info = conversation_get_proto_data(conversation,
-                                                   proto_ntlmssp);
+                                                    proto_ntlmssp);
     if (conv_ntlmssp_info == NULL) {
       /* No encryption state tied to the conversation.  Therefore, we
-        cannot decrypt the payload */
+         cannot decrypt the payload */
       return NULL;
     }
     else {
       /* We have the encryption state in the conversation.  So return the
-        crypt state tied to the requested peer
+         crypt state tied to the requested peer
        */
       if (cryptpeer == 1) {
-             return (guint8*)&conv_ntlmssp_info->sign_key_client;
+        return (guint8*)&conv_ntlmssp_info->sign_key_client;
       } else {
-             return (guint8*)&conv_ntlmssp_info->sign_key_server;
+        return (guint8*)&conv_ntlmssp_info->sign_key_server;
       }
     }
   }
 }
+
 /*
  * Get the encryption state tied to this conversation.  cryptpeer indicates
  * whether to retrieve the client key (1) or the server key (0)
@@ -1876,8 +1882,8 @@ get_encrypted_state(packet_info *pinfo, int cryptpeer)
   ntlmssp_info *conv_ntlmssp_info;
 
   conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
-                                  pinfo->ptype, pinfo->srcport,
-                                  pinfo->destport, 0);
+                                   pinfo->ptype, pinfo->srcport,
+                                   pinfo->destport, 0);
   if (conversation == NULL) {
     /* We don't have a conversation.  In this case, stop processing
        because we do not have enough info to decrypt the payload */
@@ -1886,39 +1892,42 @@ get_encrypted_state(packet_info *pinfo, int cryptpeer)
   else {
     /* We have a conversation, check for encryption state */
     conv_ntlmssp_info = conversation_get_proto_data(conversation,
-                                                   proto_ntlmssp);
+                                                    proto_ntlmssp);
     if (conv_ntlmssp_info == NULL) {
       /* No encryption state tied to the conversation.  Therefore, we
-        cannot decrypt the payload */
+         cannot decrypt the payload */
       return NULL;
     }
     else {
       /* We have the encryption state in the conversation.  So return the
-        crypt state tied to the requested peer
+         crypt state tied to the requested peer
        */
       if (cryptpeer == 1) {
-             return &conv_ntlmssp_info->rc4_state_client;
+        return &conv_ntlmssp_info->rc4_state_client;
       } else {
-             return &conv_ntlmssp_info->rc4_state_server;
+        return &conv_ntlmssp_info->rc4_state_server;
       }
     }
   }
 }
-void
+
+static void
 decrypt_data_payload(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
-                packet_info *pinfo, proto_tree *tree _U_,gpointer key);
+                     packet_info *pinfo, proto_tree *tree _U_,gpointer key);
 static void
 decrypt_verifier(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
-                packet_info *pinfo, proto_tree *tree,gpointer key);
-/*
-tvbuff_t *
+                 packet_info *pinfo, proto_tree *tree,gpointer key);
+
+#if 0
+static tvbuff_t *
 dissect_ntlmssp_encrypted_payload(tvbuff_t *data_tvb,
-                                 tvbuff_t *auth_tvb _U_,
-                                 int offset,
-                                 packet_info *pinfo,
-                                 dcerpc_auth_info *auth_info _U_)*/
+                                  tvbuff_t *auth_tvb _U_,
+                                  int offset,
+                                  packet_info *pinfo,
+                                  dcerpc_auth_info *auth_info _U_)
+#endif
 
-int
+static int
 dissect_ntlmssp_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
 {
   volatile int offset = 0;
@@ -1932,6 +1941,8 @@ dissect_ntlmssp_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
   guint32 ntlm_magic_size = 4;
   guint32 ntlm_signature_size = 8;
   guint32 ntlm_seq_size = 4;
+  void *pd_save;
+
   length = tvb_length (tvb);
   /* signature + seq + real payload */
   encrypted_block_length = length - ntlm_magic_size;
@@ -1945,11 +1956,11 @@ dissect_ntlmssp_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
   /* Setup a new tree for the NTLMSSP payload */
   if (tree) {
     tf = proto_tree_add_item (tree,
-                             hf_ntlmssp_verf,
-                             tvb, offset, -1, FALSE);
+                              hf_ntlmssp_verf,
+                              tvb, offset, -1, ENC_NA);
 
     ntlmssp_tree = proto_item_add_subtree (tf,
-                                          ett_ntlmssp);
+                                           ett_ntlmssp);
   }
 
   /*
@@ -1964,15 +1975,16 @@ dissect_ntlmssp_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
    * in the packet after our blob to see, so we just re-throw the
    * exception.
    */
+  pd_save = pinfo->private_data;
   TRY {
     /* Version number */
     proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_vers,
-                        tvb, offset, 4, TRUE);
+                         tvb, offset, 4, ENC_LITTLE_ENDIAN);
     offset += 4;
 
     /* Encrypted body */
     proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_body,
-                        tvb, offset, ntlm_signature_size + ntlm_seq_size, TRUE);
+                         tvb, offset, ntlm_signature_size + ntlm_seq_size, ENC_NA);
     tvb_memcpy(tvb, key, offset, ntlm_signature_size + ntlm_seq_size);
     /* Try to decrypt */
     decrypt_data_payload (tvb, offset+(ntlm_signature_size + ntlm_seq_size), encrypted_block_length-(ntlm_signature_size + ntlm_seq_size), pinfo, ntlmssp_tree,key);
@@ -1983,14 +1995,20 @@ dissect_ntlmssp_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
   } CATCH(BoundsError) {
     RETHROW;
   } CATCH(ReportedBoundsError) {
+    /*  Restore the private_data structure in case one of the
+     *  called dissectors modified it (and, due to the exception,
+     *  was unable to restore it).
+     */
+    pinfo->private_data = pd_save;
     show_reported_bounds_error(tvb, pinfo, tree);
   } ENDTRY;
 
   return offset;
 }
-void
+
+static void
 decrypt_data_payload(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
-                packet_info *pinfo, proto_tree *tree _U_,gpointer key)
+                     packet_info *pinfo, proto_tree *tree _U_,gpointer key)
 {
   tvbuff_t *decr_tvb; /* Used to display decrypted buffer */
   guint8 *peer_block;
@@ -2011,23 +2029,23 @@ decrypt_data_payload(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
   if (!packet_ntlmssp_info->payload_decrypted) {
     /* Pull the challenge info from the conversation */
     conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
-                                    pinfo->ptype, pinfo->srcport,
-                                    pinfo->destport, 0);
+                                     pinfo->ptype, pinfo->srcport,
+                                     pinfo->destport, 0);
     if (conversation == NULL) {
       /* There is no conversation, thus no encryption state */
       return ;
     }
 
     conv_ntlmssp_info = conversation_get_proto_data(conversation,
-                                                   proto_ntlmssp);
+                                                    proto_ntlmssp);
     if (conv_ntlmssp_info == NULL) {
       /* There is no NTLMSSP state tied to the conversation */
-           return ;
+      return ;
     }
     if (conv_ntlmssp_info->rc4_state_initialized != 1 ) {
-       /* The crypto sybsystem is not initialized.  This means that either
-                the conversation did not include a challenge, or that we do not have the right password */
-       return;
+      /* The crypto sybsystem is not initialized.  This means that either
+         the conversation did not include a challenge, or that we do not have the right password */
+      return;
     }
     if( key != NULL ){
       stored_packet_ntlmssp_info = g_hash_table_lookup(hash_packet,key);
@@ -2071,7 +2089,7 @@ decrypt_data_payload(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
 
       /* Do the decryption of the payload */
       crypt_rc4(rc4_state, packet_ntlmssp_info->decrypted_payload,
-             encrypted_block_length);
+                encrypted_block_length);
       /* decrypt the verifier */
       /*printnchar(packet_ntlmssp_info->decrypted_payload,encrypted_block_length,"data: ","\n");*/
       /* We setup a temporary buffer so we can re-encrypt the payload after
@@ -2089,12 +2107,13 @@ decrypt_data_payload(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
 
  /* Show the decrypted buffer in a new window */
   decr_tvb = tvb_new_real_data(packet_ntlmssp_info->decrypted_payload,
-                              encrypted_block_length,
-                              encrypted_block_length);
+                               encrypted_block_length,
+                               encrypted_block_length);
 
   tvb_set_child_real_data_tvbuff(tvb, decr_tvb);
   pinfo->gssapi_decrypted_tvb =  decr_tvb;
 }
+
 static void
 dissect_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
@@ -2102,6 +2121,7 @@ dissect_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   proto_tree *volatile ntlmssp_tree = NULL;
   proto_item *tf = NULL;
   ntlmssp_header_t *ntlmssph;
+  void *pd_save;
 
   ntlmssph=ep_alloc(sizeof(ntlmssp_header_t));
   ntlmssph->type=0;
@@ -2112,11 +2132,11 @@ dissect_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   /* Setup a new tree for the NTLMSSP payload */
   if (tree) {
     tf = proto_tree_add_item (tree,
-                             proto_ntlmssp,
-                             tvb, offset, -1, FALSE);
+                              proto_ntlmssp,
+                              tvb, offset, -1, ENC_NA);
 
     ntlmssp_tree = proto_item_add_subtree (tf,
-                                          ett_ntlmssp);
+                                           ett_ntlmssp);
   }
 
   /*
@@ -2131,23 +2151,23 @@ dissect_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
    * in the packet after our blob to see, so we just re-throw the
    * exception.
    */
+  pd_save = pinfo->private_data;
   TRY {
     /* NTLMSSP constant */
     proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_auth,
-                        tvb, offset, 8, FALSE);
+                         tvb, offset, 8, ENC_ASCII|ENC_NA);
     offset += 8;
 
     /* NTLMSSP Message Type */
     proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_message_type,
-                        tvb, offset, 4, TRUE);
+                         tvb, offset, 4, ENC_LITTLE_ENDIAN);
     ntlmssph->type = tvb_get_letohl (tvb, offset);
     offset += 4;
 
-    if (check_col(pinfo->cinfo, COL_INFO))
-           col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
-                           val_to_str(ntlmssph->type,
-                                      ntlmssp_message_types,
-                                      "Unknown message type"));
+    col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ","%s",
+                    val_to_str(ntlmssph->type,
+                               ntlmssp_message_types,
+                               "Unknown message type"));
 
     /* Call the appropriate dissector based on the Message Type */
     switch (ntlmssph->type) {
@@ -2167,18 +2187,35 @@ dissect_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     default:
       /* Unrecognized message type */
       proto_tree_add_text (ntlmssp_tree, tvb, offset, -1,
-                          "Unrecognized NTLMSSP Message");
+                           "Unrecognized NTLMSSP Message");
       break;
     }
   } CATCH(BoundsError) {
     RETHROW;
   } CATCH(ReportedBoundsError) {
+    /*  Restore the private_data structure in case one of the
+     *  called dissectors modified it (and, due to the exception,
+     *  was unable to restore it).
+     */
+    pinfo->private_data = pd_save;
     show_reported_bounds_error(tvb, pinfo, tree);
   } ENDTRY;
 
   /*tap_queue_packet(ntlmssp_tap, pinfo, ntlmssph);*/
 }
 
+static gboolean
+dissect_ntlmssp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
+{
+
+  if(tvb_memeql(tvb, 0, "NTLMSSP", 8) == 0) {
+
+    dissect_ntlmssp(tvb, pinfo, parent_tree);
+    return TRUE;
+  }
+
+  return FALSE;
+}
 
 
 /*
@@ -2186,7 +2223,7 @@ dissect_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
  */
 static void
 decrypt_verifier(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
-                packet_info *pinfo, proto_tree *tree,gpointer key)
+                 packet_info *pinfo, proto_tree *tree,gpointer key)
 {
   proto_tree *decr_tree = NULL;
   proto_item *tf = NULL;
@@ -2210,14 +2247,14 @@ decrypt_verifier(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
     return;
   }
   conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
-                    pinfo->ptype, pinfo->srcport,
-                    pinfo->destport, 0);
+                                   pinfo->ptype, pinfo->srcport,
+                                   pinfo->destport, 0);
   if (conversation == NULL) {
     /* There is no conversation, thus no encryption state */
     return;
   }
   conv_ntlmssp_info = conversation_get_proto_data(conversation,
-                                                   proto_ntlmssp);
+                                                  proto_ntlmssp);
   if (conv_ntlmssp_info == NULL) {
   /* There is no NTLMSSP state tied to the conversation */
     return;
@@ -2235,8 +2272,8 @@ decrypt_verifier(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
     if (!packet_ntlmssp_info->verifier_decrypted) {
       if (conv_ntlmssp_info->rc4_state_initialized != 1 ) {
         /* The crypto sybsystem is not initialized.  This means that either
-        the conversation did not include a challenge, or we are doing
-        something other than NTLMSSP v1 */
+           the conversation did not include a challenge, or we are doing
+           something other than NTLMSSP v1 */
         return;
       }
       if (conv_ntlmssp_info->server_dest_port == pinfo->destport) {
@@ -2257,7 +2294,7 @@ decrypt_verifier(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
 
       /* Setup the buffer to decrypt to */
       tvb_memcpy(tvb, packet_ntlmssp_info->verifier,
-              offset, encrypted_block_length);
+                 offset, encrypted_block_length);
 
       /*if( !(NTLMSSP_NEGOTIATE_KEY_EXCH & packet_ntlmssp_info->flags)) {*/
       if( conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY ) {
@@ -2265,8 +2302,7 @@ decrypt_verifier(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
           /* The spec says that if we have have a key exchange then we have a the signature that is crypted
            * otherwise it's just a hmac_md5(keysign,concat(message,sequence))[0..7]
            */
-          crypt_rc4(rc4_state, packet_ntlmssp_info->verifier,
-               8);
+          crypt_rc4(rc4_state, packet_ntlmssp_info->verifier, 8);
         }
         /*
          * Try to check the HMAC MD5 of the message against those calculated works great with LDAP payload but
@@ -2289,7 +2325,7 @@ decrypt_verifier(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
         /* The packet has a PAD then a checksum then a sequence and they are encoded in this order so we can decrypt all at once */
         /* Do the actual decryption of the verifier */
         crypt_rc4(rc4_state, packet_ntlmssp_info->verifier,
-               encrypted_block_length);
+                  encrypted_block_length);
       }
 
 
@@ -2311,45 +2347,45 @@ decrypt_verifier(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
   }
   /* Show the decrypted buffer in a new window */
   decr_tvb = tvb_new_child_real_data(tvb, packet_ntlmssp_info->verifier,
-                              encrypted_block_length,
-                              encrypted_block_length);
+                                     encrypted_block_length,
+                                     encrypted_block_length);
   add_new_data_source(pinfo, decr_tvb,
-                     "Decrypted NTLMSSP Verifier");
+                      "Decrypted NTLMSSP Verifier");
 
   /* Show the decrypted payload in the tree */
   tf = proto_tree_add_text(tree, decr_tvb, 0, -1,
-                          "Decrypted Verifier (%d byte%s)",
-                          encrypted_block_length,
-                          plurality(encrypted_block_length, "", "s"));
+                           "Decrypted Verifier (%d byte%s)",
+                           encrypted_block_length,
+                           plurality(encrypted_block_length, "", "s"));
   decr_tree = proto_item_add_subtree (tf, ett_ntlmssp);
 
   if(( conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY )) {
     proto_tree_add_item (decr_tree, hf_ntlmssp_verf_hmacmd5,
-                      decr_tvb, decrypted_offset, 8,TRUE);
+                         decr_tvb, decrypted_offset, 8,ENC_NA);
     decrypted_offset += 8;
 
 
 
     /* Incrementing sequence number of DCE conversation */
    proto_tree_add_item (decr_tree, hf_ntlmssp_verf_sequence,
-                        decr_tvb, decrypted_offset, 4, TRUE);
+                        decr_tvb, decrypted_offset, 4, ENC_NA);
     decrypted_offset += 4;
   }
   else {
 
     /* RANDOM PAD usually it's 0 */
     proto_tree_add_item (decr_tree, hf_ntlmssp_verf_randompad,
-                      decr_tvb, decrypted_offset, 4, TRUE);
+                         decr_tvb, decrypted_offset, 4, ENC_LITTLE_ENDIAN);
     decrypted_offset += 4;
 
     /* CRC32 of the DCE fragment data */
     proto_tree_add_item (decr_tree, hf_ntlmssp_verf_crc32,
-                      decr_tvb, decrypted_offset, 4, TRUE);
+                         decr_tvb, decrypted_offset, 4, ENC_LITTLE_ENDIAN);
     decrypted_offset += 4;
 
     /* Incrementing sequence number of DCE conversation */
    proto_tree_add_item (decr_tree, hf_ntlmssp_verf_sequence,
-                        decr_tvb, decrypted_offset, 4, TRUE);
+                        decr_tvb, decrypted_offset, 4, ENC_NA);
     decrypted_offset += 4;
   }
 }
@@ -2361,22 +2397,24 @@ dissect_ntlmssp_payload_only(tvbuff_t *tvb, packet_info *pinfo, _U_ proto_tree *
   volatile int offset = 0;
   proto_tree *volatile ntlmssp_tree = NULL;
   guint32 encrypted_block_length;
+  void *pd_save;
+
   /* the magic ntlm is the identifier of a NTLMSSP packet that's 00 00 00 01
    */
   encrypted_block_length = tvb_length (tvb);
   /* signature + seq + real payload */
 
   /* Setup a new tree for the NTLMSSP payload */
-  /*
+#if 0
   if (tree) {
     tf = proto_tree_add_item (tree,
-                             hf_ntlmssp_verf,
-                             tvb, offset, -1, FALSE);
+                              hf_ntlmssp_verf,
+                              tvb, offset, -1, ENC_NA);
 
     ntlmssp_tree = proto_item_add_subtree (tf,
-                                          ett_ntlmssp);
+                                           ett_ntlmssp);
   }
-  */
+#endif
   /*
    * Catch the ReportedBoundsError exception; the stuff we've been
    * handed doesn't necessarily run to the end of the packet, it's
@@ -2389,6 +2427,7 @@ dissect_ntlmssp_payload_only(tvbuff_t *tvb, packet_info *pinfo, _U_ proto_tree *
    * in the packet after our blob to see, so we just re-throw the
    * exception.
    */
+  pd_save = pinfo->private_data;
   TRY {
     /* Version number */
 
@@ -2399,11 +2438,17 @@ dissect_ntlmssp_payload_only(tvbuff_t *tvb, packet_info *pinfo, _U_ proto_tree *
   } CATCH(BoundsError) {
     RETHROW;
   } CATCH(ReportedBoundsError) {
+    /*  Restore the private_data structure in case one of the
+     *  called dissectors modified it (and, due to the exception,
+     *  was unable to restore it).
+     */
+    pinfo->private_data = pd_save;
     show_reported_bounds_error(tvb, pinfo, tree);
   } ENDTRY;
 
   return offset;
 }
+
 /* Used when NTLMSSP is done over DCE/RPC because in this case verifier and real payload are not contigious
  * But in fact this function could be merged with wrap_dissect_ntlmssp_verf because it's only used there
  */
@@ -2415,6 +2460,7 @@ dissect_ntlmssp_verf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   proto_item *tf = NULL;
   guint32 verifier_length;
   guint32 encrypted_block_length;
+  void *pd_save;
 
   verifier_length = tvb_length (tvb);
   encrypted_block_length = verifier_length - 4;
@@ -2428,11 +2474,11 @@ dissect_ntlmssp_verf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   /* Setup a new tree for the NTLMSSP payload */
   if (tree) {
     tf = proto_tree_add_item (tree,
-                             hf_ntlmssp_verf,
-                             tvb, offset, -1, FALSE);
+                              hf_ntlmssp_verf,
+                              tvb, offset, -1, ENC_NA);
 
     ntlmssp_tree = proto_item_add_subtree (tf,
-                                          ett_ntlmssp);
+                                           ett_ntlmssp);
   }
 
   /*
@@ -2447,15 +2493,16 @@ dissect_ntlmssp_verf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
    * in the packet after our blob to see, so we just re-throw the
    * exception.
    */
+  pd_save = pinfo->private_data;
   TRY {
     /* Version number */
     proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_vers,
-                        tvb, offset, 4, TRUE);
+                         tvb, offset, 4, ENC_LITTLE_ENDIAN);
     offset += 4;
 
     /* Encrypted body */
     proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_body,
-                        tvb, offset, encrypted_block_length, TRUE);
+                         tvb, offset, encrypted_block_length, ENC_NA);
 
     /* Try to decrypt */
     decrypt_verifier (tvb, offset, encrypted_block_length, pinfo, ntlmssp_tree,NULL);
@@ -2466,6 +2513,11 @@ dissect_ntlmssp_verf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   } CATCH(BoundsError) {
     RETHROW;
   } CATCH(ReportedBoundsError) {
+    /*  Restore the private_data structure in case one of the
+     *  called dissectors modified it (and, due to the exception,
+     *  was unable to restore it).
+     */
+    pinfo->private_data = pd_save;
     show_reported_bounds_error(tvb, pinfo, tree);
   } ENDTRY;
 
@@ -2474,27 +2526,27 @@ dissect_ntlmssp_verf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
 static tvbuff_t *
 wrap_dissect_ntlmssp_payload_only(tvbuff_t *tvb,tvbuff_t *auth_tvb _U_,
- int offset, packet_info *pinfo,dcerpc_auth_info *auth_info _U_)
                                 int offset, packet_info *pinfo,dcerpc_auth_info *auth_info _U_)
 {
-       tvbuff_t *data_tvb;
+  tvbuff_t *data_tvb;
 
-       data_tvb = tvb_new_subset(
-               tvb, offset, tvb_length_remaining(tvb, offset),
-               tvb_length_remaining(tvb, offset));
-       dissect_ntlmssp_payload_only(data_tvb, pinfo, NULL);
+  data_tvb = tvb_new_subset(
+    tvb, offset, tvb_length_remaining(tvb, offset),
+    tvb_length_remaining(tvb, offset));
+  dissect_ntlmssp_payload_only(data_tvb, pinfo, NULL);
   return pinfo->gssapi_decrypted_tvb;
 }
 
 #if 0
-tvbuff_t *
+static tvbuff_t *
 dissect_ntlmssp_encrypted_payload(tvbuff_t *data_tvb,
-                                 tvbuff_t *auth_tvb _U_,
-                                 int offset,
-                                 packet_info *pinfo,
-                                 dcerpc_auth_info *auth_info _U_)
+                                  tvbuff_t *auth_tvb _U_,
+                                  int offset,
+                                  packet_info *pinfo,
+                                  dcerpc_auth_info *auth_info _U_)
 {
-  / * gssapi_decrypted_tvb=NULL * /
-  tvbuff_t *decr_tvb; / * Used to display decrypted buffer * /
+  /* gssapi_decrypted_tvb=NULL */
+  tvbuff_t *decr_tvb; /* Used to display decrypted buffer */
   guint8 *peer_block;
   conversation_t *conversation;
   guint32 encrypted_block_length;
@@ -2505,33 +2557,33 @@ dissect_ntlmssp_encrypted_payload(tvbuff_t *data_tvb,
   encrypted_block_length = tvb_length_remaining (data_tvb, offset);
 
   fprintf(stderr,"Called dissect_ntlmssp_encrypted_payload\n");
-  / * Check to see if we already have state for this packet * /
+  /* Check to see if we already have state for this packet */
   packet_ntlmssp_info = p_get_proto_data(pinfo->fd, proto_ntlmssp);
   if (packet_ntlmssp_info == NULL) {
-    / * We don't have any packet state, so create one * /
+    /* We don't have any packet state, so create one */
     packet_ntlmssp_info = se_alloc0(sizeof(ntlmssp_packet_info));
     p_add_proto_data(pinfo->fd, proto_ntlmssp, packet_ntlmssp_info);
   }
 
   if (!packet_ntlmssp_info->payload_decrypted) {
-    / * Pull the challenge info from the conversation * /
+    /* Pull the challenge info from the conversation */
     conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
-                                    pinfo->ptype, pinfo->srcport,
-                                    pinfo->destport, 0);
+                                     pinfo->ptype, pinfo->srcport,
+                                     pinfo->destport, 0);
     if (conversation == NULL) {
-      / * There is no conversation, thus no encryption state * /
+      /* There is no conversation, thus no encryption state */
       return NULL;
 
     }
     conv_ntlmssp_info = conversation_get_proto_data(conversation,
-                                                   proto_ntlmssp);
+                                                    proto_ntlmssp);
     if (conv_ntlmssp_info == NULL) {
-    / * There is no NTLMSSP state tied to the conversation * /
+    /* There is no NTLMSSP state tied to the conversation */
     return NULL;
     }
-    / * Get the pair of RC4 state structures.  One is used for to decrypt the
+    /* Get the pair of RC4 state structures.  One is used for to decrypt the
        payload.  The other is used to re-encrypt the payload to represent
-       the peer * /
+       the peer */
     if (conv_ntlmssp_info->server_dest_port == pinfo->destport) {
       rc4_state = get_encrypted_state(pinfo, 1);
       rc4_state_peer = get_encrypted_state(pinfo, 0);
@@ -2541,33 +2593,33 @@ dissect_ntlmssp_encrypted_payload(tvbuff_t *data_tvb,
     }
 
     if (rc4_state == NULL || rc4_state_peer == NULL) {
-      / * There is no encryption state, so we cannot decrypt * /
+      /* There is no encryption state, so we cannot decrypt */
       return NULL;
     }
 
-    / * Store the decrypted contents in the packet state struct
-       (of course at this point, they aren't decrypted yet) * /
+    /* Store the decrypted contents in the packet state struct
+       (of course at this point, they aren't decrypted yet) */
     packet_ntlmssp_info->decrypted_payload = tvb_memdup(data_tvb, offset,
                                                         encrypted_block_length);
     decrypted_payloads = g_slist_prepend(decrypted_payloads,
                                          packet_ntlmssp_info->decrypted_payload);
 
-    / * Do the decryption of the payload * /
+    /* Do the decryption of the payload */
     crypt_rc4(rc4_state, packet_ntlmssp_info->decrypted_payload,
-             encrypted_block_length);
+              encrypted_block_length);
 
-    / * We setup a temporary buffer so we can re-encrypt the payload after
-       decryption.  This is to update the opposite peer's RC4 state * /
+    /* We setup a temporary buffer so we can re-encrypt the payload after
+       decryption.  This is to update the opposite peer's RC4 state */
     peer_block = ep_memdup(packet_ntlmssp_info->decrypted_payload, encrypted_block_length);
     crypt_rc4(rc4_state_peer, peer_block, encrypted_block_length);
 
     packet_ntlmssp_info->payload_decrypted = TRUE;
   }
 
-  / * Show the decrypted buffer in a new window * /
+  /* Show the decrypted buffer in a new window */
   decr_tvb = tvb_new_child_real_data(data_tvb, packet_ntlmssp_info->decrypted_payload,
-                              encrypted_block_length,
-                              encrypted_block_length);
+                                     encrypted_block_length,
+                                     encrypted_block_length);
 
   offset += encrypted_block_length;
 
@@ -2578,16 +2630,20 @@ dissect_ntlmssp_encrypted_payload(tvbuff_t *data_tvb,
 static void
 free_payload(gpointer decrypted_payload, gpointer user_data _U_)
 {
-       g_free(decrypted_payload);
+  g_free(decrypted_payload);
 }
 
-guint g_header_hash(gconstpointer pointer) {
+static guint
+header_hash(gconstpointer pointer)
+{
   guint32 crc =  ~crc32c_calculate(pointer,NTLMSSP_KEY_LEN,CRC32C_PRELOAD);
   /* Mat TBD fprintf(stderr,"Val: %u\n",crc);*/
   return crc;
 }
 
-gboolean g_header_equal(gconstpointer pointer1, gconstpointer pointer2) {
+static gboolean
+header_equal(gconstpointer pointer1, gconstpointer pointer2)
+{
   if(!memcmp(pointer1,pointer2,16)) {
     return TRUE;
   }
@@ -2599,24 +2655,71 @@ gboolean g_header_equal(gconstpointer pointer1, gconstpointer pointer2) {
 static void
 ntlmssp_init_protocol(void)
 {
-       /*
-        * Free the decrypted payloads, and then free the list of decrypted
-        * payloads.
-        */
-       if (decrypted_payloads != NULL) {
-               g_slist_foreach(decrypted_payloads, free_payload, NULL);
-               g_slist_free(decrypted_payloads);
-               decrypted_payloads = NULL;
-       }
+  /*
+   * Free the decrypted payloads, and then free the list of decrypted
+   * payloads.
+   */
+  if (decrypted_payloads != NULL) {
+    g_slist_foreach(decrypted_payloads, free_payload, NULL);
+    g_slist_free(decrypted_payloads);
+    decrypted_payloads = NULL;
+  }
 
   if(hash_packet == NULL) {
-    hash_packet = g_hash_table_new(g_header_hash,g_header_equal);
+    hash_packet = g_hash_table_new(header_hash, header_equal);
   }
 
 }
 
 
 
+static int
+wrap_dissect_ntlmssp(tvbuff_t *tvb, int offset, packet_info *pinfo,
+                     proto_tree *tree, guint8 *drep _U_)
+{
+  tvbuff_t *auth_tvb;
+
+  auth_tvb = tvb_new_subset(
+    tvb, offset, tvb_length_remaining(tvb, offset),
+    tvb_length_remaining(tvb, offset));
+
+  dissect_ntlmssp(auth_tvb, pinfo, tree);
+
+  return tvb_length_remaining(tvb, offset);
+}
+
+static int
+wrap_dissect_ntlmssp_verf(tvbuff_t *tvb, int offset, packet_info *pinfo,
+                          proto_tree *tree, guint8 *drep _U_)
+{
+  tvbuff_t *auth_tvb;
+
+  auth_tvb = tvb_new_subset(
+    tvb, offset, tvb_length_remaining(tvb, offset),
+    tvb_length_remaining(tvb, offset));
+  return dissect_ntlmssp_verf(auth_tvb, pinfo, tree);
+}
+
+static dcerpc_auth_subdissector_fns ntlmssp_sign_fns = {
+  wrap_dissect_ntlmssp,                 /* Bind */
+  wrap_dissect_ntlmssp,                 /* Bind ACK */
+  wrap_dissect_ntlmssp,                 /* AUTH3 */
+  wrap_dissect_ntlmssp_verf,            /* Request verifier */
+  wrap_dissect_ntlmssp_verf,            /* Response verifier */
+  NULL,                                 /* Request data */
+  NULL                                  /* Response data */
+};
+
+static dcerpc_auth_subdissector_fns ntlmssp_seal_fns = {
+  wrap_dissect_ntlmssp,                 /* Bind */
+  wrap_dissect_ntlmssp,                 /* Bind ACK */
+  wrap_dissect_ntlmssp,                 /* AUTH3 */
+  wrap_dissect_ntlmssp_verf,            /* Request verifier */
+  wrap_dissect_ntlmssp_verf,            /* Response verifier */
+  wrap_dissect_ntlmssp_payload_only,    /* Request data */
+  wrap_dissect_ntlmssp_payload_only     /* Response data */
+};
+
 void
 proto_register_ntlmssp(void)
 {
@@ -2666,6 +2769,8 @@ proto_register_ntlmssp(void)
       { "Target Type Server", "ntlmssp.targettypeserver", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_TARGET_TYPE_SERVER, NULL, HFILL }},
     { &hf_ntlmssp_negotiate_flags_40000,
       { "Target Type Share", "ntlmssp.targettypeshare", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_TARGET_TYPE_SHARE, NULL, HFILL }},
+
+/* Negotiate Flags */
     { &hf_ntlmssp_negotiate_flags_80000,
       { "Negotiate Extended Security", "ntlmssp.negotiatentlm2", FT_BOOLEAN, 32, TFS (&tfs_set_notset), NTLMSSP_NEGOTIATE_EXTENDED_SECURITY, NULL, HFILL }},
     { &hf_ntlmssp_negotiate_flags_100000,
@@ -2714,6 +2819,7 @@ proto_register_ntlmssp(void)
       { "NTLM Server Challenge", "ntlmssp.ntlmserverchallenge", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
     { &hf_ntlmssp_reserved,
       { "Reserved", "ntlmssp.reserved", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+
     { &hf_ntlmssp_challenge_target_name,
       { "Target Name", "ntlmssp.challenge.target_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
     { &hf_ntlmssp_auth_domain,
@@ -2740,40 +2846,83 @@ proto_register_ntlmssp(void)
       { "Maxlen", "ntlmssp.blob.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
     { &hf_ntlmssp_blob_offset,
       { "Offset", "ntlmssp.blob.offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
+    { &hf_ntlmssp_version,
+      { "Version", "ntlmssp.version", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
     { &hf_ntlmssp_version_major,
       { "Major Version", "ntlmssp.version.major", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
     { &hf_ntlmssp_version_minor,
       { "Minor Version", "ntlmssp.version.minor", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
     { &hf_ntlmssp_version_build_number,
-      { "Major Version", "ntlmssp.version.build_number", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
+      { "Build Number", "ntlmssp.version.build_number", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
     { &hf_ntlmssp_version_ntlm_current_revision,
       { "NTLM Current Revision", "ntlmssp.version.ntlm_current_revision", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
-    { &hf_ntlmssp_address_list,
-      { "Address List", "ntlmssp.challenge.addresslist", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
-    { &hf_ntlmssp_address_list_len,
-      { "Length", "ntlmssp.challenge.addresslist.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
-    { &hf_ntlmssp_address_list_maxlen,
-      { "Maxlen", "ntlmssp.challenge.addresslist.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
-    { &hf_ntlmssp_address_list_offset,
-      { "Offset", "ntlmssp.challenge.addresslist.offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
-    { &hf_ntlmssp_address_list_item_type,
-      { "Target item type", "ntlmssp.targetitemtype", FT_UINT16, BASE_HEX, VALS(ntlm_name_types), 0x0, NULL, HFILL }},
-    { &hf_ntlmssp_address_list_item_len,
-      { "Target item Length", "ntlmssp.challenge.addresslist.item.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
-    { &hf_ntlmssp_address_list_item_content,
-      { "Target item Content", "ntlmssp.challenge.addresslist.item.content", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}},
-    { &hf_ntlmssp_address_list_server_nb,
-      { "Server NetBIOS Name", "ntlmssp.challenge.addresslist.servernb", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
-    { &hf_ntlmssp_address_list_domain_nb,
-      { "Domain NetBIOS Name", "ntlmssp.challenge.addresslist.domainnb", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
-    { &hf_ntlmssp_address_list_server_dns,
-      { "Server DNS Name", "ntlmssp.challenge.addresslist.serverdns", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
-    { &hf_ntlmssp_address_list_domain_dns,
-      { "Domain DNS Name", "ntlmssp.challenge.addresslist.domaindns", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
-    { &hf_ntlmssp_address_list_forest_dns,
-      { "Forest DNS Name", "ntlmssp.challenge.addresslist.forestdns", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
-    { &hf_ntlmssp_address_list_terminator,
-      { "List Terminator", "ntlmssp.challenge.addresslist.terminator", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+
+/* Target Info */
+    { &hf_ntlmssp_challenge_target_info,
+      { "Target Info", "ntlmssp.challenge.target_info", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
+    { &hf_ntlmssp_challenge_target_info_len,
+      { "Length", "ntlmssp.challenge.target_info.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
+    { &hf_ntlmssp_challenge_target_info_maxlen,
+      { "Maxlen", "ntlmssp.challenge.target_info.maxlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
+    { &hf_ntlmssp_challenge_target_info_offset,
+      { "Offset", "ntlmssp.challenge.target_info.offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
+
+    { &hf_ntlmssp_challenge_target_info_item_type,
+      { "Target Info Item Type", "ntlmssp.challenge.target_info.item.type", FT_UINT16, BASE_HEX, VALS(ntlm_name_types), 0x0, NULL, HFILL }},
+    { &hf_ntlmssp_challenge_target_info_item_len,
+      { "Target Info Item Length", "ntlmssp.challenge.target_info.item.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
+
+    { &hf_ntlmssp_challenge_target_info_end,
+      { "List End", "ntlmssp.challenge.target_info.end", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+    { &hf_ntlmssp_challenge_target_info_nb_computer_name,
+      { "NetBIOS Computer Name", "ntlmssp.challenge.target_info.nb_computer_name", FT_STRING, BASE_NONE, NULL, 0x0, "Server NetBIOS Computer Name", HFILL }},
+    { &hf_ntlmssp_challenge_target_info_nb_domain_name,
+      { "NetBIOS Domain Name", "ntlmssp.challenge.target_info.nb_domain_name", FT_STRING, BASE_NONE, NULL, 0x0, "Server NetBIOS Domain Name", HFILL }},
+    { &hf_ntlmssp_challenge_target_info_dns_computer_name,
+      { "DNS Computer Name", "ntlmssp.challenge.target_info.dns_computer_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+    { &hf_ntlmssp_challenge_target_info_dns_domain_name,
+      { "DNS Domain Name", "ntlmssp.challenge.target_info.dns_domain_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+    { &hf_ntlmssp_challenge_target_info_dns_tree_name,
+      { "DNS Tree Name", "ntlmssp.challenge.target_info.dns_tree_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+    { &hf_ntlmssp_challenge_target_info_flags,
+      { "Flags", "ntlmssp.challenge.target_info.flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+    { &hf_ntlmssp_challenge_target_info_timestamp,
+      { "Timestamp", "ntlmssp.challenge.target_info.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, NULL, HFILL }},
+    { &hf_ntlmssp_challenge_target_info_restrictions,
+      { "Restrictions", "ntlmssp.challenge.target_info.restrictions", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
+    { &hf_ntlmssp_challenge_target_info_target_name,
+      { "Target Name", "ntlmssp.challenge.target_info.target_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+    { &hf_ntlmssp_challenge_target_info_channel_bindings,
+      { "Channel Bindings", "ntlmssp.challenge.target_info.channel_bindings", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+
+    { &hf_ntlmssp_ntlmv2_response_item_type,
+      { "NTLMV2 Response Item Type", "ntlmssp.ntlmv2_response.item.type", FT_UINT16, BASE_HEX, VALS(ntlm_name_types), 0x0, NULL, HFILL }},
+    { &hf_ntlmssp_ntlmv2_response_item_len,
+      { "NTLMV2 Response Item Length", "ntlmssp.ntlmv2_response.item.length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
+
+    { &hf_ntlmssp_ntlmv2_response_end,
+      { "List End", "ntlmssp.ntlmv2_response.end", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+    { &hf_ntlmssp_ntlmv2_response_nb_computer_name,
+      { "NetBIOS Computer Name", "ntlmssp.ntlmv2_response.nb_computer_name", FT_STRING, BASE_NONE, NULL, 0x0, "Server NetBIOS Computer Name", HFILL }},
+    { &hf_ntlmssp_ntlmv2_response_nb_domain_name,
+      { "NetBIOS Domain Name", "ntlmssp.ntlmv2_response.nb_domain_name", FT_STRING, BASE_NONE, NULL, 0x0, "Server NetBIOS Domain Name", HFILL }},
+    { &hf_ntlmssp_ntlmv2_response_dns_computer_name,
+      { "DNS Computer Name", "ntlmssp.ntlmv2_response.dns_computer_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+    { &hf_ntlmssp_ntlmv2_response_dns_domain_name,
+      { "DNS Domain Name", "ntlmssp.ntlmv2_response.dns_domain_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+    { &hf_ntlmssp_ntlmv2_response_dns_tree_name,
+      { "DNS Tree Name", "ntlmssp.ntlmv2_response.dns_tree_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+    { &hf_ntlmssp_ntlmv2_response_flags,
+      { "Flags", "ntlmssp.ntlmv2_response.flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+    { &hf_ntlmssp_ntlmv2_response_timestamp,
+      { "Timestamp", "ntlmssp.ntlmv2_response.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, NULL, HFILL }},
+    { &hf_ntlmssp_ntlmv2_response_restrictions,
+      { "Restrictions", "ntlmssp.ntlmv2_response.restrictions", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
+    { &hf_ntlmssp_ntlmv2_response_target_name,
+      { "Target Name", "ntlmssp.ntlmv2_response.target_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+    { &hf_ntlmssp_ntlmv2_response_channel_bindings,
+      { "Channel Bindings", "ntlmssp.ntlmv2_response.channel_bindings", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+
     { &hf_ntlmssp_message_integrity_code,
       { "MIC", "ntlmssp.authenticate.mic", FT_BYTES, BASE_NONE, NULL, 0x0, "Message Integrity Code", HFILL}},
     { &hf_ntlmssp_verf,
@@ -2792,30 +2941,21 @@ proto_register_ntlmssp(void)
       { "HMAC MD5", "ntlmssp.verf.hmacmd5", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
     { &hf_ntlmssp_verf_sequence,
       { "Sequence", "ntlmssp.verf.sequence", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+
     { &hf_ntlmssp_ntlmv2_response,
-      { "NTLMv2 Response", "ntlmssp.ntlmv2response", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+      { "NTLMv2 Response", "ntlmssp.ntlmv2_response", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
     { &hf_ntlmssp_ntlmv2_response_hmac,
-      { "HMAC", "ntlmssp.ntlmv2response.hmac", FT_BYTES, BASE_NONE,  NULL, 0x0, NULL, HFILL }},
+      { "HMAC", "ntlmssp.ntlmv2_response.hmac", FT_BYTES, BASE_NONE,  NULL, 0x0, NULL, HFILL }},
     { &hf_ntlmssp_ntlmv2_response_header,
-      { "Header", "ntlmssp.ntlmv2response.header", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+      { "Header", "ntlmssp.ntlmv2_response.header", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
     { &hf_ntlmssp_ntlmv2_response_reserved,
-      { "Reserved", "ntlmssp.ntlmv2response.reserved", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
+      { "Reserved", "ntlmssp.ntlmv2_response.reserved", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
     { &hf_ntlmssp_ntlmv2_response_time,
-      { "Time", "ntlmssp.ntlmv2response.time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, NULL, HFILL }},
+      { "Time", "ntlmssp.ntlmv2_response.time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, NULL, HFILL }},
     { &hf_ntlmssp_ntlmv2_response_chal,
-      { "Client challenge", "ntlmssp.ntlmv2response.chal", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+      { "Client challenge", "ntlmssp.ntlmv2_response.chal", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
     { &hf_ntlmssp_ntlmv2_response_unknown,
-      { "Unknown", "ntlmssp.ntlmv2response.unknown", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
-    { &hf_ntlmssp_ntlmv2_response_name,
-      { "Attribute", "ntlmssp.ntlmv2response.name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
-    { &hf_ntlmssp_ntlmv2_response_name_type,
-      { "Attribute type", "ntlmssp.ntlmv2response.name.type", FT_UINT32, BASE_DEC, VALS(ntlm_name_types), 0x0, NULL, HFILL }},
-    { &hf_ntlmssp_ntlmv2_response_name_len,
-      { "Value len", "ntlmssp.ntlmv2response.name.len", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
-    { &hf_ntlmssp_ntlmv2_response_restriction,
-      { "Encoding restrictions", "ntlmssp.ntlmv2response.name.restrictions", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
-    { &hf_ntlmssp_ntlmv2_response_client_time,
-      { "Client Time", "ntlmssp.ntlmv2response.client_time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, NULL, HFILL }}
+      { "Unknown", "ntlmssp.ntlmv2_response.unknown", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}
   };
 
 
@@ -2825,18 +2965,18 @@ proto_register_ntlmssp(void)
     &ett_ntlmssp_string,
     &ett_ntlmssp_blob,
     &ett_ntlmssp_version,
-    &ett_ntlmssp_address_list,
-    &ett_ntlmssp_address_list_item,
+    &ett_ntlmssp_challenge_target_info,
+    &ett_ntlmssp_challenge_target_info_item,
     &ett_ntlmssp_ntlmv2_response,
-    &ett_ntlmssp_ntlmv2_response_name
+    &ett_ntlmssp_ntlmv2_response_item,
   };
   module_t *ntlmssp_module;
 
   proto_ntlmssp = proto_register_protocol (
-                                          "NTLM Secure Service Provider", /* name */
-                                          "NTLMSSP",   /* short name */
-                                          "ntlmssp"    /* abbrev */
-                                          );
+    "NTLM Secure Service Provider", /* name */
+    "NTLMSSP",  /* short name */
+    "ntlmssp"   /* abbrev */
+    );
   proto_register_field_array (proto_ntlmssp, hf, array_length (hf));
   proto_register_subtree_array (ett, array_length (ett));
   register_init_routine(&ntlmssp_init_protocol);
@@ -2844,9 +2984,9 @@ proto_register_ntlmssp(void)
   ntlmssp_module = prefs_register_protocol(proto_ntlmssp, NULL);
 
   prefs_register_string_preference(ntlmssp_module, "nt_password",
-                                  "NT Password",
-                                  "NT Password (used to decrypt payloads)",
-                                  &gbl_nt_password);
+                                   "NT Password",
+                                   "NT Password (used to decrypt payloads)",
+                                   &gbl_nt_password);
 
   register_dissector("ntlmssp", dissect_ntlmssp, proto_ntlmssp);
   new_register_dissector("ntlmssp_payload", dissect_ntlmssp_payload, proto_ntlmssp);
@@ -2854,51 +2994,6 @@ proto_register_ntlmssp(void)
   new_register_dissector("ntlmssp_verf", dissect_ntlmssp_verf, proto_ntlmssp);
 }
 
-static int wrap_dissect_ntlmssp(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                               proto_tree *tree, guint8 *drep _U_)
-{
-       tvbuff_t *auth_tvb;
-
-       auth_tvb = tvb_new_subset(
-               tvb, offset, tvb_length_remaining(tvb, offset),
-               tvb_length_remaining(tvb, offset));
-
-       dissect_ntlmssp(auth_tvb, pinfo, tree);
-
-       return tvb_length_remaining(tvb, offset);
-}
-
-static int wrap_dissect_ntlmssp_verf(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                                    proto_tree *tree, guint8 *drep _U_)
-{
-       tvbuff_t *auth_tvb;
-
-       auth_tvb = tvb_new_subset(
-               tvb, offset, tvb_length_remaining(tvb, offset),
-               tvb_length_remaining(tvb, offset));
-       return dissect_ntlmssp_verf(auth_tvb, pinfo, tree);
-}
-
-static dcerpc_auth_subdissector_fns ntlmssp_sign_fns = {
-       wrap_dissect_ntlmssp,                   /* Bind */
-       wrap_dissect_ntlmssp,                   /* Bind ACK */
-       wrap_dissect_ntlmssp,                   /* AUTH3 */
-       wrap_dissect_ntlmssp_verf,              /* Request verifier */
-       wrap_dissect_ntlmssp_verf,              /* Response verifier */
-       NULL,                                   /* Request data */
-       NULL                                    /* Response data */
-};
-
-static dcerpc_auth_subdissector_fns ntlmssp_seal_fns = {
-       wrap_dissect_ntlmssp,                   /* Bind */
-       wrap_dissect_ntlmssp,                   /* Bind ACK */
-       wrap_dissect_ntlmssp,                   /* AUTH3 */
-       wrap_dissect_ntlmssp_verf,              /* Request verifier */
-       wrap_dissect_ntlmssp_verf,              /* Response verifier */
-       wrap_dissect_ntlmssp_payload_only,      /* Request data */
-       wrap_dissect_ntlmssp_payload_only       /* Response data */
-};
-
 void
 proto_reg_handoff_ntlmssp(void)
 {
@@ -2909,8 +3004,8 @@ proto_reg_handoff_ntlmssp(void)
   ntlmssp_handle = find_dissector("ntlmssp");
   ntlmssp_wrap_handle = find_dissector("ntlmssp_verf");
   gssapi_init_oid("1.3.6.1.4.1.311.2.2.10", proto_ntlmssp, ett_ntlmssp,
-                 ntlmssp_handle, ntlmssp_wrap_handle,
-                 "NTLMSSP - Microsoft NTLM Security Support Provider");
+                  ntlmssp_handle, ntlmssp_wrap_handle,
+                  "NTLMSSP - Microsoft NTLM Security Support Provider");
 
   /* Register authenticated pipe dissector */
 
@@ -2923,21 +3018,24 @@ proto_reg_handoff_ntlmssp(void)
    * any other levels here?
    */
   register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_CONNECT,
-                                   DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
-                                   &ntlmssp_sign_fns);
+                                    DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
+                                    &ntlmssp_sign_fns);
 
   register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT,
-                                   DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
-                                   &ntlmssp_sign_fns);
+                                    DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
+                                    &ntlmssp_sign_fns);
 
   register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_INTEGRITY,
-                                   DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
-                                   &ntlmssp_sign_fns);
+                                    DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
+                                    &ntlmssp_sign_fns);
 
   register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_PKT_PRIVACY,
-                                   DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
-                                   &ntlmssp_seal_fns);
+                                    DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
+                                    &ntlmssp_seal_fns);
   ntlmssp_tap = register_tap("ntlmssp");
+
+  heur_dissector_add("credssp", dissect_ntlmssp_heur, proto_ntlmssp);
+
 }
 
 /*
@@ -2949,6 +3047,6 @@ proto_reg_handoff_ntlmssp(void)
  * indent-tabs-mode: nil
  * End:
  *
- * vi: set shiftwidth=2 tabstop=8 expandtab
+ * vi: set shiftwidth=2 tabstop=8 expandtab:
  * :indentSize=2:tabSize=8:noTabs=true:
  */