]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
finalizing maximum IP and IP6 extension support
authorJosh <jrosenba@cisco.com>
Tue, 18 Nov 2014 23:43:34 +0000 (17:43 -0600)
committerJosh <jrosenba@cisco.com>
Tue, 18 Nov 2014 23:43:34 +0000 (17:43 -0600)
17 files changed:
src/codecs/ip/cd_auth.cc
src/codecs/ip/cd_dst_opts.cc
src/codecs/ip/cd_esp.cc
src/codecs/ip/cd_frag.cc
src/codecs/ip/cd_hop_opts.cc
src/codecs/ip/cd_ipv4.cc
src/codecs/ip/cd_ipv6.cc
src/codecs/ip/cd_mobility.cc
src/codecs/ip/cd_no_next.cc
src/codecs/ip/cd_routing.cc
src/log/log_text.cc
src/main/modules.cc
src/main/snort_config.cc
src/main/snort_config.h
src/protocols/layer.cc
src/protocols/packet.h
src/protocols/packet_manager.cc

index 36aeaaf809766ce3e4228d5b5070d784526573c0..8bec3aa0d6389d1a9035f3eb55754d95715c33c2 100644 (file)
@@ -32,6 +32,7 @@
 #include "protocols/ipv6.h"
 #include "protocols/packet.h"
 #include "codecs/ip/ip_util.h"
+#include "main/snort.h"
 
 #define CD_AUTH_NAME "auth"
 #define CD_AUTH_HELP "support for IP authentication header"
@@ -119,9 +120,16 @@ bool AuthCodec::decode(const RawData& raw, CodecData& codec, DecodeData& snort)
     // must be called AFTER setting next_prot_id
     if (snort.ip_api.is_ip6())
     {
+        if ( snort_conf->hit_ip6_maxopts(codec.ip6_extension_count) )
+        {
+            codec_events::decoder_event(codec, DECODE_IP6_EXCESS_EXT_HDR);
+            return false;
+        }
+
         ip_util::CheckIPv6ExtensionOrder(codec, IPPROTO_ID_AUTH);
         codec.proto_bits |= PROTO_BIT__IP6_EXT;
         codec.ip6_csum_proto = ah->next;
+        codec.ip6_extension_count++;
     }
     return true;
 }
index b61f2a5f3cfe419f46b0fe287a9c57ab97e171ef..b4bd59baab227aab24c6bbbc6c29519bc026367d 100644 (file)
@@ -70,7 +70,7 @@ bool Ipv6DSTOptsCodec::decode(const RawData& raw, CodecData& codec, DecodeData&)
         return false;
     }
 
-    if ( codec.ip6_extension_count >= snort_conf->get_ip6_maxopts() )
+    if ( snort_conf->hit_ip6_maxopts(codec.ip6_extension_count) )
     {
         codec_events::decoder_event(codec, DECODE_IP6_EXCESS_EXT_HDR);
         return false;
index e43b2f25b4ce06ff2bab6b1ac28c8255104e954a..1d9fa6f2fe81b86f84f185f67e0dd5274a0f27f0 100644 (file)
@@ -144,9 +144,17 @@ bool EspCodec::decode(const RawData& raw, CodecData& codec, DecodeData& snort)
     // must be called AFTER setting next_prot_id
     if (snort.ip_api.is_ip6())
     {
+        if ( snort_conf->hit_ip6_maxopts(codec.ip6_extension_count) )
+        {
+            codec_events::decoder_event(codec, DECODE_IP6_EXCESS_EXT_HDR);
+            return false;
+        }
+
+
         ip_util::CheckIPv6ExtensionOrder(codec, IPPROTO_ID_ESP);
         codec.proto_bits |= PROTO_BIT__IP6_EXT;
         codec.ip6_csum_proto = codec.next_prot_id;
+        codec.ip6_extension_count++;
     }
 
 
index 3f227f00bb838ade409ad70590339552bf97b3b4..f8eeae17fb170afb2705a9b0093f3e9366a2f431 100644 (file)
@@ -71,7 +71,7 @@ bool Ipv6FragCodec::decode(const RawData& raw, CodecData& codec, DecodeData& sno
         return false;
     }
 
-    if ( codec.ip6_extension_count >= snort_conf->get_ip6_maxopts() )
+    if ( snort_conf->hit_ip6_maxopts(codec.ip6_extension_count) )
     {
         codec_events::decoder_event(codec, DECODE_IP6_EXCESS_EXT_HDR);
         return false;
index 7b77cbc4f4adbbff96e1cbed6cf45ece0a874e38..6edc096c17d5066bd2082945271bb12d8955f0b4 100644 (file)
@@ -77,7 +77,7 @@ bool Ipv6HopOptsCodec::decode(const RawData& raw, CodecData& codec, DecodeData&)
         return false;
     }
 
-    if ( codec.ip6_extension_count >= snort_conf->get_ip6_maxopts() )
+    if ( snort_conf->hit_ip6_maxopts(codec.ip6_extension_count) )
     {
         codec_events::decoder_event(codec, DECODE_IP6_EXCESS_EXT_HDR);
         return false;
index 5603c4ebca5932c20efd65086eadd8817a68f940..c21c86e43fa06600ba812098db3a2c5ec667284e 100644 (file)
@@ -172,8 +172,11 @@ bool Ipv4Codec::decode(const RawData& raw, CodecData& codec, DecodeData& snort)
     }
 
 
-    if ( codec.ip_layer_cnt == snort_conf->get_ip_maxlayers() )
+    if ( snort_conf->hit_ip_maxlayers(codec.ip_layer_cnt) )
+    {
         codec_events::decoder_event(codec, DECODE_IP_MULTIPLE_ENCAPSULATION);
+        return false;
+    }
 
     ++codec.ip_layer_cnt;
     /* lay the IP struct over the raw data */
index c63130f06b7ff6b21c5e87be81a4fc0d4a73653f..ed1f09b261d5b7118676337e809462172b623050 100644 (file)
@@ -152,8 +152,11 @@ bool Ipv6Codec::decode(const RawData& raw, CodecData& codec, DecodeData& snort)
             goto decodeipv6_fail;
         }
 
