From 7073e6382e89e47c7641070cbd4e2e1d0dddf3f4 Mon Sep 17 00:00:00 2001 From: meirdev Date: Tue, 21 Apr 2026 14:13:18 +0300 Subject: [PATCH 1/4] Add C API to retrieve matched rules from a transaction --- headers/modsecurity/transaction.h | 6 +++++ src/transaction.cc | 43 +++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/headers/modsecurity/transaction.h b/headers/modsecurity/transaction.h index 3e70caa38e..8404f63754 100644 --- a/headers/modsecurity/transaction.h +++ b/headers/modsecurity/transaction.h @@ -739,6 +739,12 @@ int msc_update_status_code(Transaction *transaction, int status); /** @ingroup ModSecurity_C_API */ int msc_set_request_hostname(Transaction *transaction, const unsigned char *hostname); +/** @ingroup ModSecurity_C_API */ +size_t msc_get_matched_rules_count(Transaction *transaction); + +/** @ingroup ModSecurity_C_API */ +int64_t msc_get_matched_rule_id(Transaction *transaction, size_t index); + #ifdef __cplusplus } } // namespace modsecurity diff --git a/src/transaction.cc b/src/transaction.cc index 408f9b3d40..b55acaa897 100644 --- a/src/transaction.cc +++ b/src/transaction.cc @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -2325,5 +2326,47 @@ extern "C" int msc_set_request_hostname(Transaction *transaction, } +/** + * @name msc_get_matched_rules_count + * @brief Retrieve the number of matched rules on a transaction. + * + * Returns the number of rule-match records held on the transaction. + * Every rule that matched (disruptive or not) contributes one entry. + * + * @param transaction ModSecurity transaction. + * + * @returns The number of matched rule records on the transaction. + * + */ +extern "C" size_t msc_get_matched_rules_count(Transaction *transaction) { + return transaction->m_rulesMessages.size(); +} + + +/** + * @name msc_get_matched_rule_id + * @brief Retrieve the rule id of the n-th matched rule. + * + * Returns the rule id of the n-th matched rule (0-based). + * + * @param transaction ModSecurity transaction. + * @param index Zero-based index into the matched rule records. + * + * @returns The rule id at the given index. + * @retval >0 Rule id of the matched rule at the given index. + * @retval 0 Index is out of range. + * + */ +extern "C" int64_t msc_get_matched_rule_id(Transaction *transaction, + size_t index) { + if (index >= transaction->m_rulesMessages.size()) { + return 0; + } + auto it = transaction->m_rulesMessages.begin(); + std::advance(it, index); + return it->m_rule.m_ruleId; +} + + } // namespace modsecurity From eaf68398931bd3f60923563d2e7a7e8f503f7b32 Mon Sep 17 00:00:00 2001 From: meirdev Date: Wed, 22 Apr 2026 18:36:47 +0300 Subject: [PATCH 2/4] Fix Windows compiler error --- headers/modsecurity/transaction.h | 1 + 1 file changed, 1 insertion(+) diff --git a/headers/modsecurity/transaction.h b/headers/modsecurity/transaction.h index 8404f63754..87e05b7ab2 100644 --- a/headers/modsecurity/transaction.h +++ b/headers/modsecurity/transaction.h @@ -35,6 +35,7 @@ #include #include +#include #ifndef __cplusplus typedef struct ModSecurity_t ModSecurity; From cd81b6be6c6306351f5821e62996aae5e2cd9468 Mon Sep 17 00:00:00 2001 From: meirdev Date: Sun, 26 Apr 2026 21:54:48 +0300 Subject: [PATCH 3/4] Use const for transaction --- headers/modsecurity/transaction.h | 4 ++-- src/transaction.cc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/headers/modsecurity/transaction.h b/headers/modsecurity/transaction.h index 87e05b7ab2..a561a23242 100644 --- a/headers/modsecurity/transaction.h +++ b/headers/modsecurity/transaction.h @@ -741,10 +741,10 @@ int msc_update_status_code(Transaction *transaction, int status); int msc_set_request_hostname(Transaction *transaction, const unsigned char *hostname); /** @ingroup ModSecurity_C_API */ -size_t msc_get_matched_rules_count(Transaction *transaction); +size_t msc_get_matched_rules_count(const Transaction *transaction); /** @ingroup ModSecurity_C_API */ -int64_t msc_get_matched_rule_id(Transaction *transaction, size_t index); +int64_t msc_get_matched_rule_id(const Transaction *transaction, size_t index); #ifdef __cplusplus } diff --git a/src/transaction.cc b/src/transaction.cc index b55acaa897..34e0c37dc9 100644 --- a/src/transaction.cc +++ b/src/transaction.cc @@ -2338,7 +2338,7 @@ extern "C" int msc_set_request_hostname(Transaction *transaction, * @returns The number of matched rule records on the transaction. * */ -extern "C" size_t msc_get_matched_rules_count(Transaction *transaction) { +extern "C" size_t msc_get_matched_rules_count(const Transaction *transaction) { return transaction->m_rulesMessages.size(); } @@ -2357,7 +2357,7 @@ extern "C" size_t msc_get_matched_rules_count(Transaction *transaction) { * @retval 0 Index is out of range. * */ -extern "C" int64_t msc_get_matched_rule_id(Transaction *transaction, +extern "C" int64_t msc_get_matched_rule_id(const Transaction *transaction, size_t index) { if (index >= transaction->m_rulesMessages.size()) { return 0; From ddf6234c49d64507e1ef0865755c147c108375d4 Mon Sep 17 00:00:00 2001 From: meirdev Date: Sun, 26 Apr 2026 22:28:40 +0300 Subject: [PATCH 4/4] Update the interface --- headers/modsecurity/transaction.h | 5 +-- src/transaction.cc | 52 +++++++++++++++++++------------ 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/headers/modsecurity/transaction.h b/headers/modsecurity/transaction.h index a561a23242..bc506ad773 100644 --- a/headers/modsecurity/transaction.h +++ b/headers/modsecurity/transaction.h @@ -741,10 +741,11 @@ int msc_update_status_code(Transaction *transaction, int status); int msc_set_request_hostname(Transaction *transaction, const unsigned char *hostname); /** @ingroup ModSecurity_C_API */ -size_t msc_get_matched_rules_count(const Transaction *transaction); +size_t msc_get_rules_messages_size(const Transaction *transaction); /** @ingroup ModSecurity_C_API */ -int64_t msc_get_matched_rule_id(const Transaction *transaction, size_t index); +size_t msc_get_rules_messages_rule_ids(const Transaction *transaction, + int64_t *ids, size_t ids_len); #ifdef __cplusplus } diff --git a/src/transaction.cc b/src/transaction.cc index 34e0c37dc9..df32d58667 100644 --- a/src/transaction.cc +++ b/src/transaction.cc @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -2327,44 +2326,57 @@ extern "C" int msc_set_request_hostname(Transaction *transaction, /** - * @name msc_get_matched_rules_count - * @brief Retrieve the number of matched rules on a transaction. + * @name msc_get_rules_messages_size + * @brief Retrieve the number of RuleMessage records on a transaction. * - * Returns the number of rule-match records held on the transaction. - * Every rule that matched (disruptive or not) contributes one entry. + * Returns the size of Transaction::m_rulesMessages: the number of + * RuleMessage records that were selected to be logged on the + * transaction. This is not necessarily the total number of rules that + * matched! * * @param transaction ModSecurity transaction. * - * @returns The number of matched rule records on the transaction. + * @returns The number of RuleMessage records on the transaction. * */ -extern "C" size_t msc_get_matched_rules_count(const Transaction *transaction) { +extern "C" size_t msc_get_rules_messages_size(const Transaction *transaction) { return transaction->m_rulesMessages.size(); } /** - * @name msc_get_matched_rule_id - * @brief Retrieve the rule id of the n-th matched rule. + * @name msc_get_rules_messages_rule_ids + * @brief Copy the rule ids from Transaction::m_rulesMessages into a buffer. * - * Returns the rule id of the n-th matched rule (0-based). + * Copies the rule id of each RuleMessage into the caller-provided buffer. + * Only rule messages that were selected to be logged are included. + * + * The caller is expected to size the buffer using + * msc_get_rules_messages_size. If @p ids_len is smaller than the number + * of available records, only the first @p ids_len ids are written and + * the remaining records are skipped. * * @param transaction ModSecurity transaction. - * @param index Zero-based index into the matched rule records. + * @param ids Caller-provided buffer to receive the rule ids. + * May be NULL only if @p ids_len is 0. + * @param ids_len Capacity of @p ids, in number of int64_t slots. * - * @returns The rule id at the given index. - * @retval >0 Rule id of the matched rule at the given index. - * @retval 0 Index is out of range. + * @returns The number of rule ids written into @p ids. * */ -extern "C" int64_t msc_get_matched_rule_id(const Transaction *transaction, - size_t index) { - if (index >= transaction->m_rulesMessages.size()) { +extern "C" size_t msc_get_rules_messages_rule_ids(const Transaction *transaction, + int64_t *ids, size_t ids_len) { + if (ids == nullptr || ids_len == 0) { return 0; } - auto it = transaction->m_rulesMessages.begin(); - std::advance(it, index); - return it->m_rule.m_ruleId; + size_t written = 0; + for (const auto &msg : transaction->m_rulesMessages) { + if (written >= ids_len) { + break; + } + ids[written++] = msg.m_rule.m_ruleId; + } + return written; }