For proto_tree_add_item(..., proto_xxx, ...)use ENC_NA as the encoding arg.
[obnox/wireshark/wip.git] / epan / dissectors / packet-ntlmssp.c
index 6997d7f467979555d285f356889096038a1b2b69..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"
 
@@ -527,7 +527,7 @@ get_md4pass_list(md4_pass** p_pass_list,const char* nt_password)
 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 )
+                      const ntlmssp_blob *ntlm_response, const ntlmssp_blob *lm_response _U_, ntlmssp_header_t *ntlmssph )
 {
   char domain_name_unicode[256];
   char user_uppercase[256];
@@ -600,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;
     }
@@ -847,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.
@@ -970,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);
+                             tvb, blob_offset, 8, ENC_NA);
       }
     }
   }
@@ -986,7 +986,7 @@ dissect_ntlmssp_blob (tvbuff_t *tvb, int offset,
   {
     proto_tree_add_item (ntlmssp_tree,
                          hf_ntlmssp_ntlm_client_challenge,
-                         tvb, blob_offset+32, 8, FALSE);
+                         tvb, blob_offset+32, 8, ENC_NA);
     dissect_ntlmv2_response(tvb, tree, blob_offset, blob_length);
   }
 
@@ -1327,26 +1327,26 @@ dissect_ntlmv2_response(tvbuff_t *tvb, proto_tree *tree, int offset, int len)
   if (tree) {
     ntlmv2_item = proto_tree_add_item(
       tree, hf_ntlmssp_ntlmv2_response, tvb,
-      offset, len, TRUE);
+      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, TRUE);
+    offset, 16, ENC_NA);
 
   offset += 16;
 
   proto_tree_add_item(
     ntlmv2_tree, hf_ntlmssp_ntlmv2_response_header, tvb,
-    offset, 4, TRUE);
+    offset, 4, ENC_LITTLE_ENDIAN);
 
   offset += 4;
 
   proto_tree_add_item(
     ntlmv2_tree, hf_ntlmssp_ntlmv2_response_reserved, tvb,
-    offset, 4, TRUE);
+    offset, 4, ENC_LITTLE_ENDIAN);
 
   offset += 4;
 
@@ -1355,13 +1355,13 @@ dissect_ntlmv2_response(tvbuff_t *tvb, proto_tree *tree, int offset, int len)
 
   proto_tree_add_item(
     ntlmv2_tree, hf_ntlmssp_ntlmv2_response_chal, tvb,
-    offset, 8, TRUE);
+    offset, 8, ENC_NA);
 
   offset += 8;
 
   proto_tree_add_item(
     ntlmv2_tree, hf_ntlmssp_ntlmv2_response_unknown, tvb,
-    offset, 4, TRUE);
+    offset, 4, ENC_LITTLE_ENDIAN);
 
   offset += 4;
 
@@ -1412,9 +1412,11 @@ dissect_ntlmssp_negotiate (tvbuff_t *tvb, int offset, proto_tree *ntlmssp_tree,
   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;
 }
@@ -1442,7 +1444,7 @@ dissect_ntlmssp_challenge_target_info_blob (tvbuff_t *tvb, int offset,
 
   if (ntlmssp_tree) {
     tf = proto_tree_add_item (ntlmssp_tree, hf_ntlmssp_challenge_target_info, tvb,
-                              challenge_target_info_offset, challenge_target_info_length, FALSE);
+                              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(challenge_target_info_tree, hf_ntlmssp_challenge_target_info_len,
@@ -1505,7 +1507,7 @@ dissect_ntlmssp_challenge (tvbuff_t *tvb, packet_info *pinfo, int offset,
   /* NTLMSSP NT Lan Manager Challenge */
   proto_tree_add_item (ntlmssp_tree,
                        hf_ntlmssp_ntlm_server_challenge,
-                       tvb, offset, 8, FALSE);
+                       tvb, offset, 8, ENC_NA);
 
   /*
    * Store the flags and the RC4 state information with the conversation,
@@ -1573,7 +1575,7 @@ dissect_ntlmssp_challenge (tvbuff_t *tvb, packet_info *pinfo, int offset,
    * 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;
 
   /*
@@ -1593,9 +1595,11 @@ dissect_ntlmssp_challenge (tvbuff_t *tvb, packet_info *pinfo, int offset,
     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);
@@ -1746,9 +1750,8 @@ dissect_ntlmssp_auth (tvbuff_t *tvb, packet_info *pinfo, int offset,
   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);
@@ -1780,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 */
@@ -1807,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
         {
@@ -1935,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;
@@ -1949,7 +1957,7 @@ dissect_ntlmssp_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
   if (tree) {
     tf = proto_tree_add_item (tree,
                               hf_ntlmssp_verf,
-                              tvb, offset, -1, FALSE);
+                              tvb, offset, -1, ENC_NA);
 
     ntlmssp_tree = proto_item_add_subtree (tf,
                                            ett_ntlmssp);
@@ -1967,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);
@@ -1986,6 +1995,11 @@ 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;
 
@@ -2107,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;
@@ -2118,7 +2133,7 @@ dissect_ntlmssp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   if (tree) {
     tf = proto_tree_add_item (tree,
                               proto_ntlmssp,
-                              tvb, offset, -1, FALSE);
+                              tvb, offset, -1, ENC_NA);
 
     ntlmssp_tree = proto_item_add_subtree (tf,
                                            ett_ntlmssp);
@@ -2136,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) {
@@ -2178,12 +2193,29 @@ dissect_ntlmssp(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;
 
   /*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;
+}
 
 
 /*
@@ -2329,31 +2361,31 @@ decrypt_verifier(tvbuff_t *tvb, int offset, guint32 encrypted_block_length,
 
   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;
   }
 }
@@ -2365,6 +2397,8 @@ 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);
@@ -2375,7 +2409,7 @@ dissect_ntlmssp_payload_only(tvbuff_t *tvb, packet_info *pinfo, _U_ proto_tree *
   if (tree) {
     tf = proto_tree_add_item (tree,
                               hf_ntlmssp_verf,
-                              tvb, offset, -1, FALSE);
+                              tvb, offset, -1, ENC_NA);
 
     ntlmssp_tree = proto_item_add_subtree (tf,
                                            ett_ntlmssp);
@@ -2393,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 */
 
@@ -2403,6 +2438,11 @@ 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;
 
@@ -2420,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;
@@ -2434,7 +2475,7 @@ dissect_ntlmssp_verf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
   if (tree) {
     tf = proto_tree_add_item (tree,
                               hf_ntlmssp_verf,
-                              tvb, offset, -1, FALSE);
+                              tvb, offset, -1, ENC_NA);
 
     ntlmssp_tree = proto_item_add_subtree (tf,
                                            ett_ntlmssp);
@@ -2452,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);
@@ -2471,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;
 
@@ -2806,7 +2853,7 @@ proto_register_ntlmssp(void)
     { &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}},
 
@@ -2986,6 +3033,9 @@ proto_reg_handoff_ntlmssp(void)
                                     DCE_C_RPC_AUTHN_PROTOCOL_NTLMSSP,
                                     &ntlmssp_seal_fns);
   ntlmssp_tap = register_tap("ntlmssp");
+
+  heur_dissector_add("credssp", dissect_ntlmssp_heur, proto_ntlmssp);
+
 }
 
 /*
@@ -2997,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:
  */