return 0;
}
+static void fpAddAlternatePatterns(SnortConfig* sc, PortGroup* pg,
+ OptTreeNode* otn, PatternMatchData* pmd, FastPatternConfig* fp)
+{
+ if ( fp->get_debug_print_fast_patterns() )
+ print_fp_info(s_group, otn, pmd, pmd->pattern_buf, pmd->pattern_size);
+
+ PMX* pmx = (PMX*)snort_calloc(sizeof(PMX));
+ pmx->rule_node.rnRuleData = otn;
+ pmx->pmd = pmd;
+
+ Mpse::PatternDescriptor desc(pmd->no_case, pmd->negated, pmd->literal, pmd->flags);
+ pg->mpse[pmd->pm_type]->add_pattern(sc, (uint8_t*)pmd->pattern_buf, pmd->pattern_size, desc,
+ pmx);
+}
+
static int fpAddPortGroupRule(
SnortConfig* sc, PortGroup* pg, OptTreeNode* otn, FastPatternConfig* fp, bool srvc)
{
- PatternMatchData* pmd = NULL;
+ PatternMatchVector pmv;
// skip builtin rules, continue for text and so rules
if ( !otn->sigInfo.text_rule )
return -1;
OptFpList* next = nullptr;
- pmd = get_fp_content(otn, next, srvc);
+ pmv = get_fp_content(otn, next, srvc);
- if ( pmd )
+ if ( !pmv.empty() )
{
- if (
- !pmd->relative && !pmd->negated && pmd->fp_only >= 0 &&
+ PatternMatchData* main_pmd = pmv.back();
+ pmv.pop_back();
+
+ if ( !main_pmd->relative && !main_pmd->negated && main_pmd->fp_only >= 0 &&
// FIXIT-L no_case consideration is mpse specific, delegate
- !pmd->offset && !pmd->depth && pmd->no_case )
+ !main_pmd->offset && !main_pmd->depth && main_pmd->no_case )
{
if ( !next || !next->ips_opt || !next->ips_opt->is_relative() )
- pmd->fp_only = 1;
+ main_pmd->fp_only = 1;
}
- if (fpFinishPortGroupRule(sc, pg, otn, pmd, fp) == 0)
+ if (fpFinishPortGroupRule(sc, pg, otn, main_pmd, fp) == 0)
{
- if (pmd->pattern_size > otn->longestPatternLen)
- otn->longestPatternLen = pmd->pattern_size;
+ if (main_pmd->pattern_size > otn->longestPatternLen)
+ otn->longestPatternLen = main_pmd->pattern_size;
+ for (auto p : pmv)
+ fpAddAlternatePatterns(sc, pg, otn, p, fp);
return 0;
}
pm_type_strings[pmd->pm_type], pattern_length,
txt.c_str(), hex.c_str(), opts.c_str());
}
-
// public methods
//--------------------------------------------------------------------------
-PatternMatchData* get_fp_content(OptTreeNode* otn, OptFpList*& next, bool srvc)
+PatternMatchVector get_fp_content(OptTreeNode* otn, OptFpList*& next, bool srvc)
{
CursorActionType curr_cat = CAT_SET_RAW;
FpSelector best;
bool content = false;
bool fp_only = true;
+ PatternMatchVector pmds;
for (OptFpList* ofl = otn->opt_func; ofl; ofl = ofl->next)
{
{
best = curr;
next = ofl->next;
+ pmds.clear();
+ // Add alternate pattern
+ PatternMatchData* alt_pmd = ofl->ips_opt->get_alternate_pattern();
+ if (alt_pmd)
+ pmds.push_back(alt_pmd);
+ // Add main pattern last
+ pmds.push_back(best.pmd);
}
}
{
ParseWarning(WARN_RULES, "file rule %u:%u does not have file_data fast pattern",
otn->sigInfo.generator, otn->sigInfo.id);
- return nullptr;
+ pmds.clear();
}
- if ( best.pmd )
- return best.pmd;
-
- if ( content )
+ if ( content && !best.pmd)
ParseWarning(WARN_RULES, "content based rule %u:%u has no eligible fast pattern",
otn->sigInfo.generator, otn->sigInfo.id);
- return nullptr;
+ return pmds;
}
//--------------------------------------------------------------------------
#define FP_UTILS_H
// fast pattern utilities
-
+#include <vector>
#include "framework/ips_option.h"
struct OptFpList;
int flp_trim(const char* p, int plen, const char** buff);
bool set_fp_content(OptTreeNode*);
-PatternMatchData* get_fp_content(OptTreeNode*, OptFpList*&, bool srvc);
+std::vector <PatternMatchData*> get_fp_content(OptTreeNode*, OptFpList*&, bool srvc);
#endif
#include <assert.h>
#include <ctype.h>
#include <sys/time.h>
+#include <vector>
#include "detection/treenodes.h"
#include "framework/ips_option.h" // FIXIT-L not a good dependency
bool can_be_fp() const;
};
+typedef std::vector<PatternMatchData*> PatternMatchVector;
+
inline bool PatternMatchData::can_be_fp() const
{
if ( !pattern_buf || !pattern_size )
virtual struct PatternMatchData* get_pattern(int /*proto*/, RuleDirection = RULE_WO_DIR)
{ return nullptr; }
+ virtual struct PatternMatchData* get_alternate_pattern()
+ { return nullptr; }
+
static int eval(void* v, Cursor& c, Packet* p)
{
IpsOption* opt = (IpsOption*)v;
IpsOption(s_name), version(iface_version), any_frag(iface_any_frag), uuid(iface_uuid)
{
memset(&pmd, 0, sizeof(pmd));
+ memset(&alt_pmd, 0, sizeof(alt_pmd));
}
uint32_t hash() const override;
bool operator==(const IpsOption&) const override;
int eval(Cursor&, Packet*) override;
PatternMatchData* get_pattern(int proto, RuleDirection direction) override;
+ PatternMatchData* get_alternate_pattern() override;
~Dce2IfaceOption();
private:
const bool any_frag;
const Uuid uuid;
PatternMatchData pmd;
+ PatternMatchData alt_pmd;
};
Dce2IfaceOption::~Dce2IfaceOption()
{
snort_free((char*)pmd.pattern_buf);
}
+ if ( alt_pmd.pattern_buf)
+ {
+ snort_free((char*)alt_pmd.pattern_buf);
+ }
+}
+
+static char* make_pattern_buffer( const Uuid &uuid, DceRpcBoFlag type )
+{
+ int index = 0;
+ char* pattern_buf = (char*)snort_alloc(sizeof(Uuid));
+
+ uint32_t time32 = DceRpcNtohl(&uuid.time_low, type);
+ memcpy(&pattern_buf[index], &time32, sizeof(uint32_t));
+ index += sizeof(uint32_t);
+
+ uint16_t time16 = DceRpcNtohs(&uuid.time_mid, type);
+ memcpy(&pattern_buf[index], &time16, sizeof(uint16_t));
+ index += sizeof(uint16_t);
+
+ time16 = DceRpcNtohs(&uuid.time_high_and_version, type);
+ memcpy(&pattern_buf[index], &time16, sizeof(uint16_t));
+ index += sizeof(uint16_t);
+
+ pattern_buf[index] = uuid.clock_seq_and_reserved;
+ index += sizeof(uint8_t);
+
+ pattern_buf[index] = uuid.clock_seq_low;
+ index += sizeof(uint8_t);
+
+ memcpy(&pattern_buf[index], uuid.node, 6);
+
+ return pattern_buf;
}
PatternMatchData* Dce2IfaceOption::get_pattern(int proto, RuleDirection direction)
}
return &pmd;
}
- // FIXIT-L add udp fast pattern
+ else if (proto == SNORT_PROTO_UDP)
+ {
+ pmd.pattern_buf = make_pattern_buffer( uuid, DCERPC_BO_FLAG__LITTLE_ENDIAN );
+ pmd.pattern_size = sizeof(Uuid);
+ alt_pmd.pattern_buf = make_pattern_buffer( uuid, DCERPC_BO_FLAG__BIG_ENDIAN );
+ alt_pmd.pattern_size = sizeof(Uuid);
+
+ return &pmd;
+ }
+
+ return nullptr;
+}
+
+PatternMatchData* Dce2IfaceOption::get_alternate_pattern()
+{
+ if (alt_pmd.pattern_buf)
+ {
+ return &alt_pmd;
+ }
return nullptr;
}