-        if ( codec.ip_layer_cnt == snort_conf->get_ip_maxlayers() )
+        if ( snort_conf->hit_ip_maxlayers(codec.ip_layer_cnt) )
+        {
             codec_events::decoder_event(codec, DECODE_IP_MULTIPLE_ENCAPSULATION);
+            goto decodeipv6_fail;
+        }
 
         codec.ip_layer_cnt++;
         const uint32_t payload_len = ntohs(ip6h->ip6_payload_len) + ip::IP6_HEADER_LEN;
index 2c90d2e61be20449a1a2e444d1ab4f99b438ccf9..8fdb0a144370f3be88d966b3a46928625c3e150d 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "framework/codec.h"
 #include "codecs/codec_events.h"
+#include "main/snort.h"
 
 // yes, macros are necessary. The API and class constructor require different strings.
 #define CD_MOBILE_NAME "mobility"
@@ -55,8 +56,15 @@ void MobilityCodec::get_protocol_ids(std::vector<uint16_t>& v)
 
 bool MobilityCodec::decode(const RawData&, CodecData& codec, DecodeData&)
 {
+    if ( snort_conf->hit_ip6_maxopts(codec.ip6_extension_count) )
+    {
+        codec_events::decoder_event(codec, DECODE_IP6_EXCESS_EXT_HDR);
+        return false;
+    }
+
     codec_events::decoder_event(codec, DECODE_IP_BAD_PROTO);
     codec.proto_bits |= PROTO_BIT__IP6_EXT; // check for any IP related rules
+    codec.ip6_extension_count++;
     return true;
 }
 
index 87412b8e579a5c1fc26682de88491e4c14fbcdfa..15544f50b195bec2c946f2e11f97dc33954c1690 100644 (file)
@@ -60,11 +60,18 @@ bool Ipv6NoNextCodec::decode(const RawData& raw, CodecData& codec, DecodeData&)
     if (raw.len < ip::MIN_EXT_LEN)
         return false;
 
+    if ( snort_conf->hit_ip6_maxopts(codec.ip6_extension_count) )
+    {
+        codec_events::decoder_event(codec, DECODE_IP6_EXCESS_EXT_HDR);
+        return false;
+    }
+
     // The size of this packets data should be zero.  So, set this layer's
     // length and the packet's remaining length to the same number.
     const_cast<uint32_t&>(raw.len) = ip::MIN_EXT_LEN;
     codec.lyr_len = ip::MIN_EXT_LEN;
     codec.proto_bits |= PROTO_BIT__IP6_EXT; // check for any IP related rules
+    codec.ip6_extension_count++;
     return true;
 }
 
