1219 Commits

Author SHA1 Message Date
Ervin Hegedus
7bdc3c825c
Merge pull request #3220 from eduar-hte/string-null
Creating a std::string with a null pointer is undefined behaviour
2024-08-09 17:37:47 +02:00
Ervin Hegedus
3a83196a71
Merge pull request #3219 from eduar-hte/cpp17
Simplifiy configuration to build using std C++17
2024-08-09 17:34:02 +02:00
Eduardo Arias
c917d6a2dc Initialize variable in if statement to avoid doing dynamic_cast twice
- Refactored duplicate code in RuleWithOperator::getVariablesExceptions
- Leveraged auto to simplify declaration of dynamic_cast pointers.
2024-08-08 13:37:23 -07:00
Eduardo Arias
18378c10f8 Removed unnecessary dynamic_casts 2024-08-08 13:04:29 -07:00
Eduardo Arias
30a68de92d Creating a std::string with a null pointer is undefined behaviour.
- cppreference mentions this about the constructor that receives a
  const char *:
  - Constructs the string with the contents initialized with a copy of
    the null-terminated character string pointed to by s. The length of
    the string is determined by the first null character. The behavior
    is undefined if [s, s + Traits::length(s)) is not a valid range
    (for example, if s is a null pointer).
- C++23 introduces a deleted constructor to prevent this in static
  scenarios, which is how this issue was detected.
2024-08-08 11:39:37 -07:00
Eduardo Arias
59254fe3bd Simplifiy configuration to build libModSecurity with std C++17
- Leveraged autoconf again to check whether the C++ compiler supports
  the required standard version and build using it.
- Replaced the outdaded `ax_cxx_compile_stdcxx_11.m4` macro with the
  latest version of `ax_cxx_compile_stdcxx` which supports C++17.
  - https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
  - https://raw.githubusercontent.com/autoconf-archive/autoconf-archive/e4e5269db2764b9f53d759c24750ac6ca38e02ea/m4/ax_cxx_compile_stdcxx.m4
- This should also streamline updating to C++20 in the future.
2024-08-08 11:23:35 -07:00
Ervin Hegedus
a519c65902
Merge pull request #3217 from gberkes/v3/sonarcloud_Replace_this_declaration_by_a_structured_binding_declaration
V3/sonarcloud replace this declaration by a structured binding declaration
2024-08-08 17:55:09 +02:00
Ervin Hegedus
1d6e72e8e2
Merge pull request #3212 from eduar-hte/defensive-intervention
Do not assume ModSecurityIntervention argument to transaction::intervention has been initialized/cleaned
2024-08-08 17:45:34 +02:00
gberkes
c50a397a87 Suppress cppcheck false positive unassignedVariable warning. 2024-08-07 21:05:47 +02:00
gberkes
35e825d643 Refactor: replaced 3 declarations with 3 structured binding declarations.
This syntax is far more expressive and easier to understand than the old one.

Refactor: flipped the conditions in "if (contains[Tag|Msg|Id]( ... " statements
for clearer code.

Refactor: moved "Variable *b" as an init-statement inside "if()" statements for
stricter scope.

Reference: https://sonarcloud.io/project/issues?open=AY8-ff1vm_fzkWiCOtCt&id=owasp-modsecurity_ModSecurity
2024-08-07 17:55:30 +02:00
gberkes
ab78d4af79 Refactor: used the init-statement to declare "pos" inside the if statement.
C++17 introduced a construct to create and initialize a variable within the
condition of if and switch statements, and C++20 added this construct to
range-based for loops. Using this new feature simplifies common code patterns
and helps in giving variables the right scope.

Reference: https://sonarcloud.io/project/issues?open=AZDCieK2zGtqRpL2rnl-&id=owasp-modsecurity_ModSecurity
2024-08-07 13:05:02 +02:00
Eduardo Arias
0b5493d4e7 Minor performance improvements setting up intervention's log
- Initialize `log` temporary value on construction instead of doing
  default initialization and then calling `append`.
- Leverage `std::string_view` to replace `const std::string&` parameters
  in `utils::string::replaceAll` to avoid creating a `std::string`
  object (and associated allocation and copy) for the string literal`%d`
