[Patch] Support for LDAP with GSSAPI/NTLMSSP auth scheme decoding in wireshark

Matthieu Patou mat+Informatique.Samba at matws.net
Sat Apr 25 13:48:26 GMT 2009


Hello Metze, and the samba team,

I finally finished my patch to support NTLMSSP auth in LDAP.
As metze proposed I add the option that read all the keytab that were 
provided, and try all the encoded password inside it.

It seems to work quite well, I tried with a few keytab generated for 
pure "traditional" LDAP with kerberos auth and I've been able to decode 
(well if the keytab contains the md4(password) of the user trying to 
authenticate himself).
I'm quite surprised that when "extracting" crypted password in a keytab 
they are only stored by using md4(unicode(password))) even if we ask 
keytab to use arc4_hmac (but I'm far from being well aware of all in 
kerberos ...).

Concerning protocols, I tested NTLM v1 and NTLM v2, for NTLM v1 I tested 
mostly with extended security flags so for less secure (and maybe not 
anymore really used ?) scheme (like pure lan manager auth or simple nt 
auth) problems might still exist.

It would be just great if you can provide me some feedback, in anycase 
my goal is to submit it to wireshark devs soon.

Matthieu

-------------- next part --------------
--- ../ref_wr/wireshark-1.1.3-SVN-27393/epan/dissectors/packet-ntlmssp.c	2009-02-08 19:13:59.000000000 +0300
+++ epan/dissectors/packet-ntlmssp.c	2009-04-25 17:08:16.887933595 +0400
@@ -27,7 +27,7 @@
 #ifdef HAVE_CONFIG_H
 # include "config.h"
 #endif
-
+#include <unistd.h>
 #include <string.h>
 #include <ctype.h>
 
@@ -37,14 +37,18 @@
 #include "packet-windows-common.h"
 #include "packet-smb-common.h"
 #include "packet-frame.h"
+#include <epan/asn1.h>
+#include "packet-kerberos.h"
 #include <epan/prefs.h>
 #include <epan/emem.h>
 #include <epan/tap.h>
 #include <epan/crypt/crypt-rc4.h>
 #include <epan/crypt/crypt-md4.h>
+#include <epan/crypt/crypt-md5.h>
 #include <epan/crypt/crypt-des.h>
 #include "packet-dcerpc.h"
 #include "packet-gssapi.h"
+#include <epan/crc32.h>
 
 #include "packet-ntlmssp.h"
 
@@ -56,6 +60,10 @@
 #define NTLMSSP_CHALLENGE 2
 #define NTLMSSP_AUTH      3
 #define NTLMSSP_UNKNOWN   4
+#define CLIENT_SIGN_TEXT "session key to client-to-server signing key magic constant"
+#define CLIENT_SEAL_TEXT "session key to client-to-server sealing key magic constant"
+#define SERVER_SIGN_TEXT "session key to server-to-client signing key magic constant"
+#define SERVER_SEAL_TEXT "session key to server-to-client sealing key magic constant"
 
 static const value_string ntlmssp_message_types[] = {
   { NTLMSSP_NEGOTIATE, "NTLMSSP_NEGOTIATE" },
@@ -65,6 +73,13 @@
   { 0, NULL }
 };
 
+typedef struct _md4_pass {
+  guint32 md4[16];
+} md4_pass;
+
+static unsigned char zeros[24] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+static GHashTable* hash_packet = NULL;
+
 /*
  * NTLMSSP negotiation flags
  * Taken from Samba
@@ -108,7 +123,7 @@
 #define NTLMSSP_TARGET_TYPE_DOMAIN         0x00010000
 #define NTLMSSP_TARGET_TYPE_SERVER         0x00020000
 #define NTLMSSP_TARGET_TYPE_SHARE          0x00040000
-#define NTLMSSP_NEGOTIATE_NTLM2            0x00080000
+#define NTLMSSP_NEGOTIATE_EXTENDED_SECURITY 0x00080000
 #define NTLMSSP_NEGOTIATE_IDENTIFY         0x00100000
 #define NTLMSSP_NEGOTIATE_00200000         0x00200000
 #define NTLMSSP_REQUEST_NON_NT_SESSION     0x00400000
@@ -167,7 +182,8 @@
 static int hf_ntlmssp_negotiate_domain_maxlen = -1;
 static int hf_ntlmssp_negotiate_domain_buffer = -1;
 static int hf_ntlmssp_negotiate_domain = -1;
-static int hf_ntlmssp_ntlm_challenge = -1;
+static int hf_ntlmssp_ntlm_server_challenge = -1;
+static int hf_ntlmssp_ntlm_client_challenge = -1;
 static int hf_ntlmssp_reserved = -1;
 static int hf_ntlmssp_challenge_domain = -1;
 static int hf_ntlmssp_auth_username = -1;
@@ -197,7 +213,8 @@
 static int hf_ntlmssp_verf = -1;
 static int hf_ntlmssp_verf_vers = -1;
 static int hf_ntlmssp_verf_body = -1;
-static int hf_ntlmssp_verf_unknown1 = -1;
+static int hf_ntlmssp_verf_randompad = -1;
+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;
@@ -211,6 +228,7 @@
 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;
@@ -234,9 +252,12 @@
 /* Used in the conversation function */
 typedef struct _ntlmssp_info {
   guint32 flags;
-  rc4_state_struct rc4_state_peer1;
-  rc4_state_struct rc4_state_peer2;
-  guint32 peer1_dest_port;
+  int is_auth_ntlm_v2;
+  rc4_state_struct rc4_state_client;
+  rc4_state_struct rc4_state_server;
+  guint32 server_dest_port;
+  unsigned char server_challenge[8];
+  unsigned char client_challenge[8];
   int rc4_state_initialized;
   ntlmssp_blob ntlm_response;
   ntlmssp_blob lm_response;
@@ -245,20 +266,63 @@
 /* If this struct exists in the payload_decrypt, then we have already
    decrypted it once */
 typedef struct _ntlmssp_packet_info {
-  guint32 flags;
   guint8 *decrypted_payload;
   guint8 verifier[16];
   gboolean payload_decrypted;
   gboolean verifier_decrypted;
 } ntlmssp_packet_info;
 
-
+static void printnbyte(const guint8* tab,int nb,char* txt,char* txt2)
+{
+  int i=0;
+  fprintf(stderr,"%s ",txt);
+  for(i=0;i<nb;i++)
+  {
+    fprintf(stderr,"%02hhX ",*(tab+i));
+  }
+  fprintf(stderr,"%s",txt2);
+}
+/*
+ static void printnchar(const guint8* tab,int nb,char* txt,char* txt2)
+{
+  int i=0;
+  fprintf(stderr,"%s ",txt);
+  for(i=0;i<nb;i++)
+  {
+    fprintf(stderr,"%c",*(tab+i));
+  }
+  fprintf(stderr,"%s",txt2);
+}
+*/
 /*
  * GSlist of decrypted payloads.
  */
 static GSList *decrypted_payloads;
 
 /*
+  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)
+{
+  guint8 pw21[21]; /* 21 bytes place for the needed key */
+
+  memset(pw21, 0, sizeof(pw21));
+  memcpy(pw21, key, 16);
+
+  memset(response, 0, 24);
+  /* crypt_des_ecb(data,key)*/
+  crypt_des_ecb(response, data, pw21, 1);
+  crypt_des_ecb(response + 8, data, pw21 + 7, 1);
+  crypt_des_ecb(response + 16, data, pw21 + 14, 1);
+
+  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.
@@ -281,31 +345,257 @@
   return 1;
 }
 
