Ethereal-dev: [Ethereal-dev] PATCH: ESP transport null encyption decode

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

From: Mark Phillips <msp@xxxxxxxxxxxxxxxxxx>
Date: Fri, 22 Oct 2004 13:44:46 +0100 (BST)
Hi,

The attached patch adds the, optional, ability to decode transport ESP packets which are using NULL encryption.

Please checkin or propose fixes!


Background
----------

It is normally hard to decode IP Security ESP protocol packets because they are encrypted (ie. when used to form a secure VPN tunnel into a corporate network).

BUT, there are applications where ESP is just used to authenticate the data with no encryption (aka. NULL encryption).

In particular the application we are developing uses transport mode ESP with NULL encyption and either SHA1 or MD5 authentication.

The proposed patch adds the (by default disabled), capability to decode TCP or UDP packets contained in NULL encypted ESP transport packets. The authentication information is displayed, but not checked.

Patch breakdown
---------------


epan/dissectors/packet-ip.c
epan/dissectors/packet-ip.h

Make dissect_icmp public so we can call it to decode any enacapsulated ICMP packets.

epan/dissectors/packet-tcp.c
epan/dissectors/packet-tcp.h

Make dissect_tcp public so we can call it to decode any enacapsulated
TCP packets.

epan/dissectors/packet-udp
epan/dissectors/packet-udp.c

Make dissect_udp public so we can call it to decode any enacapsulated
UDP packets.

Fix UDP length calculation in decode_udp_ports. The code did not correctly allow for the UDP header which means that if there is additional data AFTER the UDP (ie. the ESP authentication field), its length will be included in the length passed to the protocol contained within the UDP packet.

epan/dissectors/packet-ipsec.c

Include the ip/udp/tcp headers

Add/register g_esp_enable_null_encryption_decode_heuristic option (default FALSE).

Add/register new packet fields hf_esp_pad and hf_esp_protocol.

If g_esp_enable_null_encryption_decode_heuristic is true, attempts to decode the ESP packet contents:-

  The code assumes that if this is a transport ESP NULL encrypted
  packet it will contain a 12 byte (ie. SHA1 or MD5) authentication
  trailer, prefixed with the ESP pad and payload type field, which in
  turn will specify the payload as being ICMP/UDP/TCP. If a reasonable
  payload type is found the the payload is passed to the appropriate
  dissector. If not the payload is displayed as raw data.

If g_esp_enable_null_encryption_decode_heuristic is false (default),
will decode the packet in the same was as it used to be (ie. raw data).


Cheers
Mark Phillips

--
Mark S. Phillips        	mob. 07903 559147
mark.phillips@xxxxxxxxxx	Tel. 01279 441124
--- ethereal-2004-10-22/epan/dissectors/packet-ip.c.orig	2004-09-29 01:52:45.000000000 +0100
+++ ethereal-2004-10-22/epan/dissectors/packet-ip.c	2004-10-22 12:59:03.281893000 +0100
@@ -54,8 +54,6 @@
 
 static int ip_tap = -1;
 
-static void dissect_icmp(tvbuff_t *, packet_info *, proto_tree *);
-
 /* Decode the old IPv4 TOS field as the DiffServ DS Field */
 static gboolean g_ip_dscp_actif = TRUE;
 
@@ -1300,7 +1298,7 @@
  * RFC 1256 for router discovery messages.
  * RFC 2002 and 3012 for Mobile IP stuff.
  */
-static void
+void
 dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
   proto_tree *icmp_tree;
--- ethereal-2004-10-22/epan/dissectors/packet-ip.h.orig	2004-07-18 19:06:47.000000000 +0100
+++ ethereal-2004-10-22/epan/dissectors/packet-ip.h	2004-10-22 12:59:03.291887000 +0100
@@ -45,4 +45,6 @@
 /* Export the DSCP value-string table for other protocols */
 extern const value_string dscp_vals[];
 
+void dissect_icmp(tvbuff_t *, packet_info *, proto_tree *);
+
 #endif
