Ethereal-dev: [Ethereal-dev] some dcerpc and nbss updates

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

From: Todd Sabin <tas@xxxxxxxxxxx>
Date: 26 Sep 2001 07:46:52 -0400
Hi,

The attached diff contains code to do two things.

1.  dissect the auth info in connection oriented dcerpc packets.

2.  modifies packet-nbns.c to use pass off netbios session packets to
heuristic dissectors, and packet-dcerpc.c registers itself there.
Most of the time, the layer directly above netbios session is SMB.
However, it's possible to do DCE/RPC directly on the netbios session
layer, with the ncacn_nb_tcp protseq.  That's what this is for.  Note
that for this to work, I've had to comment out the #define RJSHACK,
because it's just, well, wrong.  I think the correct solution is to
make the SMB dissector a heuristic dissector as well, and then if no
dissector claims a nbns packet, do the stuff in the RJSHACK code.  For
now, though, if no heuristic nbss dissector handles a packet, it's
shipped off to dissect_smb directly, as before.


Todd


Index: packet-dcerpc.c
===================================================================
RCS file: /cvsroot/ethereal/packet-dcerpc.c,v
retrieving revision 1.8
diff -u -r1.8 packet-dcerpc.c
--- packet-dcerpc.c	2001/09/03 10:33:05	1.8
+++ packet-dcerpc.c	2001/09/26 02:26:08
@@ -102,6 +102,11 @@
 static int hf_dcerpc_cn_ack_result = -1;
 static int hf_dcerpc_cn_ack_reason = -1;
 static int hf_dcerpc_cn_cancel_count = -1;
+static int hf_dcerpc_auth_type = -1;
+static int hf_dcerpc_auth_level = -1;
+static int hf_dcerpc_auth_pad_len = -1;
+static int hf_dcerpc_auth_rsrvd = -1;
+static int hf_dcerpc_auth_ctx_id = -1;
 static int hf_dcerpc_dg_flags1 = -1;
 static int hf_dcerpc_dg_flags1_rsrvd_01 = -1;
 static int hf_dcerpc_dg_flags1_last_frag = -1;
@@ -442,7 +447,51 @@
     return 0;
 }
 
+static int
+dissect_dcerpc_cn_auth (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree,
+                        e_dce_cn_common_hdr_t *hdr)
+{
+    int offset;
+    guint8 auth_pad_len;
+    /*
+     * If the full packet is here, and we've got an auth len, and it's
+     * valid, then dissect the auth info
+     */
+    if (tvb_length (tvb) >= hdr->frag_len
+        && hdr->auth_len
+        && (hdr->auth_len + 8 <= hdr->frag_len)) {
+
+        offset = hdr->frag_len - (hdr->auth_len + 8);
+        
+        offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                       hf_dcerpc_auth_type, NULL);
+        offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                       hf_dcerpc_auth_level, NULL);
+        offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                       hf_dcerpc_auth_pad_len, &auth_pad_len);
+        offset = dissect_dcerpc_uint8 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
+                                       hf_dcerpc_auth_rsrvd, NULL);
+        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");
+
+        /* figure out where the auth padding starts */
+        offset = hdr->frag_len - (hdr->auth_len + 8 + auth_pad_len);
+        if (offset > 0 && auth_pad_len) {
+            proto_tree_add_text (dcerpc_tree, tvb, offset, 
+                                 auth_pad_len, "Auth padding");
+            return hdr->auth_len + 8 + auth_pad_len;
+        } else {
+            return hdr->auth_len + 8;
+        }
+    } else {
+        return 0;
+    }
+}
 
+
+
 /*
  * Connection oriented packet types
  */
@@ -525,6 +574,8 @@
     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
                                     hf_dcerpc_cn_bind_trans_ver, &trans_ver);
 
+    dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr);
+
     if (check_col (pinfo->fd, COL_INFO)) {
         col_add_fstr (pinfo->fd, COL_INFO, "%s: UUID %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x ver %d.%d",
                       hdr->ptype == PDU_BIND ? "Bind" : "Alter Ctx",
@@ -597,6 +648,8 @@
                                         &reason);
     }
     
