Jan 06 2026 dev (#387)

* sync code

* update code to support brotli

* update code to support brotli

* update code to support brotli

* sync code

* fix findBrotli

* sync code

* sync code

* sync code

* sync code

---------

Co-authored-by: Ned Wright <nedwright@proton.me>
Co-authored-by: Daniel Eisenberg <danielei@checkpoint.com>
This commit is contained in:
Daniel-Eisenberg
2026-01-13 17:17:52 +02:00
committed by GitHub
parent c1058db57d
commit e7b6e51b31
216 changed files with 12601 additions and 2825 deletions

View File

@@ -68,8 +68,12 @@ public:
const std::vector<IpProtoRange> & getProtoValue() const { return ip_proto_value; }
const std::vector<MatchQuery> & getItems() const { return items; }
std::string getFirstValue() const { return first_value; }
MatchResult getMatch(const std::unordered_map<std::string, std::set<std::string>> &key_value_pairs) const;
bool matchAttributes(const std::unordered_map<std::string, std::set<std::string>> &key_value_pairs) const;
MatchResult getMatch(
const std::unordered_map<std::string, std::set<std::string>> &key_value_pairs,
bool skip_irrelevant_key = false) const;
bool matchAttributes(
const std::unordered_map<std::string, std::set<std::string>> &key_value_pairs,
bool skip_irrelevant_key = false) const;
bool matchException(const std::string &behaviorKey, const std::string &behaviorValue) const;
bool isKeyTypeIp() const;
bool isKeyTypePort() const;
@@ -82,7 +86,8 @@ public:
private:
bool matchAttributes(
const std::unordered_map<std::string, std::set<std::string>> &key_value_pairs,
std::set<std::string> &matched_override_keywords) const;
std::set<std::string> &matched_override_keywords,
bool skip_irrelevant_key = false) const;
StaticKeys getKeyByName(const std::string &key_type_name);
bool matchAttributes(const std::set<std::string> &values,
std::set<std::string> &matched_override_keywords) const;

View File

@@ -190,7 +190,7 @@ public:
static void
preload()
{
registerExpectedConfiguration<ParameterException>("rulebase", "exception");
registerExpectedConfigurationWithCache<ParameterException>("assetId", "rulebase", "exception");
registerConfigLoadCb([](){ is_geo_location_exception_exists = is_geo_location_exception_being_loaded; });
registerConfigPrepareCb([](){ is_geo_location_exception_being_loaded = false; });
}
@@ -198,14 +198,20 @@ public:
void load(cereal::JSONInputArchive &archive_in);
std::set<ParameterBehavior>
getBehavior(const std::unordered_map<std::string, std::set<std::string>> &key_value_pairs) const;
getBehavior(
const std::unordered_map<std::string, std::set<std::string>> &key_value_pairs,
bool skip_irrelevant_key = false) const;
std::set<ParameterBehavior>
getBehavior(
const std::unordered_map<std::string, std::set<std::string>> &key_value_pairs,
std::set<std::string> &matched_override_keywords) const;
const std::unordered_map<std::string, std::set<std::string>> &key_value_pairs,
std::set<std::string> &matched_override_keywords,
bool skip_irrelevant_key = false) const;
static bool isGeoLocationExceptionExists() { return is_geo_location_exception_exists; }
const MatchQuery& getMatch() const { return match; }
bool isContainingKVPair() const { return is_containing_kv_pair; }
bool checkKVPair() const;
private:
class MatchBehaviorPair
@@ -221,6 +227,7 @@ private:
ParameterBehavior behavior;
static bool is_geo_location_exception_exists;
static bool is_geo_location_exception_being_loaded;
bool is_containing_kv_pair;
};
static const ParameterBehavior action_ignore(BehaviorKey::ACTION, BehaviorValue::IGNORE);

View File

