#pragma once
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
#include "action_mapper.hpp"
#include "exclusion/common.hpp"
#include "exclusion/object_filter.hpp"
#include "expression.hpp"
#include "indexed_multivector.hpp"
#include "obfuscator.hpp"
#include "processor/base.hpp"
#include "rule.hpp"
#include "scanner.hpp"
#include "utils.hpp"
namespace ddwaf {
struct rule_spec {
bool enabled;
rule_flags flags;
core_rule::source_type source;
std::string name;
std::unordered_map<std::string, std::string> tags;
std::shared_ptr<expression> expr;
std::vector<std::string> actions;
std::vector<rule_attribute> attributes;
};
enum class reference_type : uint8_t { none, id, tags };
struct reference_spec {
reference_type type;
std::string ref_id;
std::unordered_map<std::string, std::string> tags;
};
struct rule_override_spec {
reference_type type;
std::optional<bool> enabled;
std::optional<std::vector<std::string>> actions;
std::vector<reference_spec> targets;
std::unordered_map<std::string, std::string> tags;
};
struct rule_filter_spec {
std::shared_ptr<expression> expr;
std::vector<reference_spec> targets;
filter_mode on_match;
std::string custom_action;
};
struct input_filter_spec {
std::shared_ptr<expression> expr;
std::shared_ptr<object_filter> filter;
std::vector<reference_spec> targets;
};
enum class processor_type : uint8_t {
extract_schema,
http_endpoint_fingerprint,
http_network_fingerprint,
http_header_fingerprint,
session_fingerprint,
jwt_decode,
uri_parse,
};
struct processor_spec {
processor_type type;
std::shared_ptr<expression> expr;
std::vector<processor_mapping> mappings;
struct {
std::vector<reference_spec> include;
std::vector<reference_spec> exclude;
} scanners;
bool evaluate{false};
bool output{true};
};
struct processor_override_spec {
std::vector<reference_spec> targets;
struct {
std::vector<reference_spec> include;
std::vector<reference_spec> exclude;
} scanners;
};
enum class data_type : uint8_t { unknown, data_with_expiration, ip_with_expiration };
struct data_spec {
using value_type = std::pair<std::string, uint64_t>;
data_type type{data_type::unknown};
indexed_multivector<std::string, value_type> values;
};
struct action_spec {
action_type type;
std::string type_str;
std::unordered_map<std::string, scalar_type> parameters;
};
enum class change_set : uint16_t {
none = 0,
rules = 1,
custom_rules = 2,
rule_overrides = 4,
filters = 8,
rule_data = 16,
processors = 32,
processor_overrides = 64,
scanners = 128,
actions = 256,
exclusion_data = 512,
obfuscator = 1024,
};
constexpr change_set operator|(change_set lhs, change_set rhs)
{
return static_cast<change_set>(static_cast<std::underlying_type_t<change_set>>(lhs) |
static_cast<std::underlying_type_t<change_set>>(rhs));
}
constexpr change_set &operator|=(change_set &lhs, change_set rhs) { return lhs = lhs | rhs; }
constexpr change_set operator&(change_set lhs, change_set rhs)
{
return static_cast<change_set>(static_cast<std::underlying_type_t<change_set>>(lhs) &
static_cast<std::underlying_type_t<change_set>>(rhs));
}
constexpr change_set &operator&=(change_set &lhs, change_set rhs) { return lhs = lhs & rhs; }
constexpr bool contains(change_set set, change_set opt) { return (set & opt) != change_set::none; }
struct configuration_change_spec {
[[nodiscard]] bool empty() const { return content == change_set::none; }
change_set content{change_set::none};
std::unordered_set<std::string> base_rules;
std::unordered_set<std::string> user_rules;
std::vector<std::pair<std::string, std::string>> rule_data;
std::unordered_set<std::string> rule_overrides_by_id;
std::unordered_set<std::string> rule_overrides_by_tags;
std::unordered_set<std::string> rule_filters;
std::unordered_set<std::string> input_filters;
std::vector<std::pair<std::string, std::string>> exclusion_data;
std::unordered_set<std::string> processors;
std::unordered_set<std::string> processor_overrides;
std::unordered_set<std::string> scanners;
std::unordered_set<std::string> actions;
};
struct configuration_spec {
std::unordered_map<std::string, rule_spec> base_rules;
std::unordered_map<std::string, rule_spec> user_rules;
std::unordered_map<std::string, data_spec> rule_data;
std::unordered_map<std::string, rule_override_spec> rule_overrides_by_id;
std::unordered_map<std::string, rule_override_spec> rule_overrides_by_tags;
std::unordered_map<std::string, rule_filter_spec> rule_filters;
std::unordered_map<std::string, input_filter_spec> input_filters;
std::unordered_map<std::string, data_spec> exclusion_data;
std::unordered_map<std::string, processor_spec> processors;
std::unordered_map<std::string, processor_override_spec> processor_overrides;
std::unordered_map<std::string, scanner> scanners;
std::unordered_map<std::string, action_spec> actions;
std::shared_ptr<match_obfuscator> obfuscator;
};
}