Ethereal-dev: Re: [Ethereal-dev] ntlmssp decoding

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Devin Heitmueller <dheitmueller@xxxxxxxxxxx>
Date: 06 Jul 2002 19:27:42 -0400
Ok, here is where I am now.

Made all the changes that were recommended, I think.  I have not yet
broken it into a separate dissector.  That is next on my list.  In the
meantime, please review the revised patch.

* Changed all comments to /* */ notation
* Reversed order of boolean dissection
* Broke flags field dissection into it's own function
* NTLMSSP code now only runs if auth_type is 10, and the DCE/RPC request
type is BIND or BIND act.  This is because the auth_type is set for all
subsequent packets in the stream regardless of the presence of the
NTLMSSP payload.  If anyone know of something better to key off of, let
me know.
* Added checks for proto_tree before calling proto_tree_add_xxx
* Properly decode strings
* Additional dissection of workstation name, domain name
* Separated NTLMSSP into it's own subtree
* Lots of cleanup

Still a work in progress, but getting closer....

Thanks to everyone who has offered feedback,

Devin

-- 
Devin Heitmueller
Senior Software Engineer
Netilla Networks Inc
Index: packet-dcerpc.c
===================================================================
RCS file: /cvsroot/ethereal/packet-dcerpc.c,v
retrieving revision 1.64
diff -u --unified -r1.64 packet-dcerpc.c
--- packet-dcerpc.c	2002/06/24 09:23:39	1.64
+++ packet-dcerpc.c	2002/07/06 23:22:03
@@ -99,6 +99,34 @@
 	{ 0, NULL }
 };
 
+static const value_string ntlmssp_message_types[] = {
+  { 1, "NTLMSSP_NEGOTIATE" },
+  { 2, "NTLMSSP_CHALLENGE" },
+  { 3, "NTLMSSP_AUTH" },
+  { 4, "NTLMSSP_UNKNOWN" }
+};
+
+/* 
+ * NTLMSSP negotiation flags 
+ * Taken from Samba-TNG rpc_ntlmssp.h
+ */
+#define NTLMSSP_NEGOTIATE_UNICODE          0x00000001
+#define NTLMSSP_NEGOTIATE_OEM              0x00000002
+#define NTLMSSP_REQUEST_TARGET             0x00000004
+#define NTLMSSP_NEGOTIATE_SIGN             0x00000010
+#define NTLMSSP_NEGOTIATE_SEAL             0x00000020
+#define NTLMSSP_NEGOTIATE_LM_KEY           0x00000080
+#define NTLMSSP_NEGOTIATE_00000100         0x00000100
+#define NTLMSSP_NEGOTIATE_NTLM             0x00000200
+#define NTLMSSP_NEGOTIATE_00000400         0x00000400
+#define NTLMSSP_NEGOTIATE_00001000         0x00001000
+#define NTLMSSP_NEGOTIATE_00002000         0x00002000
+#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN      0x00008000
+#define NTLMSSP_NEGOTIATE_NTLM2            0x00080000
+#define NTLMSSP_NEGOTIATE_TARGET_INFO      0x00800000
+#define NTLMSSP_NEGOTIATE_128              0x20000000
+#define NTLMSSP_NEGOTIATE_KEY_EXCH         0x40000000
+
 /*
  * Protection levels.
  */
@@ -381,7 +409,40 @@
 static int hf_dcerpc_fragment_multiple_tails = -1;
 static int hf_dcerpc_fragment_too_long_fragment = -1;
 static int hf_dcerpc_fragment_error = -1;