@@ -112,7 +112,7 @@ public:
static void
preload()
{
registerExpectedConfiguration<BasicRuleConfig>("rulebase", "rulesConfig");
registerExpectedConfigurationWithCache<BasicRuleConfig>("assetId", "rulebase", "rulesConfig");
registerExpectedSetting<std::vector<BasicRuleConfig>>("rulebase", "rulesConfig");
registerConfigLoadCb(BasicRuleConfig::updateCountMetric);
registerConfigPrepareCb([](){ BasicRuleConfig::assets_ids_aggregation.clear(); });

View File

@@ -52,7 +52,7 @@ public:
static void
preload()
{
registerExpectedConfiguration<WebTriggerConf>("rulebase", "webUserResponse");
registerExpectedConfigurationWithCache<WebTriggerConf>("triggerId", "rulebase", "webUserResponse");
}
/// \brief Load function to deserialize configuration from JSONInputArchive.
@@ -104,6 +104,14 @@ public:
return redirect_url;
}
/// \brief Get the content type for the trigger.
/// \return The content type for the trigger.
const std::string &
getContentType() const
{
return content_type;
}
/// \brief Check if the trigger should add an event ID to the header.
/// \return True if the trigger should add an event ID, otherwise false.
bool
@@ -120,6 +128,7 @@ private:
std::string details_level;
std::string response_body;
std::string redirect_url;
std::string content_type;
uint response_code;
bool add_event_id_to_header = false;
};
@@ -175,7 +184,8 @@ public:
static void
preload()
{
registerExpectedConfiguration<LogTriggerConf>("rulebase", "log");
//registerExpectedConfiguration<LogTriggerConf>("rulebase", "log");
registerExpectedConfigurationWithCache<LogTriggerConf>("triggerId", "rulebase", "log");
}
/// \brief LogGen operator for LogTriggerConf.
@@ -260,6 +270,15 @@ public:
return should_log_on_prevent.isSet(security_type);
}
/// \brief Check if should ignore exception log for the given security type.
/// \param security_type The security type to check.
/// \return True if should ignore exception, otherwise false.
bool
shouldIgnoreExceptionLog(SecurityType security_type) const
{
return should_log_exception.isSet(security_type);
}
/// \brief Check if the log is active on detect for the given security type.
/// \param security_type The security type to check.
/// \return True if the log is active on detect, otherwise false.
@@ -333,6 +352,7 @@ private:
Flags<ReportIS::StreamType> active_streams;
Flags<SecurityType> should_log_on_detect;
Flags<SecurityType> should_log_on_prevent;
Flags<SecurityType> should_log_exception;
Flags<SecurityType> log_geo_location;
Flags<WebLogFields> log_web_fields;
extendLoggingSeverity extend_logging_severity = extendLoggingSeverity::None;
@@ -349,7 +369,7 @@ public:
static void
preload()
{
registerExpectedConfiguration<ReportTriggerConf>("rulebase", "report");
registerExpectedConfigurationWithCache<ReportTriggerConf>("triggerId", "rulebase", "report");
}
/// \brief Load function to deserialize configuration from JSONInputArchive.

View File

