diff --git a/cmake/objects.cmake b/cmake/objects.cmake index b61e041ee..2f96b98cf 100644 --- a/cmake/objects.cmake +++ b/cmake/objects.cmake @@ -24,6 +24,7 @@ set(LIBDDWAF_SOURCE ${libddwaf_SOURCE_DIR}/src/generator/extract_schema.cpp ${libddwaf_SOURCE_DIR}/src/parser/common.cpp ${libddwaf_SOURCE_DIR}/src/parser/parser.cpp + ${libddwaf_SOURCE_DIR}/src/parser/parser_v1.cpp ${libddwaf_SOURCE_DIR}/src/parser/parser_v2.cpp ${libddwaf_SOURCE_DIR}/src/parser/rule_data_parser.cpp ${libddwaf_SOURCE_DIR}/src/condition/lfi_detector.cpp diff --git a/src/condition/matcher_proxy.cpp b/src/condition/matcher_proxy.cpp index 625797a91..80e654ced 100644 --- a/src/condition/matcher_proxy.cpp +++ b/src/condition/matcher_proxy.cpp @@ -126,7 +126,7 @@ const matcher::base *matcher_proxy::get_matcher( return nullptr; } -eval_result matcher_proxy::eval_impl(const argument_stack &stack, cache_type &cache, +eval_result matcher_proxy::eval(cache_type &cache, const object_store &store, const exclusion::object_set_ref &objects_excluded, const std::unordered_map> &dynamic_matchers, const object_limits &limits, ddwaf::timer &deadline) const @@ -136,43 +136,44 @@ eval_result matcher_proxy::eval_impl(const argument_stack &stack, cache_type &ca return {}; } - const auto &targets = stack.get(0); - if (cache.targets.size() != targets.size()) { - cache.targets.assign(targets.size(), nullptr); + if (cache.targets.size() != targets_.size()) { + cache.targets.assign(targets_.size(), nullptr); } - for (unsigned i = 0; i < targets.size(); ++i) { + for (unsigned i = 0; i < targets_.size(); ++i) { if (deadline.expired()) { throw ddwaf::timeout_exception(); } - const auto &target = targets[i]; - if (target.object == cache.targets[i]) { + const auto &target = targets_[i]; + auto [object, attr] = store.get_target(target.root); + if (object == nullptr || object == cache.targets[i]) { continue; } - if (!target.ephemeral) { - cache.targets[i] = target.object; + const bool ephemeral = (attr == object_store::attribute::ephemeral); + if (!ephemeral) { + cache.targets[i] = object; } std::optional optional_match; // TODO: iterators could be cached to avoid reinitialisation if (target.source == data_source::keys) { - object::key_iterator it(target.object, target.key_path, objects_excluded, limits); + object::key_iterator it(object, target.key_path, objects_excluded, limits); optional_match = eval_target(it, *matcher, target.transformers, limits, deadline); } else { - object::value_iterator it(target.object, target.key_path, objects_excluded, limits); + object::value_iterator it(object, target.key_path, objects_excluded, limits); optional_match = eval_target(it, *matcher, target.transformers, limits, deadline); } if (optional_match.has_value()) { - optional_match->address = target.address; - optional_match->ephemeral = target.ephemeral; + optional_match->address = target.name; + optional_match->ephemeral = ephemeral; DDWAF_TRACE( - "Target {} matched parameter value {}", target.address, optional_match->resolved); + "Target {} matched parameter value {}", target.name, optional_match->resolved); cache.match = std::move(optional_match); - return {true, target.ephemeral}; + return {true, ephemeral}; } } diff --git a/src/condition/matcher_proxy.hpp b/src/condition/matcher_proxy.hpp index ab760ad32..6c896cdcb 100644 --- a/src/condition/matcher_proxy.hpp +++ b/src/condition/matcher_proxy.hpp @@ -10,35 +10,48 @@ namespace ddwaf::condition { -class matcher_proxy : public base_impl { +class matcher_proxy : public base { public: matcher_proxy(std::unique_ptr &&matcher, std::string data_id, std::vector args) - : base_impl(std::move(args)), matcher_(std::move(matcher)), - data_id_(std::move(data_id)) - {} + : matcher_(std::move(matcher)), data_id_(std::move(data_id)) + { + if (args.size() > 1) { + throw std::invalid_argument("Matcher initialised with more than one argument"); + } -protected: - eval_result eval_impl(const argument_stack &stack, cache_type &cache, + if (args.empty()) { + throw std::invalid_argument("Matcher initialised without arguments"); + } + + targets_ = std::move(args[0].targets); + } + + eval_result eval(cache_type &cache, const object_store &store, const exclusion::object_set_ref &objects_excluded, const std::unordered_map> &dynamic_matchers, - const object_limits &limits, ddwaf::timer &deadline) const; + const object_limits &limits, ddwaf::timer &deadline) const override; - [[nodiscard]] const matcher::base *get_matcher( - const std::unordered_map> &dynamic_matchers) - const; + void get_addresses(std::unordered_map &addresses) const override + { + for (const auto &target : targets_) { addresses.emplace(target.root, target.name); } + } - static const std::vector &arguments_impl() + static const std::vector &arguments() { static std::vector args = { {"inputs", object_type::any, true, false}}; return args; - }; + } + +protected: + [[nodiscard]] const matcher::base *get_matcher( + const std::unordered_map> &dynamic_matchers) + const; std::unique_ptr matcher_; std::string data_id_; - - friend class base_impl; + std::vector targets_; }; } // namespace ddwaf::condition diff --git a/src/parser/parser.hpp b/src/parser/parser.hpp index e768bc49f..7c97c736b 100644 --- a/src/parser/parser.hpp +++ b/src/parser/parser.hpp @@ -22,6 +22,12 @@ using base_section_info = ddwaf::base_ruleset_info::base_section_info; namespace ddwaf::parser { unsigned parse_schema_version(parameter::map &ruleset); + +namespace v1 { +void parse( + parameter::map &ruleset, base_ruleset_info &info, ddwaf::ruleset &rs, object_limits limits); +} // namespace v1 + namespace v2 { rule_spec_container parse_rules(parameter::vector &rule_array, base_section_info &info, diff --git a/src/parser/parser_v1.cpp b/src/parser/parser_v1.cpp new file mode 100644 index 000000000..2156eca3b --- /dev/null +++ b/src/parser/parser_v1.cpp @@ -0,0 +1,193 @@ +// Unless explicitly stated otherwise all files in this repository are +// dual-licensed under the Apache-2.0 License or BSD-3-Clause License. +// +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2021 Datadog, Inc. + +#include +#include +#include +#include + +#include "condition/matcher_proxy.hpp" +#include "exception.hpp" +#include "log.hpp" +#include "matcher/is_sqli.hpp" +#include "matcher/is_xss.hpp" +#include "matcher/phrase_match.hpp" +#include "matcher/regex_match.hpp" +#include "parameter.hpp" +#include "parser/common.hpp" +#include "parser/parser.hpp" +#include "rule.hpp" +#include "ruleset.hpp" +#include "ruleset_info.hpp" + +namespace ddwaf::parser::v1 { + +namespace { + +std::shared_ptr parse_expression(parameter::vector &conditions_array, + const std::vector &transformers, ddwaf::object_limits limits) +{ + std::vector> conditions; + + for (const auto &cond_param : conditions_array) { + auto cond = static_cast(cond_param); + + auto matcher_name = at(cond, "operation"); + auto params = at(cond, "parameters"); + + parameter::map options; + std::unique_ptr matcher; + if (matcher_name == "phrase_match") { + auto list = at(params, "list"); + + std::vector patterns; + std::vector lengths; + + patterns.reserve(list.size()); + lengths.reserve(list.size()); + + for (auto &pattern : list) { + if (pattern.type != DDWAF_OBJ_STRING) { + throw ddwaf::parsing_error("phrase_match list item not a string"); + } + + patterns.push_back(pattern.stringValue); + lengths.push_back((uint32_t)pattern.nbEntries); + } + + matcher = std::make_unique(patterns, lengths); + } else if (matcher_name == "match_regex") { + auto regex = at(params, "regex"); + options = at(params, "options", options); + + auto case_sensitive = at(options, "case_sensitive", false); + auto min_length = at(options, "min_length", 0); + if (min_length < 0) { + throw ddwaf::parsing_error("min_length is a negative number"); + } + + matcher = std::make_unique(regex, min_length, case_sensitive); + } else if (matcher_name == "is_xss") { + matcher = std::make_unique(); + } else if (matcher_name == "is_sqli") { + matcher = std::make_unique(); + } else { + throw ddwaf::parsing_error("unknown matcher: " + std::string(matcher_name)); + } + + std::vector definitions; + definitions.emplace_back(); + condition::argument_definition &def = definitions.back(); + + auto inputs = at(params, "inputs"); + for (const auto &input_param : inputs) { + auto input = static_cast(input_param); + if (input.empty()) { + throw ddwaf::parsing_error("empty address"); + } + + std::string root; + std::vector key_path; + const size_t pos = input.find(':', 0); + if (pos == std::string::npos || pos + 1 >= input.size()) { + root = input; + } else { + root = input.substr(0, pos); + key_path.emplace_back(input.substr(pos + 1, input.size())); + } + + def.targets.emplace_back(condition::target_definition{root, get_target_index(root), + std::move(key_path), transformers, condition::data_source::values}); + } + + conditions.emplace_back(std::make_unique( + std::move(matcher), std::string{}, std::move(definitions))); + } + + return std::make_shared(std::move(conditions), limits); +} + +void parseRule(parameter::map &rule, base_section_info &info, + std::unordered_set &rule_ids, ddwaf::ruleset &rs, ddwaf::object_limits limits) +{ + auto id = at(rule, "id"); + if (rule_ids.find(id) != rule_ids.end()) { + DDWAF_WARN("duplicate rule {}", id); + info.add_failed(id, "duplicate rule"); + return; + } + + try { + std::vector rule_transformers; + auto transformers = at(rule, "transformers", parameter::vector()); + for (const auto &transformer_param : transformers) { + auto transformer = static_cast(transformer_param); + auto id = transformer_from_string(transformer); + if (!id.has_value()) { + throw ddwaf::parsing_error("invalid transformer" + std::string(transformer)); + } + rule_transformers.emplace_back(id.value()); + } + + auto conditions_array = at(rule, "conditions"); + auto expression = parse_expression(conditions_array, rule_transformers, limits); + + std::unordered_map tags; + for (auto &[key, value] : at(rule, "tags")) { + try { + tags.emplace(key, std::string(value)); + } catch (const bad_cast &e) { + throw invalid_type(std::string(key), e); + } + } + + if (tags.find("type") == tags.end()) { + throw ddwaf::parsing_error("missing key 'type'"); + } + + auto rule_ptr = std::make_shared( + std::string(id), at(rule, "name"), std::move(tags), std::move(expression)); + + rule_ids.emplace(rule_ptr->get_id()); + rs.insert_rule(rule_ptr); + info.add_loaded(rule_ptr->get_id()); + } catch (const std::exception &e) { + DDWAF_WARN("failed to parse rule '{}': {}", id, e.what()); + info.add_failed(id, e.what()); + } +} + +} // namespace + +void parse( + parameter::map &ruleset, base_ruleset_info &info, ddwaf::ruleset &rs, object_limits limits) +{ + auto rules_array = at(ruleset, "events"); + rs.rules.reserve(rules_array.size()); + + auto §ion = info.add_section("rules"); + + std::unordered_set rule_ids; + for (unsigned i = 0; i < rules_array.size(); ++i) { + const auto &rule_param = rules_array[i]; + try { + auto rule = static_cast(rule_param); + parseRule(rule, section, rule_ids, rs, limits); + } catch (const std::exception &e) { + DDWAF_WARN("{}", e.what()); + section.add_failed("index:" + to_string(i), e.what()); + } + } + + if (rs.rules.empty()) { + throw ddwaf::parsing_error("no valid rules found"); + } + + DDWAF_DEBUG("Loaded %zu rules out of %zu available in the ruleset", rs.rules.size(), + rules_array.size()); +} + +} // namespace ddwaf::parser::v1 diff --git a/src/waf.cpp b/src/waf.cpp index 912c38ea8..b907f3e23 100644 --- a/src/waf.cpp +++ b/src/waf.cpp @@ -23,6 +23,17 @@ waf::waf(ddwaf::parameter input, ddwaf::base_ruleset_info &info, ddwaf::object_l } } + // Prevent combining version 1 of the ruleset and the builder + if (version == 1) { + ddwaf::ruleset rs; + rs.free_fn = free_fn; + rs.event_obfuscator = event_obfuscator; + DDWAF_DEBUG("Parsing ruleset with schema version 1.x"); + parser::v1::parse(input_map, info, rs, limits); + ruleset_ = std::make_shared(std::move(rs)); + return; + } + if (version == 2) { DDWAF_DEBUG("Parsing ruleset with schema version 2.x"); builder_ = std::make_shared(limits, free_fn, std::move(event_obfuscator)); diff --git a/tests/collection_test.cpp b/tests/collection_test.cpp index d22f1f0d9..f91f73ff5 100644 --- a/tests/collection_test.cpp +++ b/tests/collection_test.cpp @@ -5,9 +5,11 @@ // Copyright 2021 Datadog, Inc. #include "collection.hpp" +#include "condition/matcher_proxy.hpp" #include "matcher/exact_match.hpp" #include "matcher/ip_match.hpp" #include "test.hpp" +#include "test_utils.hpp" using namespace ddwaf; using namespace std::literals; @@ -23,9 +25,11 @@ TYPED_TEST_SUITE(TestCollection, CollectionTypes); // Validate that a rule within the collection matches only once TYPED_TEST(TestCollection, SingleRuleMatch) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; @@ -72,9 +76,11 @@ TYPED_TEST(TestCollection, MultipleRuleCachedMatch) std::vector> rules; TypeParam rule_collection; { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "type"}, {"category", "category1"}}; @@ -86,9 +92,11 @@ TYPED_TEST(TestCollection, MultipleRuleCachedMatch) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category2"}}; @@ -137,9 +145,11 @@ TYPED_TEST(TestCollection, MultipleRuleFailAndMatch) std::vector> rules; TypeParam rule_collection; { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "type"}, {"category", "category1"}}; @@ -151,9 +161,11 @@ TYPED_TEST(TestCollection, MultipleRuleFailAndMatch) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category2"}}; @@ -199,12 +211,16 @@ TYPED_TEST(TestCollection, MultipleRuleFailAndMatch) // Validate that the rule cache is acted on TYPED_TEST(TestCollection, SingleRuleMultipleCalls) { - expression_builder builder(2); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(2); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); - builder.start_condition(std::vector{"admin"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; @@ -254,9 +270,11 @@ TEST(TestPriorityCollection, NoRegularMatchAfterPriorityMatch) collection regular; priority_collection priority; { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "type"}, {"category", "category1"}}; @@ -268,9 +286,11 @@ TEST(TestPriorityCollection, NoRegularMatchAfterPriorityMatch) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category2"}}; @@ -323,9 +343,11 @@ TEST(TestPriorityCollection, PriorityMatchAfterRegularMatch) collection regular; priority_collection priority; { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "type"}, {"category", "category1"}}; @@ -337,9 +359,11 @@ TEST(TestPriorityCollection, PriorityMatchAfterRegularMatch) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category2"}}; @@ -392,9 +416,11 @@ TEST(TestPriorityCollection, NoPriorityMatchAfterPriorityMatch) std::vector> rules; priority_collection priority; { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "type"}, {"category", "category1"}}; @@ -407,9 +433,11 @@ TEST(TestPriorityCollection, NoPriorityMatchAfterPriorityMatch) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category2"}}; @@ -461,9 +489,11 @@ TEST(TestPriorityCollection, NoPriorityMatchAfterEphemeralPriorityMatch) std::vector> rules; priority_collection priority; { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "type"}, {"category", "category1"}}; @@ -476,9 +506,11 @@ TEST(TestPriorityCollection, NoPriorityMatchAfterEphemeralPriorityMatch) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category2"}}; @@ -535,9 +567,11 @@ TEST(TestPriorityCollection, EphemeralPriorityMatchNoOtherMatches) std::vector> rules; priority_collection priority; { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "type"}, {"category", "category1"}}; @@ -550,9 +584,11 @@ TEST(TestPriorityCollection, EphemeralPriorityMatchNoOtherMatches) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category2"}}; diff --git a/tests/context_test.cpp b/tests/context_test.cpp index 0ac1cd12f..5c2738b00 100644 --- a/tests/context_test.cpp +++ b/tests/context_test.cpp @@ -12,6 +12,7 @@ #include "matcher/exact_match.hpp" #include "matcher/ip_match.hpp" #include "test.hpp" +#include "test_utils.hpp" #include @@ -105,9 +106,11 @@ class processor : public ddwaf::processor { TEST(TestContext, PreprocessorEval) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; @@ -136,9 +139,11 @@ TEST(TestContext, PreprocessorEval) TEST(TestContext, PostprocessorEval) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; @@ -167,9 +172,11 @@ TEST(TestContext, PostprocessorEval) TEST(TestContext, SkipRuleNoTargets) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; @@ -193,9 +200,11 @@ TEST(TestContext, SkipRuleNoTargets) TEST(TestContext, MatchTimeout) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; @@ -218,9 +227,11 @@ TEST(TestContext, MatchTimeout) TEST(TestContext, NoMatch) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; @@ -244,9 +255,11 @@ TEST(TestContext, NoMatch) TEST(TestContext, Match) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; @@ -272,9 +285,11 @@ TEST(TestContext, MatchMultipleRulesInCollectionSingleRun) { auto ruleset = std::make_shared(); { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "type"}, {"category", "category1"}}; @@ -285,9 +300,11 @@ TEST(TestContext, MatchMultipleRulesInCollectionSingleRun) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category2"}}; @@ -332,9 +349,11 @@ TEST(TestContext, MatchMultipleRulesWithPrioritySingleRun) { auto ruleset = std::make_shared(); { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "type"}, {"category", "category1"}}; @@ -345,9 +364,11 @@ TEST(TestContext, MatchMultipleRulesWithPrioritySingleRun) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category2"}}; @@ -403,9 +424,11 @@ TEST(TestContext, MatchMultipleRulesInCollectionDoubleRun) { auto ruleset = std::make_shared(); { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "type"}, {"category", "category1"}}; @@ -416,9 +439,11 @@ TEST(TestContext, MatchMultipleRulesInCollectionDoubleRun) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category2"}}; @@ -475,9 +500,11 @@ TEST(TestContext, MatchMultipleRulesWithPriorityDoubleRunPriorityLast) { auto ruleset = std::make_shared(); { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "type"}, {"category", "category1"}}; @@ -488,9 +515,11 @@ TEST(TestContext, MatchMultipleRulesWithPriorityDoubleRunPriorityLast) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category2"}}; @@ -568,9 +597,11 @@ TEST(TestContext, MatchMultipleRulesWithPriorityDoubleRunPriorityFirst) { auto ruleset = std::make_shared(); { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "type"}, {"category", "category1"}}; @@ -582,9 +613,11 @@ TEST(TestContext, MatchMultipleRulesWithPriorityDoubleRunPriorityFirst) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category2"}}; @@ -643,9 +676,11 @@ TEST(TestContext, MatchMultipleRulesWithPriorityUntilAllActionsMet) { auto ruleset = std::make_shared(); { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "type"}, {"category", "category1"}}; @@ -656,9 +691,11 @@ TEST(TestContext, MatchMultipleRulesWithPriorityUntilAllActionsMet) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category2"}}; @@ -734,9 +771,11 @@ TEST(TestContext, MatchMultipleCollectionsSingleRun) { auto ruleset = std::make_shared(); { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "type1"}, {"category", "category1"}}; @@ -747,9 +786,11 @@ TEST(TestContext, MatchMultipleCollectionsSingleRun) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type2"}, {"category", "category2"}}; @@ -777,9 +818,11 @@ TEST(TestContext, MatchMultiplePriorityCollectionsSingleRun) { auto ruleset = std::make_shared(); { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "type1"}, {"category", "category1"}}; @@ -791,9 +834,11 @@ TEST(TestContext, MatchMultiplePriorityCollectionsSingleRun) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type2"}, {"category", "category2"}}; @@ -822,9 +867,11 @@ TEST(TestContext, MatchMultipleCollectionsDoubleRun) { auto ruleset = std::make_shared(); { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "type1"}, {"category", "category1"}}; @@ -835,9 +882,11 @@ TEST(TestContext, MatchMultipleCollectionsDoubleRun) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type2"}, {"category", "category2"}}; @@ -877,9 +926,11 @@ TEST(TestContext, MatchMultiplePriorityCollectionsDoubleRun) { auto ruleset = std::make_shared(); { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "type1"}, {"category", "category1"}}; @@ -891,9 +942,11 @@ TEST(TestContext, MatchMultiplePriorityCollectionsDoubleRun) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type2"}, {"category", "category2"}}; @@ -938,9 +991,11 @@ TEST(TestContext, SkipRuleFilterNoTargets) std::shared_ptr rule; std::shared_ptr filter; { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category"}}; @@ -952,9 +1007,11 @@ TEST(TestContext, SkipRuleFilterNoTargets) // Generate filter { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); filter = std::make_shared( "1", builder.build(), std::set{rule.get()}); @@ -984,9 +1041,11 @@ TEST(TestContext, SkipRuleButNotRuleFilterNoTargets) std::shared_ptr rule; std::shared_ptr filter; { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category"}}; @@ -998,9 +1057,11 @@ TEST(TestContext, SkipRuleButNotRuleFilterNoTargets) // Generate filter { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); filter = std::make_shared( "1", builder.build(), std::set{rule.get()}); @@ -1029,9 +1090,11 @@ TEST(TestContext, RuleFilterWithCondition) // Generate rule std::shared_ptr rule; { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category"}}; @@ -1043,9 +1106,11 @@ TEST(TestContext, RuleFilterWithCondition) // Generate filter { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); auto filter = std::make_shared( "1", builder.build(), std::set{rule.get()}); @@ -1077,9 +1142,11 @@ TEST(TestContext, RuleFilterWithEphemeralConditionMatch) // Generate rule std::shared_ptr rule; { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category"}}; @@ -1091,9 +1158,11 @@ TEST(TestContext, RuleFilterWithEphemeralConditionMatch) // Generate filter { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); auto filter = std::make_shared( "1", builder.build(), std::set{rule.get()}); @@ -1134,9 +1203,11 @@ TEST(TestContext, OverlappingRuleFiltersEphemeralBypassPersistentMonitor) // Generate rule std::shared_ptr rule; { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category"}}; @@ -1148,9 +1219,11 @@ TEST(TestContext, OverlappingRuleFiltersEphemeralBypassPersistentMonitor) // Generate filter { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); auto filter = std::make_shared( "1", builder.build(), std::set{rule.get()}); @@ -1158,9 +1231,11 @@ TEST(TestContext, OverlappingRuleFiltersEphemeralBypassPersistentMonitor) } { - expression_builder builder(1); - builder.start_condition(std::vector{"unrouted"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.route"); + builder.end_condition(std::vector{"unrouted"}); auto filter = std::make_shared("2", builder.build(), std::set{rule.get()}, exclusion::filter_mode::monitor); @@ -1207,9 +1282,11 @@ TEST(TestContext, OverlappingRuleFiltersEphemeralMonitorPersistentBypass) // Generate rule std::shared_ptr rule; { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category"}}; @@ -1221,9 +1298,11 @@ TEST(TestContext, OverlappingRuleFiltersEphemeralMonitorPersistentBypass) // Generate filter { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); auto filter = std::make_shared("1", builder.build(), std::set{rule.get()}, exclusion::filter_mode::monitor); @@ -1231,9 +1310,11 @@ TEST(TestContext, OverlappingRuleFiltersEphemeralMonitorPersistentBypass) } { - expression_builder builder(1); - builder.start_condition(std::vector{"unrouted"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.route"); + builder.end_condition(std::vector{"unrouted"}); auto filter = std::make_shared( "2", builder.build(), std::set{rule.get()}); @@ -1277,9 +1358,11 @@ TEST(TestContext, RuleFilterTimeout) // Generate rule std::shared_ptr rule; { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category"}}; @@ -1291,9 +1374,11 @@ TEST(TestContext, RuleFilterTimeout) // Generate filter { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); auto filter = std::make_shared( "1", builder.build(), std::set{rule.get()}); @@ -1320,9 +1405,11 @@ TEST(TestContext, NoRuleFilterWithCondition) // Generate rule std::shared_ptr rule; { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category"}}; @@ -1334,9 +1421,11 @@ TEST(TestContext, NoRuleFilterWithCondition) // Generate filter { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); auto filter = std::make_shared( "1", builder.build(), std::set{rule.get()}); @@ -1567,9 +1656,11 @@ TEST(TestContext, MultipleRuleFiltersNonOverlappingRulesWithConditions) ddwaf::test::context ctx(ruleset); { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); auto filter = std::make_shared("1", builder.build(), std::set{ @@ -1578,9 +1669,11 @@ TEST(TestContext, MultipleRuleFiltersNonOverlappingRulesWithConditions) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); auto filter = std::make_shared("2", builder.build(), std::set{ @@ -1650,9 +1743,11 @@ TEST(TestContext, MultipleRuleFiltersOverlappingRulesWithConditions) ddwaf::test::context ctx(ruleset); { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); auto filter = std::make_shared("1", builder.build(), std::set{rules[0].get(), rules[1].get(), rules[2].get(), rules[3].get(), @@ -1661,9 +1756,11 @@ TEST(TestContext, MultipleRuleFiltersOverlappingRulesWithConditions) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); auto filter = std::make_shared("2", builder.build(), std::set{rules[3].get(), rules[4].get(), rules[5].get(), rules[6].get(), @@ -1719,9 +1816,11 @@ TEST(TestContext, SkipInputFilterNoTargets) std::shared_ptr rule; std::shared_ptr filter; { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category"}}; @@ -1764,9 +1863,11 @@ TEST(TestContext, SkipRuleButNotInputFilterNoTargets) std::shared_ptr rule; std::shared_ptr filter; { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "type"}, {"category", "category"}}; @@ -1803,9 +1904,11 @@ TEST(TestContext, SkipRuleButNotInputFilterNoTargets) TEST(TestContext, InputFilterExclude) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; @@ -1840,10 +1943,12 @@ TEST(TestContext, InputFilterExclude) TEST(TestContext, InputFilterExcludeEphemeral) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); builder.add_target("http.peer_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; @@ -1890,10 +1995,12 @@ TEST(TestContext, InputFilterExcludeEphemeral) TEST(TestContext, InputFilterExcludeEphemeralReuseObject) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); builder.add_target("http.peer_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; @@ -1932,9 +2039,11 @@ TEST(TestContext, InputFilterExcludeEphemeralReuseObject) TEST(TestContext, InputFilterExcludeRule) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; @@ -1985,9 +2094,11 @@ TEST(TestContext, InputFilterExcludeRule) TEST(TestContext, InputFilterExcludeRuleEphemeral) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; @@ -2033,9 +2144,11 @@ TEST(TestContext, InputFilterExcludeRuleEphemeral) TEST(TestContext, InputFilterMonitorRuleEphemeral) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; @@ -2086,9 +2199,11 @@ TEST(TestContext, InputFilterMonitorRuleEphemeral) TEST(TestContext, InputFilterExcluderRuleEphemeralAndPersistent) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; @@ -2145,9 +2260,11 @@ TEST(TestContext, InputFilterExcluderRuleEphemeralAndPersistent) TEST(TestContext, InputFilterMonitorRuleEphemeralAndPersistent) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; @@ -2211,9 +2328,11 @@ TEST(TestContext, InputFilterWithCondition) { auto ruleset = std::make_shared(); { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "type"}, {"category", "category"}}; @@ -2224,9 +2343,11 @@ TEST(TestContext, InputFilterWithCondition) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); auto obj_filter = std::make_shared(); obj_filter->insert(get_target_index("http.client_ip"), "http.client_ip"); @@ -2297,9 +2418,11 @@ TEST(TestContext, InputFilterWithEphemeralCondition) auto ruleset = std::make_shared(); ruleset->event_obfuscator = std::make_shared(); { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "type"}, {"category", "category"}}; @@ -2310,9 +2433,11 @@ TEST(TestContext, InputFilterWithEphemeralCondition) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); auto obj_filter = std::make_shared(); obj_filter->insert(get_target_index("http.client_ip"), "http.client_ip"); @@ -2353,9 +2478,11 @@ TEST(TestContext, InputFilterMultipleRules) { auto ruleset = std::make_shared(); { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "ip_type"}, {"category", "category"}}; @@ -2367,9 +2494,11 @@ TEST(TestContext, InputFilterMultipleRules) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "usr_type"}, {"category", "category"}}; @@ -2462,9 +2591,11 @@ TEST(TestContext, InputFilterMultipleRulesMultipleFilters) { auto ruleset = std::make_shared(); { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "ip_type"}, {"category", "category"}}; @@ -2476,9 +2607,11 @@ TEST(TestContext, InputFilterMultipleRulesMultipleFilters) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr_id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "usr_type"}, {"category", "category"}}; @@ -2584,9 +2717,11 @@ TEST(TestContext, InputFilterMultipleRulesMultipleFiltersMultipleObjects) { auto ruleset = std::make_shared(); { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{ {"type", "ip_type"}, {"category", "category"}}; @@ -2598,9 +2733,11 @@ TEST(TestContext, InputFilterMultipleRulesMultipleFiltersMultipleObjects) } { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr_id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{ {"type", "usr_type"}, {"category", "category"}}; @@ -2612,9 +2749,11 @@ TEST(TestContext, InputFilterMultipleRulesMultipleFiltersMultipleObjects) } { - expression_builder builder(1); - builder.start_condition(std::vector{"mycookie"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.headers", {"cookie"}); + builder.end_condition(std::vector{"mycookie"}); std::unordered_map tags{ {"type", "cookie_type"}, {"category", "category"}}; diff --git a/tests/expression_test.cpp b/tests/expression_test.cpp index 0f1cdbebe..4bf19cc34 100644 --- a/tests/expression_test.cpp +++ b/tests/expression_test.cpp @@ -14,9 +14,11 @@ using namespace std::literals; TEST(TestExpression, SimpleMatch) { - expression_builder builder(1); - builder.start_condition(".*", 0, true); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.query"); + builder.end_condition(".*", 0, true); auto expr = builder.build(); @@ -48,9 +50,11 @@ TEST(TestExpression, SimpleMatch) TEST(TestExpression, EphemeralMatch) { - expression_builder builder(1); - builder.start_condition(".*", 0, true); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.query"); + builder.end_condition(".*", 0, true); auto expr = builder.build(); @@ -82,10 +86,12 @@ TEST(TestExpression, EphemeralMatch) TEST(TestExpression, MultiInputMatchOnSecondEval) { - expression_builder builder(1); - builder.start_condition("^value$", 0, true); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.query"); builder.add_target("server.request.body"); + builder.end_condition("^value$", 0, true); auto expr = builder.build(); @@ -137,9 +143,11 @@ TEST(TestExpression, MultiInputMatchOnSecondEval) TEST(TestExpression, EphemeralMatchOnSecondEval) { - expression_builder builder(1); - builder.start_condition("^value$", 0, true); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.body"); + builder.end_condition("^value$", 0, true); auto expr = builder.build(); @@ -191,11 +199,16 @@ TEST(TestExpression, EphemeralMatchOnSecondEval) TEST(TestExpression, EphemeralMatchTwoConditions) { - expression_builder builder(1); - builder.start_condition("^value$", 0, true); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.query"); - builder.start_condition("^value$", 0, true); + builder.end_condition("^value$", 0, true); + + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.body"); + builder.end_condition("^value$", 0, true); auto expr = builder.build(); @@ -243,11 +256,16 @@ TEST(TestExpression, EphemeralMatchTwoConditions) TEST(TestExpression, EphemeralMatchOnFirstConditionFirstEval) { - expression_builder builder(1); - builder.start_condition("^value$", 0, true); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.query"); - builder.start_condition("^value$", 0, true); + builder.end_condition("^value$", 0, true); + + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.body"); + builder.end_condition("^value$", 0, true); auto expr = builder.build(); @@ -291,11 +309,16 @@ TEST(TestExpression, EphemeralMatchOnFirstConditionFirstEval) TEST(TestExpression, EphemeralMatchOnFirstConditionSecondEval) { - expression_builder builder(1); - builder.start_condition("^value$", 0, true); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.query"); - builder.start_condition("^value$", 0, true); + builder.end_condition("^value$", 0, true); + + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.body"); + builder.end_condition("^value$", 0, true); auto expr = builder.build(); @@ -339,9 +362,11 @@ TEST(TestExpression, EphemeralMatchOnFirstConditionSecondEval) TEST(TestExpression, DuplicateInput) { - expression_builder builder(1); - builder.start_condition("^value$", 0, true); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.query"); + builder.end_condition("^value$", 0, true); auto expr = builder.build(); @@ -385,9 +410,11 @@ TEST(TestExpression, DuplicateInput) TEST(TestExpression, DuplicateEphemeralInput) { - expression_builder builder(1); - builder.start_condition("^value$", 0, true); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.query"); + builder.end_condition("^value$", 0, true); auto expr = builder.build(); @@ -431,9 +458,11 @@ TEST(TestExpression, DuplicateEphemeralInput) TEST(TestExpression, MatchDuplicateInputNoCache) { - expression_builder builder(1); - builder.start_condition("^value$", 0, true); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.query"); + builder.end_condition("^value$", 0, true); auto expr = builder.build(); @@ -483,13 +512,16 @@ TEST(TestExpression, MatchDuplicateInputNoCache) TEST(TestExpression, TwoConditionsSingleInputNoMatch) { - expression_builder builder(2); - - builder.start_condition("value", 0, true); + test::expression_builder builder(2); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.query"); + builder.end_condition("value", 0, true); - builder.start_condition("^value$", 0, true); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.query"); + builder.end_condition("^value$", 0, true); auto expr = builder.build(); @@ -529,13 +561,16 @@ TEST(TestExpression, TwoConditionsSingleInputNoMatch) TEST(TestExpression, TwoConditionsSingleInputMatch) { - expression_builder builder(2); - - builder.start_condition("value", 0, true); + test::expression_builder builder(2); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.query"); + builder.end_condition("value", 0, true); - builder.start_condition("^value$", 0, true); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.query"); + builder.end_condition("^value$", 0, true); auto expr = builder.build(); @@ -555,13 +590,16 @@ TEST(TestExpression, TwoConditionsSingleInputMatch) TEST(TestExpression, TwoConditionsMultiInputSingleEvalMatch) { - expression_builder builder(2); - - builder.start_condition("query", 0, true); + test::expression_builder builder(2); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.query"); + builder.end_condition("query", 0, true); - builder.start_condition("body", 0, true); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.body"); + builder.end_condition("body", 0, true); auto expr = builder.build(); @@ -583,13 +621,16 @@ TEST(TestExpression, TwoConditionsMultiInputSingleEvalMatch) TEST(TestExpression, TwoConditionsMultiInputMultiEvalMatch) { - expression_builder builder(2); - - builder.start_condition("query", 0, true); + test::expression_builder builder(2); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.query"); + builder.end_condition("query", 0, true); - builder.start_condition("body", 0, true); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.body"); + builder.end_condition("body", 0, true); auto expr = builder.build(); @@ -631,9 +672,11 @@ TEST(TestExpression, TwoConditionsMultiInputMultiEvalMatch) TEST(TestExpression, MatchWithKeyPath) { - expression_builder builder(1); - builder.start_condition(".*", 0, true); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.query", {"key"}); + builder.end_condition(".*", 0, true); auto expr = builder.build(); ddwaf_object root; @@ -662,9 +705,11 @@ TEST(TestExpression, MatchWithKeyPath) TEST(TestExpression, MatchWithTransformer) { - expression_builder builder(1); - builder.start_condition("value", 0, true); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.query", {}, {transformer_id::lowercase}); + builder.end_condition("value", 0, true); auto expr = builder.build(); ddwaf_object root; @@ -690,10 +735,12 @@ TEST(TestExpression, MatchWithTransformer) TEST(TestExpression, MatchWithMultipleTransformers) { - expression_builder builder(1); - builder.start_condition("^ value $", 0, true); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.query", {}, {transformer_id::compress_whitespace, transformer_id::lowercase}); + builder.end_condition("^ value $", 0, true); auto expr = builder.build(); ddwaf_object root; @@ -719,9 +766,11 @@ TEST(TestExpression, MatchWithMultipleTransformers) TEST(TestExpression, MatchOnKeys) { - expression_builder builder(1); - builder.start_condition("value", 0, true); - builder.add_target("server.request.query", {}, {}, expression::data_source::keys); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); + builder.add_target("server.request.query", {}, {}, condition::data_source::keys); + builder.end_condition("value", 0, true); auto expr = builder.build(); ddwaf_object root; @@ -750,10 +799,12 @@ TEST(TestExpression, MatchOnKeys) TEST(TestExpression, MatchOnKeysWithTransformer) { - expression_builder builder(1); - builder.start_condition("value", 0, true); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target( - "server.request.query", {}, {transformer_id::lowercase}, expression::data_source::keys); + "server.request.query", {}, {transformer_id::lowercase}, condition::data_source::keys); + builder.end_condition("value", 0, true); auto expr = builder.build(); ddwaf_object root; @@ -782,9 +833,11 @@ TEST(TestExpression, MatchOnKeysWithTransformer) TEST(TestExpression, ExcludeInput) { - expression_builder builder(1); - builder.start_condition(".*", 0, true); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.query"); + builder.end_condition(".*", 0, true); auto expr = builder.build(); ddwaf_object root; @@ -804,9 +857,11 @@ TEST(TestExpression, ExcludeInput) TEST(TestExpression, ExcludeKeyPath) { - expression_builder builder(1); - builder.start_condition(".*", 0, true); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("server.request.query"); + builder.end_condition(".*", 0, true); auto expr = builder.build(); ddwaf_object root; diff --git a/tests/input_filter_test.cpp b/tests/input_filter_test.cpp index d45e73705..250e15ce7 100644 --- a/tests/input_filter_test.cpp +++ b/tests/input_filter_test.cpp @@ -5,6 +5,7 @@ // Copyright 2021 Datadog, Inc. #include "test.hpp" +#include "test_utils.hpp" #include "exclusion/input_filter.hpp" #include "matcher/exact_match.hpp" @@ -142,9 +143,11 @@ TEST(TestInputFilter, EphemeralObjectExclusionNoConditions) TEST(TestInputFilter, PersistentInputExclusionWithPersistentCondition) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); ddwaf_object root; ddwaf_object tmp; @@ -174,9 +177,11 @@ TEST(TestInputFilter, PersistentInputExclusionWithPersistentCondition) TEST(TestInputFilter, EphemeralInputExclusionWithEphemeralCondition) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); ddwaf_object root; ddwaf_object tmp; @@ -206,9 +211,11 @@ TEST(TestInputFilter, EphemeralInputExclusionWithEphemeralCondition) TEST(TestInputFilter, PersistentInputExclusionWithEphemeralCondition) { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); ddwaf::object_store store; @@ -242,9 +249,11 @@ TEST(TestInputFilter, PersistentInputExclusionWithEphemeralCondition) TEST(TestInputFilter, EphemeralInputExclusionWithPersistentCondition) { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); ddwaf::object_store store; @@ -278,9 +287,11 @@ TEST(TestInputFilter, EphemeralInputExclusionWithPersistentCondition) TEST(TestInputFilter, InputExclusionWithConditionAndTransformers) { - expression_builder builder(1); - builder.start_condition(std::vector{"admin"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id", {}, {transformer_id::lowercase}); + builder.end_condition(std::vector{"admin"}); ddwaf_object root; ddwaf_object tmp; @@ -309,9 +320,11 @@ TEST(TestInputFilter, InputExclusionWithConditionAndTransformers) TEST(TestInputFilter, InputExclusionFailedCondition) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); ddwaf_object root; ddwaf_object tmp; @@ -336,9 +349,11 @@ TEST(TestInputFilter, InputExclusionFailedCondition) TEST(TestInputFilter, ObjectExclusionWithCondition) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); ddwaf_object root; ddwaf_object child; @@ -373,9 +388,11 @@ TEST(TestInputFilter, ObjectExclusionWithCondition) TEST(TestInputFilter, ObjectExclusionFailedCondition) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); ddwaf_object root; ddwaf_object child; @@ -406,13 +423,16 @@ TEST(TestInputFilter, ObjectExclusionFailedCondition) TEST(TestInputFilter, InputValidateCachedMatch) { - expression_builder builder(2); - - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(2); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); - builder.start_condition(std::vector{"admin"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); auto obj_filter = std::make_shared(); obj_filter->insert(get_target_index("usr.id"), "usr.id"); @@ -458,10 +478,11 @@ TEST(TestInputFilter, InputValidateCachedMatch) TEST(TestInputFilter, InputValidateCachedEphemeralMatch) { - expression_builder builder(2); - - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(2); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); auto obj_filter = std::make_shared(); obj_filter->insert(get_target_index("usr.id"), "usr.id"); @@ -533,13 +554,16 @@ TEST(TestInputFilter, InputValidateCachedEphemeralMatch) TEST(TestInputFilter, InputMatchWithoutCache) { - expression_builder builder(2); - - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(2); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); - builder.start_condition(std::vector{"admin"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); auto obj_filter = std::make_shared(); obj_filter->insert(get_target_index("http.client_ip"), "http.client_ip"); @@ -580,13 +604,16 @@ TEST(TestInputFilter, InputMatchWithoutCache) TEST(TestInputFilter, InputNoMatchWithoutCache) { - expression_builder builder(2); - - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(2); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); - builder.start_condition(std::vector{"admin"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); auto obj_filter = std::make_shared(); obj_filter->insert(get_target_index("http.client_ip"), "http.client_ip"); @@ -635,13 +662,16 @@ TEST(TestInputFilter, InputNoMatchWithoutCache) TEST(TestInputFilter, InputCachedMatchSecondRun) { - expression_builder builder(2); - - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(2); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); - builder.start_condition(std::vector{"admin"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); auto obj_filter = std::make_shared(); obj_filter->insert(get_target_index("http.client_ip"), "http.client_ip"); @@ -692,13 +722,16 @@ TEST(TestInputFilter, InputCachedMatchSecondRun) TEST(TestInputFilter, ObjectValidateCachedMatch) { - expression_builder builder(2); - - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(2); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); - builder.start_condition(std::vector{"admin"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); auto obj_filter = std::make_shared(); obj_filter->insert(get_target_index("query"), "query", {"params"}); @@ -753,13 +786,16 @@ TEST(TestInputFilter, ObjectValidateCachedMatch) TEST(TestInputFilter, ObjectMatchWithoutCache) { - expression_builder builder(2); - - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(2); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); - builder.start_condition(std::vector{"admin"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); auto obj_filter = std::make_shared(); obj_filter->insert(get_target_index("query"), "query", {"params"}); @@ -810,13 +846,16 @@ TEST(TestInputFilter, ObjectMatchWithoutCache) TEST(TestInputFilter, ObjectNoMatchWithoutCache) { - expression_builder builder(2); - - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(2); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); - builder.start_condition(std::vector{"admin"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); auto obj_filter = std::make_shared(); obj_filter->insert(get_target_index("query"), "query", {"params"}); @@ -867,13 +906,16 @@ TEST(TestInputFilter, ObjectNoMatchWithoutCache) TEST(TestInputFilter, ObjectCachedMatchSecondRun) { - expression_builder builder(2); - - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(2); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); - builder.start_condition(std::vector{"admin"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); auto obj_filter = std::make_shared(); obj_filter->insert(get_target_index("query"), "query", {"params"}); diff --git a/tests/key_iterator_test.cpp b/tests/key_iterator_test.cpp index c29f47477..6a02f2b67 100644 --- a/tests/key_iterator_test.cpp +++ b/tests/key_iterator_test.cpp @@ -598,7 +598,8 @@ TEST(TestKeyIterator, TestInvalidObjectPath) ddwaf_object_invalid(&object); exclusion::object_set_ref exclude; - ddwaf::object::key_iterator it(&object, {"key", "0", "value"}, exclude); + std::vector key_path{"key", "0", "value"}; + ddwaf::object::key_iterator it(&object, key_path, exclude); EXPECT_FALSE((bool)it); auto path = it.get_current_path(); @@ -618,13 +619,15 @@ TEST(TestKeyIterator, TestSimplePath) exclusion::object_set_ref exclude; { - ddwaf::object::key_iterator it(&object, {"key"}, {}); + std::vector key_path{"key"}; + ddwaf::object::key_iterator it(&object, key_path, {}); EXPECT_FALSE((bool)it); EXPECT_FALSE(++it); } { - ddwaf::object::key_iterator it(&object, {"key", "0"}, {}); + std::vector key_path{"key", "0"}; + ddwaf::object::key_iterator it(&object, key_path, {}); EXPECT_FALSE((bool)it); auto path = it.get_current_path(); @@ -634,7 +637,8 @@ TEST(TestKeyIterator, TestSimplePath) } { - ddwaf::object::key_iterator it(&object, {"key", "0", "value"}, {}); + std::vector key_path{"key", "0", "value"}; + ddwaf::object::key_iterator it(&object, key_path, {}); EXPECT_FALSE((bool)it); auto path = it.get_current_path(); @@ -670,7 +674,8 @@ TEST(TestKeyIterator, TestMultiPath) {"value", {"first", "value"}}, }; - ddwaf::object::key_iterator it(&object, {"first"}, exclude); + std::vector key_path{"first"}; + ddwaf::object::key_iterator it(&object, key_path, exclude); for (auto &[value, path] : values) { EXPECT_STREQ((*it)->stringValue, value.c_str()); @@ -689,7 +694,8 @@ TEST(TestKeyIterator, TestMultiPath) {"value", {"first", "second", "value"}}, }; - ddwaf::object::key_iterator it(&object, {"first", "second"}, exclude); + std::vector key_path{"first", "second"}; + ddwaf::object::key_iterator it(&object, key_path, exclude); for (auto &[value, path] : values) { EXPECT_STREQ((*it)->stringValue, value.c_str()); @@ -703,7 +709,8 @@ TEST(TestKeyIterator, TestMultiPath) } { - ddwaf::object::key_iterator it(&object, {"first", "second", "third"}, exclude); + std::vector key_path{"first", "second", "third"}; + ddwaf::object::key_iterator it(&object, key_path, exclude); EXPECT_FALSE((bool)it); } @@ -730,7 +737,8 @@ TEST(TestKeyIterator, TestContainerMixPath) exclusion::object_set_ref exclude; { - ddwaf::object::key_iterator it(&object, {"root", "key0"}, exclude); + std::vector key_path{"root", "key0"}; + ddwaf::object::key_iterator it(&object, key_path, exclude); EXPECT_TRUE((bool)it); EXPECT_STREQ((*it)->stringValue, "key0_0"); @@ -743,7 +751,8 @@ TEST(TestKeyIterator, TestContainerMixPath) } { - ddwaf::object::key_iterator it(&object, {"root", "key1"}, exclude); + std::vector key_path{"root", "key1"}; + ddwaf::object::key_iterator it(&object, key_path, exclude); EXPECT_FALSE((bool)it); EXPECT_FALSE(++it); } @@ -755,7 +764,8 @@ TEST(TestKeyIterator, TestContainerMixPath) {"key2_2", {"root", "key2", "key2_2"}}, }; - ddwaf::object::key_iterator it(&object, {"root", "key2"}, exclude); + std::vector key_path{"root", "key2"}; + ddwaf::object::key_iterator it(&object, key_path, exclude); for (auto &[value, path] : values) { EXPECT_STREQ((*it)->stringValue, value.c_str()); @@ -791,18 +801,20 @@ TEST(TestKeyIterator, TestContainerMixInvalidPath) exclusion::object_set_ref exclude; { - ddwaf::object::key_iterator it(&object, {"rat"}, exclude); + std::vector key_path{"rat"}; + ddwaf::object::key_iterator it(&object, key_path, exclude); EXPECT_FALSE((bool)it); } { - ddwaf::object::key_iterator it(&object, {"root", "cat"}, exclude); + std::vector key_path{"root", "cat"}; + ddwaf::object::key_iterator it(&object, key_path, exclude); EXPECT_FALSE((bool)it); } { - ddwaf::object::key_iterator it( - &object, {"root", "key2", "key2_2", "0", "1", "2", "3"}, exclude); + std::vector key_path{"root", "key2", "key2_2", "0", "1", "2", "3"}; + ddwaf::object::key_iterator it(&object, key_path, exclude); EXPECT_FALSE((bool)it); } @@ -831,14 +843,16 @@ TEST(TestKeyIterator, TestMapDepthLimitPath) exclusion::object_set_ref exclude; { limits.max_container_depth = 3; - ddwaf::object::key_iterator it(&object, {"root", "child", "grandchild"}, exclude, limits); + std::vector key_path{"root", "child", "grandchild"}; + ddwaf::object::key_iterator it(&object, key_path, exclude, limits); EXPECT_FALSE(it); } { limits.max_container_depth = 4; - ddwaf::object::key_iterator it(&object, {"root", "child", "grandchild"}, exclude, limits); + std::vector key_path{"root", "child", "grandchild"}; + ddwaf::object::key_iterator it(&object, key_path, exclude, limits); EXPECT_TRUE(it); { @@ -927,7 +941,8 @@ TEST(TestKeyIterator, TestInvalidMapKeyWithPath) exclusion::object_set_ref exclude; { - ddwaf::object::key_iterator it(&root, {"key"}, exclude); + std::vector key_path{"key"}; + ddwaf::object::key_iterator it(&root, key_path, exclude); EXPECT_FALSE(it); } @@ -936,7 +951,8 @@ TEST(TestKeyIterator, TestInvalidMapKeyWithPath) ddwaf_object_map_add(&root, "other", &other); { - ddwaf::object::key_iterator it(&root, {"other"}, exclude); + std::vector key_path{"other"}; + ddwaf::object::key_iterator it(&root, key_path, exclude); EXPECT_TRUE(it); EXPECT_FALSE(++it); } @@ -1023,7 +1039,8 @@ TEST(TestKeyIterator, TestExcludeObjectInKeyPath) std::unordered_set persistent{&child.array[0]}; exclusion::object_set_ref exclude{persistent, {}}; - ddwaf::object::key_iterator it(&root, {"parent", "child"}, exclude); + std::vector key_path{"parent", "child"}; + ddwaf::object::key_iterator it(&root, key_path, exclude); EXPECT_FALSE(it); @@ -1041,7 +1058,8 @@ TEST(TestKeyIterator, TestExcludeRootOfKeyPath) std::unordered_set persistent{&root.array[0]}; exclusion::object_set_ref exclude{persistent, {}}; - ddwaf::object::key_iterator it(&root, {"parent", "child"}, exclude); + std::vector key_path{"parent", "child"}; + ddwaf::object::key_iterator it(&root, key_path, exclude); EXPECT_FALSE(it); diff --git a/tests/processor_test.cpp b/tests/processor_test.cpp index d095fdcef..d2c814b3d 100644 --- a/tests/processor_test.cpp +++ b/tests/processor_test.cpp @@ -11,6 +11,8 @@ #include +#include "test_utils.hpp" + using ::testing::_; using ::testing::Return; @@ -155,9 +157,11 @@ TEST(TestProcessor, SingleMappingOutputNoEvalConditionalTrue) std::vector mappings{{get_target_index("input_address"), "input_address", get_target_index("output_address"), "output_address"}}; - expression_builder builder(1); - builder.start_condition>(true); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("enabled?"); + builder.end_condition>(true); processor proc{"id", std::move(gen), builder.build(), std::move(mappings), {}, false, true}; EXPECT_STREQ(proc.get_id().c_str(), "id"); @@ -199,9 +203,11 @@ TEST(TestProcessor, SingleMappingOutputNoEvalConditionalCached) std::vector mappings{{get_target_index("input_address"), "input_address", get_target_index("output_address"), "output_address"}}; - expression_builder builder(1); - builder.start_condition>(true); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("enabled?"); + builder.end_condition>(true); processor proc{"id", std::move(gen), builder.build(), std::move(mappings), {}, false, true}; EXPECT_STREQ(proc.get_id().c_str(), "id"); @@ -258,9 +264,11 @@ TEST(TestProcessor, SingleMappingOutputNoEvalConditionalFalse) std::vector mappings{{get_target_index("input_address"), "input_address", get_target_index("output_address"), "output_address"}}; - expression_builder builder(1); - builder.start_condition>(true); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("enabled?"); + builder.end_condition>(true); processor proc{"id", std::move(gen), builder.build(), std::move(mappings), {}, false, true}; EXPECT_STREQ(proc.get_id().c_str(), "id"); @@ -348,9 +356,11 @@ TEST(TestProcessor, SingleMappingNoOutputEvalConditionalTrue) std::vector mappings{{get_target_index("input_address"), "input_address", get_target_index("output_address"), "output_address"}}; - expression_builder builder(1); - builder.start_condition>(true); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("enabled?"); + builder.end_condition>(true); processor proc{"id", std::move(gen), builder.build(), std::move(mappings), {}, true, false}; EXPECT_STREQ(proc.get_id().c_str(), "id"); @@ -393,9 +403,11 @@ TEST(TestProcessor, SingleMappingNoOutputEvalConditionalFalse) std::vector mappings{{get_target_index("input_address"), "input_address", get_target_index("output_address"), "output_address"}}; - expression_builder builder(1); - builder.start_condition>(true); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("enabled?"); + builder.end_condition>(true); processor proc{"id", std::move(gen), builder.build(), std::move(mappings), {}, true, false}; EXPECT_STREQ(proc.get_id().c_str(), "id"); diff --git a/tests/rule_filter_test.cpp b/tests/rule_filter_test.cpp index f9d240d9e..264e3f3ba 100644 --- a/tests/rule_filter_test.cpp +++ b/tests/rule_filter_test.cpp @@ -17,9 +17,11 @@ namespace { TEST(TestRuleFilter, Match) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); auto rule = std::make_shared(ddwaf::rule("", "", {}, std::make_shared())); @@ -51,9 +53,11 @@ TEST(TestRuleFilter, Match) TEST(TestRuleFilter, EphemeralMatch) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); auto rule = std::make_shared(ddwaf::rule("", "", {}, std::make_shared())); @@ -85,9 +89,11 @@ TEST(TestRuleFilter, EphemeralMatch) TEST(TestRuleFilter, NoMatch) { - expression_builder builder(1); - builder.start_condition(std::vector{}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{}); ddwaf::exclusion::rule_filter filter{"filter", builder.build(), {}}; @@ -107,13 +113,17 @@ TEST(TestRuleFilter, NoMatch) TEST(TestRuleFilter, ValidateCachedMatch) { - expression_builder builder(2); + test::expression_builder builder(2); - builder.start_condition(std::vector{"192.168.0.1"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); - builder.start_condition(std::vector{"admin"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); auto rule = std::make_shared(ddwaf::rule("", "", {}, std::make_shared())); @@ -159,13 +169,17 @@ TEST(TestRuleFilter, ValidateCachedMatch) TEST(TestRuleFilter, CachedMatchAndEphemeralMatch) { - expression_builder builder(2); + test::expression_builder builder(2); - builder.start_condition(std::vector{"192.168.0.1"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); - builder.start_condition(std::vector{"admin"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); auto rule = std::make_shared(ddwaf::rule("", "", {}, std::make_shared())); @@ -213,13 +227,17 @@ TEST(TestRuleFilter, CachedMatchAndEphemeralMatch) TEST(TestRuleFilter, ValidateEphemeralMatchCache) { - expression_builder builder(2); + test::expression_builder builder(2); - builder.start_condition(std::vector{"192.168.0.1"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); - builder.start_condition(std::vector{"admin"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); auto rule = std::make_shared(ddwaf::rule("", "", {}, std::make_shared())); @@ -262,13 +280,17 @@ TEST(TestRuleFilter, ValidateEphemeralMatchCache) TEST(TestRuleFilter, MatchWithoutCache) { - expression_builder builder(2); + test::expression_builder builder(2); - builder.start_condition(std::vector{"192.168.0.1"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); - builder.start_condition(std::vector{"admin"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); auto rule = std::make_shared(ddwaf::rule("", "", {}, std::make_shared())); @@ -307,13 +329,17 @@ TEST(TestRuleFilter, MatchWithoutCache) TEST(TestRuleFilter, NoMatchWithoutCache) { - expression_builder builder(2); + test::expression_builder builder(2); - builder.start_condition(std::vector{"192.168.0.1"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); - builder.start_condition(std::vector{"admin"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); auto rule = std::make_shared(ddwaf::rule("", "", {}, std::make_shared())); @@ -352,13 +378,17 @@ TEST(TestRuleFilter, NoMatchWithoutCache) TEST(TestRuleFilter, FullCachedMatchSecondRun) { - expression_builder builder(2); + test::expression_builder builder(2); - builder.start_condition(std::vector{"192.168.0.1"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); - builder.start_condition(std::vector{"admin"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); auto rule = std::make_shared(ddwaf::rule("", "", {}, std::make_shared())); diff --git a/tests/rule_test.cpp b/tests/rule_test.cpp index 57e7ca523..fb16a28e6 100644 --- a/tests/rule_test.cpp +++ b/tests/rule_test.cpp @@ -18,9 +18,11 @@ namespace { TEST(TestRule, Match) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; ddwaf::rule rule( @@ -77,9 +79,11 @@ TEST(TestRule, Match) TEST(TestRule, EphemeralMatch) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; ddwaf::rule rule( @@ -120,9 +124,11 @@ TEST(TestRule, EphemeralMatch) TEST(TestRule, NoMatch) { - expression_builder builder(1); - builder.start_condition(std::vector{}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; ddwaf::rule rule("id", "name", std::move(tags), builder.build()); @@ -144,12 +150,16 @@ TEST(TestRule, NoMatch) TEST(TestRule, ValidateCachedMatch) { - expression_builder builder(2); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(2); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); - builder.start_condition(std::vector{"admin"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; @@ -215,12 +225,16 @@ TEST(TestRule, ValidateCachedMatch) TEST(TestRule, MatchWithoutCache) { - expression_builder builder(2); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(2); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); - builder.start_condition(std::vector{"admin"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; @@ -278,12 +292,16 @@ TEST(TestRule, MatchWithoutCache) TEST(TestRule, NoMatchWithoutCache) { - expression_builder builder(2); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(2); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); - builder.start_condition(std::vector{"admin"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; @@ -322,12 +340,16 @@ TEST(TestRule, NoMatchWithoutCache) TEST(TestRule, FullCachedMatchSecondRun) { - expression_builder builder(2); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(2); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); - builder.start_condition(std::vector{"admin"}); + builder.start_condition(); + builder.add_argument(); builder.add_target("usr.id"); + builder.end_condition(std::vector{"admin"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; @@ -368,9 +390,11 @@ TEST(TestRule, FullCachedMatchSecondRun) TEST(TestRule, ExcludeObject) { - expression_builder builder(1); - builder.start_condition(std::vector{"192.168.0.1"}); + test::expression_builder builder(1); + builder.start_condition(); + builder.add_argument(); builder.add_target("http.client_ip"); + builder.end_condition(std::vector{"192.168.0.1"}); std::unordered_map tags{{"type", "type"}, {"category", "category"}}; diff --git a/tests/test_utils.hpp b/tests/test_utils.hpp index 939712e73..6a3549eb0 100644 --- a/tests/test_utils.hpp +++ b/tests/test_utils.hpp @@ -14,10 +14,14 @@ #include +#include "condition/matcher_proxy.hpp" #include "context_allocator.hpp" #include "ddwaf.h" #include "event.hpp" +#include "expression.hpp" +#include "matcher/base.hpp" #include "test.hpp" +#include "utils.hpp" namespace ddwaf::test { struct event { @@ -46,6 +50,62 @@ std::ostream &operator<<(std::ostream &os, const event::match &m); std::string object_to_json(const ddwaf_object &obj); rapidjson::Document object_to_rapidjson(const ddwaf_object &obj); +class expression_builder { +public: + explicit expression_builder(std::size_t num_conditions, ddwaf::object_limits limits = {}) + : limits_(limits) + { + conditions_.reserve(num_conditions); + } + + void start_condition() { arguments_.clear(); } + + template + void end_condition(Args... args) + requires std::is_base_of_v + { + conditions_.emplace_back(std::make_unique( + std::make_unique(std::forward(args)...), std::string{}, + std::move(arguments_))); + } + + template + void end_condition(std::string data_id) + requires std::is_base_of_v + { + conditions_.emplace_back(std::make_unique( + std::move(arguments_), std::move(data_id), std::make_unique())); + } + + template + void end_condition() + requires std::is_base_of_v + { + conditions_.emplace_back(std::make_unique(std::move(arguments_))); + } + + void add_argument() { arguments_.emplace_back(); } + + void add_target(const std::string &name, std::vector key_path = {}, + std::vector transformers = {}, + condition::data_source source = condition::data_source::values) + { + auto &argument = arguments_.back(); + argument.targets.emplace_back(condition::target_definition{ + name, get_target_index(name), std::move(key_path), std::move(transformers), source}); + } + + std::shared_ptr build() + { + return std::make_shared(std::move(conditions_), limits_); + } + +protected: + ddwaf::object_limits limits_{}; + std::vector arguments_{}; + std::vector> conditions_{}; +}; + } // namespace ddwaf::test namespace YAML { diff --git a/tests/transformer/manager_test.cpp b/tests/transformer/manager_test.cpp index 977b64f36..20d568291 100644 --- a/tests/transformer/manager_test.cpp +++ b/tests/transformer/manager_test.cpp @@ -53,24 +53,78 @@ TEST(TestTransformerManager, InvalidTypes) ddwaf_object dst; ddwaf_object_unsigned(&src, 29); - EXPECT_FALSE(transformer::manager::transform(src, dst, {transformer_id::compress_whitespace})); - EXPECT_FALSE(transformer::manager::transform(src, dst, {transformer_id::lowercase})); - EXPECT_FALSE(transformer::manager::transform(src, dst, {transformer_id::normalize_path})); - EXPECT_FALSE(transformer::manager::transform(src, dst, {transformer_id::normalize_path_win})); - EXPECT_FALSE(transformer::manager::transform(src, dst, {transformer_id::remove_comments})); - EXPECT_FALSE(transformer::manager::transform(src, dst, {transformer_id::remove_nulls})); - EXPECT_FALSE(transformer::manager::transform(src, dst, {transformer_id::unicode_normalize})); - EXPECT_FALSE(transformer::manager::transform(src, dst, {transformer_id::url_decode})); - EXPECT_FALSE(transformer::manager::transform(src, dst, {transformer_id::url_decode_iis})); - EXPECT_FALSE(transformer::manager::transform(src, dst, {transformer_id::base64_decode})); - EXPECT_FALSE(transformer::manager::transform(src, dst, {transformer_id::base64_encode})); - EXPECT_FALSE(transformer::manager::transform(src, dst, {transformer_id::url_path})); - EXPECT_FALSE(transformer::manager::transform(src, dst, {transformer_id::url_basename})); - EXPECT_FALSE(transformer::manager::transform(src, dst, {transformer_id::url_querystring})); - EXPECT_FALSE(transformer::manager::transform(src, dst, {transformer_id::shell_unescape})); - EXPECT_FALSE(transformer::manager::transform(src, dst, {transformer_id::js_decode})); - EXPECT_FALSE(transformer::manager::transform(src, dst, {transformer_id::html_entity_decode})); - EXPECT_FALSE(transformer::manager::transform(src, dst, {transformer_id::css_decode})); + { + std::vector ids{transformer_id::compress_whitespace}; + EXPECT_FALSE(transformer::manager::transform(src, dst, ids)); + } + { + std::vector ids{transformer_id::lowercase}; + EXPECT_FALSE(transformer::manager::transform(src, dst, ids)); + } + { + std::vector ids{transformer_id::normalize_path}; + EXPECT_FALSE(transformer::manager::transform(src, dst, ids)); + } + { + std::vector ids{transformer_id::normalize_path_win}; + EXPECT_FALSE(transformer::manager::transform(src, dst, ids)); + } + { + std::vector ids{transformer_id::remove_comments}; + EXPECT_FALSE(transformer::manager::transform(src, dst, ids)); + } + { + std::vector ids{transformer_id::remove_nulls}; + EXPECT_FALSE(transformer::manager::transform(src, dst, ids)); + } + { + std::vector ids{transformer_id::unicode_normalize}; + EXPECT_FALSE(transformer::manager::transform(src, dst, ids)); + } + { + std::vector ids{transformer_id::url_decode}; + EXPECT_FALSE(transformer::manager::transform(src, dst, ids)); + } + { + std::vector ids{transformer_id::url_decode_iis}; + EXPECT_FALSE(transformer::manager::transform(src, dst, ids)); + } + { + std::vector ids{transformer_id::base64_decode}; + EXPECT_FALSE(transformer::manager::transform(src, dst, ids)); + } + { + std::vector ids{transformer_id::base64_encode}; + EXPECT_FALSE(transformer::manager::transform(src, dst, ids)); + } + { + std::vector ids{transformer_id::url_path}; + EXPECT_FALSE(transformer::manager::transform(src, dst, ids)); + } + { + std::vector ids{transformer_id::url_basename}; + EXPECT_FALSE(transformer::manager::transform(src, dst, ids)); + } + { + std::vector ids{transformer_id::url_querystring}; + EXPECT_FALSE(transformer::manager::transform(src, dst, ids)); + } + { + std::vector ids{transformer_id::shell_unescape}; + EXPECT_FALSE(transformer::manager::transform(src, dst, ids)); + } + { + std::vector ids{transformer_id::js_decode}; + EXPECT_FALSE(transformer::manager::transform(src, dst, ids)); + } + { + std::vector ids{transformer_id::html_entity_decode}; + EXPECT_FALSE(transformer::manager::transform(src, dst, ids)); + } + { + std::vector ids{transformer_id::css_decode}; + EXPECT_FALSE(transformer::manager::transform(src, dst, ids)); + } } TEST(TestTransformerManager, EmptyStrings) diff --git a/tests/value_iterator_test.cpp b/tests/value_iterator_test.cpp index d1326550e..2369bbcd6 100644 --- a/tests/value_iterator_test.cpp +++ b/tests/value_iterator_test.cpp @@ -597,7 +597,8 @@ TEST(TestValueIterator, TestInvalidObjectPath) std::unordered_set persistent; exclusion::object_set_ref exclude{persistent, {}}; { - ddwaf::object::value_iterator it(&object, {"key"}, exclude); + std::vector key_path{"key"}; + ddwaf::object::value_iterator it(&object, key_path, exclude); EXPECT_FALSE(it); auto path = it.get_current_path(); @@ -607,7 +608,8 @@ TEST(TestValueIterator, TestInvalidObjectPath) } { - ddwaf::object::value_iterator it(&object, {"key", "0"}, exclude); + std::vector key_path{"key", "0"}; + ddwaf::object::value_iterator it(&object, key_path, exclude); EXPECT_FALSE(it); auto path = it.get_current_path(); @@ -617,7 +619,8 @@ TEST(TestValueIterator, TestInvalidObjectPath) } { - ddwaf::object::value_iterator it(&object, {"key", "0", "value"}, exclude); + std::vector key_path{"key", "0", "value"}; + ddwaf::object::value_iterator it(&object, key_path, exclude); EXPECT_FALSE(it); auto path = it.get_current_path(); @@ -639,7 +642,8 @@ TEST(TestValueIterator, TestSimplePath) std::unordered_set persistent; exclusion::object_set_ref exclude{persistent, {}}; { - ddwaf::object::value_iterator it(&object, {"key"}, exclude); + std::vector key_path{"key"}; + ddwaf::object::value_iterator it(&object, key_path, exclude); EXPECT_TRUE(it); std::vector expected_path = {"key"}; @@ -651,7 +655,8 @@ TEST(TestValueIterator, TestSimplePath) } { - ddwaf::object::value_iterator it(&object, {"key", "0"}, exclude); + std::vector key_path{"key", "0"}; + ddwaf::object::value_iterator it(&object, key_path, exclude); EXPECT_FALSE(it); auto path = it.get_current_path(); @@ -661,7 +666,8 @@ TEST(TestValueIterator, TestSimplePath) } { - ddwaf::object::value_iterator it(&object, {"key", "0", "value"}, exclude); + std::vector key_path{"key", "0", "value"}; + ddwaf::object::value_iterator it(&object, key_path, exclude); EXPECT_FALSE(it); auto path = it.get_current_path(); @@ -691,7 +697,8 @@ TEST(TestValueIterator, TestMultiPath) std::unordered_set persistent; exclusion::object_set_ref exclude{persistent, {}}; { - ddwaf::object::value_iterator it(&object, {"first"}, exclude); + std::vector key_path{"first"}; + ddwaf::object::value_iterator it(&object, key_path, exclude); EXPECT_TRUE(it); EXPECT_STREQ((*it)->stringValue, "final"); @@ -725,7 +732,8 @@ TEST(TestValueIterator, TestMultiPath) } { - ddwaf::object::value_iterator it(&object, {"first", "second"}, exclude); + std::vector key_path{"first", "second"}; + ddwaf::object::value_iterator it(&object, key_path, exclude); EXPECT_TRUE(it); EXPECT_STREQ((*it)->stringValue, "final"); @@ -749,7 +757,8 @@ TEST(TestValueIterator, TestMultiPath) } { - ddwaf::object::value_iterator it(&object, {"first", "second", "third"}, exclude); + std::vector key_path{"first", "second", "third"}; + ddwaf::object::value_iterator it(&object, key_path, exclude); EXPECT_TRUE(it); EXPECT_STREQ((*it)->stringValue, "final"); @@ -793,7 +802,8 @@ TEST(TestValueIterator, TestContainerMixPath) {"value0_3", {"root", "key0", "3"}}, }; - ddwaf::object::value_iterator it(&object, {"root", "key0"}, exclude); + std::vector key_path{"root", "key0"}; + ddwaf::object::value_iterator it(&object, key_path, exclude); for (auto &[value, path] : values) { EXPECT_STREQ((*it)->stringValue, value.c_str()); @@ -807,7 +817,8 @@ TEST(TestValueIterator, TestContainerMixPath) } { - ddwaf::object::value_iterator it(&object, {"root", "key1"}, exclude); + std::vector key_path{"root", "key1"}; + ddwaf::object::value_iterator it(&object, key_path, exclude); EXPECT_STREQ((*it)->stringValue, "value1_0"); auto it_path = it.get_current_path(); @@ -822,7 +833,8 @@ TEST(TestValueIterator, TestContainerMixPath) {"value2_2", {"root", "key2", "key2_2", "0"}}, {"value2_3", {"root", "key2", "key2_2", "1"}}}; - ddwaf::object::value_iterator it(&object, {"root", "key2"}, exclude); + std::vector key_path{"root", "key2"}; + ddwaf::object::value_iterator it(&object, key_path, exclude); for (auto &[value, path] : values) { EXPECT_STREQ((*it)->stringValue, value.c_str()); @@ -859,18 +871,20 @@ TEST(TestValueIterator, TestContainerMixInvalidPath) std::unordered_set persistent; exclusion::object_set_ref exclude{persistent, {}}; { - ddwaf::object::value_iterator it(&object, {"rat"}, exclude); + std::vector key_path{"rat"}; + ddwaf::object::value_iterator it(&object, key_path, exclude); EXPECT_FALSE(it); } { - ddwaf::object::value_iterator it(&object, {"root", "cat"}, exclude); + std::vector key_path{"root", "cat"}; + ddwaf::object::value_iterator it(&object, key_path, exclude); EXPECT_FALSE(it); } { - ddwaf::object::value_iterator it( - &object, {"root", "key2", "key2_2", "0", "1", "2", "3"}, exclude); + std::vector key_path{"root", "key2", "key2_2", "0", "1", "2", "3"}; + ddwaf::object::value_iterator it(&object, key_path, exclude); EXPECT_FALSE(it); } @@ -897,14 +911,16 @@ TEST(TestValueIterator, TestMapDepthLimitPath) exclusion::object_set_ref exclude{persistent, {}}; { limits.max_container_depth = 3; - ddwaf::object::value_iterator it(&object, {"root", "child", "grandchild"}, exclude, limits); + std::vector key_path{"root", "child", "grandchild"}; + ddwaf::object::value_iterator it(&object, key_path, exclude, limits); EXPECT_FALSE(it); } { limits.max_container_depth = 4; - ddwaf::object::value_iterator it(&object, {"root", "child", "grandchild"}, exclude, limits); + std::vector key_path{"root", "child", "grandchild"}; + ddwaf::object::value_iterator it(&object, key_path, exclude, limits); auto it_path = it.get_current_path(); std::vector path = {"root", "child", "grandchild", "key"}; @@ -987,14 +1003,16 @@ TEST(TestValueIterator, TestInvalidMapKeyWithPath) exclusion::object_set_ref exclude{persistent, {}}; { // The invalid key should have no impact - ddwaf::object::value_iterator it(&root, {"key"}, exclude); + std::vector key_path{"key"}; + ddwaf::object::value_iterator it(&root, key_path, exclude); EXPECT_FALSE(it); } ddwaf_object_map_add(&root, "other", ddwaf_object_string(&tmp, "value")); { // The invalid key should have no impact - ddwaf::object::value_iterator it(&root, {"other"}, exclude); + std::vector key_path{"other"}; + ddwaf::object::value_iterator it(&root, key_path, exclude); EXPECT_TRUE(it); } @@ -1070,7 +1088,8 @@ TEST(TestValueIterator, TestExcludeObjectInKeyPath) std::unordered_set persistent = {&child.array[0]}; exclusion::object_set_ref exclude{persistent, {}}; - ddwaf::object::value_iterator it(&root, {"parent", "child"}, exclude); + std::vector key_path{"parent", "child"}; + ddwaf::object::value_iterator it(&root, key_path, exclude); EXPECT_FALSE(it); @@ -1088,7 +1107,8 @@ TEST(TestValueIterator, TestExcludeRootOfKeyPath) std::unordered_set persistent = {&root.array[0]}; exclusion::object_set_ref exclude{persistent, {}}; - ddwaf::object::value_iterator it(&root, {"parent", "child"}, exclude); + std::vector key_path{"parent", "child"}; + ddwaf::object::value_iterator it(&root, key_path, exclude); EXPECT_FALSE(it);