diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d745ba44..71ca3c7c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,7 +66,7 @@ jobs: env: CC: ${{ matrix.compiler.cc }} CXX: ${{ matrix.compiler.cxx }} - run: ./configure ${{ matrix.platform.configure }} ${{ matrix.configure.opt }} + run: ./configure ${{ matrix.platform.configure }} ${{ matrix.configure.opt }} --enable-assertions=yes - uses: ammaraskar/gcc-problem-matcher@master - name: make run: make -j `nproc` @@ -78,7 +78,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-12] + os: [macos-14] configure: - {label: "with parser generation", opt: "--enable-parser-generation" } - {label: "wo curl", opt: "--without-curl" } @@ -91,10 +91,12 @@ jobs: - {label: "with pcre2", opt: "--with-pcre2" } steps: - name: Setup Dependencies - # autoconf, curl, pcre2 not installed because they're already + # curl, pcre2 not installed because they're already # included in the image run: | - brew install automake \ + brew install autoconf \ + automake \ + libtool \ yajl \ lmdb \ lua \ @@ -112,7 +114,7 @@ jobs: - name: build.sh run: ./build.sh - name: configure - run: ./configure ${{ matrix.configure.opt }} + run: ./configure ${{ matrix.configure.opt }} --enable-assertions=yes - uses: ammaraskar/gcc-problem-matcher@master - name: make run: make -j `sysctl -n hw.logicalcpu` @@ -130,11 +132,11 @@ jobs: configuration: [Release] configure: - {label: "full", opt: "" } - - {label: "wo curl", opt: "-DWITHOUT_CURL=ON" } - - {label: "wo lmdb", opt: "-DWITHOUT_LMDB=ON" } - - {label: "wo lua", opt: "-DWITHOUT_LUA=ON" } - - {label: "wo maxmind", opt: "-DWITHOUT_MAXMIND=ON" } - - {label: "wo libxml", opt: "-WITHOUT_LIBXML2=ON" } + - {label: "wo curl", opt: "-DWITH_CURL=OFF" } + - {label: "wo lua", opt: "-DWITH_LUA=OFF" } + - {label: "wo maxmind", opt: "-DWITH_MAXMIND=OFF" } + - {label: "wo libxml", opt: "-DWITH_LIBXML2=OFF" } + - {label: "with lmdb", opt: "-DWITH_LMDB=ON" } steps: - uses: actions/checkout@v4 with: diff --git a/.gitignore b/.gitignore index be0de155..9515fb56 100644 --- a/.gitignore +++ b/.gitignore @@ -50,6 +50,7 @@ ltmain.sh examples/simple_example_using_c/test /tools/rules-check/modsec-rules-check examples/multiprocess_c/multi +examples/multithread/multithread examples/reading_logs_via_rule_message/simple_request examples/reading_logs_with_offset/read examples/using_bodies_in_chunks/simple_request diff --git a/README.md b/README.md index 36201735..704967d6 100644 --- a/README.md +++ b/README.md @@ -236,10 +236,16 @@ CFLAGS to disable the compilation optimization parameters: ```shell $ export CFLAGS="-g -O0" $ ./build.sh -$ ./configure +$ ./configure --enable-assertions=yes $ make $ sudo make install ``` +"Assertions allow us to document assumptions and to spot violations early in the +development process. What is more, assertions allow us to spot violations with a +minimum of effort." https://dl.acm.org/doi/pdf/10.1145/240964.240969 + +It is recommended to use assertions where applicable, and to enable them with +'--enable-assertions=yes' during the testing and debugging workflow. ### Benchmarking diff --git a/build/ax_cxx_compile_stdcxx.m4 b/build/ax_cxx_compile_stdcxx.m4 new file mode 100644 index 00000000..8edf5152 --- /dev/null +++ b/build/ax_cxx_compile_stdcxx.m4 @@ -0,0 +1,1018 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the specified +# version of the C++ standard. If necessary, add switches to CXX and +# CXXCPP to enable support. VERSION may be '11', '14', '17', or '20' for +# the respective C++ standard version. +# +# The second argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for no added switch, and then for an extended mode. +# +# The third argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline support for the specified C++ standard is +# required and that the macro should error out if no mode with that +# support is found. If specified 'optional', then configuration proceeds +# regardless, after defining HAVE_CXX${VERSION} if and only if a +# supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +# Copyright (c) 2015 Paul Norman +# Copyright (c) 2015 Moritz Klammler +# Copyright (c) 2016, 2018 Krzesimir Nowak +# Copyright (c) 2019 Enji Cooper +# Copyright (c) 2020 Jason Merrill +# Copyright (c) 2021 Jörn Heusipp +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 18 + +dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro +dnl (serial version number 13). + +AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl + m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], + [$1], [14], [ax_cxx_compile_alternatives="14 1y"], + [$1], [17], [ax_cxx_compile_alternatives="17 1z"], + [$1], [20], [ax_cxx_compile_alternatives="20"], + [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$2], [], [], + [$2], [ext], [], + [$2], [noext], [], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], + [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], + [$3], [optional], [ax_cxx_compile_cxx$1_required=false], + [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) + AC_LANG_PUSH([C++])dnl + ac_success=no + + m4_if([$2], [], [dnl + AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, + ax_cv_cxx_compile_cxx$1, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [ax_cv_cxx_compile_cxx$1=yes], + [ax_cv_cxx_compile_cxx$1=no])]) + if test x$ax_cv_cxx_compile_cxx$1 = xyes; then + ac_success=yes + fi]) + + m4_if([$2], [noext], [], [dnl + if test x$ac_success = xno; then + for alternative in ${ax_cxx_compile_alternatives}; do + switch="-std=gnu++${alternative}" + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + fi]) + + m4_if([$2], [ext], [], [dnl + if test x$ac_success = xno; then + dnl HP's aCC needs +std=c++11 according to: + dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf + dnl Cray's crayCC needs "-h std=c++11" + dnl MSVC needs -std:c++NN for C++17 and later (default is C++14) + for alternative in ${ax_cxx_compile_alternatives}; do + for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}" MSVC; do + if test x"$switch" = xMSVC; then + dnl AS_TR_SH maps both `:` and `=` to `_` so -std:c++17 would collide + dnl with -std=c++17. We suffix the cache variable name with _MSVC to + dnl avoid this. + switch=-std:c++${alternative} + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_${switch}_MSVC]) + else + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + fi + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + if test x$ac_success = xyes; then + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx$1_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) + fi + fi + if test x$ac_success = xno; then + HAVE_CXX$1=0 + AC_MSG_NOTICE([No compiler with C++$1 support was found]) + else + HAVE_CXX$1=1 + AC_DEFINE(HAVE_CXX$1,1, + [define if the compiler supports basic C++$1 syntax]) + fi + AC_SUBST(HAVE_CXX$1) +]) + + +dnl Test body for checking C++11 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 +) + +dnl Test body for checking C++14 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 +) + +dnl Test body for checking C++17 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 +) + +dnl Test body for checking C++20 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_20 +) + + +dnl Tests for new features in C++11 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +// MSVC always sets __cplusplus to 199711L in older versions; newer versions +// only set it correctly if /Zc:__cplusplus is specified as well as a +// /std:c++NN switch: +// https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ +#elif __cplusplus < 201103L && !defined _MSC_VER + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual ~Base() {} + virtual void f() {} + }; + + struct Derived : public Base + { + virtual ~Derived() override {} + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check single_type; + typedef check> double_type; + typedef check>> triple_type; + typedef check>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template + struct sum; + + template + struct sum + { + static constexpr auto value = N0 + sum::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { func(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + +]]) + + +dnl Tests for new features in C++14 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L && !defined _MSC_VER + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same::value, ""); + static_assert(is_same::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + +]]) + + +dnl Tests for new features in C++17 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ + +// If the compiler admits that it is not ready for C++17, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201703L && !defined _MSC_VER + +#error "This is not a C++17 compiler" + +#else + +#include +#include +#include + +namespace cxx17 +{ + + namespace test_constexpr_lambdas + { + + constexpr int foo = [](){return 42;}(); + + } + + namespace test::nested_namespace::definitions + { + + } + + namespace test_fold_expression + { + + template + int multiply(Args... args) + { + return (args * ... * 1); + } + + template + bool all(Args... args) + { + return (args && ...); + } + + } + + namespace test_extended_static_assert + { + + static_assert (true); + + } + + namespace test_auto_brace_init_list + { + + auto foo = {5}; + auto bar {5}; + + static_assert(std::is_same, decltype(foo)>::value); + static_assert(std::is_same::value); + } + + namespace test_typename_in_template_template_parameter + { + + template typename X> struct D; + + } + + namespace test_fallthrough_nodiscard_maybe_unused_attributes + { + + int f1() + { + return 42; + } + + [[nodiscard]] int f2() + { + [[maybe_unused]] auto unused = f1(); + + switch (f1()) + { + case 17: + f1(); + [[fallthrough]]; + case 42: + f1(); + } + return f1(); + } + + } + + namespace test_extended_aggregate_initialization + { + + struct base1 + { + int b1, b2 = 42; + }; + + struct base2 + { + base2() { + b3 = 42; + } + int b3; + }; + + struct derived : base1, base2 + { + int d; + }; + + derived d1 {{1, 2}, {}, 4}; // full initialization + derived d2 {{}, {}, 4}; // value-initialized bases + + } + + namespace test_general_range_based_for_loop + { + + struct iter + { + int i; + + int& operator* () + { + return i; + } + + const int& operator* () const + { + return i; + } + + iter& operator++() + { + ++i; + return *this; + } + }; + + struct sentinel + { + int i; + }; + + bool operator== (const iter& i, const sentinel& s) + { + return i.i == s.i; + } + + bool operator!= (const iter& i, const sentinel& s) + { + return !(i == s); + } + + struct range + { + iter begin() const + { + return {0}; + } + + sentinel end() const + { + return {5}; + } + }; + + void f() + { + range r {}; + + for (auto i : r) + { + [[maybe_unused]] auto v = i; + } + } + + } + + namespace test_lambda_capture_asterisk_this_by_value + { + + struct t + { + int i; + int foo() + { + return [*this]() + { + return i; + }(); + } + }; + + } + + namespace test_enum_class_construction + { + + enum class byte : unsigned char + {}; + + byte foo {42}; + + } + + namespace test_constexpr_if + { + + template + int f () + { + if constexpr(cond) + { + return 13; + } + else + { + return 42; + } + } + + } + + namespace test_selection_statement_with_initializer + { + + int f() + { + return 13; + } + + int f2() + { + if (auto i = f(); i > 0) + { + return 3; + } + + switch (auto i = f(); i + 4) + { + case 17: + return 2; + + default: + return 1; + } + } + + } + + namespace test_template_argument_deduction_for_class_templates + { + + template + struct pair + { + pair (T1 p1, T2 p2) + : m1 {p1}, + m2 {p2} + {} + + T1 m1; + T2 m2; + }; + + void f() + { + [[maybe_unused]] auto p = pair{13, 42u}; + } + + } + + namespace test_non_type_auto_template_parameters + { + + template + struct B + {}; + + B<5> b1; + B<'a'> b2; + + } + + namespace test_structured_bindings + { + + int arr[2] = { 1, 2 }; + std::pair pr = { 1, 2 }; + + auto f1() -> int(&)[2] + { + return arr; + } + + auto f2() -> std::pair& + { + return pr; + } + + struct S + { + int x1 : 2; + volatile double y1; + }; + + S f3() + { + return {}; + } + + auto [ x1, y1 ] = f1(); + auto& [ xr1, yr1 ] = f1(); + auto [ x2, y2 ] = f2(); + auto& [ xr2, yr2 ] = f2(); + const auto [ x3, y3 ] = f3(); + + } + + namespace test_exception_spec_type_system + { + + struct Good {}; + struct Bad {}; + + void g1() noexcept; + void g2(); + + template + Bad + f(T*, T*); + + template + Good + f(T1*, T2*); + + static_assert (std::is_same_v); + + } + + namespace test_inline_variables + { + + template void f(T) + {} + + template inline T g(T) + { + return T{}; + } + + template<> inline void f<>(int) + {} + + template<> int g<>(int) + { + return 5; + } + + } + +} // namespace cxx17 + +#endif // __cplusplus < 201703L && !defined _MSC_VER + +]]) + + +dnl Tests for new features in C++20 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[ + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 202002L && !defined _MSC_VER + +#error "This is not a C++20 compiler" + +#else + +#include + +namespace cxx20 +{ + +// As C++20 supports feature test macros in the standard, there is no +// immediate need to actually test for feature availability on the +// Autoconf side. + +} // namespace cxx20 + +#endif // __cplusplus < 202002L && !defined _MSC_VER + +]]) diff --git a/build/ax_cxx_compile_stdcxx_11.m4 b/build/ax_cxx_compile_stdcxx_11.m4 deleted file mode 100644 index e76fd605..00000000 --- a/build/ax_cxx_compile_stdcxx_11.m4 +++ /dev/null @@ -1,171 +0,0 @@ -# ============================================================================ -# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html -# ============================================================================ -# -# SYNOPSIS -# -# AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional]) -# -# DESCRIPTION -# -# Check for baseline language coverage in the compiler for the C++11 -# standard; if necessary, add switches to CXXFLAGS to enable support. -# -# The first argument, if specified, indicates whether you insist on an -# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. -# -std=c++11). If neither is specified, you get whatever works, with -# preference for an extended mode. -# -# The second argument, if specified 'mandatory' or if left unspecified, -# indicates that baseline C++11 support is required and that the macro -# should error out if no mode with that support is found. If specified -# 'optional', then configuration proceeds regardless, after defining -# HAVE_CXX11 if and only if a supporting mode is found. -# -# LICENSE -# -# Copyright (c) 2008 Benjamin Kosnik -# Copyright (c) 2012 Zack Weinberg -# Copyright (c) 2013 Roy Stogner -# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov -# Copyright (c) 2015 Paul Norman -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 12 - -m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [[ - template - struct check - { - static_assert(sizeof(int) <= sizeof(T), "not big enough"); - }; - - struct Base { - virtual void f() {} - }; - struct Child : public Base { - virtual void f() override {} - }; - - typedef check> right_angle_brackets; - - int a; - decltype(a) b; - - typedef check check_type; - check_type c; - check_type&& cr = static_cast(c); - - auto d = a; - auto l = [](){}; - // Prevent Clang error: unused variable 'l' [-Werror,-Wunused-variable] - struct use_l { use_l() { l(); } }; - - // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae - // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function because of this - namespace test_template_alias_sfinae { - struct foo {}; - - template - using member = typename T::member_type; - - template - void func(...) {} - - template - void func(member*) {} - - void test(); - - void test() { - func(0); - } - } - - // Check for C++11 attribute support - void noret [[noreturn]] () { throw 0; } -]]) - -AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl - m4_if([$1], [], [], - [$1], [ext], [], - [$1], [noext], [], - [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl - m4_if([$2], [], [ax_cxx_compile_cxx11_required=true], - [$2], [mandatory], [ax_cxx_compile_cxx11_required=true], - [$2], [optional], [ax_cxx_compile_cxx11_required=false], - [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])]) - AC_LANG_PUSH([C++])dnl - ac_success=no - AC_CACHE_CHECK(whether $CXX supports C++11 features by default, - ax_cv_cxx_compile_cxx11, - [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], - [ax_cv_cxx_compile_cxx11=yes], - [ax_cv_cxx_compile_cxx11=no])]) - if test x$ax_cv_cxx_compile_cxx11 = xyes; then - ac_success=yes - fi - - m4_if([$1], [noext], [], [dnl - if test x$ac_success = xno; then - for switch in -std=gnu++11 -std=gnu++0x; do - cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) - AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, - $cachevar, - [ac_save_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS $switch" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], - [eval $cachevar=yes], - [eval $cachevar=no]) - CXXFLAGS="$ac_save_CXXFLAGS"]) - if eval test x\$$cachevar = xyes; then - CXXFLAGS="$CXXFLAGS $switch" - ac_success=yes - break - fi - done - fi]) - - m4_if([$1], [ext], [], [dnl - if test x$ac_success = xno; then - dnl HP's aCC needs +std=c++11 according to: - dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf - for switch in -std=c++11 -std=c++0x +std=c++11; do - cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) - AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, - $cachevar, - [ac_save_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS $switch" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], - [eval $cachevar=yes], - [eval $cachevar=no]) - CXXFLAGS="$ac_save_CXXFLAGS"]) - if eval test x\$$cachevar = xyes; then - CXXFLAGS="$CXXFLAGS $switch" - ac_success=yes - break - fi - done - fi]) - AC_LANG_POP([C++]) - if test x$ax_cxx_compile_cxx11_required = xtrue; then - if test x$ac_success = xno; then - AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.]) - fi - else - if test x$ac_success = xno; then - HAVE_CXX11=0 - AC_MSG_NOTICE([No compiler with C++11 support was found]) - else - HAVE_CXX11=1 - AC_DEFINE(HAVE_CXX11,1, - [define if the compiler supports basic C++11 syntax]) - fi - - AC_SUBST(HAVE_CXX11) - fi -]) diff --git a/build/pcre.m4 b/build/pcre.m4 index 5575797f..4d991232 100644 --- a/build/pcre.m4 +++ b/build/pcre.m4 @@ -27,30 +27,41 @@ else AC_MSG_CHECKING([for libpcre config script]) - for x in ${test_paths}; do - dnl # Determine if the script was specified and use it directly - if test ! -d "$x" -a -e "$x"; then - PCRE_CONFIG=$x - pcre_path="no" - break - fi + AC_CHECK_PROG([PCRE_CONFIG_IN_ENV], [pcre-config], [yes], [no]) - dnl # Try known config script names/locations - for PCRE_CONFIG in pcre-config; do - if test -e "${x}/bin/${PCRE_CONFIG}"; then - pcre_path="${x}/bin" + if test "$PCRE_CONFIG_IN_ENV" = "yes"; then + AC_MSG_NOTICE([pcre-config found in envinronment]) + + PCRE_CONFIG=pcre-config + pcre_path="no" + else + AC_MSG_NOTICE([pcre-config not found in environment. checking known paths]) + + for x in ${test_paths}; do + dnl # Determine if the script was specified and use it directly + if test ! -d "$x" -a -e "$x"; then + PCRE_CONFIG=$x + pcre_path="no" break - elif test -e "${x}/${PCRE_CONFIG}"; then - pcre_path="${x}" + fi + + dnl # Try known config script names/locations + for PCRE_CONFIG in pcre-config; do + if test -e "${x}/bin/${PCRE_CONFIG}"; then + pcre_path="${x}/bin" + break + elif test -e "${x}/${PCRE_CONFIG}"; then + pcre_path="${x}" + break + else + pcre_path="" + fi + done + if test -n "$pcre_path"; then break - else - pcre_path="" fi done - if test -n "$pcre_path"; then - break - fi - done + fi if test -n "${pcre_path}"; then if test "${pcre_path}" != "no"; then diff --git a/build/win32/CMakeLists.txt b/build/win32/CMakeLists.txt index bdb9a45f..cebf4c9b 100644 --- a/build/win32/CMakeLists.txt +++ b/build/win32/CMakeLists.txt @@ -2,13 +2,13 @@ cmake_minimum_required(VERSION 3.24) set(BASE_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) -option(WITHOUT_LMDB "Include LMDB support" OFF) -option(WITHOUT_LUA "Include LUA support" OFF) -option(WITHOUT_LIBXML2 "Include LibXML2 support" OFF) -option(WITHOUT_MAXMIND "Include MaxMind support" OFF) -option(WITHOUT_CURL "Include CURL support" OFF) +option(WITH_LMDB "Include LMDB support" OFF) +option(WITH_LUA "Include LUA support" ON) +option(WITH_LIBXML2 "Include LibXML2 support" ON) +option(WITH_MAXMIND "Include MaxMind support" ON) +option(WITH_CURL "Include CURL support" ON) -option(USE_ASAN "Build with Address Sanitizer" OFF) +option(USE_ASAN "Build with Address Sanitizer" OFF) # common compiler settings @@ -93,24 +93,23 @@ set(HAVE_SSDEEP 0) # should always be zero, no conan package available macro(enable_feature flag option) if(${option}) - set(${flag} 0) + set(${flag} 1) # ON else() - set(${flag} 1) + set(${flag} 0) # OFF endif() endmacro() -enable_feature(HAVE_LMDB ${WITHOUT_LMDB}) -enable_feature(HAVE_LUA ${WITHOUT_LUA}) -enable_feature(HAVE_LIBXML2 ${WITHOUT_LIBXML2}) -enable_feature(HAVE_MAXMIND ${WITHOUT_MAXMIND}) -enable_feature(HAVE_CURL ${WITHOUT_CURL}) +enable_feature(HAVE_LMDB ${WITH_LMDB}) +enable_feature(HAVE_LUA ${WITH_LUA}) +enable_feature(HAVE_LIBXML2 ${WITH_LIBXML2}) +enable_feature(HAVE_MAXMIND ${WITH_MAXMIND}) +enable_feature(HAVE_CURL ${WITH_CURL}) include(${CMAKE_CURRENT_LIST_DIR}/ConfigureChecks.cmake) configure_file(config.h.cmake ${BASE_DIR}/src/config.h) find_package(PCRE2 REQUIRED) -find_package(PThreads4W REQUIRED) find_package(Poco REQUIRED) find_package(dirent REQUIRED) # used only by tests (check dirent::dirent refernces) @@ -139,7 +138,7 @@ add_library(libModSecurity SHARED ${libModSecuritySources}) target_compile_definitions(libModSecurity PRIVATE WITH_PCRE2) target_include_directories(libModSecurity PRIVATE ${BASE_DIR} ${BASE_DIR}/headers ${BASE_DIR}/others ${MBEDTLS_DIR}/include) -target_link_libraries(libModSecurity PRIVATE pcre2::pcre2 pthreads4w::pthreads4w libinjection mbedcrypto Poco::Poco Iphlpapi.lib) +target_link_libraries(libModSecurity PRIVATE pcre2::pcre2 libinjection mbedcrypto Poco::Poco Iphlpapi.lib) macro(add_package_dependency project compile_definition link_library flag) if(${flag}) @@ -255,12 +254,15 @@ setExampleTargetProperties(using_bodies_in_chunks) # reading_logs_via_rule_message add_executable(reading_logs_via_rule_message ${BASE_DIR}/examples/reading_logs_via_rule_message/simple_request.cc) setExampleTargetProperties(reading_logs_via_rule_message) -target_link_libraries(reading_logs_via_rule_message PRIVATE libModSecurity pthreads4w::pthreads4w) # reading_logs_with_offset add_executable(reading_logs_with_offset ${BASE_DIR}/examples/reading_logs_with_offset/read.cc) setExampleTargetProperties(reading_logs_with_offset) +# multithread +add_executable(multithread ${BASE_DIR}/examples/multithread/multithread.cc) +setExampleTargetProperties(multithread) + # tools # diff --git a/build/win32/README.md b/build/win32/README.md index 7b70cfbd..85fd868e 100644 --- a/build/win32/README.md +++ b/build/win32/README.md @@ -51,6 +51,7 @@ Built files will be located in the directory: `build\win32\build\[build_configur * `using_bodies_in_chunks.exe` * `reading_logs_via_rule_message.exe` * `reading_logs_with_offset.exe` + * `multithread.exe` * Executable files for tools * `rules_check.exe` diff --git a/build/win32/conanfile.txt b/build/win32/conanfile.txt index b1a69821..b8f9721d 100644 --- a/build/win32/conanfile.txt +++ b/build/win32/conanfile.txt @@ -1,7 +1,6 @@ [requires] yajl/2.1.0 pcre2/10.42 -pthreads4w/3.0.0 libxml2/2.12.6 lua/5.4.6 libcurl/8.6.0 diff --git a/build/yajl.m4 b/build/yajl.m4 index dd695715..e050c084 100644 --- a/build/yajl.m4 +++ b/build/yajl.m4 @@ -78,6 +78,29 @@ else # fi fi +# FIX: if the include directory in CFLAGS ends with "include/yajl", +# remove the suffix "/yajl". the library header files are included +# using the prefix (for example, #include ), and +# this is even the case for the library itself (for example, +# yajl_tree.h includes yajl/yajl_common.h). + +new_cflags="" + +for flag in $YAJL_CFLAGS; do + case "$flag" in + -I*/include/yajl) + new_flag="${flag%/yajl}" + new_cflags="$new_cflags $new_flag" + ;; + *) + new_cflags="$new_cflags $flag" + ;; + esac +done + +YAJL_CFLAGS="$new_cflags" + + if test -z "${YAJL_LDADD}"; then if test -z "${YAJL_MANDATORY}"; then if test -z "${YAJL_DISABLED}"; then diff --git a/configure.ac b/configure.ac index f69c5c61..11cef0b6 100644 --- a/configure.ac +++ b/configure.ac @@ -52,8 +52,8 @@ AC_PROG_MAKE_SET PKG_PROG_PKG_CONFIG -# Check if the compiler is c++17 compatible. -# AX_CXX_COMPILE_STDCXX_17(,mandatory) +# Set C++ standard version and check if compiler supports it. +AX_CXX_COMPILE_STDCXX(17, noext, mandatory) # Check for libinjection if ! test -f "${srcdir}/others/libinjection/src/libinjection_html5.c"; then @@ -164,8 +164,8 @@ AC_CHECK_HEADERS([iostream]) AC_CHECK_HEADERS([sys/utsname.h]) -# ?? -LT_INIT([dlopen]) +# Initialize libtool +LT_INIT # Identify platform AC_CANONICAL_HOST @@ -248,6 +248,17 @@ AC_SUBST([MSC_VERSION]) MSC_GIT_VERSION=msc_version_git AC_SUBST([MSC_GIT_VERSION]) +AC_ARG_ENABLE(assertions, + [AS_HELP_STRING([--enable-assertions],[Turn on assertions feature: undefine NDEBUG])], + + [case "${enableval}" in + yes) assertions=true ;; + no) assertions=false ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-assertions) ;; + esac], + + [assertions=false] + ) AC_ARG_ENABLE(debug-logs, [AS_HELP_STRING([--disable-debug-logs],[Turn off the SecDebugLog feature])], @@ -305,23 +316,6 @@ AC_ARG_ENABLE(parser-generation, [buildParser=false] ) -# Mutex -AC_ARG_ENABLE(mutex-on-pm, - [AS_HELP_STRING([--enable-mutex-on-pm],[Treats pm operations as a critical section])], - - [case "${enableval}" in - yes) mutexPm=true ;; - no) mutexPm=false ;; - *) AC_MSG_ERROR(bad value ${enableval} for --enable-mutex-on-pm) ;; - esac], - - [mutexPm=false] - ) -if test "$mutexPm" == "true"; then - MODSEC_MUTEX_ON_PM="-DMUTEX_ON_PM=1" - AC_SUBST(MODSEC_MUTEX_ON_PM) -fi - if test $buildParser = true; then AC_PROG_YACC @@ -377,6 +371,14 @@ if test "$aflFuzzer" == "true"; then GLOBAL_CPPFLAGS="$GLOBAL_CPPFLAGS $FUZZ_CPPCFLAGS" $buildExamples = false fi + +case $assertions in + false) ASSERTIONS_CPPCFLAGS="-DNDEBUG" ;; + true) ASSERTIONS_CPPCFLAGS="-UNDEBUG" ;; + *) AC_MSG_ERROR(bad value ${assertions} for assertions) ;; +esac +GLOBAL_CPPFLAGS="$GLOBAL_CPPFLAGS $ASSERTIONS_CPPCFLAGS" + AC_SUBST(GLOBAL_LDADD) AC_SUBST(GLOBAL_CPPFLAGS) @@ -404,6 +406,7 @@ AM_COND_IF([EXAMPLES], examples/Makefile \ examples/simple_example_using_c/Makefile \ examples/multiprocess_c/Makefile \ + examples/multithread/Makefile \ examples/reading_logs_with_offset/Makefile \ examples/reading_logs_via_rule_message/Makefile \ examples/using_bodies_in_chunks/Makefile \ @@ -613,6 +616,11 @@ if test $buildTestUtilities = true; then else echo " + Test Utilities ....disabled" fi +if test $assertions = true; then + echo " + Assertions ....enabled" +else + echo " + Assertions ....disabled" +fi if test $debugLogs = true; then echo " + SecDebugLog ....enabled" else diff --git a/examples/Makefile.am b/examples/Makefile.am index 609cb93e..2dbb21ac 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -4,6 +4,7 @@ ACLOCAL_AMFLAGS = -I build SUBDIRS = \ multiprocess_c \ + multithread \ reading_logs_with_offset \ reading_logs_via_rule_message \ simple_example_using_c \ diff --git a/examples/multiprocess_c/Makefile.am b/examples/multiprocess_c/Makefile.am index 85c26487..726d1d90 100644 --- a/examples/multiprocess_c/Makefile.am +++ b/examples/multiprocess_c/Makefile.am @@ -15,7 +15,6 @@ multi_LDFLAGS = \ -L$(top_builddir)/src/.libs/ \ $(GEOIP_LDFLAGS) \ -lmodsecurity \ - -lpthread \ -lm \ -lstdc++ \ $(LUA_LDFLAGS) \ diff --git a/examples/multithread/Makefile.am b/examples/multithread/Makefile.am new file mode 100644 index 00000000..c17b431a --- /dev/null +++ b/examples/multithread/Makefile.am @@ -0,0 +1,55 @@ + + +noinst_PROGRAMS = multithread + +multithread_SOURCES = \ + multithread.cc + +multithread_LDADD = \ + $(CURL_LDADD) \ + $(GEOIP_LDADD) \ + $(GLOBAL_LDADD) \ + $(LIBXML2_LDADD) \ + $(LMDB_LDADD) \ + $(MAXMIND_LDADD) \ + $(LUA_LDADD) \ + $(PCRE_LDADD) \ + $(SSDEEP_LDADD) \ + $(YAJL_LDADD) + +multithread_LDFLAGS = \ + -L$(top_builddir)/src/.libs/ \ + $(GEOIP_LDFLAGS) \ + -lmodsecurity \ + -lpthread \ + -lm \ + -lstdc++ \ + $(LMDB_LDFLAGS) \ + $(LUA_LDFLAGS) \ + $(MAXMIND_LDFLAGS) \ + $(SSDEEP_LDFLAGS) \ + $(YAJL_LDFLAGS) + +multithread_CPPFLAGS = \ + $(GLOBAL_CFLAGS) \ + -I$(top_builddir)/headers \ + -I$(top_builddir) \ + -g \ + -I../others \ + -fPIC \ + -O3 \ + $(CURL_CFLAGS) \ + $(GEOIP_CFLAGS) \ + $(GLOBAL_CPPFLAGS) \ + $(MODSEC_NO_LOGS) \ + $(YAJL_CFLAGS) \ + $(LMDB_CFLAGS) \ + $(LUA_CFLAGS) \ + $(PCRE_CFLAGS) \ + $(LIBXML2_CFLAGS) + + +MAINTAINERCLEANFILES = \ + Makefile.in + + diff --git a/examples/multithread/basic_rules.conf b/examples/multithread/basic_rules.conf new file mode 100644 index 00000000..cff18342 --- /dev/null +++ b/examples/multithread/basic_rules.conf @@ -0,0 +1,14 @@ +SecDebugLog debug.log +SecDebugLogLevel 9 + + +SecRule REQUEST_HEADERS:User-Agent ".*" "id:1,phase:1,t:sha1,t:hexEncode,setvar:tx.ua_hash=%{MATCHED_VAR}" + +SecAction "id:2,phase:2,initcol:ip=%{REMOTE_ADDR}_%{tx.ua_hash}" + +SecRule REQUEST_HEADERS:User-Agent "@rx .*" "id:3,phase:2,setvar:ip.auth_attempt=+1" + +SecRule ARGS:foo "@rx herewego" "id:4,phase:2,setvar:ip.foo=bar,expirevar:ip.foo=2" +#SecRule ARGS:foo "@rx herewego" "id:4,phase:2,setvar:ip.foo=bar" +SecRule IP "@rx bar" "id:5,phase:2,pass" +SecRule IP:auth_attempt "@rx bar" "id:6,phase:2,pass" diff --git a/examples/multithread/multithread.cc b/examples/multithread/multithread.cc new file mode 100644 index 00000000..4233bc71 --- /dev/null +++ b/examples/multithread/multithread.cc @@ -0,0 +1,68 @@ +#include +#include +#include + +#include +#include +#include + +static void process_request(modsecurity::ModSecurity *modsec, modsecurity::RulesSet *rules, int tid) { + std::cout << "Hello World! It's me, thread #" << tid << std::endl; + + for(int i = 0; i != 1'000; i++) { + auto modsecTransaction = std::make_unique(modsec, rules, nullptr); + + modsecTransaction->processConnection("127.0.0.1", 12345, "127.0.0.1", 80); + modsecTransaction->processURI( + "https://www.modsecurity.org/test?foo=herewego", + "GET", "1.1"); + + modsecTransaction->addRequestHeader("User-Agent", + "Basic ModSecurity example"); + modsecTransaction->processRequestHeaders(); + modsecTransaction->processRequestBody(); + + modsecTransaction->addResponseHeader("HTTP/1.1", + "200 OK"); + modsecTransaction->processResponseHeaders(200, "HTTP 1.2"); + modsecTransaction->processResponseBody(); + + modsecTransaction->processLogging(); + + std::this_thread::sleep_for(std::chrono::microseconds(100)); + } + + std::cout << "Thread #" << tid << " exits" << std::endl; +} + +int main (int argc, char *argv[]) { + auto modsec = std::make_unique(); + modsec->setConnectorInformation("ModSecurity-test v0.0.1-alpha (Simple " \ + "example on how to use ModSecurity API"); + + char main_rule_uri[] = "basic_rules.conf"; + auto rules = std::make_unique(); + if (rules->loadFromUri(main_rule_uri) < 0) { + std::cerr << "Problems loading the rules..." << std::endl; + std::cerr << rules->m_parserError.str() << std::endl; + return -1; + } + + constexpr auto NUM_THREADS = 100; + std::array threads; + + for (auto i = 0; i != threads.size(); ++i) { + threads[i] = std::thread( + [&modsec, &rules, i]() { + process_request(modsec.get(), rules.get(), i); + }); + } + + std::this_thread::sleep_for(std::chrono::microseconds(10000)); + + for (auto i = 0; i != threads.size(); ++i) { + threads[i].join(); + } + + return 0; +} \ No newline at end of file diff --git a/examples/reading_logs_via_rule_message/Makefile.am b/examples/reading_logs_via_rule_message/Makefile.am index cab135bc..210edef3 100644 --- a/examples/reading_logs_via_rule_message/Makefile.am +++ b/examples/reading_logs_via_rule_message/Makefile.am @@ -32,7 +32,6 @@ simple_request_LDFLAGS = \ simple_request_CPPFLAGS = \ $(GLOBAL_CFLAGS) \ - -std=c++17 \ -I$(top_builddir)/headers \ -I$(top_builddir) \ -g \ diff --git a/examples/reading_logs_via_rule_message/reading_logs_via_rule_message.h b/examples/reading_logs_via_rule_message/reading_logs_via_rule_message.h index 6b280048..33148cd7 100644 --- a/examples/reading_logs_via_rule_message/reading_logs_via_rule_message.h +++ b/examples/reading_logs_via_rule_message/reading_logs_via_rule_message.h @@ -13,14 +13,19 @@ * */ +#ifndef EXAMPLES_READING_LOGS_VIA_RULE_MESSAGE_READING_LOGS_VIA_RULE_MESSAGE_H_ +#define EXAMPLES_READING_LOGS_VIA_RULE_MESSAGE_READING_LOGS_VIA_RULE_MESSAGE_H_ + #include #include #include +#include #include -#include + +#include "modsecurity/rule_message.h" -#define NUM_THREADS 100 +constexpr auto NUM_THREADS = 100; char request_header[] = "" \ @@ -62,40 +67,21 @@ char response_body[] = "" \ char ip[] = "200.249.12.31"; -#include "modsecurity/rule_message.h" -#ifndef EXAMPLES_READING_LOGS_VIA_RULE_MESSAGE_READING_LOGS_VIA_RULE_MESSAGE_H_ -#define EXAMPLES_READING_LOGS_VIA_RULE_MESSAGE_READING_LOGS_VIA_RULE_MESSAGE_H_ +static void process_request(modsecurity::ModSecurity *modsec, modsecurity::RulesSet *rules) { + for (auto z = 0; z < 10000; z++) { + auto modsecTransaction = std::make_unique(modsec, rules, nullptr); - -struct data_ms { - modsecurity::ModSecurity *modsec; - modsecurity::RulesSet *rules; -}; - -#if defined _MSC_VER -#pragma warning(push) -#pragma warning(disable:4716) // avoid error C4716: 'process_request': must return a value, as MSVC C++ compiler doesn't support [[noreturn]] -#pragma warning(disable:4715) // avoid warning c4715: 'process_request' : not all control paths return a value -#endif - -[[noreturn]] static void *process_request(void *data) { - struct data_ms *a = (struct data_ms *)data; - modsecurity::ModSecurity *modsec = a->modsec; - modsecurity::RulesSet *rules = a->rules; - int z = 0; - - for (z = 0; z < 10000; z++) { - modsecurity::Transaction *modsecTransaction = \ - new modsecurity::Transaction(modsec, rules, NULL); modsecTransaction->processConnection(ip, 12345, "127.0.0.1", 80); modsecTransaction->processURI(request_uri, "GET", "1.1"); std::this_thread::sleep_for(std::chrono::microseconds(10)); + modsecTransaction->addRequestHeader("Host", "net.tutsplus.com"); modsecTransaction->processRequestHeaders(); modsecTransaction->processRequestBody(); + modsecTransaction->addResponseHeader("HTTP/1.1", "200 OK"); modsecTransaction->processResponseHeaders(200, "HTTP 1.2"); @@ -103,18 +89,11 @@ struct data_ms { (const unsigned char*)response_body, strlen((const char*)response_body)); modsecTransaction->processResponseBody(); + modsecTransaction->processLogging(); - - delete modsecTransaction; } - - pthread_exit(nullptr); } -#if defined _MSC_VER -#pragma warning(pop) -#endif - class ReadingLogsViaRuleMessage { public: ReadingLogsViaRuleMessage(char *request_header, @@ -134,11 +113,6 @@ class ReadingLogsViaRuleMessage { { } int process() const { - pthread_t threads[NUM_THREADS]; - int i; - struct data_ms dms; - void *status; - auto modsec = std::make_unique(); modsec->setConnectorInformation("ModSecurity-test v0.0.1-alpha" \ " (ModSecurity test)"); @@ -152,18 +126,19 @@ class ReadingLogsViaRuleMessage { return -1; } - dms.modsec = modsec.get(); - dms.rules = rules.get(); + std::array threads; - for (i = 0; i < NUM_THREADS; i++) { - pthread_create(&threads[i], NULL, process_request, - reinterpret_cast(&dms)); + for (auto i = 0; i != threads.size(); ++i) { + threads[i] = std::thread( + [&modsec, &rules]() { + process_request(modsec.get(), rules.get()); + }); } std::this_thread::sleep_for(std::chrono::microseconds(10000)); - for (i=0; i < NUM_THREADS; i++) { - pthread_join(threads[i], &status); + for (auto i = 0; i != threads.size(); ++i) { + threads[i].join(); std::cout << "Main: completed thread id :" << i << std::endl; } diff --git a/examples/reading_logs_with_offset/Makefile.am b/examples/reading_logs_with_offset/Makefile.am index 33c8959d..3ecda10c 100644 --- a/examples/reading_logs_with_offset/Makefile.am +++ b/examples/reading_logs_with_offset/Makefile.am @@ -21,7 +21,6 @@ read_LDFLAGS = \ -L$(top_builddir)/src/.libs/ \ $(GEOIP_LDFLAGS) \ -lmodsecurity \ - -lpthread \ -lm \ -lstdc++ \ $(LMDB_LDFLAGS) \ @@ -32,7 +31,6 @@ read_LDFLAGS = \ read_CPPFLAGS = \ $(GLOBAL_CFLAGS) \ - -std=c++17 \ -I$(top_builddir)/headers \ -I$(top_builddir) \ -g \ diff --git a/examples/simple_example_using_c/test.c b/examples/simple_example_using_c/test.c index c7ed91b2..0c60ad5c 100644 --- a/examples/simple_example_using_c/test.c +++ b/examples/simple_example_using_c/test.c @@ -68,6 +68,8 @@ int main (int argc, char **argv) msc_process_response_body(transaction); msc_process_logging(transaction); end: + if(error != NULL) + msc_rules_error_cleanup(error); msc_rules_cleanup(rules); msc_cleanup(modsec); diff --git a/examples/using_bodies_in_chunks/Makefile.am b/examples/using_bodies_in_chunks/Makefile.am index 72f7bd22..5d645379 100644 --- a/examples/using_bodies_in_chunks/Makefile.am +++ b/examples/using_bodies_in_chunks/Makefile.am @@ -21,19 +21,16 @@ simple_request_LDFLAGS = \ -L$(top_builddir)/src/.libs/ \ $(GEOIP_LDFLAGS) \ -lmodsecurity \ - -lpthread \ -lm \ -lstdc++ \ $(MAXMIND_LDFLAGS) \ $(LMDB_LDFLAGS) \ - -lpthread \ $(LUA_LDFLAGS) \ $(SSDEEP_LDFLAGS) \ $(YAJL_LDFLAGS) simple_request_CPPFLAGS = \ $(GLOBAL_CFLAGS) \ - -std=c++17 \ -I$(top_builddir)/headers \ -I$(top_builddir) \ -g \ diff --git a/headers/modsecurity/actions/action.h b/headers/modsecurity/actions/action.h index 374b77d6..24f0da6d 100644 --- a/headers/modsecurity/actions/action.h +++ b/headers/modsecurity/actions/action.h @@ -13,41 +13,66 @@ * */ -#ifdef __cplusplus - -#include -#include -#include - -#endif - -#include "modsecurity/intervention.h" -#include "modsecurity/rule.h" -#include "modsecurity/rule_with_actions.h" - #ifndef HEADERS_MODSECURITY_ACTIONS_ACTION_H_ #define HEADERS_MODSECURITY_ACTIONS_ACTION_H_ #ifdef __cplusplus +#include +#include + namespace modsecurity { class Transaction; class RuleWithOperator; +class RuleWithActions; +class RuleMessage; namespace actions { class Action { public: + /** + * + * Define the action kind regarding to the execution time. + * + * + */ + enum class Kind { + /** + * + * Action that are executed while loading the configuration. For instance + * the rule ID or the rule phase. + * + */ + ConfigurationKind, + /** + * + * Those are actions that demands to be executed before call the operator. + * For instance the tranformations. + * + * + */ + RunTimeBeforeMatchAttemptKind, + /** + * + * Actions that are executed after the execution of the operator, only if + * the operator returned Match (or True). For instance the disruptive + * actions. + * + */ + RunTimeOnlyIfMatchKind, + }; + explicit Action(const std::string& _action) : m_isNone(false), temporaryAction(false), - action_kind(2), + action_kind(Kind::RunTimeOnlyIfMatchKind), m_name(nullptr), m_parser_payload("") { set_name_and_payload(_action); } - explicit Action(const std::string& _action, int kind) + explicit Action(const std::string& _action, Kind kind) : m_isNone(false), temporaryAction(false), action_kind(kind), @@ -74,8 +99,6 @@ class Action { virtual ~Action() { } - virtual std::string evaluate(const std::string &exp, - Transaction *transaction); virtual bool evaluate(RuleWithActions *rule, Transaction *transaction); virtual bool evaluate(RuleWithActions *rule, Transaction *transaction, std::shared_ptr ruleMessage) { @@ -87,9 +110,9 @@ class Action { void set_name_and_payload(const std::string& data) { size_t pos = data.find(":"); - std::string t = "t:"; + const char t[] = "t:"; - if (data.compare(0, t.length(), t) == 0) { + if (data.compare(0, std::size(t) - 1, t) == 0) { pos = data.find(":", 2); } @@ -109,41 +132,9 @@ class Action { bool m_isNone; bool temporaryAction; - int action_kind; + Kind action_kind; std::shared_ptr m_name; std::string m_parser_payload; - - /** - * - * Define the action kind regarding to the execution time. - * - * - */ - enum Kind { - /** - * - * Action that are executed while loading the configuration. For instance - * the rule ID or the rule phase. - * - */ - ConfigurationKind, - /** - * - * Those are actions that demands to be executed before call the operator. - * For instance the tranformations. - * - * - */ - RunTimeBeforeMatchAttemptKind, - /** - * - * Actions that are executed after the execution of the operator, only if - * the operator returned Match (or True). For instance the disruptive - * actions. - * - */ - RunTimeOnlyIfMatchKind, - }; }; diff --git a/headers/modsecurity/modsecurity.h b/headers/modsecurity/modsecurity.h index 192cd22e..d44ad248 100644 --- a/headers/modsecurity/modsecurity.h +++ b/headers/modsecurity/modsecurity.h @@ -38,10 +38,10 @@ * std::cout << "There is an intervention" << std::endl; * } * - * ... + * ... * * @endcode - * + * */ /** @@ -81,6 +81,11 @@ #endif +#include "modsecurity/intervention.h" +#include "modsecurity/transaction.h" +#include "modsecurity/debug_log.h" + + #ifndef HEADERS_MODSECURITY_MODSECURITY_H_ #define HEADERS_MODSECURITY_MODSECURITY_H_ @@ -160,7 +165,7 @@ namespace modsecurity { LoggingPhase, /** * Just a marking for the expected number of phases. - * + * */ NUMBER_OF_PHASES, }; @@ -170,11 +175,6 @@ namespace modsecurity { #endif - -#include "modsecurity/intervention.h" -#include "modsecurity/transaction.h" -#include "modsecurity/debug_log.h" - /** * TAG_NUM: * diff --git a/headers/modsecurity/rule.h b/headers/modsecurity/rule.h index 1d5570a8..18e64c0a 100644 --- a/headers/modsecurity/rule.h +++ b/headers/modsecurity/rule.h @@ -52,7 +52,7 @@ namespace operators { class Operator; } -using TransformationResult = std::pair, +using TransformationResult = std::pair>; using TransformationResults = std::list; diff --git a/headers/modsecurity/rule_with_actions.h b/headers/modsecurity/rule_with_actions.h index 4b7db43f..26967f2a 100644 --- a/headers/modsecurity/rule_with_actions.h +++ b/headers/modsecurity/rule_with_actions.h @@ -119,16 +119,7 @@ class RuleWithActions : public Rule { void executeTransformations( - Transaction *trasn, const std::string &value, TransformationResults &ret); - - inline void executeTransformation( - actions::transformations::Transformation *a, - std::shared_ptr *value, - Transaction *trans, - TransformationResults *ret, - std::string *path, - int *nth) const; - + const Transaction *trasn, const std::string &value, TransformationResults &ret); void performLogging(Transaction *trans, std::shared_ptr ruleMessage, @@ -166,6 +157,14 @@ class RuleWithActions : public Rule { RuleWithActions *m_chainedRuleParent; private: + inline void executeTransformation( + const actions::transformations::Transformation &a, + std::string &value, + const Transaction *trans, + TransformationResults &ret, + std::string &path, + int &nth) const; + /* actions */ actions::Action *m_disruptiveAction; actions::LogData *m_logData; diff --git a/headers/modsecurity/rule_with_operator.h b/headers/modsecurity/rule_with_operator.h index e2fea4e6..42fa0f9e 100644 --- a/headers/modsecurity/rule_with_operator.h +++ b/headers/modsecurity/rule_with_operator.h @@ -50,7 +50,7 @@ class RuleWithOperator : public RuleWithActions { bool evaluate(Transaction *transaction, std::shared_ptr rm) override; - void getVariablesExceptions(Transaction *t, + void getVariablesExceptions(Transaction &t, variables::Variables *exclusion, variables::Variables *addition); inline void getFinalVars(variables::Variables *vars, variables::Variables *eclusion, Transaction *trans); diff --git a/headers/modsecurity/rules_set.h b/headers/modsecurity/rules_set.h index 4af55f40..c5616cc4 100644 --- a/headers/modsecurity/rules_set.h +++ b/headers/modsecurity/rules_set.h @@ -99,6 +99,7 @@ int msc_rules_add_remote(RulesSet *rules, const char *key, const char *uri, const char **error); int msc_rules_add_file(RulesSet *rules, const char *file, const char **error); int msc_rules_add(RulesSet *rules, const char *plain_rules, const char **error); +void msc_rules_error_cleanup(const char *error); int msc_rules_cleanup(RulesSet *rules); #ifdef __cplusplus diff --git a/headers/modsecurity/rules_set_properties.h b/headers/modsecurity/rules_set_properties.h index 77b11269..643abce8 100644 --- a/headers/modsecurity/rules_set_properties.h +++ b/headers/modsecurity/rules_set_properties.h @@ -333,9 +333,9 @@ class RulesSetProperties { case FalseConfigBoolean: return "False"; case PropertyNotSetConfigBoolean: + default: return "Not set"; } - return NULL; } diff --git a/headers/modsecurity/transaction.h b/headers/modsecurity/transaction.h index 9caace2c..c5e8881f 100644 --- a/headers/modsecurity/transaction.h +++ b/headers/modsecurity/transaction.h @@ -14,6 +14,7 @@ */ #ifdef __cplusplus +#include #include #include #include @@ -307,11 +308,8 @@ class TransactionSecMarkerManagement { } std::shared_ptr getCurrentMarker() const { - if (m_marker) { - return m_marker; - } else { - throw; // cppcheck-suppress rethrowNoCurrentException - } + assert((m_marker != nullptr) && "You might have forgotten to call and evaluate isInsideAMarker() before calling getCurrentMarker()."); + return m_marker; } void removeMarker() { @@ -725,6 +723,9 @@ void msc_transaction_cleanup(Transaction *transaction); /** @ingroup ModSecurity_C_API */ int msc_intervention(Transaction *transaction, ModSecurityIntervention *it); +/** @ingroup ModSecurity_C_API */ +void msc_intervention_cleanup(ModSecurityIntervention *it); + /** @ingroup ModSecurity_C_API */ int msc_process_logging(Transaction *transaction); diff --git a/src/Makefile.am b/src/Makefile.am index fc67cb6c..6153036c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -219,7 +219,6 @@ OPERATORS = \ operators/no_match.cc \ operators/operator.cc \ operators/pm.cc \ - operators/pm_f.cc \ operators/pm_from_file.cc \ operators/rbl.cc \ operators/rsub.cc \ @@ -248,12 +247,9 @@ UTILS = \ utils/geo_lookup.cc \ utils/https_client.cc \ utils/ip_tree.cc \ - utils/md5.cc \ utils/msc_tree.cc \ utils/random.cc \ utils/regex.cc \ - utils/sha1.cc \ - utils/string.cc \ utils/system.cc \ utils/shared_files.cc @@ -311,7 +307,6 @@ libmodsecurity_la_CFLAGS = libmodsecurity_la_CPPFLAGS = \ - -std=c++17 \ -I.. \ -g \ -I../others \ @@ -323,7 +318,6 @@ libmodsecurity_la_CPPFLAGS = \ $(GEOIP_CFLAGS) \ $(GLOBAL_CPPFLAGS) \ $(MODSEC_NO_LOGS) \ - $(MODSEC_MUTEX_ON_PM) \ $(YAJL_CFLAGS) \ $(LMDB_CFLAGS) \ $(PCRE_CFLAGS) \ diff --git a/src/actions/accuracy.cc b/src/actions/accuracy.cc index c8cfca72..ace9f1c5 100644 --- a/src/actions/accuracy.cc +++ b/src/actions/accuracy.cc @@ -15,16 +15,10 @@ #include "src/actions/accuracy.h" -#include -#include - -#include "modsecurity/actions/action.h" -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" +#include "modsecurity/rule_with_actions.h" -namespace modsecurity { -namespace actions { +namespace modsecurity::actions { bool Accuracy::init(std::string *error) { @@ -45,5 +39,4 @@ bool Accuracy::evaluate(RuleWithActions *rule, Transaction *transaction) { } -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions diff --git a/src/actions/accuracy.h b/src/actions/accuracy.h index f787af19..bbcdba58 100644 --- a/src/actions/accuracy.h +++ b/src/actions/accuracy.h @@ -30,7 +30,7 @@ namespace actions { class Accuracy : public Action { public: explicit Accuracy(const std::string &action) - : Action(action, ConfigurationKind), + : Action(action, Kind::ConfigurationKind), m_accuracy(0) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/action.cc b/src/actions/action.cc index e58e2067..dd329a50 100644 --- a/src/actions/action.cc +++ b/src/actions/action.cc @@ -45,12 +45,6 @@ namespace modsecurity { namespace actions { -std::string Action::evaluate(const std::string &value, - Transaction *transaction) { - return value; -} - - bool Action::evaluate(RuleWithActions *rule, Transaction *transaction) { return true; } diff --git a/src/actions/audit_log.h b/src/actions/audit_log.h index d870de2a..cde74387 100644 --- a/src/actions/audit_log.h +++ b/src/actions/audit_log.h @@ -33,7 +33,7 @@ namespace actions { class AuditLog : public Action { public: explicit AuditLog(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool evaluate(RuleWithActions *rule, Transaction *transaction, std::shared_ptr rm) override; diff --git a/src/actions/capture.h b/src/actions/capture.h index 33207439..0b072ece 100644 --- a/src/actions/capture.h +++ b/src/actions/capture.h @@ -29,7 +29,7 @@ namespace actions { class Capture : public Action { public: explicit Capture(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; }; diff --git a/src/actions/chain.cc b/src/actions/chain.cc index 197f861f..62f0409c 100644 --- a/src/actions/chain.cc +++ b/src/actions/chain.cc @@ -15,14 +15,9 @@ #include "src/actions/chain.h" -#include -#include +#include "modsecurity/rule_with_actions.h" -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" - -namespace modsecurity { -namespace actions { +namespace modsecurity::actions { bool Chain::evaluate(RuleWithActions *rule, Transaction *transaction) { @@ -31,5 +26,4 @@ bool Chain::evaluate(RuleWithActions *rule, Transaction *transaction) { } -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions diff --git a/src/actions/chain.h b/src/actions/chain.h index c5642baa..3b04f17e 100644 --- a/src/actions/chain.h +++ b/src/actions/chain.h @@ -33,7 +33,7 @@ namespace actions { class Chain : public Action { public: explicit Chain(const std::string &action) - : Action(action, ConfigurationKind) { } + : Action(action, Kind::ConfigurationKind) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; }; diff --git a/src/actions/ctl/audit_engine.h b/src/actions/ctl/audit_engine.h index 03e0cb4c..b822a667 100644 --- a/src/actions/ctl/audit_engine.h +++ b/src/actions/ctl/audit_engine.h @@ -34,7 +34,7 @@ namespace ctl { class AuditEngine : public Action { public: explicit AuditEngine(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), m_auditEngine(audit_log::AuditLog::AuditLogStatus::NotSetLogStatus) { } bool init(std::string *error) override; diff --git a/src/actions/ctl/audit_log_parts.h b/src/actions/ctl/audit_log_parts.h index f4980780..0eb7c6b2 100644 --- a/src/actions/ctl/audit_log_parts.h +++ b/src/actions/ctl/audit_log_parts.h @@ -29,7 +29,7 @@ namespace ctl { class AuditLogParts : public Action { public: explicit AuditLogParts(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), mPartsAction(0), mParts("") { } diff --git a/src/actions/ctl/request_body_access.h b/src/actions/ctl/request_body_access.h index afe3b3d4..1dcc88c5 100644 --- a/src/actions/ctl/request_body_access.h +++ b/src/actions/ctl/request_body_access.h @@ -30,7 +30,7 @@ namespace ctl { class RequestBodyAccess : public Action { public: explicit RequestBodyAccess(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), m_request_body_access(false) { } bool init(std::string *error) override; diff --git a/src/actions/ctl/request_body_processor_json.h b/src/actions/ctl/request_body_processor_json.h index 48125597..9d726b17 100644 --- a/src/actions/ctl/request_body_processor_json.h +++ b/src/actions/ctl/request_body_processor_json.h @@ -29,7 +29,7 @@ namespace ctl { class RequestBodyProcessorJSON : public Action { public: explicit RequestBodyProcessorJSON(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; }; diff --git a/src/actions/ctl/request_body_processor_urlencoded.h b/src/actions/ctl/request_body_processor_urlencoded.h index 5b5557d4..0277664a 100644 --- a/src/actions/ctl/request_body_processor_urlencoded.h +++ b/src/actions/ctl/request_body_processor_urlencoded.h @@ -29,7 +29,7 @@ namespace ctl { class RequestBodyProcessorURLENCODED : public Action { public: explicit RequestBodyProcessorURLENCODED(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; }; diff --git a/src/actions/ctl/request_body_processor_xml.h b/src/actions/ctl/request_body_processor_xml.h index 9084d1d9..5bd15edd 100644 --- a/src/actions/ctl/request_body_processor_xml.h +++ b/src/actions/ctl/request_body_processor_xml.h @@ -29,7 +29,7 @@ namespace ctl { class RequestBodyProcessorXML : public Action { public: explicit RequestBodyProcessorXML(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; }; diff --git a/src/actions/ctl/rule_engine.h b/src/actions/ctl/rule_engine.h index fca5d39b..7aef4232 100644 --- a/src/actions/ctl/rule_engine.h +++ b/src/actions/ctl/rule_engine.h @@ -31,7 +31,7 @@ namespace ctl { class RuleEngine : public Action { public: explicit RuleEngine(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), m_ruleEngine(RulesSetProperties::PropertyNotSetRuleEngine) { } bool init(std::string *error) override; diff --git a/src/actions/ctl/rule_remove_by_id.h b/src/actions/ctl/rule_remove_by_id.h index e0f0902b..f731db31 100644 --- a/src/actions/ctl/rule_remove_by_id.h +++ b/src/actions/ctl/rule_remove_by_id.h @@ -30,7 +30,7 @@ namespace ctl { class RuleRemoveById : public Action { public: explicit RuleRemoveById(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool init(std::string *error) override; bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/ctl/rule_remove_by_tag.h b/src/actions/ctl/rule_remove_by_tag.h index 5689b7b1..e85cdbfa 100644 --- a/src/actions/ctl/rule_remove_by_tag.h +++ b/src/actions/ctl/rule_remove_by_tag.h @@ -30,7 +30,7 @@ namespace ctl { class RuleRemoveByTag : public Action { public: explicit RuleRemoveByTag(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), m_tag("") { } bool init(std::string *error) override; diff --git a/src/actions/ctl/rule_remove_target_by_id.h b/src/actions/ctl/rule_remove_target_by_id.h index d71e4fc2..92b7286d 100644 --- a/src/actions/ctl/rule_remove_target_by_id.h +++ b/src/actions/ctl/rule_remove_target_by_id.h @@ -30,7 +30,7 @@ namespace ctl { class RuleRemoveTargetById : public Action { public: explicit RuleRemoveTargetById(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), m_id(0), m_target("") { } diff --git a/src/actions/ctl/rule_remove_target_by_tag.h b/src/actions/ctl/rule_remove_target_by_tag.h index 7863e5a5..b4e21239 100644 --- a/src/actions/ctl/rule_remove_target_by_tag.h +++ b/src/actions/ctl/rule_remove_target_by_tag.h @@ -30,7 +30,7 @@ namespace ctl { class RuleRemoveTargetByTag : public Action { public: explicit RuleRemoveTargetByTag(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool init(std::string *error) override; bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/data/status.h b/src/actions/data/status.h index d792247d..566a927e 100644 --- a/src/actions/data/status.h +++ b/src/actions/data/status.h @@ -33,8 +33,8 @@ namespace data { class Status : public Action { public: - explicit Status(const std::string &action) : Action(action, 2), - m_status(0) { } + explicit Status(const std::string &action) + : Action(action), m_status(0) { } bool init(std::string *error) override; bool evaluate(RuleWithActions *rule, Transaction *transaction, diff --git a/src/actions/disruptive/allow.h b/src/actions/disruptive/allow.h index d9a716ce..a6d538a4 100644 --- a/src/actions/disruptive/allow.h +++ b/src/actions/disruptive/allow.h @@ -54,7 +54,7 @@ enum AllowType : int { class Allow : public Action { public: explicit Allow(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), m_allowType(NoneAllowType) { } diff --git a/src/actions/disruptive/redirect.h b/src/actions/disruptive/redirect.h index 46b5d51a..72ecf98e 100644 --- a/src/actions/disruptive/redirect.h +++ b/src/actions/disruptive/redirect.h @@ -37,12 +37,12 @@ namespace disruptive { class Redirect : public Action { public: explicit Redirect(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), m_status(0), m_string(nullptr) { } explicit Redirect(std::unique_ptr z) - : Action("redirert", RunTimeOnlyIfMatchKind), + : Action("redirert"), m_status(0), m_string(std::move(z)) { } diff --git a/src/actions/expire_var.h b/src/actions/expire_var.h index 1b1537bb..f0ca7496 100644 --- a/src/actions/expire_var.h +++ b/src/actions/expire_var.h @@ -36,7 +36,7 @@ class ExpireVar : public Action { explicit ExpireVar(const std::string &action) : Action(action) { } explicit ExpireVar(std::unique_ptr z) - : Action("expirevar", RunTimeOnlyIfMatchKind), + : Action("expirevar"), m_string(std::move(z)) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/init_col.h b/src/actions/init_col.h index 16d7ace9..f5a9263b 100644 --- a/src/actions/init_col.h +++ b/src/actions/init_col.h @@ -35,7 +35,7 @@ class InitCol : public Action { explicit InitCol(const std::string &action) : Action(action) { } InitCol(const std::string &action, std::unique_ptr z) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), m_string(std::move(z)) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/log.h b/src/actions/log.h index 736d4a13..d2cb5cd2 100644 --- a/src/actions/log.h +++ b/src/actions/log.h @@ -31,7 +31,7 @@ namespace actions { class Log : public Action { public: explicit Log(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool evaluate(RuleWithActions *rule, Transaction *transaction, std::shared_ptr rm) override; diff --git a/src/actions/log_data.h b/src/actions/log_data.h index da2fbf4d..6e618f2a 100644 --- a/src/actions/log_data.h +++ b/src/actions/log_data.h @@ -33,10 +33,10 @@ namespace actions { class LogData : public Action { public: explicit LogData(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } explicit LogData(std::unique_ptr z) - : Action("logdata", RunTimeOnlyIfMatchKind), + : Action("logdata"), m_string(std::move(z)) { } bool evaluate(RuleWithActions *rule, Transaction *transaction, diff --git a/src/actions/maturity.cc b/src/actions/maturity.cc index 131d2148..fca6aaa4 100644 --- a/src/actions/maturity.cc +++ b/src/actions/maturity.cc @@ -15,16 +15,10 @@ #include "src/actions/maturity.h" -#include -#include - -#include "modsecurity/actions/action.h" -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" +#include "modsecurity/rule_with_actions.h" -namespace modsecurity { -namespace actions { +namespace modsecurity::actions { bool Maturity::init(std::string *error) { @@ -45,5 +39,4 @@ bool Maturity::evaluate(RuleWithActions *rule, Transaction *transaction) { } -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions diff --git a/src/actions/maturity.h b/src/actions/maturity.h index dd185efa..3f873af4 100644 --- a/src/actions/maturity.h +++ b/src/actions/maturity.h @@ -30,7 +30,7 @@ namespace actions { class Maturity : public Action { public: explicit Maturity(const std::string &action) - : Action(action, ConfigurationKind), + : Action(action, Kind::ConfigurationKind), m_maturity(0) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/msg.h b/src/actions/msg.h index 61661194..c75e6d6e 100644 --- a/src/actions/msg.h +++ b/src/actions/msg.h @@ -34,10 +34,10 @@ namespace actions { class Msg : public Action { public: explicit Msg(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } explicit Msg(std::unique_ptr z) - : Action("msg", RunTimeOnlyIfMatchKind), + : Action("msg"), m_string(std::move(z)) { } bool evaluate(RuleWithActions *rule, Transaction *transaction, diff --git a/src/actions/multi_match.h b/src/actions/multi_match.h index b0fd2c76..71fe288f 100644 --- a/src/actions/multi_match.h +++ b/src/actions/multi_match.h @@ -33,7 +33,7 @@ namespace actions { class MultiMatch : public Action { public: explicit MultiMatch(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; }; diff --git a/src/actions/no_audit_log.h b/src/actions/no_audit_log.h index dbd5d098..6deb5e4a 100644 --- a/src/actions/no_audit_log.h +++ b/src/actions/no_audit_log.h @@ -33,7 +33,7 @@ namespace actions { class NoAuditLog : public Action { public: explicit NoAuditLog(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool evaluate(RuleWithActions *rule, Transaction *transaction, std::shared_ptr rm) override; diff --git a/src/actions/no_log.h b/src/actions/no_log.h index 87d4e305..193a64ea 100644 --- a/src/actions/no_log.h +++ b/src/actions/no_log.h @@ -31,7 +31,7 @@ namespace actions { class NoLog : public Action { public: explicit NoLog(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind) { } + : Action(action) { } bool evaluate(RuleWithActions *rule, Transaction *transaction, std::shared_ptr rm) override; diff --git a/src/actions/phase.cc b/src/actions/phase.cc index 2e9e7277..1d17ec33 100644 --- a/src/actions/phase.cc +++ b/src/actions/phase.cc @@ -15,20 +15,15 @@ #include "src/actions/phase.h" -#include -#include - -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" -#include "modsecurity/modsecurity.h" +#include "modsecurity/rule_with_actions.h" #include "src/utils/string.h" -namespace modsecurity { -namespace actions { +namespace modsecurity::actions { + bool Phase::init(std::string *error) { - std::string a = utils::string::tolower(m_parser_payload); + const auto a = utils::string::tolower(m_parser_payload); m_phase = -1; try { @@ -77,5 +72,5 @@ bool Phase::evaluate(RuleWithActions *rule, Transaction *transaction) { return true; } -} // namespace actions -} // namespace modsecurity + +} // namespace modsecurity::actions diff --git a/src/actions/phase.h b/src/actions/phase.h index 0fada3c3..7c814584 100644 --- a/src/actions/phase.h +++ b/src/actions/phase.h @@ -32,7 +32,7 @@ namespace actions { class Phase : public Action { public: - explicit Phase(const std::string &action) : Action(action, ConfigurationKind), + explicit Phase(const std::string &action) : Action(action, Kind::ConfigurationKind), m_phase(0), m_secRulesPhase(0) { } diff --git a/src/actions/rev.cc b/src/actions/rev.cc index 43d8d1be..6543a5da 100644 --- a/src/actions/rev.cc +++ b/src/actions/rev.cc @@ -15,16 +15,10 @@ #include "src/actions/rev.h" -#include -#include - -#include "modsecurity/actions/action.h" -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" +#include "modsecurity/rule_with_actions.h" -namespace modsecurity { -namespace actions { +namespace modsecurity::actions { bool Rev::init(std::string *error) { @@ -39,5 +33,4 @@ bool Rev::evaluate(RuleWithActions *rule, Transaction *transaction) { } -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions diff --git a/src/actions/rev.h b/src/actions/rev.h index 9e3c1bfb..a023b425 100644 --- a/src/actions/rev.h +++ b/src/actions/rev.h @@ -29,7 +29,7 @@ namespace actions { class Rev : public Action { public: - explicit Rev(const std::string &action) : Action(action, ConfigurationKind) { } + explicit Rev(const std::string &action) : Action(action, Kind::ConfigurationKind) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; bool init(std::string *error) override; diff --git a/src/actions/rule_id.cc b/src/actions/rule_id.cc index d16bf63b..c7864707 100644 --- a/src/actions/rule_id.cc +++ b/src/actions/rule_id.cc @@ -15,14 +15,10 @@ #include "src/actions/rule_id.h" -#include -#include +#include "modsecurity/rule_with_actions.h" -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" -namespace modsecurity { -namespace actions { +namespace modsecurity::actions { bool RuleId::init(std::string *error) { @@ -54,5 +50,4 @@ bool RuleId::evaluate(RuleWithActions *rule, Transaction *transaction) { } -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions diff --git a/src/actions/rule_id.h b/src/actions/rule_id.h index 2e26f87f..8f16c95e 100644 --- a/src/actions/rule_id.h +++ b/src/actions/rule_id.h @@ -33,7 +33,7 @@ namespace actions { class RuleId : public Action { public: explicit RuleId(const std::string &action) - : Action(action, ConfigurationKind), + : Action(action, Kind::ConfigurationKind), m_ruleId(0) { } bool init(std::string *error) override; diff --git a/src/actions/set_env.h b/src/actions/set_env.h index 33ccfc33..cc24c285 100644 --- a/src/actions/set_env.h +++ b/src/actions/set_env.h @@ -36,7 +36,7 @@ class SetENV : public Action { : Action(_action) { } explicit SetENV(std::unique_ptr z) - : Action("setenv", RunTimeOnlyIfMatchKind), + : Action("setenv"), m_string(std::move(z)) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/set_rsc.h b/src/actions/set_rsc.h index 5913b7c7..7830ee92 100644 --- a/src/actions/set_rsc.h +++ b/src/actions/set_rsc.h @@ -36,7 +36,7 @@ class SetRSC : public Action { : Action(_action) { } explicit SetRSC(std::unique_ptr z) - : Action("setsrc", RunTimeOnlyIfMatchKind), + : Action("setsrc"), m_string(std::move(z)) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/set_sid.h b/src/actions/set_sid.h index 64f8f3cc..dca45433 100644 --- a/src/actions/set_sid.h +++ b/src/actions/set_sid.h @@ -36,7 +36,7 @@ class SetSID : public Action { : Action(_action) { } explicit SetSID(std::unique_ptr z) - : Action("setsid", RunTimeOnlyIfMatchKind), + : Action("setsid"), m_string(std::move(z)) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/set_uid.h b/src/actions/set_uid.h index b8c3a0db..76893999 100644 --- a/src/actions/set_uid.h +++ b/src/actions/set_uid.h @@ -36,7 +36,7 @@ class SetUID : public Action { : Action(_action) { } explicit SetUID(std::unique_ptr z) - : Action("setuid", RunTimeOnlyIfMatchKind), + : Action("setuid"), m_string(std::move(z)) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/set_var.cc b/src/actions/set_var.cc index 6befdf0c..f30ae188 100644 --- a/src/actions/set_var.cc +++ b/src/actions/set_var.cc @@ -51,18 +51,12 @@ bool SetVar::evaluate(RuleWithActions *rule, Transaction *t) { std::string m_variableNameExpanded; auto *v = m_variable.get(); - variables::Tx_DynamicElement *tx = dynamic_cast< - variables::Tx_DynamicElement *> (v); - variables::Session_DynamicElement *session = dynamic_cast< - variables::Session_DynamicElement *> (v); - variables::Ip_DynamicElement *ip = dynamic_cast< - variables::Ip_DynamicElement *> (v); - variables::Resource_DynamicElement *resource = dynamic_cast< - variables::Resource_DynamicElement *> (v); - variables::Global_DynamicElement *global = dynamic_cast< - variables::Global_DynamicElement *> (v); - variables::User_DynamicElement *user = dynamic_cast< - variables::User_DynamicElement *> (v); + auto tx = dynamic_cast (v); + auto session = dynamic_cast (v); + auto ip = dynamic_cast (v); + auto resource = dynamic_cast (v); + auto global = dynamic_cast (v); + auto user = dynamic_cast (v); if (tx) { m_variableNameExpanded = tx->m_string->evaluate(t, rule); } else if (session) { diff --git a/src/actions/skip.h b/src/actions/skip.h index 71e5d7aa..ee24abe7 100644 --- a/src/actions/skip.h +++ b/src/actions/skip.h @@ -30,7 +30,7 @@ namespace actions { class Skip : public Action { public: explicit Skip(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), m_skip_next(0) { } bool init(std::string *error) override; diff --git a/src/actions/skip_after.h b/src/actions/skip_after.h index f7e0680d..39b2c269 100644 --- a/src/actions/skip_after.h +++ b/src/actions/skip_after.h @@ -31,7 +31,7 @@ namespace actions { class SkipAfter : public Action { public: explicit SkipAfter(const std::string &action) - : Action(action, RunTimeOnlyIfMatchKind), + : Action(action), m_skipName(std::make_shared(m_parser_payload)) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/actions/tag.h b/src/actions/tag.h index 75369f5f..bf3988b5 100644 --- a/src/actions/tag.h +++ b/src/actions/tag.h @@ -33,7 +33,7 @@ namespace actions { class Tag : public Action { public: explicit Tag(std::unique_ptr z) - : Action("tag", RunTimeOnlyIfMatchKind), + : Action("tag"), m_string(std::move(z)) { } std::string getName(Transaction *transaction); diff --git a/src/actions/transformations/base64_decode.cc b/src/actions/transformations/base64_decode.cc index 8ddfe235..fe910e50 100644 --- a/src/actions/transformations/base64_decode.cc +++ b/src/actions/transformations/base64_decode.cc @@ -13,33 +13,19 @@ * */ -#include "src/actions/transformations/base64_decode.h" +#include "base64_decode.h" -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/base64.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string Base64Decode::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret = Utils::Base64::decode(value); - - return ret; +bool Base64Decode::transform(std::string &value, const Transaction *trans) const { + if (value.empty()) return false; + value = Utils::Base64::decode(value); + return true; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/base64_decode.h b/src/actions/transformations/base64_decode.h index a8227699..8c97dbe8 100644 --- a/src/actions/transformations/base64_decode.h +++ b/src/actions/transformations/base64_decode.h @@ -13,33 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_BASE64_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_BASE64_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class Base64Decode : public Transformation { public: - explicit Base64Decode(const std::string &action) : Transformation(action) { } + using Transformation::Transformation; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_BASE64_DECODE_H_ diff --git a/src/actions/transformations/base64_decode_ext.cc b/src/actions/transformations/base64_decode_ext.cc index ee8e4b5b..e6c13987 100644 --- a/src/actions/transformations/base64_decode_ext.cc +++ b/src/actions/transformations/base64_decode_ext.cc @@ -13,33 +13,19 @@ * */ -#include "src/actions/transformations/base64_decode_ext.h" +#include "base64_decode_ext.h" -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/base64.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string Base64DecodeExt::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret = Utils::Base64::decode_forgiven(value); - - return ret; +bool Base64DecodeExt::transform(std::string &value, const Transaction *trans) const { + if (value.empty()) return false; + value = Utils::Base64::decode_forgiven(value); + return true; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/base64_decode_ext.h b/src/actions/transformations/base64_decode_ext.h index ad0efbdc..66b0678f 100644 --- a/src/actions/transformations/base64_decode_ext.h +++ b/src/actions/transformations/base64_decode_ext.h @@ -13,33 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_BASE64_DECODE_EXT_H_ #define SRC_ACTIONS_TRANSFORMATIONS_BASE64_DECODE_EXT_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class Base64DecodeExt : public Transformation { public: - explicit Base64DecodeExt(const std::string &action) : Transformation(action) { } + using Transformation::Transformation; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_BASE64_DECODE_EXT_H_ diff --git a/src/actions/transformations/base64_encode.cc b/src/actions/transformations/base64_encode.cc index 8be74803..bf802a1e 100644 --- a/src/actions/transformations/base64_encode.cc +++ b/src/actions/transformations/base64_encode.cc @@ -13,33 +13,19 @@ * */ -#include "src/actions/transformations/base64_encode.h" +#include "base64_encode.h" -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/base64.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string Base64Encode::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret = Utils::Base64::encode(value); - - return ret; +bool Base64Encode::transform(std::string &value, const Transaction *trans) const { + if (value.empty()) return false; + value = Utils::Base64::encode(value); + return true; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/base64_encode.h b/src/actions/transformations/base64_encode.h index 0f7fd1fe..3c1d96f1 100644 --- a/src/actions/transformations/base64_encode.h +++ b/src/actions/transformations/base64_encode.h @@ -13,33 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_BASE64_ENCODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_BASE64_ENCODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class Base64Encode : public Transformation { public: - explicit Base64Encode(const std::string &action) : Transformation(action) { } + using Transformation::Transformation; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_BASE64_ENCODE_H_ diff --git a/src/actions/transformations/cmd_line.cc b/src/actions/transformations/cmd_line.cc index 72087e36..8db1529d 100644 --- a/src/actions/transformations/cmd_line.cc +++ b/src/actions/transformations/cmd_line.cc @@ -13,30 +13,17 @@ * */ -#include "src/actions/transformations/cmd_line.h" - -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "cmd_line.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string CmdLine::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; - int space = 0; +bool CmdLine::transform(std::string &value, const Transaction *trans) const { + char *d = value.data(); + bool space = false; - for (auto& a : value) { + for (const auto& a : value) { switch (a) { /* remove some characters */ case '"': @@ -52,9 +39,9 @@ std::string CmdLine::evaluate(const std::string &value, case '\t': case '\r': case '\n': - if (space == 0) { - ret.append(" "); - space++; + if (space == false) { + *d++ = ' '; + space = true; } break; @@ -62,26 +49,27 @@ std::string CmdLine::evaluate(const std::string &value, case '/': case '(': if (space) { - ret.pop_back(); + d--; } - space = 0; - ret.append(&a, 1); + space = false; + *d++ = a; break; /* copy normal characters */ default : char b = std::tolower(a); - ret.append(&b, 1); - space = 0; + *d++ = b; + space = false; break; } } - return ret; + const auto new_len = d - value.c_str(); + const auto changed = new_len != value.length(); + value.resize(new_len); + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/cmd_line.h b/src/actions/transformations/cmd_line.h index 851f2938..27672b60 100644 --- a/src/actions/transformations/cmd_line.h +++ b/src/actions/transformations/cmd_line.h @@ -13,35 +13,21 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_CMD_LINE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_CMD_LINE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class CmdLine : public Transformation { public: - explicit CmdLine(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // modsecurity::namespace actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_CMD_LINE_H_ diff --git a/src/actions/transformations/compress_whitespace.cc b/src/actions/transformations/compress_whitespace.cc index 506de248..a9b31c96 100644 --- a/src/actions/transformations/compress_whitespace.cc +++ b/src/actions/transformations/compress_whitespace.cc @@ -13,54 +13,36 @@ * */ -#include "src/actions/transformations/compress_whitespace.h" - -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "compress_whitespace.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -CompressWhitespace::CompressWhitespace(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} -std::string CompressWhitespace::evaluate(const std::string &value, - Transaction *transaction) { +bool CompressWhitespace::transform(std::string &value, const Transaction *trans) const { + bool inWhiteSpace = false; - std::string a; - int inWhiteSpace = 0; - int i = 0; + auto d = value.data(); - while (i < value.size()) { - if (isspace(value[i])) { + for(const auto c : value) { + if (isspace(c)) { if (inWhiteSpace) { - i++; continue; } else { - inWhiteSpace = 1; - a.append(" ", 1); + inWhiteSpace = true; + *d++ = ' '; } } else { - inWhiteSpace = 0; - a.append(&value.at(i), 1); + inWhiteSpace = false; + *d++ = c; } - i++; } - return a; + const auto new_len = d - value.c_str(); + const auto changed = new_len != value.length(); + value.resize(new_len); + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/compress_whitespace.h b/src/actions/transformations/compress_whitespace.h index 184ddcfa..8f74a3c1 100644 --- a/src/actions/transformations/compress_whitespace.h +++ b/src/actions/transformations/compress_whitespace.h @@ -13,34 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_COMPRESS_WHITESPACE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_COMPRESS_WHITESPACE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class CompressWhitespace : public Transformation { public: + using Transformation::Transformation; - explicit CompressWhitespace(const std::string &action) ; - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_COMPRESS_WHITESPACE_H_ diff --git a/src/actions/transformations/css_decode.cc b/src/actions/transformations/css_decode.cc index f8085123..41da9390 100644 --- a/src/actions/transformations/css_decode.cc +++ b/src/actions/transformations/css_decode.cc @@ -13,42 +13,13 @@ * */ -#include "src/actions/transformations/css_decode.h" +#include "css_decode.h" -#include - -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/string.h" +using namespace modsecurity::utils::string; -namespace modsecurity { -namespace actions { -namespace transformations { - - -std::string CssDecode::evaluate(const std::string &value, - Transaction *transaction) { - - char *tmp = reinterpret_cast( - malloc(sizeof(char) * value.size() + 1)); - memcpy(tmp, value.c_str(), value.size() + 1); - tmp[value.size()] = '\0'; - - CssDecode::css_decode_inplace(reinterpret_cast(tmp), - value.size()); - - std::string ret(tmp, 0, value.size()); - free(tmp); - return ret; -} +namespace modsecurity::actions::transformations { /** @@ -58,15 +29,13 @@ std::string CssDecode::evaluate(const std::string &value, * http://www.w3.org/TR/REC-CSS2/syndata.html#q4 * http://www.unicode.org/roadmaps/ */ -int CssDecode::css_decode_inplace(unsigned char *input, int64_t input_len) { - unsigned char *d = (unsigned char *)input; - int64_t i, j, count; +static inline bool css_decode_inplace(std::string &val) { + const auto input_len = val.length(); + auto input = reinterpret_cast(val.data()); + auto d = input; + bool changed = false; - if (input == NULL) { - return -1; - } - - i = count = 0; + std::string::size_type i = 0; while (i < input_len) { /* Is the character a backslash? */ if (input[i] == '\\') { @@ -75,7 +44,7 @@ int CssDecode::css_decode_inplace(unsigned char *input, int64_t input_len) { i++; /* We are not going to need the backslash. */ /* Check for 1-6 hex characters following the backslash */ - j = 0; + std::string::size_type j = 0; while ((j < 6) && (i + j < input_len) && (VALID_HEX(input[i + j]))) { @@ -157,40 +126,45 @@ int CssDecode::css_decode_inplace(unsigned char *input, int64_t input_len) { } /* Move over. */ - count++; i += j; + + changed = true; } else if (input[i] == '\n') { /* No hexadecimal digits after backslash */ /* A newline character following backslash is ignored. */ i++; + changed = true; } else { /* The character after backslash is not a hexadecimal digit, * nor a newline. */ /* Use one character after backslash as is. */ *d++ = input[i++]; - count++; } } else { /* No characters after backslash. */ /* Do not include backslash in output *(continuation to nothing) */ i++; + changed = true; } } else { /* Character is not a backslash. */ /* Copy one normal character to output. */ *d++ = input[i++]; - count++; } } /* Terminate output string. */ *d = '\0'; - return count; + val.resize(d - input); + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +bool CssDecode::transform(std::string &value, const Transaction *trans) const { + return css_decode_inplace(value); +} + + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/css_decode.h b/src/actions/transformations/css_decode.h index a6769bad..c9b451f8 100644 --- a/src/actions/transformations/css_decode.h +++ b/src/actions/transformations/css_decode.h @@ -13,37 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_CSS_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_CSS_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; - -namespace actions { -namespace transformations { +#include "transformation.h" +namespace modsecurity::actions::transformations { class CssDecode : public Transformation { public: - explicit CssDecode(const std::string &action) - : Transformation(action) { } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + using Transformation::Transformation; - static int css_decode_inplace(unsigned char *input, int64_t input_len); + bool transform(std::string &value, const Transaction *trans) const override; }; - -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_CSS_DECODE_H_ diff --git a/src/actions/transformations/escape_seq_decode.cc b/src/actions/transformations/escape_seq_decode.cc index 03303272..94df2269 100644 --- a/src/actions/transformations/escape_seq_decode.cc +++ b/src/actions/transformations/escape_seq_decode.cc @@ -13,36 +13,22 @@ * */ -#include "src/actions/transformations/escape_seq_decode.h" +#include "escape_seq_decode.h" -#include -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/string.h" -namespace modsecurity { -namespace actions { -namespace transformations { +using namespace modsecurity::utils::string; -EscapeSeqDecode::EscapeSeqDecode(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} +namespace modsecurity::actions::transformations { -int EscapeSeqDecode::ansi_c_sequences_decode_inplace(unsigned char *input, - int input_len) { - unsigned char *d = input; - int i, count; +static inline int ansi_c_sequences_decode_inplace(std::string &value) { + auto d = reinterpret_cast(value.data()); + const unsigned char* input = d; + const auto input_len = value.length(); - i = count = 0; + bool changed = false; + std::string::size_type i = 0; while (i < input_len) { if ((input[i] == '\\') && (i + 1 < input_len)) { int c = -1; @@ -120,43 +106,29 @@ int EscapeSeqDecode::ansi_c_sequences_decode_inplace(unsigned char *input, if (c == -1) { /* Didn't recognise encoding, copy raw bytes. */ *d++ = input[i + 1]; - count++; i += 2; } else { /* Converted the encoding. */ *d++ = c; - count++; } + + changed = true; } else { /* Input character not a backslash, copy it. */ *d++ = input[i++]; - count++; } } *d = '\0'; - return count; + value.resize(d - input); + return changed; } -std::string EscapeSeqDecode::evaluate(const std::string &value, - Transaction *transaction) { - - unsigned char *tmp = (unsigned char *) malloc(sizeof(char) - * value.size() + 1); - memcpy(tmp, value.c_str(), value.size() + 1); - tmp[value.size()] = '\0'; - - int size = ansi_c_sequences_decode_inplace(tmp, value.size()); - - std::string ret(""); - ret.assign(reinterpret_cast(tmp), size); - free(tmp); - - return ret; +bool EscapeSeqDecode::transform(std::string &value, const Transaction *trans) const { + return ansi_c_sequences_decode_inplace(value); } -} // namespace transformations -} // namespace actions -} // namespace modsecurity + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/escape_seq_decode.h b/src/actions/transformations/escape_seq_decode.h index d68f33b5..71976fe1 100644 --- a/src/actions/transformations/escape_seq_decode.h +++ b/src/actions/transformations/escape_seq_decode.h @@ -13,35 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_ESCAPE_SEQ_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_ESCAPE_SEQ_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class EscapeSeqDecode : public Transformation { public: + using Transformation::Transformation; - explicit EscapeSeqDecode(const std::string &action) ; - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; - int ansi_c_sequences_decode_inplace(unsigned char *input, int input_len); + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_ESCAPE_SEQ_DECODE_H_ diff --git a/src/actions/transformations/hex_decode.cc b/src/actions/transformations/hex_decode.cc index 1525377c..1b43b6cd 100644 --- a/src/actions/transformations/hex_decode.cc +++ b/src/actions/transformations/hex_decode.cc @@ -13,67 +13,35 @@ * */ -#include "src/actions/transformations/hex_decode.h" +#include "hex_decode.h" -#include -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/string.h" -namespace modsecurity { -namespace actions { -namespace transformations { + +namespace modsecurity::actions::transformations { -std::string HexDecode::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; - unsigned char *input; - int size = 0; +static inline int inplace(std::string &value) { + if (value.empty()) return false; - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); + const auto len = value.length(); + auto d = reinterpret_cast(value.data()); + const auto data = d; - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - size = inplace(input, value.length()); - - ret.assign(reinterpret_cast(input), size); - free(input); - - return ret; -} - - -int HexDecode::inplace(unsigned char *data, int len) { - unsigned char *d = data; - int count = 0; - - if ((data == NULL) || (len == 0)) { - return 0; - } - - for (int i = 0;i <= len - 2;i += 2) { + for (int i = 0; i <= len - 2; i += 2) { *d++ = utils::string::x2c(&data[i]); - count++; } + *d = '\0'; - return count; + value.resize(d - data); + return true; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +bool HexDecode::transform(std::string &value, const Transaction *trans) const { + return inplace(value); +} + + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/hex_decode.h b/src/actions/transformations/hex_decode.h index a2f48c6d..1ee6a1b7 100644 --- a/src/actions/transformations/hex_decode.h +++ b/src/actions/transformations/hex_decode.h @@ -13,35 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_HEX_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_HEX_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class HexDecode : public Transformation { public: - explicit HexDecode(const std::string &action) : Transformation(action) { } + using Transformation::Transformation; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; - - static int inplace(unsigned char *data, int len); + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_HEX_DECODE_H_ diff --git a/src/actions/transformations/hex_encode.cc b/src/actions/transformations/hex_encode.cc index 4e6121df..689a132f 100644 --- a/src/actions/transformations/hex_encode.cc +++ b/src/actions/transformations/hex_encode.cc @@ -13,41 +13,25 @@ * */ -#include "src/actions/transformations/hex_encode.h" +#include "hex_encode.h" -#include -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "modsecurity/rule_with_actions.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -HexEncode::HexEncode(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} -std::string HexEncode::evaluate(const std::string &value, - Transaction *transaction) { +bool HexEncode::transform(std::string &value, const Transaction *trans) const { + if (value.empty()) return false; std::stringstream result; - for (std::size_t i=0; i < value.length(); i++) { - unsigned int ii = (unsigned char)(value[i]); + for (const auto c : value) { + unsigned int ii = (unsigned char)c; result << std::setw(2) << std::setfill('0') << std::hex << ii; } - return result.str(); + value = result.str(); + return true; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/hex_encode.h b/src/actions/transformations/hex_encode.h index 1ba39c56..9037a514 100644 --- a/src/actions/transformations/hex_encode.h +++ b/src/actions/transformations/hex_encode.h @@ -13,34 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_HEX_ENCODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_HEX_ENCODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class HexEncode : public Transformation { public: + using Transformation::Transformation; - explicit HexEncode(const std::string &action); - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_HEX_ENCODE_H_ diff --git a/src/actions/transformations/html_entity_decode.cc b/src/actions/transformations/html_entity_decode.cc index 6a683245..8a0cc3e9 100644 --- a/src/actions/transformations/html_entity_decode.cc +++ b/src/actions/transformations/html_entity_decode.cc @@ -13,70 +13,36 @@ * */ -#include "src/actions/transformations/html_entity_decode.h" +#include "html_entity_decode.h" -#include +#include -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "src/utils/string.h" #ifdef WIN32 #include "src/compat/msvc.h" #endif +using namespace modsecurity::utils::string; -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string HtmlEntityDecode::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; - unsigned char *input; +static inline bool inplace(std::string &value) { + const auto input_len = value.length(); + auto d = reinterpret_cast(value.data()); + const unsigned char *input = d; + const unsigned char *end = input + input_len; - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - size_t i = inplace(input, value.length()); - - ret.assign(reinterpret_cast(input), i); - free(input); - - return ret; -} - - -int HtmlEntityDecode::inplace(unsigned char *input, uint64_t input_len) { - unsigned char *d = input; - int i, count; - - if ((input == NULL) || (input_len == 0)) { - return 0; - } - - i = count = 0; - while ((i < input_len) && (count < input_len)) { - int z, copy = 1; + std::string::size_type i = 0; + while (i < input_len) { + std::string::size_type copy = 1; /* Require an ampersand and at least one character to * start looking into the entity. */ if ((input[i] == '&') && (i + 1 < input_len)) { - int k, j = i + 1; + auto j = i + 1; if (input[j] == '#') { /* Numerical entity. */ @@ -96,19 +62,18 @@ int HtmlEntityDecode::inplace(unsigned char *input, uint64_t input_len) { } j++; /* j is the position of the first digit now. */ - k = j; - while ((j < input_len) && (isxdigit(input[j]))) { + constexpr int MAX_HEX_DIGITS = 2; // supports only bytes (max value 0xff) + auto k = j; + while ((j - k < MAX_HEX_DIGITS) && (j < input_len) && (isxdigit(input[j]))) { j++; } if (j > k) { /* Do we have at least one digit? */ /* Decode the entity. */ - char *x; - x = reinterpret_cast(calloc(sizeof(char), - ((j - k) + 1))); + char x[MAX_HEX_DIGITS + 1]; memcpy(x, (const char *)&input[k], j - k); - *d++ = (unsigned char)strtol(x, NULL, 16); - free(x); - count++; + x[j - k] = '\0'; + + *d++ = (unsigned char)strtol(x, nullptr, 16); /* Skip over the semicolon if it's there. */ if ((j < input_len) && (input[j] == ';')) { @@ -122,19 +87,18 @@ int HtmlEntityDecode::inplace(unsigned char *input, uint64_t input_len) { } } else { /* Decimal entity. */ - k = j; - while ((j < input_len) && (isdigit(input[j]))) { + constexpr int MAX_DEC_DIGITS = 3; // supports only bytes (max value 255) + auto k = j; + while ((j - k < MAX_DEC_DIGITS) && (j < input_len) && (isdigit(input[j]))) { j++; } if (j > k) { /* Do we have at least one digit? */ /* Decode the entity. */ - char *x; - x = reinterpret_cast(calloc(sizeof(char), - ((j - k) + 1))); + char x[MAX_DEC_DIGITS + 1]; memcpy(x, (const char *)&input[k], j - k); - *d++ = (unsigned char)strtol(x, NULL, 10); - free(x); - count++; + x[j - k] = '\0'; + + *d++ = (unsigned char)strtol(x, nullptr, 10); /* Skip over the semicolon if it's there. */ if ((j < input_len) && (input[j] == ';')) { @@ -149,38 +113,31 @@ int HtmlEntityDecode::inplace(unsigned char *input, uint64_t input_len) { } } else { /* Text entity. */ - k = j; + auto k = j; while ((j < input_len) && (isalnum(input[j]))) { j++; } if (j > k) { /* Do we have at least one digit? */ - char *x; - x = reinterpret_cast(calloc(sizeof(char), - ((j - k) + 1))); - memcpy(x, (const char *)&input[k], j - k); + const auto x = reinterpret_cast(&input[k]); /* Decode the entity. */ /* ENH What about others? */ - if (strcasecmp(x, "quot") == 0) { + if (strncasecmp(x, "quot", 4) == 0) { *d++ = '"'; - } else if (strcasecmp(x, "amp") == 0) { + } else if (strncasecmp(x, "amp", 3) == 0) { *d++ = '&'; - } else if (strcasecmp(x, "lt") == 0) { + } else if (strncasecmp(x, "lt", 2) == 0) { *d++ = '<'; - } else if (strcasecmp(x, "gt") == 0) { + } else if (strncasecmp(x, "gt", 2) == 0) { *d++ = '>'; - } else if (strcasecmp(x, "nbsp") == 0) { + } else if (strncasecmp(x, "nbsp", 4) == 0) { *d++ = NBSP; } else { /* We do no want to convert this entity, * copy the raw data over. */ copy = j - k + 1; - free(x); goto HTML_ENT_OUT; } - free(x); - - count++; /* Skip over the semicolon if it's there. */ if ((j < input_len) && (input[j] == ';')) { @@ -196,17 +153,21 @@ int HtmlEntityDecode::inplace(unsigned char *input, uint64_t input_len) { HTML_ENT_OUT: - for (z = 0; ((z < copy) && (count < input_len)); z++) { + for (auto z = 0; z < copy; z++) { *d++ = input[i++]; - count++; } } *d = '\0'; - return count; + value.resize(d - input); + return d != end; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity + +bool HtmlEntityDecode::transform(std::string &value, const Transaction *trans) const { + return inplace(value); +} + + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/html_entity_decode.h b/src/actions/transformations/html_entity_decode.h index 44fcc323..499f8f2f 100644 --- a/src/actions/transformations/html_entity_decode.h +++ b/src/actions/transformations/html_entity_decode.h @@ -13,40 +13,20 @@ * */ -#include -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" -#include "src/utils/string.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_HTML_ENTITY_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_HTML_ENTITY_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; - -namespace actions { -namespace transformations { +#include "transformation.h" +namespace modsecurity::actions::transformations { class HtmlEntityDecode : public Transformation { public: - explicit HtmlEntityDecode(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; - - static int inplace(unsigned char *input, uint64_t input_len); + bool transform(std::string &value, const Transaction *trans) const override; }; - -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_HTML_ENTITY_DECODE_H_ diff --git a/src/actions/transformations/js_decode.cc b/src/actions/transformations/js_decode.cc index 2f4cf8bb..857125c7 100644 --- a/src/actions/transformations/js_decode.cc +++ b/src/actions/transformations/js_decode.cc @@ -13,55 +13,22 @@ * */ -#include "src/actions/transformations/js_decode.h" +#include "js_decode.h" -#include - -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/string.h" +using namespace modsecurity::utils::string; -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string JsDecode::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; - unsigned char *input; +static inline int inplace(std::string &value) { + auto d = reinterpret_cast(value.data()); + const unsigned char *input = d; + const auto input_len = value.length(); - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - size_t i = inplace(input, value.length()); - - ret.assign(reinterpret_cast(input), i); - free(input); - - return ret; -} - - -int JsDecode::inplace(unsigned char *input, uint64_t input_len) { - unsigned char *d = (unsigned char *)input; - int64_t i, count; - - i = count = 0; + bool changed = false; + std::string::size_type i = 0; while (i < input_len) { if (input[i] == '\\') { /* Character is an escape. */ @@ -82,14 +49,14 @@ int JsDecode::inplace(unsigned char *input, uint64_t input_len) { } d++; - count++; i += 6; + changed = true; } else if ((i + 3 < input_len) && (input[i + 1] == 'x') && VALID_HEX(input[i + 2]) && VALID_HEX(input[i + 3])) { /* \xHH */ *d++ = utils::string::x2c(&input[i + 2]); - count++; i += 4; + changed = true; } else if ((i + 1 < input_len) && ISODIGIT(input[i + 1])) { /* \OOO (only one byte, \000 - \377) */ char buf[4]; @@ -110,7 +77,7 @@ int JsDecode::inplace(unsigned char *input, uint64_t input_len) { } *d++ = (unsigned char)strtol(buf, NULL, 8); i += 1 + j; - count++; + changed = true; } } else if (i + 1 < input_len) { /* \C */ @@ -144,25 +111,28 @@ int JsDecode::inplace(unsigned char *input, uint64_t input_len) { *d++ = c; i += 2; - count++; + changed = true; } else { /* Not enough bytes */ while (i < input_len) { *d++ = input[i++]; - count++; } } } else { *d++ = input[i++]; - count++; } } *d = '\0'; - return count; + value.resize(d - input); + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity + +bool JsDecode::transform(std::string &value, const Transaction *trans) const { + return inplace(value); +} + + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/js_decode.h b/src/actions/transformations/js_decode.h index 60d6617b..840577cb 100644 --- a/src/actions/transformations/js_decode.h +++ b/src/actions/transformations/js_decode.h @@ -13,35 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_JS_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_JS_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class JsDecode : public Transformation { public: - explicit JsDecode(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; - static int inplace(unsigned char *input, uint64_t input_len); + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_JS_DECODE_H_ diff --git a/src/actions/transformations/length.cc b/src/actions/transformations/length.cc index 61015b82..ac98914c 100644 --- a/src/actions/transformations/length.cc +++ b/src/actions/transformations/length.cc @@ -13,34 +13,16 @@ * */ -#include "src/actions/transformations/length.h" - -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "length.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -Length::Length(const std::string &action) - : Transformation(action) { - this->action_kind = 1; + +bool Length::transform(std::string &value, const Transaction *trans) const { + value = std::to_string(value.size()); + return true; } -std::string Length::evaluate(const std::string &value, - Transaction *transaction) { - return std::to_string(value.size()); -} - -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/length.h b/src/actions/transformations/length.h index 8892a9dc..39465238 100644 --- a/src/actions/transformations/length.h +++ b/src/actions/transformations/length.h @@ -13,34 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_LENGTH_H_ #define SRC_ACTIONS_TRANSFORMATIONS_LENGTH_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class Length : public Transformation { public: + using Transformation::Transformation; - explicit Length(const std::string &action); - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_LENGTH_H_ diff --git a/src/actions/transformations/lower_case.cc b/src/actions/transformations/lower_case.cc index 7bca9479..0238b5a4 100644 --- a/src/actions/transformations/lower_case.cc +++ b/src/actions/transformations/lower_case.cc @@ -13,37 +13,19 @@ * */ -#include "src/actions/transformations/lower_case.h" -#include -#include -#include +#include "lower_case.h" -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" -#include "modsecurity/actions/action.h" - -namespace modsecurity { -namespace actions { -namespace transformations { +#include -LowerCase::LowerCase(const std::string &a) - : Transformation(a) { +namespace modsecurity::actions::transformations { + + +bool LowerCase::transform(std::string &value, const Transaction *trans) const { + return convert(value, [](auto c) { + return std::tolower(c); }); } -std::string LowerCase::evaluate(const std::string &val, - Transaction *transaction) { - std::locale loc; - std::string value(val); - for (std::string::size_type i=0; i < value.length(); ++i) { - value[i] = std::tolower(value[i], loc); - } - - return value; -} - -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/lower_case.h b/src/actions/transformations/lower_case.h index 59049840..192b2aa3 100644 --- a/src/actions/transformations/lower_case.h +++ b/src/actions/transformations/lower_case.h @@ -13,34 +13,35 @@ * */ -#include -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_LOWER_CASE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_LOWER_CASE_H_ -#ifdef __cplusplus +#include "transformation.h" -namespace modsecurity { -class Transaction; -namespace actions { -namespace transformations { +#include +namespace modsecurity::actions::transformations { class LowerCase : public Transformation { public: - explicit LowerCase(const std::string &action); - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + using Transformation::Transformation; + + bool transform(std::string &value, const Transaction *trans) const override; + + template + static bool convert(std::string &val, Operation op) { + bool changed = false; + + std::transform(val.begin(), val.end(), val.data(), + [&](auto c) { + const auto nc = op(c); + if(nc != c) changed = true; + return nc; }); + + return changed; + } }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_LOWER_CASE_H_ diff --git a/src/actions/transformations/md5.cc b/src/actions/transformations/md5.cc index 71c36bc3..b1cdc93e 100644 --- a/src/actions/transformations/md5.cc +++ b/src/actions/transformations/md5.cc @@ -13,32 +13,17 @@ * */ -#include "src/actions/transformations/md5.h" +#include "md5.h" -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/md5.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string Md5::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret = Utils::Md5::digest(value); - - return ret; +bool Md5::transform(std::string &value, const Transaction *trans) const { + value = Utils::Md5::digest(value); + return true; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/md5.h b/src/actions/transformations/md5.h index 37f22473..d1813c5f 100644 --- a/src/actions/transformations/md5.h +++ b/src/actions/transformations/md5.h @@ -13,33 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_MD5_H_ #define SRC_ACTIONS_TRANSFORMATIONS_MD5_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class Md5 : public Transformation { public: - explicit Md5(const std::string &action) : Transformation(action) { } + using Transformation::Transformation; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_MD5_H_ diff --git a/src/actions/transformations/none.cc b/src/actions/transformations/none.cc index f122bf03..adbf32a6 100644 --- a/src/actions/transformations/none.cc +++ b/src/actions/transformations/none.cc @@ -13,30 +13,15 @@ * */ -#include "src/actions/transformations/none.h" - -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "none.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string None::evaluate(const std::string &value, - Transaction *transaction) { - return value; +bool None::transform(std::string &value, const Transaction *trans) const { + return false; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/none.h b/src/actions/transformations/none.h index e8a0e9d9..2fe428bb 100644 --- a/src/actions/transformations/none.h +++ b/src/actions/transformations/none.h @@ -13,20 +13,12 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_NONE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_NONE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class None : public Transformation { public: @@ -34,14 +26,9 @@ class None : public Transformation { : Transformation(action) { m_isNone = true; } - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_NONE_H_ diff --git a/src/actions/transformations/normalise_path.cc b/src/actions/transformations/normalise_path.cc index e75b9849..91c04027 100644 --- a/src/actions/transformations/normalise_path.cc +++ b/src/actions/transformations/normalise_path.cc @@ -13,47 +13,14 @@ * */ -#include "src/actions/transformations/normalise_path.h" - -#include - -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "normalise_path.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -NormalisePath::NormalisePath(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} -std::string NormalisePath::evaluate(const std::string &value, - Transaction *transaction) { - int changed = 0; - - char *tmp = reinterpret_cast( - malloc(sizeof(char) * value.size() + 1)); - memcpy(tmp, value.c_str(), value.size() + 1); - tmp[value.size()] = '\0'; - - int i = normalize_path_inplace((unsigned char *)tmp, - value.size(), 0, &changed); - - std::string ret(""); - ret.assign(tmp, i); - free(tmp); - - return ret; +bool NormalisePath::transform(std::string &value, const Transaction *trans) const { + return normalize_path_inplace(value, false); } @@ -61,21 +28,22 @@ std::string NormalisePath::evaluate(const std::string &value, * * IMP1 Assumes NUL-terminated */ -int NormalisePath::normalize_path_inplace(unsigned char *input, int input_len, - int win, int *changed) { +bool NormalisePath::normalize_path_inplace(std::string &val, const bool win) { unsigned char *src; unsigned char *dst; unsigned char *end; - int ldst = 0; int hitroot = 0; int done = 0; int relative; int trailing; - *changed = 0; + bool changed = false; /* Need at least one byte to normalize */ - if (input_len <= 0) return 0; + if(val.empty()) return false; + + auto input = reinterpret_cast(val.data()); + const auto input_len = val.length(); /* * ENH: Deal with UNC and drive letters? @@ -83,7 +51,6 @@ int NormalisePath::normalize_path_inplace(unsigned char *input, int input_len, src = dst = input; end = input + (input_len - 1); - ldst = 1; relative = ((*input == '/') || (win && (*input == '\\'))) ? 0 : 1; trailing = ((*end == '/') || (win && (*end == '\\'))) ? 1 : 0; @@ -94,11 +61,11 @@ int NormalisePath::normalize_path_inplace(unsigned char *input, int input_len, if (win) { if (*src == '\\') { *src = '/'; - *changed = 1; + changed = true; } if ((src < end) && (*(src + 1) == '\\')) { *(src + 1) = '/'; - *changed = 1; + changed = true; } } @@ -116,7 +83,7 @@ int NormalisePath::normalize_path_inplace(unsigned char *input, int input_len, /* Could it be an empty path segment? */ if ((src != end) && *src == '/') { /* Ignore */ - *changed = 1; + changed = true; goto copy; /* Copy will take care of this. */ } else if (*src == '.') { /* Could it be a back or self reference? */ @@ -153,25 +120,25 @@ int NormalisePath::normalize_path_inplace(unsigned char *input, int input_len, } } - if (done) goto length; /* Skip the copy. */ + if (done) goto skip_copy; /* Skip the copy. */ src++; - *changed = 1; + changed = true; } else if (dst == input) { /* Relative Self-reference? */ - *changed = 1; + changed = true; /* Ignore. */ - if (done) goto length; /* Skip the copy. */ + if (done) goto skip_copy; /* Skip the copy. */ src++; } else if (*(dst - 1) == '/') { /* Self-reference? */ - *changed = 1; + changed = true; /* Ignore. */ - if (done) goto length; /* Skip the copy. */ + if (done) goto skip_copy; /* Skip the copy. */ dst--; src++; } @@ -191,7 +158,7 @@ copy: && ((*(src + 1) == '/') || (win && (*(src + 1) == '\\'))) ) { src++; } - if (oldsrc != src) *changed = 1; + if (oldsrc != src) changed = true; /* Do not copy the forward slash to the root * if it is not a relative path. Instead @@ -199,30 +166,28 @@ copy: */ if (relative && (dst == input)) { src++; - goto length; /* Skip the copy */ + goto skip_copy; /* Skip the copy */ } } *(dst++) = *(src++); -length: - ldst = (dst - input); +skip_copy: + ; // nop for the goto label to work } /* Make sure that there is not a trailing slash in the * normalized form if there was not one in the original form. */ if (!trailing && (dst > input) && *(dst - 1) == '/') { - ldst--; dst--; } /* Always NUL terminate */ *dst = '\0'; - return ldst; + val.resize(dst - input); + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/normalise_path.h b/src/actions/transformations/normalise_path.h index b3869bea..a1ef8918 100644 --- a/src/actions/transformations/normalise_path.h +++ b/src/actions/transformations/normalise_path.h @@ -13,37 +13,22 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_H_ #define SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class NormalisePath : public Transformation { public: + using Transformation::Transformation; - explicit NormalisePath(const std::string &action); + bool transform(std::string &value, const Transaction *trans) const override; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; - - static int normalize_path_inplace(unsigned char *input, int input_len, - int win, int *changed); + static bool normalize_path_inplace(std::string &val, const bool win); }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_H_ diff --git a/src/actions/transformations/normalise_path_win.cc b/src/actions/transformations/normalise_path_win.cc index 6c171a59..b60943e1 100644 --- a/src/actions/transformations/normalise_path_win.cc +++ b/src/actions/transformations/normalise_path_win.cc @@ -13,48 +13,17 @@ * */ -#include "src/actions/transformations/normalise_path_win.h" +#include "normalise_path_win.h" -#include - -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" -#include "src/actions/transformations/normalise_path.h" +#include "normalise_path.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string NormalisePathWin::evaluate(const std::string &value, - Transaction *transaction) { - int changed; - - char *tmp = reinterpret_cast( - malloc(sizeof(char) * value.size() + 1)); - memcpy(tmp, value.c_str(), value.size() + 1); - tmp[value.size()] = '\0'; - - int i = NormalisePath::normalize_path_inplace( - reinterpret_cast(tmp), - value.size(), 1, &changed); - - std::string ret(""); - ret.assign(tmp, i); - free(tmp); - - return ret; +bool NormalisePathWin::transform(std::string &value, const Transaction *trans) const { + return NormalisePath::normalize_path_inplace(value, true); } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/normalise_path_win.h b/src/actions/transformations/normalise_path_win.h index a1f8c5f7..0cf11260 100644 --- a/src/actions/transformations/normalise_path_win.h +++ b/src/actions/transformations/normalise_path_win.h @@ -13,33 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_WIN_H_ #define SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_WIN_H_ +#include "transformation.h" -namespace modsecurity { -class Transaction; - -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class NormalisePathWin : public Transformation { public: - explicit NormalisePathWin(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_NORMALISE_PATH_WIN_H_ diff --git a/src/actions/transformations/parity_even_7bit.cc b/src/actions/transformations/parity_even_7bit.cc index 2c0be31c..d9327b9e 100644 --- a/src/actions/transformations/parity_even_7bit.cc +++ b/src/actions/transformations/parity_even_7bit.cc @@ -13,70 +13,15 @@ * */ -#include "src/actions/transformations/parity_even_7bit.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "parity_even_7bit.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string ParityEven7bit::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; - unsigned char *input; - - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - std::memcpy(input, value.c_str(), value.length()+1); - - inplace(input, value.length()); - - ret.assign(reinterpret_cast(input), value.length()); - free(input); - - return ret; -} - -bool ParityEven7bit::inplace(unsigned char *input, uint64_t input_len) { - uint64_t i; - - i = 0; - while (i < input_len) { - unsigned int x = input[i]; - - input[i] ^= input[i] >> 4; - input[i] &= 0xf; - - if ((0x6996 >> input[i]) & 1) { - input[i] = x | 0x80; - } else { - input[i] = x & 0x7f; - } - i++; - } - - return true; +bool ParityEven7bit::transform(std::string &value, const Transaction *trans) const { + return ParityEven7bit::inplace(value); } - -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/parity_even_7bit.h b/src/actions/transformations/parity_even_7bit.h index 08aa8823..8e107a5d 100644 --- a/src/actions/transformations/parity_even_7bit.h +++ b/src/actions/transformations/parity_even_7bit.h @@ -13,33 +13,42 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_PARITY_EVEN_7BIT_H_ #define SRC_ACTIONS_TRANSFORMATIONS_PARITY_EVEN_7BIT_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class ParityEven7bit : public Transformation { public: - explicit ParityEven7bit(const std::string &action) : Transformation(action) { } + using Transformation::Transformation; - std::string evaluate(const std::string &exp, Transaction *transaction) override; - static bool inplace(unsigned char *input, uint64_t input_len); + bool transform(std::string &value, const Transaction *trans) const override; + + template + static bool inplace(std::string &value) { + if (value.empty()) return false; + + for(auto &c : value) { + auto &uc = reinterpret_cast(c); + unsigned int x = uc; + + uc ^= uc >> 4; + uc &= 0xf; + + const bool condition = (0x6996 >> uc) & 1; + if (even ? condition : !condition) { + uc = x | 0x80; + } else { + uc = x & 0x7f; + } + } + + return true; + } }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_PARITY_EVEN_7BIT_H_ diff --git a/src/actions/transformations/parity_odd_7bit.cc b/src/actions/transformations/parity_odd_7bit.cc index 5ac38d20..865a2754 100644 --- a/src/actions/transformations/parity_odd_7bit.cc +++ b/src/actions/transformations/parity_odd_7bit.cc @@ -13,69 +13,16 @@ * */ -#include "src/actions/transformations/parity_odd_7bit.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "parity_odd_7bit.h" +#include "parity_even_7bit.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string ParityOdd7bit::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; - unsigned char *input; - - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - inplace(input, value.length()); - - ret.assign(reinterpret_cast(input), value.length()); - free(input); - - return ret; -} - -bool ParityOdd7bit::inplace(unsigned char *input, uint64_t input_len) { - uint64_t i; - - i = 0; - while (i < input_len) { - unsigned int x = input[i]; - - input[i] ^= input[i] >> 4; - input[i] &= 0xf; - - if ((0x6996 >> input[i]) & 1) { - input[i] = x & 0x7f; - } else { - input[i] = x | 0x80; - } - i++; - } - - return true; +bool ParityOdd7bit::transform(std::string &value, const Transaction *trans) const { + return ParityEven7bit::inplace(value); } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/parity_odd_7bit.h b/src/actions/transformations/parity_odd_7bit.h index 8b7e34d2..0b9164b9 100644 --- a/src/actions/transformations/parity_odd_7bit.h +++ b/src/actions/transformations/parity_odd_7bit.h @@ -13,33 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_PARITY_ODD_7BIT_H_ #define SRC_ACTIONS_TRANSFORMATIONS_PARITY_ODD_7BIT_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class ParityOdd7bit : public Transformation { public: - explicit ParityOdd7bit(const std::string &action) : Transformation(action) { } + using Transformation::Transformation; - std::string evaluate(const std::string &exp, Transaction *transaction) override; - static bool inplace(unsigned char *input, uint64_t input_len); + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_PARITY_ODD_7BIT_H_ diff --git a/src/actions/transformations/parity_zero_7bit.cc b/src/actions/transformations/parity_zero_7bit.cc index 7bb84636..77ad0514 100644 --- a/src/actions/transformations/parity_zero_7bit.cc +++ b/src/actions/transformations/parity_zero_7bit.cc @@ -13,61 +13,26 @@ * */ -#include "src/actions/transformations/parity_zero_7bit.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "parity_zero_7bit.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string ParityZero7bit::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; - unsigned char *input; +static inline bool inplace(std::string &value) { + if (value.empty()) return false; - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - inplace(input, value.length()); - - ret.assign(reinterpret_cast(input), value.length()); - free(input); - - return ret; -} - - -bool ParityZero7bit::inplace(unsigned char *input, uint64_t input_len) { - uint64_t i; - - i = 0; - while (i < input_len) { - input[i] &= 0x7f; - i++; + for(auto &c : value) { + ((unsigned char&)c) &= 0x7f; } return true; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +bool ParityZero7bit::transform(std::string &value, const Transaction *trans) const { + return inplace(value); +} + + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/parity_zero_7bit.h b/src/actions/transformations/parity_zero_7bit.h index 4b4ccd23..aa9d1bf3 100644 --- a/src/actions/transformations/parity_zero_7bit.h +++ b/src/actions/transformations/parity_zero_7bit.h @@ -13,33 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_PARITY_ZERO_7BIT_H_ #define SRC_ACTIONS_TRANSFORMATIONS_PARITY_ZERO_7BIT_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class ParityZero7bit : public Transformation { public: - explicit ParityZero7bit(const std::string &action) : Transformation(action) { } + using Transformation::Transformation; - std::string evaluate(const std::string &exp, Transaction *transaction) override; - static bool inplace(unsigned char *input, uint64_t input_len); + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_PARITY_ZERO_7BIT_H_ diff --git a/src/actions/transformations/remove_comments.cc b/src/actions/transformations/remove_comments.cc index 043dd950..5f3edaef 100644 --- a/src/actions/transformations/remove_comments.cc +++ b/src/actions/transformations/remove_comments.cc @@ -13,61 +13,40 @@ * */ -#include "src/actions/transformations/remove_comments.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "remove_comments.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string RemoveComments::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; - unsigned char *input; +static inline int inplace(std::string &value) { + auto input = reinterpret_cast(value.data()); + const auto input_len = value.length(); + bool changed = false, incomment = false; + std::string::size_type i = 0, j = 0; - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - uint64_t input_len = value.size(); - uint64_t i, j, incomment; - - i = j = incomment = 0; while (i < input_len) { - if (incomment == 0) { + if (!incomment) { if ((input[i] == '/') && (i + 1 < input_len) && (input[i + 1] == '*')) { - incomment = 1; + incomment = true; + changed = true; i += 2; } else if ((input[i] == '<') && (i + 1 < input_len) && (input[i + 1] == '!') && (i + 2 < input_len) && (input[i+2] == '-') && (i + 3 < input_len) && (input[i + 3] == '-')) { - incomment = 1; + incomment = true; + changed = true; i += 4; } else if ((input[i] == '-') && (i + 1 < input_len) && (input[i + 1] == '-')) { input[i] = ' '; + changed = true; break; } else if (input[i] == '#') { input[i] = ' '; + changed = true; break; } else { input[j] = input[i]; @@ -77,7 +56,7 @@ std::string RemoveComments::evaluate(const std::string &value, } else { if ((input[i] == '*') && (i + 1 < input_len) && (input[i + 1] == '/')) { - incomment = 0; + incomment = false; i += 2; input[j] = input[i]; i++; @@ -85,7 +64,7 @@ std::string RemoveComments::evaluate(const std::string &value, } else if ((input[i] == '-') && (i + 1 < input_len) && (input[i + 1] == '-') && (i + 2 < input_len) && (input[i+2] == '>')) { - incomment = 0; + incomment = false; i += 3; input[j] = input[i]; i++; @@ -100,13 +79,14 @@ std::string RemoveComments::evaluate(const std::string &value, input[j++] = ' '; } - ret.assign(reinterpret_cast(input), j); - free(input); - - return ret; + value.resize(j); + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +bool RemoveComments::transform(std::string &value, const Transaction *trans) const { + return inplace(value); +} + + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/remove_comments.h b/src/actions/transformations/remove_comments.h index 78dd213d..948536cb 100644 --- a/src/actions/transformations/remove_comments.h +++ b/src/actions/transformations/remove_comments.h @@ -13,35 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_REMOVE_COMMENTS_H_ #define SRC_ACTIONS_TRANSFORMATIONS_REMOVE_COMMENTS_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; - -namespace actions { -namespace transformations { +#include "transformation.h" +namespace modsecurity::actions::transformations { class RemoveComments : public Transformation { public: - explicit RemoveComments(const std::string &action) : Transformation(action) { } + using Transformation::Transformation; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; - -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_REMOVE_COMMENTS_H_ diff --git a/src/actions/transformations/remove_comments_char.cc b/src/actions/transformations/remove_comments_char.cc index 4c54e68a..7e666db3 100644 --- a/src/actions/transformations/remove_comments_char.cc +++ b/src/actions/transformations/remove_comments_char.cc @@ -13,62 +13,51 @@ * */ -#include "src/actions/transformations/remove_comments_char.h" - -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "remove_comments_char.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -RemoveCommentsChar::RemoveCommentsChar(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} -std::string RemoveCommentsChar::evaluate(const std::string &val, - Transaction *transaction) { - size_t i = 0; - std::string transformed_value; - transformed_value.reserve(val.size()); +bool RemoveCommentsChar::transform(std::string &value, const Transaction *trans) const { + char *d = value.data(); + const char *s = d; + const char *e = s + value.size(); - while (i < val.size()) { - if (val.at(i) == '/' - && (i+1 < val.size()) && val.at(i+1) == '*') { - i += 2; - } else if (val.at(i) == '*' - && (i+1 < val.size()) && val.at(i+1) == '/') { - i += 2; - } else if (val.at(i) == '<' - && (i+1 < val.size()) - && val.at(i+1) == '!' - && (i+2 < val.size()) - && val.at(i+2) == '-' - && (i+3 < val.size()) - && val.at(i+3) == '-') { - i += 4; - } else if (val.at(i) == '-' - && (i+1 < val.size()) && val.at(i+1) == '-' - && (i+2 < val.size()) && val.at(i+2) == '>') { - i += 3; - } else if (val.at(i) == '-' - && (i+1 < val.size()) && val.at(i+1) == '-') { - i += 2; - } else if (val.at(i) == '#') { - i += 1; + while (s < e) { + if (*s == '/' + && (s+1 < e) && *(s+1) == '*') { + s += 2; + } else if (*s == '*' + && (s+1 < e) && *(s+1) == '/') { + s += 2; + } else if (*s == '<' + && (s+1 < e) + && *(s+1) == '!' + && (s+2 < e) + && *(s+2) == '-' + && (s+3 < e) + && *(s+3) == '-') { + s += 4; + } else if (*s == '-' + && (s+1 < e) && *(s+1) == '-' + && (s+2 < e) && *(s+2) == '>') { + s += 3; + } else if (*s == '-' + && (s+1 < e) && *(s+1) == '-') { + s += 2; + } else if (*s == '#') { + s += 1; } else { - transformed_value += val.at(i); - i++; + *d++ = *s++; } } - return transformed_value; + + const auto changed = d != s; + const auto new_len = d - value.c_str(); + value.resize(new_len); + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/remove_comments_char.h b/src/actions/transformations/remove_comments_char.h index 722aba59..d11b0148 100644 --- a/src/actions/transformations/remove_comments_char.h +++ b/src/actions/transformations/remove_comments_char.h @@ -13,33 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_REMOVE_COMMENTS_CHAR_H_ #define SRC_ACTIONS_TRANSFORMATIONS_REMOVE_COMMENTS_CHAR_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class RemoveCommentsChar : public Transformation { public: - explicit RemoveCommentsChar(const std::string &action); + using Transformation::Transformation; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_REMOVE_COMMENTS_CHAR_H_ diff --git a/src/actions/transformations/remove_nulls.cc b/src/actions/transformations/remove_nulls.cc index 2d479c73..1d3cc552 100644 --- a/src/actions/transformations/remove_nulls.cc +++ b/src/actions/transformations/remove_nulls.cc @@ -13,40 +13,15 @@ * */ -#include "src/actions/transformations/remove_nulls.h" - -#include - -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "remove_nulls.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string RemoveNulls::evaluate(const std::string &val, - Transaction *transaction) { - size_t i = 0; - std::string transformed_value; - transformed_value.reserve(val.size()); - - while (i < val.size()) { - if (val.at(i) == '\0') { - // do nothing; continue on to next char in original val - } else { - transformed_value += val.at(i); - } - i++; - } - - return transformed_value; +bool RemoveNulls::transform(std::string &value, const Transaction *trans) const { + return remove_if(value, [](const auto c) { return c == '\0'; }); } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/remove_nulls.h b/src/actions/transformations/remove_nulls.h index eeb33b36..67c90ee0 100644 --- a/src/actions/transformations/remove_nulls.h +++ b/src/actions/transformations/remove_nulls.h @@ -13,34 +13,34 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_REMOVE_NULLS_H_ #define SRC_ACTIONS_TRANSFORMATIONS_REMOVE_NULLS_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +#include + +namespace modsecurity::actions::transformations { class RemoveNulls : public Transformation { public: - explicit RemoveNulls(const std::string &action) - : Transformation(action) { } + using Transformation::Transformation; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; + + template + static bool remove_if(std::string &val, Pred pred) { + const auto old_size = val.size(); + + val.erase( + std::remove_if( + val.begin(), val.end(), pred), + val.end()); + + return val.size() != old_size; + } }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_REMOVE_NULLS_H_ diff --git a/src/actions/transformations/remove_whitespace.cc b/src/actions/transformations/remove_whitespace.cc index 37964663..f7047f47 100644 --- a/src/actions/transformations/remove_whitespace.cc +++ b/src/actions/transformations/remove_whitespace.cc @@ -13,49 +13,27 @@ * */ -#include "src/actions/transformations/remove_whitespace.h" +#include "remove_whitespace.h" -#include +#include "remove_nulls.h" -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +namespace modsecurity::actions::transformations { -namespace modsecurity { -namespace actions { -namespace transformations { - -RemoveWhitespace::RemoveWhitespace(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - -std::string RemoveWhitespace::evaluate(const std::string &val, - Transaction *transaction) { - std::string transformed_value; - transformed_value.reserve(val.size()); - - size_t i = 0; +bool RemoveWhitespace::transform(std::string &value, const Transaction *trans) const { const char nonBreakingSpaces = 0xa0; const char nonBreakingSpaces2 = 0xc2; - // loop through all the chars - while (i < val.size()) { + auto pred = [](const auto c) { // remove whitespaces and non breaking spaces (NBSP) - if (std::isspace(static_cast(val[i])) - || (val[i] == nonBreakingSpaces) - || val[i] == nonBreakingSpaces2) { - // don't copy; continue on to next char in original val - } else { - transformed_value += val.at(i); - } - i++; - } + return std::isspace(static_cast(c)) + || c == nonBreakingSpaces + || c == nonBreakingSpaces2; + }; - return transformed_value; + return RemoveNulls::remove_if(value, pred); } -} // namespace transformations -} // namespace actions -} // namespace modsecurity + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/remove_whitespace.h b/src/actions/transformations/remove_whitespace.h index f977914c..b95a508b 100644 --- a/src/actions/transformations/remove_whitespace.h +++ b/src/actions/transformations/remove_whitespace.h @@ -13,33 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_REMOVE_WHITESPACE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_REMOVE_WHITESPACE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class RemoveWhitespace : public Transformation { public: - explicit RemoveWhitespace(const std::string &action); + using Transformation::Transformation; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_REMOVE_WHITESPACE_H_ diff --git a/src/actions/transformations/replace_comments.cc b/src/actions/transformations/replace_comments.cc index 77e3e3b7..78ae786c 100644 --- a/src/actions/transformations/replace_comments.cc +++ b/src/actions/transformations/replace_comments.cc @@ -13,54 +13,34 @@ * */ -#include "src/actions/transformations/replace_comments.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "replace_comments.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -ReplaceComments::ReplaceComments(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} -std::string ReplaceComments::evaluate(const std::string &value, - Transaction *transaction) { - uint64_t i, j, incomment; +static inline bool inplace(std::string &value) { + auto input = reinterpret_cast(value.data()); + const auto input_len = value.length(); + bool changed = false, incomment = false; + std::string::size_type i = 0, j = 0; - char *input = reinterpret_cast( - malloc(sizeof(char) * value.size() + 1)); - memcpy(input, value.c_str(), value.size() + 1); - input[value.size()] = '\0'; - - i = j = incomment = 0; - while (i < value.size()) { - if (incomment == 0) { - if ((input[i] == '/') && (i + 1 < value.size()) + while (i < input_len) { + if (!incomment) { + if ((input[i] == '/') && (i + 1 < input_len) && (input[i + 1] == '*')) { - incomment = 1; + incomment = true; i += 2; + changed = true; } else { input[j] = input[i]; i++; j++; } } else { - if ((input[i] == '*') && (i + 1 < value.size()) + if ((input[i] == '*') && (i + 1 < input_len) && (input[i + 1] == '/')) { - incomment = 0; + incomment = false; i += 2; input[j] = ' '; j++; @@ -74,15 +54,14 @@ std::string ReplaceComments::evaluate(const std::string &value, input[j++] = ' '; } - - std::string resp; - resp.append(reinterpret_cast(input), j); - - free(input); - - return resp; + value.resize(j); + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity + +bool ReplaceComments::transform(std::string &value, const Transaction *trans) const { + return inplace(value); +} + + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/replace_comments.h b/src/actions/transformations/replace_comments.h index 6808f426..db206e53 100644 --- a/src/actions/transformations/replace_comments.h +++ b/src/actions/transformations/replace_comments.h @@ -13,34 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_REPLACE_COMMENTS_H_ #define SRC_ACTIONS_TRANSFORMATIONS_REPLACE_COMMENTS_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class ReplaceComments : public Transformation { public: + using Transformation::Transformation; - explicit ReplaceComments(const std::string &action) ; - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_REPLACE_COMMENTS_H_ diff --git a/src/actions/transformations/replace_nulls.cc b/src/actions/transformations/replace_nulls.cc index 1af860f4..9792da5d 100644 --- a/src/actions/transformations/replace_nulls.cc +++ b/src/actions/transformations/replace_nulls.cc @@ -13,40 +13,23 @@ * */ -#include "src/actions/transformations/replace_nulls.h" - -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" +#include "replace_nulls.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -ReplaceNulls::ReplaceNulls(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} -std::string ReplaceNulls::evaluate(const std::string &val, - Transaction *transaction) { - int64_t i; - std::string value(val); +bool ReplaceNulls::transform(std::string &value, const Transaction *trans) const { + bool changed = false; - i = 0; - while (i < value.size()) { - if (value.at(i) == '\0') { - value[i] = ' '; - } else { - i++; + for(auto &c : value) { + if (c == '\0') { + c = ' '; + changed = true; } } - return value; + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/replace_nulls.h b/src/actions/transformations/replace_nulls.h index 8e2d315f..a01077c7 100644 --- a/src/actions/transformations/replace_nulls.h +++ b/src/actions/transformations/replace_nulls.h @@ -13,34 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_REPLACE_NULLS_H_ #define SRC_ACTIONS_TRANSFORMATIONS_REPLACE_NULLS_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class ReplaceNulls : public Transformation { public: + using Transformation::Transformation; - explicit ReplaceNulls(const std::string &action) ; - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_REPLACE_NULLS_H_ diff --git a/src/actions/transformations/sha1.cc b/src/actions/transformations/sha1.cc index 9e0c7f53..38863345 100644 --- a/src/actions/transformations/sha1.cc +++ b/src/actions/transformations/sha1.cc @@ -13,35 +13,18 @@ * */ -#include "src/actions/transformations/sha1.h" +#include "sha1.h" -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/sha1.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -Sha1::Sha1(const std::string &action) - : Transformation(action) { - this->action_kind = 1; + +bool Sha1::transform(std::string &value, const Transaction *trans) const { + value = Utils::Sha1::digest(value); + return true; } -std::string Sha1::evaluate(const std::string &value, - Transaction *transaction) { - return Utils::Sha1::digest(value); -} - -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/sha1.h b/src/actions/transformations/sha1.h index eb5fb3f1..f7776411 100644 --- a/src/actions/transformations/sha1.h +++ b/src/actions/transformations/sha1.h @@ -13,32 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_SHA1_H_ #define SRC_ACTIONS_TRANSFORMATIONS_SHA1_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class Sha1 : public Transformation { public: - explicit Sha1(const std::string &action) ; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + using Transformation::Transformation; + + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_SHA1_H_ diff --git a/src/actions/transformations/sql_hex_decode.cc b/src/actions/transformations/sql_hex_decode.cc index 8c8805ff..0ce24087 100644 --- a/src/actions/transformations/sql_hex_decode.cc +++ b/src/actions/transformations/sql_hex_decode.cc @@ -13,101 +13,62 @@ * */ -#include "src/actions/transformations/sql_hex_decode.h" +#include "sql_hex_decode.h" -#include -#include -#include -#include -#include -#include #include -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/string.h" +using namespace modsecurity::utils::string; -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -#ifndef VALID_HEX -#define VALID_HEX(X) (((X >= '0') && (X <= '9')) \ - || ((X >= 'a') && (X <= 'f')) \ - || ((X >= 'A') && (X <= 'F'))) -#endif -#ifndef ISODIGIT -#define ISODIGIT(X) ((X >= '0') && (X <= '7')) -#endif -std::string SqlHexDecode::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; - unsigned char *input; - int size = 0; - - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - size = inplace(input, value.length()); - - ret.assign(reinterpret_cast(input), size); - free(input); - - return ret; +static inline int mytolower(int ch) { + if (ch >= 'A' && ch <= 'Z') + return ('a' + ch - 'A'); + else + return ch; } - -int SqlHexDecode::inplace(unsigned char *data, int len) { - unsigned char *d, *begin = data; - int count = 0; - - if ((data == NULL) || (len == 0)) { - return 0; +static inline bool inplace(std::string &value) { + if (value.empty()) { + return false; } - for (d = data; (++count < len) && *data; *d++ = *data++) { - if (*data != '0') { - continue; - } - ++data; - ++count; - if (mytolower(*data) != 'x') { - data--; - count--; - continue; - } + auto d = reinterpret_cast(value.data()); + const unsigned char *data = d; + const auto end = data + value.size(); - data++; - ++count; + bool changed = false; - // Do we need to keep "0x" if no hexa after? - if (!VALID_HEX(data[0]) || !VALID_HEX(data[1])) { - data -= 2; - count -= 2; - continue; + while (data < end) { + if (data + 3 < end + && *data == '0' + && mytolower(*(data + 1)) == 'x' + && VALID_HEX(*(data + 2)) && VALID_HEX(*(data + 3))) { + data += 2; // skip '0x' + do { + *d++ = utils::string::x2c(data); + data += 2; + } while ((data + 1 < end) && VALID_HEX(*data) && VALID_HEX(*(data + 1))); + changed = true; } - - while (VALID_HEX(data[0]) && VALID_HEX(data[1])) { - *d++ = utils::string::x2c(data); - data += 2; - count += 2; + else { + *d++ = *data++; } } *d = '\0'; - return strlen(reinterpret_cast(begin)); + + value.resize(d - reinterpret_cast(value.c_str())); + return changed; } +bool SqlHexDecode::transform(std::string &value, const Transaction *trans) const { + return inplace(value); +} -} // namespace transformations -} // namespace actions -} // namespace modsecurity + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/sql_hex_decode.h b/src/actions/transformations/sql_hex_decode.h index 9a3afe0f..0acb1cff 100644 --- a/src/actions/transformations/sql_hex_decode.h +++ b/src/actions/transformations/sql_hex_decode.h @@ -13,42 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_SQL_HEX_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_SQL_HEX_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class SqlHexDecode : public Transformation { public: - explicit SqlHexDecode(const std::string &action) : Transformation(action) { } + using Transformation::Transformation; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; - - static int inplace(unsigned char *data, int len); - - static int mytolower(int ch) { - if (ch >= 'A' && ch <= 'Z') - return ('a' + ch - 'A'); - else - return ch; - } + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_SQL_HEX_DECODE_H_ diff --git a/src/actions/transformations/transformation.cc b/src/actions/transformations/transformation.cc index 3b38431a..b6fbf5a3 100644 --- a/src/actions/transformations/transformation.cc +++ b/src/actions/transformations/transformation.cc @@ -13,65 +13,62 @@ * */ -#include "src/actions/transformations/transformation.h" +#include "transformation.h" #include - #include #include #include "modsecurity/transaction.h" #include "modsecurity/actions/action.h" -#include "src/actions/transformations/base64_decode_ext.h" -#include "src/actions/transformations/base64_decode.h" -#include "src/actions/transformations/base64_encode.h" -#include "src/actions/transformations/cmd_line.h" -#include "src/actions/transformations/compress_whitespace.h" -#include "src/actions/transformations/css_decode.h" -#include "src/actions/transformations/escape_seq_decode.h" -#include "src/actions/transformations/hex_decode.h" -#include "src/actions/transformations/hex_encode.h" -#include "src/actions/transformations/html_entity_decode.h" -#include "src/actions/transformations/js_decode.h" -#include "src/actions/transformations/length.h" -#include "src/actions/transformations/lower_case.h" -#include "src/actions/transformations/md5.h" -#include "src/actions/transformations/none.h" -#include "src/actions/transformations/normalise_path.h" -#include "src/actions/transformations/normalise_path_win.h" -#include "src/actions/transformations/parity_even_7bit.h" -#include "src/actions/transformations/parity_odd_7bit.h" -#include "src/actions/transformations/parity_zero_7bit.h" -#include "src/actions/transformations/remove_comments_char.h" -#include "src/actions/transformations/remove_comments.h" -#include "src/actions/transformations/remove_nulls.h" -#include "src/actions/transformations/remove_whitespace.h" -#include "src/actions/transformations/replace_comments.h" -#include "src/actions/transformations/replace_nulls.h" -#include "src/actions/transformations/sha1.h" -#include "src/actions/transformations/sql_hex_decode.h" -#include "src/actions/transformations/trim.h" -#include "src/actions/transformations/trim_left.h" -#include "src/actions/transformations/trim_right.h" -#include "src/actions/transformations/upper_case.h" -#include "src/actions/transformations/url_decode.h" -#include "src/actions/transformations/url_decode_uni.h" -#include "src/actions/transformations/url_encode.h" -#include "src/actions/transformations/utf8_to_unicode.h" + +#include "base64_decode_ext.h" +#include "base64_decode.h" +#include "base64_encode.h" +#include "cmd_line.h" +#include "compress_whitespace.h" +#include "css_decode.h" +#include "escape_seq_decode.h" +#include "hex_decode.h" +#include "hex_encode.h" +#include "html_entity_decode.h" +#include "js_decode.h" +#include "length.h" +#include "lower_case.h" +#include "md5.h" +#include "none.h" +#include "normalise_path.h" +#include "normalise_path_win.h" +#include "parity_even_7bit.h" +#include "parity_odd_7bit.h" +#include "parity_zero_7bit.h" +#include "remove_comments_char.h" +#include "remove_comments.h" +#include "remove_nulls.h" +#include "remove_whitespace.h" +#include "replace_comments.h" +#include "replace_nulls.h" +#include "sha1.h" +#include "sql_hex_decode.h" +#include "trim.h" +#include "trim_left.h" +#include "trim_right.h" +#include "upper_case.h" +#include "url_decode.h" +#include "url_decode_uni.h" +#include "url_encode.h" +#include "utf8_to_unicode.h" #define IF_MATCH(b) \ if (a.compare(2, std::strlen(#b), #b) == 0) -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -std::string Transformation::evaluate(const std::string &value, - Transaction *transaction) { - return value; +bool Transformation::transform(std::string &value, const Transaction *trans) const { + return false; } Transformation* Transformation::instantiate(std::string a) { @@ -119,6 +116,5 @@ Transformation* Transformation::instantiate(std::string a) { return new Transformation(a); } -} // namespace transformations -} // namespace actions -} // namespace modsecurity + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/transformation.h b/src/actions/transformations/transformation.h index f1d81503..1d0ea99a 100644 --- a/src/actions/transformations/transformation.h +++ b/src/actions/transformations/transformation.h @@ -13,37 +13,23 @@ * */ -#include - -#include "modsecurity/actions/action.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_TRANSFORMATION_H_ #define SRC_ACTIONS_TRANSFORMATIONS_TRANSFORMATION_H_ +#include "modsecurity/actions/action.h" -namespace modsecurity { -class Transaction; - -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class Transformation : public Action { public: explicit Transformation(const std::string& _action) - : Action(_action, RunTimeBeforeMatchAttemptKind) { } - - explicit Transformation(const std::string& _action, int kind) - : Action(_action, kind) { } - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + : Action(_action, Kind::RunTimeBeforeMatchAttemptKind) { } static Transformation* instantiate(std::string a); + + virtual bool transform(std::string &value, const Transaction *trans) const; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_TRANSFORMATION_H_ diff --git a/src/actions/transformations/trim.cc b/src/actions/transformations/trim.cc index 5902497f..2056b256 100644 --- a/src/actions/transformations/trim.cc +++ b/src/actions/transformations/trim.cc @@ -13,67 +13,51 @@ * */ -#include "src/actions/transformations/trim.h" +#include "trim.h" -#include -#include #include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" -#include "modsecurity/actions/action.h" - -namespace modsecurity { -namespace actions { -namespace transformations { -std::string *Trim::ltrim(std::string *s) { - s->erase( - s->begin(), - std::find_if(s->begin(), s->end(), [](unsigned char c) { +namespace modsecurity::actions::transformations { + + +bool Trim::ltrim(std::string &s) { + auto it = std::find_if(s.begin(), s.end(), [](unsigned char c) { return !std::isspace(c); - }) - ); + }); - return s; + const bool changed = it != s.begin(); + + s.erase(s.begin(), it); + + return changed; } -std::string *Trim::rtrim(std::string *s) { - s->erase( - std::find_if(s->rbegin(), s->rend(), [](unsigned char c) { +bool Trim::rtrim(std::string &s) { + auto it = std::find_if(s.rbegin(), s.rend(), [](unsigned char c) { return !std::isspace(c); - }).base(), - s->end() - ); + }).base(); - return s; + const bool changed = it != s.end(); + + s.erase(it, s.end()); + + return changed; } -std::string *Trim::trim(std::string *s) { - return ltrim(rtrim(s)); +bool Trim::trim(std::string &s) { + bool changed = false; + changed |= rtrim(s); + changed |= ltrim(s); + return changed; } -Trim::Trim(const std::string &action) - : Transformation(action) { - this->action_kind = 1; +bool Trim::transform(std::string &value, const Transaction *trans) const { + return trim(value); } -std::string -Trim::evaluate(const std::string &val, - Transaction *transaction) { - std::string value(val); - return *this->trim(&value); -} - - -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/trim.h b/src/actions/transformations/trim.h index ac16050c..e436f5bf 100644 --- a/src/actions/transformations/trim.h +++ b/src/actions/transformations/trim.h @@ -13,38 +13,24 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_TRIM_H_ #define SRC_ACTIONS_TRANSFORMATIONS_TRIM_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class Trim : public Transformation { public: + using Transformation::Transformation; - explicit Trim(const std::string &action) ; + bool transform(std::string &value, const Transaction *trans) const override; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; - - std::string *ltrim(std::string *s); - std::string *rtrim(std::string *s); - std::string *trim(std::string *s); + static bool ltrim(std::string &s); + static bool rtrim(std::string &s); + static bool trim(std::string &s); }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_TRIM_H_ diff --git a/src/actions/transformations/trim_left.cc b/src/actions/transformations/trim_left.cc index 50c0cc6a..2ce70149 100644 --- a/src/actions/transformations/trim_left.cc +++ b/src/actions/transformations/trim_left.cc @@ -13,37 +13,16 @@ * */ -#include "src/actions/transformations/trim_left.h" - -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" -#include "src/actions/transformations/trim.h" -#include "modsecurity/actions/action.h" - -namespace modsecurity { -namespace actions { -namespace transformations { +#include "trim_left.h" +#include "trim.h" +namespace modsecurity::actions::transformations { -TrimLeft::TrimLeft(const std::string &action) - : Trim(action) { - this->action_kind = 1; + +bool TrimLeft::transform(std::string &value, const Transaction *trans) const { + return Trim::ltrim(value); } -std::string TrimLeft::evaluate(const std::string &val, - Transaction *transaction) { - std::string value(val); - return *ltrim(&value); -} -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/trim_left.h b/src/actions/transformations/trim_left.h index 54e4885c..8acf1fe5 100644 --- a/src/actions/transformations/trim_left.h +++ b/src/actions/transformations/trim_left.h @@ -13,34 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" -#include "src/actions/transformations/trim.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_TRIM_LEFT_H_ #define SRC_ACTIONS_TRANSFORMATIONS_TRIM_LEFT_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -class TrimLeft : public Trim { +class TrimLeft : public Transformation { public: - explicit TrimLeft(const std::string &action) ; + using Transformation::Transformation; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_TRIM_LEFT_H_ diff --git a/src/actions/transformations/trim_right.cc b/src/actions/transformations/trim_right.cc index 92383f7e..e6536786 100644 --- a/src/actions/transformations/trim_right.cc +++ b/src/actions/transformations/trim_right.cc @@ -13,35 +13,16 @@ * */ -#include "src/actions/transformations/trim_right.h" - -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" -#include "modsecurity/actions/action.h" - -namespace modsecurity { -namespace actions { -namespace transformations { +#include "trim_right.h" +#include "trim.h" -TrimRight::TrimRight(const std::string &action) - : Trim(action) { - this->action_kind = 1; +namespace modsecurity::actions::transformations { + + +bool TrimRight::transform(std::string &value, const Transaction *trans) const { + return Trim::rtrim(value); } -std::string TrimRight::evaluate(const std::string &val, - Transaction *transaction) { - std::string value(val); - return *this->rtrim(&value); -} -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/trim_right.h b/src/actions/transformations/trim_right.h index 9a96b4c5..7e31795a 100644 --- a/src/actions/transformations/trim_right.h +++ b/src/actions/transformations/trim_right.h @@ -13,34 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" -#include "src/actions/transformations/trim.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_TRIM_RIGHT_H_ #define SRC_ACTIONS_TRANSFORMATIONS_TRIM_RIGHT_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -class TrimRight : public Trim { +class TrimRight : public Transformation { public: - explicit TrimRight(const std::string &action) ; + using Transformation::Transformation; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_TRIM_RIGHT_H_ diff --git a/src/actions/transformations/upper_case.cc b/src/actions/transformations/upper_case.cc index 998ec725..2b3978c7 100644 --- a/src/actions/transformations/upper_case.cc +++ b/src/actions/transformations/upper_case.cc @@ -13,37 +13,21 @@ * */ -#include "src/actions/transformations/upper_case.h" -#include -#include -#include +#include "upper_case.h" -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" -#include "modsecurity/actions/action.h" +#include -namespace modsecurity { -namespace actions { -namespace transformations { +#include "lower_case.h" -UpperCase::UpperCase(const std::string &a) - : Transformation(a) { +namespace modsecurity::actions::transformations { + + +bool UpperCase::transform(std::string &value, const Transaction *trans) const { + return LowerCase::convert(value, [](auto c) + { return std::toupper(c); }); } -std::string UpperCase::evaluate(const std::string &val, - Transaction *transaction) { - std::string value(val); - std::locale loc; - for (std::string::size_type i=0; i < value.length(); ++i) { - value[i] = std::toupper(value[i], loc); - } - - return value; -} - -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/upper_case.h b/src/actions/transformations/upper_case.h index f4a77220..87a1df8a 100644 --- a/src/actions/transformations/upper_case.h +++ b/src/actions/transformations/upper_case.h @@ -13,35 +13,20 @@ * */ -#include -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_UPPER_CASE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_UPPER_CASE_H_ -#ifdef __cplusplus - -namespace modsecurity { -class Transaction; -namespace actions { -namespace transformations { +#include "transformation.h" +namespace modsecurity::actions::transformations { class UpperCase : public Transformation { public: - explicit UpperCase(const std::string &action) ; + using Transformation::Transformation; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_UPPER_CASE_H_ diff --git a/src/actions/transformations/url_decode.cc b/src/actions/transformations/url_decode.cc index 845c6a64..dbc7bf9f 100644 --- a/src/actions/transformations/url_decode.cc +++ b/src/actions/transformations/url_decode.cc @@ -13,52 +13,18 @@ * */ -#include "src/actions/transformations/url_decode.h" +#include "url_decode.h" -#include -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/decode.h" -namespace modsecurity { -namespace actions { -namespace transformations { + +namespace modsecurity::actions::transformations { -UrlDecode::UrlDecode(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} - -std::string UrlDecode::evaluate(const std::string &value, - Transaction *transaction) { - unsigned char *val(NULL); - int invalid_count = 0; - int changed; - - val = (unsigned char *) malloc(sizeof(char) * value.size() + 1); - memcpy(val, value.c_str(), value.size() + 1); - val[value.size()] = '\0'; - - int size = utils::urldecode_nonstrict_inplace(val, value.size(), - &invalid_count, &changed); - std::string out; - - out.append((const char *)val, size); - - free(val); - - return out; +bool UrlDecode::transform(std::string &value, const Transaction *trans) const { + int invalid_count; + return utils::urldecode_nonstrict_inplace(value, invalid_count); } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/url_decode.h b/src/actions/transformations/url_decode.h index e965dae7..cc73c9c3 100644 --- a/src/actions/transformations/url_decode.h +++ b/src/actions/transformations/url_decode.h @@ -13,36 +13,20 @@ * */ -#include -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_URL_DECODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_URL_DECODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; - -namespace actions { -namespace transformations { +#include "transformation.h" +namespace modsecurity::actions::transformations { class UrlDecode : public Transformation { public: + using Transformation::Transformation; - explicit UrlDecode(const std::string &action) ; - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_URL_DECODE_H_ diff --git a/src/actions/transformations/url_decode_uni.cc b/src/actions/transformations/url_decode_uni.cc index ad5b8111..58d683c8 100644 --- a/src/actions/transformations/url_decode_uni.cc +++ b/src/actions/transformations/url_decode_uni.cc @@ -13,65 +13,29 @@ * */ -#include "src/actions/transformations/url_decode_uni.h" +#include "url_decode_uni.h" -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "modsecurity/rules_set_properties.h" #include "modsecurity/rules_set.h" -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/string.h" -#include "src/utils/system.h" +using namespace modsecurity::utils::string; -namespace modsecurity { -namespace actions { -namespace transformations { - - -std::string UrlDecodeUni::evaluate(const std::string &value, - Transaction *t) { - std::string ret; - unsigned char *input; - - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - size_t i = inplace(input, value.length(), t); - - ret.assign(reinterpret_cast(input), i); - free(input); - - return ret; -} +namespace modsecurity::actions::transformations { /** * * IMP1 Assumes NUL-terminated */ -int UrlDecodeUni::inplace(unsigned char *input, uint64_t input_len, - Transaction *t) { - unsigned char *d = input; - int64_t i, count, fact, j, xv; - int Code, hmap = -1; +static inline bool inplace(std::string &value, + const Transaction *t) { + bool changed = false; + auto d = reinterpret_cast(value.data()); + const unsigned char *input = d; + const auto input_len = value.length(); - if (input == NULL) return -1; + std::string::size_type i, count, fact, j, xv; + int Code, hmap = -1; i = count = 0; while (i < input_len) { @@ -131,19 +95,17 @@ int UrlDecodeUni::inplace(unsigned char *input, uint64_t input_len, } } d++; - count++; i += 6; + changed = true; } else { /* Invalid data, skip %u. */ *d++ = input[i++]; *d++ = input[i++]; - count += 2; } } else { /* Not enough bytes (4 data bytes), skip %u. */ *d++ = input[i++]; *d++ = input[i++]; - count += 2; } } else { /* Standard URL encoding. */ @@ -158,8 +120,8 @@ int UrlDecodeUni::inplace(unsigned char *input, uint64_t input_len, if (VALID_HEX(c1) && VALID_HEX(c2)) { *d++ = utils::string::x2c(&input[i + 1]); - count++; i += 3; + changed = true; } else { /* Not a valid encoding, skip this % */ *d++ = input[i++]; @@ -168,28 +130,32 @@ int UrlDecodeUni::inplace(unsigned char *input, uint64_t input_len, } else { /* Not enough bytes available, skip this % */ *d++ = input[i++]; - count++; } } } else { /* Character is not a percent sign. */ if (input[i] == '+') { *d++ = ' '; + changed = true; } else { *d++ = input[i]; } - count++; i++; } } *d = '\0'; - return count; + value.resize(d - input); + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity + +bool UrlDecodeUni::transform(std::string &value, const Transaction *trans) const { + return inplace(value, trans); +} + + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/url_decode_uni.h b/src/actions/transformations/url_decode_uni.h index d7b0dd21..046f251a 100644 --- a/src/actions/transformations/url_decode_uni.h +++ b/src/actions/transformations/url_decode_uni.h @@ -13,35 +13,20 @@ * */ -#include - -#include "modsecurity/rules_set_properties.h" -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_URL_DECODE_UNI_H_ #define SRC_ACTIONS_TRANSFORMATIONS_URL_DECODE_UNI_H_ +#include "transformation.h" -#ifdef __cplusplus -namespace modsecurity { -class Transaction; -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class UrlDecodeUni : public Transformation { public: - explicit UrlDecodeUni(const std::string &action) : Transformation(action) { } + using Transformation::Transformation; - std::string evaluate(const std::string &exp, Transaction *transaction) override; - static int inplace(unsigned char *input, uint64_t input_len, - Transaction *transaction); + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_URL_DECODE_UNI_H_ diff --git a/src/actions/transformations/url_encode.cc b/src/actions/transformations/url_encode.cc index 19ecb334..2692a2d3 100644 --- a/src/actions/transformations/url_encode.cc +++ b/src/actions/transformations/url_encode.cc @@ -13,90 +13,50 @@ * */ -#include "src/actions/transformations/url_encode.h" +#include "url_encode.h" -#include -#include -#include -#include -#include -#include - -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/string.h" -namespace modsecurity { -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { -UrlEncode::UrlEncode(const std::string &action) - : Transformation(action) { - this->action_kind = 1; -} +static inline bool url_enc(std::string &value) { + const auto len = value.size() * 3 + 1; + std::string ret(len, {}); - -std::string UrlEncode::url_enc(const char *input, - unsigned int input_len, int *changed) { - char *rval, *d; - unsigned int i, len; - int count = 0; - - *changed = 0; - - len = input_len * 3 + 1; - d = rval = reinterpret_cast(malloc(len)); - if (rval == NULL) { - return NULL; - } + bool changed = false; /* ENH Only encode the characters that really need to be encoded. */ - for (i = 0; i < input_len; i++) { - unsigned char c = input[i]; - + char *d = ret.data(); + for (const auto c : value) { if (c == ' ') { *d++ = '+'; - *changed = 1; - count++; + changed = true; } else { if ( (c == 42) || ((c >= 48) && (c <= 57)) || ((c >= 65) && (c <= 90)) || ((c >= 97) && (c <= 122))) { *d++ = c; - count++; - } else { + } + else + { *d++ = '%'; - count++; - utils::string::c2x(c, (unsigned char *)d); - d += 2; - count++; - count++; - *changed = 1; + d = (char *)utils::string::c2x(c, (unsigned char *)d); + changed = true; } } } - *d = '\0'; - - std::string ret(""); - ret.append(rval, count); - free(rval); - return ret; + ret.resize(d - ret.c_str()); + std::swap(value, ret); + return changed; } -std::string UrlEncode::evaluate(const std::string &value, - Transaction *transaction) { - int changed; - - std::string ret = url_enc(value.c_str(), value.size(), &changed); - - return ret; +bool UrlEncode::transform(std::string &value, const Transaction *trans) const { + return url_enc(value); } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/url_encode.h b/src/actions/transformations/url_encode.h index a45be564..e112fb57 100644 --- a/src/actions/transformations/url_encode.h +++ b/src/actions/transformations/url_encode.h @@ -13,37 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_URL_ENCODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_URL_ENCODE_H_ -#ifdef __cplusplus -namespace modsecurity { -class Transaction; +#include "transformation.h" -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class UrlEncode : public Transformation { public: + using Transformation::Transformation; - explicit UrlEncode(const std::string &action) ; - - std::string evaluate(const std::string &exp, - Transaction *transaction) override; - - std::string url_enc(const char *input, - unsigned int input_len, int *changed); + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - -#endif +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_URL_ENCODE_H_ diff --git a/src/actions/transformations/utf8_to_unicode.cc b/src/actions/transformations/utf8_to_unicode.cc index 70c1f9c8..4b01583e 100644 --- a/src/actions/transformations/utf8_to_unicode.cc +++ b/src/actions/transformations/utf8_to_unicode.cc @@ -13,83 +13,40 @@ * */ -#include "src/actions/transformations/utf8_to_unicode.h" +#include "utf8_to_unicode.h" -#include -#include -#include -#include -#include -#include #include -#include "modsecurity/transaction.h" -#include "src/actions/transformations/transformation.h" #include "src/utils/string.h" -namespace modsecurity { -namespace actions { -namespace transformations { +constexpr int UNICODE_ERROR_CHARACTERS_MISSING = -1; +constexpr int UNICODE_ERROR_INVALID_ENCODING = -2; -std::string Utf8ToUnicode::evaluate(const std::string &value, - Transaction *transaction) { - std::string ret; - unsigned char *input; - int changed = 0; - char *out; - - input = reinterpret_cast - (malloc(sizeof(char) * value.length()+1)); - - if (input == NULL) { - return ""; - } - - memcpy(input, value.c_str(), value.length()+1); - - out = inplace(input, value.size() + 1, &changed); - free(input); - if (out != NULL) { - ret.assign(reinterpret_cast(out), - strlen(reinterpret_cast(out))); - free(out); - } - - return ret; -} +namespace modsecurity::actions::transformations { -char *Utf8ToUnicode::inplace(unsigned char *input, - uint64_t input_len, int *changed) { - unsigned int count = 0; - char *data; - char *data_orig; - unsigned int i, len, j; - unsigned int bytes_left = input_len; +static inline bool encode(std::string &value) { + auto input = reinterpret_cast(value.data()); + const auto input_len = value.length(); + + bool changed = false; + std::string::size_type count = 0; + auto bytes_left = input_len; unsigned char unicode[8]; - *changed = 0; /* RFC3629 states that UTF-8 are encoded using sequences of 1 to 4 octets. */ /* Max size per character should fit in 4 bytes */ - len = input_len * 4 + 1; - data = reinterpret_cast(malloc(sizeof(char) * len)); - if (data == NULL) { - return NULL; - } - data_orig = data; + const auto len = input_len * 4 + 1; + std::string ret(len, {}); + auto data = ret.data(); - if (input == NULL) { - free(data); - return NULL; - } - - for (i = 0; i < bytes_left;) { + for (std::string::size_type i = 0; i < bytes_left;) { int unicode_len = 0; unsigned int d = 0; unsigned char c; - unsigned char *utf = (unsigned char *)&input[i]; + auto utf = &input[i]; c = *utf; @@ -117,7 +74,7 @@ char *Utf8ToUnicode::inplace(unsigned char *input, unicode_len = UNICODE_ERROR_INVALID_ENCODING; } else { unicode_len = 2; - count+=6; + count += 6; if (count <= len) { int length = 0; /* compute character number */ @@ -147,11 +104,11 @@ char *Utf8ToUnicode::inplace(unsigned char *input, break; } - for (j = 0; j < length; j++) { + for (std::string::size_type j = 0; j < length; j++) { *data++ = unicode[j]; } - *changed = 1; + changed = true; } } } else if ((c & 0xF0) == 0xE0) { @@ -199,11 +156,11 @@ char *Utf8ToUnicode::inplace(unsigned char *input, break; } - for (j = 0; j < length; j++) { + for (std::string::size_type j = 0; j < length; j++) { *data++ = unicode[j]; } - *changed = 1; + changed = true; } } } else if ((c & 0xF8) == 0xF0) { @@ -261,11 +218,11 @@ char *Utf8ToUnicode::inplace(unsigned char *input, break; } - for (j = 0; j < length; j++) { + for (std::string::size_type j = 0; j < length; j++) { *data++ = unicode[j]; } - *changed = 1; + changed = true; } } } else { @@ -309,10 +266,15 @@ char *Utf8ToUnicode::inplace(unsigned char *input, *data ='\0'; - return data_orig; + ret.resize(data - ret.c_str()); + std::swap(value, ret); + return changed; } -} // namespace transformations -} // namespace actions -} // namespace modsecurity +bool Utf8ToUnicode::transform(std::string &value, const Transaction *trans) const { + return encode(value); +} + + +} // namespace modsecurity::actions::transformations diff --git a/src/actions/transformations/utf8_to_unicode.h b/src/actions/transformations/utf8_to_unicode.h index 4d488410..af125338 100644 --- a/src/actions/transformations/utf8_to_unicode.h +++ b/src/actions/transformations/utf8_to_unicode.h @@ -13,40 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_ACTIONS_TRANSFORMATIONS_UTF8_TO_UNICODE_H_ #define SRC_ACTIONS_TRANSFORMATIONS_UTF8_TO_UNICODE_H_ -#define UNICODE_ERROR_CHARACTERS_MISSING -1 -#define UNICODE_ERROR_INVALID_ENCODING -2 -#define UNICODE_ERROR_OVERLONG_CHARACTER -3 -#define UNICODE_ERROR_RESTRICTED_CHARACTER -4 -#define UNICODE_ERROR_DECODING_ERROR -5 +#include "transformation.h" -namespace modsecurity { -class Transaction; - -namespace actions { -namespace transformations { +namespace modsecurity::actions::transformations { class Utf8ToUnicode : public Transformation { public: - explicit Utf8ToUnicode(const std::string &action) : Transformation(action) { } + using Transformation::Transformation; - std::string evaluate(const std::string &exp, - Transaction *transaction) override; - - static char *inplace(unsigned char *input, uint64_t input_len, - int *changed); + bool transform(std::string &value, const Transaction *trans) const override; }; -} // namespace transformations -} // namespace actions -} // namespace modsecurity - +} // namespace modsecurity::actions::transformations #endif // SRC_ACTIONS_TRANSFORMATIONS_UTF8_TO_UNICODE_H_ diff --git a/src/actions/ver.cc b/src/actions/ver.cc index 43b8b832..d7b8bdc4 100644 --- a/src/actions/ver.cc +++ b/src/actions/ver.cc @@ -15,16 +15,10 @@ #include "src/actions/ver.h" -#include -#include - -#include "modsecurity/actions/action.h" -#include "modsecurity/transaction.h" -#include "modsecurity/rule.h" +#include "modsecurity/rule_with_actions.h" -namespace modsecurity { -namespace actions { +namespace modsecurity::actions { bool Ver::evaluate(RuleWithActions *rule, Transaction *transaction) { @@ -33,5 +27,4 @@ bool Ver::evaluate(RuleWithActions *rule, Transaction *transaction) { } -} // namespace actions -} // namespace modsecurity +} // namespace modsecurity::actions diff --git a/src/actions/ver.h b/src/actions/ver.h index 364d567b..8bce189c 100644 --- a/src/actions/ver.h +++ b/src/actions/ver.h @@ -29,7 +29,7 @@ namespace actions { class Ver : public Action { public: - explicit Ver(const std::string &action) : Action(action, ConfigurationKind) { } + explicit Ver(const std::string &action) : Action(action, Kind::ConfigurationKind) { } bool evaluate(RuleWithActions *rule, Transaction *transaction) override; diff --git a/src/audit_log/writer/parallel.cc b/src/audit_log/writer/parallel.cc index d23e7958..5237adb7 100644 --- a/src/audit_log/writer/parallel.cc +++ b/src/audit_log/writer/parallel.cc @@ -51,28 +51,27 @@ Parallel::~Parallel() { inline std::string Parallel::logFilePath(time_t *t, int part) { - struct tm timeinfo; - char tstr[300]; - std::string name(""); + std::string name; + struct tm timeinfo; localtime_r(t, &timeinfo); if (part & YearMonthDayDirectory) { - memset(tstr, '\0', 300); - strftime(tstr, 299, "/%Y%m%d", &timeinfo); - name = tstr; + char tstr[std::size("/yyyymmdd")]; + strftime(tstr, std::size(tstr), "/%Y%m%d", &timeinfo); + name.append(tstr); } if (part & YearMonthDayAndTimeDirectory) { - memset(tstr, '\0', 300); - strftime(tstr, 299, "/%Y%m%d-%H%M", &timeinfo); - name = name + tstr; + char tstr[std::size("/yyyymmdd-hhmm")]; + strftime(tstr, std::size(tstr), "/%Y%m%d-%H%M", &timeinfo); + name.append(tstr); } if (part & YearMonthDayAndTimeFileName) { - memset(tstr, '\0', 300); - strftime(tstr, 299, "/%Y%m%d-%H%M%S", &timeinfo); - name = name + tstr; + char tstr[std::size("/yyyymmdd-hhmmss")]; + strftime(tstr, std::size(tstr), "/%Y%m%d-%H%M%S", &timeinfo); + name.append(tstr); } return name; diff --git a/src/collection/backend/in_memory-per_process.cc b/src/collection/backend/in_memory-per_process.cc index a4ca5e2e..b16ee843 100644 --- a/src/collection/backend/in_memory-per_process.cc +++ b/src/collection/backend/in_memory-per_process.cc @@ -25,8 +25,6 @@ #include #endif -#include - #include "modsecurity/variable_value.h" #include "src/utils/regex.h" #include "src/utils/string.h" @@ -39,26 +37,48 @@ namespace backend { InMemoryPerProcess::InMemoryPerProcess(const std::string &name) : Collection(name) { - this->reserve(1000); - pthread_mutex_init(&m_lock, NULL); + m_map.reserve(1000); } InMemoryPerProcess::~InMemoryPerProcess() { - this->clear(); - pthread_mutex_destroy(&m_lock); + m_map.clear(); } -void InMemoryPerProcess::store(std::string key, std::string value) { - pthread_mutex_lock(&m_lock); - this->emplace(key, value); - pthread_mutex_unlock(&m_lock); + +template +inline void __store(Map &map, std::string key, std::string value) { + // NOTE: should be called with write-lock previously acquired + + map.emplace(key, value); +} + + +template +inline bool __updateFirst(Map &map, + const std::string &key, + const std::string &value) { + // NOTE: should be called with write-lock previously acquired + + if (auto search = map.find(key); search != map.end()) { + search->second.setValue(value); + return true; + } + + return false; +} + + +void InMemoryPerProcess::store(const std::string &key, const std::string &value) { + const std::lock_guard lock(m_mutex); // write lock (exclusive access) + __store(m_map, key, value); } bool InMemoryPerProcess::storeOrUpdateFirst(const std::string &key, const std::string &value) { - if (updateFirst(key, value) == false) { - store(key, value); + const std::lock_guard lock(m_mutex); // write lock (exclusive access) + if (__updateFirst(m_map, key, value) == false) { + __store(m_map, key, value); } return true; } @@ -66,66 +86,59 @@ bool InMemoryPerProcess::storeOrUpdateFirst(const std::string &key, bool InMemoryPerProcess::updateFirst(const std::string &key, const std::string &value) { - pthread_mutex_lock(&m_lock); - - if (auto search = this->find(key); search != this->end()) { - search->second.setValue(value); - pthread_mutex_unlock(&m_lock); - return true; - } - - pthread_mutex_unlock(&m_lock); - return false; + const std::lock_guard lock(m_mutex); // write lock (exclusive access) + return __updateFirst(m_map, key, value); } void InMemoryPerProcess::del(const std::string& key) { - pthread_mutex_lock(&m_lock); - this->erase(key); - pthread_mutex_unlock(&m_lock); + const std::lock_guard lock(m_mutex); // write lock (exclusive access) + m_map.erase(key); } void InMemoryPerProcess::delIfExpired(const std::string& key) { - pthread_mutex_lock(&m_lock); + const std::lock_guard lock(m_mutex); // write lock (exclusive access) // Double check the status while within the mutex - auto iter = this->find(key); - if ((iter != this->end()) && (iter->second.isExpired())) { - this->erase(key); + const auto iter = std::find_if(m_map.begin(), m_map.end(), + [&key](const auto &x) { return x.first == key && x.second.isExpired(); }); + if (iter != m_map.end()) { + m_map.erase(key); } - pthread_mutex_unlock(&m_lock); } void InMemoryPerProcess::setExpiry(const std::string& key, int32_t expiry_seconds) { - pthread_mutex_lock(&m_lock); + const std::lock_guard lock(m_mutex); // write lock (exclusive access) - if (auto search = this->find(key); search != this->end()) { + if (const auto search = m_map.find(key); search != m_map.end()) { search->second.setExpiry(expiry_seconds); - pthread_mutex_unlock(&m_lock); return; } // We allow an expiry value to be set for a key that has not (yet) had a value set. - auto iter = this->emplace(key, CollectionData()); + const auto iter = m_map.emplace(key, CollectionData()); iter->second.setExpiry(expiry_seconds); - - pthread_mutex_unlock(&m_lock); } void InMemoryPerProcess::resolveSingleMatch(const std::string& var, std::vector *l) { std::list expiredVars; - auto range = this->equal_range(var); - for (auto it = range.first; it != range.second; ++it) { - if (it->second.isExpired()) { - expiredVars.push_back(it->first); - } else if (it->second.hasValue() == false) { - // No-op. A non-expired expiry exists for the key but there is no actual value - } else { - l->push_back(new VariableValue(&m_name, &it->first, &it->second.getValue())); - } + { + const std::shared_lock lock(m_mutex); // read lock (shared access) + + const auto range = m_map.equal_range(var); + for (auto it = range.first; it != range.second; ++it) { + if (it->second.isExpired()) { + expiredVars.push_back(it->first); + } else if (it->second.hasValue() == false) { + // No-op. A non-expired expiry exists for the key but there is no actual value + } else { + l->push_back(new VariableValue(&m_name, &it->first, &it->second.getValue())); + } + } } + for (const auto& expiredVar : expiredVars) { delIfExpired(expiredVar); } @@ -134,40 +147,45 @@ void InMemoryPerProcess::resolveSingleMatch(const std::string& var, void InMemoryPerProcess::resolveMultiMatches(const std::string& var, std::vector *l, variables::KeyExclusions &ke) { - size_t keySize = var.size(); + const auto keySize = var.size(); l->reserve(15); std::list expiredVars; - if (keySize == 0) { - for (auto &i : *this) { - if (ke.toOmit(i.first)) { - continue; + { + const std::shared_lock lock(m_mutex); // read lock (shared access) + + if (keySize == 0) { + for (auto &i : m_map) { + if (ke.toOmit(i.first)) { + continue; + } + if (i.second.isExpired()) { + expiredVars.push_back(i.first); + } else if (i.second.hasValue() == false) { + // No-op. A non-expired expiry exists for the key but there is no actual value + } else { + l->insert(l->begin(), new VariableValue(&m_name, &i.first, + &i.second.getValue())); + } } - if (i.second.isExpired()) { - expiredVars.push_back(i.first); - } else if (i.second.hasValue() == false) { - // No-op. A non-expired expiry exists for the key but there is no actual value - } else { - l->insert(l->begin(), new VariableValue(&m_name, &i.first, - &i.second.getValue())); - } - } - } else { - auto range = this->equal_range(var); - for (auto it = range.first; it != range.second; ++it) { - if (ke.toOmit(var)) { - continue; + } else { + const auto range = m_map.equal_range(var); + for (auto it = range.first; it != range.second; ++it) { + if (ke.toOmit(var)) { + continue; + } + if (it->second.isExpired()) { + expiredVars.push_back(it->first); + } else if (it->second.hasValue() == false) { + // No-op. A non-expired expiry exists for the key but there is no actual value + } else { + l->insert(l->begin(), new VariableValue(&m_name, &var, + &it->second.getValue())); + } } - if (it->second.isExpired()) { - expiredVars.push_back(it->first); - } else if (it->second.hasValue() == false) { - // No-op. A non-expired expiry exists for the key but there is no actual value - } else { - l->insert(l->begin(), new VariableValue(&m_name, &var, - &it->second.getValue())); - } } } + for (const auto& expiredVar : expiredVars) { delIfExpired(expiredVar); } @@ -176,47 +194,30 @@ void InMemoryPerProcess::resolveMultiMatches(const std::string& var, void InMemoryPerProcess::resolveRegularExpression(const std::string& var, std::vector *l, variables::KeyExclusions &ke) { - - //if (var.find(":") == std::string::npos) { - // return; - //} - //if (var.size() < var.find(":") + 3) { - // return; - //} - //std::string col = std::string(var, 0, var.find(":")); - //std::string name = std::string(var, var.find(":") + 2, - // var.size() - var.find(":") - 3); - //size_t keySize = col.size(); Utils::Regex r(var, true); std::list expiredVars; - for (const auto& x : *this) { - //if (x.first.size() <= keySize + 1) { - // continue; - //} - //if (x.first.at(keySize) != ':') { - // continue; - //} - //if (std::string(x.first, 0, keySize) != col) { - // continue; - //} - //std::string content = std::string(x.first, keySize + 1, - // x.first.size() - keySize - 1); - int ret = Utils::regex_search(x.first, r); - if (ret <= 0) { - continue; + { + const std::shared_lock lock(m_mutex); // read lock (shared access) + + for (const auto& x : m_map) { + const auto ret = Utils::regex_search(x.first, r); + if (ret <= 0) { + continue; + } + if (ke.toOmit(x.first)) { + continue; + } + if (x.second.isExpired()) { + expiredVars.push_back(x.first); + } else if (x.second.hasValue() == false) { + // No-op. A non-expired expiry exists for the key but there is no actual value + } else { + l->insert(l->begin(), new VariableValue(&m_name, &x.first, &x.second.getValue())); + } } - if (ke.toOmit(x.first)) { - continue; - } - if (x.second.isExpired()) { - expiredVars.push_back(x.first); - } else if (x.second.hasValue() == false) { - // No-op. A non-expired expiry exists for the key but there is no actual value - } else { - l->insert(l->begin(), new VariableValue(&m_name, &x.first, &x.second.getValue())); - } } + for (const auto& expiredVar : expiredVars) { delIfExpired(expiredVar); } @@ -225,18 +226,29 @@ void InMemoryPerProcess::resolveRegularExpression(const std::string& var, std::unique_ptr InMemoryPerProcess::resolveFirst( const std::string& var) { - auto range = equal_range(var); - for (auto it = range.first; it != range.second; ++it) { - if (it->second.isExpired()) { - delIfExpired(it->second.getValue()); - } else if (it->second.hasValue() == false) { - // No-op. A non-expired expiry exists for the key but there is no actual value - } else { - return std::unique_ptr(new std::string(it->second.getValue())); - } + std::unique_ptr ret; + std::list expiredVars; + + { + const std::shared_lock lock(m_mutex); // read lock (shared access) + + const auto range = m_map.equal_range(var); + for (auto it = range.first; it != range.second; ++it) { + if (it->second.isExpired()) { + expiredVars.push_back(it->first); + } else if (it->second.hasValue() == false) { + // No-op. A non-expired expiry exists for the key but there is no actual value + } else { + ret = std::make_unique(it->second.getValue()); + } + } } - return NULL; + for (const auto& expiredVar : expiredVars) { + delIfExpired(expiredVar); + } + + return ret; } diff --git a/src/collection/backend/in_memory-per_process.h b/src/collection/backend/in_memory-per_process.h index 3cacdca0..2e283d25 100644 --- a/src/collection/backend/in_memory-per_process.h +++ b/src/collection/backend/in_memory-per_process.h @@ -12,7 +12,6 @@ * directly using the email address security@modsecurity.org. * */ -#include #ifdef __cplusplus @@ -24,6 +23,7 @@ #include #include #include +#include #endif @@ -71,13 +71,11 @@ struct MyHash{ }; class InMemoryPerProcess : - public std::unordered_multimap*/MyHash, MyEqual>, public Collection { public: explicit InMemoryPerProcess(const std::string &name); ~InMemoryPerProcess(); - void store(std::string key, std::string value); + void store(const std::string &key, const std::string &value); bool storeOrUpdateFirst(const std::string &key, const std::string &value) override; @@ -103,21 +101,23 @@ class InMemoryPerProcess : variables::KeyExclusions &ke) override; /* store */ - virtual void store(std::string key, std::string compartment, + virtual void store(const std::string &key, std::string &compartment, std::string value) { - std::string nkey = compartment + "::" + key; + const auto nkey = compartment + "::" + key; store(nkey, value); } - virtual void store(std::string key, std::string compartment, + virtual void store(const std::string &key, const std::string &compartment, std::string compartment2, std::string value) { - std::string nkey = compartment + "::" + compartment2 + "::" + key; + const auto nkey = compartment + "::" + compartment2 + "::" + key; store(nkey, value); } private: - pthread_mutex_t m_lock; + std::unordered_multimap*/MyHash, MyEqual> m_map; + std::shared_mutex m_mutex; }; } // namespace backend diff --git a/src/collection/backend/lmdb.cc b/src/collection/backend/lmdb.cc index 85c68e3c..4a77f5fb 100644 --- a/src/collection/backend/lmdb.cc +++ b/src/collection/backend/lmdb.cc @@ -27,8 +27,6 @@ #include #include -#include - #include "modsecurity/variable_value.h" #include "src/utils/regex.h" #include "src/variables/variable.h" diff --git a/src/collection/backend/lmdb.h b/src/collection/backend/lmdb.h index 15c4fa9f..49633e37 100644 --- a/src/collection/backend/lmdb.h +++ b/src/collection/backend/lmdb.h @@ -27,12 +27,10 @@ #ifdef WITH_LMDB #include -#include #endif // WITH_LMDB #include #include #include -#include #include "modsecurity/variable_value.h" #include "modsecurity/collection/collection.h" diff --git a/src/engine/lua.cc b/src/engine/lua.cc index 0fac4f64..1bed9044 100644 --- a/src/engine/lua.cc +++ b/src/engine/lua.cc @@ -185,7 +185,7 @@ int Lua::run(Transaction *t, const std::string &str) { lua_getglobal(L, "main"); - ms_dbg_a(t, 1, str); + ms_dbg_a(t, 9, str); /* Put the parameter on the stack. */ if (!str.empty() ) { @@ -267,7 +267,7 @@ int Lua::getvar(lua_State *L) { t = reinterpret_cast(z); std::string var = variables::Variable::stringMatchResolve(t, varname); - var = applyTransformations(L, t, 2, var); + applyTransformations(L, t, 2, var); if (var.size() == 0) { lua_pushnil(L); @@ -407,12 +407,10 @@ int Lua::setvar(lua_State *L) { } -std::string Lua::applyTransformations(lua_State *L, Transaction *t, - int idx, std::string var) { - std::string newVar = var; - +void Lua::applyTransformations(lua_State *L, const Transaction *t, + int idx, std::string &var) { if (lua_isuserdata(L, idx) || lua_isnoneornil(L, idx)) { - return var; + return; } if (lua_istable(L, idx)) { @@ -429,16 +427,15 @@ std::string Lua::applyTransformations(lua_State *L, Transaction *t, /* A "none" means start over */ if (strcmp("none", name) == 0) { - newVar = var; continue; } - actions::transformations::Transformation *tfn = \ + auto tfn = \ actions::transformations::Transformation::instantiate( "t:" + std::string(name)); // FIXME: transformation is not yet returning null. if (tfn) { - newVar = tfn->evaluate(newVar, t); + tfn->transform(var, t); } else { ms_dbg_a(t, 1, "SecRuleScript: Invalid transformation function: " \ @@ -447,32 +444,31 @@ std::string Lua::applyTransformations(lua_State *L, Transaction *t, delete tfn; } - return newVar; + return; } if (lua_isstring(L, idx)) { const char *name(NULL); name = reinterpret_cast(luaL_checkstring(L, idx)); - actions::transformations::Transformation *tfn = \ + auto tfn = \ actions::transformations::Transformation::instantiate( "t:" + std::string(name)); // FIXME: transformation is not yet returning null. if (tfn) { - newVar = tfn->evaluate(newVar, t); + tfn->transform(var, t); delete tfn; } else { ms_dbg_a(t, 1, "SecRuleScript: Invalid transformation function: " \ + std::string(name)); } - return newVar; + return; } ms_dbg_a(t, 8, "SecRuleScript: Transformation parameter must be a " \ "transformation name or array of transformation names, but found " \ "" + std::string(lua_typename(L, idx)) + " (type " \ + std::to_string(lua_type(L, idx)) + ")"); - return newVar; } #endif diff --git a/src/engine/lua.h b/src/engine/lua.h index a33f28f8..452c7f49 100644 --- a/src/engine/lua.h +++ b/src/engine/lua.h @@ -79,8 +79,8 @@ class Lua { static int getvar(lua_State *L); static int getvars(lua_State *L); static int setvar(lua_State *L); - static std::string applyTransformations(lua_State *L, Transaction *t, - int idx, std::string var); + static void applyTransformations(lua_State *L, const Transaction *t, + int idx, std::string &var); LuaScriptBlob m_blob; #endif diff --git a/src/modsecurity.cc b/src/modsecurity.cc index 855facb3..93caa952 100644 --- a/src/modsecurity.cc +++ b/src/modsecurity.cc @@ -300,7 +300,6 @@ int ModSecurity::processContentOffset(const char *content, size_t len, while (!trans.empty()) { modsecurity::actions::transformations::Transformation *t; - std::string varValueRes; yajl_gen_map_open(g); yajl_gen_string(g, reinterpret_cast("transformation"), @@ -312,8 +311,7 @@ int ModSecurity::processContentOffset(const char *content, size_t len, t = modsecurity::actions::transformations::Transformation::instantiate( trans.back().str().c_str()); - varValueRes = t->evaluate(varValue, NULL); - varValue.assign(varValueRes); + t->transform(varValue, nullptr); trans.pop_back(); yajl_gen_string(g, reinterpret_cast("value"), diff --git a/src/operators/pm.cc b/src/operators/pm.cc index ebf31c40..ccd809e1 100644 --- a/src/operators/pm.cc +++ b/src/operators/pm.cc @@ -15,20 +15,81 @@ #include "src/operators/pm.h" -#include - -#include #include #include #include -#include -#include -#include -#include "src/operators/operator.h" #include "src/utils/acmp.h" #include "src/utils/string.h" +using namespace modsecurity::utils::string; + +static inline std::string parse_pm_content(const std::string &op_parm) { + auto offset = op_parm.find_first_not_of(" \t"); + if (offset == std::string::npos) { + return op_parm; + } + + auto size = op_parm.size() - offset; + if (size >= 2 && + op_parm.at(offset) == '\"' && op_parm.back() == '\"') { + offset++; + size -= 2; + } + + if (size == 0) { + return op_parm; + } + + std::string parsed_parm(op_parm.c_str() + offset, size); + + unsigned char bin_offset = 0; + unsigned char bin_parm[3] = { 0 }; + bool bin = false, esc = false; + + char *d = parsed_parm.data(); + for(const char *s = d, *e = d + size; s != e; ++s) { + if (*s == '|') { + bin = !bin; + } else if(!esc && *s == '\\') { + esc = true; + } else { + if (bin) { + if (VALID_HEX(*s)) { + bin_parm[bin_offset] = (char)*s; + bin_offset++; + if (bin_offset == 2) { + unsigned char c = strtol((char *)bin_parm, (char **) nullptr, 16) & 0xFF; + bin_offset = 0; + *d++ = c; + } + } else { + // Invalid hex character + return op_parm; + } + } else if (esc) { + if (*s == ':' || + *s == ';' || + *s == '\\' || + *s == '\"') + { + *d++ = *s; + } else { + // Unsupported escape sequence + return op_parm; + } + esc = false; + } else { + *d++ = *s; + } + } + } + + parsed_parm.resize(d - parsed_parm.c_str()); + return parsed_parm; +} + + namespace modsecurity { namespace operators { @@ -39,9 +100,6 @@ Pm::~Pm() { free(m_p); m_p = NULL; -#ifdef MODSEC_MUTEX_ON_PM - pthread_mutex_destroy(&m_lock); -#endif } @@ -88,13 +146,7 @@ bool Pm::evaluate(Transaction *transaction, RuleWithActions *rule, pt.parser = m_p; pt.ptr = NULL; const char *match = NULL; -#ifdef MODSEC_MUTEX_ON_PM - pthread_mutex_lock(&m_lock); -#endif rc = acmp_process_quick(&pt, &match, input.c_str(), input.length()); -#ifdef MODSEC_MUTEX_ON_PM - pthread_mutex_unlock(&m_lock); -#endif if (rc >= 0 && transaction) { std::string match_(match?match:""); @@ -114,39 +166,19 @@ bool Pm::evaluate(Transaction *transaction, RuleWithActions *rule, bool Pm::init(const std::string &file, std::string *error) { - std::vector vec; - std::istringstream *iss; - const char *err = NULL; + const auto op_parm = parse_pm_content(m_param); -#ifdef MODSEC_MUTEX_ON_PM - pthread_mutex_init(&m_lock, NULL); -#endif - char *content = parse_pm_content(m_param.c_str(), m_param.length(), &err); - if (content == NULL) { - iss = new std::istringstream(m_param); - } else { - iss = new std::istringstream(content); - } - - std::copy(std::istream_iterator(*iss), + std::istringstream iss{op_parm}; + std::for_each(std::istream_iterator(iss), std::istream_iterator(), - back_inserter(vec)); - - for (auto &a : vec) { - acmp_add_pattern(m_p, a.c_str(), NULL, NULL, a.length()); - } + [this](const auto &a) { + acmp_add_pattern(m_p, a.c_str(), NULL, NULL, a.length()); + }); while (m_p->is_failtree_done == 0) { acmp_prepare(m_p); } - if (content) { - free(content); - content = NULL; - } - - delete iss; - return true; } diff --git a/src/operators/pm.h b/src/operators/pm.h index b090ec5d..72d3a546 100644 --- a/src/operators/pm.h +++ b/src/operators/pm.h @@ -17,9 +17,9 @@ #define SRC_OPERATORS_PM_H_ #include -#include #include #include +#include #include "src/operators/operator.h" #include "src/utils/acmp.h" @@ -52,12 +52,6 @@ class Pm : public Operator { protected: ACMP *m_p; - -#ifdef MODSEC_MUTEX_ON_PM - - private: - pthread_mutex_t m_lock; -#endif }; diff --git a/src/operators/pm_f.cc b/src/operators/pm_f.cc deleted file mode 100644 index bc83a33b..00000000 --- a/src/operators/pm_f.cc +++ /dev/null @@ -1,27 +0,0 @@ -/* - * ModSecurity, http://www.modsecurity.org/ - * Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/) - * - * You may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * If any of the files related to licensing are missing or if you have any - * other questions related to licensing please contact Trustwave Holdings, Inc. - * directly using the email address security@modsecurity.org. - * - */ - -#include "src/operators/pm_f.h" - -#include - -#include "src/operators/pm_from_file.h" - -namespace modsecurity { -namespace operators { - - -} // namespace operators -} // namespace modsecurity diff --git a/src/operators/validate_utf8_encoding.cc b/src/operators/validate_utf8_encoding.cc index 3e17686f..cd2f064c 100644 --- a/src/operators/validate_utf8_encoding.cc +++ b/src/operators/validate_utf8_encoding.cc @@ -19,6 +19,14 @@ #include "src/operators/operator.h" + +constexpr int UNICODE_ERROR_CHARACTERS_MISSING = -1; +constexpr int UNICODE_ERROR_INVALID_ENCODING = -2; +constexpr int UNICODE_ERROR_OVERLONG_CHARACTER = -3; +constexpr int UNICODE_ERROR_RESTRICTED_CHARACTER = -4; +constexpr int UNICODE_ERROR_DECODING_ERROR = -5; + + namespace modsecurity { namespace operators { diff --git a/src/operators/validate_utf8_encoding.h b/src/operators/validate_utf8_encoding.h index e59eef58..2bd75dc8 100644 --- a/src/operators/validate_utf8_encoding.h +++ b/src/operators/validate_utf8_encoding.h @@ -22,13 +22,6 @@ #include "src/operators/operator.h" -#define UNICODE_ERROR_CHARACTERS_MISSING -1 -#define UNICODE_ERROR_INVALID_ENCODING -2 -#define UNICODE_ERROR_OVERLONG_CHARACTER -3 -#define UNICODE_ERROR_RESTRICTED_CHARACTER -4 -#define UNICODE_ERROR_DECODING_ERROR -5 - - namespace modsecurity { namespace operators { diff --git a/src/parser/Makefile.am b/src/parser/Makefile.am index 1fc57310..cded6261 100644 --- a/src/parser/Makefile.am +++ b/src/parser/Makefile.am @@ -11,7 +11,6 @@ libmodsec_parser_la_SOURCES = \ test.cc libmodsec_parser_la_CPPFLAGS = \ - -std=c++17 \ -I../.. \ -I../../headers \ -I../../others \ diff --git a/src/parser/seclang-parser.cc b/src/parser/seclang-parser.cc index 9e18db4d..fbce5704 100644 --- a/src/parser/seclang-parser.cc +++ b/src/parser/seclang-parser.cc @@ -2295,8 +2295,9 @@ namespace yy { std::vector *a = new std::vector(); std::vector *t = new std::vector(); for (auto &i : *yystack_[0].value.as < std::unique_ptr > > > ().get()) { - if (dynamic_cast(i.get())) { - t->push_back(dynamic_cast(i.release())); + if (auto pt = dynamic_cast(i.get())) { + t->push_back(pt); + i.release(); } else { a->push_back(i.release()); } @@ -2320,11 +2321,11 @@ namespace yy { YYERROR; } } -#line 2324 "seclang-parser.cc" +#line 2325 "seclang-parser.cc" break; case 76: // expression: "DIRECTIVE" variables op -#line 1115 "seclang-parser.yy" +#line 1116 "seclang-parser.yy" { variables::Variables *v = new variables::Variables(); for (auto &i : *yystack_[1].value.as < std::unique_ptr > > > ().get()) { @@ -2343,17 +2344,18 @@ namespace yy { YYERROR; } } -#line 2347 "seclang-parser.cc" +#line 2348 "seclang-parser.cc" break; case 77: // expression: "CONFIG_DIR_SEC_ACTION" actions -#line 1134 "seclang-parser.yy" +#line 1135 "seclang-parser.yy" { std::vector *a = new std::vector(); std::vector *t = new std::vector(); for (auto &i : *yystack_[0].value.as < std::unique_ptr > > > ().get()) { - if (dynamic_cast(i.get())) { - t->push_back(dynamic_cast(i.release())); + if (auto pt = dynamic_cast(i.get())) { + t->push_back(pt); + i.release(); } else { a->push_back(i.release()); } @@ -2366,18 +2368,19 @@ namespace yy { )); driver.addSecAction(std::move(rule)); } -#line 2370 "seclang-parser.cc" +#line 2372 "seclang-parser.cc" break; case 78: // expression: "DIRECTIVE_SECRULESCRIPT" actions -#line 1153 "seclang-parser.yy" +#line 1155 "seclang-parser.yy" { std::string err; std::vector *a = new std::vector(); std::vector *t = new std::vector(); for (auto &i : *yystack_[0].value.as < std::unique_ptr > > > ().get()) { - if (dynamic_cast(i.get())) { - t->push_back(dynamic_cast(i.release())); + if (auto pt = dynamic_cast(i.get())) { + t->push_back(pt); + i.release(); } else { a->push_back(i.release()); } @@ -2398,11 +2401,11 @@ namespace yy { YYERROR; } } -#line 2402 "seclang-parser.cc" +#line 2405 "seclang-parser.cc" break; case 79: // expression: "CONFIG_DIR_SEC_DEFAULT_ACTION" actions -#line 1181 "seclang-parser.yy" +#line 1184 "seclang-parser.yy" { bool hasDisruptive = false; std::vector *actions = new std::vector(); @@ -2421,8 +2424,8 @@ namespace yy { definedPhase = phase->m_phase; secRuleDefinedPhase = phase->m_secRulesPhase; delete phase; - } else if (a->action_kind == actions::Action::RunTimeOnlyIfMatchKind || - a->action_kind == actions::Action::RunTimeBeforeMatchAttemptKind) { + } else if (a->action_kind == actions::Action::Kind::RunTimeOnlyIfMatchKind || + a->action_kind == actions::Action::Kind::RunTimeBeforeMatchAttemptKind) { actions::transformations::None *none = dynamic_cast(a); if (none != NULL) { driver.error(yystack_[2].location, "The transformation none is not suitable to be part of the SecDefaultActions"); @@ -2459,78 +2462,78 @@ namespace yy { delete actions; } -#line 2463 "seclang-parser.cc" +#line 2466 "seclang-parser.cc" break; case 80: // expression: "CONFIG_DIR_SEC_MARKER" -#line 1238 "seclang-parser.yy" +#line 1241 "seclang-parser.yy" { driver.addSecMarker(modsecurity::utils::string::removeBracketsIfNeeded(yystack_[0].value.as < std::string > ()), /* file name */ std::unique_ptr(new std::string(*yystack_[0].location.end.filename)), /* line number */ yystack_[0].location.end.line ); } -#line 2474 "seclang-parser.cc" +#line 2477 "seclang-parser.cc" break; case 81: // expression: "CONFIG_DIR_RULE_ENG" "CONFIG_VALUE_OFF" -#line 1245 "seclang-parser.yy" +#line 1248 "seclang-parser.yy" { driver.m_secRuleEngine = modsecurity::RulesSet::DisabledRuleEngine; } -#line 2482 "seclang-parser.cc" +#line 2485 "seclang-parser.cc" break; case 82: // expression: "CONFIG_DIR_RULE_ENG" "CONFIG_VALUE_ON" -#line 1249 "seclang-parser.yy" +#line 1252 "seclang-parser.yy" { driver.m_secRuleEngine = modsecurity::RulesSet::EnabledRuleEngine; } -#line 2490 "seclang-parser.cc" +#line 2493 "seclang-parser.cc" break; case 83: // expression: "CONFIG_DIR_RULE_ENG" "CONFIG_VALUE_DETC" -#line 1253 "seclang-parser.yy" +#line 1256 "seclang-parser.yy" { driver.m_secRuleEngine = modsecurity::RulesSet::DetectionOnlyRuleEngine; } -#line 2498 "seclang-parser.cc" +#line 2501 "seclang-parser.cc" break; case 84: // expression: "CONFIG_DIR_REQ_BODY" "CONFIG_VALUE_ON" -#line 1257 "seclang-parser.yy" +#line 1260 "seclang-parser.yy" { driver.m_secRequestBodyAccess = modsecurity::RulesSetProperties::TrueConfigBoolean; } -#line 2506 "seclang-parser.cc" +#line 2509 "seclang-parser.cc" break; case 85: // expression: "CONFIG_DIR_REQ_BODY" "CONFIG_VALUE_OFF" -#line 1261 "seclang-parser.yy" +#line 1264 "seclang-parser.yy" { driver.m_secRequestBodyAccess = modsecurity::RulesSetProperties::FalseConfigBoolean; } -#line 2514 "seclang-parser.cc" +#line 2517 "seclang-parser.cc" break; case 86: // expression: "CONFIG_DIR_RES_BODY" "CONFIG_VALUE_ON" -#line 1265 "seclang-parser.yy" +#line 1268 "seclang-parser.yy" { driver.m_secResponseBodyAccess = modsecurity::RulesSetProperties::TrueConfigBoolean; } -#line 2522 "seclang-parser.cc" +#line 2525 "seclang-parser.cc" break; case 87: // expression: "CONFIG_DIR_RES_BODY" "CONFIG_VALUE_OFF" -#line 1269 "seclang-parser.yy" +#line 1272 "seclang-parser.yy" { driver.m_secResponseBodyAccess = modsecurity::RulesSetProperties::FalseConfigBoolean; } -#line 2530 "seclang-parser.cc" +#line 2533 "seclang-parser.cc" break; case 88: // expression: "CONFIG_SEC_ARGUMENT_SEPARATOR" -#line 1273 "seclang-parser.yy" +#line 1276 "seclang-parser.yy" { if (yystack_[0].value.as < std::string > ().length() != 1) { driver.error(yystack_[1].location, "Argument separator should be set to a single character."); @@ -2539,259 +2542,259 @@ namespace yy { driver.m_secArgumentSeparator.m_value = yystack_[0].value.as < std::string > (); driver.m_secArgumentSeparator.m_set = true; } -#line 2543 "seclang-parser.cc" +#line 2546 "seclang-parser.cc" break; case 89: // expression: "CONFIG_COMPONENT_SIG" -#line 1282 "seclang-parser.yy" +#line 1285 "seclang-parser.yy" { driver.m_components.push_back(yystack_[0].value.as < std::string > ()); } -#line 2551 "seclang-parser.cc" +#line 2554 "seclang-parser.cc" break; case 90: // expression: "CONFIG_CONN_ENGINE" "CONFIG_VALUE_ON" -#line 1286 "seclang-parser.yy" +#line 1289 "seclang-parser.yy" { driver.error(yystack_[2].location, "SecConnEngine is not yet supported."); YYERROR; } -#line 2560 "seclang-parser.cc" +#line 2563 "seclang-parser.cc" break; case 91: // expression: "CONFIG_CONN_ENGINE" "CONFIG_VALUE_OFF" -#line 1291 "seclang-parser.yy" +#line 1294 "seclang-parser.yy" { } -#line 2567 "seclang-parser.cc" +#line 2570 "seclang-parser.cc" break; case 92: // expression: "CONFIG_SEC_WEB_APP_ID" -#line 1294 "seclang-parser.yy" +#line 1297 "seclang-parser.yy" { driver.m_secWebAppId.m_value = yystack_[0].value.as < std::string > (); driver.m_secWebAppId.m_set = true; } -#line 2576 "seclang-parser.cc" +#line 2579 "seclang-parser.cc" break; case 93: // expression: "CONFIG_SEC_SERVER_SIG" -#line 1299 "seclang-parser.yy" +#line 1302 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecServerSignature is not supported."); YYERROR; } -#line 2585 "seclang-parser.cc" +#line 2588 "seclang-parser.cc" break; case 94: // expression: "CONFIG_SEC_CACHE_TRANSFORMATIONS" -#line 1304 "seclang-parser.yy" +#line 1307 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecCacheTransformations is not supported."); YYERROR; } -#line 2594 "seclang-parser.cc" +#line 2597 "seclang-parser.cc" break; case 95: // expression: "CONFIG_SEC_DISABLE_BACKEND_COMPRESS" "CONFIG_VALUE_ON" -#line 1309 "seclang-parser.yy" +#line 1312 "seclang-parser.yy" { driver.error(yystack_[2].location, "SecDisableBackendCompression is not supported."); YYERROR; } -#line 2603 "seclang-parser.cc" +#line 2606 "seclang-parser.cc" break; case 96: // expression: "CONFIG_SEC_DISABLE_BACKEND_COMPRESS" "CONFIG_VALUE_OFF" -#line 1314 "seclang-parser.yy" +#line 1317 "seclang-parser.yy" { } -#line 2610 "seclang-parser.cc" +#line 2613 "seclang-parser.cc" break; case 97: // expression: "CONFIG_CONTENT_INJECTION" "CONFIG_VALUE_ON" -#line 1317 "seclang-parser.yy" +#line 1320 "seclang-parser.yy" { driver.error(yystack_[2].location, "SecContentInjection is not yet supported."); YYERROR; } -#line 2619 "seclang-parser.cc" +#line 2622 "seclang-parser.cc" break; case 98: // expression: "CONFIG_CONTENT_INJECTION" "CONFIG_VALUE_OFF" -#line 1322 "seclang-parser.yy" +#line 1325 "seclang-parser.yy" { } -#line 2626 "seclang-parser.cc" +#line 2629 "seclang-parser.cc" break; case 99: // expression: "CONFIG_SEC_CHROOT_DIR" -#line 1325 "seclang-parser.yy" +#line 1328 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecChrootDir is not supported."); YYERROR; } -#line 2635 "seclang-parser.cc" +#line 2638 "seclang-parser.cc" break; case 100: // expression: "CONFIG_SEC_HASH_ENGINE" "CONFIG_VALUE_ON" -#line 1330 "seclang-parser.yy" +#line 1333 "seclang-parser.yy" { driver.error(yystack_[2].location, "SecHashEngine is not yet supported."); YYERROR; } -#line 2644 "seclang-parser.cc" +#line 2647 "seclang-parser.cc" break; case 101: // expression: "CONFIG_SEC_HASH_ENGINE" "CONFIG_VALUE_OFF" -#line 1335 "seclang-parser.yy" +#line 1338 "seclang-parser.yy" { } -#line 2651 "seclang-parser.cc" +#line 2654 "seclang-parser.cc" break; case 102: // expression: "CONFIG_SEC_HASH_KEY" -#line 1338 "seclang-parser.yy" +#line 1341 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecHashKey is not yet supported."); YYERROR; } -#line 2660 "seclang-parser.cc" +#line 2663 "seclang-parser.cc" break; case 103: // expression: "CONFIG_SEC_HASH_PARAM" -#line 1343 "seclang-parser.yy" +#line 1346 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecHashParam is not yet supported."); YYERROR; } -#line 2669 "seclang-parser.cc" +#line 2672 "seclang-parser.cc" break; case 104: // expression: "CONFIG_SEC_HASH_METHOD_RX" -#line 1348 "seclang-parser.yy" +#line 1351 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecHashMethodRx is not yet supported."); YYERROR; } -#line 2678 "seclang-parser.cc" +#line 2681 "seclang-parser.cc" break; case 105: // expression: "CONFIG_SEC_HASH_METHOD_PM" -#line 1353 "seclang-parser.yy" +#line 1356 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecHashMethodPm is not yet supported."); YYERROR; } -#line 2687 "seclang-parser.cc" +#line 2690 "seclang-parser.cc" break; case 106: // expression: "CONFIG_DIR_GSB_DB" -#line 1358 "seclang-parser.yy" +#line 1361 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecGsbLookupDb is not supported."); YYERROR; } -#line 2696 "seclang-parser.cc" +#line 2699 "seclang-parser.cc" break; case 107: // expression: "CONFIG_SEC_GUARDIAN_LOG" -#line 1363 "seclang-parser.yy" +#line 1366 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecGuardianLog is not supported."); YYERROR; } -#line 2705 "seclang-parser.cc" +#line 2708 "seclang-parser.cc" break; case 108: // expression: "CONFIG_SEC_INTERCEPT_ON_ERROR" "CONFIG_VALUE_ON" -#line 1368 "seclang-parser.yy" +#line 1371 "seclang-parser.yy" { driver.error(yystack_[2].location, "SecInterceptOnError is not yet supported."); YYERROR; } -#line 2714 "seclang-parser.cc" +#line 2717 "seclang-parser.cc" break; case 109: // expression: "CONFIG_SEC_INTERCEPT_ON_ERROR" "CONFIG_VALUE_OFF" -#line 1373 "seclang-parser.yy" +#line 1376 "seclang-parser.yy" { } -#line 2721 "seclang-parser.cc" +#line 2724 "seclang-parser.cc" break; case 110: // expression: "CONFIG_SEC_CONN_R_STATE_LIMIT" -#line 1376 "seclang-parser.yy" +#line 1379 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecConnReadStateLimit is not yet supported."); YYERROR; } -#line 2730 "seclang-parser.cc" +#line 2733 "seclang-parser.cc" break; case 111: // expression: "CONFIG_SEC_CONN_W_STATE_LIMIT" -#line 1381 "seclang-parser.yy" +#line 1384 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecConnWriteStateLimit is not yet supported."); YYERROR; } -#line 2739 "seclang-parser.cc" +#line 2742 "seclang-parser.cc" break; case 112: // expression: "CONFIG_SEC_SENSOR_ID" -#line 1386 "seclang-parser.yy" +#line 1389 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecSensorId is not yet supported."); YYERROR; } -#line 2748 "seclang-parser.cc" +#line 2751 "seclang-parser.cc" break; case 113: // expression: "CONFIG_SEC_RULE_INHERITANCE" "CONFIG_VALUE_ON" -#line 1391 "seclang-parser.yy" +#line 1394 "seclang-parser.yy" { driver.error(yystack_[2].location, "SecRuleInheritance is not yet supported."); YYERROR; } -#line 2757 "seclang-parser.cc" +#line 2760 "seclang-parser.cc" break; case 114: // expression: "CONFIG_SEC_RULE_INHERITANCE" "CONFIG_VALUE_OFF" -#line 1396 "seclang-parser.yy" +#line 1399 "seclang-parser.yy" { } -#line 2764 "seclang-parser.cc" +#line 2767 "seclang-parser.cc" break; case 115: // expression: "CONFIG_SEC_RULE_PERF_TIME" -#line 1399 "seclang-parser.yy" +#line 1402 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecRulePerfTime is not yet supported."); YYERROR; } -#line 2773 "seclang-parser.cc" +#line 2776 "seclang-parser.cc" break; case 116: // expression: "CONFIG_SEC_STREAM_IN_BODY_INSPECTION" -#line 1404 "seclang-parser.yy" +#line 1407 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecStreamInBodyInspection is not supported."); YYERROR; } -#line 2782 "seclang-parser.cc" +#line 2785 "seclang-parser.cc" break; case 117: // expression: "CONFIG_SEC_STREAM_OUT_BODY_INSPECTION" -#line 1409 "seclang-parser.yy" +#line 1412 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecStreamOutBodyInspection is not supported."); YYERROR; } -#line 2791 "seclang-parser.cc" +#line 2794 "seclang-parser.cc" break; case 118: // expression: "CONFIG_SEC_RULE_REMOVE_BY_ID" -#line 1414 "seclang-parser.yy" +#line 1417 "seclang-parser.yy" { std::string error; if (driver.m_exceptions.load(yystack_[0].value.as < std::string > (), &error) == false) { @@ -2804,11 +2807,11 @@ namespace yy { YYERROR; } } -#line 2808 "seclang-parser.cc" +#line 2811 "seclang-parser.cc" break; case 119: // expression: "CONFIG_SEC_RULE_REMOVE_BY_TAG" -#line 1427 "seclang-parser.yy" +#line 1430 "seclang-parser.yy" { std::string error; if (driver.m_exceptions.loadRemoveRuleByTag(yystack_[0].value.as < std::string > (), &error) == false) { @@ -2821,11 +2824,11 @@ namespace yy { YYERROR; } } -#line 2825 "seclang-parser.cc" +#line 2828 "seclang-parser.cc" break; case 120: // expression: "CONFIG_SEC_RULE_REMOVE_BY_MSG" -#line 1440 "seclang-parser.yy" +#line 1443 "seclang-parser.yy" { std::string error; if (driver.m_exceptions.loadRemoveRuleByMsg(yystack_[0].value.as < std::string > (), &error) == false) { @@ -2838,11 +2841,11 @@ namespace yy { YYERROR; } } -#line 2842 "seclang-parser.cc" +#line 2845 "seclang-parser.cc" break; case 121: // expression: "CONFIG_SEC_RULE_UPDATE_TARGET_BY_TAG" variables_pre_process -#line 1453 "seclang-parser.yy" +#line 1456 "seclang-parser.yy" { std::string error; if (driver.m_exceptions.loadUpdateTargetByTag(yystack_[1].value.as < std::string > (), std::move(yystack_[0].value.as < std::unique_ptr > > > ()), &error) == false) { @@ -2855,11 +2858,11 @@ namespace yy { YYERROR; } } -#line 2859 "seclang-parser.cc" +#line 2862 "seclang-parser.cc" break; case 122: // expression: "CONFIG_SEC_RULE_UPDATE_TARGET_BY_MSG" variables_pre_process -#line 1466 "seclang-parser.yy" +#line 1469 "seclang-parser.yy" { std::string error; if (driver.m_exceptions.loadUpdateTargetByMsg(yystack_[1].value.as < std::string > (), std::move(yystack_[0].value.as < std::unique_ptr > > > ()), &error) == false) { @@ -2872,11 +2875,11 @@ namespace yy { YYERROR; } } -#line 2876 "seclang-parser.cc" +#line 2879 "seclang-parser.cc" break; case 123: // expression: "CONFIG_SEC_RULE_UPDATE_TARGET_BY_ID" variables_pre_process -#line 1479 "seclang-parser.yy" +#line 1482 "seclang-parser.yy" { std::string error; double ruleId; @@ -2902,11 +2905,11 @@ namespace yy { YYERROR; } } -#line 2906 "seclang-parser.cc" +#line 2909 "seclang-parser.cc" break; case 124: // expression: "CONFIG_SEC_RULE_UPDATE_ACTION_BY_ID" actions -#line 1505 "seclang-parser.yy" +#line 1508 "seclang-parser.yy" { std::string error; double ruleId; @@ -2933,11 +2936,11 @@ namespace yy { YYERROR; } } -#line 2937 "seclang-parser.cc" +#line 2940 "seclang-parser.cc" break; case 125: // expression: "CONFIG_DIR_DEBUG_LVL" -#line 1533 "seclang-parser.yy" +#line 1536 "seclang-parser.yy" { if (driver.m_debugLog != NULL) { driver.m_debugLog->setDebugLogLevel(atoi(yystack_[0].value.as < std::string > ().c_str())); @@ -2949,11 +2952,11 @@ namespace yy { YYERROR; } } -#line 2953 "seclang-parser.cc" +#line 2956 "seclang-parser.cc" break; case 126: // expression: "CONFIG_DIR_DEBUG_LOG" -#line 1545 "seclang-parser.yy" +#line 1548 "seclang-parser.yy" { if (driver.m_debugLog != NULL) { std::string error; @@ -2972,11 +2975,11 @@ namespace yy { YYERROR; } } -#line 2976 "seclang-parser.cc" +#line 2979 "seclang-parser.cc" break; case 127: // expression: "CONFIG_DIR_GEO_DB" -#line 1565 "seclang-parser.yy" +#line 1568 "seclang-parser.yy" { #if defined(WITH_GEOIP) or defined(WITH_MAXMIND) std::string err; @@ -3003,47 +3006,47 @@ namespace yy { YYERROR; #endif // WITH_GEOIP } -#line 3007 "seclang-parser.cc" +#line 3010 "seclang-parser.cc" break; case 128: // expression: "CONFIG_DIR_ARGS_LIMIT" -#line 1592 "seclang-parser.yy" +#line 1595 "seclang-parser.yy" { driver.m_argumentsLimit.m_set = true; driver.m_argumentsLimit.m_value = atoi(yystack_[0].value.as < std::string > ().c_str()); } -#line 3016 "seclang-parser.cc" +#line 3019 "seclang-parser.cc" break; case 129: // expression: "CONFIG_DIR_REQ_BODY_JSON_DEPTH_LIMIT" -#line 1597 "seclang-parser.yy" +#line 1600 "seclang-parser.yy" { driver.m_requestBodyJsonDepthLimit.m_set = true; driver.m_requestBodyJsonDepthLimit.m_value = atoi(yystack_[0].value.as < std::string > ().c_str()); } -#line 3025 "seclang-parser.cc" +#line 3028 "seclang-parser.cc" break; case 130: // expression: "CONFIG_DIR_REQ_BODY_LIMIT" -#line 1603 "seclang-parser.yy" +#line 1606 "seclang-parser.yy" { driver.m_requestBodyLimit.m_set = true; driver.m_requestBodyLimit.m_value = atoi(yystack_[0].value.as < std::string > ().c_str()); } -#line 3034 "seclang-parser.cc" +#line 3037 "seclang-parser.cc" break; case 131: // expression: "CONFIG_DIR_REQ_BODY_NO_FILES_LIMIT" -#line 1608 "seclang-parser.yy" +#line 1611 "seclang-parser.yy" { driver.m_requestBodyNoFilesLimit.m_set = true; driver.m_requestBodyNoFilesLimit.m_value = atoi(yystack_[0].value.as < std::string > ().c_str()); } -#line 3043 "seclang-parser.cc" +#line 3046 "seclang-parser.cc" break; case 132: // expression: "CONFIG_DIR_REQ_BODY_IN_MEMORY_LIMIT" -#line 1613 "seclang-parser.yy" +#line 1616 "seclang-parser.yy" { std::stringstream ss; ss << "As of ModSecurity version 3.0, SecRequestBodyInMemoryLimit is no longer "; @@ -3052,77 +3055,77 @@ namespace yy { driver.error(yystack_[1].location, ss.str()); YYERROR; } -#line 3056 "seclang-parser.cc" +#line 3059 "seclang-parser.cc" break; case 133: // expression: "CONFIG_DIR_RES_BODY_LIMIT" -#line 1622 "seclang-parser.yy" +#line 1625 "seclang-parser.yy" { driver.m_responseBodyLimit.m_set = true; driver.m_responseBodyLimit.m_value = atoi(yystack_[0].value.as < std::string > ().c_str()); } -#line 3065 "seclang-parser.cc" +#line 3068 "seclang-parser.cc" break; case 134: // expression: "CONFIG_DIR_REQ_BODY_LIMIT_ACTION" "CONFIG_VALUE_PROCESS_PARTIAL" -#line 1627 "seclang-parser.yy" +#line 1630 "seclang-parser.yy" { driver.m_requestBodyLimitAction = modsecurity::RulesSet::BodyLimitAction::ProcessPartialBodyLimitAction; } -#line 3073 "seclang-parser.cc" +#line 3076 "seclang-parser.cc" break; case 135: // expression: "CONFIG_DIR_REQ_BODY_LIMIT_ACTION" "CONFIG_VALUE_REJECT" -#line 1631 "seclang-parser.yy" +#line 1634 "seclang-parser.yy" { driver.m_requestBodyLimitAction = modsecurity::RulesSet::BodyLimitAction::RejectBodyLimitAction; } -#line 3081 "seclang-parser.cc" +#line 3084 "seclang-parser.cc" break; case 136: // expression: "CONFIG_DIR_RES_BODY_LIMIT_ACTION" "CONFIG_VALUE_PROCESS_PARTIAL" -#line 1635 "seclang-parser.yy" +#line 1638 "seclang-parser.yy" { driver.m_responseBodyLimitAction = modsecurity::RulesSet::BodyLimitAction::ProcessPartialBodyLimitAction; } -#line 3089 "seclang-parser.cc" +#line 3092 "seclang-parser.cc" break; case 137: // expression: "CONFIG_DIR_RES_BODY_LIMIT_ACTION" "CONFIG_VALUE_REJECT" -#line 1639 "seclang-parser.yy" +#line 1642 "seclang-parser.yy" { driver.m_responseBodyLimitAction = modsecurity::RulesSet::BodyLimitAction::RejectBodyLimitAction; } -#line 3097 "seclang-parser.cc" +#line 3100 "seclang-parser.cc" break; case 138: // expression: "CONFIG_SEC_REMOTE_RULES_FAIL_ACTION" "CONFIG_VALUE_ABORT" -#line 1643 "seclang-parser.yy" +#line 1646 "seclang-parser.yy" { driver.m_remoteRulesActionOnFailed = RulesSet::OnFailedRemoteRulesAction::AbortOnFailedRemoteRulesAction; } -#line 3105 "seclang-parser.cc" +#line 3108 "seclang-parser.cc" break; case 139: // expression: "CONFIG_SEC_REMOTE_RULES_FAIL_ACTION" "CONFIG_VALUE_WARN" -#line 1647 "seclang-parser.yy" +#line 1650 "seclang-parser.yy" { driver.m_remoteRulesActionOnFailed = RulesSet::OnFailedRemoteRulesAction::WarnOnFailedRemoteRulesAction; } -#line 3113 "seclang-parser.cc" +#line 3116 "seclang-parser.cc" break; case 141: // expression: "CONFIG_DIR_PCRE_MATCH_LIMIT" -#line 1656 "seclang-parser.yy" +#line 1659 "seclang-parser.yy" { driver.m_pcreMatchLimit.m_set = true; driver.m_pcreMatchLimit.m_value = atoi(yystack_[0].value.as < std::string > ().c_str()); } -#line 3122 "seclang-parser.cc" +#line 3125 "seclang-parser.cc" break; case 142: // expression: "CONGIG_DIR_RESPONSE_BODY_MP" -#line 1661 "seclang-parser.yy" +#line 1664 "seclang-parser.yy" { std::istringstream buf(yystack_[0].value.as < std::string > ()); std::istream_iterator beg(buf), end; @@ -3134,37 +3137,37 @@ namespace yy { driver.m_responseBodyTypeToBeInspected.m_value.insert(*it); } } -#line 3138 "seclang-parser.cc" +#line 3141 "seclang-parser.cc" break; case 143: // expression: "CONGIG_DIR_RESPONSE_BODY_MP_CLEAR" -#line 1673 "seclang-parser.yy" +#line 1676 "seclang-parser.yy" { driver.m_responseBodyTypeToBeInspected.m_set = true; driver.m_responseBodyTypeToBeInspected.m_clear = true; driver.m_responseBodyTypeToBeInspected.m_value.clear(); } -#line 3148 "seclang-parser.cc" +#line 3151 "seclang-parser.cc" break; case 144: // expression: "CONFIG_XML_EXTERNAL_ENTITY" "CONFIG_VALUE_OFF" -#line 1679 "seclang-parser.yy" +#line 1682 "seclang-parser.yy" { driver.m_secXMLExternalEntity = modsecurity::RulesSetProperties::FalseConfigBoolean; } -#line 3156 "seclang-parser.cc" +#line 3159 "seclang-parser.cc" break; case 145: // expression: "CONFIG_XML_EXTERNAL_ENTITY" "CONFIG_VALUE_ON" -#line 1683 "seclang-parser.yy" +#line 1686 "seclang-parser.yy" { driver.m_secXMLExternalEntity = modsecurity::RulesSetProperties::TrueConfigBoolean; } -#line 3164 "seclang-parser.cc" +#line 3167 "seclang-parser.cc" break; case 146: // expression: "CONGIG_DIR_SEC_TMP_DIR" -#line 1687 "seclang-parser.yy" +#line 1690 "seclang-parser.yy" { /* Parser error disabled to avoid breaking default installations with modsecurity.conf-recommended std::stringstream ss; @@ -3175,31 +3178,31 @@ namespace yy { YYERROR; */ } -#line 3179 "seclang-parser.cc" +#line 3182 "seclang-parser.cc" break; case 149: // expression: "CONGIG_DIR_SEC_COOKIE_FORMAT" -#line 1708 "seclang-parser.yy" +#line 1711 "seclang-parser.yy" { if (atoi(yystack_[0].value.as < std::string > ().c_str()) == 1) { driver.error(yystack_[1].location, "SecCookieFormat 1 is not yet supported."); YYERROR; } } -#line 3190 "seclang-parser.cc" +#line 3193 "seclang-parser.cc" break; case 150: // expression: "CONFIG_SEC_COOKIEV0_SEPARATOR" -#line 1715 "seclang-parser.yy" +#line 1718 "seclang-parser.yy" { driver.error(yystack_[1].location, "SecCookieV0Separator is not yet supported."); YYERROR; } -#line 3199 "seclang-parser.cc" +#line 3202 "seclang-parser.cc" break; case 152: // expression: "CONFIG_DIR_UNICODE_MAP_FILE" -#line 1725 "seclang-parser.yy" +#line 1728 "seclang-parser.yy" { std::string error; std::vector param; @@ -3253,31 +3256,31 @@ namespace yy { } } -#line 3257 "seclang-parser.cc" +#line 3260 "seclang-parser.cc" break; case 153: // expression: "CONFIG_SEC_COLLECTION_TIMEOUT" -#line 1779 "seclang-parser.yy" +#line 1782 "seclang-parser.yy" { /* Parser error disabled to avoid breaking default CRS installations with crs-setup.conf-recommended driver.error(@0, "SecCollectionTimeout is not yet supported."); YYERROR; */ } -#line 3268 "seclang-parser.cc" +#line 3271 "seclang-parser.cc" break; case 154: // expression: "CONFIG_SEC_HTTP_BLKEY" -#line 1786 "seclang-parser.yy" +#line 1789 "seclang-parser.yy" { driver.m_httpblKey.m_set = true; driver.m_httpblKey.m_value = yystack_[0].value.as < std::string > (); } -#line 3277 "seclang-parser.cc" +#line 3280 "seclang-parser.cc" break; case 155: // variables: variables_pre_process -#line 1794 "seclang-parser.yy" +#line 1797 "seclang-parser.yy" { std::unique_ptr > > originalList = std::move(yystack_[0].value.as < std::unique_ptr > > > ()); std::unique_ptr>> newList(new std::vector>()); @@ -3311,2401 +3314,2401 @@ namespace yy { } yylhs.value.as < std::unique_ptr > > > () = std::move(newNewList); } -#line 3315 "seclang-parser.cc" +#line 3318 "seclang-parser.cc" break; case 156: // variables_pre_process: variables_may_be_quoted -#line 1831 "seclang-parser.yy" +#line 1834 "seclang-parser.yy" { yylhs.value.as < std::unique_ptr > > > () = std::move(yystack_[0].value.as < std::unique_ptr > > > ()); } -#line 3323 "seclang-parser.cc" +#line 3326 "seclang-parser.cc" break; case 157: // variables_pre_process: "QUOTATION_MARK" variables_may_be_quoted "QUOTATION_MARK" -#line 1835 "seclang-parser.yy" +#line 1838 "seclang-parser.yy" { yylhs.value.as < std::unique_ptr > > > () = std::move(yystack_[1].value.as < std::unique_ptr > > > ()); } -#line 3331 "seclang-parser.cc" +#line 3334 "seclang-parser.cc" break; case 158: // variables_may_be_quoted: variables_may_be_quoted PIPE var -#line 1842 "seclang-parser.yy" +#line 1845 "seclang-parser.yy" { yystack_[2].value.as < std::unique_ptr > > > ()->push_back(std::move(yystack_[0].value.as < std::unique_ptr > ())); yylhs.value.as < std::unique_ptr > > > () = std::move(yystack_[2].value.as < std::unique_ptr > > > ()); } -#line 3340 "seclang-parser.cc" +#line 3343 "seclang-parser.cc" break; case 159: // variables_may_be_quoted: variables_may_be_quoted PIPE VAR_EXCLUSION var -#line 1847 "seclang-parser.yy" +#line 1850 "seclang-parser.yy" { std::unique_ptr c(new VariableModificatorExclusion(std::move(yystack_[0].value.as < std::unique_ptr > ()))); yystack_[3].value.as < std::unique_ptr > > > ()->push_back(std::move(c)); yylhs.value.as < std::unique_ptr > > > () = std::move(yystack_[3].value.as < std::unique_ptr > > > ()); } -#line 3350 "seclang-parser.cc" +#line 3353 "seclang-parser.cc" break; case 160: // variables_may_be_quoted: variables_may_be_quoted PIPE VAR_COUNT var -#line 1853 "seclang-parser.yy" +#line 1856 "seclang-parser.yy" { std::unique_ptr c(new VariableModificatorCount(std::move(yystack_[0].value.as < std::unique_ptr > ()))); yystack_[3].value.as < std::unique_ptr > > > ()->push_back(std::move(c)); yylhs.value.as < std::unique_ptr > > > () = std::move(yystack_[3].value.as < std::unique_ptr > > > ()); } -#line 3360 "seclang-parser.cc" +#line 3363 "seclang-parser.cc" break; case 161: // variables_may_be_quoted: var -#line 1859 "seclang-parser.yy" +#line 1862 "seclang-parser.yy" { std::unique_ptr>> b(new std::vector>()); b->push_back(std::move(yystack_[0].value.as < std::unique_ptr > ())); yylhs.value.as < std::unique_ptr > > > () = std::move(b); } -#line 3370 "seclang-parser.cc" +#line 3373 "seclang-parser.cc" break; case 162: // variables_may_be_quoted: VAR_EXCLUSION var -#line 1865 "seclang-parser.yy" +#line 1868 "seclang-parser.yy" { std::unique_ptr>> b(new std::vector>()); std::unique_ptr c(new VariableModificatorExclusion(std::move(yystack_[0].value.as < std::unique_ptr > ()))); b->push_back(std::move(c)); yylhs.value.as < std::unique_ptr > > > () = std::move(b); } -#line 3381 "seclang-parser.cc" +#line 3384 "seclang-parser.cc" break; case 163: // variables_may_be_quoted: VAR_COUNT var -#line 1872 "seclang-parser.yy" +#line 1875 "seclang-parser.yy" { std::unique_ptr>> b(new std::vector>()); std::unique_ptr c(new VariableModificatorCount(std::move(yystack_[0].value.as < std::unique_ptr > ()))); b->push_back(std::move(c)); yylhs.value.as < std::unique_ptr > > > () = std::move(b); } -#line 3392 "seclang-parser.cc" +#line 3395 "seclang-parser.cc" break; case 164: // var: VARIABLE_ARGS "Dictionary element" -#line 1882 "seclang-parser.yy" +#line 1885 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Args_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3400 "seclang-parser.cc" +#line 3403 "seclang-parser.cc" break; case 165: // var: VARIABLE_ARGS "Dictionary element, selected by regexp" -#line 1886 "seclang-parser.yy" +#line 1889 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Args_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3408 "seclang-parser.cc" +#line 3411 "seclang-parser.cc" break; case 166: // var: VARIABLE_ARGS -#line 1890 "seclang-parser.yy" +#line 1893 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Args_NoDictElement()); } -#line 3416 "seclang-parser.cc" +#line 3419 "seclang-parser.cc" break; case 167: // var: VARIABLE_ARGS_POST "Dictionary element" -#line 1894 "seclang-parser.yy" +#line 1897 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsPost_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3424 "seclang-parser.cc" +#line 3427 "seclang-parser.cc" break; case 168: // var: VARIABLE_ARGS_POST "Dictionary element, selected by regexp" -#line 1898 "seclang-parser.yy" +#line 1901 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsPost_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3432 "seclang-parser.cc" +#line 3435 "seclang-parser.cc" break; case 169: // var: VARIABLE_ARGS_POST -#line 1902 "seclang-parser.yy" +#line 1905 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsPost_NoDictElement()); } -#line 3440 "seclang-parser.cc" +#line 3443 "seclang-parser.cc" break; case 170: // var: VARIABLE_ARGS_GET "Dictionary element" -#line 1906 "seclang-parser.yy" +#line 1909 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsGet_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3448 "seclang-parser.cc" +#line 3451 "seclang-parser.cc" break; case 171: // var: VARIABLE_ARGS_GET "Dictionary element, selected by regexp" -#line 1910 "seclang-parser.yy" +#line 1913 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsGet_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3456 "seclang-parser.cc" +#line 3459 "seclang-parser.cc" break; case 172: // var: VARIABLE_ARGS_GET -#line 1914 "seclang-parser.yy" +#line 1917 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsGet_NoDictElement()); } -#line 3464 "seclang-parser.cc" +#line 3467 "seclang-parser.cc" break; case 173: // var: VARIABLE_FILES_SIZES "Dictionary element" -#line 1918 "seclang-parser.yy" +#line 1921 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesSizes_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3472 "seclang-parser.cc" +#line 3475 "seclang-parser.cc" break; case 174: // var: VARIABLE_FILES_SIZES "Dictionary element, selected by regexp" -#line 1922 "seclang-parser.yy" +#line 1925 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesSizes_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3480 "seclang-parser.cc" +#line 3483 "seclang-parser.cc" break; case 175: // var: VARIABLE_FILES_SIZES -#line 1926 "seclang-parser.yy" +#line 1929 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesSizes_NoDictElement()); } -#line 3488 "seclang-parser.cc" +#line 3491 "seclang-parser.cc" break; case 176: // var: VARIABLE_FILES_NAMES "Dictionary element" -#line 1930 "seclang-parser.yy" +#line 1933 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3496 "seclang-parser.cc" +#line 3499 "seclang-parser.cc" break; case 177: // var: VARIABLE_FILES_NAMES "Dictionary element, selected by regexp" -#line 1934 "seclang-parser.yy" +#line 1937 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3504 "seclang-parser.cc" +#line 3507 "seclang-parser.cc" break; case 178: // var: VARIABLE_FILES_NAMES -#line 1938 "seclang-parser.yy" +#line 1941 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesNames_NoDictElement()); } -#line 3512 "seclang-parser.cc" +#line 3515 "seclang-parser.cc" break; case 179: // var: VARIABLE_FILES_TMP_CONTENT "Dictionary element" -#line 1942 "seclang-parser.yy" +#line 1945 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesTmpContent_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3520 "seclang-parser.cc" +#line 3523 "seclang-parser.cc" break; case 180: // var: VARIABLE_FILES_TMP_CONTENT "Dictionary element, selected by regexp" -#line 1946 "seclang-parser.yy" +#line 1949 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesTmpContent_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3528 "seclang-parser.cc" +#line 3531 "seclang-parser.cc" break; case 181: // var: VARIABLE_FILES_TMP_CONTENT -#line 1950 "seclang-parser.yy" +#line 1953 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesTmpContent_NoDictElement()); } -#line 3536 "seclang-parser.cc" +#line 3539 "seclang-parser.cc" break; case 182: // var: VARIABLE_MULTIPART_FILENAME "Dictionary element" -#line 1954 "seclang-parser.yy" +#line 1957 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultiPartFileName_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3544 "seclang-parser.cc" +#line 3547 "seclang-parser.cc" break; case 183: // var: VARIABLE_MULTIPART_FILENAME "Dictionary element, selected by regexp" -#line 1958 "seclang-parser.yy" +#line 1961 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultiPartFileName_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3552 "seclang-parser.cc" +#line 3555 "seclang-parser.cc" break; case 184: // var: VARIABLE_MULTIPART_FILENAME -#line 1962 "seclang-parser.yy" +#line 1965 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultiPartFileName_NoDictElement()); } -#line 3560 "seclang-parser.cc" +#line 3563 "seclang-parser.cc" break; case 185: // var: VARIABLE_MULTIPART_NAME "Dictionary element" -#line 1966 "seclang-parser.yy" +#line 1969 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultiPartName_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3568 "seclang-parser.cc" +#line 3571 "seclang-parser.cc" break; case 186: // var: VARIABLE_MULTIPART_NAME "Dictionary element, selected by regexp" -#line 1970 "seclang-parser.yy" +#line 1973 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultiPartName_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3576 "seclang-parser.cc" +#line 3579 "seclang-parser.cc" break; case 187: // var: VARIABLE_MULTIPART_NAME -#line 1974 "seclang-parser.yy" +#line 1977 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultiPartName_NoDictElement()); } -#line 3584 "seclang-parser.cc" +#line 3587 "seclang-parser.cc" break; case 188: // var: VARIABLE_MATCHED_VARS_NAMES "Dictionary element" -#line 1978 "seclang-parser.yy" +#line 1981 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVarsNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3592 "seclang-parser.cc" +#line 3595 "seclang-parser.cc" break; case 189: // var: VARIABLE_MATCHED_VARS_NAMES "Dictionary element, selected by regexp" -#line 1982 "seclang-parser.yy" +#line 1985 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVarsNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3600 "seclang-parser.cc" +#line 3603 "seclang-parser.cc" break; case 190: // var: VARIABLE_MATCHED_VARS_NAMES -#line 1986 "seclang-parser.yy" +#line 1989 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVarsNames_NoDictElement()); } -#line 3608 "seclang-parser.cc" +#line 3611 "seclang-parser.cc" break; case 191: // var: VARIABLE_MATCHED_VARS "Dictionary element" -#line 1990 "seclang-parser.yy" +#line 1993 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVars_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3616 "seclang-parser.cc" +#line 3619 "seclang-parser.cc" break; case 192: // var: VARIABLE_MATCHED_VARS "Dictionary element, selected by regexp" -#line 1994 "seclang-parser.yy" +#line 1997 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVars_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3624 "seclang-parser.cc" +#line 3627 "seclang-parser.cc" break; case 193: // var: VARIABLE_MATCHED_VARS -#line 1998 "seclang-parser.yy" +#line 2001 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVars_NoDictElement()); } -#line 3632 "seclang-parser.cc" +#line 3635 "seclang-parser.cc" break; case 194: // var: VARIABLE_FILES "Dictionary element" -#line 2002 "seclang-parser.yy" +#line 2005 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Files_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3640 "seclang-parser.cc" +#line 3643 "seclang-parser.cc" break; case 195: // var: VARIABLE_FILES "Dictionary element, selected by regexp" -#line 2006 "seclang-parser.yy" +#line 2009 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Files_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3648 "seclang-parser.cc" +#line 3651 "seclang-parser.cc" break; case 196: // var: VARIABLE_FILES -#line 2010 "seclang-parser.yy" +#line 2013 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Files_NoDictElement()); } -#line 3656 "seclang-parser.cc" +#line 3659 "seclang-parser.cc" break; case 197: // var: VARIABLE_REQUEST_COOKIES "Dictionary element" -#line 2014 "seclang-parser.yy" +#line 2017 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestCookies_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3664 "seclang-parser.cc" +#line 3667 "seclang-parser.cc" break; case 198: // var: VARIABLE_REQUEST_COOKIES "Dictionary element, selected by regexp" -#line 2018 "seclang-parser.yy" +#line 2021 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestCookies_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3672 "seclang-parser.cc" +#line 3675 "seclang-parser.cc" break; case 199: // var: VARIABLE_REQUEST_COOKIES -#line 2022 "seclang-parser.yy" +#line 2025 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestCookies_NoDictElement()); } -#line 3680 "seclang-parser.cc" +#line 3683 "seclang-parser.cc" break; case 200: // var: VARIABLE_REQUEST_HEADERS "Dictionary element" -#line 2026 "seclang-parser.yy" +#line 2029 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestHeaders_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3688 "seclang-parser.cc" +#line 3691 "seclang-parser.cc" break; case 201: // var: VARIABLE_REQUEST_HEADERS "Dictionary element, selected by regexp" -#line 2030 "seclang-parser.yy" +#line 2033 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestHeaders_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3696 "seclang-parser.cc" +#line 3699 "seclang-parser.cc" break; case 202: // var: VARIABLE_REQUEST_HEADERS -#line 2034 "seclang-parser.yy" +#line 2037 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestHeaders_NoDictElement()); } -#line 3704 "seclang-parser.cc" +#line 3707 "seclang-parser.cc" break; case 203: // var: VARIABLE_RESPONSE_HEADERS "Dictionary element" -#line 2038 "seclang-parser.yy" +#line 2041 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseHeaders_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3712 "seclang-parser.cc" +#line 3715 "seclang-parser.cc" break; case 204: // var: VARIABLE_RESPONSE_HEADERS "Dictionary element, selected by regexp" -#line 2042 "seclang-parser.yy" +#line 2045 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseHeaders_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3720 "seclang-parser.cc" +#line 3723 "seclang-parser.cc" break; case 205: // var: VARIABLE_RESPONSE_HEADERS -#line 2046 "seclang-parser.yy" +#line 2049 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseHeaders_NoDictElement()); } -#line 3728 "seclang-parser.cc" +#line 3731 "seclang-parser.cc" break; case 206: // var: VARIABLE_GEO "Dictionary element" -#line 2050 "seclang-parser.yy" +#line 2053 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Geo_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3736 "seclang-parser.cc" +#line 3739 "seclang-parser.cc" break; case 207: // var: VARIABLE_GEO "Dictionary element, selected by regexp" -#line 2054 "seclang-parser.yy" +#line 2057 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Geo_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3744 "seclang-parser.cc" +#line 3747 "seclang-parser.cc" break; case 208: // var: VARIABLE_GEO -#line 2058 "seclang-parser.yy" +#line 2061 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Geo_NoDictElement()); } -#line 3752 "seclang-parser.cc" +#line 3755 "seclang-parser.cc" break; case 209: // var: VARIABLE_REQUEST_COOKIES_NAMES "Dictionary element" -#line 2062 "seclang-parser.yy" +#line 2065 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestCookiesNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3760 "seclang-parser.cc" +#line 3763 "seclang-parser.cc" break; case 210: // var: VARIABLE_REQUEST_COOKIES_NAMES "Dictionary element, selected by regexp" -#line 2066 "seclang-parser.yy" +#line 2069 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestCookiesNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3768 "seclang-parser.cc" +#line 3771 "seclang-parser.cc" break; case 211: // var: VARIABLE_REQUEST_COOKIES_NAMES -#line 2070 "seclang-parser.yy" +#line 2073 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestCookiesNames_NoDictElement()); } -#line 3776 "seclang-parser.cc" +#line 3779 "seclang-parser.cc" break; case 212: // var: VARIABLE_MULTIPART_PART_HEADERS "Dictionary element" -#line 2074 "seclang-parser.yy" +#line 2077 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartPartHeaders_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3784 "seclang-parser.cc" +#line 3787 "seclang-parser.cc" break; case 213: // var: VARIABLE_MULTIPART_PART_HEADERS "Dictionary element, selected by regexp" -#line 2078 "seclang-parser.yy" +#line 2081 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartPartHeaders_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3792 "seclang-parser.cc" +#line 3795 "seclang-parser.cc" break; case 214: // var: VARIABLE_MULTIPART_PART_HEADERS -#line 2082 "seclang-parser.yy" +#line 2085 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartPartHeaders_NoDictElement()); } -#line 3800 "seclang-parser.cc" +#line 3803 "seclang-parser.cc" break; case 215: // var: VARIABLE_RULE "Dictionary element" -#line 2086 "seclang-parser.yy" +#line 2089 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Rule_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3808 "seclang-parser.cc" +#line 3811 "seclang-parser.cc" break; case 216: // var: VARIABLE_RULE "Dictionary element, selected by regexp" -#line 2090 "seclang-parser.yy" +#line 2093 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Rule_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3816 "seclang-parser.cc" +#line 3819 "seclang-parser.cc" break; case 217: // var: VARIABLE_RULE -#line 2094 "seclang-parser.yy" +#line 2097 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Rule_NoDictElement()); } -#line 3824 "seclang-parser.cc" +#line 3827 "seclang-parser.cc" break; case 218: // var: "RUN_TIME_VAR_ENV" "Dictionary element" -#line 2098 "seclang-parser.yy" +#line 2101 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Env("ENV:" + yystack_[0].value.as < std::string > ())); } -#line 3832 "seclang-parser.cc" +#line 3835 "seclang-parser.cc" break; case 219: // var: "RUN_TIME_VAR_ENV" "Dictionary element, selected by regexp" -#line 2102 "seclang-parser.yy" +#line 2105 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Env("ENV:" + yystack_[0].value.as < std::string > ())); } -#line 3840 "seclang-parser.cc" +#line 3843 "seclang-parser.cc" break; case 220: // var: "RUN_TIME_VAR_ENV" -#line 2106 "seclang-parser.yy" +#line 2109 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Env("ENV")); } -#line 3848 "seclang-parser.cc" +#line 3851 "seclang-parser.cc" break; case 221: // var: "RUN_TIME_VAR_XML" "Dictionary element" -#line 2110 "seclang-parser.yy" +#line 2113 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::XML("XML:" + yystack_[0].value.as < std::string > ())); } -#line 3856 "seclang-parser.cc" +#line 3859 "seclang-parser.cc" break; case 222: // var: "RUN_TIME_VAR_XML" "Dictionary element, selected by regexp" -#line 2114 "seclang-parser.yy" +#line 2117 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::XML("XML:" + yystack_[0].value.as < std::string > ())); } -#line 3864 "seclang-parser.cc" +#line 3867 "seclang-parser.cc" break; case 223: // var: "RUN_TIME_VAR_XML" -#line 2118 "seclang-parser.yy" +#line 2121 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::XML_NoDictElement()); } -#line 3872 "seclang-parser.cc" +#line 3875 "seclang-parser.cc" break; case 224: // var: "FILES_TMPNAMES" "Dictionary element" -#line 2122 "seclang-parser.yy" +#line 2125 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesTmpNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3880 "seclang-parser.cc" +#line 3883 "seclang-parser.cc" break; case 225: // var: "FILES_TMPNAMES" "Dictionary element, selected by regexp" -#line 2126 "seclang-parser.yy" +#line 2129 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesTmpNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3888 "seclang-parser.cc" +#line 3891 "seclang-parser.cc" break; case 226: // var: "FILES_TMPNAMES" -#line 2130 "seclang-parser.yy" +#line 2133 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesTmpNames_NoDictElement()); } -#line 3896 "seclang-parser.cc" +#line 3899 "seclang-parser.cc" break; case 227: // var: "RESOURCE" run_time_string -#line 2134 "seclang-parser.yy" +#line 2137 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Resource_DynamicElement(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 3904 "seclang-parser.cc" +#line 3907 "seclang-parser.cc" break; case 228: // var: "RESOURCE" "Dictionary element" -#line 2138 "seclang-parser.yy" +#line 2141 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Resource_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3912 "seclang-parser.cc" +#line 3915 "seclang-parser.cc" break; case 229: // var: "RESOURCE" "Dictionary element, selected by regexp" -#line 2142 "seclang-parser.yy" +#line 2145 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Resource_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3920 "seclang-parser.cc" +#line 3923 "seclang-parser.cc" break; case 230: // var: "RESOURCE" -#line 2146 "seclang-parser.yy" +#line 2149 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Resource_NoDictElement()); } -#line 3928 "seclang-parser.cc" +#line 3931 "seclang-parser.cc" break; case 231: // var: "VARIABLE_IP" run_time_string -#line 2150 "seclang-parser.yy" +#line 2153 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Ip_DynamicElement(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 3936 "seclang-parser.cc" +#line 3939 "seclang-parser.cc" break; case 232: // var: "VARIABLE_IP" "Dictionary element" -#line 2154 "seclang-parser.yy" +#line 2157 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Ip_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3944 "seclang-parser.cc" +#line 3947 "seclang-parser.cc" break; case 233: // var: "VARIABLE_IP" "Dictionary element, selected by regexp" -#line 2158 "seclang-parser.yy" +#line 2161 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Ip_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3952 "seclang-parser.cc" +#line 3955 "seclang-parser.cc" break; case 234: // var: "VARIABLE_IP" -#line 2162 "seclang-parser.yy" +#line 2165 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Ip_NoDictElement()); } -#line 3960 "seclang-parser.cc" +#line 3963 "seclang-parser.cc" break; case 235: // var: "VARIABLE_GLOBAL" run_time_string -#line 2166 "seclang-parser.yy" +#line 2169 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Global_DynamicElement(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 3968 "seclang-parser.cc" +#line 3971 "seclang-parser.cc" break; case 236: // var: "VARIABLE_GLOBAL" "Dictionary element" -#line 2170 "seclang-parser.yy" +#line 2173 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Global_DictElement(yystack_[0].value.as < std::string > ())); } -#line 3976 "seclang-parser.cc" +#line 3979 "seclang-parser.cc" break; case 237: // var: "VARIABLE_GLOBAL" "Dictionary element, selected by regexp" -#line 2174 "seclang-parser.yy" +#line 2177 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Global_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 3984 "seclang-parser.cc" +#line 3987 "seclang-parser.cc" break; case 238: // var: "VARIABLE_GLOBAL" -#line 2178 "seclang-parser.yy" +#line 2181 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Global_NoDictElement()); } -#line 3992 "seclang-parser.cc" +#line 3995 "seclang-parser.cc" break; case 239: // var: "VARIABLE_USER" run_time_string -#line 2182 "seclang-parser.yy" +#line 2185 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::User_DynamicElement(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 4000 "seclang-parser.cc" +#line 4003 "seclang-parser.cc" break; case 240: // var: "VARIABLE_USER" "Dictionary element" -#line 2186 "seclang-parser.yy" +#line 2189 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::User_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4008 "seclang-parser.cc" +#line 4011 "seclang-parser.cc" break; case 241: // var: "VARIABLE_USER" "Dictionary element, selected by regexp" -#line 2190 "seclang-parser.yy" +#line 2193 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::User_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4016 "seclang-parser.cc" +#line 4019 "seclang-parser.cc" break; case 242: // var: "VARIABLE_USER" -#line 2194 "seclang-parser.yy" +#line 2197 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::User_NoDictElement()); } -#line 4024 "seclang-parser.cc" +#line 4027 "seclang-parser.cc" break; case 243: // var: "VARIABLE_TX" run_time_string -#line 2198 "seclang-parser.yy" +#line 2201 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Tx_DynamicElement(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 4032 "seclang-parser.cc" +#line 4035 "seclang-parser.cc" break; case 244: // var: "VARIABLE_TX" "Dictionary element" -#line 2202 "seclang-parser.yy" +#line 2205 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Tx_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4040 "seclang-parser.cc" +#line 4043 "seclang-parser.cc" break; case 245: // var: "VARIABLE_TX" "Dictionary element, selected by regexp" -#line 2206 "seclang-parser.yy" +#line 2209 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Tx_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4048 "seclang-parser.cc" +#line 4051 "seclang-parser.cc" break; case 246: // var: "VARIABLE_TX" -#line 2210 "seclang-parser.yy" +#line 2213 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Tx_NoDictElement()); } -#line 4056 "seclang-parser.cc" +#line 4059 "seclang-parser.cc" break; case 247: // var: "VARIABLE_SESSION" run_time_string -#line 2214 "seclang-parser.yy" +#line 2217 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Session_DynamicElement(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 4064 "seclang-parser.cc" +#line 4067 "seclang-parser.cc" break; case 248: // var: "VARIABLE_SESSION" "Dictionary element" -#line 2218 "seclang-parser.yy" +#line 2221 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Session_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4072 "seclang-parser.cc" +#line 4075 "seclang-parser.cc" break; case 249: // var: "VARIABLE_SESSION" "Dictionary element, selected by regexp" -#line 2222 "seclang-parser.yy" +#line 2225 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Session_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4080 "seclang-parser.cc" +#line 4083 "seclang-parser.cc" break; case 250: // var: "VARIABLE_SESSION" -#line 2226 "seclang-parser.yy" +#line 2229 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Session_NoDictElement()); } -#line 4088 "seclang-parser.cc" +#line 4091 "seclang-parser.cc" break; case 251: // var: "Variable ARGS_NAMES" "Dictionary element" -#line 2230 "seclang-parser.yy" +#line 2233 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4096 "seclang-parser.cc" +#line 4099 "seclang-parser.cc" break; case 252: // var: "Variable ARGS_NAMES" "Dictionary element, selected by regexp" -#line 2234 "seclang-parser.yy" +#line 2237 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4104 "seclang-parser.cc" +#line 4107 "seclang-parser.cc" break; case 253: // var: "Variable ARGS_NAMES" -#line 2238 "seclang-parser.yy" +#line 2241 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsNames_NoDictElement()); } -#line 4112 "seclang-parser.cc" +#line 4115 "seclang-parser.cc" break; case 254: // var: VARIABLE_ARGS_GET_NAMES "Dictionary element" -#line 2242 "seclang-parser.yy" +#line 2245 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsGetNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4120 "seclang-parser.cc" +#line 4123 "seclang-parser.cc" break; case 255: // var: VARIABLE_ARGS_GET_NAMES "Dictionary element, selected by regexp" -#line 2246 "seclang-parser.yy" +#line 2249 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsGetNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4128 "seclang-parser.cc" +#line 4131 "seclang-parser.cc" break; case 256: // var: VARIABLE_ARGS_GET_NAMES -#line 2250 "seclang-parser.yy" +#line 2253 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsGetNames_NoDictElement()); } -#line 4136 "seclang-parser.cc" +#line 4139 "seclang-parser.cc" break; case 257: // var: VARIABLE_ARGS_POST_NAMES "Dictionary element" -#line 2255 "seclang-parser.yy" +#line 2258 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsPostNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4144 "seclang-parser.cc" +#line 4147 "seclang-parser.cc" break; case 258: // var: VARIABLE_ARGS_POST_NAMES "Dictionary element, selected by regexp" -#line 2259 "seclang-parser.yy" +#line 2262 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsPostNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4152 "seclang-parser.cc" +#line 4155 "seclang-parser.cc" break; case 259: // var: VARIABLE_ARGS_POST_NAMES -#line 2263 "seclang-parser.yy" +#line 2266 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsPostNames_NoDictElement()); } -#line 4160 "seclang-parser.cc" +#line 4163 "seclang-parser.cc" break; case 260: // var: VARIABLE_REQUEST_HEADERS_NAMES "Dictionary element" -#line 2268 "seclang-parser.yy" +#line 2271 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestHeadersNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4168 "seclang-parser.cc" +#line 4171 "seclang-parser.cc" break; case 261: // var: VARIABLE_REQUEST_HEADERS_NAMES "Dictionary element, selected by regexp" -#line 2272 "seclang-parser.yy" +#line 2275 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestHeadersNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4176 "seclang-parser.cc" +#line 4179 "seclang-parser.cc" break; case 262: // var: VARIABLE_REQUEST_HEADERS_NAMES -#line 2276 "seclang-parser.yy" +#line 2279 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestHeadersNames_NoDictElement()); } -#line 4184 "seclang-parser.cc" +#line 4187 "seclang-parser.cc" break; case 263: // var: VARIABLE_RESPONSE_CONTENT_TYPE -#line 2281 "seclang-parser.yy" +#line 2284 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseContentType()); } -#line 4192 "seclang-parser.cc" +#line 4195 "seclang-parser.cc" break; case 264: // var: VARIABLE_RESPONSE_HEADERS_NAMES "Dictionary element" -#line 2286 "seclang-parser.yy" +#line 2289 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseHeadersNames_DictElement(yystack_[0].value.as < std::string > ())); } -#line 4200 "seclang-parser.cc" +#line 4203 "seclang-parser.cc" break; case 265: // var: VARIABLE_RESPONSE_HEADERS_NAMES "Dictionary element, selected by regexp" -#line 2290 "seclang-parser.yy" +#line 2293 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseHeadersNames_DictElementRegexp(yystack_[0].value.as < std::string > ())); } -#line 4208 "seclang-parser.cc" +#line 4211 "seclang-parser.cc" break; case 266: // var: VARIABLE_RESPONSE_HEADERS_NAMES -#line 2294 "seclang-parser.yy" +#line 2297 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseHeadersNames_NoDictElement()); } -#line 4216 "seclang-parser.cc" +#line 4219 "seclang-parser.cc" break; case 267: // var: VARIABLE_ARGS_COMBINED_SIZE -#line 2298 "seclang-parser.yy" +#line 2301 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ArgsCombinedSize()); } -#line 4224 "seclang-parser.cc" +#line 4227 "seclang-parser.cc" break; case 268: // var: "AUTH_TYPE" -#line 2302 "seclang-parser.yy" +#line 2305 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::AuthType()); } -#line 4232 "seclang-parser.cc" +#line 4235 "seclang-parser.cc" break; case 269: // var: "FILES_COMBINED_SIZE" -#line 2306 "seclang-parser.yy" +#line 2309 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FilesCombinedSize()); } -#line 4240 "seclang-parser.cc" +#line 4243 "seclang-parser.cc" break; case 270: // var: "FULL_REQUEST" -#line 2310 "seclang-parser.yy" +#line 2313 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FullRequest()); } -#line 4248 "seclang-parser.cc" +#line 4251 "seclang-parser.cc" break; case 271: // var: "FULL_REQUEST_LENGTH" -#line 2314 "seclang-parser.yy" +#line 2317 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::FullRequestLength()); } -#line 4256 "seclang-parser.cc" +#line 4259 "seclang-parser.cc" break; case 272: // var: "INBOUND_DATA_ERROR" -#line 2318 "seclang-parser.yy" +#line 2321 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::InboundDataError()); } -#line 4264 "seclang-parser.cc" +#line 4267 "seclang-parser.cc" break; case 273: // var: "MATCHED_VAR" -#line 2322 "seclang-parser.yy" +#line 2325 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVar()); } -#line 4272 "seclang-parser.cc" +#line 4275 "seclang-parser.cc" break; case 274: // var: "MATCHED_VAR_NAME" -#line 2326 "seclang-parser.yy" +#line 2329 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MatchedVarName()); } -#line 4280 "seclang-parser.cc" +#line 4283 "seclang-parser.cc" break; case 275: // var: "MSC_PCRE_ERROR" -#line 2330 "seclang-parser.yy" +#line 2333 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MscPcreError()); } -#line 4288 "seclang-parser.cc" +#line 4291 "seclang-parser.cc" break; case 276: // var: "MSC_PCRE_LIMITS_EXCEEDED" -#line 2334 "seclang-parser.yy" +#line 2337 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MscPcreLimitsExceeded()); } -#line 4296 "seclang-parser.cc" +#line 4299 "seclang-parser.cc" break; case 277: // var: VARIABLE_MULTIPART_BOUNDARY_QUOTED -#line 2338 "seclang-parser.yy" +#line 2341 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartBoundaryQuoted()); } -#line 4304 "seclang-parser.cc" +#line 4307 "seclang-parser.cc" break; case 278: // var: VARIABLE_MULTIPART_BOUNDARY_WHITESPACE -#line 2342 "seclang-parser.yy" +#line 2345 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartBoundaryWhiteSpace()); } -#line 4312 "seclang-parser.cc" +#line 4315 "seclang-parser.cc" break; case 279: // var: "MULTIPART_CRLF_LF_LINES" -#line 2346 "seclang-parser.yy" +#line 2349 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartCrlfLFLines()); } -#line 4320 "seclang-parser.cc" +#line 4323 "seclang-parser.cc" break; case 280: // var: "MULTIPART_DATA_AFTER" -#line 2350 "seclang-parser.yy" +#line 2353 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartDateAfter()); } -#line 4328 "seclang-parser.cc" +#line 4331 "seclang-parser.cc" break; case 281: // var: VARIABLE_MULTIPART_DATA_BEFORE -#line 2354 "seclang-parser.yy" +#line 2357 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartDateBefore()); } -#line 4336 "seclang-parser.cc" +#line 4339 "seclang-parser.cc" break; case 282: // var: "MULTIPART_FILE_LIMIT_EXCEEDED" -#line 2358 "seclang-parser.yy" +#line 2361 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartFileLimitExceeded()); } -#line 4344 "seclang-parser.cc" +#line 4347 "seclang-parser.cc" break; case 283: // var: "MULTIPART_HEADER_FOLDING" -#line 2362 "seclang-parser.yy" +#line 2365 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartHeaderFolding()); } -#line 4352 "seclang-parser.cc" +#line 4355 "seclang-parser.cc" break; case 284: // var: "MULTIPART_INVALID_HEADER_FOLDING" -#line 2366 "seclang-parser.yy" +#line 2369 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartInvalidHeaderFolding()); } -#line 4360 "seclang-parser.cc" +#line 4363 "seclang-parser.cc" break; case 285: // var: VARIABLE_MULTIPART_INVALID_PART -#line 2370 "seclang-parser.yy" +#line 2373 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartInvalidPart()); } -#line 4368 "seclang-parser.cc" +#line 4371 "seclang-parser.cc" break; case 286: // var: "MULTIPART_INVALID_QUOTING" -#line 2374 "seclang-parser.yy" +#line 2377 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartInvalidQuoting()); } -#line 4376 "seclang-parser.cc" +#line 4379 "seclang-parser.cc" break; case 287: // var: VARIABLE_MULTIPART_LF_LINE -#line 2378 "seclang-parser.yy" +#line 2381 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartLFLine()); } -#line 4384 "seclang-parser.cc" +#line 4387 "seclang-parser.cc" break; case 288: // var: VARIABLE_MULTIPART_MISSING_SEMICOLON -#line 2382 "seclang-parser.yy" +#line 2385 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartMissingSemicolon()); } -#line 4392 "seclang-parser.cc" +#line 4395 "seclang-parser.cc" break; case 289: // var: VARIABLE_MULTIPART_SEMICOLON_MISSING -#line 2386 "seclang-parser.yy" +#line 2389 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartMissingSemicolon()); } -#line 4400 "seclang-parser.cc" +#line 4403 "seclang-parser.cc" break; case 290: // var: "MULTIPART_STRICT_ERROR" -#line 2390 "seclang-parser.yy" +#line 2393 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartStrictError()); } -#line 4408 "seclang-parser.cc" +#line 4411 "seclang-parser.cc" break; case 291: // var: "MULTIPART_UNMATCHED_BOUNDARY" -#line 2394 "seclang-parser.yy" +#line 2397 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::MultipartUnmatchedBoundary()); } -#line 4416 "seclang-parser.cc" +#line 4419 "seclang-parser.cc" break; case 292: // var: "OUTBOUND_DATA_ERROR" -#line 2398 "seclang-parser.yy" +#line 2401 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::OutboundDataError()); } -#line 4424 "seclang-parser.cc" +#line 4427 "seclang-parser.cc" break; case 293: // var: "PATH_INFO" -#line 2402 "seclang-parser.yy" +#line 2405 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::PathInfo()); } -#line 4432 "seclang-parser.cc" +#line 4435 "seclang-parser.cc" break; case 294: // var: "QUERY_STRING" -#line 2406 "seclang-parser.yy" +#line 2409 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::QueryString()); } -#line 4440 "seclang-parser.cc" +#line 4443 "seclang-parser.cc" break; case 295: // var: "REMOTE_ADDR" -#line 2410 "seclang-parser.yy" +#line 2413 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RemoteAddr()); } -#line 4448 "seclang-parser.cc" +#line 4451 "seclang-parser.cc" break; case 296: // var: "REMOTE_HOST" -#line 2414 "seclang-parser.yy" +#line 2417 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RemoteHost()); } -#line 4456 "seclang-parser.cc" +#line 4459 "seclang-parser.cc" break; case 297: // var: "REMOTE_PORT" -#line 2418 "seclang-parser.yy" +#line 2421 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RemotePort()); } -#line 4464 "seclang-parser.cc" +#line 4467 "seclang-parser.cc" break; case 298: // var: "REQBODY_ERROR" -#line 2422 "seclang-parser.yy" +#line 2425 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ReqbodyError()); } -#line 4472 "seclang-parser.cc" +#line 4475 "seclang-parser.cc" break; case 299: // var: "REQBODY_ERROR_MSG" -#line 2426 "seclang-parser.yy" +#line 2429 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ReqbodyErrorMsg()); } -#line 4480 "seclang-parser.cc" +#line 4483 "seclang-parser.cc" break; case 300: // var: "REQBODY_PROCESSOR" -#line 2430 "seclang-parser.yy" +#line 2433 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ReqbodyProcessor()); } -#line 4488 "seclang-parser.cc" +#line 4491 "seclang-parser.cc" break; case 301: // var: "REQBODY_PROCESSOR_ERROR" -#line 2434 "seclang-parser.yy" +#line 2437 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ReqbodyProcessorError()); } -#line 4496 "seclang-parser.cc" +#line 4499 "seclang-parser.cc" break; case 302: // var: "REQBODY_PROCESSOR_ERROR_MSG" -#line 2438 "seclang-parser.yy" +#line 2441 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ReqbodyProcessorErrorMsg()); } -#line 4504 "seclang-parser.cc" +#line 4507 "seclang-parser.cc" break; case 303: // var: "REQUEST_BASENAME" -#line 2442 "seclang-parser.yy" +#line 2445 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestBasename()); } -#line 4512 "seclang-parser.cc" +#line 4515 "seclang-parser.cc" break; case 304: // var: "REQUEST_BODY" -#line 2446 "seclang-parser.yy" +#line 2449 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestBody()); } -#line 4520 "seclang-parser.cc" +#line 4523 "seclang-parser.cc" break; case 305: // var: "REQUEST_BODY_LENGTH" -#line 2450 "seclang-parser.yy" +#line 2453 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestBodyLength()); } -#line 4528 "seclang-parser.cc" +#line 4531 "seclang-parser.cc" break; case 306: // var: "REQUEST_FILENAME" -#line 2454 "seclang-parser.yy" +#line 2457 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestFilename()); } -#line 4536 "seclang-parser.cc" +#line 4539 "seclang-parser.cc" break; case 307: // var: "REQUEST_LINE" -#line 2458 "seclang-parser.yy" +#line 2461 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestLine()); } -#line 4544 "seclang-parser.cc" +#line 4547 "seclang-parser.cc" break; case 308: // var: "REQUEST_METHOD" -#line 2462 "seclang-parser.yy" +#line 2465 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestMethod()); } -#line 4552 "seclang-parser.cc" +#line 4555 "seclang-parser.cc" break; case 309: // var: "REQUEST_PROTOCOL" -#line 2466 "seclang-parser.yy" +#line 2469 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestProtocol()); } -#line 4560 "seclang-parser.cc" +#line 4563 "seclang-parser.cc" break; case 310: // var: "REQUEST_URI" -#line 2470 "seclang-parser.yy" +#line 2473 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestURI()); } -#line 4568 "seclang-parser.cc" +#line 4571 "seclang-parser.cc" break; case 311: // var: "REQUEST_URI_RAW" -#line 2474 "seclang-parser.yy" +#line 2477 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::RequestURIRaw()); } -#line 4576 "seclang-parser.cc" +#line 4579 "seclang-parser.cc" break; case 312: // var: "RESPONSE_BODY" -#line 2478 "seclang-parser.yy" +#line 2481 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseBody()); } -#line 4584 "seclang-parser.cc" +#line 4587 "seclang-parser.cc" break; case 313: // var: "RESPONSE_CONTENT_LENGTH" -#line 2482 "seclang-parser.yy" +#line 2485 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseContentLength()); } -#line 4592 "seclang-parser.cc" +#line 4595 "seclang-parser.cc" break; case 314: // var: "RESPONSE_PROTOCOL" -#line 2486 "seclang-parser.yy" +#line 2489 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseProtocol()); } -#line 4600 "seclang-parser.cc" +#line 4603 "seclang-parser.cc" break; case 315: // var: "RESPONSE_STATUS" -#line 2490 "seclang-parser.yy" +#line 2493 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ResponseStatus()); } -#line 4608 "seclang-parser.cc" +#line 4611 "seclang-parser.cc" break; case 316: // var: "SERVER_ADDR" -#line 2494 "seclang-parser.yy" +#line 2497 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ServerAddr()); } -#line 4616 "seclang-parser.cc" +#line 4619 "seclang-parser.cc" break; case 317: // var: "SERVER_NAME" -#line 2498 "seclang-parser.yy" +#line 2501 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ServerName()); } -#line 4624 "seclang-parser.cc" +#line 4627 "seclang-parser.cc" break; case 318: // var: "SERVER_PORT" -#line 2502 "seclang-parser.yy" +#line 2505 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::ServerPort()); } -#line 4632 "seclang-parser.cc" +#line 4635 "seclang-parser.cc" break; case 319: // var: "SESSIONID" -#line 2506 "seclang-parser.yy" +#line 2509 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::SessionID()); } -#line 4640 "seclang-parser.cc" +#line 4643 "seclang-parser.cc" break; case 320: // var: "UNIQUE_ID" -#line 2510 "seclang-parser.yy" +#line 2513 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::UniqueID()); } -#line 4648 "seclang-parser.cc" +#line 4651 "seclang-parser.cc" break; case 321: // var: "URLENCODED_ERROR" -#line 2514 "seclang-parser.yy" +#line 2517 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::UrlEncodedError()); } -#line 4656 "seclang-parser.cc" +#line 4659 "seclang-parser.cc" break; case 322: // var: "USERID" -#line 2518 "seclang-parser.yy" +#line 2521 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::UserID()); } -#line 4664 "seclang-parser.cc" +#line 4667 "seclang-parser.cc" break; case 323: // var: "VARIABLE_STATUS" -#line 2522 "seclang-parser.yy" +#line 2525 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Status()); } -#line 4672 "seclang-parser.cc" +#line 4675 "seclang-parser.cc" break; case 324: // var: "VARIABLE_STATUS_LINE" -#line 2526 "seclang-parser.yy" +#line 2529 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::Status()); } -#line 4680 "seclang-parser.cc" +#line 4683 "seclang-parser.cc" break; case 325: // var: "WEBAPPID" -#line 2530 "seclang-parser.yy" +#line 2533 "seclang-parser.yy" { VARIABLE_CONTAINER(yylhs.value.as < std::unique_ptr > (), new variables::WebAppId()); } -#line 4688 "seclang-parser.cc" +#line 4691 "seclang-parser.cc" break; case 326: // var: "RUN_TIME_VAR_DUR" -#line 2534 "seclang-parser.yy" +#line 2537 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new Duration(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4699 "seclang-parser.cc" +#line 4702 "seclang-parser.cc" break; case 327: // var: "RUN_TIME_VAR_BLD" -#line 2542 "seclang-parser.yy" +#line 2545 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new ModsecBuild(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4710 "seclang-parser.cc" +#line 4713 "seclang-parser.cc" break; case 328: // var: "RUN_TIME_VAR_HSV" -#line 2549 "seclang-parser.yy" +#line 2552 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new HighestSeverity(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4721 "seclang-parser.cc" +#line 4724 "seclang-parser.cc" break; case 329: // var: "RUN_TIME_VAR_REMOTE_USER" -#line 2556 "seclang-parser.yy" +#line 2559 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new RemoteUser(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4732 "seclang-parser.cc" +#line 4735 "seclang-parser.cc" break; case 330: // var: "RUN_TIME_VAR_TIME" -#line 2563 "seclang-parser.yy" +#line 2566 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new Time(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4743 "seclang-parser.cc" +#line 4746 "seclang-parser.cc" break; case 331: // var: "RUN_TIME_VAR_TIME_DAY" -#line 2570 "seclang-parser.yy" +#line 2573 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeDay(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4754 "seclang-parser.cc" +#line 4757 "seclang-parser.cc" break; case 332: // var: "RUN_TIME_VAR_TIME_EPOCH" -#line 2577 "seclang-parser.yy" +#line 2580 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeEpoch(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4765 "seclang-parser.cc" +#line 4768 "seclang-parser.cc" break; case 333: // var: "RUN_TIME_VAR_TIME_HOUR" -#line 2584 "seclang-parser.yy" +#line 2587 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeHour(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4776 "seclang-parser.cc" +#line 4779 "seclang-parser.cc" break; case 334: // var: "RUN_TIME_VAR_TIME_MIN" -#line 2591 "seclang-parser.yy" +#line 2594 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeMin(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4787 "seclang-parser.cc" +#line 4790 "seclang-parser.cc" break; case 335: // var: "RUN_TIME_VAR_TIME_MON" -#line 2598 "seclang-parser.yy" +#line 2601 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeMon(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4798 "seclang-parser.cc" +#line 4801 "seclang-parser.cc" break; case 336: // var: "RUN_TIME_VAR_TIME_SEC" -#line 2605 "seclang-parser.yy" +#line 2608 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeSec(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4809 "seclang-parser.cc" +#line 4812 "seclang-parser.cc" break; case 337: // var: "RUN_TIME_VAR_TIME_WDAY" -#line 2612 "seclang-parser.yy" +#line 2615 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeWDay(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4820 "seclang-parser.cc" +#line 4823 "seclang-parser.cc" break; case 338: // var: "RUN_TIME_VAR_TIME_YEAR" -#line 2619 "seclang-parser.yy" +#line 2622 "seclang-parser.yy" { std::string name(yystack_[0].value.as < std::string > ()); char z = name.at(0); std::unique_ptr c(new TimeYear(name)); yylhs.value.as < std::unique_ptr > () = std::move(c); } -#line 4831 "seclang-parser.cc" +#line 4834 "seclang-parser.cc" break; case 339: // act: "Accuracy" -#line 2629 "seclang-parser.yy" +#line 2632 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Accuracy(yystack_[0].value.as < std::string > ())); } -#line 4839 "seclang-parser.cc" +#line 4842 "seclang-parser.cc" break; case 340: // act: "Allow" -#line 2633 "seclang-parser.yy" +#line 2636 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::disruptive::Allow(yystack_[0].value.as < std::string > ())); } -#line 4847 "seclang-parser.cc" +#line 4850 "seclang-parser.cc" break; case 341: // act: "Append" -#line 2637 "seclang-parser.yy" +#line 2640 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("Append", yystack_[1].location); } -#line 4855 "seclang-parser.cc" +#line 4858 "seclang-parser.cc" break; case 342: // act: "AuditLog" -#line 2641 "seclang-parser.yy" +#line 2644 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::AuditLog(yystack_[0].value.as < std::string > ())); } -#line 4863 "seclang-parser.cc" +#line 4866 "seclang-parser.cc" break; case 343: // act: "Block" -#line 2645 "seclang-parser.yy" +#line 2648 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Block(yystack_[0].value.as < std::string > ())); } -#line 4871 "seclang-parser.cc" +#line 4874 "seclang-parser.cc" break; case 344: // act: "Capture" -#line 2649 "seclang-parser.yy" +#line 2652 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Capture(yystack_[0].value.as < std::string > ())); } -#line 4879 "seclang-parser.cc" +#line 4882 "seclang-parser.cc" break; case 345: // act: "Chain" -#line 2653 "seclang-parser.yy" +#line 2656 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Chain(yystack_[0].value.as < std::string > ())); } -#line 4887 "seclang-parser.cc" +#line 4890 "seclang-parser.cc" break; case 346: // act: "ACTION_CTL_AUDIT_ENGINE" "CONFIG_VALUE_ON" -#line 2657 "seclang-parser.yy" +#line 2660 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::AuditEngine("ctl:auditengine=on")); driver.m_auditLog->setCtlAuditEngineActive(); } -#line 4896 "seclang-parser.cc" +#line 4899 "seclang-parser.cc" break; case 347: // act: "ACTION_CTL_AUDIT_ENGINE" "CONFIG_VALUE_OFF" -#line 2662 "seclang-parser.yy" +#line 2665 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::AuditEngine("ctl:auditengine=off")); } -#line 4904 "seclang-parser.cc" +#line 4907 "seclang-parser.cc" break; case 348: // act: "ACTION_CTL_AUDIT_ENGINE" "CONFIG_VALUE_RELEVANT_ONLY" -#line 2666 "seclang-parser.yy" +#line 2669 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::AuditEngine("ctl:auditengine=relevantonly")); driver.m_auditLog->setCtlAuditEngineActive(); } -#line 4913 "seclang-parser.cc" +#line 4916 "seclang-parser.cc" break; case 349: // act: "ACTION_CTL_AUDIT_LOG_PARTS" -#line 2671 "seclang-parser.yy" +#line 2674 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::AuditLogParts(yystack_[0].value.as < std::string > ())); } -#line 4921 "seclang-parser.cc" +#line 4924 "seclang-parser.cc" break; case 350: // act: "ACTION_CTL_BDY_JSON" -#line 2675 "seclang-parser.yy" +#line 2678 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RequestBodyProcessorJSON(yystack_[0].value.as < std::string > ())); } -#line 4929 "seclang-parser.cc" +#line 4932 "seclang-parser.cc" break; case 351: // act: "ACTION_CTL_BDY_XML" -#line 2679 "seclang-parser.yy" +#line 2682 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RequestBodyProcessorXML(yystack_[0].value.as < std::string > ())); } -#line 4937 "seclang-parser.cc" +#line 4940 "seclang-parser.cc" break; case 352: // act: "ACTION_CTL_BDY_URLENCODED" -#line 2683 "seclang-parser.yy" +#line 2686 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RequestBodyProcessorURLENCODED(yystack_[0].value.as < std::string > ())); } -#line 4945 "seclang-parser.cc" +#line 4948 "seclang-parser.cc" break; case 353: // act: "ACTION_CTL_FORCE_REQ_BODY_VAR" "CONFIG_VALUE_ON" -#line 2687 "seclang-parser.yy" +#line 2690 "seclang-parser.yy" { //ACTION_NOT_SUPPORTED("CtlForceReequestBody", @0); ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Action(yystack_[1].value.as < std::string > ())); } -#line 4954 "seclang-parser.cc" +#line 4957 "seclang-parser.cc" break; case 354: // act: "ACTION_CTL_FORCE_REQ_BODY_VAR" "CONFIG_VALUE_OFF" -#line 2692 "seclang-parser.yy" +#line 2695 "seclang-parser.yy" { //ACTION_NOT_SUPPORTED("CtlForceReequestBody", @0); ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Action(yystack_[1].value.as < std::string > ())); } -#line 4963 "seclang-parser.cc" +#line 4966 "seclang-parser.cc" break; case 355: // act: "ACTION_CTL_REQUEST_BODY_ACCESS" "CONFIG_VALUE_ON" -#line 2697 "seclang-parser.yy" +#line 2700 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RequestBodyAccess(yystack_[1].value.as < std::string > () + "true")); } -#line 4971 "seclang-parser.cc" +#line 4974 "seclang-parser.cc" break; case 356: // act: "ACTION_CTL_REQUEST_BODY_ACCESS" "CONFIG_VALUE_OFF" -#line 2701 "seclang-parser.yy" +#line 2704 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RequestBodyAccess(yystack_[1].value.as < std::string > () + "false")); } -#line 4979 "seclang-parser.cc" +#line 4982 "seclang-parser.cc" break; case 357: // act: "ACTION_CTL_RULE_ENGINE" "CONFIG_VALUE_ON" -#line 2705 "seclang-parser.yy" +#line 2708 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RuleEngine("ctl:RuleEngine=on")); } -#line 4987 "seclang-parser.cc" +#line 4990 "seclang-parser.cc" break; case 358: // act: "ACTION_CTL_RULE_ENGINE" "CONFIG_VALUE_OFF" -#line 2709 "seclang-parser.yy" +#line 2712 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RuleEngine("ctl:RuleEngine=off")); } -#line 4995 "seclang-parser.cc" +#line 4998 "seclang-parser.cc" break; case 359: // act: "ACTION_CTL_RULE_ENGINE" "CONFIG_VALUE_DETC" -#line 2713 "seclang-parser.yy" +#line 2716 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RuleEngine("ctl:RuleEngine=detectiononly")); } -#line 5003 "seclang-parser.cc" +#line 5006 "seclang-parser.cc" break; case 360: // act: "ACTION_CTL_RULE_REMOVE_BY_ID" -#line 2717 "seclang-parser.yy" +#line 2720 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RuleRemoveById(yystack_[0].value.as < std::string > ())); } -#line 5011 "seclang-parser.cc" +#line 5014 "seclang-parser.cc" break; case 361: // act: "ACTION_CTL_RULE_REMOVE_BY_TAG" -#line 2721 "seclang-parser.yy" +#line 2724 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RuleRemoveByTag(yystack_[0].value.as < std::string > ())); } -#line 5019 "seclang-parser.cc" +#line 5022 "seclang-parser.cc" break; case 362: // act: "ACTION_CTL_RULE_REMOVE_TARGET_BY_ID" -#line 2725 "seclang-parser.yy" +#line 2728 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RuleRemoveTargetById(yystack_[0].value.as < std::string > ())); } -#line 5027 "seclang-parser.cc" +#line 5030 "seclang-parser.cc" break; case 363: // act: "ACTION_CTL_RULE_REMOVE_TARGET_BY_TAG" -#line 2729 "seclang-parser.yy" +#line 2732 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ctl::RuleRemoveTargetByTag(yystack_[0].value.as < std::string > ())); } -#line 5035 "seclang-parser.cc" +#line 5038 "seclang-parser.cc" break; case 364: // act: "Deny" -#line 2733 "seclang-parser.yy" +#line 2736 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::disruptive::Deny(yystack_[0].value.as < std::string > ())); } -#line 5043 "seclang-parser.cc" +#line 5046 "seclang-parser.cc" break; case 365: // act: "DeprecateVar" -#line 2737 "seclang-parser.yy" +#line 2740 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("DeprecateVar", yystack_[1].location); } -#line 5051 "seclang-parser.cc" +#line 5054 "seclang-parser.cc" break; case 366: // act: "Drop" -#line 2741 "seclang-parser.yy" +#line 2744 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::disruptive::Drop(yystack_[0].value.as < std::string > ())); } -#line 5059 "seclang-parser.cc" +#line 5062 "seclang-parser.cc" break; case 367: // act: "Exec" -#line 2745 "seclang-parser.yy" +#line 2748 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Exec(yystack_[0].value.as < std::string > ())); } -#line 5067 "seclang-parser.cc" +#line 5070 "seclang-parser.cc" break; case 368: // act: "ExpireVar" run_time_string -#line 2749 "seclang-parser.yy" +#line 2752 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::ExpireVar(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5075 "seclang-parser.cc" +#line 5078 "seclang-parser.cc" break; case 369: // act: "Id" -#line 2753 "seclang-parser.yy" +#line 2756 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::RuleId(yystack_[0].value.as < std::string > ())); } -#line 5083 "seclang-parser.cc" +#line 5086 "seclang-parser.cc" break; case 370: // act: "InitCol" run_time_string -#line 2757 "seclang-parser.yy" +#line 2760 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::InitCol(yystack_[1].value.as < std::string > (), std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5091 "seclang-parser.cc" +#line 5094 "seclang-parser.cc" break; case 371: // act: "LogData" run_time_string -#line 2761 "seclang-parser.yy" +#line 2764 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::LogData(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5099 "seclang-parser.cc" +#line 5102 "seclang-parser.cc" break; case 372: // act: "Log" -#line 2765 "seclang-parser.yy" +#line 2768 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Log(yystack_[0].value.as < std::string > ())); } -#line 5107 "seclang-parser.cc" +#line 5110 "seclang-parser.cc" break; case 373: // act: "Maturity" -#line 2769 "seclang-parser.yy" +#line 2772 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Maturity(yystack_[0].value.as < std::string > ())); } -#line 5115 "seclang-parser.cc" +#line 5118 "seclang-parser.cc" break; case 374: // act: "Msg" run_time_string -#line 2773 "seclang-parser.yy" +#line 2776 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Msg(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5123 "seclang-parser.cc" +#line 5126 "seclang-parser.cc" break; case 375: // act: "MultiMatch" -#line 2777 "seclang-parser.yy" +#line 2780 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::MultiMatch(yystack_[0].value.as < std::string > ())); } -#line 5131 "seclang-parser.cc" +#line 5134 "seclang-parser.cc" break; case 376: // act: "NoAuditLog" -#line 2781 "seclang-parser.yy" +#line 2784 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::NoAuditLog(yystack_[0].value.as < std::string > ())); } -#line 5139 "seclang-parser.cc" +#line 5142 "seclang-parser.cc" break; case 377: // act: "NoLog" -#line 2785 "seclang-parser.yy" +#line 2788 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::NoLog(yystack_[0].value.as < std::string > ())); } -#line 5147 "seclang-parser.cc" +#line 5150 "seclang-parser.cc" break; case 378: // act: "Pass" -#line 2789 "seclang-parser.yy" +#line 2792 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::disruptive::Pass(yystack_[0].value.as < std::string > ())); } -#line 5155 "seclang-parser.cc" +#line 5158 "seclang-parser.cc" break; case 379: // act: "Pause" -#line 2793 "seclang-parser.yy" +#line 2796 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("Pause", yystack_[1].location); } -#line 5163 "seclang-parser.cc" +#line 5166 "seclang-parser.cc" break; case 380: // act: "Phase" -#line 2797 "seclang-parser.yy" +#line 2800 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Phase(yystack_[0].value.as < std::string > ())); } -#line 5171 "seclang-parser.cc" +#line 5174 "seclang-parser.cc" break; case 381: // act: "Prepend" -#line 2801 "seclang-parser.yy" +#line 2804 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("Prepend", yystack_[1].location); } -#line 5179 "seclang-parser.cc" +#line 5182 "seclang-parser.cc" break; case 382: // act: "Proxy" -#line 2805 "seclang-parser.yy" +#line 2808 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("Proxy", yystack_[1].location); } -#line 5187 "seclang-parser.cc" +#line 5190 "seclang-parser.cc" break; case 383: // act: "Redirect" run_time_string -#line 2809 "seclang-parser.yy" +#line 2812 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::disruptive::Redirect(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5195 "seclang-parser.cc" +#line 5198 "seclang-parser.cc" break; case 384: // act: "Rev" -#line 2813 "seclang-parser.yy" +#line 2816 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Rev(yystack_[0].value.as < std::string > ())); } -#line 5203 "seclang-parser.cc" +#line 5206 "seclang-parser.cc" break; case 385: // act: "SanitiseArg" -#line 2817 "seclang-parser.yy" +#line 2820 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("SanitiseArg", yystack_[1].location); } -#line 5211 "seclang-parser.cc" +#line 5214 "seclang-parser.cc" break; case 386: // act: "SanitiseMatched" -#line 2821 "seclang-parser.yy" +#line 2824 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("SanitiseMatched", yystack_[1].location); } -#line 5219 "seclang-parser.cc" +#line 5222 "seclang-parser.cc" break; case 387: // act: "SanitiseMatchedBytes" -#line 2825 "seclang-parser.yy" +#line 2828 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("SanitiseMatchedBytes", yystack_[1].location); } -#line 5227 "seclang-parser.cc" +#line 5230 "seclang-parser.cc" break; case 388: // act: "SanitiseRequestHeader" -#line 2829 "seclang-parser.yy" +#line 2832 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("SanitiseRequestHeader", yystack_[1].location); } -#line 5235 "seclang-parser.cc" +#line 5238 "seclang-parser.cc" break; case 389: // act: "SanitiseResponseHeader" -#line 2833 "seclang-parser.yy" +#line 2836 "seclang-parser.yy" { ACTION_NOT_SUPPORTED("SanitiseResponseHeader", yystack_[1].location); } -#line 5243 "seclang-parser.cc" +#line 5246 "seclang-parser.cc" break; case 390: // act: "SetEnv" run_time_string -#line 2837 "seclang-parser.yy" +#line 2840 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetENV(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5251 "seclang-parser.cc" +#line 5254 "seclang-parser.cc" break; case 391: // act: "SetRsc" run_time_string -#line 2841 "seclang-parser.yy" +#line 2844 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetRSC(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5259 "seclang-parser.cc" +#line 5262 "seclang-parser.cc" break; case 392: // act: "SetSid" run_time_string -#line 2845 "seclang-parser.yy" +#line 2848 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetSID(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5267 "seclang-parser.cc" +#line 5270 "seclang-parser.cc" break; case 393: // act: "SetUID" run_time_string -#line 2849 "seclang-parser.yy" +#line 2852 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetUID(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5275 "seclang-parser.cc" +#line 5278 "seclang-parser.cc" break; case 394: // act: "SetVar" setvar_action -#line 2853 "seclang-parser.yy" +#line 2856 "seclang-parser.yy" { yylhs.value.as < std::unique_ptr > () = std::move(yystack_[0].value.as < std::unique_ptr > ()); } -#line 5283 "seclang-parser.cc" +#line 5286 "seclang-parser.cc" break; case 395: // act: "Severity" -#line 2857 "seclang-parser.yy" +#line 2860 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Severity(yystack_[0].value.as < std::string > ())); } -#line 5291 "seclang-parser.cc" +#line 5294 "seclang-parser.cc" break; case 396: // act: "Skip" -#line 2861 "seclang-parser.yy" +#line 2864 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Skip(yystack_[0].value.as < std::string > ())); } -#line 5299 "seclang-parser.cc" +#line 5302 "seclang-parser.cc" break; case 397: // act: "SkipAfter" -#line 2865 "seclang-parser.yy" +#line 2868 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SkipAfter(yystack_[0].value.as < std::string > ())); } -#line 5307 "seclang-parser.cc" +#line 5310 "seclang-parser.cc" break; case 398: // act: "Status" -#line 2869 "seclang-parser.yy" +#line 2872 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::data::Status(yystack_[0].value.as < std::string > ())); } -#line 5315 "seclang-parser.cc" +#line 5318 "seclang-parser.cc" break; case 399: // act: "Tag" run_time_string -#line 2873 "seclang-parser.yy" +#line 2876 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Tag(std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5323 "seclang-parser.cc" +#line 5326 "seclang-parser.cc" break; case 400: // act: "Ver" -#line 2877 "seclang-parser.yy" +#line 2880 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::Ver(yystack_[0].value.as < std::string > ())); } -#line 5331 "seclang-parser.cc" +#line 5334 "seclang-parser.cc" break; case 401: // act: "xmlns" -#line 2881 "seclang-parser.yy" +#line 2884 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::XmlNS(yystack_[0].value.as < std::string > ())); } -#line 5339 "seclang-parser.cc" +#line 5342 "seclang-parser.cc" break; case 402: // act: "ACTION_TRANSFORMATION_PARITY_ZERO_7_BIT" -#line 2885 "seclang-parser.yy" +#line 2888 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::ParityZero7bit(yystack_[0].value.as < std::string > ())); } -#line 5347 "seclang-parser.cc" +#line 5350 "seclang-parser.cc" break; case 403: // act: "ACTION_TRANSFORMATION_PARITY_ODD_7_BIT" -#line 2889 "seclang-parser.yy" +#line 2892 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::ParityOdd7bit(yystack_[0].value.as < std::string > ())); } -#line 5355 "seclang-parser.cc" +#line 5358 "seclang-parser.cc" break; case 404: // act: "ACTION_TRANSFORMATION_PARITY_EVEN_7_BIT" -#line 2893 "seclang-parser.yy" +#line 2896 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::ParityEven7bit(yystack_[0].value.as < std::string > ())); } -#line 5363 "seclang-parser.cc" +#line 5366 "seclang-parser.cc" break; case 405: // act: "ACTION_TRANSFORMATION_SQL_HEX_DECODE" -#line 2897 "seclang-parser.yy" +#line 2900 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::SqlHexDecode(yystack_[0].value.as < std::string > ())); } -#line 5371 "seclang-parser.cc" +#line 5374 "seclang-parser.cc" break; case 406: // act: "ACTION_TRANSFORMATION_BASE_64_ENCODE" -#line 2901 "seclang-parser.yy" +#line 2904 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Base64Encode(yystack_[0].value.as < std::string > ())); } -#line 5379 "seclang-parser.cc" +#line 5382 "seclang-parser.cc" break; case 407: // act: "ACTION_TRANSFORMATION_BASE_64_DECODE" -#line 2905 "seclang-parser.yy" +#line 2908 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Base64Decode(yystack_[0].value.as < std::string > ())); } -#line 5387 "seclang-parser.cc" +#line 5390 "seclang-parser.cc" break; case 408: // act: "ACTION_TRANSFORMATION_BASE_64_DECODE_EXT" -#line 2909 "seclang-parser.yy" +#line 2912 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Base64DecodeExt(yystack_[0].value.as < std::string > ())); } -#line 5395 "seclang-parser.cc" +#line 5398 "seclang-parser.cc" break; case 409: // act: "ACTION_TRANSFORMATION_CMD_LINE" -#line 2913 "seclang-parser.yy" +#line 2916 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::CmdLine(yystack_[0].value.as < std::string > ())); } -#line 5403 "seclang-parser.cc" +#line 5406 "seclang-parser.cc" break; case 410: // act: "ACTION_TRANSFORMATION_SHA1" -#line 2917 "seclang-parser.yy" +#line 2920 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Sha1(yystack_[0].value.as < std::string > ())); } -#line 5411 "seclang-parser.cc" +#line 5414 "seclang-parser.cc" break; case 411: // act: "ACTION_TRANSFORMATION_MD5" -#line 2921 "seclang-parser.yy" +#line 2924 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Md5(yystack_[0].value.as < std::string > ())); } -#line 5419 "seclang-parser.cc" +#line 5422 "seclang-parser.cc" break; case 412: // act: "ACTION_TRANSFORMATION_ESCAPE_SEQ_DECODE" -#line 2925 "seclang-parser.yy" +#line 2928 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::EscapeSeqDecode(yystack_[0].value.as < std::string > ())); } -#line 5427 "seclang-parser.cc" +#line 5430 "seclang-parser.cc" break; case 413: // act: "ACTION_TRANSFORMATION_HEX_ENCODE" -#line 2929 "seclang-parser.yy" +#line 2932 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::HexEncode(yystack_[0].value.as < std::string > ())); } -#line 5435 "seclang-parser.cc" +#line 5438 "seclang-parser.cc" break; case 414: // act: "ACTION_TRANSFORMATION_HEX_DECODE" -#line 2933 "seclang-parser.yy" +#line 2936 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::HexDecode(yystack_[0].value.as < std::string > ())); } -#line 5443 "seclang-parser.cc" +#line 5446 "seclang-parser.cc" break; case 415: // act: "ACTION_TRANSFORMATION_LOWERCASE" -#line 2937 "seclang-parser.yy" +#line 2940 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::LowerCase(yystack_[0].value.as < std::string > ())); } -#line 5451 "seclang-parser.cc" +#line 5454 "seclang-parser.cc" break; case 416: // act: "ACTION_TRANSFORMATION_UPPERCASE" -#line 2941 "seclang-parser.yy" +#line 2944 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::UpperCase(yystack_[0].value.as < std::string > ())); } -#line 5459 "seclang-parser.cc" +#line 5462 "seclang-parser.cc" break; case 417: // act: "ACTION_TRANSFORMATION_URL_DECODE_UNI" -#line 2945 "seclang-parser.yy" +#line 2948 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::UrlDecodeUni(yystack_[0].value.as < std::string > ())); } -#line 5467 "seclang-parser.cc" +#line 5470 "seclang-parser.cc" break; case 418: // act: "ACTION_TRANSFORMATION_URL_DECODE" -#line 2949 "seclang-parser.yy" +#line 2952 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::UrlDecode(yystack_[0].value.as < std::string > ())); } -#line 5475 "seclang-parser.cc" +#line 5478 "seclang-parser.cc" break; case 419: // act: "ACTION_TRANSFORMATION_URL_ENCODE" -#line 2953 "seclang-parser.yy" +#line 2956 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::UrlEncode(yystack_[0].value.as < std::string > ())); } -#line 5483 "seclang-parser.cc" +#line 5486 "seclang-parser.cc" break; case 420: // act: "ACTION_TRANSFORMATION_NONE" -#line 2957 "seclang-parser.yy" +#line 2960 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::None(yystack_[0].value.as < std::string > ())); } -#line 5491 "seclang-parser.cc" +#line 5494 "seclang-parser.cc" break; case 421: // act: "ACTION_TRANSFORMATION_COMPRESS_WHITESPACE" -#line 2961 "seclang-parser.yy" +#line 2964 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::CompressWhitespace(yystack_[0].value.as < std::string > ())); } -#line 5499 "seclang-parser.cc" +#line 5502 "seclang-parser.cc" break; case 422: // act: "ACTION_TRANSFORMATION_REMOVE_WHITESPACE" -#line 2965 "seclang-parser.yy" +#line 2968 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::RemoveWhitespace(yystack_[0].value.as < std::string > ())); } -#line 5507 "seclang-parser.cc" +#line 5510 "seclang-parser.cc" break; case 423: // act: "ACTION_TRANSFORMATION_REPLACE_NULLS" -#line 2969 "seclang-parser.yy" +#line 2972 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::ReplaceNulls(yystack_[0].value.as < std::string > ())); } -#line 5515 "seclang-parser.cc" +#line 5518 "seclang-parser.cc" break; case 424: // act: "ACTION_TRANSFORMATION_REMOVE_NULLS" -#line 2973 "seclang-parser.yy" +#line 2976 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::RemoveNulls(yystack_[0].value.as < std::string > ())); } -#line 5523 "seclang-parser.cc" +#line 5526 "seclang-parser.cc" break; case 425: // act: "ACTION_TRANSFORMATION_HTML_ENTITY_DECODE" -#line 2977 "seclang-parser.yy" +#line 2980 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::HtmlEntityDecode(yystack_[0].value.as < std::string > ())); } -#line 5531 "seclang-parser.cc" +#line 5534 "seclang-parser.cc" break; case 426: // act: "ACTION_TRANSFORMATION_JS_DECODE" -#line 2981 "seclang-parser.yy" +#line 2984 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::JsDecode(yystack_[0].value.as < std::string > ())); } -#line 5539 "seclang-parser.cc" +#line 5542 "seclang-parser.cc" break; case 427: // act: "ACTION_TRANSFORMATION_CSS_DECODE" -#line 2985 "seclang-parser.yy" +#line 2988 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::CssDecode(yystack_[0].value.as < std::string > ())); } -#line 5547 "seclang-parser.cc" +#line 5550 "seclang-parser.cc" break; case 428: // act: "ACTION_TRANSFORMATION_TRIM" -#line 2989 "seclang-parser.yy" +#line 2992 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Trim(yystack_[0].value.as < std::string > ())); } -#line 5555 "seclang-parser.cc" +#line 5558 "seclang-parser.cc" break; case 429: // act: "ACTION_TRANSFORMATION_TRIM_LEFT" -#line 2993 "seclang-parser.yy" +#line 2996 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::TrimLeft(yystack_[0].value.as < std::string > ())); } -#line 5563 "seclang-parser.cc" +#line 5566 "seclang-parser.cc" break; case 430: // act: "ACTION_TRANSFORMATION_TRIM_RIGHT" -#line 2997 "seclang-parser.yy" +#line 3000 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::TrimRight(yystack_[0].value.as < std::string > ())); } -#line 5571 "seclang-parser.cc" +#line 5574 "seclang-parser.cc" break; case 431: // act: "ACTION_TRANSFORMATION_NORMALISE_PATH_WIN" -#line 3001 "seclang-parser.yy" +#line 3004 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::NormalisePathWin(yystack_[0].value.as < std::string > ())); } -#line 5579 "seclang-parser.cc" +#line 5582 "seclang-parser.cc" break; case 432: // act: "ACTION_TRANSFORMATION_NORMALISE_PATH" -#line 3005 "seclang-parser.yy" +#line 3008 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::NormalisePath(yystack_[0].value.as < std::string > ())); } -#line 5587 "seclang-parser.cc" +#line 5590 "seclang-parser.cc" break; case 433: // act: "ACTION_TRANSFORMATION_LENGTH" -#line 3009 "seclang-parser.yy" +#line 3012 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Length(yystack_[0].value.as < std::string > ())); } -#line 5595 "seclang-parser.cc" +#line 5598 "seclang-parser.cc" break; case 434: // act: "ACTION_TRANSFORMATION_UTF8_TO_UNICODE" -#line 3013 "seclang-parser.yy" +#line 3016 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::Utf8ToUnicode(yystack_[0].value.as < std::string > ())); } -#line 5603 "seclang-parser.cc" +#line 5606 "seclang-parser.cc" break; case 435: // act: "ACTION_TRANSFORMATION_REMOVE_COMMENTS_CHAR" -#line 3017 "seclang-parser.yy" +#line 3020 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::RemoveCommentsChar(yystack_[0].value.as < std::string > ())); } -#line 5611 "seclang-parser.cc" +#line 5614 "seclang-parser.cc" break; case 436: // act: "ACTION_TRANSFORMATION_REMOVE_COMMENTS" -#line 3021 "seclang-parser.yy" +#line 3024 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::RemoveComments(yystack_[0].value.as < std::string > ())); } -#line 5619 "seclang-parser.cc" +#line 5622 "seclang-parser.cc" break; case 437: // act: "ACTION_TRANSFORMATION_REPLACE_COMMENTS" -#line 3025 "seclang-parser.yy" +#line 3028 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::transformations::ReplaceComments(yystack_[0].value.as < std::string > ())); } -#line 5627 "seclang-parser.cc" +#line 5630 "seclang-parser.cc" break; case 438: // setvar_action: "NOT" var -#line 3032 "seclang-parser.yy" +#line 3035 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetVar(actions::SetVarOperation::unsetOperation, std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5635 "seclang-parser.cc" +#line 5638 "seclang-parser.cc" break; case 439: // setvar_action: var -#line 3036 "seclang-parser.yy" +#line 3039 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetVar(actions::SetVarOperation::setToOneOperation, std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5643 "seclang-parser.cc" +#line 5646 "seclang-parser.cc" break; case 440: // setvar_action: var SETVAR_OPERATION_EQUALS run_time_string -#line 3040 "seclang-parser.yy" +#line 3043 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetVar(actions::SetVarOperation::setOperation, std::move(yystack_[2].value.as < std::unique_ptr > ()), std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5651 "seclang-parser.cc" +#line 5654 "seclang-parser.cc" break; case 441: // setvar_action: var SETVAR_OPERATION_EQUALS_PLUS run_time_string -#line 3044 "seclang-parser.yy" +#line 3047 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetVar(actions::SetVarOperation::sumAndSetOperation, std::move(yystack_[2].value.as < std::unique_ptr > ()), std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5659 "seclang-parser.cc" +#line 5662 "seclang-parser.cc" break; case 442: // setvar_action: var SETVAR_OPERATION_EQUALS_MINUS run_time_string -#line 3048 "seclang-parser.yy" +#line 3051 "seclang-parser.yy" { ACTION_CONTAINER(yylhs.value.as < std::unique_ptr > (), new actions::SetVar(actions::SetVarOperation::substractAndSetOperation, std::move(yystack_[2].value.as < std::unique_ptr > ()), std::move(yystack_[0].value.as < std::unique_ptr > ()))); } -#line 5667 "seclang-parser.cc" +#line 5670 "seclang-parser.cc" break; case 443: // run_time_string: run_time_string "FREE_TEXT_QUOTE_MACRO_EXPANSION" -#line 3055 "seclang-parser.yy" +#line 3058 "seclang-parser.yy" { yystack_[1].value.as < std::unique_ptr > ()->appendText(yystack_[0].value.as < std::string > ()); yylhs.value.as < std::unique_ptr > () = std::move(yystack_[1].value.as < std::unique_ptr > ()); } -#line 5676 "seclang-parser.cc" +#line 5679 "seclang-parser.cc" break; case 444: // run_time_string: run_time_string var -#line 3060 "seclang-parser.yy" +#line 3063 "seclang-parser.yy" { yystack_[1].value.as < std::unique_ptr > ()->appendVar(std::move(yystack_[0].value.as < std::unique_ptr > ())); yylhs.value.as < std::unique_ptr > () = std::move(yystack_[1].value.as < std::unique_ptr > ()); } -#line 5685 "seclang-parser.cc" +#line 5688 "seclang-parser.cc" break; case 445: // run_time_string: "FREE_TEXT_QUOTE_MACRO_EXPANSION" -#line 3065 "seclang-parser.yy" +#line 3068 "seclang-parser.yy" { std::unique_ptr r(new RunTimeString()); r->appendText(yystack_[0].value.as < std::string > ()); yylhs.value.as < std::unique_ptr > () = std::move(r); } -#line 5695 "seclang-parser.cc" +#line 5698 "seclang-parser.cc" break; case 446: // run_time_string: var -#line 3071 "seclang-parser.yy" +#line 3074 "seclang-parser.yy" { std::unique_ptr r(new RunTimeString()); r->appendVar(std::move(yystack_[0].value.as < std::unique_ptr > ())); yylhs.value.as < std::unique_ptr > () = std::move(r); } -#line 5705 "seclang-parser.cc" +#line 5708 "seclang-parser.cc" break; -#line 5709 "seclang-parser.cc" +#line 5712 "seclang-parser.cc" default: break; @@ -7236,44 +7239,44 @@ namespace yy { 934, 938, 942, 946, 950, 954, 958, 963, 967, 971, 975, 979, 983, 988, 993, 997, 1001, 1005, 1009, 1013, 1017, 1021, 1025, 1029, 1033, 1037, 1041, 1045, 1049, 1053, - 1057, 1061, 1065, 1069, 1083, 1084, 1114, 1133, 1152, 1180, - 1237, 1244, 1248, 1252, 1256, 1260, 1264, 1268, 1272, 1281, - 1285, 1290, 1293, 1298, 1303, 1308, 1313, 1316, 1321, 1324, - 1329, 1334, 1337, 1342, 1347, 1352, 1357, 1362, 1367, 1372, - 1375, 1380, 1385, 1390, 1395, 1398, 1403, 1408, 1413, 1426, - 1439, 1452, 1465, 1478, 1504, 1532, 1544, 1564, 1591, 1596, - 1602, 1607, 1612, 1621, 1626, 1630, 1634, 1638, 1642, 1646, - 1650, 1655, 1660, 1672, 1678, 1682, 1686, 1697, 1706, 1707, - 1714, 1719, 1724, 1778, 1785, 1793, 1830, 1834, 1841, 1846, - 1852, 1858, 1864, 1871, 1881, 1885, 1889, 1893, 1897, 1901, - 1905, 1909, 1913, 1917, 1921, 1925, 1929, 1933, 1937, 1941, - 1945, 1949, 1953, 1957, 1961, 1965, 1969, 1973, 1977, 1981, - 1985, 1989, 1993, 1997, 2001, 2005, 2009, 2013, 2017, 2021, - 2025, 2029, 2033, 2037, 2041, 2045, 2049, 2053, 2057, 2061, - 2065, 2069, 2073, 2077, 2081, 2085, 2089, 2093, 2097, 2101, - 2105, 2109, 2113, 2117, 2121, 2125, 2129, 2133, 2137, 2141, - 2145, 2149, 2153, 2157, 2161, 2165, 2169, 2173, 2177, 2181, - 2185, 2189, 2193, 2197, 2201, 2205, 2209, 2213, 2217, 2221, - 2225, 2229, 2233, 2237, 2241, 2245, 2249, 2254, 2258, 2262, - 2267, 2271, 2275, 2280, 2285, 2289, 2293, 2297, 2301, 2305, - 2309, 2313, 2317, 2321, 2325, 2329, 2333, 2337, 2341, 2345, - 2349, 2353, 2357, 2361, 2365, 2369, 2373, 2377, 2381, 2385, - 2389, 2393, 2397, 2401, 2405, 2409, 2413, 2417, 2421, 2425, - 2429, 2433, 2437, 2441, 2445, 2449, 2453, 2457, 2461, 2465, - 2469, 2473, 2477, 2481, 2485, 2489, 2493, 2497, 2501, 2505, - 2509, 2513, 2517, 2521, 2525, 2529, 2533, 2541, 2548, 2555, - 2562, 2569, 2576, 2583, 2590, 2597, 2604, 2611, 2618, 2628, - 2632, 2636, 2640, 2644, 2648, 2652, 2656, 2661, 2665, 2670, - 2674, 2678, 2682, 2686, 2691, 2696, 2700, 2704, 2708, 2712, - 2716, 2720, 2724, 2728, 2732, 2736, 2740, 2744, 2748, 2752, - 2756, 2760, 2764, 2768, 2772, 2776, 2780, 2784, 2788, 2792, - 2796, 2800, 2804, 2808, 2812, 2816, 2820, 2824, 2828, 2832, - 2836, 2840, 2844, 2848, 2852, 2856, 2860, 2864, 2868, 2872, - 2876, 2880, 2884, 2888, 2892, 2896, 2900, 2904, 2908, 2912, - 2916, 2920, 2924, 2928, 2932, 2936, 2940, 2944, 2948, 2952, - 2956, 2960, 2964, 2968, 2972, 2976, 2980, 2984, 2988, 2992, - 2996, 3000, 3004, 3008, 3012, 3016, 3020, 3024, 3031, 3035, - 3039, 3043, 3047, 3054, 3059, 3064, 3070 + 1057, 1061, 1065, 1069, 1083, 1084, 1115, 1134, 1154, 1183, + 1240, 1247, 1251, 1255, 1259, 1263, 1267, 1271, 1275, 1284, + 1288, 1293, 1296, 1301, 1306, 1311, 1316, 1319, 1324, 1327, + 1332, 1337, 1340, 1345, 1350, 1355, 1360, 1365, 1370, 1375, + 1378, 1383, 1388, 1393, 1398, 1401, 1406, 1411, 1416, 1429, + 1442, 1455, 1468, 1481, 1507, 1535, 1547, 1567, 1594, 1599, + 1605, 1610, 1615, 1624, 1629, 1633, 1637, 1641, 1645, 1649, + 1653, 1658, 1663, 1675, 1681, 1685, 1689, 1700, 1709, 1710, + 1717, 1722, 1727, 1781, 1788, 1796, 1833, 1837, 1844, 1849, + 1855, 1861, 1867, 1874, 1884, 1888, 1892, 1896, 1900, 1904, + 1908, 1912, 1916, 1920, 1924, 1928, 1932, 1936, 1940, 1944, + 1948, 1952, 1956, 1960, 1964, 1968, 1972, 1976, 1980, 1984, + 1988, 1992, 1996, 2000, 2004, 2008, 2012, 2016, 2020, 2024, + 2028, 2032, 2036, 2040, 2044, 2048, 2052, 2056, 2060, 2064, + 2068, 2072, 2076, 2080, 2084, 2088, 2092, 2096, 2100, 2104, + 2108, 2112, 2116, 2120, 2124, 2128, 2132, 2136, 2140, 2144, + 2148, 2152, 2156, 2160, 2164, 2168, 2172, 2176, 2180, 2184, + 2188, 2192, 2196, 2200, 2204, 2208, 2212, 2216, 2220, 2224, + 2228, 2232, 2236, 2240, 2244, 2248, 2252, 2257, 2261, 2265, + 2270, 2274, 2278, 2283, 2288, 2292, 2296, 2300, 2304, 2308, + 2312, 2316, 2320, 2324, 2328, 2332, 2336, 2340, 2344, 2348, + 2352, 2356, 2360, 2364, 2368, 2372, 2376, 2380, 2384, 2388, + 2392, 2396, 2400, 2404, 2408, 2412, 2416, 2420, 2424, 2428, + 2432, 2436, 2440, 2444, 2448, 2452, 2456, 2460, 2464, 2468, + 2472, 2476, 2480, 2484, 2488, 2492, 2496, 2500, 2504, 2508, + 2512, 2516, 2520, 2524, 2528, 2532, 2536, 2544, 2551, 2558, + 2565, 2572, 2579, 2586, 2593, 2600, 2607, 2614, 2621, 2631, + 2635, 2639, 2643, 2647, 2651, 2655, 2659, 2664, 2668, 2673, + 2677, 2681, 2685, 2689, 2694, 2699, 2703, 2707, 2711, 2715, + 2719, 2723, 2727, 2731, 2735, 2739, 2743, 2747, 2751, 2755, + 2759, 2763, 2767, 2771, 2775, 2779, 2783, 2787, 2791, 2795, + 2799, 2803, 2807, 2811, 2815, 2819, 2823, 2827, 2831, 2835, + 2839, 2843, 2847, 2851, 2855, 2859, 2863, 2867, 2871, 2875, + 2879, 2883, 2887, 2891, 2895, 2899, 2903, 2907, 2911, 2915, + 2919, 2923, 2927, 2931, 2935, 2939, 2943, 2947, 2951, 2955, + 2959, 2963, 2967, 2971, 2975, 2979, 2983, 2987, 2991, 2995, + 2999, 3003, 3007, 3011, 3015, 3019, 3023, 3027, 3034, 3038, + 3042, 3046, 3050, 3057, 3062, 3067, 3073 }; void @@ -7305,9 +7308,9 @@ namespace yy { } // yy -#line 7309 "seclang-parser.cc" +#line 7312 "seclang-parser.cc" -#line 3077 "seclang-parser.yy" +#line 3080 "seclang-parser.yy" void yy::seclang_parser::error (const location_type& l, const std::string& m) { diff --git a/src/parser/seclang-parser.yy b/src/parser/seclang-parser.yy index 0be74565..41583768 100644 --- a/src/parser/seclang-parser.yy +++ b/src/parser/seclang-parser.yy @@ -1086,8 +1086,9 @@ expression: std::vector *a = new std::vector(); std::vector *t = new std::vector(); for (auto &i : *$4.get()) { - if (dynamic_cast(i.get())) { - t->push_back(dynamic_cast(i.release())); + if (auto pt = dynamic_cast(i.get())) { + t->push_back(pt); + i.release(); } else { a->push_back(i.release()); } @@ -1135,8 +1136,9 @@ expression: std::vector *a = new std::vector(); std::vector *t = new std::vector(); for (auto &i : *$2.get()) { - if (dynamic_cast(i.get())) { - t->push_back(dynamic_cast(i.release())); + if (auto pt = dynamic_cast(i.get())) { + t->push_back(pt); + i.release(); } else { a->push_back(i.release()); } @@ -1155,8 +1157,9 @@ expression: std::vector *a = new std::vector(); std::vector *t = new std::vector(); for (auto &i : *$2.get()) { - if (dynamic_cast(i.get())) { - t->push_back(dynamic_cast(i.release())); + if (auto pt = dynamic_cast(i.get())) { + t->push_back(pt); + i.release(); } else { a->push_back(i.release()); } @@ -1196,8 +1199,8 @@ expression: definedPhase = phase->m_phase; secRuleDefinedPhase = phase->m_secRulesPhase; delete phase; - } else if (a->action_kind == actions::Action::RunTimeOnlyIfMatchKind || - a->action_kind == actions::Action::RunTimeBeforeMatchAttemptKind) { + } else if (a->action_kind == actions::Action::Kind::RunTimeOnlyIfMatchKind || + a->action_kind == actions::Action::Kind::RunTimeBeforeMatchAttemptKind) { actions::transformations::None *none = dynamic_cast(a); if (none != NULL) { driver.error(@0, "The transformation none is not suitable to be part of the SecDefaultActions"); diff --git a/src/request_body_processor/multipart.cc b/src/request_body_processor/multipart.cc index d9ed6c6d..71d0d0e8 100644 --- a/src/request_body_processor/multipart.cc +++ b/src/request_body_processor/multipart.cc @@ -65,27 +65,25 @@ MultipartPartTmpFile::~MultipartPartTmpFile() { } void MultipartPartTmpFile::Open() { - struct tm timeinfo; - time_t tt = time(NULL); + time_t tt = time(nullptr); + struct tm timeinfo; localtime_r(&tt, &timeinfo); - char tstr[300] {}; - strftime(tstr, 299, "/%Y%m%d-%H%M%S", &timeinfo); + char tstr[std::size("/yyyymmdd-hhmmss")]; + strftime(tstr, std::size(tstr), "/%Y%m%d-%H%M%S", &timeinfo); std::string path = m_transaction->m_rules->m_uploadDirectory.m_value; path = path + tstr + "-" + *m_transaction->m_id.get(); path += "-file-XXXXXX"; - char* tmp = strdup(path.c_str()); #ifndef WIN32 - m_tmp_file_fd = mkstemp(tmp); + m_tmp_file_fd = mkstemp(path.data()); #else - _mktemp_s(tmp, path.length()+1); - m_tmp_file_fd = _open(tmp, _O_CREAT | _O_EXCL | _O_RDWR); + _mktemp_s(path.data(), path.length()+1); + m_tmp_file_fd = _open(path.c_str(), _O_CREAT | _O_EXCL | _O_RDWR); #endif - m_tmp_file_name.assign(tmp); - free(tmp); + m_tmp_file_name = path; ms_dbg_a(m_transaction, 4, "MultipartPartTmpFile: Create filename= " + m_tmp_file_name); int mode = m_transaction->m_rules->m_uploadFileMode.m_value; @@ -857,7 +855,7 @@ int Multipart::process_part_header(std::string *error, int offset) { } new_value = std::string(data); - utils::string::chomp(&new_value); + utils::string::chomp(new_value); /* update the header value in the table */ header_value = m_mpp->m_headers.at( @@ -918,6 +916,18 @@ int Multipart::process_part_header(std::string *error, int offset) { return false; } + /* check if multipart header contains any invalid characters */ + for (const auto& ch : header_name) { + if (ch < 33 || ch > 126) { + ms_dbg_a(m_transaction, 1, + "Multipart: Invalid part header " \ + "(contains invalid character)."); + error->assign("Multipart: Invalid part header "\ + "(contains invalid character)."); + return false; + } + } + /* extract the value value */ data++; i++; @@ -926,7 +936,7 @@ int Multipart::process_part_header(std::string *error, int offset) { i++; } header_value = std::string(data); - utils::string::chomp(&header_value); + utils::string::chomp(header_value); /* error if the name already exists */ if (m_mpp->m_headers.count(header_name) > 0) { @@ -1271,22 +1281,10 @@ int Multipart::multipart_complete(std::string *error) { int Multipart::count_boundary_params(const std::string& str_header_value) { - std::string lower = utils::string::tolower(str_header_value); - const char *header_value = lower.c_str(); - char *duplicate = NULL; - char *s = NULL; int count = 0; - if (header_value == NULL) { - return -1; - } - - duplicate = strdup(header_value); - if (duplicate == NULL) { - return -1; - } - - s = duplicate; + const auto lower = utils::string::tolower(str_header_value); + const char *s = lower.c_str(); while ((s = strstr(s, "boundary")) != NULL) { s += 8; @@ -1295,7 +1293,6 @@ int Multipart::count_boundary_params(const std::string& str_header_value) { } } - free(duplicate); return count; } diff --git a/src/rule_with_actions.cc b/src/rule_with_actions.cc index 5ae7d407..1cde8005 100644 --- a/src/rule_with_actions.cc +++ b/src/rule_with_actions.cc @@ -17,6 +17,7 @@ #include +#include #include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include #include "modsecurity/rules_set.h" #include "src/operators/operator.h" @@ -86,45 +88,50 @@ RuleWithActions::RuleWithActions( if (actions) { for (Action *a : *actions) { - if (a->action_kind == Action::ConfigurationKind) { - a->evaluate(this, NULL); - delete a; - - } else if (a->action_kind == Action::RunTimeOnlyIfMatchKind) { - if (dynamic_cast(a)) { - m_containsCaptureAction = true; + switch (a->action_kind) { + case Action::Kind::ConfigurationKind: + a->evaluate(this, NULL); delete a; - } else if (dynamic_cast(a)) { - m_containsMultiMatchAction = true; - delete a; - } else if (dynamic_cast(a)) { - m_severity = dynamic_cast(a); - } else if (dynamic_cast(a)) { - m_logData = dynamic_cast(a); - } else if (dynamic_cast(a)) { - m_msg = dynamic_cast(a); - } else if (dynamic_cast(a)) { - m_actionsSetVar.push_back( - dynamic_cast(a)); - } else if (dynamic_cast(a)) { - m_actionsTag.push_back(dynamic_cast(a)); - } else if (dynamic_cast(a)) { - m_actionsRuntimePos.push_back(a); - m_containsStaticBlockAction = true; - } else if (a->isDisruptive() == true) { - if (m_disruptiveAction != nullptr) { - delete m_disruptiveAction; - m_disruptiveAction = nullptr; + break; + case Action::Kind::RunTimeOnlyIfMatchKind: + if (dynamic_cast(a)) { + m_containsCaptureAction = true; + delete a; + } else if (dynamic_cast(a)) { + m_containsMultiMatchAction = true; + delete a; + } else if (auto sa = dynamic_cast(a)) { + m_severity = sa; + } else if (auto lda = dynamic_cast(a)) { + m_logData = lda; + } else if (auto ma = dynamic_cast(a)) { + m_msg = ma; + } else if (auto sva = dynamic_cast(a)) { + m_actionsSetVar.push_back(sva); + } else if (auto ta = dynamic_cast(a)) { + m_actionsTag.push_back(ta); + } else if (dynamic_cast(a)) { + m_actionsRuntimePos.push_back(a); + m_containsStaticBlockAction = true; + } else if (a->isDisruptive() == true) { + if (m_disruptiveAction != nullptr) { + delete m_disruptiveAction; + m_disruptiveAction = nullptr; + } + m_disruptiveAction = a; + } else { + m_actionsRuntimePos.push_back(a); } - m_disruptiveAction = a; - } else { - m_actionsRuntimePos.push_back(a); - } - } else { - delete a; - std::cout << "General failure, action: " << a->m_name; - std::cout << " has an unknown type." << std::endl; - throw; // cppcheck-suppress rethrowNoCurrentException + break; + default: + std::cout << "General failure, action: " << a->m_name; + std::cout << " has an unknown type." << std::endl; + delete a; + #ifdef NDEBUG + break; + #else + assert(false); + #endif } } delete actions; @@ -206,7 +213,7 @@ void RuleWithActions::executeActionsIndependentOfChainedRuleResult(Transaction * if (m_ruleId != b.first) { continue; } - actions::Action *a = dynamic_cast(b.second.get()); + actions::Action *a = b.second.get(); if (a->isDisruptive() == true && *a->m_name.get() == "block") { ms_dbg_a(trans, 9, "Rule contains a `block' action"); *containsBlock = true; @@ -239,8 +246,8 @@ void RuleWithActions::executeActionsAfterFullMatch(Transaction *trans, bool containsBlock, std::shared_ptr ruleMessage) { bool disruptiveAlreadyExecuted = false; - for (auto &a : trans->m_rules->m_defaultActions[getPhase()]) { // cppcheck-suppress ctunullpointer - if (a.get()->action_kind != actions::Action::RunTimeOnlyIfMatchKind) { + for (const auto &a : trans->m_rules->m_defaultActions[getPhase()]) { // cppcheck-suppress ctunullpointer + if (a.get()->action_kind != actions::Action::Kind::RunTimeOnlyIfMatchKind) { continue; } if (!a.get()->isDisruptive()) { @@ -259,7 +266,7 @@ void RuleWithActions::executeActionsAfterFullMatch(Transaction *trans, if (m_ruleId != b.first) { continue; } - actions::Action *a = dynamic_cast(b.second.get()); + actions::Action *a = b.second.get(); executeAction(trans, containsBlock, ruleMessage, a, false); disruptiveAlreadyExecuted = true; } @@ -317,49 +324,42 @@ void RuleWithActions::executeAction(Transaction *trans, inline void RuleWithActions::executeTransformation( - actions::transformations::Transformation *a, - std::shared_ptr *value, - Transaction *trans, - TransformationResults *ret, - std::string *path, - int *nth) const { + const actions::transformations::Transformation &a, + std::string &value, + const Transaction *trans, + TransformationResults &ret, + std::string &path, + int &nth) const { - std::string *oldValue = (*value).get(); - std::string newValue = a->evaluate(*oldValue, trans); - - if (newValue != *oldValue) { - auto u = std::make_shared(newValue); - if (m_containsMultiMatchAction) { - ret->push_back(std::make_pair(u, a->m_name)); - (*nth)++; - } - *value = u; + if (a.transform(value, trans) && + m_containsMultiMatchAction) { + ret.emplace_back(value, a.m_name); + nth++; } - if (path->empty()) { - path->append(*a->m_name.get()); + if (path.empty()) { + path.append(*a.m_name.get()); } else { - path->append("," + *a->m_name.get()); + path.append("," + *a.m_name.get()); } ms_dbg_a(trans, 9, " T (" + \ - std::to_string(*nth) + ") " + \ - *a->m_name.get() + ": \"" + \ - utils::string::limitTo(80, newValue) +"\""); + std::to_string(nth) + ") " + \ + *a.m_name.get() + ": \"" + \ + utils::string::limitTo(80, value) +"\""); } void RuleWithActions::executeTransformations( - Transaction *trans, const std::string &in, TransformationResults &ret) { + const Transaction *trans, const std::string &in, TransformationResults &ret) { int none = 0; int transformations = 0; - std::string path(""); - auto value = std::make_shared(in); + std::string path; + auto value = in; if (m_containsMultiMatchAction == true) { /* keep the original value */ - ret.push_back(std::make_pair( - std::make_shared(*value), - std::make_shared(path))); + ret.emplace_back(value, + std::make_shared(path)); } for (Action *a : m_transformations) { @@ -374,22 +374,23 @@ void RuleWithActions::executeTransformations( if (none == 0) { for (auto &a : trans->m_rules->m_defaultActions[getPhase()]) { if (a->action_kind \ - != actions::Action::RunTimeBeforeMatchAttemptKind) { + != actions::Action::Kind::RunTimeBeforeMatchAttemptKind) { continue; } // FIXME: here the object needs to be a transformation already. - Transformation *t = dynamic_cast(a.get()); - executeTransformation(t, &value, trans, &ret, &path, - &transformations); + auto t = dynamic_cast(a.get()); + assert(t != nullptr); + executeTransformation(*t, value, trans, ret, path, + transformations); } } - for (Transformation *a : m_transformations) { + for (const Transformation *a : m_transformations) { + assert(a != nullptr); if (none == 0) { - Transformation *t = dynamic_cast(a); - executeTransformation(t, &value, trans, &ret, &path, - &transformations); + executeTransformation(*a, value, trans, ret, path, + transformations); } if (a->m_isNone) { none--; @@ -403,7 +404,8 @@ void RuleWithActions::executeTransformations( if (m_ruleId != b.first) { continue; } - Transformation *a = dynamic_cast(b.second.get()); + auto a = dynamic_cast(b.second.get()); + assert(a != nullptr); if (a->m_isNone) { none++; } @@ -414,11 +416,11 @@ void RuleWithActions::executeTransformations( if (m_ruleId != b.first) { continue; } - Transformation *a = dynamic_cast(b.second.get()); + auto a = dynamic_cast(b.second.get()); + assert(a != nullptr); if (none == 0) { - Transformation *t = dynamic_cast(a); - executeTransformation(t, &value, trans, &ret, &path, - &transformations); + executeTransformation(*a, value, trans, ret, path, + transformations); } if (a->m_isNone) { none--; @@ -432,9 +434,8 @@ void RuleWithActions::executeTransformations( } if (!m_containsMultiMatchAction) { - ret.push_back(std::make_pair( - std::make_shared(*value), - std::make_shared(path))); + ret.emplace_back(value, + std::make_shared(path)); } } @@ -472,7 +473,7 @@ std::vector RuleWithActions::getActionsByName(const std::stri if (m_ruleId != b.first) { continue; } - actions::Action *z = dynamic_cast(b.second.get()); + actions::Action *z = b.second.get(); if (*z->m_name.get() == name) { ret.push_back(z); } @@ -482,7 +483,7 @@ std::vector RuleWithActions::getActionsByName(const std::stri if (m_ruleId != b.first) { continue; } - actions::Action *z = dynamic_cast(b.second.get()); + actions::Action *z = b.second.get(); if (*z->m_name.get() == name) { ret.push_back(z); } diff --git a/src/rule_with_operator.cc b/src/rule_with_operator.cc index 3a5ff385..b043af5c 100644 --- a/src/rule_with_operator.cc +++ b/src/rule_with_operator.cc @@ -131,56 +131,43 @@ bool RuleWithOperator::executeOperatorAt(Transaction *trans, const std::string & } -void RuleWithOperator::getVariablesExceptions(Transaction *t, +template +void getVariablesExceptionsHelper( + variables::Variables *exclusion, variables::Variables *addition, + const MapType &map, Operation op) { + for (const auto &[x, v] : map) { + if (op(x)) { + auto b = v.get(); + if (auto vme = dynamic_cast(b)) { + exclusion->push_back(vme->m_base.get()); + } else { + addition->push_back(b); + } + } + } +} + + +void RuleWithOperator::getVariablesExceptions(Transaction &t, variables::Variables *exclusion, variables::Variables *addition) { - for (const auto &a : t->m_rules->m_exceptions.m_variable_update_target_by_tag) { // cppcheck-suppress ctunullpointer - if (containsTag(*a.first.get(), t) == false) { - continue; - } - Variable *b = a.second.get(); - if (dynamic_cast(b)) { - exclusion->push_back( - dynamic_cast( - b)->m_base.get()); - } else { - addition->push_back(b); - } - } + getVariablesExceptionsHelper(exclusion, addition, + t.m_rules->m_exceptions.m_variable_update_target_by_tag, + [this, &t](const auto &tag) { return containsTag(*tag.get(), &t); }); - for (const auto &a : t->m_rules->m_exceptions.m_variable_update_target_by_msg) { - if (containsMsg(*a.first.get(), t) == false) { - continue; - } - Variable *b = a.second.get(); - if (dynamic_cast(b)) { - exclusion->push_back( - dynamic_cast( - b)->m_base.get()); - } else { - addition->push_back(b); - } - } + getVariablesExceptionsHelper(exclusion, addition, + t.m_rules->m_exceptions.m_variable_update_target_by_msg, + [this, &t](const auto &msg) { return containsMsg(*msg.get(), &t); }); - for (const auto &a : t->m_rules->m_exceptions.m_variable_update_target_by_id) { - if (m_ruleId != a.first) { - continue; - } - Variable *b = a.second.get(); - if (dynamic_cast(b)) { - exclusion->push_back( - dynamic_cast( - b)->m_base.get()); - } else { - addition->push_back(b); - } - } + getVariablesExceptionsHelper(exclusion, addition, + t.m_rules->m_exceptions.m_variable_update_target_by_id, + [this](const auto &id) { return m_ruleId == id; }); } inline void RuleWithOperator::getFinalVars(variables::Variables *vars, variables::Variables *exclusion, Transaction *trans) { variables::Variables addition; - getVariablesExceptions(trans, exclusion, &addition); + getVariablesExceptions(*trans, exclusion, &addition); // cppcheck-suppress ctunullpointer for (int i = 0; i < m_variables->size(); i++) { Variable *variable = m_variables->at(i); @@ -309,10 +296,9 @@ bool RuleWithOperator::evaluate(Transaction *trans, executeTransformations(trans, value, values); for (const auto &valueTemp : values) { - bool ret; - std::string valueAfterTrans = std::move(*valueTemp.first); + const auto &valueAfterTrans = valueTemp.first; - ret = executeOperatorAt(trans, key, valueAfterTrans, ruleMessage); + const bool ret = executeOperatorAt(trans, key, valueAfterTrans, ruleMessage); if (ret == true) { ruleMessage->m_match = m_operator->resolveMatchMessage(trans, diff --git a/src/rules_exceptions.cc b/src/rules_exceptions.cc index 1349866d..71cf28c2 100644 --- a/src/rules_exceptions.cc +++ b/src/rules_exceptions.cc @@ -36,15 +36,15 @@ bool RulesExceptions::loadUpdateActionById(double id, std::string *error) { for (auto &a : *actions) { - if (a->action_kind == actions::Action::ConfigurationKind) { + if (a->action_kind == actions::Action::Kind::ConfigurationKind) { std::cout << "General failure, action: " << a->m_name; std::cout << " has not expected to be used with UpdateActionByID."; std::cout << std::endl; } else if (a->action_kind - == actions::Action::RunTimeBeforeMatchAttemptKind) { + == actions::Action::Kind::RunTimeBeforeMatchAttemptKind) { m_action_pre_update_target_by_id.emplace(std::pair>(id , std::move(a))); - } else if (a->action_kind == actions::Action::RunTimeOnlyIfMatchKind) { + } else if (a->action_kind == actions::Action::Kind::RunTimeOnlyIfMatchKind) { m_action_pos_update_target_by_id.emplace(std::pair>(id , std::move(a))); } else { diff --git a/src/rules_set.cc b/src/rules_set.cc index 883c78e1..025abe69 100644 --- a/src/rules_set.cc +++ b/src/rules_set.cc @@ -311,6 +311,21 @@ extern "C" int msc_rules_add(RulesSet *rules, const char *plain_rules, } +/** + * @name msc_rules_error_cleanup + * @brief Deallocates an error message buffer returned by a msc_rules_xxx function. + * + * This is a helper function to free the error message buffer allocated + * by a msc_rules_xxx function. + * + * @param error Error message pointer. + * + */ +extern "C" void msc_rules_error_cleanup(const char *error) { + free((void*) error); +} + + extern "C" int msc_rules_cleanup(RulesSet *rules) { delete rules; return true; diff --git a/src/transaction.cc b/src/transaction.cc index efd1cd1b..8c9dd669 100644 --- a/src/transaction.cc +++ b/src/transaction.cc @@ -348,46 +348,22 @@ bool Transaction::extractArguments(const std::string &orig, if (m_rules->m_secArgumentSeparator.m_set) { sep1 = m_rules->m_secArgumentSeparator.m_value.at(0); } - std::vector key_value_sets = utils::string::ssplit(buf, sep1); + const auto key_value_sets = utils::string::ssplit(buf, sep1); - for (std::string t : key_value_sets) { - char sep2 = '='; - size_t key_s = 0; - size_t value_s = 0; - int invalid = 0; - int changed = 0; + for (const auto &t : key_value_sets) { + const auto sep2 = '='; + auto [key, value] = utils::string::ssplit_pair(t, sep2); - std::string key; - std::string value; - std::pair key_value_pair = utils::string::ssplit_pair(t, sep2); - key = key_value_pair.first; - value = key_value_pair.second; + int invalid_count; + utils::urldecode_nonstrict_inplace(key, invalid_count); + utils::urldecode_nonstrict_inplace(value, invalid_count); - key_s = (key.length() + 1); - value_s = (value.length() + 1); - unsigned char *key_c = reinterpret_cast( - calloc(sizeof(char), key_s)); - unsigned char *value_c = reinterpret_cast( - calloc(sizeof(char), value_s)); - - memcpy(key_c, key.c_str(), key_s); - memcpy(value_c, value.c_str(), value_s); - - key_s = utils::urldecode_nonstrict_inplace(key_c, key_s, - &invalid, &changed); - value_s = utils::urldecode_nonstrict_inplace(value_c, value_s, - &invalid, &changed); - - if (invalid) { + if (invalid_count > 0) { m_variableUrlEncodedError.set("1", m_variableOffset); } - addArgument(orig, std::string(reinterpret_cast(key_c), key_s-1), - std::string(reinterpret_cast(value_c), value_s-1), offset); + addArgument(orig, key, value, offset); offset = offset + t.size() + 1; - - free(key_c); - free(value_c); } return true; @@ -1469,49 +1445,57 @@ int Transaction::processLogging() { * @brief Check if ModSecurity has anything to ask to the server. * * Intervention can generate a log event and/or perform a disruptive action. + * + * If the return value is true, all fields in the ModSecurityIntervention + * parameter have been initialized and are safe to access. + * If the return value is false, no changes to the ModSecurityIntervention + * parameter have been made. * - * @param Pointer ModSecurityIntervention structure + * @param it Pointer to ModSecurityIntervention structure * @retval true A intervention should be made. * @retval false Nothing to be done. * */ bool Transaction::intervention(ModSecurityIntervention *it) { + const auto disruptive = m_it.disruptive; if (m_it.disruptive) { if (m_it.url) { it->url = strdup(m_it.url); + } else { + it->url = NULL; } it->disruptive = m_it.disruptive; it->status = m_it.status; if (m_it.log != NULL) { - std::string log(""); - log.append(m_it.log); - utils::string::replaceAll(&log, std::string("%d"), + std::string log(m_it.log); + utils::string::replaceAll(log, "%d", std::to_string(it->status)); it->log = strdup(log.c_str()); + } else { + it->log = NULL; } intervention::reset(&m_it); } - return it->disruptive; + return disruptive; } std::string Transaction::toOldAuditLogFormatIndex(const std::string &filename, double size, const std::string &md5) { std::stringstream ss; - struct tm timeinfo; - char tstr[300]; - memset(tstr, '\0', 300); + struct tm timeinfo; localtime_r(&this->m_timeStamp, &timeinfo); - strftime(tstr, 299, "[%d/%b/%Y:%H:%M:%S %z]", &timeinfo); + char tstr[std::size("[dd/Mmm/yyyy:hh:mm:ss shhmm]")]; + strftime(tstr, std::size(tstr), "[%d/%b/%Y:%H:%M:%S %z]", &timeinfo); ss << utils::string::dash_if_empty( m_variableRequestHeaders.resolveFirst("Host").get()) << " "; - ss << utils::string::dash_if_empty(this->m_clientIpAddress->c_str()) << " "; + ss << utils::string::dash_if_empty(this->m_clientIpAddress.get()) << " "; /** TODO: Check variable */ variables::RemoteUser *r = new variables::RemoteUser("REMOTE_USER"); std::vector l; @@ -1522,7 +1506,7 @@ std::string Transaction::toOldAuditLogFormatIndex(const std::string &filename, delete r; ss << utils::string::dash_if_empty( - m_variableRemoteUser.c_str()); + &m_variableRemoteUser); ss << " "; /** TODO: Check variable */ //ss << utils::string::dash_if_empty( @@ -1563,14 +1547,14 @@ std::string Transaction::toOldAuditLogFormatIndex(const std::string &filename, std::string Transaction::toOldAuditLogFormat(int parts, const std::string &trailer) { std::stringstream audit_log; - struct tm timeinfo; - char tstr[300]; - memset(tstr, '\0', 300); + struct tm timeinfo; localtime_r(&this->m_timeStamp, &timeinfo); + char tstr[std::size("[dd/Mmm/yyyy:hh:mm:ss shhmm]")]; + strftime(tstr, std::size(tstr), "[%d/%b/%Y:%H:%M:%S %z]", &timeinfo); + audit_log << "--" << trailer << "-" << "A--" << std::endl; - strftime(tstr, 299, "[%d/%b/%Y:%H:%M:%S %z]", &timeinfo); audit_log << tstr; audit_log << " " << m_id->c_str(); audit_log << " " << this->m_clientIpAddress->c_str(); @@ -2260,11 +2244,16 @@ extern "C" void msc_transaction_cleanup(Transaction *transaction) { * * Intervention can generate a log event and/or perform a disruptive action. * - * @param transaction ModSecurity transaction. + * If the return value is not zero, all fields in the ModSecurityIntervention + * parameter have been initialized and are safe to access. + * If the return value is zero, no changes to the ModSecurityIntervention + * parameter have been made. * - * @return Pointer to ModSecurityIntervention structure - * @retval >0 A intervention should be made. - * @retval NULL Nothing to be done. + * @param transaction ModSecurity transaction. + * @param it Pointer to ModSecurityIntervention structure + * @returns If an intervention should be made + * @retval >0 A intervention should be made. + * @retval 0 Nothing to be done. * */ extern "C" int msc_intervention(Transaction *transaction, @@ -2273,6 +2262,22 @@ extern "C" int msc_intervention(Transaction *transaction, } +/** + * @name msc_intervention_cleanup + * @brief Removes all the resources allocated by a given Intervention. + * + * This is a helper function to free any allocated buffers owned by the + * intervention. + * + * @param it ModSecurity intervention. + * + */ +extern "C" void msc_intervention_cleanup(ModSecurityIntervention *it) { + intervention::free(it); + intervention::clean(it); +} + + /** * @name msc_get_response_body * @brief Retrieve a buffer with the updated response body. diff --git a/src/utils/acmp.cc b/src/utils/acmp.cc index 708ce3a2..fb61f31d 100644 --- a/src/utils/acmp.cc +++ b/src/utils/acmp.cc @@ -33,136 +33,9 @@ * that should be mitigated. This ACMP parser should be re-written to * consume less memory. */ + extern "C" { -char *parse_pm_content(const char *op_parm, unsigned short int op_len, const char **error_msg) { - char *parm = NULL; - char *content; - unsigned short int offset = 0; -// char converted = 0; - int i, x; - unsigned char bin = 0, esc = 0, bin_offset = 0; - unsigned char c = 0; - unsigned char bin_parm[3] = { 0 }; - char *processed = NULL; - - content = strdup(op_parm); - - if (content == NULL) { - *error_msg = std::string("Error allocating memory for pattern matching content.").c_str(); - return NULL; - } - - while (offset < op_len && (content[offset] == ' ' || content[offset] == '\t')) { - offset++; - }; - - op_len = strlen(content); - - if (content[offset] == '\"' && content[op_len-1] == '\"') { - parm = strdup(content + offset + 1); - if (parm == NULL) { - *error_msg = std::string("Error allocating memory for pattern matching content.").c_str(); - free(content); - content = NULL; - return NULL; - } - parm[op_len - offset - 2] = '\0'; - } else { - parm = strdup(content + offset); - if (parm == NULL) { - free(content); - content = NULL; - *error_msg = std::string("Error allocating memory for pattern matching content.").c_str(); - return NULL; - } - } - - free(content); - content = NULL; - - op_len = strlen(parm); - - if (op_len == 0) { - *error_msg = "Content length is 0."; - free(parm); - return NULL; - } - - for (i = 0, x = 0; i < op_len; i++) { - if (parm[i] == '|') { - if (bin) { - bin = 0; - } else { - bin = 1; - } - } else if(!esc && parm[i] == '\\') { - esc = 1; - } else { - if (bin) { - if (parm[i] == 0 || parm[i] == 1 || parm[i] == 2 || - parm[i] == 3 || parm[i] == 4 || parm[i] == 5 || - parm[i] == 6 || parm[i] == 7 || parm[i] == 8 || - parm[i] == 9 || - parm[i] == 'A' || parm[i] == 'a' || - parm[i] == 'B' || parm[i] == 'b' || - parm[i] == 'C' || parm[i] == 'c' || - parm[i] == 'D' || parm[i] == 'd' || - parm[i] == 'E' || parm[i] == 'e' || - parm[i] == 'F' || parm[i] == 'f') - { - bin_parm[bin_offset] = (char)parm[i]; - bin_offset++; - if (bin_offset == 2) { - c = strtol((char *)bin_parm, (char **) NULL, 16) & 0xFF; - bin_offset = 0; - parm[x] = c; - x++; - //converted = 1; - } - } else if (parm[i] == ' ') { - } - } else if (esc) { - if (parm[i] == ':' || - parm[i] == ';' || - parm[i] == '\\' || - parm[i] == '\"') - { - parm[x] = parm[i]; - x++; - } else { - *error_msg = std::string("Unsupported escape sequence.").c_str(); - free(parm); - return NULL; - } - esc = 0; - //converted = 1; - } else { - parm[x] = parm[i]; - x++; - } - } - } - -#if 0 - if (converted) { - op_len = x; - } -#endif - - //processed = memcpy(processed, parm, op_len); - processed = strdup(parm); - free(parm); - parm = NULL; - - if (processed == NULL) { - *error_msg = std::string("Error allocating memory for pattern matching content.").c_str(); - return NULL; - } - - return processed; -} - /* ******************************************************************************* ******************************************************************************* diff --git a/src/utils/acmp.h b/src/utils/acmp.h index 1af454e1..a93165fe 100644 --- a/src/utils/acmp.h +++ b/src/utils/acmp.h @@ -23,6 +23,7 @@ #endif #include +#include extern "C" { @@ -189,8 +190,6 @@ int acmp_process_quick(ACMPT *acmpt, const char **match, const char *data, size_ */ int acmp_prepare(ACMP *parser); -char *parse_pm_content(const char *op_parm, unsigned short int op_len, const char **error_msg); - } #endif /*ACMP_H_*/ diff --git a/src/utils/base64.cc b/src/utils/base64.cc index ebbb7393..7b1f4b07 100644 --- a/src/utils/base64.cc +++ b/src/utils/base64.cc @@ -23,33 +23,30 @@ #include "mbedtls/base64.h" +template +inline std::string base64Helper(const char *data, const unsigned int len, Operation op) { + size_t out_len = 0; + + op(nullptr, 0, &out_len, + reinterpret_cast(data), len); + + std::string ret(out_len, {}); + if(out_len > 0) { + op(reinterpret_cast(ret.data()), ret.size(), &out_len, + reinterpret_cast(data), len); + + ret.resize(out_len); + } + + return ret; +} + namespace modsecurity { namespace Utils { std::string Base64::encode(const std::string& data) { - size_t encoded_len = 0; - unsigned char *d; - std::string ret; - - mbedtls_base64_encode(NULL, 0, &encoded_len, - reinterpret_cast(data.c_str()), data.size()); - - d = reinterpret_cast(malloc(sizeof(char) * encoded_len)); - if (d == NULL) { - return data; - } - - memset(d, '\0', encoded_len); - - mbedtls_base64_encode(d, encoded_len, &encoded_len, - (unsigned char*) data.c_str(), data.size()); - - ret.assign(reinterpret_cast(d), encoded_len); - free(d); - - - return ret; + return base64Helper(data.c_str(), data.size(), mbedtls_base64_encode); } @@ -63,53 +60,12 @@ std::string Base64::decode(const std::string& data, bool forgiven) { std::string Base64::decode(const std::string& data) { - size_t decoded_len = 0; - unsigned char *d; - std::string ret; - size_t len = strlen(data.c_str()); - - mbedtls_base64_decode(NULL, 0, &decoded_len, - reinterpret_cast(data.c_str()), len); - - d = reinterpret_cast(malloc(sizeof(char) * decoded_len)); - if (d == NULL) { - return data; - } - - memset(d, '\0', decoded_len); - - mbedtls_base64_decode(d, decoded_len, &decoded_len, - reinterpret_cast(data.c_str()), len); - - ret.assign(reinterpret_cast(d), decoded_len); - free(d); - - return ret; + return base64Helper(data.c_str(), strlen(data.c_str()), mbedtls_base64_decode); } std::string Base64::decode_forgiven(const std::string& data) { - size_t decoded_len = 0; - unsigned char *d; - std::string ret; - - decode_forgiven_engine(NULL, 0, &decoded_len, - reinterpret_cast(data.c_str()), data.size()); - - d = reinterpret_cast(malloc(sizeof(char) * decoded_len)); - if (d == NULL) { - return data; - } - - memset(d, '\0', decoded_len); - - decode_forgiven_engine(d, decoded_len, &decoded_len, - reinterpret_cast(data.c_str()), data.size()); - - ret.assign(reinterpret_cast(d), decoded_len); - free(d); - - return ret; + return base64Helper(data.c_str(), data.size(), decode_forgiven_engine); } @@ -215,6 +171,5 @@ void Base64::decode_forgiven_engine(unsigned char *plain_text, } } - } // namespace Utils } // namespace modsecurity diff --git a/src/utils/decode.cc b/src/utils/decode.cc index 8629f8fb..2735cf3e 100644 --- a/src/utils/decode.cc +++ b/src/utils/decode.cc @@ -17,68 +17,60 @@ #include "modsecurity/modsecurity.h" #include "src/utils/string.h" +using namespace modsecurity::utils::string; -namespace modsecurity { -namespace utils { +namespace modsecurity::utils { -int urldecode_nonstrict_inplace(unsigned char *input, - uint64_t input_len, int *invalid_count, int *changed) { - unsigned char *d = (unsigned char *)input; - uint64_t i, count; +bool urldecode_nonstrict_inplace(std::string &val, + int &invalid_count) { + unsigned char *d = (unsigned char *)val.data(); + unsigned char *s = d; + const unsigned char *e = s + val.size(); - *changed = 0; + invalid_count = 0; + bool changed = false; - if (input == NULL) { - return -1; - } - - i = count = 0; - while (i < input_len) { - if (input[i] == '%') { + while (s != e) { + if (*s == '%') { /* Character is a percent sign. */ /* Are there enough bytes available? */ - if (i + 2 < input_len) { - char c1 = input[i + 1]; - char c2 = input[i + 2]; + if (s + 2 < e) { + const auto c1 = *(s + 1); + const auto c2 = *(s + 2); if (VALID_HEX(c1) && VALID_HEX(c2)) { - uint64_t uni = string::x2c(&input[i + 1]); + const auto uni = string::x2c(s + 1); - *d++ = (wchar_t)uni; - count++; - i += 3; - *changed = 1; + *d++ = uni; + s += 3; + changed = true; } else { /* Not a valid encoding, skip this % */ - *d++ = input[i++]; - count++; - (*invalid_count)++; + *d++ = *s++; + invalid_count++; } } else { /* Not enough bytes available, copy the raw bytes. */ - *d++ = input[i++]; - count++; - (*invalid_count)++; + *d++ = *s++; + invalid_count++; } } else { /* Character is not a percent sign. */ - if (input[i] == '+') { + if (*s == '+') { *d++ = ' '; - *changed = 1; + changed = true; } else { - *d++ = input[i]; + *d++ = *s; } - count++; - i++; + s++; } } -#if 0 - *d = '\0'; -#endif + if (changed) + val.resize((char*) d - val.c_str()); - return count; + return changed; } @@ -120,5 +112,4 @@ std::string uri_decode(const std::string & sSrc) { } -} // namespace utils -} // namespace modsecurity +} // namespace modsecurity::utils diff --git a/src/utils/decode.h b/src/utils/decode.h index e0e31bcb..d80a55d5 100644 --- a/src/utils/decode.h +++ b/src/utils/decode.h @@ -29,8 +29,8 @@ namespace modsecurity { namespace utils { -int urldecode_nonstrict_inplace(unsigned char *input, - uint64_t input_len, int *invalid_count, int *changed); +bool urldecode_nonstrict_inplace(std::string &val, + int &invalid_count); std::string uri_decode(const std::string & sSrc); diff --git a/src/utils/md5.cc b/src/utils/md5.cc deleted file mode 100644 index 99b9d278..00000000 --- a/src/utils/md5.cc +++ /dev/null @@ -1,40 +0,0 @@ - - -#include "src/utils/md5.h" -#include "mbedtls/md5.h" - -namespace modsecurity { -namespace Utils { - - -std::string Md5::hexdigest(const std::string& input) { - unsigned char digest[16]; - - mbedtls_md5(reinterpret_cast(input.c_str()), - input.size(), digest); - - char buf[33]; - for (int i = 0; i < 16; i++) { - sprintf(buf+i*2, "%02x", digest[i]); - } - - return std::string(buf, 32); -} - - -std::string Md5::digest(const std::string& input) { - unsigned char output[16]; - std::string ret; - - mbedtls_md5(reinterpret_cast(input.c_str()), - input.size(), output); - - ret.assign(reinterpret_cast(output), 16); - - return ret; -} - - -} // namespace Utils -} // namespace modsecurity - diff --git a/src/utils/md5.h b/src/utils/md5.h index b6ebc120..68f5d748 100644 --- a/src/utils/md5.h +++ b/src/utils/md5.h @@ -13,29 +13,20 @@ * */ -#include - -#include "modsecurity/actions/action.h" -#include "src/actions/transformations/transformation.h" - #ifndef SRC_UTILS_MD5_H_ #define SRC_UTILS_MD5_H_ -#include -#include +#include "src/utils/sha1.h" +#include "mbedtls/md5.h" +#include -namespace modsecurity { -namespace Utils { +namespace modsecurity::Utils { -class Md5 { - public: - Md5() { } - static std::string hexdigest(const std::string& input); - static std::string digest(const std::string& input); +class Md5 : public DigestImpl<&mbedtls_md5, 16> { }; -} // namespace Utils -} // namespace modsecurity + +} // namespace modsecurity::Utils #endif // SRC_UTILS_MD5_H_ \ No newline at end of file diff --git a/src/utils/sha1.cc b/src/utils/sha1.cc deleted file mode 100644 index 4c28d4ed..00000000 --- a/src/utils/sha1.cc +++ /dev/null @@ -1,60 +0,0 @@ -/* - * ModSecurity, http://www.modsecurity.org/ - * Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/) - * - * You may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * If any of the files related to licensing are missing or if you have any - * other questions related to licensing please contact Trustwave Holdings, Inc. - * directly using the email address security@modsecurity.org. - * - */ - - -#include "src/utils/sha1.h" -#include "mbedtls/sha1.h" -#include -#include -#include - -namespace modsecurity { -namespace Utils { - - -std::string Sha1::hexdigest(const std::string& input) { - unsigned char digest[20] = { 0 }; - static const char* const lut = "0123456789abcdef"; - - mbedtls_sha1(reinterpret_cast(input.c_str()), - input.size(), digest); - std::string a; - - for (int i = 0; i < 20; i++) { - const unsigned char c = digest[i]; - a.push_back(lut[c >> 4]); - a.push_back(lut[c & 15]); - } - - return a; -} - - -std::string Sha1::digest(const std::string& input) { - unsigned char output[20]; - std::string ret; - - mbedtls_sha1(reinterpret_cast(input.c_str()), - input.size(), output); - - ret.assign(reinterpret_cast(output), 20); - - return ret; -} - - -} // namespace Utils -} // namespace modsecurity - diff --git a/src/utils/sha1.h b/src/utils/sha1.h index 6bae47c2..2dac3ea2 100644 --- a/src/utils/sha1.h +++ b/src/utils/sha1.h @@ -13,26 +13,63 @@ * */ - #ifndef SRC_UTILS_SHA1_H_ #define SRC_UTILS_SHA1_H_ -#include -#include #include +#include -namespace modsecurity { -namespace Utils { +#include "src/utils/string.h" +#include "mbedtls/sha1.h" -class Sha1 { +namespace modsecurity::Utils { + + +using DigestOp = int (*)(const unsigned char *, size_t, unsigned char []); + + +template +class DigestImpl { public: - Sha1() { } - static std::string hexdigest(const std::string& input); - static std::string digest(const std::string& input); + static std::string digest(const std::string& input) { + return digestHelper(input, [](const auto digest) { + return std::string(digest); + }); + } + + static void digestReplace(std::string& value) { + digestHelper(value, [&value](const auto digest) mutable { + value = digest; + }); + } + + static std::string hexdigest(const std::string &input) { + return digestHelper(input, [](const auto digest) { + return utils::string::string_to_hex(digest); + }); + } + +private: + + template + static auto digestHelper(const std::string &input, + ConvertOp convertOp) -> auto { + char digest[DigestSize]; + + auto ret = digestOp(reinterpret_cast(input.c_str()), + input.size(), reinterpret_cast(digest)); + assert(ret == 0); + + return convertOp(std::string_view(digest, DigestSize)); + } }; -} // namespace Utils -} // namespace modsecurity + +class Sha1 : public DigestImpl<&mbedtls_sha1, 20> { +}; + + +} // namespace modsecurity::Utils #endif // SRC_UTILS_SHA1_H_ diff --git a/src/utils/shared_files.cc b/src/utils/shared_files.cc index df18022f..6982d0d6 100644 --- a/src/utils/shared_files.cc +++ b/src/utils/shared_files.cc @@ -17,8 +17,7 @@ #include #ifdef WIN32 -#include -#include +#include #endif @@ -34,7 +33,32 @@ SharedFiles::handlers_map::iterator SharedFiles::add_new_handler( return m_handlers.end(); } - return m_handlers.insert({ fileName, {fp, 0} }).first; +#ifdef WIN32 + // replace invalid characters for a Win32 named object + auto tmp = fileName; + std::replace(tmp.begin(), tmp.end(), '\\', '_'); + std::replace(tmp.begin(), tmp.end(), '/', '_'); + + // use named mutex for multi-process locking support + const auto mutexName = "Global\\ModSecurity_" + tmp; + + HANDLE hMutex = CreateMutex(NULL, FALSE, mutexName.c_str()); + if (hMutex == NULL) { + error->assign("Failed to create mutex for shared file: " + fileName); + fclose(fp); + return m_handlers.end(); + } +#endif + + auto handler = handler_info { + fp, +#ifdef WIN32 + hMutex, +#endif + 0 + }; + // cppcheck-suppress resourceLeak ; false positive, fp is closed in SharedFiles::close + return m_handlers.insert({ fileName, handler }).first; } @@ -69,6 +93,9 @@ void SharedFiles::close(const std::string& fileName) { if (it->second.cnt == 0) { fclose(it->second.fp); +#ifdef WIN32 + CloseHandle(it->second.hMutex); +#endif m_handlers.erase(it); } @@ -92,9 +119,11 @@ bool SharedFiles::write(const std::string& fileName, lock.l_type = F_WRLCK; fcntl(fileno(it->second.fp), F_SETLKW, &lock); #else - auto handle = reinterpret_cast(_get_osfhandle(fileno(it->second.fp))); - OVERLAPPED overlapped = { 0 }; - ::LockFileEx(handle, LOCKFILE_EXCLUSIVE_LOCK, 0, MAXDWORD, MAXDWORD, &overlapped); + DWORD dwWaitResult = WaitForSingleObject(it->second.hMutex, INFINITE); + if (dwWaitResult != WAIT_OBJECT_0) { + error->assign("couldn't lock shared file: " + fileName); + return false; + } #endif auto wrote = fwrite(msg.c_str(), 1, msg.size(), it->second.fp); @@ -109,8 +138,7 @@ bool SharedFiles::write(const std::string& fileName, lock.l_type = F_UNLCK; fcntl(fileno(it->second.fp), F_SETLKW, &lock); #else - overlapped = { 0 }; - ::UnlockFileEx(handle, 0, MAXDWORD, MAXDWORD, &overlapped); + ::ReleaseMutex(it->second.hMutex); #endif return ret; diff --git a/src/utils/shared_files.h b/src/utils/shared_files.h index 4953eeff..fcc78c98 100644 --- a/src/utils/shared_files.h +++ b/src/utils/shared_files.h @@ -18,6 +18,9 @@ #include +#ifdef WIN32 +#include +#endif #include #include @@ -53,6 +56,9 @@ private: struct handler_info { FILE* fp; +#ifdef WIN32 + HANDLE hMutex; +#endif unsigned int cnt; }; diff --git a/src/utils/string.cc b/src/utils/string.cc deleted file mode 100644 index 8d9e08ff..00000000 --- a/src/utils/string.cc +++ /dev/null @@ -1,268 +0,0 @@ -/* - * ModSecurity, http://www.modsecurity.org/ - * Copyright (c) 2015 - 2023 Trustwave Holdings, Inc. (http://www.trustwave.com/) - * - * You may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * If any of the files related to licensing are missing or if you have any - * other questions related to licensing please contact Trustwave Holdings, Inc. - * directly using the email address security@modsecurity.org. - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined _MSC_VER -#include -#elif defined __GNUC__ -#include -#include -#endif - -#include "modsecurity/modsecurity.h" - -#include "src/utils/string.h" - - -namespace modsecurity { -namespace utils { -namespace string { - - -std::string parserSanitizer(std::string a) { - a = removeWhiteSpacesIfNeeded(a); - a = removeBracketsIfNeeded(a); - return a; -} - - -std::string removeWhiteSpacesIfNeeded(std::string a) { - while (a.size() > 1 && a.at(0) == ' ') { - a.erase(0, 1); - } - while (a.size() > 1 && a.at(a.length()-1) == ' ') { - a.pop_back(); - } - return a; -} - - -std::string ascTime(time_t *t) { - std::string ts = std::ctime(t); - ts.pop_back(); - return ts; -} - - -std::string dash_if_empty(const std::string *str) { - if (str == NULL || str->empty()) { - return "-"; - } - - return *str; -} - - -std::string dash_if_empty(const char *str) { - if (str == NULL || strlen(str) == 0) { - return "-"; - } - - return std::string(str); -} - - -std::string limitTo(int amount, const std::string &str) { - std::string ret; - - if (str.length() > amount) { - ret.assign(str, 0, amount); - ret = ret + " (" + std::to_string(str.length() - amount) + " " \ - "characters omitted)"; - return ret; - } - - return str; -} - - -std::string removeBracketsIfNeeded(std::string a) { - if (a.length() > 1 && a.at(0) == '"' && a.at(a.length()-1) == '"') { - a.pop_back(); - a.erase(0, 1); - } - if (a.length() > 1 && a.at(0) == '\'' && a.at(a.length()-1) == '\'') { - a.pop_back(); - a.erase(0, 1); - } - return a; -} - - -std::string string_to_hex(const std::string& input) { - static const char* const lut = "0123456789ABCDEF"; - size_t len = input.length(); - - std::string output; - output.reserve(2 * len); - for (size_t i = 0; i < len; ++i) { - const unsigned char c = input[i]; - output.push_back(lut[c >> 4]); - output.push_back(lut[c & 15]); - } - return output; -} - -std::string toHexIfNeeded(const std::string &str, bool escape_spec) { - // escape_spec: escape special chars or not - // spec chars: '"' (quotation mark, ascii 34), '\' (backslash, ascii 92) - std::stringstream res; - - for (int i = 0; i < str.size(); i++) { - int c = (unsigned char)str.at(i); - if (c < 32 || c > 126 || (escape_spec == true && (c == 34 || c == 92))) { - res << "\\x" << std::setw(2) << std::setfill('0') << std::hex << c; - } else { - res << str.at(i); - } - } - - return res.str(); -} - - -std::string tolower(std::string str) { - std::string value; - value.resize(str.length()); - - std::transform(str.begin(), - str.end(), - value.begin(), - ::tolower); - - return value; -} - - -std::string toupper(std::string str) { - std::string value; - value.resize(str.length()); - - std::transform(str.begin(), - str.end(), - value.begin(), - ::toupper); - - return value; -} - - -std::vector ssplit(std::string str, char delimiter) { - std::vector internal; - std::stringstream ss(str); // Turn the string into a stream. - std::string tok; - - while (getline(ss, tok, delimiter)) { - internal.push_back(tok); - } - - return internal; -} - - -std::pair ssplit_pair(const std::string& str, char delimiter) { - std::stringstream ss(str); // Turn the string into a stream. - std::string key; - std::string value; - - getline(ss, key, delimiter); - if (key.length() < str.length()) { - value = str.substr(key.length()+1); - } - - return std::make_pair(key, value); -} - - -std::vector split(std::string str, char delimiter) { - std::vector internal = ssplit(str, delimiter); - - if (internal.size() == 0) { - internal.push_back(str); - } - - return internal; -} - - -void chomp(std::string *str) { - std::string::size_type pos = str->find_last_not_of("\n\r"); - if (pos != std::string::npos) { - str->erase(pos+1, str->length()-pos-1); - } -} - - -unsigned char x2c(const unsigned char *what) { - unsigned char digit; - - digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0')); - digit *= 16; - digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A') + 10 : (what[1] - '0')); - - return digit; -} - - -/** - * Converts a single hexadecimal digit into a decimal value. - */ -unsigned char xsingle2c(const unsigned char *what) { - unsigned char digit; - - digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0')); - - return digit; -} - - -unsigned char *c2x(unsigned what, unsigned char *where) { - static const char c2x_table[] = "0123456789abcdef"; - - what = what & 0xff; - *where++ = c2x_table[what >> 4]; - *where++ = c2x_table[what & 0x0f]; - - return where; -} - - -void replaceAll(std::string *str, const std::string& from, - const std::string& to) { - size_t start_pos = 0; - while ((start_pos = str->find(from, start_pos)) != std::string::npos) { - str->replace(start_pos, from.length(), to); - start_pos += to.length(); - } -} - -} // namespace string -} // namespace utils -} // namespace modsecurity diff --git a/src/utils/string.h b/src/utils/string.h index 55ebc0bd..f5e52ff0 100644 --- a/src/utils/string.h +++ b/src/utils/string.h @@ -13,23 +13,38 @@ * */ -#include -#include -#include -#include - #ifndef SRC_UTILS_STRING_H_ #define SRC_UTILS_STRING_H_ -#define VALID_HEX(X) (((X >= '0') && (X <= '9')) || \ - ((X >= 'a') && (X <= 'f')) || ((X >= 'A') && (X <= 'F'))) -#define ISODIGIT(X) ((X >= '0') && (X <= '7')) -#define NBSP 160 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef WIN32 +#include "src/compat/msvc.h" +#endif -namespace modsecurity { -namespace utils { -namespace string { +namespace modsecurity::utils::string { + +template +constexpr bool VALID_HEX(CharT X) { + return ((X >= '0') && (X <= '9')) + || ((X >= 'a') && (X <= 'f')) + || ((X >= 'A') && (X <= 'F')); +} + +template +constexpr bool ISODIGIT(CharT X) { + return (X >= '0') && (X <= '7'); +} + +constexpr unsigned char NBSP = 160; const char HEX2DEC[256] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ @@ -55,30 +70,213 @@ const char HEX2DEC[256] = { }; -std::string ascTime(time_t *t); -std::string dash_if_empty(const char *str); -std::string dash_if_empty(const std::string *str); -std::string limitTo(int amount, const std::string &str); -std::string removeBracketsIfNeeded(std::string a); -std::string string_to_hex(const std::string& input); -std::string toHexIfNeeded(const std::string &str, bool escape_spec = false); -std::string tolower(std::string str); -std::string toupper(std::string str); -std::vector ssplit(std::string str, char delimiter); -std::pair ssplit_pair(const std::string& str, char delimiter); -std::vector split(std::string str, char delimiter); -void chomp(std::string *str); -void replaceAll(std::string *str, const std::string& from, - const std::string& to); -std::string removeWhiteSpacesIfNeeded(std::string a); -std::string parserSanitizer(std::string a); +inline std::string ascTime(const time_t *t) { + struct tm timeinfo; + localtime_r(t, &timeinfo); + char tstr[std::size("Www Mmm dd hh:mm:ss yyyy")]; + strftime(tstr, std::size(tstr), "%c", &timeinfo); + return tstr; +} -unsigned char x2c(const unsigned char *what); -unsigned char xsingle2c(const unsigned char *what); -unsigned char *c2x(unsigned what, unsigned char *where); -} // namespace string -} // namespace utils -} // namespace modsecurity +inline std::string dash_if_empty(const std::string *str) { + if (str == nullptr || str->empty()) { + return "-"; + } + + return *str; +} + + +inline std::string limitTo(int amount, const std::string &str) { + std::string ret; + + if (str.length() > amount) { + ret.assign(str, 0, amount); + ret = ret + " (" + std::to_string(str.length() - amount) + " " \ + "characters omitted)"; + return ret; + } + + return str; +} + + +inline std::string toHexIfNeeded(const std::string &str, bool escape_spec = false) { + // escape_spec: escape special chars or not + // spec chars: '"' (quotation mark, ascii 34), '\' (backslash, ascii 92) + std::stringstream res; + + for (int i = 0; i < str.size(); i++) { + int c = (unsigned char)str.at(i); + if (c < 32 || c > 126 || (escape_spec == true && (c == 34 || c == 92))) { + res << "\\x" << std::setw(2) << std::setfill('0') << std::hex << c; + } else { + res << str.at(i); + } + } + + return res.str(); +} + + +inline std::vector ssplit(const std::string &str, char delimiter) { + std::vector internal; + std::stringstream ss(str); // Turn the string into a stream. + std::string tok; + + while (getline(ss, tok, delimiter)) { + internal.push_back(tok); + } + + return internal; +} + + +inline std::pair ssplit_pair(const std::string& str, char delimiter) { + std::stringstream ss(str); // Turn the string into a stream. + std::string key; + std::string value; + + getline(ss, key, delimiter); + if (key.length() < str.length()) { + value = str.substr(key.length()+1); + } + + return std::make_pair(key, value); +} + + +inline std::vector split(const std::string &str, char delimiter) { + std::vector internal = ssplit(str, delimiter); + + if (internal.empty()) { + internal.push_back(str); + } + + return internal; +} + + +inline void chomp(std::string &str) { + std::string::size_type pos = str.find_last_not_of("\n\r"); + if (pos != std::string::npos) { + str.erase(pos+1, str.length()-pos-1); + } +} + + +inline void replaceAll(std::string &str, std::string_view from, + std::string_view to) { + size_t start_pos = 0; + while ((start_pos = str.find(from, start_pos)) != std::string::npos) { + str.replace(start_pos, from.length(), to); + start_pos += to.length(); + } +} + + +inline std::string removeWhiteSpacesIfNeeded(std::string a) { + while (a.size() > 1 && a.at(0) == ' ') { + a.erase(0, 1); + } + while (a.size() > 1 && a.at(a.length()-1) == ' ') { + a.pop_back(); + } + return a; +} + + +inline std::string removeBracketsIfNeeded(std::string a) { + if (a.length() > 1 && a.at(0) == '"' && a.at(a.length()-1) == '"') { + a.pop_back(); + a.erase(0, 1); + } + if (a.length() > 1 && a.at(0) == '\'' && a.at(a.length()-1) == '\'') { + a.pop_back(); + a.erase(0, 1); + } + return a; +} + + +inline std::string parserSanitizer(std::string a) { + a = removeWhiteSpacesIfNeeded(a); + a = removeBracketsIfNeeded(a); + return a; +} + + +/** + * Converts a single hexadecimal digit into a decimal value. + */ +inline unsigned char xsingle2c(const unsigned char *what) { + unsigned char digit; + + digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0')); + + return digit; +} + + +inline unsigned char x2c(const unsigned char *what) { + unsigned char digit; + + digit = xsingle2c(what); + digit *= 16; + digit += xsingle2c(what+1); + + return digit; +} + + +inline unsigned char *c2x(unsigned what, unsigned char *where) { + static const char c2x_table[] = "0123456789abcdef"; + + what = what & 0xff; + *where++ = c2x_table[what >> 4]; + *where++ = c2x_table[what & 0x0f]; + + return where; +} + + +inline std::string string_to_hex(std::string_view input) { + static const char* const lut = "0123456789abcdef"; + + std::string a(input.size()*2, 0); + char *d = a.data(); + + for (const unsigned char c : input) { + *d++ = lut[c >> 4]; + *d++ = lut[c & 15]; + } + + return a; +} + + +template +inline std::string toCaseHelper(std::string str, Operation op) { + std::transform(str.begin(), + str.end(), + str.begin(), + op); + + return str; +} + + +inline std::string tolower(std::string str) { // cppcheck-suppress passedByValue ; copied value is used for in-place transformation + return toCaseHelper(str, ::tolower); +} + + +inline std::string toupper(std::string str) { // cppcheck-suppress passedByValue ; copied value is used for in-place transformation + return toCaseHelper(str, ::toupper); +} + + +} // namespace modsecurity::utils::string #endif // SRC_UTILS_STRING_H_ diff --git a/src/variables/remote_user.cc b/src/variables/remote_user.cc index 23bc6487..550294c7 100644 --- a/src/variables/remote_user.cc +++ b/src/variables/remote_user.cc @@ -56,8 +56,7 @@ void RemoteUser::evaluate(Transaction *transaction, base64 = Utils::Base64::decode(base64); - const auto pos = base64.find(":"); - if (pos != std::string::npos) { + if (const auto pos{base64.find(":")}; pos != std::string::npos) { transaction->m_variableRemoteUser.assign(std::string(base64, 0, pos)); auto var = std::make_unique(&v->getKeyWithCollection(), diff --git a/src/variables/rule.h b/src/variables/rule.h index 3d3cbcc0..eed98c8a 100644 --- a/src/variables/rule.h +++ b/src/variables/rule.h @@ -35,7 +35,7 @@ namespace variables { class Rule_DictElement : public VariableDictElement { \ public: explicit Rule_DictElement(const std::string &dictElement) - : VariableDictElement(std::string("RULE"), dictElement) { } + : VariableDictElement(m_rule, dictElement) { } static void id(Transaction *t, RuleWithActions *rule, @@ -49,13 +49,8 @@ class Rule_DictElement : public VariableDictElement { \ if (!r || r->m_ruleId == 0) { return; } - std::string *a = new std::string(std::to_string(r->m_ruleId)); - VariableValue *var = new VariableValue(&m_rule, &m_rule_id, - a - ); - delete a; - var->addOrigin(); - l->push_back(var); + + addVariableOrigin(m_rule_id, std::to_string(r->m_ruleId), l); } @@ -72,13 +67,7 @@ class Rule_DictElement : public VariableDictElement { \ return; } - std::string *a = new std::string(r->m_rev); - VariableValue *var = new VariableValue(&m_rule, &m_rule_rev, - a - ); - delete a; - var->addOrigin(); - l->push_back(var); + addVariableOrigin(m_rule_rev, r->m_rev, l); } @@ -92,13 +81,7 @@ class Rule_DictElement : public VariableDictElement { \ } if (r && r->hasSeverity()) { - std::string *a = new std::string(std::to_string(r->severity())); - VariableValue *var = new VariableValue(&m_rule, &m_rule_severity, - a - ); - delete a; - var->addOrigin(); - l->push_back(var); + addVariableOrigin(m_rule_severity, std::to_string(r->severity()), l); } } @@ -113,13 +96,7 @@ class Rule_DictElement : public VariableDictElement { \ } if (r && r->hasLogData()) { - std::string *a = new std::string(r->logData(t)); - VariableValue *var = new VariableValue(&m_rule, &m_rule_logdata, - a - ); - delete a; - var->addOrigin(); - l->push_back(var); + addVariableOrigin(m_rule_logdata, r->logData(t), l); } } @@ -133,36 +110,30 @@ class Rule_DictElement : public VariableDictElement { \ } if (r && r->hasMsg()) { - std::string *a = new std::string(r->msg(t)); - VariableValue *var = new VariableValue(&m_rule, &m_rule_msg, - a - ); - delete a; - var->addOrigin(); - l->push_back(var); + addVariableOrigin(m_rule_msg, r->msg(t), l); } } void evaluate(Transaction *t, RuleWithActions *rule, std::vector *l) override { - if (m_dictElement == "id") { + if (m_dictElement == m_rule_id) { id(t, rule, l); return; } - if (rule && m_dictElement == "rev") { + if (rule && m_dictElement == m_rule_rev) { rev(t, rule, l); return; } - if (rule && m_dictElement == "severity") { + if (rule && m_dictElement == m_rule_severity) { severity(t, rule, l); return; } - if (m_dictElement == "logdata") { + if (m_dictElement == m_rule_logdata) { logData(t, rule, l); return; } - if (m_dictElement == "msg") { + if (m_dictElement == m_rule_msg) { msg(t, rule, l); return; } @@ -174,6 +145,18 @@ class Rule_DictElement : public VariableDictElement { \ static const std::string m_rule_severity; static const std::string m_rule_logdata; static const std::string m_rule_msg; + +private: + + static inline void addVariableOrigin(const std::string &key, + const std::string &value, + std::vector *l) { + auto var = new VariableValue(&m_rule, &key, + &value + ); + var->addOrigin(); + l->push_back(var); + } }; diff --git a/src/variables/time.cc b/src/variables/time.cc index 7d481ee6..c674f4e0 100644 --- a/src/variables/time.cc +++ b/src/variables/time.cc @@ -40,15 +40,13 @@ namespace variables { void Time::evaluate(Transaction *transaction, RuleWithActions *rule, std::vector *l) { - - char tstr[200]; - struct tm timeinfo; time_t timer; - time(&timer); - memset(tstr, '\0', 200); + struct tm timeinfo; localtime_r(&timer, &timeinfo); + + char tstr[std::size("hh:mm:ss")]; strftime(tstr, 200, "%H:%M:%S", &timeinfo); transaction->m_variableTime.assign(tstr); diff --git a/src/variables/time_day.cc b/src/variables/time_day.cc index f094d4c9..eefe937f 100644 --- a/src/variables/time_day.cc +++ b/src/variables/time_day.cc @@ -40,15 +40,14 @@ namespace variables { void TimeDay::evaluate(Transaction *transaction, RuleWithActions *rule, std::vector *l) { - char tstr[200]; - struct tm timeinfo; time_t timer; - time(&timer); - memset(tstr, '\0', 200); + struct tm timeinfo; localtime_r(&timer, &timeinfo); - strftime(tstr, 200, "%d", &timeinfo); + + char tstr[std::size("dd")]; + strftime(tstr, std::size(tstr), "%d", &timeinfo); transaction->m_variableTimeDay.assign(tstr); diff --git a/src/variables/time_hour.cc b/src/variables/time_hour.cc index ab809ead..1a9c1bf7 100644 --- a/src/variables/time_hour.cc +++ b/src/variables/time_hour.cc @@ -40,15 +40,14 @@ namespace variables { void TimeHour::evaluate(Transaction *transaction, RuleWithActions *rule, std::vector *l) { - char tstr[200]; - struct tm timeinfo; time_t timer; - time(&timer); - memset(tstr, '\0', 200); + struct tm timeinfo; localtime_r(&timer, &timeinfo); - strftime(tstr, 200, "%H", &timeinfo); + + char tstr[std::size("hh")]; + strftime(tstr, std::size(tstr), "%H", &timeinfo); transaction->m_variableTimeHour.assign(tstr); diff --git a/src/variables/time_min.cc b/src/variables/time_min.cc index 9d03be4d..134582de 100644 --- a/src/variables/time_min.cc +++ b/src/variables/time_min.cc @@ -40,15 +40,14 @@ namespace variables { void TimeMin::evaluate(Transaction *transaction, RuleWithActions *rule, std::vector *l) { - char tstr[200]; - struct tm timeinfo; time_t timer; - time(&timer); - memset(tstr, '\0', 200); + struct tm timeinfo; localtime_r(&timer, &timeinfo); - strftime(tstr, 200, "%M", &timeinfo); + + char tstr[std::size("mm")]; + strftime(tstr, std::size(tstr), "%M", &timeinfo); transaction->m_variableTimeMin.assign(tstr); diff --git a/src/variables/time_mon.cc b/src/variables/time_mon.cc index 17e74f31..18059112 100644 --- a/src/variables/time_mon.cc +++ b/src/variables/time_mon.cc @@ -40,19 +40,13 @@ namespace variables { void TimeMon::evaluate(Transaction *transaction, RuleWithActions *rule, std::vector *l) { - char tstr[200]; - struct tm timeinfo; time_t timer; - time(&timer); - memset(tstr, '\0', 200); + struct tm timeinfo; localtime_r(&timer, &timeinfo); - strftime(tstr, 200, "%m", &timeinfo); - int a = atoi(tstr); - a--; - transaction->m_variableTimeMin.assign(std::to_string(a)); + transaction->m_variableTimeMin.assign(std::to_string(timeinfo.tm_mon)); l->push_back(new VariableValue(&m_retName, &transaction->m_variableTimeMin)); diff --git a/src/variables/time_sec.cc b/src/variables/time_sec.cc index 5e39af7f..a9604771 100644 --- a/src/variables/time_sec.cc +++ b/src/variables/time_sec.cc @@ -40,15 +40,14 @@ namespace variables { void TimeSec::evaluate(Transaction *transaction, RuleWithActions *rule, std::vector *l) { - char tstr[200]; - struct tm timeinfo; time_t timer; - time(&timer); - memset(tstr, '\0', 200); + struct tm timeinfo; localtime_r(&timer, &timeinfo); - strftime(tstr, 200, "%S", &timeinfo); + + char tstr[std::size("ss")]; + strftime(tstr, std::size(tstr), "%S", &timeinfo); transaction->m_variableTimeSec.assign(tstr); diff --git a/src/variables/time_wday.cc b/src/variables/time_wday.cc index fd6a0278..e1840f58 100644 --- a/src/variables/time_wday.cc +++ b/src/variables/time_wday.cc @@ -40,15 +40,14 @@ namespace variables { void TimeWDay::evaluate(Transaction *transaction, RuleWithActions *rule, std::vector *l) { - char tstr[200]; - struct tm timeinfo; time_t timer; - time(&timer); - memset(tstr, '\0', 200); + struct tm timeinfo; localtime_r(&timer, &timeinfo); - strftime(tstr, 200, "%u", &timeinfo); + + char tstr[std::size("d")]; + strftime(tstr, std::size(tstr), "%u", &timeinfo); transaction->m_variableTimeWDay.assign(tstr); diff --git a/src/variables/time_year.cc b/src/variables/time_year.cc index f68e8cd6..a8f1a502 100644 --- a/src/variables/time_year.cc +++ b/src/variables/time_year.cc @@ -40,15 +40,14 @@ namespace variables { void TimeYear::evaluate(Transaction *transaction, RuleWithActions *rule, std::vector *l) { - char tstr[200]; - struct tm timeinfo; time_t timer; - time(&timer); - memset(tstr, '\0', 200); + struct tm timeinfo; localtime_r(&timer, &timeinfo); - strftime(tstr, 200, "%Y", &timeinfo); + + char tstr[std::size("yyyy")]; + strftime(tstr, std::size(tstr), "%Y", &timeinfo); transaction->m_variableTimeYear.assign(tstr); diff --git a/src/variables/variable.h b/src/variables/variable.h index e854aca7..fc4671bb 100644 --- a/src/variables/variable.h +++ b/src/variables/variable.h @@ -707,9 +707,8 @@ class VariableModificatorCount : public Variable { } reslIn.clear(); - std::string *res = new std::string(std::to_string(count)); - val = new VariableValue(m_fullName.get(), res); - delete res; + auto res = std::to_string(count); + val = new VariableValue(m_fullName.get(), &res); l->push_back(val); return; diff --git a/src/variables/xml.cc b/src/variables/xml.cc index 9b3d8ff9..03dbc967 100644 --- a/src/variables/xml.cc +++ b/src/variables/xml.cc @@ -124,13 +124,12 @@ void XML::evaluate(Transaction *t, content = reinterpret_cast( xmlNodeGetContent(nodes->nodeTab[i])); if (content != NULL) { - std::string *a = new std::string(content); + auto a = std::string(content); VariableValue *var = new VariableValue(m_fullName.get(), - a); + &a); if (!m_keyExclusion.toOmit(*m_fullName)) { l->push_back(var); } - delete a; xmlFree(content); } } diff --git a/test/Makefile.am b/test/Makefile.am index 753e3a38..4d4396ae 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -70,7 +70,6 @@ unit_tests_LDFLAGS = \ unit_tests_CPPFLAGS = \ - -std=c++17 \ -Icommon \ -I../ \ -g \ @@ -126,7 +125,6 @@ regression_tests_LDFLAGS = \ regression_tests_CPPFLAGS = \ - -std=c++17 \ -Icommon \ -I../ \ -g \ @@ -179,7 +177,6 @@ rules_optimization_LDFLAGS = \ $(YAJL_LDFLAGS) rules_optimization_CPPFLAGS = \ - -std=c++17 \ -Icommon \ -I../ \ -g \ diff --git a/test/benchmark/Makefile.am b/test/benchmark/Makefile.am index 865818ca..88da53e8 100644 --- a/test/benchmark/Makefile.am +++ b/test/benchmark/Makefile.am @@ -32,7 +32,6 @@ benchmark_LDFLAGS = \ $(LUA_LDFLAGS) benchmark_CPPFLAGS = \ - -std=c++17 \ -I$(top_builddir)/headers \ $(GLOBAL_CPPFLAGS) \ $(PCRE_CFLAGS) \ diff --git a/test/benchmark/benchmark.cc b/test/benchmark/benchmark.cc index a1037a47..8b36d368 100644 --- a/test/benchmark/benchmark.cc +++ b/test/benchmark/benchmark.cc @@ -73,7 +73,7 @@ int main(int argc, char *argv[]) { modsecurity::ModSecurity *modsec; modsecurity::RulesSet *rules; modsecurity::ModSecurityIntervention it; - modsecurity::intervention::reset(&it); + modsecurity::intervention::clean(&it); modsec = new modsecurity::ModSecurity(); modsec->setConnectorInformation("ModSecurity-benchmark v0.0.1-alpha" \ " (ModSecurity benchmark utility)"); @@ -167,6 +167,8 @@ int main(int argc, char *argv[]) { next_request: modsecTransaction->processLogging(); delete modsecTransaction; + modsecurity::intervention::free(&it); + modsecurity::intervention::clean(&it); } delete rules; diff --git a/test/coding_style_suppressions.txt b/test/coding_style_suppressions.txt index c2b1ea52..bba5a62c 100644 --- a/test/coding_style_suppressions.txt +++ b/test/coding_style_suppressions.txt @@ -13,7 +13,6 @@ ./src/utils/acmp.cc ./src/utils/acmp.h ./src/utils/mbedtls/ -./src/utils/md5.cc ./src/utils/md5.h ./src/utils/msc_tree.cc ./src/utils/msc_tree.h diff --git a/test/common/modsecurity_test.cc b/test/common/modsecurity_test.cc index 22757191..0f769054 100644 --- a/test/common/modsecurity_test.cc +++ b/test/common/modsecurity_test.cc @@ -93,13 +93,13 @@ bool ModSecurityTest::load_test_json(const std::string &file) { template -std::pair>* +void ModSecurityTest::load_tests(const std::string &path) { DIR *dir; struct dirent *ent; struct stat buffer; - if ((dir = opendir(path.c_str())) == NULL) { + if ((dir = opendir(path.c_str())) == nullptr) { /* if target is a file, use it as a single test. */ if (stat(path.c_str(), &buffer) == 0) { if (load_test_json(path) == false) { @@ -107,10 +107,10 @@ ModSecurityTest::load_tests(const std::string &path) { std::cout << std::endl; } } - return NULL; + return; } - while ((ent = readdir(dir)) != NULL) { + while ((ent = readdir(dir)) != nullptr) { std::string filename = ent->d_name; std::string json = ".json"; if (filename.size() < json.size() @@ -123,16 +123,15 @@ ModSecurityTest::load_tests(const std::string &path) { } } closedir(dir); - - return NULL; } template -std::pair>* ModSecurityTest::load_tests() { - return load_tests(this->target); +void ModSecurityTest::load_tests() { + load_tests(this->target); } + template void ModSecurityTest::cmd_options(int argc, char **argv) { int i = 1; @@ -144,6 +143,10 @@ void ModSecurityTest::cmd_options(int argc, char **argv) { i++; m_count_all = true; } + if (argc > i && strcmp(argv[i], "mtstress") == 0) { + i++; + m_test_multithreaded = true; + } if (std::getenv("AUTOMAKE_TESTS")) { m_automake_output = true; } diff --git a/test/common/modsecurity_test.h b/test/common/modsecurity_test.h index 79a168f7..8b55a16c 100644 --- a/test/common/modsecurity_test.h +++ b/test/common/modsecurity_test.h @@ -34,12 +34,13 @@ template class ModSecurityTest : ModSecurityTest() : m_test_number(0), m_automake_output(false), - m_count_all(false) { } + m_count_all(false), + m_test_multithreaded(false) { } std::string header(); void cmd_options(int, char **); - std::pair>* load_tests(); - std::pair>* load_tests(const std::string &path); + void load_tests(); + void load_tests(const std::string &path); bool load_test_json(const std::string &file); std::string target; @@ -48,6 +49,7 @@ template class ModSecurityTest : int m_test_number; bool m_automake_output; bool m_count_all; + bool m_test_multithreaded; }; } // namespace modsecurity_test diff --git a/test/fuzzer/Makefile.am b/test/fuzzer/Makefile.am index dc1b1e50..ea210240 100644 --- a/test/fuzzer/Makefile.am +++ b/test/fuzzer/Makefile.am @@ -30,7 +30,6 @@ afl_fuzzer_LDADD = \ afl_fuzzer_CPPFLAGS = \ - -std=c++17 \ -Icommon \ -I../ \ -I../../ \ diff --git a/test/optimization/optimization.cc b/test/optimization/optimization.cc index f4014058..19298b0b 100644 --- a/test/optimization/optimization.cc +++ b/test/optimization/optimization.cc @@ -87,7 +87,7 @@ int main(int argc, char **argv) { continue; } - if (dynamic_cast(z.get()) != nullptr) { + if (dynamic_cast(z.get())) { std::string op = "Unconditional"; if (operators.count(op) > 0) { operators[op] = 1 + operators[op]; @@ -96,9 +96,7 @@ int main(int argc, char **argv) { } } - if (dynamic_cast(z.get()) != nullptr) { - auto *rwo = dynamic_cast(z.get()); - + if (auto rwo = dynamic_cast(z.get())) { std::string op = rwo->getOperatorName(); if (operators.count(op) > 0) { operators[op] = 1 + operators[op]; diff --git a/test/regression/regression.cc b/test/regression/regression.cc index 962aff0e..a6ede61c 100644 --- a/test/regression/regression.cc +++ b/test/regression/regression.cc @@ -480,9 +480,14 @@ int main(int argc, char **argv) { ModSecurityTest test; std::string ver(MODSECURITY_VERSION); - std::string envvar("MODSECURITY=ModSecurity " + ver + " regression tests"); + std::string envvar("ModSecurity " + ver + " regression tests"); + +#ifndef WIN32 + setenv("MODSECURITY", envvar.c_str(), 1); +#else + _putenv_s("MODSECURITY", envvar.c_str()); +#endif - putenv(strdup(envvar.c_str())); #ifndef NO_LOGS int test_number = 0; #endif diff --git a/test/test-cases/regression/config-secremoterules.json b/test/test-cases/regression/config-secremoterules.json index 017245c1..1ba3fd4b 100644 --- a/test/test-cases/regression/config-secremoterules.json +++ b/test/test-cases/regression/config-secremoterules.json @@ -46,7 +46,7 @@ "version_min":300000, "title":"Include remote rules - failed download (Abort)", "expected":{ - "parser_error": "Failed to download: HTTP response code said error" + "parser_error": "Failed to download" }, "rules":[ "SecRuleEngine On", diff --git a/test/test-cases/regression/fn-setHostname.json b/test/test-cases/regression/fn-setHostname.json index 33d90695..59c5b52e 100644 --- a/test/test-cases/regression/fn-setHostname.json +++ b/test/test-cases/regression/fn-setHostname.json @@ -29,7 +29,7 @@ ] }, "expected":{ - "http_code": 200, + "http_code": 403, "debug_log": "[hostname: \"modsecurity.org\"]" }, "rules":[ diff --git a/test/test-cases/regression/operator-pm.json b/test/test-cases/regression/operator-pm.json index 4f94d6ea..2261ebe9 100644 --- a/test/test-cases/regression/operator-pm.json +++ b/test/test-cases/regression/operator-pm.json @@ -3,7 +3,7 @@ "enabled": 1, "version_min": 300000, "version_max": 0, - "title": "pm operator test 1/4", + "title": "pm operator test 1/6", "client": { "ip": "200.249.12.31", "port": 2313 @@ -77,7 +77,7 @@ "enabled": 1, "version_min": 300000, "version_max": 0, - "title": "pm operater test 3/4", + "title": "pm operater test 3/6", "client": { "ip": "200.249.12.31", "port": 2313 @@ -114,7 +114,7 @@ "enabled": 1, "version_min": 300000, "version_max": 0, - "title": "pm operater test 4/4", + "title": "pm operater test 4/6", "client": { "ip": "200.249.12.31", "port": 2313 @@ -146,5 +146,79 @@ "SecRuleEngine On", "SecRule ARGS \"@pm a ` b\" \"phase:1,id:999,deny,status:500\"" ] + }, + { + "enabled": 1, + "version_min": 300000, + "version_max": 0, + "title": "pm operater test 5/6", + "client": { + "ip": "200.249.12.31", + "port": 2313 + }, + "server": { + "ip": "200.249.12.31", + "port": 80 + }, + "request": { + "headers": { + "Host": "net.tutsplus.com" + }, + "uri": "\/test.pl?param1=123", + "method": "GET", + "http_version": 1.1, + "body": "" + }, + "response": { + "headers": { + "Content-Type": "text\/xml; charset=utf-8\n\r", + "Content-Length": "length\n\r" + } + }, + "expected": { + "debug_log": "Rule returned 1", + "http_code": 403 + }, + "rules": [ + "SecRuleEngine On", + "SecRule ARGS \"@pm 1 2 3\" \"phase:1,id:999,deny\"" + ] + }, + { + "enabled": 1, + "version_min": 300000, + "version_max": 0, + "title": "pm operater test 6/6", + "client": { + "ip": "200.249.12.31", + "port": 2313 + }, + "server": { + "ip": "200.249.12.31", + "port": 80 + }, + "request": { + "headers": { + "Host": "net.tutsplus.com" + }, + "uri": "\/test.pl?param1=abc", + "method": "GET", + "http_version": 1.1, + "body": "" + }, + "response": { + "headers": { + "Content-Type": "text\/xml; charset=utf-8\n\r", + "Content-Length": "length\n\r" + } + }, + "expected": { + "debug_log": "Rule returned 0", + "http_code": 200 + }, + "rules": [ + "SecRuleEngine On", + "SecRule ARGS \"@pm 1 2 3\" \"phase:1,id:999,deny\"" + ] } ] diff --git a/test/test-cases/regression/request-body-parser-multipart.json b/test/test-cases/regression/request-body-parser-multipart.json index c9220573..4e25168e 100644 --- a/test/test-cases/regression/request-body-parser-multipart.json +++ b/test/test-cases/regression/request-body-parser-multipart.json @@ -3294,5 +3294,56 @@ "SecRequestBodyAccess On", "SecRule ARGS:namea \"@streq 111\" \"phase:2,deny,id:500096\"" ] + }, + { + "enabled":1, + "version_min":300000, + "title":"multipart parser (invalid part header - contains invalid character)", + "client":{ + "ip":"200.249.12.31", + "port":123 + }, + "server":{ + "ip":"200.249.12.31", + "port":80 + }, + "request":{ + "headers":{ + "Host":"localhost", + "User-Agent":"curl/7.38.0", + "Accept":"*/*", + "Content-Length":"330", + "Content-Type":"multipart/form-data; boundary=a", + "Expect":"100-continue" + }, + "uri":"/", + "method":"POST", + "body":[ + "--a\r", + "\u000eContent-Disposition\u000e: form-data; name=\"file\"; filename=\"1.jsp\"\r", + "Content-Disposition: form-data; name=\"post\";\r", + "\r", + "<%out.print(123)%>\r", + "--a--\r" + ] + }, + "response":{ + "headers":{ + "Date":"Mon, 13 Jul 2015 20:02:41 GMT", + "Last-Modified":"Sun, 26 Oct 2014 22:33:37 GMT", + "Content-Type":"text/html" + }, + "body":[ + "no need." + ] + }, + "expected":{ + "http_code":403, + "debug_log":"Multipart: Invalid part header \\(contains invalid character\\)" + }, + "rules":[ + "SecruleEngine On", + "SecRule REQBODY_PROCESSOR_ERROR \"@eq 1\" \"phase:2,deny,status:403,id:500077\"" + ] } ] diff --git a/test/test-suite.in b/test/test-suite.in index eee696ec..0feb361b 100644 --- a/test/test-suite.in +++ b/test/test-suite.in @@ -49,6 +49,7 @@ TESTS+=test/test-cases/regression/config-update-target-by-tag.json TESTS+=test/test-cases/regression/config-xml_external_entity.json TESTS+=test/test-cases/regression/debug_log.json TESTS+=test/test-cases/regression/directive-sec_rule_script.json +TESTS+=test/test-cases/regression/fn-setHostname.json TESTS+=test/test-cases/regression/issue-1152.json TESTS+=test/test-cases/regression/issue-1528.json TESTS+=test/test-cases/regression/issue-1565.json diff --git a/test/unit/unit.cc b/test/unit/unit.cc index 46013ec7..5ebc9d3f 100644 --- a/test/unit/unit.cc +++ b/test/unit/unit.cc @@ -15,7 +15,9 @@ #include #include - +#include +#include +#include #include #include #include @@ -38,6 +40,7 @@ using modsecurity_test::UnitTest; +using modsecurity_test::UnitTestResult; using modsecurity_test::ModSecurityTest; using modsecurity_test::ModSecurityTestResults; using modsecurity::actions::transformations::Transformation; @@ -53,64 +56,151 @@ void print_help() { } -void perform_unit_test(ModSecurityTest *test, UnitTest *t, - ModSecurityTestResults* res) { - std::string error; +struct OperatorTest { + using ItemType = Operator; + + static ItemType* init(const UnitTest &t) { + auto op = Operator::instantiate(t.name, t.param); + assert(op != nullptr); + + std::string error; + op->init(t.filename, &error); + + return op; + } + + static UnitTestResult eval(ItemType &op, const UnitTest &t) { + return {op.evaluate(nullptr, nullptr, t.input, nullptr), {}}; + } + + static bool check(const UnitTestResult &result, const UnitTest &t) { + return result.ret != t.ret; + } +}; + + +struct TransformationTest { + using ItemType = Transformation; + + static ItemType* init(const UnitTest &t) { + auto tfn = Transformation::instantiate("t:" + t.name); + assert(tfn != nullptr); + + return tfn; + } + + static UnitTestResult eval(const ItemType &tfn, const UnitTest &t) { + std::string ret = t.input; + tfn.transform(ret, nullptr); + return {1, ret}; + } + + static bool check(const UnitTestResult &result, const UnitTest &t) { + return result.output != t.output; + } +}; + + +template +UnitTestResult perform_unit_test_once(const UnitTest &t) { + std::unique_ptr item(TestType::init(t)); + assert(item.get() != nullptr); + + return TestType::eval(*item.get(), t); +} + + +template +UnitTestResult perform_unit_test_multithreaded(const UnitTest &t) { + + constexpr auto NUM_THREADS = 50; + constexpr auto ITERATIONS = 5'000; + + std::array threads; + std::array results; + + std::unique_ptr item(TestType::init(t)); + assert(item.get() != nullptr); + + for (auto i = 0; i != threads.size(); ++i) + { + auto &result = results[i]; + threads[i] = std::thread( + [&item, &t, &result]() + { + for (auto j = 0; j != ITERATIONS; ++j) + result = TestType::eval(*item.get(), t); + }); + } + + UnitTestResult ret; + + for (auto i = 0; i != threads.size(); ++i) + { + threads[i].join(); + if (TestType::check(results[i], t)) + ret = results[i]; // error value, keep iterating to join all threads + else if(i == 0) + ret = results[i]; // initial value + } + + return ret; // cppcheck-suppress uninitvar ; false positive, ret assigned at least once in previous loop +} + + +template +void perform_unit_test_helper(const ModSecurityTest &test, UnitTest &t, + ModSecurityTestResults &res) { + + if (!test.m_test_multithreaded) + t.result = perform_unit_test_once(t); + else + t.result = perform_unit_test_multithreaded(t); + + if (TestType::check(t.result, t)) { + res.push_back(&t); + if (test.m_automake_output) { + std::cout << "FAIL "; + } + } else if (test.m_automake_output) { + std::cout << "PASS "; + } +} + + +void perform_unit_test(const ModSecurityTest &test, UnitTest &t, + ModSecurityTestResults &res) { bool found = true; - if (test->m_automake_output) { + if (test.m_automake_output) { std::cout << ":test-result: "; } - if (t->resource.empty() == false) { - found = (std::find(resources.begin(), resources.end(), t->resource) - != resources.end()); + if (t.resource.empty() == false) { + found = std::find(resources.begin(), resources.end(), t.resource) + != resources.end(); } if (!found) { - t->skipped = true; - res->push_back(t); - if (test->m_automake_output) { + t.skipped = true; + res.push_back(&t); + if (test.m_automake_output) { std::cout << "SKIP "; } } - if (t->type == "op") { - Operator *op = Operator::instantiate(t->name, t->param); - op->init(t->filename, &error); - int ret = op->evaluate(NULL, NULL, t->input, NULL); - t->obtained = ret; - if (ret != t->ret) { - res->push_back(t); - if (test->m_automake_output) { - std::cout << "FAIL "; - } - } else if (test->m_automake_output) { - std::cout << "PASS "; - } - delete op; - } else if (t->type == "tfn") { - Transformation *tfn = Transformation::instantiate("t:" + t->name); - std::string ret = tfn->evaluate(t->input, NULL); - t->obtained = 1; - t->obtainedOutput = ret; - if (ret != t->output) { - res->push_back(t); - if (test->m_automake_output) { - std::cout << "FAIL "; - } - } else if (test->m_automake_output) { - std::cout << "PASS "; - } - delete tfn; + if (t.type == "op") { + perform_unit_test_helper(test, t, res); + } else if (t.type == "tfn") { + perform_unit_test_helper(test, t, res); } else { - std::cerr << "Failed. Test type is unknown: << " << t->type; + std::cerr << "Failed. Test type is unknown: << " << t.type; std::cerr << std::endl; } - if (test->m_automake_output) { - std::cout << t->name << " " - << modsecurity::utils::string::toHexIfNeeded(t->input) + if (test.m_automake_output) { + std::cout << t.name << " " + << modsecurity::utils::string::toHexIfNeeded(t.input) << std::endl; } } @@ -151,17 +241,15 @@ int main(int argc, char **argv) { test.load_tests("test-cases/secrules-language-tests/transformations"); } - for (std::pair *> a : test) { - std::vector *tests = a.second; - + for (auto& [filename, tests] : test) { total += tests->size(); - for (UnitTest *t : *tests) { + for (auto t : *tests) { ModSecurityTestResults r; if (!test.m_automake_output) { - std::cout << " " << a.first << "...\t"; + std::cout << " " << filename << "...\t"; } - perform_unit_test(&test, t, &r); + perform_unit_test(test, *t, r); if (!test.m_automake_output) { int skp = 0; @@ -189,10 +277,10 @@ int main(int argc, char **argv) { if (!test.m_automake_output) { std::cout << "Total >> " << total << std::endl; - } - for (UnitTest *t : results) { - std::cout << t->print() << std::endl; + for (const auto t : results) { + std::cout << t->print() << std::endl; + } } const int skp = std::count_if(results.cbegin(), results.cend(), [](const auto &i) @@ -216,8 +304,8 @@ int main(int argc, char **argv) { } for (auto a : test) { - auto *vec = a.second; - for(auto *t : *vec) + auto vec = a.second; + for(auto t : *vec) delete t; delete vec; } diff --git a/test/unit/unit_test.cc b/test/unit/unit_test.cc index d15533a3..b0060732 100644 --- a/test/unit/unit_test.cc +++ b/test/unit/unit_test.cc @@ -30,20 +30,6 @@ namespace modsecurity_test { -std::string string_to_hex(const std::string& input) { - static const char* const lut = "0123456789ABCDEF"; - size_t len = input.length(); - - std::string output; - output.reserve(2 * len); - for (size_t i = 0; i < len; ++i) { - const unsigned char c = input[i]; - output.push_back(lut[c >> 4]); - output.push_back(lut[c & 15]); - } - return output; -} - void replaceAll(std::string *s, const std::string &search, const char replace) { for (size_t pos = 0; ; pos += 0) { @@ -102,15 +88,15 @@ std::string UnitTest::print() { i << " \"param\": \"" << this->param << "\"" << std::endl; i << " \"output\": \"" << this->output << "\"" << std::endl; i << "}" << std::endl; - if (this->ret != this->obtained) { + if (this->ret != this->result.ret) { i << "Expecting: \"" << this->ret << "\" - returned: \""; - i << this->obtained << "\"" << std::endl; + i << this->result.ret << "\"" << std::endl; } - if (this->output != this->obtainedOutput) { + if (this->output != this->result.output) { i << "Expecting: \""; i << modsecurity::utils::string::toHexIfNeeded(this->output); i << "\" - returned: \""; - i << modsecurity::utils::string::toHexIfNeeded(this->obtainedOutput); + i << modsecurity::utils::string::toHexIfNeeded(this->result.output); i << "\""; i << std::endl; } diff --git a/test/unit/unit_test.h b/test/unit/unit_test.h index d200db5d..81d99d14 100644 --- a/test/unit/unit_test.h +++ b/test/unit/unit_test.h @@ -25,6 +25,12 @@ namespace modsecurity_test { +class UnitTestResult { + public: + int ret; + std::string output; +}; + class UnitTest { public: static UnitTest *from_yajl_node(const yajl_val &); @@ -39,9 +45,8 @@ class UnitTest { std::string filename; std::string output; int ret; - int obtained; int skipped; - std::string obtainedOutput; + UnitTestResult result; }; } // namespace modsecurity_test diff --git a/tools/rules-check/Makefile.am b/tools/rules-check/Makefile.am index bd929383..6f398fb2 100644 --- a/tools/rules-check/Makefile.am +++ b/tools/rules-check/Makefile.am @@ -28,7 +28,6 @@ modsec_rules_check_LDFLAGS = \ $(YAJL_LDFLAGS) modsec_rules_check_CPPFLAGS = \ - -std=c++17 \ -I$(top_builddir)/headers \ $(GLOBAL_CPPFLAGS) \ $(PCRE_CFLAGS) \ diff --git a/tools/rules-check/rules-check.cc b/tools/rules-check/rules-check.cc index 46c8e1a8..f63d7aa1 100644 --- a/tools/rules-check/rules-check.cc +++ b/tools/rules-check/rules-check.cc @@ -36,9 +36,8 @@ void print_help(const char *name) { int main(int argc, char **argv) { - modsecurity::RulesSet *rules; + auto rules = std::make_unique(); char **args = argv; - rules = new modsecurity::RulesSet(); int ret = 0; args++; @@ -50,41 +49,26 @@ int main(int argc, char **argv) { while (*args != NULL) { struct stat buffer; - std::string argFull(""); - const char *arg = *args; + std::string arg = *args; std::string err; int r; - if (argFull.empty() == false) { - if (arg[strlen(arg)-1] == '\"') { - argFull.append(arg, strlen(arg)-1); - goto next; - } else { - argFull.append(arg); - goto next; - } - } + // strip arg from leading and trailing '"' chars + arg.erase(arg.find_last_not_of('\"')+1); + arg.erase(0, arg.find_first_not_of('\"')); - if (arg[0] == '\"' && argFull.empty() == true) { - if (arg[strlen(arg)-1] == '\"') { - argFull.append(arg+1, strlen(arg) - 2); - } else { - argFull.append(arg+1); - goto next; - } - } - - if (argFull.empty() == false) { - arg = strdup(argFull.c_str()); - argFull.clear(); + if (arg.empty() == true) { + args++; + continue; } std::cout << " : " << arg << " -- "; - if (stat(arg, &buffer) == 0) { - r = rules->loadFromUri(arg); + if (stat(arg.c_str(), &buffer) == 0) { + r = rules->loadFromUri(arg.c_str()); } else { - r = rules->load(arg); + r = rules->load(arg.c_str()); } + if (r < 0) { err.assign(rules->m_parserError.str()); rules->m_parserError.str(""); @@ -95,12 +79,10 @@ int main(int argc, char **argv) { if (err.empty() == false) { std::cerr << " " << err << std::endl; } -next: + args++; } - delete rules; - if (ret < 0) { std::cout << "Test failed." << std::endl; } else {