2024-08-06 14:40:45 -07:00
Eduardo Arias
c947f5e40d Do not assume ModSecurityIntervention argument to transaction::intervention has been initialized/cleaned
- Keep m_it->disruptive value and use it as return value to guarantee
  that the value is correct.
  - If m_it->disruptive is false and the 'it' argument has not been
    initialized/cleaned, the function may incorrectly return a non-zero
    value.
- When a disruptive intervention is being reported by the function,
  defensively initialize log & url to NULL if there's no such data to
  provide to the caller.
  - If the caller has not initialized/cleaned those fields in the 'it'
    argument, after returning from transaction::intervention, the user
    can safely read the log & url fields and in all scenarios they'll
    have valid values.
2024-08-06 14:40:45 -07:00
Ervin Hegedus
68d551c5f9
Merge pull request #3210 from eduar-hte/shared-files-deadlock
Fixed shared files deadlock in a multi-threaded Windows application
2024-08-06 17:35:41 +02:00
Eduardo Arias
4b5f719906 Fixed shared files deadlock in a multi-threaded Windows application
- The shared files Windows implementation introduced in PR #3132 works
  in multi-process single-threaded contexts but it doesn't work
  correctly in single-process multi-threaded contexts.
- The issue is that the LockFileEx Win32 function works on a per-handle
  basis.
  - In a multi-process context, each process will have called
    SharedFiles::add_new_handler when initializing the SharedFile and
    obtained a handle, and thus locking will work.
  - When running ModSecurity in a single process using multiple threads,
    the initialization of the SharedFile will happen once and the handle
    will be shared by all threads. Then, if two threads try to write to
    the same shared file concurrently, they may deadlock as one of them
    will lock the file (by calling LockFileEx) and then proceed to write
    to the file. If before writing to the file and unlocking it, another
    thread calls LockFileEx on the same handle, the attempt to write to
    the file will lock generating a deadlock.
- The new implementation replaces usage of LockFileEx/UnlockFileEx with
  a named mutex to lock access to the shared file.
  - A named mutex is used to support multi-process scenarios.
  - The mutex name is generated using the filename to support multiple
    shared files (such as that for the debug and audit logs).
    - This assumes that both process will initialize the SharedFile
      instance using the same filename (which is expected as they'd be
      using the same configuration file)
2024-08-05 13:04:09 -07:00
Eduardo Arias
dab9bb6a11 Added methods to free buffers allocated by ModSecurity APIs
- The following methods are introduced to allow clients of
  libModSecurity that are not able to link and call the C/C++ standard
  library to be able to free the buffers allocated by libModSecurity.
- msc_intervention_cleanup: Frees the buffers in a
  ModSecurityIntervention structure that have been allocated by calls to
  msc_intervention.
- msc_rules_error_cleanup: Frees an error message buffer allocated by
  the msc_rules_xxx functions to detail the condition that triggered
  the error.
2024-08-05 12:18:11 -07:00
gberkes
b4659959cd Refactor: Ensure safe error handling by removing isolated throw; statements.
- SonarCloud analysis identified standalone `throw;` calls without accompanying `try-catch` blocks, used inconsistently as placeholders or for premature termination under specific conditions.
- Removed these `throw;` instances to prevent potential runtime issues in future development phases, where such configurations might inadvertently be created.
- Introduced `assert` statements as a more appropriate mechanism for asserting preconditions in the affected class member functions, ensuring clearer intent and safer code behavior during development.
- Refactor action_kind processing to use switch() instead of if-else chains; add assertion in default case.
- Fix SonarCloud issue: Make this variable a const reference.
https://sonarcloud.io/project/issues?resolved=false&pullRequest=3104&id=owasp-modsecurity_ModSecurity&open=AY8Vpgy4f6U6E7VKL4Cn
2024-08-04 22:04:07 +02:00
Ervin Hegedus
b6d218f72d
Merge pull request #3116 from gberkes/v3/remove_this_conditional_structure
Deleted redundant code in 'ModSecurity::serverLog(...)'.
2024-08-02 16:33:07 +02:00
Ervin Hegedus
c7efeb6d06
Merge branch 'owasp-modsecurity:v3/master' into v3/sethostname 2024-08-01 22:35:44 +02:00
Ervin Hegedus
4b38435a6e
Merge pull request #3117 from airween/v3/eualrangebyfind
fix: Changed 'equal_range()' + loop by 'find()' in resolveFirst() methods
2024-07-31 15:46:54 +02:00
Ervin Hegedus
937fc5ae59
Provide a function to set 'hostname' field in log 2024-07-29 22:07:26 +02:00
Eduardo Arias
6faf6d7ec0 Removed unnecessary usage of heap-allocated VariableValue (m_var)
- Removed unused methods
2024-07-17 00:49:27 +00:00
Eduardo Arias
dc0a06fc70 Improve performance of VariableOrigin instances
- The previous approach would create a std::unique_ptr and store it in
  a std::list in VariableValue (Origins)