@@ -22,13 +22,13 @@
class FilterVerdict
{
public:
FilterVerdict(ngx_http_cp_verdict_e _verdict = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INSPECT)
FilterVerdict(ServiceVerdict _verdict = ServiceVerdict::TRAFFIC_VERDICT_INSPECT)
:
verdict(_verdict)
{}
FilterVerdict(
ngx_http_cp_verdict_e _verdict,
ServiceVerdict _verdict,
const std::string &_web_reponse_id)
:
verdict(_verdict),
@@ -40,15 +40,21 @@ public:
verdict(_verdict.getVerdict()),
web_user_response_id(_verdict.getWebUserResponseByPractice())
{
if (verdict == ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INJECT) {
if (verdict == ServiceVerdict::TRAFFIC_VERDICT_INJECT) {
addModifications(_verdict.getModifications(), _event_idx);
}
}
FilterVerdict(ServiceVerdict _verdict, const CustomResponse &_custom_response)
:
verdict(_verdict),
custom_response(_custom_response)
{}
void
addModifications(const FilterVerdict &other)
{
if (other.verdict != ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INJECT) return;
if (other.verdict != ServiceVerdict::TRAFFIC_VERDICT_INJECT) return;
modifications.insert(modifications.end(), other.modifications.begin(), other.modifications.end());
total_modifications += other.total_modifications;
@@ -58,22 +64,24 @@ public:
addModifications(
const ModificationList &mods,
ModifiedChunkIndex _event_idx,
ngx_http_cp_verdict_e alt_verdict = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_IRRELEVANT)
ServiceVerdict alt_verdict = ServiceVerdict::TRAFFIC_VERDICT_IRRELEVANT)
{
total_modifications += mods.size();
modifications.push_back(EventModifications(_event_idx, mods));
if (alt_verdict != ngx_http_cp_verdict_e::TRAFFIC_VERDICT_IRRELEVANT) verdict = alt_verdict;
if (alt_verdict != ServiceVerdict::TRAFFIC_VERDICT_IRRELEVANT) verdict = alt_verdict;
}
uint getModificationsAmount() const { return total_modifications; }
ngx_http_cp_verdict_e getVerdict() const { return verdict; }
ServiceVerdict getVerdict() const { return verdict; }
const std::vector<EventModifications> & getModifications() const { return modifications; }
const std::string getWebUserResponseID() const { return web_user_response_id; }
Maybe<CustomResponse> getCustomResponse() const { return custom_response; }
private:
ngx_http_cp_verdict_e verdict = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INSPECT;
ServiceVerdict verdict = ServiceVerdict::TRAFFIC_VERDICT_INSPECT;
std::vector<EventModifications> modifications;
std::string web_user_response_id;
Maybe<CustomResponse> custom_response = genError("uninitialized");
uint total_modifications = 0;
};

View File

@@ -25,12 +25,12 @@
#include "debug.h"
#include "buffer.h"
#include "http_transaction_data.h"
#include "nginx_attachment_common.h"
#include "nano_attachment_common.h"
USE_DEBUG_FLAG(D_HTTP_MANAGER);
using ModificationType = ngx_http_modification_type_e;
using ModificationPosition = ngx_http_cp_inject_pos_t;
using ModificationType = HttpModificationType;
using ModificationPosition = NanoHttpCpInjectPos;
static const ModificationPosition injection_pos_irrelevant = INJECT_POS_IRRELEVANT;
@@ -185,12 +185,18 @@ class HttpHeader
{
public:
HttpHeader() = default;
HttpHeader(const Buffer &_key, const Buffer &_value, uint8_t _header_index, bool _is_last_header = false)
HttpHeader(
const Buffer &_key,
const Buffer &_value,
uint8_t _header_index,
bool _is_last_header = false,
bool _should_log = true)
:
key(_key),
value(_value),
is_last_header(_is_last_header),
header_index(_header_index)
header_index(_header_index),
should_log(_should_log)
{
}
@@ -203,7 +209,8 @@ public:
key,
value,
is_last_header,
header_index
header_index,
should_log
);
}
@@ -215,7 +222,8 @@ public:
key,
value,
is_last_header,
header_index
header_index,
should_log
);
}
// LCOV_EXCL_STOP
@@ -232,6 +240,8 @@ public:
<< std::to_string(header_index)
<< ", Is last header: "
<< (is_last_header ? "True" : "False")
<< ", Should log: "
<< (should_log ? "True" : "False")
<< ")";
}
@@ -241,12 +251,18 @@ public:
bool isLastHeader() const { return is_last_header; }
void setIsLastHeader() { is_last_header = true; }
uint8_t getHeaderIndex() const { return header_index; }
bool shouldLog() const { return should_log; }
void setShouldNotLog() {
dbgTrace(D_HTTP_MANAGER) << "Header '" << std::dumpHex(key) << "' marked as should not log";
should_log = false;
}
private:
Buffer key;
Buffer value;
bool is_last_header = false;
uint8_t header_index = 0;
bool should_log = true;
};
using BodyModification = Buffer;
@@ -362,23 +378,54 @@ private:
uint8_t body_chunk_index;
};
class CustomResponse
{
public:
CustomResponse(
const std::string& body,
uint16_t status_code,
const std::string& content_type = "application/json"
) :
body(body),
status_code(status_code),
content_type(content_type)
{}
std::string getBody() const { return body; }
uint16_t getStatusCode() const { return status_code; }
std::string getContentType() const { return content_type; }
private:
std::string body;
uint16_t status_code;
std::string content_type;
};
class EventVerdict
{
public:
EventVerdict() = default;
EventVerdict(ngx_http_cp_verdict_e event_verdict) : modifications(), verdict(event_verdict) {}
EventVerdict(ServiceVerdict event_verdict) : modifications(), verdict(event_verdict) {}
EventVerdict(const ModificationList &mods) : modifications(mods) {}
EventVerdict(const ModificationList &mods, ngx_http_cp_verdict_e event_verdict) :
EventVerdict(const ModificationList &mods, ServiceVerdict event_verdict) :
modifications(mods),
verdict(event_verdict)
{}
EventVerdict(
const CustomResponse &custom_response
) :
modifications(),
verdict(ServiceVerdict::TRAFFIC_VERDICT_CUSTOM_RESPONSE),
custom_response(custom_response)
{}
EventVerdict(
const ModificationList &mods,
ngx_http_cp_verdict_e event_verdict,
ServiceVerdict event_verdict,
std::string response_id) :
modifications(mods),
verdict(event_verdict),
@@ -390,17 +437,20 @@ public:
// LCOV_EXCL_STOP
const ModificationList & getModifications() const { return modifications; }
ngx_http_cp_verdict_e getVerdict() const { return verdict; }
ServiceVerdict getVerdict() const { return verdict; }
const std::string getWebUserResponseByPractice() const { return webUserResponseByPractice; }
void setWebUserResponseByPractice(const std::string id) {
dbgTrace(D_HTTP_MANAGER) << "current verdict web user response set to: " << id;
webUserResponseByPractice = id;
}
Maybe<CustomResponse> getCustomResponse() const { return custom_response; }
private:
ModificationList modifications;
ngx_http_cp_verdict_e verdict = ngx_http_cp_verdict_e::TRAFFIC_VERDICT_INSPECT;
ServiceVerdict verdict = ServiceVerdict::TRAFFIC_VERDICT_INSPECT;
std::string webUserResponseByPractice;
Maybe<CustomResponse> custom_response = genError("uninitialized");
};
#endif // __I_HTTP_EVENT_IMPL_H__

