#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"
// 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;
}
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;
// 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++;
}
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;
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;
}
- 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 */
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;
#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"
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;
}
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;
}
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;
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 )
{
{ "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 }
};
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*/
}
/* 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));
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);
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,
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); }
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)
// 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]);
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;
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);
{
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);