+static int hf_dcerpc_auth_ntlmssp = -1;
+static int hf_dcerpc_ntlmssp = -1;
+static int hf_dcerpc_ntlmssp_message_type = -1;
+static int hf_dcerpc_ntlmssp_negotiate_flags = -1;
+static int hf_dcerpc_ntlmssp_negotiate_flags_01 = -1;
+static int hf_dcerpc_ntlmssp_negotiate_flags_02 = -1;
+static int hf_dcerpc_ntlmssp_negotiate_flags_04 = -1;
+static int hf_dcerpc_ntlmssp_negotiate_flags_10 = -1;
+static int hf_dcerpc_ntlmssp_negotiate_flags_20 = -1;
+static int hf_dcerpc_ntlmssp_negotiate_flags_80 = -1;
+static int hf_dcerpc_ntlmssp_negotiate_flags_100 = -1;
+static int hf_dcerpc_ntlmssp_negotiate_flags_200 = -1;
+static int hf_dcerpc_ntlmssp_negotiate_flags_400 = -1;
+static int hf_dcerpc_ntlmssp_negotiate_flags_1000 = -1;
+static int hf_dcerpc_ntlmssp_negotiate_flags_2000 = -1;
+static int hf_dcerpc_ntlmssp_negotiate_flags_8000 = -1;
+static int hf_dcerpc_ntlmssp_negotiate_flags_80000 = -1;
+static int hf_dcerpc_ntlmssp_negotiate_flags_800000 = -1;
+static int hf_dcerpc_ntlmssp_negotiate_flags_20000000 = -1;
+static int hf_dcerpc_ntlmssp_negotiate_flags_40000000 = -1;
+static int hf_dcerpc_ntlmssp_negotiate_workstation_strlen = -1;
+static int hf_dcerpc_ntlmssp_negotiate_workstation_maxlen = -1;
+static int hf_dcerpc_ntlmssp_negotiate_workstation_buffer = -1;
+static int hf_dcerpc_ntlmssp_negotiate_workstation = -1;
+static int hf_dcerpc_ntlmssp_negotiate_domain_strlen = -1;
+static int hf_dcerpc_ntlmssp_negotiate_domain_maxlen = -1;
+static int hf_dcerpc_ntlmssp_negotiate_domain_buffer = -1;
+static int hf_dcerpc_ntlmssp_negotiate_domain = -1;
+static int hf_dcerpc_ntlmssp_ntlm_challenge = -1;
+static int hf_dcerpc_ntlmssp_reserved = -1;
+static int hf_dcerpc_ntlmssp_challenge_unknown1 = -1;
+static int hf_dcerpc_ntlmssp_challenge_unknown2 = -1;
 
+
 static gint ett_dcerpc = -1;
 static gint ett_dcerpc_cn_flags = -1;
 static gint ett_dcerpc_drep = -1;
@@ -390,6 +451,9 @@
 static gint ett_dcerpc_pointer_data = -1;
 static gint ett_dcerpc_fragments = -1;
 static gint ett_dcerpc_fragment = -1;
+static gint ett_dcerpc_ntlmssp = -1;
+static gint ett_dcerpc_negotiate_flags = -1;
+
 
 fragment_items dcerpc_frag_items = {
 	&ett_dcerpc_fragments,
@@ -1298,12 +1362,191 @@
 }
 
 static int