View File

@@ -31,6 +31,7 @@ public:
const Buffer & getValue() const { return req_header.getValue(); }
bool isLastHeader() const { return req_header.isLastHeader(); }
uint8_t getHeaderIndex() const { return req_header.getHeaderIndex(); }
bool shouldLog() const { return req_header.shouldLog(); }
template <class Archive>
void

View File

@@ -0,0 +1,40 @@
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __HYPERSCAN_HOOK_H__
#define __HYPERSCAN_HOOK_H__
#ifdef USE_HYPERSCAN
#include <vector>
#include <string>
#include <set>
#include "hs.h"
#include "i_pm_scan.h"
class HyperscanHook : public I_PMScan {
public:
HyperscanHook();
~HyperscanHook();
Maybe<void> prepare(const std::set<PMPattern> &patterns);
std::set<PMPattern> scanBuf(const Buffer &buf) const override;
std::set<std::pair<uint, uint>> scanBufWithOffset(const Buffer &buf) const override;
void scanBufWithOffsetLambda(const Buffer &buf, I_PMScan::CBFunction cb) const override;
bool ok() const { return m_hsReady; }
private:
hs_database_t *m_hsDatabase;
hs_scratch_t *m_hsScratch;
std::vector<std::string> m_hsPatterns;
std::vector<PMPattern> m_idToPattern;
bool m_hsReady;
};
#endif // USE_HYPERSCAN
#endif // __HYPERSCAN_HOOK_H__

View File

