diff --git a/.github/workflows/test-ci-windows.yml b/.github/workflows/test-ci-windows.yml new file mode 100644 index 00000000..7abe75ee --- /dev/null +++ b/.github/workflows/test-ci-windows.yml @@ -0,0 +1,69 @@ +name: CI/CD for IIS Module + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + build: + runs-on: windows-latest + + steps: + - name: Checkout code + uses: actions/checkout@v5 + + - name: Setup MSYS2 + uses: msys2/setup-msys2@v2 + with: + msystem: UCRT64 + update: true + install: > + git + make + autoconf + automake + libtool + mingw-w64-ucrt-x86_64-gcc + mingw-w64-ucrt-x86_64-pkg-config + + - name: Clone and build ssdeep + shell: msys2 {0} + run: | + git clone https://github.com/ssdeep-project/ssdeep.git --depth 1 + cd ssdeep + autoreconf -i + ./configure --enable-shared --disable-static CFLAGS="-O3" CXXFLAGS="-O3" + make dll + mkdir -p ${{ github.workspace }}/ssdeep-install/bin + mkdir -p ${{ github.workspace }}/ssdeep-install/include + cp fuzzy.dll ${{ github.workspace }}/ssdeep-install/bin/ + cp fuzzy.h ${{ github.workspace }}/ssdeep-install/include/ + cp fuzzy.def ${{ github.workspace }}/ssdeep-install/ + + - name: Configure CMake for IIS Module + run: | + cmake \ + -DAPACHE_ROOT="C:/tools/Apache24" \ + -DSSDEEP_ROOT="${{ github.workspace }}/ssdeep-install" \ + -DCMAKE_INSTALL_PREFIX="${{ github.workspace }}/install" \ + -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" \ + -DWITH_SSDEEP=ON \ + -DWITH_LUA=ON \ + -DWITH_YAJL=ON \ + -S IIS -B iis/build + + - name: Build IIS Module + shell: pwsh + run: | + cmake --build iis/build --config Release + + # - name: Package IIS Module with WiX + # shell: pwsh + # run: | + # $CURRENT_DIR = "${{ github.workspace }}/iis/wix" + # candle.exe -ext WixUtilExtension -ext WixUIExtension "$CURRENT_DIR\installer.wxs" -out "$CURRENT_DIR\installer.wixobj" -arch x64 + # light.exe -ext WixUtilExtension -ext WixUIExtension "$CURRENT_DIR\installer.wixobj" -out "$CURRENT_DIR\installer-64.msi" \ No newline at end of file diff --git a/iis/CMakeLists.txt b/iis/CMakeLists.txt new file mode 100644 index 00000000..11ebd1f9 --- /dev/null +++ b/iis/CMakeLists.txt @@ -0,0 +1,330 @@ +cmake_minimum_required(VERSION 3.15) +project(ModSecurityIIS C CXX) + +find_package(LibXml2 CONFIG REQUIRED) +find_package(PCRE2 CONFIG REQUIRED) +find_package(CURL CONFIG REQUIRED) + +# iis/CMakeLists.txt +set(IIS_MODULE_NAME "modsecurityiis") # Name should match the original output + +# Source files for IIS module (reusing Apache sources) +set(IIS_APACHE_SOURCES + ../apache2/mod_security2.c + ../apache2/apache2_config.c + ../apache2/apache2_io.c + ../apache2/apache2_util.c + ../apache2/re.c + ../apache2/re_operators.c + ../apache2/re_actions.c + ../apache2/re_tfns.c + ../apache2/re_variables.c + ../apache2/msc_logging.c + ../apache2/msc_xml.c + ../apache2/msc_multipart.c + ../apache2/modsecurity.c + ../apache2/msc_parsers.c + ../apache2/msc_util.c + ../apache2/msc_pcre.c + ../apache2/persist_dbm.c + ../apache2/msc_reqbody.c + ../apache2/msc_geo.c + ../apache2/msc_gsb.c + ../apache2/msc_crypt.c + ../apache2/msc_tree.c + ../apache2/msc_unicode.c + ../apache2/acmp.c + ../apache2/msc_lua.c + ../apache2/msc_release.c + ../apache2/msc_status_engine.c + ../apache2/msc_remote_rules.c + ../apache2/msc_json.c + ../apache2/libinjection/libinjection_html5.c + ../apache2/libinjection/libinjection_sqli.c + ../apache2/libinjection/libinjection_xss.c +) + +# Source files for standalone components (if they exist in the project) +set(IIS_STANDALONE_SOURCES + ../standalone/api.c + ../standalone/buckets.c + ../standalone/config.c + ../standalone/filters.c + ../standalone/hooks.c + ../standalone/regex.c + ../standalone/server.c +) + +# Source files for IIS-specific components +set(IIS_MODULE_SOURCES + main.cpp + moduleconfig.cpp + mymodule.cpp +) + + +# Determine architecture +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(ARCHITECTURE "x64") +else() + set(ARCHITECTURE "x86") +endif() + +# Check if standalone directory exists, if not, exclude those sources +if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/../standalone) + set(IIS_STANDALONE_SOURCES "") +endif() + +set(IIS_RESOURCE_MC "${CMAKE_CURRENT_SOURCE_DIR}/ModSecurityIISMessage.mc") + +set(MC_GENERATED_RC "${CMAKE_CURRENT_BINARY_DIR}/ModSecurityIISMessage.rc") +set(MC_GENERATED_H "${CMAKE_CURRENT_BINARY_DIR}/ModSecurityIISMessage.h") +add_custom_command( + OUTPUT ${MC_GENERATED_RC} ${MC_GENERATED_H} + COMMAND mc.exe + ARGS -U -h "${CMAKE_CURRENT_BINARY_DIR}/" -r "${CMAKE_CURRENT_BINARY_DIR}/" "${IIS_RESOURCE_MC}" + DEPENDS "${IIS_RESOURCE_MC}" + COMMENT "Generating resource files from ${IIS_RESOURCE_MC}" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) + +set(MC_GENERATED_RES "${CMAKE_CURRENT_BINARY_DIR}/ModSecurityIISMessage.res") +add_custom_command( + OUTPUT ${MC_GENERATED_RES} + COMMAND rc.exe + ARGS /fo "${MC_GENERATED_RES}" "${MC_GENERATED_RC}" + DEPENDS ${MC_GENERATED_RC} + COMMENT "Building resource file: ${MC_GENERATED_RES}" +) + +set_source_files_properties( + ${MC_GENERATED_RC} + ${MC_GENERATED_H} + ${MC_GENERATED_RES} + PROPERTIES GENERATED TRUE +) + +add_library(${IIS_MODULE_NAME} SHARED + ${IIS_APACHE_SOURCES} + ${IIS_STANDALONE_SOURCES} + ${IIS_MODULE_SOURCES} + ${MC_GENERATED_RES} +) + +# Set the output name and extension +set_target_properties(${IIS_MODULE_NAME} PROPERTIES + OUTPUT_NAME ${IIS_MODULE_NAME} + PREFIX "" + SUFFIX ".dll" +) + +# Include directories +target_include_directories(${IIS_MODULE_NAME} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/../apache2 + ${CMAKE_CURRENT_SOURCE_DIR}/../apache2/libinjection + ${LIBXML2_INCLUDE_DIR}/libxml + ${PCRE_INCLUDE_DIRS} + ${CURL_INCLUDE_DIRS} + ${CMAKE_CURRENT_BINARY_DIR} # 添加构建目录以访问生成的头文件 +) + +# Include standalone directory if it exists +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/../standalone) + target_include_directories(${IIS_MODULE_NAME} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/../standalone + ) +endif() + +# Apache-specific includes +if(APACHE_ROOT) + target_include_directories(${IIS_MODULE_NAME} PRIVATE + ${APACHE_ROOT}/include + ) +endif() + +# Compile definitions to match the original Makefile.win +set(MODSECURITY_VERSION_FLAG "VERSION_IIS") # Define the version flag string +target_compile_definitions(${IIS_MODULE_NAME} PRIVATE + WIN32 + WINNT + inline=APR_INLINE + AP_DECLARE_STATIC + WITH_CURL + WITH_REMOTE_RULES + MSC_LARGE_STREAM_INPUT + WITH_YAJL + ${MODSECURITY_VERSION_FLAG} # Use the defined version flag +) + +option(WITH_LUA "Enable Lua support" OFF) +# Optional compile definitions +if(WITH_LUA) + find_package(Lua CONFIG REQUIRED) + target_compile_definitions(${IIS_MODULE_NAME} PRIVATE WITH_LUA) + target_include_directories(${IIS_MODULE_NAME} PRIVATE ${LUA_INCLUDE_DIR}) +endif() + +# Default Apache root based on architecture +if(NOT APACHE_ROOT) + if(ARCHITECTURE STREQUAL "x64") + set(APACHE_ROOT "C:/Apache24_x64" CACHE PATH "Path to Apache x64 installation") + else() + set(APACHE_ROOT "C:/Apache24_x86" CACHE PATH "Path to Apache x86 installation") + endif() +endif() + +option(WITH_YAJL "Enable YAJL support" OFF) +if(WITH_YAJL) + # Manually find YAJL if config.cmake is not available (e.g., from vcpkg) + find_path(YAJL_INCLUDE_DIR yajl/yajl_common.h + PATHS "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg_installed/${ARCHITECTURE}-windows/include" + NO_DEFAULT_PATH + ) + find_library(YAJL_LIBRARY NAMES yajl + PATHS "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg_installed/${ARCHITECTURE}-windows/lib" + NO_DEFAULT_PATH + ) + + if(YAJL_INCLUDE_DIR AND YAJL_LIBRARY) + set(YAJL_INCLUDE_DIRS ${YAJL_INCLUDE_DIR}) + set(YAJL_LIBRARIES ${YAJL_LIBRARY}) + target_compile_definitions(${IIS_MODULE_NAME} PRIVATE WITH_YAJL) + target_include_directories(${IIS_MODULE_NAME} PRIVATE ${YAJL_INCLUDE_DIRS}) + else() + message(WARNING "YAJL not found. Please ensure yajl is installed via vcpkg in the iis/vcpkg_installed directory. Disabling YAJL support.") + option(WITH_YAJL "Enable YAJL support" OFF) # Disable if not found + endif() +endif() + +option(WITH_SSDEEP "Enable SSDEEP support" OFF) +if(WITH_SSDEEP) + + set(SSDEEP_ROOT "" CACHE PATH "Path to manually built ssdeep") + if(NOT SSDEEP_ROOT OR NOT EXISTS "${SSDEEP_ROOT}") + message(WARNING "SSDEEP_ROOT is not defined or path does not exist. Please set SSDEEP_ROOT to the ssdeep installation directory. Disabling SSDEEP support.") + set(WITH_SSDEEP OFF CACHE BOOL "Enable SSDEEP support" FORCE) + else() + message(STATUS "SSDEEP_ROOT: ${SSDEEP_ROOT}") + + # 查找头文件 + find_path(SSDEEP_INCLUDE_DIR fuzzy.h + PATHS "${SSDEEP_ROOT}/include" + NO_DEFAULT_PATH + ) + + if(SSDEEP_INCLUDE_DIR) + message(STATUS "Found manually built ssdeep include: ${SSDEEP_INCLUDE_DIR}") + target_compile_definitions(${IIS_MODULE_NAME} PRIVATE WITH_SSDEEP) + target_include_directories(${IIS_MODULE_NAME} PRIVATE ${SSDEEP_INCLUDE_DIR}) + + # 检查 fuzzy.def 文件是否存在 + set(SSDEEP_DEF_FILE "${SSDEEP_ROOT}/fuzzy.def") + if(NOT EXISTS "${SSDEEP_DEF_FILE}") + message(WARNING "fuzzy.def not found at ${SSDEEP_DEF_FILE}. Disabling SSDEEP support.") + set(WITH_SSDEEP OFF CACHE BOOL "Enable SSDEEP support" FORCE) + else() + set(SSDEEP_GENERATED_LIB "${CMAKE_CURRENT_BINARY_DIR}/fuzzy.lib") + + # 添加自定义命令生成 fuzzy.lib + add_custom_command( + OUTPUT ${SSDEEP_GENERATED_LIB} + COMMAND lib.exe /machine:${ARCHITECTURE} /def:${SSDEEP_DEF_FILE} /out:${SSDEEP_GENERATED_LIB} + DEPENDS "${SSDEEP_DEF_FILE}" + COMMENT "Generating SSDEEP .lib from .def for MSVC" + VERBATIM + ) + + # 确保自定义命令的输出被标记为生成文件 + set_source_files_properties(${SSDEEP_GENERATED_LIB} PROPERTIES GENERATED TRUE) + + # 添加自定义目标确保生成 fuzzy.lib + add_custom_target(generate_ssdeep_lib ALL + DEPENDS ${SSDEEP_GENERATED_LIB} + COMMENT "Ensuring ssdeep lib is generated" + ) + + # 使主目标依赖于 fuzzy.lib 的生成 + add_dependencies(${IIS_MODULE_NAME} generate_ssdeep_lib) + + endif() + else() + message(WARNING "SSDEEP include (fuzzy.h) not found at ${SSDEEP_ROOT}/include. Disabling SSDEEP support.") + set(WITH_SSDEEP OFF CACHE BOOL "Enable SSDEEP support" FORCE) + endif() + endif() +endif() + +# Compiler-specific options for MSVC to match the original Makefile.win +if(MSVC) + target_compile_options(${IIS_MODULE_NAME} PRIVATE + /nologo + /O2 + /W3 + /wd4244 + /wd4018 + /MD + /Zi + ) + + # Linker options to match the original Makefile.win + set_target_properties(${IIS_MODULE_NAME} PROPERTIES + LINK_FLAGS "/DEBUG /OPT:REF /OPT:ICF" + ) +endif() + +# Link libraries to match the original Makefile.win +target_link_libraries(${IIS_MODULE_NAME} PRIVATE + LibXml2::LibXml2 + PCRE2::8BIT + CURL::libcurl + kernel32 + user32 + gdi32 + winspool + comdlg32 + advapi32 + shell32 + ole32 + oleaut32 + uuid + odbc32 + odbccp32 + ws2_32 + iphlpapi +) + +# Apache-specific libraries +if(APACHE_ROOT) + target_link_libraries(${IIS_MODULE_NAME} PRIVATE + ${APACHE_ROOT}/lib/libhttpd.lib + ${APACHE_ROOT}/lib/libapr-1.lib + ${APACHE_ROOT}/lib/libaprutil-1.lib + ) +endif() + +# Optional link libraries +if(WITH_LUA) + target_link_libraries(${IIS_MODULE_NAME} PRIVATE ${LUA_LIBRARIES}) +endif() + +if(WITH_YAJL) + target_link_libraries(${IIS_MODULE_NAME} PRIVATE ${YAJL_LIBRARIES}) +endif() + +if(WITH_SSDEEP AND SSDEEP_INCLUDE_DIR AND SSDEEP_GENERATED_LIB) + target_link_libraries(${IIS_MODULE_NAME} PRIVATE ${SSDEEP_GENERATED_LIB}) +else() + message(WARNING "SSDEEP library not found or generated. Disabling SSDEEP support.") + option(WITH_SSDEEP "Enable SSDEEP support" OFF) # Disable if library not found +endif() + +# Install target - copy to release files directory +install(TARGETS ${IIS_MODULE_NAME} + RUNTIME DESTINATION . + LIBRARY DESTINATION . +) + +# Also install the PDB file if it's generated +install(FILES $ DESTINATION . OPTIONAL) \ No newline at end of file diff --git a/iis/vcpkg.json b/iis/vcpkg.json new file mode 100644 index 00000000..55f76ebe --- /dev/null +++ b/iis/vcpkg.json @@ -0,0 +1,9 @@ +{ + "dependencies": [ + "curl", + "libxml2", + "lua", + "pcre2", + "yajl" + ] +} \ No newline at end of file