-/* Create an NTLMSSP version 1 key.
+
+/* 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)
+{
+  int password_len = 0;
+  int i;
+  
+  password_len = strlen(nt_password);
+  if(nt_password_unicode != NULL)
+  {
+   for(i=0;i<(password_len);i++)
+   {
+     nt_password_unicode[i*2]=nt_password[i];
+     nt_password_unicode[i*2+1]=0;
+   }
+  }
+  nt_password_unicode[2*password_len]='\0';
+}
+
+/* This function generate the Key Exchange Key 
+ * Depending on the flags this key will either be used to crypt the exported session key
+ * or will be used directly as exported session key.
+ * Exported session key is the key that will be used for sealing and signing communication*/
+
+static void 
+get_keyexchange_key(unsigned char keyexchangekey[16],const unsigned char sessionbasekey[16],const unsigned char lm_challenge_response[24],int flags)
+{
+  guint8 basekey[16];
+  guint8 zeros[24];
+
+  memset(keyexchangekey,0,16);
+  memset(basekey,0,16);
+  /* sessionbasekey is either derived from lm_password_hash or from nt_password_hash depending on the key type negotiated */
+  memcpy(basekey,sessionbasekey,8);
+  memset(basekey,0xBD,8);
+  if(flags&NTLMSSP_NEGOTIATE_LM_KEY)
+  {
+    /*data,key*/
+    crypt_des_ecb(keyexchangekey,lm_challenge_response,basekey,1);
+    crypt_des_ecb(keyexchangekey+8,lm_challenge_response,basekey+7,1);
+  }
+  else
+  {
+    if(flags&NTLMSSP_REQUEST_NON_NT_SESSION)
+    {
+      /*People from samba tends to use the same function in this case than in the previous one but with 0 data 
+       * it's not clear that it produce the good result 
+       * memcpy(keyexchangekey,lm_hash,8);
+       * Let's trust samba implementation it mights seem weird but they are more often rights than the spec !
+       */
+      memset(zeros,0,24); 
+      crypt_des_ecb(keyexchangekey,zeros,basekey,3);
+      crypt_des_ecb(keyexchangekey+8,zeros,basekey+7,1);
+    }
+    else
+    {
+      /* it is stated page 65 of NTLM SSP spec that sessionbasekey should be encrypted with hmac_md5 using the concact of both challenge 
+       * when it's NTLM v1 + extended security but it turns out to be wrong !
+       */
+      memcpy(keyexchangekey,sessionbasekey,16);
+    }
+  }
+}
+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[16];
+  int password_len = 0;
+  char nt_password_unicode[256];
+  md4_pass* pass_list;
+  int i = 0;
+
+  for(ek=enc_key_list;ek;ek=ek->next){
+    if( ek->keylength == 16 ) {
+      nb_pass++;
+    }
+  }
+  memset(nt_password_hash,0,16);
+  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,zeros,16) != 0 ) {
+    memcpy(pass_list[i].md4,nt_password_hash,16);
+    i = 1;
+  }
+  for(ek=enc_key_list;ek;ek=ek->next){
+    if( ek->keylength == 16 ) {
+      memcpy(pass_list[i].md4,ek->keyvalue,16);
+      i++;
+    }
+  }
+  return nb_pass;
+}
+/* Create an NTLMSSP version 2
+ */
+static void
+create_ntlmssp_v2_key(const char *nt_password, 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 ) {
+  char domain_name_unicode[256];
+  char user_uppercase[256];
+  char buf[512];
+  /*guint8 md4[16];*/
+  unsigned char nt_password_hash[16];
+  unsigned char nt_proof[16];
+  unsigned char ntowf[16];
+  guint8 sessionbasekey[16];
+  guint8 keyexchangekey[16];
+  guint8 lm_challenge_response[24];
+  guint32 i;
+  guint32 j;
+  rc4_state_struct rc4state;
+  guint32  user_len;
+  guint32 domain_len;
+  md4_pass *pass_list;
+  guint32 nb_pass = 0;
+  int found = 0;
+
+  /* We are going to try password encrypted in keytab as well, it's an idean of Stepan Metzmacher <metze at samba.org> 
+   * The idea is to be able to test all the key of domain in once and to be able to decode the NTLM dialogs */
+
+  memset(sessionkey, 0, 16);
+  nb_pass = get_md4pass_list(&pass_list,nt_password);
+  fprintf(stderr,"Working with %d keys\n",nb_pass);
+  i=0;
+  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]);
+       }  
+     }
+  }
+  else {
+     /* 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 ) {
+    str_to_unicode(ntlmssph->domain_name,domain_name_unicode);
+  }
+  else {
+    /* Unable to calculate the session not enought space in buffer, note this is unlikely to happen but ......*/
+    return;
+  }
+  while (i < nb_pass ) {
+    fprintf(stderr,"Turn %d, ",i);
+    memcpy(nt_password_hash,pass_list[i].md4,16);
+    printnbyte(nt_password_hash,16,"Current NT password hash: ","\n");
+    i++;
+    /* ntowf computation */ 
+    memset(buf,0,512);
+    memcpy(buf,user_uppercase,user_len*2);
+    memcpy(buf+user_len*2,domain_name_unicode,domain_len*2);
+    md5_hmac(buf,domain_len*2+user_len*2,nt_password_hash,16,ntowf);
+    /* LM response */
+    memset(buf,0,512);
+    memcpy(buf,serverchallenge,8);
+    memcpy(buf+8,clientchallenge,8);
+    md5_hmac(buf,16,ntowf,16,lm_challenge_response);
+    memcpy(lm_challenge_response+16,clientchallenge,8);
+    printnbyte(lm_challenge_response,24,"LM Response: ","\n");
+  
+    /* NT proof = First 16 bytes of NT response */
+    memset(buf,0,512);
+    memcpy(buf,serverchallenge,8);
+    memcpy(buf+8,ntlm_response.contents+16,ntlm_response.length-16);
+    md5_hmac(buf,ntlm_response.length-8,ntowf,16,nt_proof);
+    printnbyte(nt_proof,16,"NT proof: ","\n");
+    if( !memcmp(nt_proof,ntlm_response.contents,16) ) {
+      fprintf(stderr,"Found a matching password\n");
+      found = 1;
+      break;
+    }
+
+  }
+  if( found == 0 ) {
+    fprintf(stderr,"Unable to find a matching password, give up decoding\n");
+
+    return;
+  }
+  
+  md5_hmac(nt_proof,16,ntowf,16,sessionbasekey);
+  get_keyexchange_key(keyexchangekey,sessionbasekey,lm_challenge_response,flags);
+  /* now decrypt session key if needed and setup sessionkey for decrypting further communications */ 
+  if (flags & NTLMSSP_NEGOTIATE_KEY_EXCH)
+  {
+    memcpy(sessionkey,encryptedsessionkey,16);
+    crypt_rc4_init(&rc4state,keyexchangekey,16);
+    crypt_rc4(&rc4state,sessionkey,16);
+  }
+  else
+  {
+    memcpy(sessionkey,keyexchangekey,16);
+  }
+
+}
+ /* Create an NTLMSSP version 1 key 
+ * That is more complicated logic and methods and user challenge as well.
  * password points to the ANSI password to encrypt, challenge points to
- * the 8 octet challenge string, key128 will do a 128 bit key if set to 1,
- * otherwise it will do a 40 bit key.  The result is stored in
- * sspkey (expected to be 16 octets)
+ * the 8 octet challenge string
  */
 static void