@@ -21,7 +21,16 @@
class I_StaticResourcesHandler
{
public:
virtual bool registerStaticResource(const std::string &resource_name, const std::string &resource_full_path) = 0;
virtual bool registerStaticResource(
const std::string &resource_name,
const std::string &resource_full_path,
bool overwrite_if_exists = false
) = 0;
virtual bool registerStaticResourceByContent(
const std::string &resource_name,
const std::string &file_content
) = 0;
protected:
virtual ~I_StaticResourcesHandler() {}

View File

@@ -2,13 +2,13 @@
#define __IPS_COMP_H__
#include "singleton.h"
#include "i_generic_rulebase.h"
#include "i_keywords_rule.h"
#include "i_table.h"
#include "i_mainloop.h"
#include "i_http_manager.h"
#include "i_environment.h"
#include "http_inspection_events.h"
#include "i_generic_rulebase.h"
#include "component.h"
class IPSComp

View File

@@ -7,9 +7,17 @@ class MockNginxAttachment:
public Singleton::Provide<I_StaticResourcesHandler>::From<MockProvider<I_StaticResourcesHandler>>
{
public:
MOCK_METHOD2(
MOCK_METHOD3(
registerStaticResource,
bool(const std::string &static_resource_name, const std::string &static_resource_path)
bool(const std::string &static_resource_name,
const std::string &static_resource_path,
bool overwrite_if_exists
)
);
MOCK_METHOD2(
registerStaticResourceByContent,
bool(const std::string &resource_name, const std::string &file_content)
);
};

View File

@@ -14,7 +14,7 @@
#ifndef __NGINX_INTAKER_METRIC_H__
#define __NGINX_INTAKER_METRIC_H__
#include "nginx_attachment_common.h"
#include "nano_attachment_common.h"
#include "generic_metric.h"
#include "cpu/cpu_metric.h"
@@ -26,11 +26,11 @@ public:
void resetAllCounters();
ngx_http_plugin_metric_type_e EnumOfIndex(int i);
AttachmentMetricType EnumOfIndex(int i);
void addPluginMetricCounter(const ngx_http_cp_metric_data_t *recieved_metric_data);
void addPluginMetricCounter(const NanoHttpMetricData *recieved_metric_data);
uint64_t getPluginMetricCounter(ngx_http_plugin_metric_type_e _verdict) const;
uint64_t getPluginMetricCounter(AttachmentMetricType _verdict) const;
void notifyCPU() const { cpu_event.notify(); }

View File

@@ -120,6 +120,7 @@ public:
const std::vector<RateLimitRule> & getRateLimitRules() const { return rate_limit_rules; }
const RateLimitAction & getRateLimitMode() const { return mode; }
const std::string & getWebUserResponse() const { return web_user_response; }
RateLimitRule generateSiblingRateLimitRule(const RateLimitRule &rule);
@@ -150,6 +151,8 @@ public:
static bool isActive() { return is_active; }
void setWebUserResponse(const std::string& response_id) { web_user_response = response_id; }
static const std::map<RateLimitAction, std::string> rate_limit_action_to_string;
static const std::map<std::string, RateLimitAction> rate_limit_string_to_action;
@@ -160,6 +163,7 @@ private:
static bool is_active;
RateLimitAction mode;
std::vector<RateLimitRule> rate_limit_rules;
std::string web_user_response;
};
#endif // __RATE_LIMIT_CONFIG_H__

View File

@@ -44,6 +44,7 @@ static const std::string default_syslog_socket_address = "127.0.0.1:1514";
static const std::string rpm_full_load_path = "/tmp/rpm_full_load";
static const std::string rpm_partial_load_path = "/tmp/rpm_partial_load";
static const std::string first_rpm_policy_load_path = "/tmp/first_rpm_policy_load";
static const std::string readiness_file_path = "/tmp/readiness";
static const int default_port = 5555;

View File

@@ -31,7 +31,6 @@ public:
std::vector<std::string> getHeaderValuesFromConfig(const std::string &header_key) const;
void setXFFValuesToOpaqueCtx(const HttpHeader &header, ExtractType type) const;
void setWafTagValuesToOpaqueCtx(const HttpHeader &header) const;
private:
class UsersIdentifiersConfig
{