--- ethereal-2004-10-22/epan/dissectors/packet-ipsec.c.orig	2004-09-29 01:52:45.000000000 +0100
+++ ethereal-2004-10-22/epan/dissectors/packet-ipsec.c	2004-10-22 13:22:32.421615000 +0100
@@ -35,9 +35,14 @@
 #include <epan/addr_resolv.h>
 #include <epan/ipproto.h>
 #include <epan/prefs.h>
+#include "packet-udp.h"
+#include "packet-tcp.h"
+#include "packet-ip.h"
 
 /* Place AH payload in sub tree */
 static gboolean g_ah_payload_in_subtree = FALSE;
+/* Assume ESP contains NULL encrypted data */
+static gboolean g_esp_enable_null_encryption_decode_heuristic = FALSE;
 
 static int proto_ah = -1;
 static int hf_ah_spi = -1;
@@ -45,6 +50,8 @@
 static int proto_esp = -1;
 static int hf_esp_spi = -1;
 static int hf_esp_sequence = -1;
+static int hf_esp_pad = -1;
+static int hf_esp_protocol = -1;
 static int proto_ipcomp = -1;
 static int hf_ipcomp_flags = -1;
 static int hf_ipcomp_cpi = -1;
@@ -214,6 +221,9 @@
      * (ie none)
      */
     if(tree) {
+        int len, pad, encapsulated_protocol;
+        int auth_decode_ok = 1;
+
 	ti = proto_tree_add_item(tree, proto_esp, tvb, 0, -1, FALSE);
 	esp_tree = proto_item_add_subtree(ti, ett_esp);
 	proto_tree_add_uint(esp_tree, hf_esp_spi, tvb,
@@ -222,9 +232,57 @@
 	proto_tree_add_uint(esp_tree, hf_esp_sequence, tvb,
 			    offsetof(struct newesp, esp_seq), 4,
 			    (guint32)g_ntohl(esp.esp_seq));
-	call_dissector(data_handle,
-	    tvb_new_subset(tvb, sizeof(struct newesp), -1, -1),
-	    pinfo, esp_tree);
+
+        if(g_esp_enable_null_encryption_decode_heuristic)
+        {
+           len = tvb_length_remaining(tvb, 0); /* Get length of whole ESP packet. */
+           pad = tvb_get_guint8(tvb, len - 14);
+           encapsulated_protocol = tvb_get_guint8(tvb, len - 13);
+           
+           switch(encapsulated_protocol)
+           {
+              case IP_PROTO_ICMP:
+                 dissect_icmp(tvb_new_subset(tvb, sizeof(struct newesp), -1, 
+                                             len - sizeof(struct newesp) - 14 - pad),
+                              pinfo, esp_tree);
+                 break;
+              case IP_PROTO_UDP:
+                 dissect_udp(tvb_new_subset(tvb, sizeof(struct newesp), -1, 
+                                            len - sizeof(struct newesp) - 14 - pad),
+                             pinfo, esp_tree);
+                 break;
+              case IP_PROTO_TCP:
+                 dissect_tcp(tvb_new_subset(tvb, sizeof(struct newesp), -1,
+                                            len - sizeof(struct newesp) - 14 - pad),
+                             pinfo, esp_tree);
+                 break;
+              default:
+                 auth_decode_ok = 0;
+                 break;
+           }
+        }
+        else
+        {
+           auth_decode_ok = 0;
+        }
+        
+        if(auth_decode_ok)
+        {
+           proto_tree_add_uint(esp_tree, hf_esp_pad, tvb,
+                               len - 14, 1,
+                               pad);
+           proto_tree_add_uint(esp_tree, hf_esp_protocol, tvb,
+                               len - 13, 1,
+                               encapsulated_protocol);
+           proto_tree_add_text(esp_tree, tvb, len - 12, 12,
+                               "Authentication Data");
+        }
+        else
+        {
+           call_dissector(data_handle,
+                          tvb_new_subset(tvb, sizeof(struct newesp), -1, -1),
+                          pinfo, esp_tree);
+        }
     }
 }
 