-create_ntlmssp_v1_key(const char *nt_password, const guint8 *challenge,
-		      int use_key_128, guint8 *sspkey)
+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)
 {
   unsigned char lm_password_upper[16];
   unsigned char lm_password_hash[16];
+  unsigned char nt_password_hash[16];
+  unsigned char challenges_hash[16];
+  unsigned char challenges_hash_first8[8];
+  unsigned char challenges[16];
+  guint8 md4[16];
+  guint8 nb_pass = 0;
+  guint8 sessionbasekey[16];
+  guint8 keyexchangekey[16];
   guint8 lm_challenge_response[24];
-  guint8 rc4key[24];
-  guint8 pw21[21]; /* Password hash padded to 21 bytes */
+  guint8 nt_challenge_response[24];
+  rc4_state_struct rc4state;
+  md5_state_t md5state; 
+  char nt_password_unicode[256];
   size_t password_len;
   unsigned int i;
+  int found = 0;
+  md4_pass *pass_list;
   unsigned char lmhash_key[] =
     {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
-
+  
+  memset(sessionkey, 0, 16);
   memset(lm_password_upper, 0, sizeof(lm_password_upper));
-
+  /* lm auth/lm session == (!NTLM_NEGOTIATE_NT_ONLY && NTLMSSP_NEGOTIATE_LM_KEY) || ! (EXTENDED_SECURITY) || ! NTLMSSP_NEGOTIATE_NTLM*/
   /* Create a Lan Manager hash of the input password */
   if (nt_password[0] != '\0') {
     password_len = strlen(nt_password);
+    /*Do not forget to free nt_password_nt*/
+    str_to_unicode(nt_password,nt_password_unicode);
+    crypt_md4(nt_password_hash,nt_password_unicode,password_len*2);
     /* Truncate password if too long */
     if (password_len > 16)
       password_len = 16;
@@ -313,42 +603,168 @@
       lm_password_upper[i] = toupper(nt_password[i]);
     }
   }
+  else
+  {
+    /* Unable to calculate the session key without a password ... and we will not use one for a keytab*/
+    if( !(flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY )) {
+      return;
+    }
+  }
+  if((flags & NTLMSSP_NEGOTIATE_LM_KEY && !(flags & NTLMSSP_NEGOTIATE_NT_ONLY)) || !(flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY)  || !(flags & NTLMSSP_NEGOTIATE_NTLM)) {
+    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);
+    memcpy(sessionbasekey,lm_password_hash,16);
+  }
+  else {
+    
+    memset(lm_challenge_response,0,24);
+    if( flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY ) {
+      nb_pass = get_md4pass_list(&pass_list,nt_password);
+      fprintf(stderr,"Working with %d keys\n",nb_pass);
+      i=0;
+      while (i < nb_pass ) {
+        fprintf(stderr,"Turn %d, ",i);
+        memcpy(nt_password_hash,pass_list[i].md4,16);
+        printnbyte(nt_password_hash,16,"Current NT password hash: ","\n");
+        i++;
+        memcpy(lm_challenge_response,clientchallenge,8);
+        md5_init(&md5state); 
+        md5_append(&md5state,serverchallenge,8);
+        md5_append(&md5state,clientchallenge,8);
+        md5_finish(&md5state,challenges_hash);
+        strncpy(challenges_hash_first8,challenges_hash,8);
+        crypt_des_ecb_long(nt_challenge_response,nt_password_hash,challenges_hash_first8);
+        if( !memcmp(ref_nt_challenge_response,nt_challenge_response,24) ) {
+          fprintf(stderr,"Found a matching password\n");
+          found = 1;
+          break;
+        }
+      }
+    }
+    else {
+      crypt_des_ecb_long(nt_challenge_response,nt_password_hash,serverchallenge);
+      if( flags & NTLMSSP_NEGOTIATE_NT_ONLY ) {
+        memcpy(lm_challenge_response,nt_challenge_response,24);
+      }
+      else {
+        crypt_des_ecb_long(lm_challenge_response,lm_password_hash,serverchallenge);
+      }
+      if( !memcmp(ref_nt_challenge_response,nt_challenge_response,24) && !memcmp(ref_lm_challenge_response,lm_challenge_response,24) ) {
+          fprintf(stderr,"Found a matching password\n");
+          found = 1;
+      }    
+    }
+    /* So it's clearly not like this that's put into NTLMSSP doc but after some digging into samba code I'm quite confident
+     * that sessionbasekey should be based md4(nt_password_hash) only in the case of some NT auth
+     * Otherwise it should be lm_password_hash ...*/
+    crypt_md4(md4,nt_password_hash,16);
+    if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY) {
+     memcpy(challenges,serverchallenge,8);
+     memcpy(challenges+8,clientchallenge,8);
+     /*md5_hmac(text,text_len,key,key_len,digest);*/
+     md5_hmac(challenges,16,md4,16,sessionbasekey);
+    }
+    else {
+     memcpy(sessionbasekey,md4,16);
+    }  
+  } 
 
-  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);
+  if( found == 0 ) {
+    fprintf(stderr,"Unable to find a matching password, give up decoding\n");
+
+    return;
+  }
 
-  /* Generate the LanMan Challenge Response */
-  ntlmssp_generate_challenge_response(lm_challenge_response,
-				      lm_password_hash, challenge);
-
-  /* Generate the NTLMSSP-v1 RC4 Key.
-   * The RC4 key is derived from the Lan Manager Hash.
-   * See lkcl "DCE/RPC over SMB" page 254 for the algorithm.
-   */
-  memset(pw21, 0xBD, sizeof(pw21));
-  memcpy(pw21, lm_password_hash, sizeof(lm_password_hash));
 
-  /* Only the first eight bytes of challenge_response is used */
-  crypt_des_ecb(rc4key, lm_challenge_response, pw21, 1);
-  crypt_des_ecb(rc4key + 8, lm_challenge_response, pw21 + 7, 1);
-  crypt_des_ecb(rc4key + 16, lm_challenge_response, pw21 + 14, 1);
-
-  /* Create the SSP Key */
-  memset(sspkey, 0, sizeof(sspkey));
-  if (use_key_128) {
-    /* Create 128 bit key */
-    memcpy(sspkey, rc4key, 16);
+  get_keyexchange_key(keyexchangekey,sessionbasekey,lm_challenge_response,flags);
+  memset(sessionkey, 0, 16);
+  printnbyte(nt_challenge_response,24,"NT challenge response","\n");
+  printnbyte(lm_challenge_response,24,"LM challenge response","\n");
+  /* now decrypt session key if needed and setup sessionkey for decrypting further communications */ 
+  if (flags & NTLMSSP_NEGOTIATE_KEY_EXCH)
+  {
+    memcpy(sessionkey,encryptedsessionkey,16);
+    crypt_rc4_init(&rc4state,keyexchangekey,16);
+    crypt_rc4(&rc4state,sessionkey,16);
+  }
+  else
+  {
+    memcpy(sessionkey,keyexchangekey,16);
   }
-  else {
-    /* Create 40 bit key */
-    memcpy(sspkey, rc4key, 5);
-    sspkey[5]=0xe5;
-    sspkey[6]=0x38;
-    sspkey[7]=0xb0;
+}
+/* We return either a 128 or 64 bit key
+ */
+static void 
+get_sealing_rc4key(const guint8 exportedsessionkey[16] ,const int flags ,int *keylen ,guint8 *clientsealkey ,guint8 *serversealkey)
+{
+  md5_state_t md5state; 
+  md5_state_t md5state2; 
+  memset(clientsealkey,0,16);
+  memset(serversealkey,0,16);
+  memcpy(clientsealkey,exportedsessionkey,16);
+  if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY)
+  {
+    if (flags & NTLMSSP_NEGOTIATE_128)
+    {
+      /* The exportedsessionkey has already the good length just update the length*/
+      *keylen = 16;
+    }
+    else
+    {
+      if (flags & NTLMSSP_NEGOTIATE_56)
+      {
+        memset(clientsealkey+7,0,9);
+        *keylen = 7;
+      }
+      else
+      {
+        memset(clientsealkey+5,0,11);
+        *keylen = 5;
+      }
+    }
+    memcpy(serversealkey,clientsealkey,16);
+    md5_init(&md5state); 
+    md5_append(&md5state,clientsealkey,*keylen);
+    md5_append(&md5state,CLIENT_SEAL_TEXT,strlen(CLIENT_SEAL_TEXT)+1);
+    md5_finish(&md5state,clientsealkey);
+    md5_init(&md5state2); 
+    md5_append(&md5state2,serversealkey,*keylen);
+    md5_append(&md5state2,SERVER_SEAL_TEXT,strlen(SERVER_SEAL_TEXT)+1);
+    md5_finish(&md5state2,serversealkey);
+  }
+  else
+  {
+    if (flags & NTLMSSP_NEGOTIATE_128)
+    {
+      /* The exportedsessionkey has already the good length just update the length*/
+      *keylen = 16;
+    }
+    else
+    {
+      *keylen = 8;
+      if (flags & NTLMSSP_NEGOTIATE_56)
+      {
+        memset(clientsealkey+7,0,9);
+      }
+      else
+      {
+        memset(clientsealkey+5,0,11);
+        clientsealkey[5]=0xe5;
+        clientsealkey[6]=0x38;
+        clientsealkey[7]=0xb0;
+      }
+    }  
+    serversealkey = memcpy(serversealkey,clientsealkey,*keylen);
   }
-  return;
 }
