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

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: Thu, 11 Nov 2004 16:19:40 +0000 (GMT)
Hi Guy,

I have updated the patch, as requested, to handle truncated packets (and rebased to 2004-11-11).

Is this ok? If so can you please submit it for me.

Kind Regards

Mark Phillips


On Sat, 30 Oct 2004, Guy Harris wrote:

Mark Phillips wrote:

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,

Note that "tvb_length_remaining(tvb, 0)" is equivalent to
"tvb_length()", and that "tvb_length()" returns the amount of *captured*

data in the tvbuff, which isn't necessarily the actual length of the
packet; if it's not, the calls that use "len - 14" and "len - 13" don't
necessarily fetch the data in the trailer.

Handling trailers correctly is a bit tricky, due to the possibility that

the captured data might have been cut short by a "snapshot length" or by

"slicing" or whatever the particular network analyzer that captured the
data calls it.

The right thing to do is probably to use "tvb_reported_length()" to get
the actual packet length on the wire, and to check whether the trailer
data is present, using, for example, "tvb_bytes_exist()".  If it's not
present, you'd have to skip the heuristic, otherwise it's safe to fetch
"pad" and "encapsulated_protocol" and use them.

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.

I've checked that in, with some other cleanups of the length processing.

_______________________________________________
Ethereal-dev mailing list
Ethereal-dev@xxxxxxxxxxxx
http://www.ethereal.com/mailman/listinfo/ethereal-dev



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

Old Nortel address (til Xmas 2004)	ESN 742 2461
msp@xxxxxxxxxxxxxxxxxx        	Tel. +44 1279 402461
--- ethereal-2004-11-11/epan/dissectors/packet-ipsec.c.orig	2004-09-29 01:52:45.000000000 +0100
+++ ethereal-2004-11-11/epan/dissectors/packet-ipsec.c	2004-11-11 14:22:08.363049000 +0000
@@ -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,60 @@
 	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)
+        {
+           /* Get length of whole ESP packet. */
+           len = tvb_reported_length(tvb);
+
+           /* Make sure the packet is not truncated before the fields
+            * we need to read to determine the encapsulated protocol */
+           if(tvb_bytes_exist(tvb, len - 14, 2))
+           {
+              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);
+           /* Make sure we have the auth trailer data */
+           if(tvb_bytes_exist(tvb, len - 12, 12))
+           {
+              proto_tree_add_text(esp_tree, tvb, len - 12, 12,
+                                  "Authentication Data");
+           }
+           else
+           {
+              /* Truncated so just display what we have */
+              proto_tree_add_text(esp_tree, tvb, len - 12, 12 - (len - tvb_length(tvb)),
+                                  "Authentication Data (truncated)");
+           }
+        }
+        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 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);
 }