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

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: Wed, 27 Oct 2004 15:02:00 +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
attempt decode of packets contained in NULL encypted ESP transport
packets. The authentication information is displayed, but not checked.

Patch breakdown
===============

epan/dissectors/packet-ipsec.c
------------------------------

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 fields, which in
  turn will specify the payload type. Decode is attempted based on
  this type and if this fails, the payload is displayed as raw data.


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


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

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.



Cheers
Mark Phillips


--
Mark S. Phillips        	mob. 07903 559147
mark.phillips@xxxxxxxxxx	Tel. 01279 441124

Old Nortel address (til 3rd Dec 2004)	ESN 742 2461
msp@xxxxxxxxxxxxxxxxxx        	Tel. +44 1279 402461
--- ethereal-2004-10-27/epan/dissectors/packet-ipsec.c.orig	2004-10-27 14:02:18.170499000 +0100
+++ ethereal-2004-10-27/epan/dissectors/packet-ipsec.c	2004-10-27 14:02:57.580806000 +0100
@@ -38,6 +38,8 @@
 
 /* Place AH payload in sub tree */
 static gboolean g_ah_payload_in_subtree = FALSE;
+/* Default ESP payload decode to off (only works if payload is NULL encrypted) */
+static gboolean g_esp_enable_null_encryption_decode_heuristic = FALSE;
 
 static int proto_ah = -1;
 static int hf_ah_spi = -1;
@@ -45,6 +47,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 +218,9 @@
      * (ie none)
      */
     if(tree) {
+        int len, pad, encapsulated_protocol;
+        int auth_decode_ok = 0;
+
 	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 +229,43 @@
 	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);
+           
+           if(dissector_try_port(ip_dissector_table, 
+                                  encapsulated_protocol,
+                                  tvb_new_subset(tvb, 
+                                                 sizeof(struct newesp), 
+                                                 -1, 
+                                                 len - sizeof(struct newesp) - 14 - pad),
+                                  pinfo,
+                                  esp_tree))
+           {
+              auth_decode_ok = 1;
+           }
+        }
+        
+        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 +340,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 +364,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 +386,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 attempts decode based on the 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-27/epan/dissectors/packet-udp.c.orig	2004-09-29 01:52:45.000000000 +0100
+++ ethereal-2004-10-27/epan/dissectors/packet-udp.c	2004-10-27 14:02:57.580844000 +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);