-
+/* Create an NTLMSSP version 1 key.
+ * password points to the ANSI password to encrypt, challenge points to
+ * the 8 octet challenge string, key128 will do a 128 bit key if set to 1,
+ * otherwise it will do a 40 bit key.  The result is stored in
+ * sspkey (expected to be 16 octets)
+ */
 /* dissect a string - header area contains:
      two byte len
      two byte maxlen
@@ -457,14 +873,27 @@
     result->length = blob_length;
     memset(result->contents, 0, MAX_BLOB_SIZE);
     if (blob_length < MAX_BLOB_SIZE)
+    {
       tvb_memcpy(tvb, result->contents, blob_offset, blob_length);
+      if (blob_hf == hf_ntlmssp_auth_lmresponse && !(strncmp(tvb->real_data+blob_offset+8,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",16)))
+      {
+        proto_tree_add_item (ntlmssp_tree,
+		       hf_ntlmssp_ntlm_client_challenge,
+		       tvb, blob_offset, 8, FALSE);
+      }
+    }
   }
 
   /* If we are dissecting the NTLM response and it is a NTLMv2
      response call the appropriate dissector. */
 
   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);
+  }
 
   return offset;
 }
@@ -601,6 +1030,9 @@
 #define NTLM_NAME_DNS_HOST   0x0003
 #define NTLM_NAME_DNS_DOMAIN 0x0004
 #define NTLM_NAME_CLIENT_TIME 0x0007
+#define NTLM_NAME_RESTRICTION 0x0008
+
+
 
 static const value_string ntlm_name_types[] = {
 	{ NTLM_NAME_END, "End of list" },
@@ -608,7 +1040,9 @@
 	{ NTLM_NAME_NB_DOMAIN, "NetBIOS domain name" },
 	{ NTLM_NAME_DNS_HOST, "DNS host name" },
 	{ NTLM_NAME_DNS_DOMAIN, "DNS domain name" },
+
 	{ NTLM_NAME_CLIENT_TIME, "Client Time" },
+	{ NTLM_NAME_RESTRICTION, "Encoding restriction" },
 	{ 0, NULL }
 };
 
