From Solomon Peachy: do WEP decryption before reassembly.
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 18 Jun 2002 20:17:17 +0000 (20:17 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 18 Jun 2002 20:17:17 +0000 (20:17 +0000)
Use "memset()" rather than "bzero()", as "memset()" is the official ANSI
C routine (and you get an error when compiling with MSVC++ if you use
"bzero()").

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@5699 f5534014-38df-0310-8fa8-9805f1628bb7

packet-ieee80211.c

index 03fddb6f48e790fce49104f42846581b34d0ff59..86069370ac2aeba088e0105ae23f5df020204cfc 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright 2000, Axis Communications AB 
  * Inquiries/bugreports should be sent to Johan.Jorgensen@axis.com
  *
- * $Id: packet-ieee80211.c,v 1.65 2002/06/18 08:38:17 guy Exp $
+ * $Id: packet-ieee80211.c,v 1.66 2002/06/18 20:17:17 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -90,7 +90,7 @@ static guint8 **wep_keys = NULL;
 static int *wep_keylens = NULL;
 static void init_wepkeys(void);
 static int wep_decrypt(guint8 *buf, guint32 len, int key_override);
-static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb);
+static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len);
 #define SSWAP(a,b) {guint8 tmp = s[a]; s[a] = s[b]; s[b] = tmp;}
 
 /* #define USE_ENV */
@@ -1125,7 +1125,7 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
   guint16 hdr_len;
   gint len, reported_len;
   gboolean save_fragmented;
-  tvbuff_t *volatile next_tvb;
+  tvbuff_t *volatile next_tvb = NULL;
   guint32 addr_type;
   volatile gboolean is_802_2;
 
@@ -1558,6 +1558,102 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
       return;
     }
 
+  /*
+   * For WEP-encrypted frames, dissect the WEP parameters and decrypt
+   * the data, if we have a matching key.  Otherwise display it as data.
+   */
+  if (IS_WEP(COOK_FLAGS(fcf))) {
+    gboolean can_decrypt = FALSE;
+    proto_tree *wep_tree = NULL;
+
+    if (tree) {
+      proto_item *wep_fields;
+
+      wep_fields = proto_tree_add_text(tree, tvb, hdr_len, 4,
+                                          "WEP parameters");
+
+      wep_tree = proto_item_add_subtree (wep_fields, ett_wep_parameters);
+      proto_tree_add_item (wep_tree, hf_wep_iv, tvb, hdr_len, 3, TRUE);
+
+      proto_tree_add_uint (wep_tree, hf_wep_key, tvb, hdr_len, 1,
+                          COOK_WEP_KEY (tvb_get_guint8 (tvb, 3)));
+    }
+
+    len = tvb_length_remaining(tvb, 4);
+    reported_len = tvb_reported_length_remaining(tvb, 4);
+    if (len == -1 || reported_len == -1) {
+      /* We don't have anything beyond the IV. */
+      return;
+    }
+
+    /*
+     * Well, this packet should, in theory, have an ICV.
+     * Do we have the entire packet, and does it have enough data for
+     * the ICV?
+     */
+    if (reported_len < 4) {
+      /*
+       * The packet is claimed not to even have enough data for a
+       * 4-byte ICV.
+       * Pretend it doesn't have an ICV.
+       */
+      ;
+    } else if (len < reported_len) {
+      /*
+       * The packet is claimed to have enough data for a 4-byte ICV,
+       * but we didn't capture all of the packet.
+       * Slice off the 4-byte ICV from the reported length, and trim
+       * the captured length so it's no more than the reported length;
+       * that will slice off what of the ICV, if any, is in the
+       * captured length.
+       *
+       */
+      reported_len -= 4;
+      if (len > reported_len)
+       len = reported_len;
+    } else {
+      /*
+       * We have the entire packet, and it includes a 4-byte ICV.
+       * Slice it off, and put it into the tree.
+       *
+       * We only support decrypting if we have the the ICV.
+       *
+       * XXX - the ICV is encrypted; we're putting the encrypted
+       * value, not the decrypted value, into the tree.
+       */
+      len -= 4;
+      reported_len -= 4;
+      if (tree)
+       proto_tree_add_item (wep_tree, hf_wep_icv, tvb, len, 4,
+                            FALSE);
+      can_decrypt = TRUE;
+    }
+
+    if (!can_decrypt || (next_tvb = try_decrypt_wep(tvb, hdr_len, reported_len - hdr_len + 4)) == NULL) {
+      /* WEP decode impossible or failed, treat payload as raw data. */
+      next_tvb = tvb_new_subset(tvb, 4, len, reported_len);
+
+      call_dissector(data_handle, next_tvb, pinfo, tree);
+      return; 
+    } else {
+      add_new_data_source(pinfo, next_tvb, "Decrypted WEP data");
+       /*
+         if (check_col(pinfo->cinfo, COL_INFO))
+         col_set_str(pinfo->cinfo, COL_INFO, "Decrypted WEP data");
+       */
+    }
+    hdr_len += 4;  /* so we don't include the IV in the fragment payload */
+  }
+
+  if (next_tvb == NULL) {
+    next_tvb = tvb;  /* and WEP decode failed, if attempted.  offsets ok. */
+  } else {  
+    /* WEP decode successful! Lie about offsets as we're using a child skb */
+    reported_len -= hdr_len;
+    len -= hdr_len;
+    hdr_len = 0;
+  }
+
   /*
    * Do defragmentation if "wlan_defragment" is true, and we have more
    * fragments or this isn't the first fragment.
@@ -1589,7 +1685,7 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
      * whatever reassembly is in progress, if any, and see
      * if it's done.
      */
