From 5899c359e743f593c6972d6c46f908b1dc36ca19 Mon Sep 17 00:00:00 2001 From: Anil Mahtani <929854+Anilm3@users.noreply.github.com> Date: Mon, 25 Nov 2024 11:25:15 +0000 Subject: [PATCH] Add copy_data processor as a mechanism to extract request data into derivatives --- .gitignore | 1 + src/builder/processor_builder.cpp | 11 +++++++++ src/builder/processor_builder.hpp | 2 +- src/parser/processor_parser.cpp | 8 +++++- src/processor/copy_data.hpp | 41 +++++++++++++++++++++++++++++++ src/utils.cpp | 9 ++++--- src/utils.hpp | 2 +- 7 files changed, 67 insertions(+), 7 deletions(-) create mode 100644 src/processor/copy_data.hpp diff --git a/.gitignore b/.gitignore index 699ea3a7e..cb82b5acf 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,4 @@ perf/test_files/breakdown.numbers .vscode *.swp *.swo +*.swn diff --git a/src/builder/processor_builder.cpp b/src/builder/processor_builder.cpp index c5f61a026..9ea30ea03 100644 --- a/src/builder/processor_builder.cpp +++ b/src/builder/processor_builder.cpp @@ -12,6 +12,7 @@ #include "indexer.hpp" #include "parser/specification.hpp" #include "processor/base.hpp" +#include "processor/copy_data.hpp" #include "processor/extract_schema.hpp" #include "processor/fingerprint.hpp" #include "scanner.hpp" @@ -81,6 +82,14 @@ template <> struct typed_processor_builder { } }; +template <> struct typed_processor_builder { + std::shared_ptr build(const auto &spec) + { + return std::make_shared( + spec.id, spec.expr, spec.mappings, spec.evaluate, spec.output); + } +}; + template concept has_build_with_scanners = requires(typed_processor_builder b, Spec spec, Scanners scanners) { @@ -117,6 +126,8 @@ template return build_with_type(*this, scanners); case processor_type::session_fingerprint: return build_with_type(*this, scanners); + case processor_type::copy_data: + return build_with_type(*this, scanners); default: break; } diff --git a/src/builder/processor_builder.hpp b/src/builder/processor_builder.hpp index 0ab3be0f0..47792d5ac 100644 --- a/src/builder/processor_builder.hpp +++ b/src/builder/processor_builder.hpp @@ -18,11 +18,11 @@ namespace ddwaf { enum class processor_type : unsigned { extract_schema, - // Reserved http_endpoint_fingerprint, http_network_fingerprint, http_header_fingerprint, session_fingerprint, + copy_data, }; struct processor_builder { diff --git a/src/parser/processor_parser.cpp b/src/parser/processor_parser.cpp index a720624a8..51f6878cf 100644 --- a/src/parser/processor_parser.cpp +++ b/src/parser/processor_parser.cpp @@ -18,6 +18,7 @@ #include "parser/parser.hpp" #include "parser/specification.hpp" #include "processor/base.hpp" +#include "processor/copy_data.hpp" #include "processor/extract_schema.hpp" #include "processor/fingerprint.hpp" #include "semver.hpp" @@ -106,6 +107,8 @@ processor_container parse_processors( type = processor_type::http_header_fingerprint; } else if (generator_id == "session_fingerprint") { type = processor_type::session_fingerprint; + } else if (generator_id == "copy_data") { + type = processor_type::copy_data; } else { DDWAF_WARN("Unknown generator: {}", generator_id); info.add_failed(id, "unknown generator '" + generator_id + "'"); @@ -130,9 +133,12 @@ processor_container parse_processors( } else if (type == processor_type::http_network_fingerprint) { mappings = parse_processor_mappings( mappings_vec, addresses, http_network_fingerprint::param_names); - } else { + } else if (type == processor_type::session_fingerprint) { mappings = parse_processor_mappings( mappings_vec, addresses, session_fingerprint::param_names); + } else { + mappings = parse_processor_mappings( + mappings_vec, addresses, copy_data_processor::param_names); } std::vector scanners; diff --git a/src/processor/copy_data.hpp b/src/processor/copy_data.hpp new file mode 100644 index 000000000..79307b419 --- /dev/null +++ b/src/processor/copy_data.hpp @@ -0,0 +1,41 @@ +// 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 "processor/base.hpp" + +namespace ddwaf { + +class copy_data_processor : public structured_processor { +public: + static constexpr std::array param_names{"input"}; + + copy_data_processor(std::string id, std::shared_ptr expr, + std::vector mappings, bool evaluate, bool output) + : structured_processor( + std::move(id), std::move(expr), std::move(mappings), evaluate, output) + {} + + // NOLINTNEXTLINE(readability-convert-member-functions-to-static) + std::pair eval_impl( + const unary_argument &input, processor_cache & /*cache*/, + ddwaf::timer & /*deadline*/) const + { + if (input.value == nullptr) { + return {}; + } + + // Objects generated by this post-processors must always be non-ephemeral + // as there would be no way to distinguish between derivatives generated + // across multiple calls. + return {ddwaf::object::clone(input.value), object_store::attribute::none}; + } +}; + +} // namespace ddwaf diff --git a/src/utils.cpp b/src/utils.cpp index 354c630ff..474517dd7 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -5,7 +5,7 @@ // Copyright 2021 Datadog, Inc. #include -#include +#include #include #include "ddwaf.h" @@ -46,17 +46,18 @@ void clone_helper(const ddwaf_object &source, ddwaf_object &destination) } } -ddwaf_object clone(ddwaf_object *input) +ddwaf_object clone(const ddwaf_object *input) { ddwaf_object tmp; ddwaf_object_invalid(&tmp); ddwaf_object copy; - std::list> queue; + std::deque> queue; clone_helper(*input, copy); if (is_container(input)) { - queue.emplace_front(input, ©); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast) + queue.emplace_front(const_cast(input), ©); } while (!queue.empty()) { diff --git a/src/utils.hpp b/src/utils.hpp index 0c53cdad0..cbbf97f7b 100644 --- a/src/utils.hpp +++ b/src/utils.hpp @@ -112,7 +112,7 @@ inline bool is_invalid_or_null(const ddwaf_object *obj) return obj != nullptr && (obj->type == DDWAF_OBJ_INVALID || obj->type == DDWAF_OBJ_NULL); } -ddwaf_object clone(ddwaf_object *input); +ddwaf_object clone(const ddwaf_object *input); } // namespace object // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)