@@ -617,7 +1051,7 @@
 {
 	proto_item *ntlmv2_item = NULL;
 	proto_tree *ntlmv2_tree = NULL;
-
+  const guint8 *restriction_bytes;
 	/* Dissect NTLMv2 bits&pieces */
 
 	if (tree) {
@@ -709,6 +1143,14 @@
 			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:
@@ -716,10 +1158,9 @@
 		default:
 			name = tvb_get_ephemeral_faked_unicode(
 				tvb, offset, name_len / 2, TRUE);
-
 			proto_tree_add_text(
 				name_tree, tvb, offset, name_len,
-				"Name: %s", name);
+				"Value: %s", name);
 			proto_item_append_text(
 				name_item, "%s, %s",
 				val_to_str(name_type, ntlm_name_types,
@@ -911,12 +1352,14 @@
   guint32 negotiate_flags;
   int item_start, item_end;
   int data_start, data_end;
+  guint8 clientkey[16]; /* NTLMSSP cipher key for client */
+  guint8 serverkey[16]; /* NTLMSSP cipher key for server*/
   ntlmssp_info *conv_ntlmssp_info;
   conversation_t *conversation;
   gboolean unicode_strings = FALSE;
   guint8 challenge[8];
   guint8 sspkey[16]; /* NTLMSSP cipher key */
-  guint8 ssp_key_len; /* Either 8 or 16 (40 bit or 128) */
+  int ssp_key_len; /* Either 8 or 16 (40 bit or 128) */
 
   /* need to find unicode flag */
   negotiate_flags = tvb_get_letohl (tvb, offset+8);
@@ -940,7 +1383,7 @@
 
   /* NTLMSSP NT Lan Manager Challenge */
   proto_tree_add_item (ntlmssp_tree,
-		       hf_ntlmssp_ntlm_challenge,
+		       hf_ntlmssp_ntlm_server_challenge,
 		       tvb, offset, 8, FALSE);
 
   /*
@@ -961,22 +1404,26 @@
     conv_ntlmssp_info->flags = negotiate_flags;
     /* Insert the RC4 state information into the conversation */
     tvb_memcpy(tvb, challenge, offset, 8);
-
+    tvb_memcpy(tvb, conv_ntlmssp_info->server_challenge, offset, 8);
+    conv_ntlmssp_info->is_auth_ntlm_v2=0;
     /* Between the challenge and the user provided password, we can build the
-       NTLMSSP key and initialize the cipher */
-    if (conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_128) {
-      create_ntlmssp_v1_key(nt_password, challenge, 1, sspkey);
-      ssp_key_len = 16;
-    }
-    else {
-      create_ntlmssp_v1_key(nt_password, challenge, 0, sspkey);
-      ssp_key_len = 8;
+       NTLMSSP key and initialize the cipher if we are not in EXTENDED SECURITY 
+       in this case we need the client challenge as well*/
+    /* BTW this is true just if we are in LM Authentification if not the logic is a bit different.
+     * Right now it's not very clear what is LM Authentification it __seems__ to be when 
+     * NEGOTIATE NT ONLY is not set and NEGOSIATE EXTENDED SECURITY is not set as well*/
+    if (!(conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY))
+    {
+      create_ntlmssp_v1_key(nt_password, conv_ntlmssp_info->server_challenge,NULL, sspkey,NULL,conv_ntlmssp_info->flags,conv_ntlmssp_info->ntlm_response.contents,conv_ntlmssp_info->lm_response.contents);
+      if( memcmp(sspkey,zeros,16) != 0 ) {
+        get_sealing_rc4key(sspkey,conv_ntlmssp_info->flags,&ssp_key_len,clientkey,serverkey);
+        crypt_rc4_init(&conv_ntlmssp_info->rc4_state_client, sspkey, ssp_key_len);
+        crypt_rc4_init(&conv_ntlmssp_info->rc4_state_server, sspkey, ssp_key_len);
+        conv_ntlmssp_info->server_dest_port = pinfo->destport;
+        conv_ntlmssp_info->rc4_state_initialized = 1;
+      }
+  
     }
-    crypt_rc4_init(&conv_ntlmssp_info->rc4_state_peer1, sspkey, ssp_key_len);
-    crypt_rc4_init(&conv_ntlmssp_info->rc4_state_peer2, sspkey, ssp_key_len);
-    conv_ntlmssp_info->peer1_dest_port = pinfo->destport;
-    conv_ntlmssp_info->rc4_state_initialized = 1;
-
     conversation_add_proto_data(conversation, proto_ntlmssp, conv_ntlmssp_info);
   }
   offset += 8;
@@ -1023,15 +1470,27 @@
   int item_start, item_end;
   int data_start, data_end = 0;
   guint32 negotiate_flags;
+  guint8 sspkey[16]; /* exported session key */
+  guint8 clientkey[16]; /* NTLMSSP cipher key for client */
+  guint8 serverkey[16]; /* NTLMSSP cipher key for server*/
+  guint8 encryptedsessionkey[16];
+  ntlmssp_blob sessionblob;
   gboolean unicode_strings = FALSE;
-  ntlmssp_info *conv_ntlmssp_info;
+  ntlmssp_info *conv_ntlmssp_info = NULL;
   conversation_t *conversation;
-
+  int ssp_key_len;
   /*
    * Get flag info from the original negotiate message, if any.
    * This is because the flag information is sometimes missing from
    * the AUTHENTICATE message, so we can't figure out whether
    * strings are Unicode or not by looking at *our* flags.
+   * XXX it seems it's more from the CHALLENGE message, which is more clever in fact
+   * because the server can change some flags.
+   * But according to MS NTLMSSP doc it's not that simple. 
+   * In case of Conection less mode AUTHENTICATE flags should be used because they
+   * reprensent the choice of the client after having been informed of options of the 
+   * server in the CHALLENGE message.
+   * In Connection mode then the CHALLENGE flags should (must ?) be used
    */
   conv_ntlmssp_info = p_get_proto_data(pinfo->fd, proto_ntlmssp);
   if (conv_ntlmssp_info == NULL) {
@@ -1060,7 +1519,10 @@
 
   /*
    * Sometimes the session key and flags are missing.
-   * Sometimes the session key is present but the flags are missing.
+   * Sometimes the session key is present but the flags are missing. 
+   * XXX Who stay so ? Reading spec I would rather say the opposite: flags are 
+   * always present, session information are always there as well but sometime 
+   * session information could be null (in case of no session)
    * Sometimes they're both present.
    *
    * This does not correlate with any flags in the previous CHALLENGE
@@ -1082,7 +1544,7 @@
 				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,
@@ -1090,8 +1552,18 @@
 				&item_end,
 				conv_ntlmssp_info == NULL ? NULL :
 				&conv_ntlmssp_info->ntlm_response);
+  if( conv_ntlmssp_info != NULL && conv_ntlmssp_info->ntlm_response.length > 24 ) {
+    strncpy(conv_ntlmssp_info->client_challenge,conv_ntlmssp_info->ntlm_response.contents+32,8);
+  }
   data_start = MIN(data_start, item_start);
   data_end = MAX(data_end, item_end);
+  if( conv_ntlmssp_info != NULL )
+  {
+    if( conv_ntlmssp_info->ntlm_response.length > 24 )
+    {
+      conv_ntlmssp_info->is_auth_ntlm_v2=1;
+    }
+  }
 
   /* domain name */
   item_start = tvb_get_letohl(tvb, offset+4);
@@ -1099,6 +1571,7 @@
 				  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);
 
@@ -1108,6 +1581,7 @@
 				  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);
 
@@ -1128,20 +1602,274 @@
     /* Session Key */
     offset = dissect_ntlmssp_blob(tvb, offset, ntlmssp_tree,
 				  hf_ntlmssp_auth_sesskey,
-				  &item_end, NULL);
+				  &item_end, &sessionblob);
     data_end = MAX(data_end, item_end);
   }
-
+  memcpy(encryptedsessionkey,sessionblob.contents,sessionblob.length);
   if (offset < data_start) {
     /* NTLMSSP Negotiate Flags */
     negotiate_flags = tvb_get_letohl (tvb, offset);
     offset = dissect_ntlmssp_negotiate_flags (tvb, offset, ntlmssp_tree,
 					      negotiate_flags);
   }