index 604d47cb8dbbce6ef5fcf7385ec4f504e8bfb8fe..0d0dfe99592b7aa10b5a83b45f0663bb1771f789 100644 (file)
@@ -89,7 +89,7 @@ bool Ipv6RoutingCodec::decode(const RawData& raw, CodecData& codec, DecodeData&)
         return false;
     }
 
-    if ( codec.ip6_extension_count >= snort_conf->get_ip6_maxopts())
+    if ( snort_conf->hit_ip6_maxopts(codec.ip6_extension_count) )
     {
         codec_events::decoder_event(codec, DECODE_IP6_EXCESS_EXT_HDR);
         return false;
index 06c325cfd2e77398add62f76c76ad47426032c37..3c8fba7da5415b9d80cd02fa293947a0ed79175c 100644 (file)
@@ -1845,8 +1845,8 @@ void LogIPPkt(TextLog* log, Packet * p)
     if (ScOutputAppData() && !ScVerboseByteDump())
     {
 #ifdef REG_TEST
-        const uint8_t* tmp_data;
-        uint16_t tmp_dsize;
+        const uint8_t* tmp_data = 0;
+        uint16_t tmp_dsize = 0;
 
         if ( p->proto_bits & PROTO_BIT__ICMP_EMBED )
         {
index 46a0c562ef0ba6760fa7f479824e1d6ad080a0be..2dca620492245a42adc71a7f3cd71f585b815e46 100644 (file)
@@ -1032,13 +1032,13 @@ static const Parameter network_params[] =
     { "layers", Parameter::PT_INT, "3:255", "40",
       "The maximum number of protocols that Snort can correctly decode" },
 
-    { "max_ip6_extensions", Parameter::PT_INT, "1:255", "8",
-      "The number of IP6 options following an IPv6 layer Snort must see "
-      "before triggering 116:456" },
+    { "max_ip6_extensions", Parameter::PT_INT, "0:255", "0",
+      "The number of IP6 options Snort will process for a given IPv6 layer. "
+      "If this limit is hit, rule 116:456 may fire.  0 = unlimited" },
 
-    { "max_ip_layers", Parameter::PT_INT, "1:255", "2",
-      "The number of IPv4 and IPv6 layer Snort must see "
-      "before triggering 116:293" },
+    { "max_ip_layers", Parameter::PT_INT, "0:255", "0",
+      "The maximum number of IP layers Snort will process for a given packet "
+      "If this limit is hit, rule 116:293 may fire.  0 = unlimited" },
 
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
index f029787c5ed167b794ace75a3c1f79a7d444398e..6b2eda490e3d7057a911381ba019a9be04da8c0a 100644 (file)
@@ -178,8 +178,8 @@ SnortConfig * SnortConfNew(void)
     sc->pkt_snaplen = -1;
     sc->output_flags = 0;
     sc->num_layers = DEFAULT_LAYERMAX;
-    sc->max_ip6_extensions = DEFAULT_IP6_EXTMAX;
-    sc->max_ip_layers = DEFAULT_IPMAX;
+    sc->max_ip6_extensions = 0;
+    sc->max_ip_layers = 0;
 
     /*user_id and group_id should be initialized to -1 by default, because
      * chown() use this later, -1 means no change to user_id/group_id*/
@@ -432,9 +432,14 @@ SnortConfig* MergeSnortConfs(SnortConfig *cmd_line, SnortConfig *config_file)
     }
 
     /* FIXIT-L J do these belong in network policy? */
-    config_file->num_layers = cmd_line->num_layers;
-    config_file->max_ip6_extensions = cmd_line->max_ip6_extensions;
-    config_file->max_ip_layers = cmd_line->max_ip_layers;
+    if (cmd_line->num_layers != 0)
+        config_file->num_layers = cmd_line->num_layers;
+
+    if (cmd_line->max_ip6_extensions != 0)
+        config_file->max_ip6_extensions = cmd_line->max_ip6_extensions;
+
+    if (cmd_line->max_ip_layers != 0)
+        config_file->max_ip_layers = cmd_line->max_ip_layers;
 
     if (cmd_line->obfuscation_net.family != 0)
         memcpy(&config_file->obfuscation_net, &cmd_line->obfuscation_net, sizeof(sfip_t));
index 2c4e42401eededa95aa975af4dc32427336709f6..e7fb05ee6f84a14c4106d77bcd85020b3854fd00 100644 (file)
@@ -304,11 +304,13 @@ struct SnortConfig
     inline uint8_t get_num_layers() const
     { return num_layers; }
 
-    inline uint8_t get_ip6_maxopts() const
-    { return max_ip6_extensions; }
+    // curr_layer is the zero based ip6 options
+    inline bool hit_ip6_maxopts(uint8_t curr_opt) const
+    { return max_ip6_extensions && (curr_opt >= max_ip6_extensions); }
 
-    inline uint8_t get_ip_maxlayers() const
-    { return max_ip_layers; }
+    // curr_ip is the zero based ip layer
+    inline bool hit_ip_maxlayers(uint8_t curr_ip) const
+    { return max_ip_layers && (curr_ip >= max_ip_layers); }
 };
 
 SnortConfig* SnortConfNew(void);
index 0c1d4e10dbaf3c3abaaa185cc26801cd4c818821..024381749408f6036e2c998cb927d59440c26ed7 100644 (file)
@@ -31,7 +31,7 @@
 
 namespace layer
 {
-static THREAD_LOCAL const Packet* p;
+static THREAD_LOCAL const Packet* curr_pkt;
 
 static inline const uint8_t* find_outer_layer(const Layer* lyr,
                                 uint8_t num_layers,
@@ -81,8 +81,8 @@ static inline const uint8_t* find_inner_layer(const Layer* lyr,
     return nullptr;
 }
 
-void set_packet_pointer(const Packet* const curr_pkt)
-{ p = curr_pkt; }
+void set_packet_pointer(const Packet* const p)
+{ curr_pkt = p; }
 
 const uint8_t* get_inner_layer(const Packet* p, uint16_t proto)
 { return find_inner_layer(p->layers, p->num_layers, proto); }
@@ -147,7 +147,7 @@ const eth::EtherHdr* get_eth_layer(const Packet* const p)
 
 
 const ip::IP6Frag* get_inner_ip6_frag()
-{ return get_inner_ip6_frag(p); }
+{ return get_inner_ip6_frag(curr_pkt); }
 
 
 const ip::IP6Frag* get_inner_ip6_frag(const Packet* const pkt)
@@ -182,7 +182,7 @@ int get_inner_ip6_frag_index(const Packet* const pkt)
     // get_ip6h returns null if this is ipv4
     const ip::IP6Hdr* const ip6h = pkt->ptrs.ip_api.get_ip6h();
 
-    if (ip6h && p->is_fragment())
+    if (ip6h && curr_pkt->is_fragment())
     {
         const int max_layer = pkt->num_layers-1;
         const Layer* lyr = &(pkt->layers[max_layer]);
index 896522e5ff8bb7d2f975a63f60ae8613c624b66a..e4fb3ccd503431c40f4dd44c092f5db82e255360 100644 (file)
@@ -129,8 +129,6 @@ constexpr int32_t MAX_PORTS = 65536;
 constexpr uint16_t NUM_IP_PROTOS = 256;
 constexpr int16_t SFTARGET_UNKNOWN_PROTOCOL = -1;
 constexpr uint8_t TCP_OPTLENMAX = 40; /* (((2^4) - 1) * 4  - TCP_HEADER_LEN) */
-constexpr uint8_t DEFAULT_IPMAX = 2;
-constexpr uint8_t DEFAULT_IP6_EXTMAX = 8;
 constexpr uint8_t DEFAULT_LAYERMAX = 40;
 
 
index 6dd8ca8ba9e980dfdd8771b12185ca6876028d59..43ff8a324b79b2bb958ba2204103b8a257db88b9 100644 (file)
@@ -852,7 +852,7 @@ void PacketManager::log_protocols(TextLog* const text_log,
     if (num_layers != 0)
     {
         // Grinder is not in the layer array
-        Codec* const cd = CodecManager::s_protocols[CodecManager::grinder];
+        Codec* cd = CodecManager::s_protocols[CodecManager::grinder];
 
         TextLog_Print(text_log, "%-.6s(DLT):  ", cd->get_name());
         cd->log(text_log, lyr[0].start, p);
@@ -863,7 +863,7 @@ void PacketManager::log_protocols(TextLog* const text_log,
         {
             const uint16_t protocol = lyr[i].prot_id;
             const uint8_t codec_offset =  CodecManager::s_proto_map[protocol];
-            Codec* const cd = CodecManager::s_protocols[codec_offset];
+            cd = CodecManager::s_protocols[codec_offset];
 
 
             TextLog_NewLine(text_log);