-    fd_head = fragment_add_seq_check(tvb, hdr_len, pinfo, seq_number,
+    fd_head = fragment_add_seq_check(next_tvb, hdr_len, pinfo, seq_number,
                                     wlan_fragment_table,
                                     wlan_reassembled_table,
                                     frag_number,
@@ -1619,7 +1715,7 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
         * Not fragmented, really.
         * Show it as a regular frame.
         */
-       next_tvb = tvb_new_subset (tvb, hdr_len, len, reported_len);
+       next_tvb = tvb_new_subset (next_tvb, hdr_len, len, reported_len);
       }
 
       /* It's not fragmented. */
@@ -1640,7 +1736,7 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
       /* First fragment, or not fragmented.  Dissect what we have here. */
 
       /* Get a tvbuff for the payload. */
-      next_tvb = tvb_new_subset (tvb, hdr_len, len, reported_len);
+      next_tvb = tvb_new_subset (next_tvb, hdr_len, len, reported_len);
 
       /*
        * If this is the first fragment, but not the only fragment,
@@ -1661,100 +1757,8 @@ dissect_ieee80211_common (tvbuff_t * tvb, packet_info * pinfo,
     call_dissector(data_handle, next_tvb, pinfo, tree);
     pinfo->fragmented = save_fragmented;
     return;
-  }
-
-  /*
-   * For WEP-encrypted frames, dissect the WEP parameters and decrypt
-   * the data, if we have a matching key.  Otherwise display it as data.
-   *
-   * XXX - is WEP encrypting done *before* fragmentation or *after*
-   * fragmentation?  We're doing the WEP stuff here, after defragmenting,
-   * which is correct only if WEP encrypting is done *after* fragmentation.
-   */
-  if (IS_WEP(COOK_FLAGS(fcf))) {
-    gboolean can_decrypt = FALSE;
-    tvbuff_t *tmp_tvb;
-    proto_tree *wep_tree = NULL;
-
-    if (tree) {
-      proto_item *wep_fields;
-
-      wep_fields = proto_tree_add_text(tree, next_tvb, 0, 4,
-                                          "WEP parameters");
-
-      wep_tree = proto_item_add_subtree (wep_fields, ett_wep_parameters);
-      proto_tree_add_item (wep_tree, hf_wep_iv, next_tvb, 0, 3, TRUE);
-
-      proto_tree_add_uint (wep_tree, hf_wep_key, next_tvb, 3, 1,
-                          COOK_WEP_KEY (tvb_get_guint8 (next_tvb, 3)));
-    }
-
-    len = tvb_length_remaining(next_tvb, 4);
-    reported_len = tvb_reported_length_remaining(next_tvb, 4);
-    if (len == -1 || reported_len == -1) {
-      /* We don't have anything beyond the IV. */
-      return;
-    }
-
-    /*
-     * Well, this packet should, in theory, have an ICV.
-     * Do we have the entire packet, and does it have enough data for
-     * the ICV?
-     */
-    if (reported_len < 4) {
-      /*
-       * The packet is claimed not to even have enough data for a
-       * 4-byte ICV.
-       * Pretend it doesn't have an ICV.
-       */
-      ;
-    } else if (len < reported_len) {
-      /*
-       * The packet is claimed to have enough data for a 4-byte ICV,
-       * but we didn't capture all of the packet.
-       * Slice off the 4-byte ICV from the reported length, and trim
-       * the captured length so it's no more than the reported length;
-       * that will slice off what of the ICV, if any, is in the
-       * captured length.
-       *
-       */
-      reported_len -= 4;
-      if (len > reported_len)
-       len = reported_len;
-    } else {
-      /*
-       * We have the entire packet, and it includes a 4-byte ICV.
-       * Slice it off, and put it into the tree.
-       *
-       * We only support decrypting if we have the the ICV.
-       *
-       * XXX - the ICV is encrypted; we're putting the encrypted
-       * value, not the decrypted value, into the tree.
-       */
-      len -= 4;
-      reported_len -= 4;
-      if (tree)
-       proto_tree_add_item (wep_tree, hf_wep_icv, next_tvb, 4 + len, 4,
-                            FALSE);
-      can_decrypt = TRUE;
-    }
-
-    if (!can_decrypt || (tmp_tvb = try_decrypt_wep(next_tvb)) == NULL) {
-      /* WEP decode impossible or failed, treat payload as raw data. */
-      tmp_tvb = tvb_new_subset(next_tvb, 4, len, reported_len);
-
-      call_dissector(data_handle, tmp_tvb, pinfo, tree);
-      return; 
-    } else {
-      add_new_data_source(pinfo, tmp_tvb, "Decrypted WEP data");
-       /*
-         if (check_col(pinfo->cinfo, COL_INFO))
-         col_set_str(pinfo->cinfo, COL_INFO, "Decrypted WEP data");
-       */
-    }
-    next_tvb = tmp_tvb;
-  }
-
+  }  
+  
   switch (COOK_FRAME_TYPE (fcf))
     {
 
@@ -2405,11 +2409,10 @@ static const guint32 wep_crc32_table[256] = {
         0x2d02ef8dL
 };
 
-static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb) {
+static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb, guint32 offset, guint32 len) {
   guint8 *tmp = NULL;
   int i;
   tvbuff_t *decr_tvb = NULL;
-  guint len = tvb_length(tvb);
 
   if (num_wepkeys < 1)
     return NULL;
@@ -2425,7 +2428,7 @@ static tvbuff_t *try_decrypt_wep(tvbuff_t *tvb) {
 #if 0
     printf("trying %d\n", i);
 #endif
-    tvb_memcpy(tvb, tmp, 0, len);
+    tvb_memcpy(tvb, tmp, offset, len);
     if (wep_decrypt(tmp, len, i) == 0) {
 
       /* decrypt successful, let's set up a new data tvb. */
@@ -2587,7 +2590,7 @@ static void init_wepkeys(void) {
 #endif
 
       wep_keys[i] = malloc(32 * sizeof(guint8));
-      bzero(wep_keys[i], 32 * sizeof(guint8));
+      memset(wep_keys[i], 0, 32 * sizeof(guint8));
       tmp3 = wep_keys[i];
       while ((tmp != NULL) && (*tmp != 0)) {
        tmp3[j] = strtoul(tmp, &tmp2, 16) & 0xff;