-
+  /* Try to attach to an existing conversation if not then it's useless to try to do so
+   * because we are missing important information (ie. server challenge)
+   */
+  if (conv_ntlmssp_info) {
+    /* If we are in EXTENDED SECURITY then we can now initialize cipher */
+    if ((conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY))
+    {
+      if( conv_ntlmssp_info->is_auth_ntlm_v2 ) {
+        create_ntlmssp_v2_key(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
+      {
+        strncpy(conv_ntlmssp_info->client_challenge,conv_ntlmssp_info->lm_response.contents,8);
+        create_ntlmssp_v1_key(nt_password, conv_ntlmssp_info->server_challenge,conv_ntlmssp_info->client_challenge, sspkey,encryptedsessionkey,conv_ntlmssp_info->flags,conv_ntlmssp_info->ntlm_response.contents,conv_ntlmssp_info->lm_response.contents);
+      }
+      /* ssp is the exported session key */
+      if( memcmp(sspkey,zeros,16) != 0) {
+        get_sealing_rc4key(sspkey,conv_ntlmssp_info->flags,&ssp_key_len,clientkey,serverkey);
+        crypt_rc4_init(&conv_ntlmssp_info->rc4_state_server, serverkey, ssp_key_len);
+        crypt_rc4_init(&conv_ntlmssp_info->rc4_state_client, clientkey, ssp_key_len); 
+        conv_ntlmssp_info->server_dest_port = pinfo->destport;
+        conv_ntlmssp_info->rc4_state_initialized = 1;
+      }
+    }
+   }
   return MAX(offset, data_end);
 }
+/*
+ * Get the encryption state tied to this conversation.  cryptpeer indicates
+ * whether to retrieve the client key (1) or the server key (0) 
+ */
+static rc4_state_struct *
+get_encrypted_state(packet_info *pinfo, int cryptpeer)
+{
+  conversation_t *conversation;
+  ntlmssp_info *conv_ntlmssp_info;
 
+  conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
+				   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 */
+    return NULL;
+  }
+  else {
+    /* We have a conversation, check for encryption state */
+    conv_ntlmssp_info = conversation_get_proto_data(conversation,
+						    proto_ntlmssp);
+    if (conv_ntlmssp_info == NULL) {
+      /* No encryption state tied to the conversation.  Therefore, we
+	 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
+       */
+      if (cryptpeer == 1) {
+	      return &conv_ntlmssp_info->rc4_state_client;
+      } else {
+	      return &conv_ntlmssp_info->rc4_state_server;
+      }
+    }
+  }
+}
+void 
+decrypt_data_payload(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
+		 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 *
+dissect_ntlmssp_encrypted_payload(tvbuff_t *data_tvb,
+				  tvbuff_t *auth_tvb _U_,
+				  int offset,
+				  packet_info *pinfo,
+				  dcerpc_auth_info *auth_info _U_)*/
+
+int
+dissect_ntlmssp_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
+{
+  volatile int offset = 0;
+  proto_tree *volatile ntlmssp_tree = NULL;
+  proto_item *tf = NULL;
+  guint32 length;
+  guint32 encrypted_block_length;
+  guint8 key[16];
+  /* the magic ntlm is the identifier of a NTLMSSP packet that's 00 00 00 01
+   */
+  guint32 ntlm_magic_size = 4;
+  guint32 ntlm_signature_size = 8;
+  guint32 ntlm_seq_size = 4;
+  length = tvb_length (tvb);
+  /* signature + seq + real payload */
+  encrypted_block_length = length - ntlm_magic_size;
+
+  if (encrypted_block_length < (ntlm_signature_size + ntlm_seq_size)) {
+    /* Don't know why this would happen, but if it does, don't even bother
+       attempting decryption/dissection */
+    return offset + length;
+  }
+
+  /* Setup a new tree for the NTLMSSP payload */
+  if (tree) {
+    tf = proto_tree_add_item (tree,
+			      hf_ntlmssp_verf,
+			      tvb, offset, -1, FALSE);
+
+    ntlmssp_tree = proto_item_add_subtree (tf,
+					   ett_ntlmssp);
+  }
+
+  /*
+   * Catch the ReportedBoundsError exception; the stuff we've been
+   * handed doesn't necessarily run to the end of the packet, it's
+   * an item inside a packet, so if it happens to be malformed (or
+   * we, or a dissector we call, has a bug), so that an exception
+   * is thrown, we want to report the error, but return and let
+   * our caller dissect the rest of the packet.
+   *
+   * If it gets a BoundsError, we can stop, as there's nothing more
+   * in the packet after our blob to see, so we just re-throw the
+   * exception.
+   */
+  TRY {
+    /* Version number */
+    proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_vers,
+			 tvb, offset, 4, TRUE);
+    offset += 4;
+
+    /* Encrypted body */
+    proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_verf_body,
+			 tvb, offset, encrypted_block_length, TRUE);
+    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);
+    decrypt_verifier (tvb, offset, ntlm_signature_size + ntlm_seq_size, pinfo, ntlmssp_tree,key);
+    /* let's try to hook ourselves here */
+
+    offset += 12;
+  } CATCH(BoundsError) {
+    RETHROW;
+  } CATCH(ReportedBoundsError) {
+    show_reported_bounds_error(tvb, pinfo, tree);
+  } ENDTRY;
+
+  return offset;
+}
+void 
+decrypt_data_payload(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
+		 packet_info *pinfo, proto_tree *tree _U_,gpointer key)
+{
+  tvbuff_t *decr_tvb; /* Used to display decrypted buffer */
+  guint8 *peer_block;
+  conversation_t *conversation;
+  rc4_state_struct *rc4_state;
+  rc4_state_struct *rc4_state_peer;
+  ntlmssp_info *conv_ntlmssp_info = NULL;
+  ntlmssp_packet_info *packet_ntlmssp_info = NULL;
+  ntlmssp_packet_info *stored_packet_ntlmssp_info = NULL;
+
+
+  /* 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 */
+    packet_ntlmssp_info = se_alloc(sizeof(ntlmssp_packet_info));
+    memset(packet_ntlmssp_info, 0, 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 */
+    conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
+				     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);
+    if (conv_ntlmssp_info == NULL) {
+      /* There is no NTLMSSP state tied to the conversation */
+	    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;
+    }
+    stored_packet_ntlmssp_info = g_hash_table_lookup(hash_packet,key);
+    if( stored_packet_ntlmssp_info != NULL && stored_packet_ntlmssp_info->payload_decrypted == TRUE)
+    {
+      /* Mat TBD fprintf(stderr,"Found a already decrypted packet\n");*/
+      memcpy(packet_ntlmssp_info,stored_packet_ntlmssp_info,sizeof(ntlmssp_packet_info));
+      /* Mat TBD printnbyte(packet_ntlmssp_info->decrypted_payload,encrypted_block_length,"Data: ","\n");*/
+    }
+    else
+    {
+      /* 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 */
+      if (conv_ntlmssp_info->server_dest_port == pinfo->destport) {
+        /* client */
+        rc4_state = get_encrypted_state(pinfo, 1);
+        rc4_state_peer = get_encrypted_state(pinfo, 0);
+      } else {
+        /* server */
+        rc4_state = get_encrypted_state(pinfo, 0);
+        rc4_state_peer = get_encrypted_state(pinfo, 1);
+      }
+  
+      if (rc4_state == NULL ) {
+        /* There is no encryption state, so we cannot decrypt */
+        return ;
+      }
+  
+      /* 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(tvb, offset,
+                                                          encrypted_block_length);
+      decrypted_payloads = g_slist_prepend(decrypted_payloads,
+                                           packet_ntlmssp_info->decrypted_payload);
+      g_hash_table_insert(hash_packet,key,packet_ntlmssp_info);
+  
+      /* Do the decryption of the payload */
+      crypt_rc4(rc4_state, packet_ntlmssp_info->decrypted_payload,
+  	      encrypted_block_length);
+      /* decrypt the verifier */
+  
+      /* We setup a temporary buffer so we can re-encrypt the payload after
+         decryption.  This is to update the opposite peer's RC4 state 
+         it's usefull when we have only one key for both conversation
+         in case of KEY_EXCH we have independant key so this is not needed*/
+      if( !(NTLMSSP_NEGOTIATE_KEY_EXCH & conv_ntlmssp_info->flags)) {
+        peer_block = g_malloc(encrypted_block_length);
+        memcpy(peer_block, packet_ntlmssp_info->decrypted_payload,
+  	      encrypted_block_length);
+        crypt_rc4(rc4_state_peer, peer_block, encrypted_block_length);
+        g_free(peer_block);
+      } 
+    
+      packet_ntlmssp_info->payload_decrypted = TRUE;
+    }
+  }
+
+ /* 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);
+
+  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)
 {
@@ -1226,52 +1954,14 @@
   tap_queue_packet(ntlmssp_tap, pinfo, ntlmssph);
 }
 
-/*
- * Get the encryption state tied to this conversation.  cryptpeer indicates
- * whether to retrieve the data for peer1 or peer2.
- */
-static rc4_state_struct *
-get_encrypted_state(packet_info *pinfo, int cryptpeer)
-{
-  conversation_t *conversation;
-  ntlmssp_info *conv_ntlmssp_info;
 
-  conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
-				   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 */
-    return NULL;
-  }
-  else {
-    /* We have a conversation, check for encryption state */
-    conv_ntlmssp_info = conversation_get_proto_data(conversation,
-						    proto_ntlmssp);
-    if (conv_ntlmssp_info == NULL) {
-      /* No encryption state tied to the conversation.  Therefore, we
-	 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
-       */
-      if (cryptpeer == 1) {
-	return &conv_ntlmssp_info->rc4_state_peer1;
-      } else {
-	return &conv_ntlmssp_info->rc4_state_peer2;
-      }
-    }
-  }
-}
 
 /*
  * See page 45 of "DCE/RPC over SMB" by Luke Kenneth Casson Leighton.
  */
 static void
 decrypt_verifier(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
-		 packet_info *pinfo, proto_tree *tree)
+		 packet_info *pinfo, proto_tree *tree,gpointer key)
 {
   proto_tree *decr_tree = NULL;
   proto_item *tf = NULL;
@@ -1283,69 +1973,96 @@
   ntlmssp_info *conv_ntlmssp_info = NULL;
   ntlmssp_packet_info *packet_ntlmssp_info = NULL;
   int decrypted_offset = 0;
-
+  ntlmssp_packet_info *stored_packet_ntlmssp_info = NULL;
   packet_ntlmssp_info = p_get_proto_data(pinfo->fd, proto_ntlmssp);
   if (packet_ntlmssp_info == NULL) {
     /* We don't have data for this packet */
     return;
   }
-  if (!packet_ntlmssp_info->verifier_decrypted) {
-    conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
-				     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,
+  conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
+		     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);
-    if (conv_ntlmssp_info == NULL) {
-      /* There is no NTLMSSP state tied to the conversation */
-      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 we are doing
-	 something other than NTLMSSP v1 */
-      return;
-    }
-
-    if (conv_ntlmssp_info->peer1_dest_port == pinfo->destport) {
-      rc4_state = get_encrypted_state(pinfo, 1);
-      rc4_state_peer = get_encrypted_state(pinfo, 0);
-    } else {
-      rc4_state = get_encrypted_state(pinfo, 0);
-      rc4_state_peer = get_encrypted_state(pinfo, 1);
-    }
+  if (conv_ntlmssp_info == NULL) {
+  /* There is no NTLMSSP state tied to the conversation */
+    return;
+  }
 
-    if (rc4_state == NULL || rc4_state_peer == NULL) {
-      /* There is no encryption state, so we cannot decrypt */
-      return;
+  if( key != NULL ){
+    stored_packet_ntlmssp_info = g_hash_table_lookup(hash_packet,key);
+  }
+  if( stored_packet_ntlmssp_info != NULL && stored_packet_ntlmssp_info->verifier_decrypted == TRUE) {
+      /* Mat TBD fprintf(stderr,"Found a already decrypted packet\n");*/
+      memcpy(packet_ntlmssp_info,stored_packet_ntlmssp_info,sizeof(ntlmssp_packet_info));
+  }
+  else {
+    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 */
+        return;
+      }
+      if (conv_ntlmssp_info->server_dest_port == pinfo->destport) {
+        /* client talk to server */
+        rc4_state = get_encrypted_state(pinfo, 1);
+        rc4_state_peer = get_encrypted_state(pinfo, 0);
+      } else {
+        rc4_state = get_encrypted_state(pinfo, 0);
+        rc4_state_peer = get_encrypted_state(pinfo, 1);
+      }
+  
+      if (rc4_state == NULL || rc4_state_peer == NULL) {
+        /* There is no encryption state, so we cannot decrypt */
+        return;
+      }
+  
+      /* Setup the buffer to decrypt to */
+      tvb_memcpy(tvb, packet_ntlmssp_info->verifier,
+  	       offset, encrypted_block_length);
+      
+      /*if( !(NTLMSSP_NEGOTIATE_KEY_EXCH & packet_ntlmssp_info->flags)) {*/
+      if( conv_ntlmssp_info->flags & NTLMSSP_NEGOTIATE_EXTENDED_SECURITY ) {
+        if( (NTLMSSP_NEGOTIATE_KEY_EXCH & conv_ntlmssp_info->flags)) {
+          /* 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);
+        }
+      }
+      else {
+        /* 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);
+      }
+  
+  
+  
+      /* We setup a temporary buffer so we can re-encrypt the payload after
+         decryption.  This is to update the opposite peer's RC4 state 
+         This is not needed when we just have EXTENDED SECURITY because the signature is not crypted
+         and it's also not needed when we have key exchange because server and client have independant keys */
+      if( !(NTLMSSP_NEGOTIATE_KEY_EXCH & conv_ntlmssp_info->flags) && !(NTLMSSP_NEGOTIATE_EXTENDED_SECURITY & conv_ntlmssp_info->flags)) {
+        peer_block = g_malloc(encrypted_block_length);
+        memcpy(peer_block, packet_ntlmssp_info->verifier,
+  	      encrypted_block_length);
+        crypt_rc4(rc4_state_peer, peer_block, encrypted_block_length);
+        g_free(peer_block);
+      }
+  
+      /* Mark the packet as decrypted so that subsequent attempts to dissect
+         the packet use the already decrypted payload instead of attempting
+         to decrypt again */
+      packet_ntlmssp_info->verifier_decrypted = TRUE;
     }
-
-    /* Setup the buffer to decrypt to */
-    tvb_memcpy(tvb, packet_ntlmssp_info->verifier,
-	       offset, encrypted_block_length);
-
-    /* Do the actual decryption of the verifier */
-    crypt_rc4(rc4_state, packet_ntlmssp_info->verifier,
-	      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 */
-    peer_block = g_malloc(encrypted_block_length);
-    memcpy(peer_block, packet_ntlmssp_info->verifier,
-	   encrypted_block_length);
-    crypt_rc4(rc4_state_peer, peer_block, encrypted_block_length);
-    g_free(peer_block);
-
-    /* Mark the packet as decrypted so that subsequent attempts to dissect
-       the packet use the already decrypted payload instead of attempting
-       to decrypt again */
-    packet_ntlmssp_info->verifier_decrypted = TRUE;
   }
-
   /* Show the decrypted buffer in a new window */
   decr_tvb = tvb_new_real_data(packet_ntlmssp_info->verifier,
 			       encrypted_block_length,
@@ -1360,23 +2077,36 @@
 			   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);
+    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);
+    decrypted_offset += 4;
+  }
+  else {
 
-  /* LKCL page 45 says this is a "reserved" field.  I'm not sure if it's
-     garbage because it's some sort of nonce, or because there is a problem
-     with the verifier decryption routine.  */
-  proto_tree_add_item (decr_tree, hf_ntlmssp_verf_unknown1,
-		       decr_tvb, decrypted_offset, 4, TRUE);
-  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);
-  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);
-  decrypted_offset += 4;
+    /* RANDOM PAD usually it's 0 */
+    proto_tree_add_item (decr_tree, hf_ntlmssp_verf_randompad,
+	  	       decr_tvb, decrypted_offset, 4, TRUE);
+    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);
+    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);
+    decrypted_offset += 4;
+  }
 }
 
 static int