+    dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr);
+
     if (check_col (pinfo->fd, COL_INFO)) {
         if (num_results == 1 && result == 0) {
             col_add_fstr (pinfo->fd, COL_INFO, "%s ack: accept  max_xmit: %d  max_recv: %d",
@@ -621,7 +674,7 @@
     guint16 ctx_id;
     guint16 opnum;
     e_uuid_t obj_id;
-
+    int auth_sz = 0;
     int offset = 16;
 
     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
@@ -652,6 +705,8 @@
         offset += 16;
     }
 
+    auth_sz = dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr);
+
     if (check_col (pinfo->fd, COL_INFO)) {
         col_add_fstr (pinfo->fd, COL_INFO, "Request: opnum: %d  ctx_id:%d",
                          opnum, ctx_id);
@@ -675,7 +730,10 @@
                                  value->ver, &value->uuid);
 
             /* handoff this call */
-            dcerpc_try_handoff (pinfo, tree, tvb, offset,
+            dcerpc_try_handoff (pinfo, tree, 
+                                tvb_new_subset (tvb, offset, 
+                                                hdr->frag_len - offset - auth_sz,
+                                                hdr->frag_len - offset - auth_sz), 0,
                                 &value->uuid, value->ver,
                                 opnum, TRUE);
         }
@@ -688,7 +746,7 @@
 {
     conversation_t *conv;
     guint16 ctx_id;
-
+    int auth_sz = 0;
     int offset = 16;
 
     offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep,
@@ -702,6 +760,8 @@
     /* padding */
     offset++;
 
+    auth_sz = dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, hdr);
+
     if (check_col (pinfo->fd, COL_INFO)) {
         col_add_fstr (pinfo->fd, COL_INFO, "Response: call_id: %d  ctx_id:%d",
                       hdr->call_id, ctx_id);
@@ -714,7 +774,10 @@
     } else {
         dcerpc_call_value *value = dcerpc_call_lookup (hdr->call_id, conv);
         if (value) {
-            dcerpc_try_handoff (pinfo, tree, tvb, offset, 
+            dcerpc_try_handoff (pinfo, tree, 
+                                tvb_new_subset (tvb, offset, 
+                                                hdr->frag_len - offset - auth_sz,
+                                                hdr->frag_len - offset - auth_sz), 0,
                                 &value->uuid, value->ver,
                                 value->opnum, FALSE);
         }
@@ -727,6 +790,7 @@
 static gboolean
 dissect_dcerpc_cn (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
+    static char nulls[4] = { 0 };
     proto_item *ti = NULL;
     proto_item *tf = NULL;
     proto_tree *dcerpc_tree = NULL;
@@ -737,6 +801,13 @@
     /*
      * Check if this looks like a C/O DCERPC call
      */
+    /*
+     * when done over nbt, dcerpc requests are padded with 4 bytes of null
+     * data for some reason.
+     */
+    if (tvb_bytes_exist (tvb, 0, 4) && tvb_memeql (tvb, 0, nulls, 4) == 0) {
+        tvb = tvb_new_subset (tvb, 4, -1, -1);
+    }
     if (!tvb_bytes_exist (tvb, 0, sizeof (hdr))) {
         return FALSE;
     }
@@ -824,6 +895,8 @@
         break;
 
     default:
+        /* might as well dissect the auth info */
+        dissect_dcerpc_cn_auth (tvb, pinfo, dcerpc_tree, &hdr);
         break;
     }
     return TRUE;
@@ -1158,6 +1231,16 @@
           { "Ack reason", "dcerpc.cn_ack_reason", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_cn_cancel_count,
           { "Cancel count", "dcerpc.cn_cancel_count", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+        { &hf_dcerpc_auth_type,
+          { "Auth type", "dcerpc.auth_type", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+        { &hf_dcerpc_auth_level,
+          { "Auth level", "dcerpc.auth_level", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+        { &hf_dcerpc_auth_pad_len,
+          { "Auth pad len", "dcerpc.auth_pad_len", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+        { &hf_dcerpc_auth_rsrvd,
+          { "Auth Rsrvd", "dcerpc.auth_rsrvd", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+        { &hf_dcerpc_auth_ctx_id,
+          { "Auth Context ID", "dcerpc.auth_ctx_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_dg_flags1,
           { "Flags1", "dcerpc.dg_flags1", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
         { &hf_dcerpc_dg_flags1_rsrvd_01,
@@ -1244,5 +1327,6 @@
 proto_reg_handoff_dcerpc (void)
 {
     heur_dissector_add ("tcp", dissect_dcerpc_cn, proto_dcerpc);
+    heur_dissector_add ("nbss", dissect_dcerpc_cn, proto_dcerpc);
     heur_dissector_add ("udp", dissect_dcerpc_dg, proto_dcerpc);
 }
Index: packet-nbns.c
===================================================================
RCS file: /cvsroot/ethereal/packet-nbns.c,v
retrieving revision 1.56
diff -u -r1.56 packet-nbns.c
--- packet-nbns.c	2001/09/17 02:07:00	1.56
+++ packet-nbns.c	2001/09/26 02:26:14
@@ -43,6 +43,8 @@
 #include "packet-smb.h"
 #include "prefs.h"
 
+static heur_dissector_list_t nbns_heur_subdissector_list;
+
 static int proto_nbns = -1;
 static int hf_nbns_response = -1;
 static int hf_nbns_query = -1;
@@ -1383,7 +1385,6 @@
 	int		len;
 	char		name[(NETBIOS_NAME_LEN - 1)*4 + MAXDNAME];
 	int		name_type;
-	tvbuff_t	*next_tvb;
 
 	msg_type = tvb_get_guint8(tvb, offset);
 
@@ -1500,14 +1501,18 @@
 	   */
 	  proto_item_set_len(ti, offset);
 	  {
+		tvbuff_t	*next_tvb;
 		const guint8	*next_pd;
 		int		next_offset;
 
 		next_tvb = tvb_new_subset(tvb, offset, -1, -1);
 		tvb_compat(next_tvb, &next_pd, &next_offset);
 
-		dissect_smb(next_pd, next_offset, pinfo->fd, tree,
-		    max_data - 4);
+		if (!dissector_try_heuristic (nbns_heur_subdissector_list,
+                                      next_tvb, pinfo, tree)) {
+			dissect_smb(next_pd, next_offset, pinfo->fd, tree, 
+			            max_data - 4);
+		}
 	  }
 	  break;
 
@@ -1553,7 +1558,7 @@
 
 	/* Hmmm, it may be a continuation message ... */
 
-#define RJSHACK 1
+/*#define RJSHACK 1*/
 #ifdef RJSHACK
 	if (((msg_type != SESSION_REQUEST) && 
 	     (msg_type != POSITIVE_SESSION_RESPONSE) &&
@@ -1698,6 +1703,8 @@
   proto_register_field_array(proto_nbss, hf_nbss, array_length(hf_nbss));
 
   proto_register_subtree_array(ett, array_length(ett));
+
+  register_heur_dissector_list ("nbss", &nbns_heur_subdissector_list);
 
   nbss_module = prefs_register_protocol(proto_nbss, NULL);
   prefs_register_bool_preference(nbss_module, "desegment_nbss_commands",