]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
decode: Improved handling of ICMPv4 messages
authorJeff Lucovsky <jeff@lucovsky.org>
Wed, 4 Nov 2020 13:34:51 +0000 (08:34 -0500)
committerVictor Julien <victor@inliniac.net>
Mon, 16 Nov 2020 13:23:59 +0000 (14:23 +0100)
This commit improves handling of ICMPv4 messages, especially those with
variable sized headers.

This commit also adds a header length variable for use by the new
sticky buffer for the header.

src/decode-icmpv4.c
src/decode-icmpv4.h

index e8748cac6f692c8ef119969fe723ae7ba78aa57f..90d67bab40e936280d6d60e72a797d400f51322e 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2010 Open Information Security Foundation
+/* Copyright (C) 2007-2020 Open Information Security Foundation
  *
  * You can copy, redistribute or modify this Program under the terms of
  * the GNU General Public License version 2 as published by the Free
@@ -168,8 +168,6 @@ int DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t
     p->proto = IPPROTO_ICMP;
     p->icmp_s.type = p->icmpv4h->type;
     p->icmp_s.code = p->icmpv4h->code;
-    p->payload = (uint8_t *)pkt + ICMPV4_HEADER_LEN;
-    p->payload_len = len - ICMPV4_HEADER_LEN;
 
     int ctype = ICMPv4GetCounterpart(p->icmp_s.type);
     if (ctype != -1) {
@@ -177,6 +175,7 @@ int DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t
     }
 
     ICMPV4ExtHdr* icmp4eh = (ICMPV4ExtHdr*) p->icmpv4h;
+    p->icmpv4vars.hlen = ICMPV4_HEADER_LEN;
 
     switch (p->icmpv4h->type)
     {
@@ -270,6 +269,12 @@ int DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t
             if (p->icmpv4h->code!=0) {
                 ENGINE_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
             }
+
+            if (len < (sizeof(ICMPV4Timestamp) + ICMPV4_HEADER_LEN)) {
+                ENGINE_SET_EVENT(p, ICMPV4_IPV4_TRUNC_PKT);
+            } else {
+                p->icmpv4vars.hlen += sizeof(ICMPV4Timestamp);
+            }
             break;
 
         case ICMP_TIMESTAMPREPLY:
@@ -278,6 +283,12 @@ int DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t
             if (p->icmpv4h->code!=0) {
                 ENGINE_SET_EVENT(p,ICMPV4_UNKNOWN_CODE);
             }
+
+            if (len < (sizeof(ICMPV4Timestamp) + ICMPV4_HEADER_LEN)) {
+                ENGINE_SET_EVENT(p, ICMPV4_IPV4_TRUNC_PKT);
+            } else {
+                p->icmpv4vars.hlen += sizeof(ICMPV4Timestamp);
+            }
             break;
 
         case ICMP_INFO_REQUEST:
@@ -296,6 +307,18 @@ int DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t
             }
             break;
 
+        case ICMP_ROUTERADVERT: {
+            /* pkt points to beginning of icmp message */
+            ICMPV4RtrAdvert *icmpv4_router_advert = (ICMPV4RtrAdvert *)(pkt + sizeof(ICMPV4Hdr));
+            uint32_t advert_len = icmpv4_router_advert->naddr *
+                                  (icmpv4_router_advert->addr_sz * sizeof(uint32_t));
+            if (len < (advert_len + ICMPV4_HEADER_LEN)) {
+                ENGINE_SET_EVENT(p, ICMPV4_IPV4_TRUNC_PKT);
+            } else {
+                p->icmpv4vars.hlen += advert_len;
+            }
+        } break;
+
         case ICMP_ADDRESS:
             p->icmpv4vars.id=icmp4eh->id;
             p->icmpv4vars.seq=icmp4eh->seq;
@@ -317,6 +340,9 @@ int DecodeICMPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t
 
     }
 
+    p->payload = (uint8_t *)pkt + p->icmpv4vars.hlen;
+    p->payload_len = len - p->icmpv4vars.hlen;
+
     FlowSetupPacket(p);
     return TM_ECODE_OK;
 }
index 5f9946f0a3ec2b2f9d4b4f8667ea3308f413ea50..8d44c17875fe96998fd1547cd5a2136f45f68c48 100644 (file)
@@ -186,6 +186,9 @@ typedef struct ICMPV4Vars_
     uint16_t  id;
     uint16_t  seq;
 
+    /** Actual header length **/
+    uint32_t hlen;
+
     /** Pointers to the embedded packet headers */
     IPV4Hdr *emb_ipv4h;
     TCPHdr *emb_tcph;
@@ -203,6 +206,23 @@ typedef struct ICMPV4Vars_
     uint16_t emb_dport;
 } ICMPV4Vars;
 
+/* ICMPV4 Router Advertisement - fixed components */
+/* actual size determined by address count and size */
+typedef struct ICMPV4RtrAdvert_ {
+    /** Number of advertised addresses **/
+    uint8_t naddr;
+
+    /** Size of each advertised address **/
+    uint8_t addr_sz;
+} __attribute__((__packed__)) ICMPV4RtrAdvert;
+
+/* ICMPV4 TImestamp messages */
+typedef struct ICMPV4Timestamp_ {
+    uint32_t orig_ts;
+    uint32_t rx_ts;
+    uint32_t tx_ts;
+} __attribute__((__packed__)) ICMPV4Timestamp;
+
 #define CLEAR_ICMPV4_PACKET(p) do { \
     (p)->level4_comp_csum = -1;     \
     PACKET_CLEAR_L4VARS((p));       \
@@ -238,6 +258,8 @@ typedef struct ICMPV4Vars_
 #define ICMPV4_GET_EMB_UDP(p)      (p)->icmpv4vars.emb_udph
 /** macro for icmpv4 embedded "icmpv4h" header access */
 #define ICMPV4_GET_EMB_ICMPV4H(p)  (p)->icmpv4vars.emb_icmpv4h
+/** macro for icmpv4 header length */
+#define ICMPV4_GET_HLEN_ICMPV4H(p) (p)->icmpv4vars.hlen
 
 /** macro for checking if a ICMP DEST UNREACH packet is valid for use
  *  in other parts of the engine, such as the flow engine.