@@ -1430,8 +2160,10 @@
 			 tvb, offset, encrypted_block_length, TRUE);
 
     /* Try to decrypt */
-    decrypt_verifier (tvb, offset, encrypted_block_length, pinfo, ntlmssp_tree);
+    decrypt_verifier (tvb, offset, encrypted_block_length, pinfo, ntlmssp_tree,NULL);
+    /* let's try to hook ourselves here */
 
+    offset += 12;
     offset += encrypted_block_length;
   } CATCH(BoundsError) {
     RETHROW;
@@ -1442,13 +2174,14 @@
   return offset;
 }
 
-static tvbuff_t *
+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_)
 {
+  /* gssapi_decrypted_tvb=NULL */
   tvbuff_t *decr_tvb; /* Used to display decrypted buffer */
   guint8 *peer_block;
   conversation_t *conversation;
@@ -1457,7 +2190,6 @@
   rc4_state_struct *rc4_state_peer;
   ntlmssp_info *conv_ntlmssp_info = NULL;
   ntlmssp_packet_info *packet_ntlmssp_info = NULL;
-
   encrypted_block_length = tvb_length_remaining (data_tvb, offset);
 
   /* Check to see if we already have state for this packet */
@@ -1477,19 +2209,18 @@
     if (conversation == NULL) {
       /* There is no conversation, thus no encryption state */
       return NULL;
-    }
 
+    }
     conv_ntlmssp_info = conversation_get_proto_data(conversation,
 						    proto_ntlmssp);
     if (conv_ntlmssp_info == NULL) {
-      /* There is no NTLMSSP state tied to the conversation */
-	    return NULL;
+    /* 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
        payload.  The other is used to re-encrypt the payload to represent
        the peer */
-    if (conv_ntlmssp_info->peer1_dest_port == pinfo->destport) {
+    if (conv_ntlmssp_info->server_dest_port == pinfo->destport) {
       rc4_state = get_encrypted_state(pinfo, 1);
       rc4_state_peer = get_encrypted_state(pinfo, 0);
     } else {
@@ -1542,6 +2273,21 @@
 	g_free(decrypted_payload);
 }
 
+guint g_header_hash(gconstpointer pointer) {
+  guint32 crc =  ~calculate_crc32c(pointer,16,CRC32C_PRELOAD);
+  /* Mat TBD fprintf(stderr,"Val: %u\n",crc);*/
+  return crc;
+}
+
+gboolean g_header_equal(gconstpointer pointer1, gconstpointer pointer2) {
+  if(!memcmp(pointer1,pointer2,16)) {
+    return TRUE;
+  }
+  else {
+    return FALSE;
+  }
+}
+  
 static void
 ntlmssp_init_protocol(void)
 {
@@ -1555,8 +2301,14 @@
 		decrypted_payloads = NULL;
 	}
 
+  if(hash_packet == NULL) {
+    hash_packet = g_hash_table_new(g_header_hash,g_header_equal);
+  }
+
 }
 
+
+
 void
 proto_register_ntlmssp(void)
 {
@@ -1609,7 +2361,7 @@
     { &hf_ntlmssp_negotiate_flags_40000,
       { "Target Type Share", "ntlmssp.targettypeshare", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_TARGET_TYPE_SHARE, "", HFILL }},
     { &hf_ntlmssp_negotiate_flags_80000,
-      { "Negotiate NTLM2 key", "ntlmssp.negotiatentlm2", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_NTLM2, "", HFILL }},
+      { "Negotiate Extended Security", "ntlmssp.negotiatentlm2", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_EXTENDED_SECURITY, "", HFILL }},
     { &hf_ntlmssp_negotiate_flags_100000,
       { "Negotiate Identify", "ntlmssp.negotiateidentify", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_IDENTIFY, "", HFILL }},
     { &hf_ntlmssp_negotiate_flags_200000,
@@ -1650,8 +2402,10 @@
       { "Calling workstation domain buffer", "ntlmssp.negotiate.domain.buffer", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
     { &hf_ntlmssp_negotiate_domain,
       { "Calling workstation domain", "ntlmssp.negotiate.domain", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
-    { &hf_ntlmssp_ntlm_challenge,
-      { "NTLM Challenge", "ntlmssp.ntlmchallenge", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+    { &hf_ntlmssp_ntlm_client_challenge,
+      { "NTLM Client Challenge", "ntlmssp.ntlmclientchallenge", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+    { &hf_ntlmssp_ntlm_server_challenge,
+      { "NTLM Server Challenge", "ntlmssp.ntlmserverchallenge", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
     { &hf_ntlmssp_reserved,
       { "Reserved", "ntlmssp.reserved", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
     { &hf_ntlmssp_challenge_domain,
@@ -1712,12 +2466,14 @@
       { "Verifier Body", "ntlmssp.verf.body", FT_BYTES, BASE_NONE, NULL, 0x0, "", HFILL }},
     { &hf_ntlmssp_decrypted_payload,
       { "NTLM Decrypted Payload", "ntlmssp.decrypted_payload", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
-    { &hf_ntlmssp_verf_unknown1,
-      { "Unknown 1", "ntlmssp.verf.unknown1", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+    { &hf_ntlmssp_verf_randompad,
+      { "Random Pad", "ntlmssp.verf.randompad", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
     { &hf_ntlmssp_verf_crc32,
       { "Verifier CRC32", "ntlmssp.verf.crc32", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
     { &hf_ntlmssp_verf_sequence,
       { "Verifier Sequence Number", "ntlmssp.verf.sequence", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+    { &hf_ntlmssp_verf_hmacmd5,
+      { "HMAC MD5", "ntlmssp.verf.hmacmd5", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
     { &hf_ntlmssp_ntlmv2_response,
       { "NTLMv2 Response", "ntlmssp.ntlmv2response", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
     { &hf_ntlmssp_ntlmv2_response_hmac,
@@ -1733,11 +2489,13 @@
     { &hf_ntlmssp_ntlmv2_response_unknown,
       { "Unknown", "ntlmssp.ntlmv2response.unknown", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
     { &hf_ntlmssp_ntlmv2_response_name,
-      { "Name", "ntlmssp.ntlmv2response.name", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+      { "Attribute", "ntlmssp.ntlmv2response.name", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
     { &hf_ntlmssp_ntlmv2_response_name_type,
-      { "Name type", "ntlmssp.ntlmv2response.name.type", FT_UINT32, BASE_DEC, VALS(ntlm_name_types), 0x0, "", HFILL }},
+      { "Attribute type", "ntlmssp.ntlmv2response.name.type", FT_UINT32, BASE_DEC, VALS(ntlm_name_types), 0x0, "", HFILL }},
     { &hf_ntlmssp_ntlmv2_response_name_len,
-      { "Name len", "ntlmssp.ntlmv2response.name.len", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+      { "Value len", "ntlmssp.ntlmv2response.name.len", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+    { &hf_ntlmssp_ntlmv2_response_restriction,
+      { "Encoding restrictions", "ntlmssp.ntlmv2response.name.restrictions", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
     { &hf_ntlmssp_ntlmv2_response_client_time,
       { "Client Time", "ntlmssp.ntlmv2response.client_time", FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0, "", HFILL }}
   };
@@ -1772,6 +2530,7 @@
 				   &nt_password);
 
   register_dissector("ntlmssp", dissect_ntlmssp, proto_ntlmssp);
+  new_register_dissector("ntlmssp_payload", dissect_ntlmssp_payload, proto_ntlmssp);
   new_register_dissector("ntlmssp_verf", dissect_ntlmssp_verf, proto_ntlmssp);
 }
 
--- ../ref_wr/wireshark-1.1.3-SVN-27393/epan/dissectors/packet-gssapi.c	2009-02-08 19:13:58.000000000 +0300
+++ epan/dissectors/packet-gssapi.c	2009-02-25 20:58:16.171352121 +0300
@@ -112,6 +112,7 @@
  */
 
 static dissector_handle_t ntlmssp_handle;
+static dissector_handle_t ntlmssp_payload_handle;
 static dissector_handle_t spnego_krb5_wrap_handle;
 
 static GHashTable *gssapi_oids;
@@ -315,6 +316,15 @@
 						   pinfo, subtree);
 		    goto done;
 		  }
+		  /* Maybe it's new NTLMSSP payload */
+		  if ((tvb_length_remaining(gss_tvb, start_offset)>16) &&
+		      ((tvb_memeql(gss_tvb, start_offset, "\x01\x00\x00\x00", 4) == 0))) {
+		    return_offset = call_dissector(ntlmssp_payload_handle,
+						   tvb_new_subset(gss_tvb, start_offset, -1, -1),
+						   pinfo, subtree);
+        pinfo->gssapi_data_encrypted = TRUE;
+		    goto done;
+		  }
 
 		  /* Maybe it's new GSSKRB5 CFX Wrapping */
 		  if ((tvb_length_remaining(gss_tvb, start_offset)>2) &&
@@ -630,6 +640,7 @@
 	dissector_handle_t gssapi_handle;
 
 	ntlmssp_handle = find_dissector("ntlmssp");
+	ntlmssp_payload_handle = find_dissector("ntlmssp_payload");
 	spnego_krb5_wrap_handle = find_dissector("spnego-krb5-wrap");
 
 	register_dcerpc_auth_subdissector(DCE_C_AUTHN_LEVEL_CONNECT,


More information about the samba-technical mailing list