From: Josh Date: Tue, 18 Nov 2014 23:43:34 +0000 (-0600) Subject: finalizing maximum IP and IP6 extension support X-Git-Tag: 3.0.0-233~1196^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5f46fef8f05938247fd1a5917f4075ba5cd39718;p=thirdparty%2Fsnort3.git finalizing maximum IP and IP6 extension support --- diff --git a/src/codecs/ip/cd_auth.cc b/src/codecs/ip/cd_auth.cc index 36aeaaf80..8bec3aa0d 100644 --- a/src/codecs/ip/cd_auth.cc +++ b/src/codecs/ip/cd_auth.cc @@ -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; } diff --git a/src/codecs/ip/cd_dst_opts.cc b/src/codecs/ip/cd_dst_opts.cc index b61f2a5f3..b4bd59baa 100644 --- a/src/codecs/ip/cd_dst_opts.cc +++ b/src/codecs/ip/cd_dst_opts.cc @@ -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; diff --git a/src/codecs/ip/cd_esp.cc b/src/codecs/ip/cd_esp.cc index e43b2f25b..1d9fa6f2f 100644 --- a/src/codecs/ip/cd_esp.cc +++ b/src/codecs/ip/cd_esp.cc @@ -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++; } diff --git a/src/codecs/ip/cd_frag.cc b/src/codecs/ip/cd_frag.cc index 3f227f00b..f8eeae17f 100644 --- a/src/codecs/ip/cd_frag.cc +++ b/src/codecs/ip/cd_frag.cc @@ -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; diff --git a/src/codecs/ip/cd_hop_opts.cc b/src/codecs/ip/cd_hop_opts.cc index 7b77cbc4f..6edc096c1 100644 --- a/src/codecs/ip/cd_hop_opts.cc +++ b/src/codecs/ip/cd_hop_opts.cc @@ -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; diff --git a/src/codecs/ip/cd_ipv4.cc b/src/codecs/ip/cd_ipv4.cc index 5603c4ebc..c21c86e43 100644 --- a/src/codecs/ip/cd_ipv4.cc +++ b/src/codecs/ip/cd_ipv4.cc @@ -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 */ diff --git a/src/codecs/ip/cd_ipv6.cc b/src/codecs/ip/cd_ipv6.cc index c63130f06..ed1f09b26 100644 --- a/src/codecs/ip/cd_ipv6.cc +++ b/src/codecs/ip/cd_ipv6.cc @@ -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; diff --git a/src/codecs/ip/cd_mobility.cc b/src/codecs/ip/cd_mobility.cc index 2c90d2e61..8fdb0a144 100644 --- a/src/codecs/ip/cd_mobility.cc +++ b/src/codecs/ip/cd_mobility.cc @@ -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& 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; } diff --git a/src/codecs/ip/cd_no_next.cc b/src/codecs/ip/cd_no_next.cc index 87412b8e5..15544f50b 100644 --- a/src/codecs/ip/cd_no_next.cc +++ b/src/codecs/ip/cd_no_next.cc @@ -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(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; } diff --git a/src/codecs/ip/cd_routing.cc b/src/codecs/ip/cd_routing.cc index 604d47cb8..0d0dfe995 100644 --- a/src/codecs/ip/cd_routing.cc +++ b/src/codecs/ip/cd_routing.cc @@ -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; diff --git a/src/log/log_text.cc b/src/log/log_text.cc index 06c325cfd..3c8fba7da 100644 --- a/src/log/log_text.cc +++ b/src/log/log_text.cc @@ -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 ) { diff --git a/src/main/modules.cc b/src/main/modules.cc index 46a0c562e..2dca62049 100644 --- a/src/main/modules.cc +++ b/src/main/modules.cc @@ -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 } }; diff --git a/src/main/snort_config.cc b/src/main/snort_config.cc index f029787c5..6b2eda490 100644 --- a/src/main/snort_config.cc +++ b/src/main/snort_config.cc @@ -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)); diff --git a/src/main/snort_config.h b/src/main/snort_config.h index 2c4e42401..e7fb05ee6 100644 --- a/src/main/snort_config.h +++ b/src/main/snort_config.h @@ -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); diff --git a/src/protocols/layer.cc b/src/protocols/layer.cc index 0c1d4e10d..024381749 100644 --- a/src/protocols/layer.cc +++ b/src/protocols/layer.cc @@ -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]); diff --git a/src/protocols/packet.h b/src/protocols/packet.h index 896522e5f..e4fb3ccd5 100644 --- a/src/protocols/packet.h +++ b/src/protocols/packet.h @@ -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; diff --git a/src/protocols/packet_manager.cc b/src/protocols/packet_manager.cc index 6dd8ca8ba..43ff8a324 100644 --- a/src/protocols/packet_manager.cc +++ b/src/protocols/packet_manager.cc @@ -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);