diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a18c950a9..60b2f4c16 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -94,6 +94,8 @@ jobs: submodules: recursive - name: Create Build Directory run: cmake -E make_directory ${{ github.workspace }}/build ${{ github.workspace }}/packages + - name: Download cargo arm64 target + run: rustup target add aarch64-apple-darwin - name: Generating Build Scripts run: cmake -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DMACOSX_DEPLOYMENT_TARGET=10.9 -DCMAKE_INSTALL_PREFIX=${{ github.workspace }} -DCPACK_PACKAGE_DIRECTORY=${{ github.workspace }}/packages ${{ github.workspace }} working-directory: ${{ github.workspace }}/build diff --git a/CMakeLists.txt b/CMakeLists.txt index d6e873371..55d9e37cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,11 +70,11 @@ if(LINUX) $<$:rt> $<$:dl> $<$:m>) -elseif(WIN32) - list(APPEND LIBDDWAF_INTERFACE_LIBRARIES ws2_32) +elseif(MSVC) + list(APPEND LIBDDWAF_INTERFACE_LIBRARIES NtDll UserEnv Bcrypt crypt32 wsock32 ws2_32) endif() -set(LIBDDWAF_PRIVATE_LIBRARIES "") +set(LIBDDWAF_PRIVATE_LIBRARIES libstring_checker) if(NOT MSVC AND LIBDDWAF_TESTING AND LIBDDWAF_TEST_COVERAGE) list(APPEND LIBDDWAF_PRIVATE_LIBRARIES gcov) endif() diff --git a/cmake/static.cmake b/cmake/static.cmake index 5fe4c6147..0ecc4754f 100644 --- a/cmake/static.cmake +++ b/cmake/static.cmake @@ -17,6 +17,7 @@ if(LINUX) add_custom_command(TARGET libddwaf_static POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory ar_comb COMMAND ${CMAKE_COMMAND} -E chdir ar_comb ${CMAKE_AR} -x $ + COMMAND ${CMAKE_COMMAND} -E chdir ar_comb ${CMAKE_AR} -x $ COMMAND ${CMAKE_COMMAND} -E copy $ ar_comb COMMAND ${CMAKE_AR} -qcs ar_comb/combined${CMAKE_STATIC_LIBRARY_SUFFIX} ar_comb/*.o* diff --git a/docker/libddwaf/build/Dockerfile b/docker/libddwaf/build/Dockerfile index 310adfbae..a9fbe89dc 100644 --- a/docker/libddwaf/build/Dockerfile +++ b/docker/libddwaf/build/Dockerfile @@ -4,6 +4,9 @@ ARG ARCH COPY . /libddwaf +RUN wget https://sh.rustup.rs -O rustup.sh && chmod u+x rustup.sh && ./rustup.sh -y -t x86_64-unknown-linux-musl aarch64-unknown-linux-musl armv7-unknown-linux-musleabihf i686-unknown-linux-musl +RUN ls /root/.cargo/bin | xargs -n1 bash -c 'echo "Linking $0" ; ln -s /root/.cargo/bin/$0 /usr/bin/$0' + RUN mkdir -p build RUN cd build && cmake \ -G Ninja \ diff --git a/docker/libddwaf/gcc/mingw64/Dockerfile b/docker/libddwaf/gcc/mingw64/Dockerfile index bb857da7e..166f985b0 100644 --- a/docker/libddwaf/gcc/mingw64/Dockerfile +++ b/docker/libddwaf/gcc/mingw64/Dockerfile @@ -2,7 +2,10 @@ # win64) FROM alpine:3.14 AS build -RUN apk --update-cache add cmake make mingw-w64-gcc mingw-w64-winpthreads git +RUN apk --update-cache add cmake make mingw-w64-gcc mingw-w64-winpthreads git rustup +RUN rustup-init -y --target x86_64-pc-windows-gnu + +RUN ls /root/.cargo/bin | xargs -n1 sh -c 'echo "Linking $0" ; ln -s /root/.cargo/bin/$0 /usr/bin/$0' ARG BUILD_TYPE=Release COPY . /usr/local/src/libddwaf diff --git a/src/matcher/is_passwd.hpp b/src/matcher/is_passwd.hpp new file mode 100644 index 000000000..775af181c --- /dev/null +++ b/src/matcher/is_passwd.hpp @@ -0,0 +1,39 @@ +// Unless explicitly stated otherwise all files in this repository are +// dual-licensed under the Apache-2.0 License or BSD-3-Clause License. +// +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2021 Datadog, Inc. + +#pragma once + +#include +#include + +#include "matcher/base.hpp" + +namespace ddwaf::matcher { + +class is_passwd : public base_impl { +public: + is_passwd() = default; + ~is_passwd() override = default; + is_passwd(const is_passwd &) = default; + is_passwd(is_passwd &&) noexcept = default; + is_passwd &operator=(const is_passwd &) = default; + is_passwd &operator=(is_passwd &&) noexcept = default; + +protected: + static constexpr std::string_view to_string_impl() { return ""; } + static constexpr std::string_view name_impl() { return "is_passwd"; } + + static constexpr DDWAF_OBJ_TYPE supported_type_impl() { return DDWAF_OBJ_STRING; } + + [[nodiscard]] std::pair match_impl(std::string_view obtained) const + { + return {check_string(obtained.data()), std::string{obtained}}; + } + + friend class base_impl; +}; + +} // namespace ddwaf::matcher diff --git a/src/parser/parser_v2.cpp b/src/parser/parser_v2.cpp index d8752e1cc..aae68c45d 100644 --- a/src/parser/parser_v2.cpp +++ b/src/parser/parser_v2.cpp @@ -18,6 +18,7 @@ #include "matcher/equals.hpp" #include "matcher/exact_match.hpp" #include "matcher/ip_match.hpp" +#include "matcher/is_passwd.hpp" #include "matcher/is_sqli.hpp" #include "matcher/is_xss.hpp" #include "matcher/phrase_match.hpp" @@ -82,6 +83,8 @@ std::pair> parse_matcher( matcher = std::make_unique(); } else if (name == "is_sqli") { matcher = std::make_unique(); + } else if (name == "is_passwd") { + matcher = std::make_unique(); } else if (name == "ip_match") { auto it = params.find("list"); if (it == params.end()) { diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index 084f61dca..88d290ac3 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -133,3 +133,5 @@ ExternalProject_Add(proj_event_rules set_target_properties(proj_event_rules PROPERTIES EXCLUDE_FROM_ALL TRUE) # vim: et + +add_subdirectory(string_checker) diff --git a/third_party/string_checker/.gitignore b/third_party/string_checker/.gitignore new file mode 100644 index 000000000..6985cf1bd --- /dev/null +++ b/third_party/string_checker/.gitignore @@ -0,0 +1,14 @@ +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb diff --git a/third_party/string_checker/CMakeLists.txt b/third_party/string_checker/CMakeLists.txt new file mode 100644 index 000000000..843744250 --- /dev/null +++ b/third_party/string_checker/CMakeLists.txt @@ -0,0 +1,53 @@ +# Files to clean +set_property(DIRECTORY PROPERTY ADDITIONAL_MAKE_CLEAN_FILES target) + +set(CARGO_BUILD cargo build) +set(BUILD_BYPRODUCT "${CMAKE_CURRENT_SOURCE_DIR}/target") + +if (LINUX) + if (NOT "${CMAKE_C_COMPILER_TARGET}" STREQUAL "") + if ("${CMAKE_C_COMPILER_TARGET}" STREQUAL "i386-none-linux-musl") + set(BUILD_TARGET "i686-unknown-linux-musl") + else() + string(REPLACE "none" "unknown" BUILD_TARGET ${CMAKE_C_COMPILER_TARGET}) + endif() + endif() +endif() + +if (APPLE AND "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64") + set(BUILD_TARGET "aarch64-apple-darwin") +endif() + +if (MINGW) + set(BUILD_TARGET "x86_64-pc-windows-gnu") +endif() + +if (NOT "${BUILD_TARGET}" STREQUAL "") + set(BUILD_BYPRODUCT "${BUILD_BYPRODUCT}/${BUILD_TARGET}") + set(CARGO_BUILD ${CARGO_BUILD} --target ${BUILD_TARGET}) +endif() + +if (CMAKE_BUILD_TYPE MATCHES Release OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + set(BUILD_BYPRODUCT "${BUILD_BYPRODUCT}/release") + set(CARGO_BUILD ${CARGO_BUILD} --release) +else() + set(BUILD_BYPRODUCT "${BUILD_BYPRODUCT}/debug") +endif() + +if (MSVC) + set(BUILD_BYPRODUCT "${BUILD_BYPRODUCT}/string_checker${CMAKE_STATIC_LIBRARY_SUFFIX}") +else() + set(BUILD_BYPRODUCT "${BUILD_BYPRODUCT}/libstring_checker${CMAKE_STATIC_LIBRARY_SUFFIX}") +endif() +add_custom_target( + libstring_checker_build + COMMAND ${CARGO_BUILD} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Compiling Rust library" + BYPRODUCTS ${BUILD_BYPRODUCT} +) + +add_library(libstring_checker STATIC IMPORTED GLOBAL) +set_target_properties(libstring_checker PROPERTIES IMPORTED_LOCATION ${BUILD_BYPRODUCT}) +target_include_directories(libstring_checker INTERFACE include) +add_dependencies(libstring_checker libstring_checker_build) diff --git a/third_party/string_checker/Cargo.toml b/third_party/string_checker/Cargo.toml new file mode 100644 index 000000000..6ae39639a --- /dev/null +++ b/third_party/string_checker/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "string_checker" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +crate-type = ["staticlib"] + +[profile.release] +opt-level = 'z' # Optimize for size +lto = false +codegen-units = 1 + +[dependencies] diff --git a/third_party/string_checker/include/string_checker.h b/third_party/string_checker/include/string_checker.h new file mode 100644 index 000000000..8e4c8d48c --- /dev/null +++ b/third_party/string_checker/include/string_checker.h @@ -0,0 +1,17 @@ +#ifndef RUST_C_LIB_H +#define RUST_C_LIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +bool check_string(const char *c_string); + +#ifdef __cplusplus +} +#endif + +#endif // RUST_C_LIB_H + diff --git a/third_party/string_checker/src/lib.rs b/third_party/string_checker/src/lib.rs new file mode 100644 index 000000000..c1fc63108 --- /dev/null +++ b/third_party/string_checker/src/lib.rs @@ -0,0 +1,12 @@ +use std::ffi::CStr; +use std::os::raw::c_char; + +#[no_mangle] +pub extern "C" fn check_string(c_string: *const c_char) -> bool { + let c_str = unsafe { + assert!(!c_string.is_null()); + CStr::from_ptr(c_string) + }; + + c_str.to_str().unwrap() == "/etc/passwd" +}