- The new approach now stores Origins in a std::vector and constructs
  VariableOrigin elements in-place on insertion.
- Instead of having two heap-allocations for every added VariableOrigin
  instance, this performs only one.
- If multiple origins are added, std::vector's growth strategy may even
  prevent a heap-allocation. There's a cost on growing the size of the
  vector, because a copy of current elements will be necessary.
  - Introduced reserveOrigin method to notify that multiple insertions
    will be made, so that we can use std::vector's reserve and do a
    single allocation (and copy of previous elements), and then just
    initialize the new elements in-place.
2024-07-17 00:49:27 +00:00
Eduardo Arias
a3f40ef03c Replace Mbed TLS source code in repository with a submodule
- Updated to latest Mbed TLS version (v3.6.0)
2024-05-31 00:41:10 +00:00
Eduardo Arias
7732b5e8f3 Update libinjection to version v3.9.2-92-gb9fcaaf 2024-05-31 00:41:10 +00:00
Eduardo Arias
2c488386c4 Add options nounistd & never-interactive to seclang-scanner.ll
- The parser is not used interactively so we can avoid including
  unistd.h, which is not available on Windows MSVC C++ compiler.
- The #ifdef WIN32 introduced in PR #3132 would probably be overwritten
  when the parser is updated.
2024-05-19 16:38:03 +00:00
Eduardo Arias
a8e132f3a1 Replaced the use of "new" in find_resource
- Addresses SonarCloud issue cpp:S5025 (Memory should not be managed manually)
- This function was not changed for the Windows port, but a similar
change to the one suggested was done in expandEnv in the same file.
- The first stream is not destructed at the exact same point it was in
the previous code (but rather when the second stream replaces it on
assignment to the same variable). An arbitrary scope could have been
introduced to destruct the object at the same place, but it doesn't
seem to be necessary and would make the code a bit strange.
2024-05-10 02:28:13 +00:00
Eduardo Arias
b69405a372 Use default keyword to implement constructor/destructor
- Addresses SonarCloud cpp:S3490 issue (Special member function should
not be defined unless a non standard behavior is required)
2024-05-10 02:28:13 +00:00
Eduardo Arias
411bbb2d36 Updated case of winsock header files
- Address SonarCloud cpp:S3806 issues ("#include" paths should be portable)
- This is not an actual issue in this case, because WinSock2.h and
WS2tcpip.h are Windows only.
2024-05-10 02:28:13 +00:00
Eduardo Arias
d7c49ed590 Added support to lock files on Windows and major rewrite to reintroduce reference counting and remove unused code.
- In Windows build, replaced usage of fcntl with cmd F_SETLKW with
  Win32 APIs to do file locking (LockFileEx & UnlockFileEx).
- Reintroduced the reference counting initially present in the class
  which is necessary to correctly handle merging of rules. This allows
  for correctly closing the file and removing the associated entry from
  m_handlers when the file is no longer used.
  - The need for reference counting can be seen in the example
  simple_example_using_c, where rules are initially loaded locally and
  then further rules are loaded remotely. This will initially open a
  shared file for a log, then in order to merge rules, the shared file
  is opened again for the new configuration. Then, the previous
  configuration closes the shared file on destruction. That is, two
  consecutive opens are done on a shared file, which is followed by
  a close. If the shared file is not reference counted, the shared file
  will be closed while there is still a reference active. The current
  version works because closing of the file has been disabled after
  reference counting was removed.