+dissect_dcerpc_ntlmssp_negotiate_flags (tvbuff_t *tvb, int offset, 
+					packet_info *pinfo,
+					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_dcerpc_ntlmssp_negotiate_flags, 
+			      tvb, offset, 4, negotiate_flags);
+    negotiate_flags_tree = proto_item_add_subtree (tf, ett_dcerpc_negotiate_flags);
+    
+    proto_tree_add_boolean (negotiate_flags_tree, 
+			    hf_dcerpc_ntlmssp_negotiate_flags_40000000, 
+			    tvb, offset, 4, negotiate_flags);
+    proto_tree_add_boolean (negotiate_flags_tree, 
+			    hf_dcerpc_ntlmssp_negotiate_flags_20000000, 
+			    tvb, offset, 4, negotiate_flags);
+    proto_tree_add_boolean (negotiate_flags_tree, 
+			    hf_dcerpc_ntlmssp_negotiate_flags_800000, 
+			    tvb, offset, 4, negotiate_flags);
+    proto_tree_add_boolean (negotiate_flags_tree, 
+			    hf_dcerpc_ntlmssp_negotiate_flags_80000, 
+			    tvb, offset, 4, negotiate_flags);
+    proto_tree_add_boolean (negotiate_flags_tree, 
+			    hf_dcerpc_ntlmssp_negotiate_flags_8000, 
+			    tvb, offset, 4, negotiate_flags);
+    proto_tree_add_boolean (negotiate_flags_tree, 
+			    hf_dcerpc_ntlmssp_negotiate_flags_2000, 
+			    tvb, offset, 4, negotiate_flags);
+    proto_tree_add_boolean (negotiate_flags_tree,
+			    hf_dcerpc_ntlmssp_negotiate_flags_1000,
+			    tvb, offset, 4, negotiate_flags);
+    proto_tree_add_boolean (negotiate_flags_tree, 
+			    hf_dcerpc_ntlmssp_negotiate_flags_400, 
+			    tvb, offset, 4, negotiate_flags);
+    proto_tree_add_boolean (negotiate_flags_tree, 
+			    hf_dcerpc_ntlmssp_negotiate_flags_200, 
+			    tvb, offset, 4, negotiate_flags);
+    proto_tree_add_boolean (negotiate_flags_tree, 
+			    hf_dcerpc_ntlmssp_negotiate_flags_100, 
+			    tvb, offset, 4, negotiate_flags);
+    proto_tree_add_boolean (negotiate_flags_tree,
+			    hf_dcerpc_ntlmssp_negotiate_flags_80, 
+			    tvb, offset, 4, negotiate_flags);
+    proto_tree_add_boolean (negotiate_flags_tree, 
+			    hf_dcerpc_ntlmssp_negotiate_flags_20, 
+			    tvb, offset, 4, negotiate_flags);
+    proto_tree_add_boolean (negotiate_flags_tree, 
+			    hf_dcerpc_ntlmssp_negotiate_flags_10,
+			    tvb, offset, 4, negotiate_flags);
+    proto_tree_add_boolean (negotiate_flags_tree, 
+			    hf_dcerpc_ntlmssp_negotiate_flags_04, 
+			    tvb, offset, 4, negotiate_flags);
+    proto_tree_add_boolean (negotiate_flags_tree, 
+			    hf_dcerpc_ntlmssp_negotiate_flags_02, 
+			    tvb, offset, 4, negotiate_flags);
+    proto_tree_add_boolean (negotiate_flags_tree, 
+			    hf_dcerpc_ntlmssp_negotiate_flags_01, 
+			    tvb, offset, 4, negotiate_flags);  
+  }
+  return (offset + 4);
+}
+
+
+static int
+dissect_dcerpc_ntlmssp_negotiate (tvbuff_t *tvb, int offset, 
+				  packet_info *pinfo,
+				  proto_tree *ntlmssp_tree,
+				  e_dce_cn_common_hdr_t *hdr)
+{
+  guint32 negotiate_flags;
+  guint16 workstation_length;
+  guint16 domain_length;
+
+  /* NTLMSSP Negotiate Flags */
+  negotiate_flags = tvb_get_letohs (tvb, offset);
+
+  offset = dissect_dcerpc_ntlmssp_negotiate_flags (tvb, offset, pinfo, 
+						   ntlmssp_tree,
+						   negotiate_flags);
+
+  /* Calling workstation domain name length */
+  offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ntlmssp_tree,
+				  hdr->drep,
+				  hf_dcerpc_ntlmssp_negotiate_domain_strlen,
+				  &domain_length);
+
+  /* Calling workstation domain name max length */
+  offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ntlmssp_tree,
+				  hdr->drep,
+				  hf_dcerpc_ntlmssp_negotiate_domain_maxlen,
+				  NULL);
+
+  /* Calling workstation domain name buffer? */
+  offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, ntlmssp_tree,
+				  hdr->drep,
+				  hf_dcerpc_ntlmssp_negotiate_domain_buffer,
+				  NULL);
+
+  /* Calling workstation name length */
+  offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ntlmssp_tree,
+				  hdr->drep,
+				  hf_dcerpc_ntlmssp_negotiate_workstation_strlen,
+				  &workstation_length);
+
+  /* Calling workstation name max length */
+  offset = dissect_dcerpc_uint16 (tvb, offset, pinfo, ntlmssp_tree,
+				  hdr->drep,
+				  hf_dcerpc_ntlmssp_negotiate_workstation_maxlen,
+				  NULL);
+
+  /* Calling workstation name buffer? */
+  offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, ntlmssp_tree,
+				  hdr->drep,
+				  hf_dcerpc_ntlmssp_negotiate_workstation_buffer,
+				  NULL);
+
+  /* Calling workstation name */
+  if (ntlmssp_tree) {
+    proto_tree_add_item (ntlmssp_tree, hf_dcerpc_ntlmssp_negotiate_workstation,
+			 tvb, offset, workstation_length, FALSE);
+  }
+  offset += workstation_length;
+
+  /* Calling domain name */
+  if (ntlmssp_tree) {
+    proto_tree_add_item (ntlmssp_tree, hf_dcerpc_ntlmssp_negotiate_domain,
+		       tvb, offset, domain_length, FALSE);
+  }
+  offset += domain_length;
+
+  return offset;
+}
+
+static int
+dissect_dcerpc_ntlmssp_challenge (tvbuff_t *tvb, int offset, packet_info *pinfo,
+				  proto_tree *ntlmssp_tree,
+				  e_dce_cn_common_hdr_t *hdr)
+{
+  guint32 negotiate_flags;
+
+  /* Skip over the two unknown fields */
+  offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, ntlmssp_tree,
+				  hdr->drep,
+				  hf_dcerpc_ntlmssp_challenge_unknown1,
+				  NULL);
+
+  offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, ntlmssp_tree,
+				  hdr->drep,
+				  hf_dcerpc_ntlmssp_challenge_unknown2,
+				  NULL);
+
+  /* NTLMSSP Negotiate Flags */
+  negotiate_flags = tvb_get_letohs (tvb, offset);
+  offset = dissect_dcerpc_ntlmssp_negotiate_flags (tvb, offset, pinfo, 
+						   ntlmssp_tree,
+						   negotiate_flags);
+
+  if (ntlmssp_tree) {
+    proto_tree_add_item (ntlmssp_tree,
+			 hf_dcerpc_ntlmssp_ntlm_challenge,
+			 tvb, offset, 8, FALSE);
+  }
+  offset += 8;
+  
+  if (ntlmssp_tree) {
+    proto_tree_add_item (ntlmssp_tree, hf_dcerpc_ntlmssp_reserved,
+			 tvb, offset, 8, FALSE);
+  }
+  offset += 8;
+
+  return offset;
+}
+
+static int
 dissect_dcerpc_cn_auth (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
                         e_dce_cn_common_hdr_t *hdr, int *auth_level_p)
 {
     int offset;
     guint8 auth_pad_len;
     guint8 auth_level;
+    guint8 auth_type;
 
     /*
      * Initially set "*auth_level_p" to -1 to indicate that we haven't
@@ -1327,7 +1570,7 @@
         offset = hdr->frag_len - (hdr->auth_len + 8);
         
         offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
-                                       hf_dcerpc_auth_type, NULL);
+                                       hf_dcerpc_auth_type, &auth_type);
         offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
                                        hf_dcerpc_auth_level, &auth_level);
         if (auth_level_p != NULL)
@@ -1339,7 +1582,53 @@
         offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
                                         hf_dcerpc_auth_ctx_id, NULL);
 
-        proto_tree_add_text (dcerpc_tree, tvb, offset, hdr->auth_len, "Auth Data");
+	/* Dissect NTLMSSP Parameters if the auth_type is 10 and this is a
+	   BIND request or BIND response)
+	*/
+	if ((auth_type == 10) &&
+	    ((hdr->ptype == PDU_BIND) || (hdr->ptype == PDU_BIND_ACK))) {
+	  proto_tree *ntlmssp_tree = NULL;
+	  proto_item *tf = NULL;
+
+	  /* Setup a new tree for the NTLMSSP payload */
+	  if (dcerpc_tree) {
+	    tf = proto_tree_add_item (dcerpc_tree, 
+				      hf_dcerpc_ntlmssp,
+				      tvb, offset, hdr->auth_len, FALSE);
+	    
+	    ntlmssp_tree = proto_item_add_subtree (tf, 
+						   ett_dcerpc_ntlmssp);
+	  }
+
+	  /* NTLMSSP constant */
+	  if (ntlmssp_tree) {
+	    proto_tree_add_item (ntlmssp_tree, hf_dcerpc_auth_ntlmssp, 
+				 tvb, offset, 8, FALSE);
+	  }
+	  offset += 8;
+	  
+	  /* NTLMSSP Message Type */
+	  offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, ntlmssp_tree, 
+					  hdr->drep, 
+					  hf_dcerpc_ntlmssp_message_type,
+					  &hdr->ntlmssp_message_type);
+
+	  /* Call the appropriate dissector based on the Message Type */
+	  if (hdr->ntlmssp_message_type == 1)
+	    offset = dissect_dcerpc_ntlmssp_negotiate (tvb, offset, pinfo,
+						       ntlmssp_tree, hdr);
+	  else if (hdr->ntlmssp_message_type == 2)
+	    offset = dissect_dcerpc_ntlmssp_challenge (tvb, offset, pinfo,
+						       ntlmssp_tree, hdr);
+	  else {
+	    /* Unrecognized message type */
+	    if (ntlmssp_tree) {
+	      proto_tree_add_text (ntlmssp_tree, tvb, offset, 
+				   (hdr->auth_len - 12), 
+				   "Unrecognized NTLMSSP Message");
+	    }
+	  }
+	}
 
         /* figure out where the auth padding starts */
         offset = hdr->frag_len - (hdr->auth_len + 8 + auth_pad_len);
