#include "compound_protection.h" #include #include "rule_detection.h" #include "ips_entry.h" #include "ips_comp.h" #include "debug.h" using namespace std; using MatchType = IPSSignatureSubTypes::BaseSignature::MatchType; USE_DEBUG_FLAG(D_IPS); CompoundProtection::Impl::Impl(const string &_sig_name, SignaturesVector &&sig_vec, Operation oper) : sig_name(_sig_name), sub_signatures(move(sig_vec)), operation(oper), table(Singleton::Consume::by()) { for (const auto &sig : sub_signatures) { const auto &sub_sig_context = sig->getContext(); for (auto &new_context : sub_sig_context) { bool is_new_context = true; for (auto &old_context : contexts) { if (new_context == old_context) { is_new_context = false; break; } } if (is_new_context) contexts.push_back(new_context); } } } MatchType CompoundProtection::Impl::getMatch(const set &matched) const { switch (operation) { case Operation::OR: return getMatchOr(matched); case Operation::AND: return getMatchAnd(matched); case Operation::ORDERED_AND: return getMatchOrderedAnd(matched); } dbgAssert(false) << "Unknown compound operation: " << static_cast(operation); return MatchType::NO_MATCH; } set CompoundProtection::Impl::patternsInSignature() const { set res; for (auto &sig : sub_signatures) { const auto &sub_sig_patterns = sig->patternsInSignature(); for (auto &pat : sub_sig_patterns) { res.insert(pat); } } return res; } MatchType CompoundProtection::Impl::getMatchOr(const set &matched) const { MatchType res = MatchType::NO_MATCH; for (auto &sig : sub_signatures) { switch (getSubMatch(sig, matched)) { case MatchType::NO_MATCH: break; case MatchType::CACHE_MATCH: { res = MatchType::CACHE_MATCH; break; } case MatchType::MATCH: return MatchType::MATCH; } } return res; } MatchType CompoundProtection::Impl::getMatchAnd(const set &matched) const { MatchType res = MatchType::CACHE_MATCH; for (auto &sig : sub_signatures) { switch (getSubMatch(sig, matched)) { case MatchType::NO_MATCH: { res = MatchType::NO_MATCH; break; } case MatchType::CACHE_MATCH: break; case MatchType::MATCH: { if (res == MatchType::CACHE_MATCH) res = MatchType::MATCH; break; } } } return res; } MatchType CompoundProtection::Impl::getMatchOrderedAnd(const set &matched) const { MatchType res = MatchType::CACHE_MATCH; for (auto &sig : sub_signatures) { switch (getSubMatch(sig, matched)) { case MatchType::NO_MATCH: return MatchType::NO_MATCH; case MatchType::CACHE_MATCH: break; case MatchType::MATCH: { res = MatchType::MATCH; break; } } } return res; } static bool isStringInVector(const Maybe &str, const vector &vec) { if (!str.ok()) return false; return find(vec.begin(), vec.end(), *str) != vec.end(); } MatchType CompoundProtection::Impl::getSubMatch( const std::shared_ptr &sub_sig, const set &matched ) const { if (isFlagSet(sub_sig->getSigId())) return MatchType::CACHE_MATCH; auto env = Singleton::Consume::by(); auto curr_ctx = env->get(I_KeywordsRule::getKeywordsRuleTag()); if (!isStringInVector(curr_ctx, sub_sig->getContext())) return MatchType::NO_MATCH; auto res = sub_sig->getMatch(matched); if (res != MatchType::NO_MATCH) setFlag(sub_sig->getSigId()); return res; } bool CompoundProtection::Impl::isFlagSet(const std::string &id) const { if (!table->hasState()) { dbgWarning(D_IPS) << "No entry was found, limited compound functionality"; return false; } return table->getState().isFlagSet(id); } void CompoundProtection::Impl::setFlag(const std::string &id) const { if (!table->hasState()) { dbgWarning(D_IPS) << "No entry was found, limited compound functionality"; return; } table->getState().setFlag(id); } class OperandsReader { public: OperandsReader(const string &sig_name) : base_sig_name(sig_name) {} void load(cereal::JSONInputArchive &ar) { cereal::size_type cereal_size; ar(cereal::make_size_tag(cereal_size)); rules.resize(static_cast(cereal_size)); uint index = 0; for (auto &rule : rules) { stringstream ss; ss << base_sig_name << "##" << index; ++index; RuleDetection detection(ss.str()); ar(detection); rule = detection.getRule(); } } vector> && extrackRules() { return move(rules); } private: string base_sig_name; vector> rules; }; shared_ptr CompoundProtection::get(const string &sig_name, cereal::JSONInputArchive &ar) { string operation; OperandsReader operands(sig_name); ar( cereal::make_nvp("operation", operation), cereal::make_nvp("operands", operands) ); return make_shared(sig_name, operands.extrackRules(), getOperation(operation)); } CompoundProtection::Operation CompoundProtection::getOperation(const string &operation) { if (operation == "or") return Operation::OR; if (operation == "and") return Operation::AND; if (operation == "ordered_and") return Operation::ORDERED_AND; reportConfigurationError("Unknown compound operation: " + operation); return Operation::OR; }