- Replaced `std::vector` data structure with `std::unordered_map` to
  improve lookup/update times, and simplify code.
- Removed unused code
  - Shared memory to store msc_file_handler structure
    - Initially SharedFiles used shared memory to store information
    about each shared file, including its file pointer and a mutex to
    synchronize access to the file on write. See code at commit 01c13da,
    in particular, usage of lock & fp fields in the msc_file_handler_t
    structure.
    - At that time, msc_file_handler_t included reference counting too
    with the using_it field, which was incremented when a file was
    opened and decremented on close. If the reference count reached
    zero, the shared file would be closed, the lock destroyed and the
    file handler entry removed from m_handlers.
    - Reference counting was removed in commit 7f9cd76, which
    introduced the following issues in SharedFiles::close:
      - No longer closes the file pointer.
        - The file pointer appears to be reset when a.second = 0, but
	this is a local copy of the data pair obtained from m_handlers,
	so this is essentially a nop (updating a local variable that is
	not referenced later in the function).
        - NOTE: The file pointer was moved out of the shared memory in
	this commit too, and stored alongside the msc_file_handler_t
	instance in the m_handlers entry associated to the shared file.
      - The lock is no longer destroyed.
      - The shared memory is marked to be destroyed in the call to:
      shmctl(a.first->shm_id_structure, IPC_RMID, NULL);
      - The shared file entry is not removed from m_handlers, so:
        - the file pointer is still valid, which is how writing to the
	file continues to work,
        - the reference to the shared memory is also present and will
	be marked to be destroyed whenever close is called again on the
	shared file.
    - File locking using the mutex in msc_file_handler_t was replaced in
    commit 3d20304 with usage of fcntl with cmd F_SETLKW.
    - At this time, it appears that the shared memory is no longer used,
    as the file pointer and locking no longer depend on it.
  - MODSEC_USE_GENERAL_LOCK
    - This code is introduced commit 7f9cd76 and is enabled if
    MODSEC_USE_GENERAL_LOCK` is defined.
    - The define is commented out in the source code since the original
    commit and is not present in the build configuration either.
    - In commit ff9152e, in the SharedFiles constructor, the
    initialization of the local variable toBeCreated is removed. This
    means that in this version, if MODSEC_USE_GENERAL_LOCK is enabled,
    execution of the code that checks on toBeCreated is undefined.
    - Then, in commit 9b40a04, the variable toBeCreated is initialized
    again, but is now set to false, which means that if
    MODSEC_USE_GENERAL_LOCK is enabled, the shared memory and lock it
    uses will *not* be initialized and thus doesn't work (execution of
    the current version will result in trying to acquire a lock that
    will be null).
    - I conclude that the feature is not used and can be removed.
      - Additionally, if it were working, I think the lock should be
      used in SharedFiles::write as well, which is a reader of the
      underlying data structures protected by this lock when they're
      modified in SharedFiles::open & SharedFiles::close.
2024-05-10 02:28:13 +00:00
Eduardo Arias
50e78331b1 Updated Env::evaluate to support case-insensitive environment variable names in Windows
- Env::evaluate
  - Environment variable names in Windows are case-insensitive, so in
  the Windows build we use strcasecmp to ignore case when matching
  variables in transaction->m_variableEnvs.
  - If the variable is found, we use the expected variable name to
  create the VariableValue instance, as further rule processing will
  look for the variable using case-sensitive comparisons.
    - This code is not limited to Windows to avoid another #ifdef block
    because for other platforms, because the env variable names are
    case-sensitive the value from either x.first and m_name will be the
    same.
- In Windows build, avoid redefining environ, already defined by
  including stdlib.h.
2024-05-10 02:28:13 +00:00
Eduardo Arias
50c35345ed Fixed use after free in ModSecurity::processContentOffset
- Use after free issue detected with Address Sanitizer while running
  the reading_logs_with_offset example.
- Keeps reference to last element in vars vector with vars.back(). Then
  it removes the element from vars calling vars.pop_back() which
  invalidates the reference, but it's accessed later in the function.
2024-05-10 02:28:13 +00:00
Eduardo Arias
fef419f986 Minor changes related to std::shared_ptr usage in RuleWithActions
- RuleWithActions::evaluate(Transaction *transaction)
  - Removed temporary rm local variable used to immediately create
  std::shared_ptr<RuleMessage>.
- Leverage std::make_shared & auto to simplify code.
2024-05-03 23:05:34 -03:00
Eduardo Arias
10c6ee726f Added support for expandEnv, createDir & cpu_seconds on Windows
- expandEnv on Windows uses POCO C++ Libraries implementation of Glob
  - Paths of matched files are adjusted to preserve UNIX path
  separators for consistency with the rest of the code.
  - Minor change to code shared with other platforms that removes
  allocation of std::ifstream on the heap to check whether the file can
  be opened, which can be done with local stack variable that closes
  the file when out of scope.
- createDir uses _mkdir on Windows, which doesn't support configuring
  the new directory's mode.
- added public domain implementation of clock_gettime for clock_id
  CLOCK_PROCESS_CPUTIME_ID from mingw-w64's winpthreads to support
  cpu_seconds on Windows.
- Updated included headers to support compilation on Windows (using
  Visual C++)
2024-05-03 23:05:34 -03:00
Eduardo Arias
ebf1f8fd28 On Windows use the operating system's native CA store for certificate verification of https requests.
- Updated included headers to support compilation on Windows (using
  Visual C++)
2024-05-03 23:05:34 -03:00
Eduardo Arias
91a736692a Minor changes to debug_log_writer
- Removed unused m_first data member.
- Explicitly delete copy constructor and assignment operator.
- Removed unused included headers.
2024-05-03 23:05:34 -03:00
Eduardo Arias
373633ffe2 mkstemp is not available in Windows build, replaced with _mktemp_s plus _open.
- Updated included headers to support compilation on Windows (using
  Visual C++)
- Minor change to use C++ default (zero) initialization instead of
  calling memset.
2024-05-03 23:05:34 -03:00
Eduardo Arias
35949179a4 setenv is not available in Windows build, replaced with _putenv_s 2024-05-03 23:05:34 -03:00
Eduardo Arias
abbd7b2f42 Replaced usage of apr_snprintf with snprintf (already in Windows exclusive code block)
- updated included headers to support compilation on Windows (using
  Visual C++)
2024-05-03 23:05:34 -03:00
Eduardo Arias
a48856822c Updated included headers to support compilation on Windows (using Visual C++)
- most of posix related functions and constants in unistd.h can be
  found in io.h in Visual C++
- introduced src/compat/msvc.h to adjust for compiler differences (and
  avoid updating code with #ifdef blocks for Windows support)
- removed some included headers that are not needed (both on Unix and
  Windows builds)
2024-05-03 23:05:34 -03:00
Eduardo Arias
1f419bba8f Implement sonarcloud suggestions 2024-05-02 17:18:31 -03:00
Eduardo Arias
9f5dc200ba Replace final three suppressions entries with line numbers
- These were initially not included in these changes, as they were
other PRs (#3104 & #3132) that address them.
2024-04-29 22:28:42 -03:00
Eduardo Arias
7a9c0ab15f Removed unused suppresion and avoid copy of logPath 2024-04-28 14:56:37 -03:00
Eduardo Arias
4aad8e0d06 Inline cppcheck suppressions 2024-04-28 14:56:23 -03:00
Eduardo Arias
cd2dded659 Removed unnecessary break after return 2024-04-28 14:56:00 -03:00
Eduardo Arias
0cd2f459f3 Address cppcheck suppressions in lmdb 2024-04-28 14:55:49 -03:00
Eduardo Arias
fde9d279b0 Removed unnecessary cppcheck suppression and r-value reference as copy should be avoidded by RVO 2024-04-28 14:55:18 -03:00
Felipe Zipitria
30fe6f935b
fix(rbl): typo in rbl check selector
Signed-off-by: Felipe Zipitria <felipe.zipitria@owasp.org>
2024-04-22 10:23:28 -03:00
Ervin Hegedus
16d0df0ff9
Optimized variable handling 2024-03-31 14:14:45 +02:00
Ervin Hegedus
7c4dcdfa4b
Changed 'euqal_range()' + loop by 'find()' in resolveFirst() methods 2024-03-29 16:32:34 +01:00