@@ -3427,6 +3716,73 @@
 	{ &hf_dcerpc_fragment_error,
 	  { "Defragmentation error", "dcerpc.fragment.error", FT_NONE, BASE_NONE, NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }},
 
+        { &hf_dcerpc_ntlmssp,
+          { "NTLMSSP", "dcerpc.ntlmssp", FT_NONE, BASE_NONE, NULL, 0x0, "NTLMSSP", HFILL }},
+
+        { &hf_dcerpc_auth_ntlmssp, 
+          { "NTLMSSP identifier", "dcerpc.auth_ntlmssp", FT_STRING, BASE_NONE, NULL, 0x0, "NTLMSSP Identifier", HFILL }},
+
+        { &hf_dcerpc_ntlmssp_message_type,
+          { "NTLM Message Type", "dcerpc.ntlmssp.messagetype", FT_UINT32, BASE_HEX, VALS(ntlmssp_message_types), 0x0, "", HFILL }},
+
+        { &hf_dcerpc_ntlmssp_negotiate_flags,
+          { "Flags", "dcerpc.negotiateflags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_flags_01,
+          { "Negotiate UNICODE", "dcerpc.ntlmssp.negotiateunicode", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_UNICODE, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_flags_02,
+          { "Negotiate OEM", "dcerpc.ntlmssp.negotiateoem", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_OEM, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_flags_04,
+          { "Request Target", "dcerpc.ntlmssp.requesttarget", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_REQUEST_TARGET, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_flags_10,
+          { "Negotiate Sign", "dcerpc.ntlmssp.negotiatesign", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_SIGN, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_flags_20,
+          { "Negotiate Seal", "dcerpc.ntlmssp.negotiateseal", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_SEAL, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_flags_80,
+          { "Negotiate Lan Manager Key", "dcerpc.ntlmssp.negotiatelmkey", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_LM_KEY, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_flags_100,
+          { "Negotiate 0x00000100", "dcerpc.ntlmssp.negotiate00000100", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00000100, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_flags_200,
+          { "Negotiate NTLM key", "dcerpc.ntlmssp.negotiatentlm", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_NTLM, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_flags_400,
+          { "Negotiate 0x00000400", "dcerpc.ntlmssp.negotiate00000400", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00000400, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_flags_1000,
+          { "Negotiate 0x00001000", "dcerpc.ntlmssp.negotiate00001000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00001000, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_flags_2000,
+          { "Negotiate 0x00002000", "dcerpc.ntlmssp.negotiate00002000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00002000, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_flags_8000,
+          { "Negotiate Always Sign", "dcerpc.ntlmssp.negotiatealwayssign", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_ALWAYS_SIGN, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_flags_80000,
+          { "Negotiate NTLM2 key", "dcerpc.ntlmssp.negotiatentlm2", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_NTLM2, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_flags_800000,
+          { "Negotiate Target Info", "dcerpc.ntlmssp.negotiatetargetinfo", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_TARGET_INFO, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_flags_20000000,
+          { "Negotiate 128", "dcerpc.ntlmssp.negotiate128", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_128, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_flags_40000000,
+          { "Negotiate Key Exchange", "dcerpc.ntlmssp.negotiatekeyexch", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_KEY_EXCH, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_workstation_strlen,
+          { "Calling workstation name length", "dcerpc.ntlmssp.negotiate.callingworkstation.strlen", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_workstation_maxlen,
+          { "Calling workstation name max length", "dcerpc.ntlmssp.negotiate.callingworkstation.maxlen", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_workstation_buffer,
+          { "Calling workstation name buffer", "dcerpc.ntlmssp.negotiate.callingworkstation.buffer", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_workstation,
+          { "Calling workstation name", "dcerpc.ntlmssp.negotiate.callingworkstation", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_domain_strlen,
+          { "Calling workstation domain length", "dcerpc.ntlmssp.negotiate.domain.strlen", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_domain_maxlen,
+          { "Calling workstation domain max length", "dcerpc.ntlmssp.negotiate.domain.maxlen", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_domain_buffer,
+          { "Calling workstation domain buffer", "dcerpc.ntlmssp.negotiate.domain.buffer", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_negotiate_domain,
+          { "Calling workstation domain", "dcerpc.ntlmssp.negotiate.domain", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_ntlm_challenge,
+          { "NTLM Challenge", "dcerpc.ntlmssp.ntlmchallenge", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_reserved,
+          { "Reserved", "dcerpc.ntlmssp.reserved", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_challenge_unknown1,
+          { "Unknown1", "dcerpc.ntlmssp.challenge.unknown1", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
+        { &hf_dcerpc_ntlmssp_challenge_unknown2,
+          { "Unknown2", "dcerpc.ntlmssp.challenge.unknown2", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
     };
     static gint *ett[] = {
         &ett_dcerpc,
@@ -3437,6 +3793,8 @@
         &ett_dcerpc_pointer_data,
         &ett_dcerpc_fragments,
         &ett_dcerpc_fragment,
+	&ett_dcerpc_ntlmssp,
+        &ett_dcerpc_negotiate_flags,
     };
     module_t *dcerpc_module;
 
Index: packet-dcerpc.h
===================================================================
RCS file: /cvsroot/ethereal/packet-dcerpc.h,v
retrieving revision 1.18
diff -u --unified -r1.18 packet-dcerpc.h
--- packet-dcerpc.h	2002/06/24 00:03:18	1.18
+++ packet-dcerpc.h	2002/07/06 23:22:03
@@ -48,6 +48,7 @@
     guint16 frag_len;
     guint16 auth_len;
     guint32 call_id;
+    guint32 ntlmssp_message_type;
 } e_dce_cn_common_hdr_t;
 
 typedef struct _e_dce_dg_common_hdr_t {