Skip to content

Commit 9c57c0c

Browse files
committed
Added Windows build scripts using Build Tools for Visual Studio 2022 (MSVC compiler & CMake) and Conan package manager
- Included Dockerfile to automate the setup process of prerequisites and build of libModSecurity binaries.
1 parent 70a8bbd commit 9c57c0c

9 files changed

+583
-0
lines changed

build/win32/CMakeLists.txt

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
cmake_minimum_required(VERSION 3.15)
2+
3+
set(BASE_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
4+
5+
set(USE_ASAN OFF CACHE BOOL "Build with Address Sanitizer")
6+
7+
# common compiler settings
8+
9+
# NOTE: MBEDTLS_CONFIG_FILE is not only required to compile the mbedtls subset in others, but also
10+
# when their headers are included while compiling libModSecurity
11+
add_compile_definitions(WIN32 _CRT_SECURE_NO_WARNINGS MBEDTLS_CONFIG_FILE="mbed-tls-config.h")
12+
13+
# set standards conformance preprocessor & compiler to align with cross-compiled codebase
14+
# NOTE: otherwise visual c++'s default compiler/preprocessor behaviour generates C4067 warnings
15+
# (unexpected tokens following preprocessor directive - expected a newline)
16+
add_compile_options(/Zc:preprocessor /permissive-)
17+
18+
if(USE_ASAN)
19+
add_compile_options(/fsanitize=address)
20+
add_link_options(/INFERASANLIBS /INCREMENTAL:no)
21+
endif()
22+
23+
# libinjection
24+
25+
project(libinjection C)
26+
27+
add_library(libinjection STATIC ${BASE_DIR}/others/libinjection/src/libinjection_sqli.c ${BASE_DIR}/others/libinjection/src/libinjection_xss.c ${BASE_DIR}/others/libinjection/src/libinjection_html5.c)
28+
29+
# mbedtls
30+
31+
project(mbedtls C)
32+
33+
add_library(mbedtls STATIC ${BASE_DIR}/others/mbedtls/base64.c ${BASE_DIR}/others/mbedtls/sha1.c ${BASE_DIR}/others/mbedtls/md5.c)
34+
35+
target_include_directories(mbedtls PRIVATE ${BASE_DIR}/others)
36+
37+
#
38+
# libModSecurity
39+
#
40+
41+
project(libModSecurity
42+
VERSION
43+
3.0.12
44+
LANGUAGES
45+
CXX
46+
)
47+
48+
set(CMAKE_CXX_STANDARD 17)
49+
set(CMAKE_CXX_STANDARD_REQUIRED On)
50+
set(CMAKE_CXX_EXTENSIONS Off)
51+
52+
set(PACKAGE_BUGREPORT "security@modsecurity.org")
53+
set(PACKAGE_NAME "modsecurity")
54+
set(PACKAGE_VERSION "${PROJECT_VERSION}")
55+
set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
56+
set(PACKAGE_TARNAME "${PACKAGE_NAME}")
57+
58+
set(HAVE_GEOIP 0) # should always be zero, no conan package available
59+
set(HAVE_LMDB 1)
60+
set(HAVE_LUA 1)
61+
set(HAVE_LIBXML2 1)
62+
set(HAVE_MAXMIND 1)
63+
set(HAVE_SSDEEP 0) # should always be zero, no conan package available
64+
set(HAVE_YAJL 1) # should always be one, mandatory dependency
65+
set(HAVE_CURL 1)
66+
67+
include(${CMAKE_CURRENT_LIST_DIR}/ConfigureChecks.cmake)
68+
69+
configure_file(config.h.cmake ${BASE_DIR}/src/config.h)
70+
71+
find_package(PCRE2 REQUIRED)
72+
find_package(PThreads4W REQUIRED)
73+
find_package(Poco REQUIRED)
74+
find_package(dirent REQUIRED) # used only by tests (check dirent::dirent refernces)
75+
76+
macro(include_package package flag)
77+
if(${flag})
78+
find_package(${package} REQUIRED)
79+
endif()
80+
endmacro()
81+
82+
include_package(yajl HAVE_YAJL)
83+
include_package(libxml2 HAVE_LIBXML2)
84+
include_package(lua HAVE_LUA)
85+
include_package(CURL HAVE_CURL)
86+
include_package(lmdb HAVE_LMDB)
87+
include_package(maxminddb HAVE_MAXMIND)
88+
89+
# library
90+
#
91+
92+
# NOTE: required to generate libModSecurity's import library (libModSecurity.lib), used by tests to link with shared library
93+
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
94+
95+
file(GLOB_RECURSE libModSecuritySources ${BASE_DIR}/src/*.cc)
96+
97+
add_library(libModSecurity SHARED ${libModSecuritySources})
98+
99+
target_compile_definitions(libModSecurity PRIVATE WITH_PCRE2)
100+
target_include_directories(libModSecurity PRIVATE ${BASE_DIR} ${BASE_DIR}/headers ${BASE_DIR}/others)
101+
target_link_libraries(libModSecurity PRIVATE pcre2::pcre2 pthreads4w::pthreads4w libinjection mbedtls Poco::Poco Iphlpapi.lib)
102+
103+
macro(add_package_dependency project compile_definition link_library flag)
104+
if(${flag})
105+
target_compile_definitions(${project} PRIVATE ${compile_definition})
106+
target_link_libraries(${project} PRIVATE ${link_library})
107+
endif()
108+
endmacro()
109+
110+
add_package_dependency(libModSecurity WITH_YAJL yajl::yajl HAVE_YAJL)
111+
add_package_dependency(libModSecurity WITH_LIBXML2 LibXml2::LibXml2 HAVE_LIBXML2)
112+
add_package_dependency(libModSecurity WITH_LUA lua::lua HAVE_LUA)
113+
if(HAVE_LUA)
114+
target_compile_definitions(libModSecurity PRIVATE WITH_LUA_5_4)
115+
endif()
116+
add_package_dependency(libModSecurity MSC_WITH_CURL CURL::libcurl HAVE_CURL)
117+
add_package_dependency(libModSecurity WITH_LMDB lmdb::lmdb HAVE_LMDB)
118+
add_package_dependency(libModSecurity WITH_MAXMIND maxminddb::maxminddb HAVE_MAXMIND)
119+
120+
# tests
121+
#
122+
123+
project(libModSecurityTests)
124+
125+
function(setTestTargetProperties executable)
126+
target_compile_definitions(${executable} PRIVATE WITH_PCRE2)
127+
target_include_directories(${executable} PRIVATE ${BASE_DIR} ${BASE_DIR}/headers)
128+
target_link_libraries(${executable} PRIVATE libModSecurity pcre2::pcre2 dirent::dirent)
129+
add_package_dependency(${executable} WITH_YAJL yajl::yajl HAVE_YAJL)
130+
endfunction()
131+
132+
# unit tests
133+
file(GLOB unitTestSources ${BASE_DIR}/test/unit/*.cc)
134+
add_executable(unit_tests ${unitTestSources})
135+
setTestTargetProperties(unit_tests)
136+
target_compile_options(unit_tests PRIVATE /wd4805)
137+
138+
# regression tests
139+
file(GLOB regressionTestsSources ${BASE_DIR}/test/regression/*.cc)
140+
add_executable(regression_tests ${regressionTestsSources})
141+
setTestTargetProperties(regression_tests)
142+
143+
macro(add_regression_test_capability compile_definition flag)
144+
if(${flag})
145+
target_compile_definitions(regression_tests PRIVATE ${compile_definition})
146+
endif()
147+
endmacro()
148+
149+
add_regression_test_capability(WITH_LUA HAVE_LUA)
150+
add_regression_test_capability(WITH_CURL HAVE_CURL)
151+
add_regression_test_capability(WITH_LMDB HAVE_LMDB)
152+
add_regression_test_capability(WITH_MAXMIND HAVE_MAXMIND)
153+
154+
# benchmark
155+
add_executable(benchmark ${BASE_DIR}/test/benchmark/benchmark.cc)
156+
setTestTargetProperties(benchmark)
157+
158+
# rules_optimization
159+
add_executable(rules_optimization ${BASE_DIR}/test/optimization/optimization.cc)
160+
setTestTargetProperties(rules_optimization)
161+
162+
163+
# examples
164+
#
165+
166+
project(libModSecurityExamples)
167+
168+
function(setExampleTargetProperties executable)
169+
target_include_directories(${executable} PRIVATE ${BASE_DIR} ${BASE_DIR}/headers)
170+
target_link_libraries(${executable} PRIVATE libModSecurity)
171+
endfunction()
172+
173+
# simple_example_using_c
174+
add_executable(simple_example_using_c ${BASE_DIR}/examples/simple_example_using_c/test.c)
175+
setExampleTargetProperties(simple_example_using_c)
176+
177+
# using_bodies_in_chunks
178+
add_executable(using_bodies_in_chunks ${BASE_DIR}/examples/using_bodies_in_chunks/simple_request.cc)
179+
setExampleTargetProperties(using_bodies_in_chunks)
180+
181+
# reading_logs_via_rule_message
182+
add_executable(reading_logs_via_rule_message ${BASE_DIR}/examples/reading_logs_via_rule_message/simple_request.cc)
183+
setExampleTargetProperties(reading_logs_via_rule_message)
184+
target_link_libraries(reading_logs_via_rule_message PRIVATE libModSecurity pthreads4w::pthreads4w)
185+
186+
# reading_logs_with_offset
187+
add_executable(reading_logs_with_offset ${BASE_DIR}/examples/reading_logs_with_offset/read.cc)
188+
setExampleTargetProperties(reading_logs_with_offset)
189+
190+
# tools
191+
#
192+
193+
# rules_check
194+
add_executable(rules_check ${BASE_DIR}/tools/rules-check/rules-check.cc)
195+
target_include_directories(rules_check PRIVATE ${BASE_DIR} ${BASE_DIR}/headers)
196+
target_link_libraries(rules_check PRIVATE libModSecurity)

build/win32/ConfigureChecks.cmake

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
include(CheckIncludeFile)
2+
include(CheckIncludeFiles)
3+
4+
check_include_file("dlfcn.h" HAVE_DLFCN_H)
5+
check_include_file("inttypes.h" HAVE_INTTYPES_H)
6+
check_include_file("stdint.h" HAVE_STDINT_H)
7+
check_include_file("stdio.h" HAVE_STDIO_H)
8+
check_include_file("stdlib.h" HAVE_STDLIB_H)
9+
check_include_file("string" HAVE_STRING)
10+
check_include_file("strings.h" HAVE_STRINGS_H)
11+
check_include_file("string.h" HAVE_STRING_H)
12+
check_include_file("sys/stat.h" HAVE_SYS_STAT_H)
13+
check_include_file("sys/types.h" HAVE_SYS_TYPES_H)
14+
check_include_file("sys/utsname.h" HAVE_SYS_UTSNAME_H)
15+
check_include_file("unistd.h" HAVE_UNISTD_H)
16+
17+
#/* Define to 1 if you have the ANSI C header files. */
18+
check_include_files("stdlib.h;stdarg.h;string.h;float.h" STDC_HEADERS)

build/win32/README.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# libModSecurity Windows build information <!-- omit from toc -->
2+
3+
The Windows build of libModSecurity uses Build Tools for Visual Studio 2022 (for Visual C++ & CMake) and Conan package manager.
4+
5+
## Contents <!-- omit from toc -->
6+
7+
- [Prerequisites](#prerequisites)
8+
- [Build](#build)
9+
- [Optional features](#optional-features)
10+
- [Address Sanitizer](#address-sanitizer)
11+
- [Docker container](#docker-container)
12+
13+
## Prerequisites
14+
15+
* [Build Tools for Visual Studio 2022](https://aka.ms/vs/17/release/vs_buildtools.exe)
16+
* Install *Desktop development with C++* workload, which includes:
17+
* MSVC C++ compiler
18+
* Windows SDK
19+
* CMake
20+
* Address Sanitizer
21+
* [Conan package manager 2.2.2](https://github.com/conan-io/conan/releases/download/2.2.2/conan-2.2.2-windows-x86_64-installer.exe)
22+
* Install and then setup the default Conan profile to use the MSVC C++ compiler:
23+
1. Open a command-prompt and set the MSVC C++ compiler environment by executing: `C:\BuildTools\VC\Auxiliary\Build\vcvars64.bat`
24+
2. Execute: `conan profile detect --force`
25+
* [Git for Windows 2.44.0](https://github.com/git-for-windows/git/releases/download/v2.44.0.windows.1/Git-2.44.0-64-bit.exe)
26+
* To clone the libModSecurity repository.
27+
* NOTE: Make sure to initialize and update submodules (to get `libinjection` and regression tests)
28+
* `git submodule init`
29+
* `git submodule update`
30+
31+
## Build
32+
33+
Install the prerequisites listsed in the previous section, checkout libModSecurity and from the directory where it's located execute:
34+
35+
```
36+
vcbuild.bat [build_configuration] [arch] [USE_ASAN]
37+
```
38+
39+
where `[build_configuration]` can be: `Release` (default), `RelWithDebInfo`, `MinSizeRel` or `Debug`, and `[arch]` can be: `x86_64` (default) or `x86`.
40+
41+
Built files will be located in the directory: `build\win32\build\[build_configuration]` and include:
42+
43+
* `libModSecurity.dll`
44+
* Executable files for test projects
45+
* `unit_tests.exe`
46+
* `regression_tests.exe`
47+
* `benchmark.exe`
48+
* `rules_optimization.exe`
49+
* Executable files for examples
50+
* `simple_example_using_c.exe`
51+
* `using_bodies_in_chunks.exe`
52+
* `reading_logs_via_rule_message.exe`
53+
* `reading_logs_with_offset.exe`
54+
* Executable files for tools
55+
* `rules_check.exe`
56+
57+
NOTE: When building a different configuration, it's recommended to reset:
58+
59+
* the build directory: `build\win32\build`
60+
* previously built conan packages executing the command:
61+
* `conan remove * -c`
62+
63+
### Optional features
64+
65+
By default the following all the following features are enabled by including the associated third-party library through a Conan package:
66+
67+
* libxml2 2.12.6 for XML processing support
68+
* libcurl 8.6.0 to support http requests from rules
69+
* libmaxminddb 1.9.1 to support reading MaxMind DB files.
70+
* LUA 5.4.6 to enable rules to run scripts in this language for extensibility
71+
* lmdb 0.9.31 in-memory database
72+
73+
Each of these can be turned off by updating the associated `HAVE_xxx` variable (setting it to zero) in the beginning of the libModSecurity section of `CMakeLists.txt`.
74+
75+
### Address Sanitizer
76+
77+
[AddressSanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer) (aka ASan) is a memory error detector for C/C++.
78+
79+
To generate a build with *Address Sanitizer*, add the `USE_ASAN` optional third argument to `vcbuild.bat`. For example:
80+
* `vcbuild.bat Debug x86_64 USE_ASAN`
81+
82+
NOTE: `USE_ASAN` does not work with `Release` & `MinSizeRel` configurations because they do not include debug info (it is only compatible with `Debug` & `RelWithDebInfo` builds).
83+
84+
* References
85+
* [AddressSanitizer | Microsoft Learn](https://learn.microsoft.com/en-us/cpp/sanitizers/asan?view=msvc-170)
86+
* [AddressSanitizer for Windows: x64 and Debug Build Support - C++ Team Blog (microsoft.com)](https://devblogs.microsoft.com/cppblog/asan-for-windows-x64-and-debug-build-support/)
87+
* [AddressSanitizer language, build, and debugging reference | Microsoft Learn](https://learn.microsoft.com/en-us/cpp/sanitizers/asan-building?view=msvc-170)
88+
89+
### Docker container
90+
91+
A `Dockerfile` configuration file is provided in the `docker` subdir that creates a Windows container image which installs the [prerequisites](#prerequisites) and builds libModSecurity and other binaries.
92+
93+
NOTE: Windows containers are supported in Docker Desktop for Windows, using the *Switch to Windows containers...* option on the context menu of the system tray icon.
94+
95+
To build the docker image, execute the following command (from the `build\win32\docker` directory):
96+
97+
* `docker build -t buildtools_libmodsecurity:latest -m 4GB .`
98+
* Build type, architecture and build with Address Sanitizer can be configured through build arguments (`BUILD_TYPE`, `ARCH` & `USE_ASAN` respectively). For example, to generate a debug build, add the following argument:
99+
* `--build-arg BUILD_TYPE=Debug`
100+
101+
Once the image is generated, the library and associated binaries (tests & examples) are located in the `C:\src\ModSecurity\build\win32\build\[build_type]` directory.
102+
103+
To extract the library (`libModSecurity.dll`) from the image, you can execute the following commands:
104+
105+
* `docker container create --name [container_name] buildtools_libmodsecurity`
106+
* `docker cp [container_name]:C:\src\ModSecurity\build\win32\build\[build_type]\libModSecurity.dll .`
107+
* NOTE: If you leave out the `libModSecurity.dll` filename out, you can copy all the built binaries (including examples & tests).
108+
109+
Additionally, the image can be used interactively for additional development work by executing:
110+
111+
* `docker run -it buildtools_libmodsecurity`

build/win32/conanfile.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[requires]
2+
yajl/2.1.0
3+
pcre2/10.42
4+
pthreads4w/3.0.0
5+
libxml2/2.12.6
6+
lua/5.4.6
7+
libcurl/8.6.0
8+
lmdb/0.9.31
9+
libmaxminddb/1.9.1
10+
dirent/1.24
11+
poco/1.13.3
12+
13+
[generators]
14+
CMakeDeps
15+
CMakeToolchain

0 commit comments

Comments
 (0)