@@ -299,6 +357,12 @@
       	"", HFILL }},
     { &hf_esp_sequence,
       { "Sequence",     "esp.sequence",	FT_UINT32,	BASE_DEC, NULL, 0x0,
+      	"", HFILL }},
+    { &hf_esp_pad,
+      { "Pad Length",	"esp.pad",	FT_UINT8,	BASE_DEC, NULL, 0x0,
+      	"", HFILL }},
+    { &hf_esp_protocol,
+      { "Next Header",	"esp.protocol",	FT_UINT8,	BASE_HEX, NULL, 0x0,
       	"", HFILL }}
   };
 
@@ -317,6 +381,7 @@
   };
 
   module_t *ah_module;
+  module_t *esp_module;
 
   proto_ah = proto_register_protocol("Authentication Header", "AH", "ah");
   proto_register_field_array(proto_ah, hf_ah, array_length(hf_ah));
@@ -338,6 +403,12 @@
 "Whether the AH payload decode should be placed in a subtree",
 	    &g_ah_payload_in_subtree);
 
+  esp_module = prefs_register_protocol(proto_esp, NULL);
+  prefs_register_bool_preference(esp_module, "enable_null_encryption_decode_heuristic",
+	    "Attempt to detect/decode NULL encrypted ESP payloads",
+"Assumes a 12 byte auth (SHA1/MD5) and decodes as TCP/UDP/ICMP based on ethertype 13 bytes from packet end",
+	    &g_esp_enable_null_encryption_decode_heuristic);
+
   register_dissector("esp", dissect_esp, proto_esp);
   register_dissector("ah", dissect_ah, proto_ah);
 }
--- ethereal-2004-10-22/epan/dissectors/packet-tcp.c.orig	2004-10-11 09:12:34.000000000 +0100
+++ ethereal-2004-10-22/epan/dissectors/packet-tcp.c	2004-10-22 12:59:03.321899000 +0100
@@ -2533,7 +2533,7 @@
   }
 }
 
-static void
+void
 dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
   guint8  th_off_x2; /* combines th_off and th_x2 */
--- ethereal-2004-10-22/epan/dissectors/packet-tcp.h.orig	2004-07-18 19:06:47.000000000 +0100
+++ ethereal-2004-10-22/epan/dissectors/packet-tcp.h	2004-10-22 12:59:03.321936000 +0100
@@ -93,4 +93,6 @@
 				guint32 dport, proto_tree *tree,
 				proto_tree *tcp_tree);
 
+extern void dissect_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+
 #endif
--- ethereal-2004-10-22/epan/dissectors/packet-udp.c.orig	2004-09-29 01:52:45.000000000 +0100
+++ ethereal-2004-10-22/epan/dissectors/packet-udp.c	2004-10-22 12:59:03.321974000 +0100
@@ -85,10 +85,10 @@
     /* This is the length from the UDP header; the payload should be cut
        off at that length.
        XXX - what if it's *greater* than the reported length? */
-    if (uh_ulen < len)
-      len = uh_ulen;
-    if (uh_ulen < reported_len)
-      reported_len = uh_ulen;
+    if ((uh_ulen - offset) < len)
+      len = (uh_ulen - offset);
+    if ((uh_ulen - offset) < reported_len)
+      reported_len = (uh_ulen - offset);
   }
   next_tvb = tvb_new_subset(tvb, offset, len, reported_len);
 
@@ -145,7 +145,7 @@
 }
 
 
-static void
+void
 dissect_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
   proto_tree *udp_tree;
--- ethereal-2004-10-22/epan/dissectors/packet-udp.h.orig	2004-07-18 19:06:47.000000000 +0100
+++ ethereal-2004-10-22/epan/dissectors/packet-udp.h	2004-10-22 12:59:03.322011000 +0100
@@ -35,6 +35,7 @@
   address ip_dst;
 } e_udphdr;
 
+extern void dissect_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
 
 extern void decode_udp_ports(tvbuff_t *, int, packet_info *,
 	proto_tree *, int, int, int);