Feb 10 2025 dev (#255)

* sync code

* sync code

* code sync

* code sync

---------

Co-authored-by: Ned Wright <nedwright@proton.me>
Co-authored-by: Daniel Eisenberg <danielei@checkpoint.com>
This commit is contained in:
Daniel-Eisenberg
2025-02-12 10:56:44 +02:00
committed by GitHub
parent 81433bac25
commit 4ddcd2462a
75 changed files with 1540 additions and 258 deletions

View File

@@ -91,6 +91,7 @@ add_library(waap_clib
ParserScreenedJson.cc
ParserBinaryFile.cc
RegexComparator.cc
RequestsMonitor.cc
)
add_definitions("-Wno-unused-function")

View File

@@ -0,0 +1,158 @@
#include "RequestsMonitor.h"
#include "waap.h"
#include "SyncLearningNotification.h"
#include "report_messaging.h"
#include "customized_cereal_map.h"
USE_DEBUG_FLAG(D_WAAP_CONFIDENCE_CALCULATOR);
using namespace std;
SourcesRequestMonitor::SourcesRequestMonitor(
const string& filePath,
const string& remotePath,
const string& assetId,
const string& owner) :
SerializeToLocalAndRemoteSyncBase(
chrono::minutes(10),
chrono::seconds(30),
filePath,
remotePath != "" ? remotePath + "/Monitor" : remotePath,
assetId,
owner
), m_sourcesRequests()
{
}
SourcesRequestMonitor::~SourcesRequestMonitor()
{
}
void SourcesRequestMonitor::syncWorker()
{
dbgInfo(D_WAAP_CONFIDENCE_CALCULATOR) << "Running the sync worker for assetId='" << m_assetId << "', owner='" <<
m_owner << "'";
incrementIntervalsCount();
OrchestrationMode mode = Singleton::exists<I_AgentDetails>() ?
Singleton::Consume<I_AgentDetails>::by<WaapComponent>()->getOrchestrationMode() : OrchestrationMode::ONLINE;
bool enabled = getProfileAgentSettingWithDefault<bool>(false, "appsec.sourceRequestsMonitor.enabled");
if (mode == OrchestrationMode::OFFLINE || !enabled || isBase() || !postData()) {
dbgInfo(D_WAAP_CONFIDENCE_CALCULATOR)
<< "Did not report data. for asset: "
<< m_assetId
<< " Remote URL: "
<< m_remotePath
<< " is enabled: "
<< to_string(enabled)
<< ", mode: " << int(mode);
return;
}
dbgTrace(D_WAAP_CONFIDENCE_CALCULATOR) << "Waiting for all agents to post their data";
waitSync();
if (mode == OrchestrationMode::HYBRID) {
dbgDebug(D_WAAP_CONFIDENCE_CALCULATOR) << "detected running in standalone mode. not sending sync notification";
} else {
SyncLearningNotificationObject syncNotification(m_assetId, "Monitor", getWindowId());
dbgDebug(D_WAAP_CONFIDENCE_CALCULATOR) << "sending sync notification: " << syncNotification;
ReportMessaging(
"sync notification for '" + m_assetId + "'",
ReportIS::AudienceTeam::WAAP,
syncNotification,
MessageCategory::GENERIC,
ReportIS::Tags::WAF,
ReportIS::Notification::SYNC_LEARNING
);
}
}
void SourcesRequestMonitor::logSourceHit(const string& source)
{
m_sourcesRequests[chrono::duration_cast<chrono::minutes>(
Singleton::Consume<I_TimeGet>::by<WaapComponent>()->getWalltime()
).count()][source]++;
}
// LCOV_EXCL_START Reason: internal functions not used
void SourcesRequestMonitor::pullData(const vector<string> &data)
{
// not used. report only
}
void SourcesRequestMonitor::processData()
{
// not used. report only
}
void SourcesRequestMonitor::postProcessedData()
{
// not used. report only
}
void SourcesRequestMonitor::pullProcessedData(const vector<string> &data)
{
// not used. report only
}
void SourcesRequestMonitor::updateState(const vector<string> &data)
{
// not used. report only
}
// LCOV_EXCL_STOP
typedef map<string, map<string, size_t>> MonitorJsonData;
class SourcesRequestsReport : public RestGetFile
{
public:
SourcesRequestsReport(MonitorData& _sourcesRequests, const string& _agentId)
: sourcesRequests(), agentId(_agentId)
{
MonitorJsonData montiorData;
for (const auto& window : _sourcesRequests) {
for (const auto& source : window.second) {
montiorData[to_string(window.first)][source.first] = source.second;
}
}
sourcesRequests = montiorData;
}
private:
C2S_PARAM(MonitorJsonData, sourcesRequests);
C2S_PARAM(string, agentId);
};
bool SourcesRequestMonitor::postData()
{
dbgInfo(D_WAAP_CONFIDENCE_CALCULATOR) << "Sending the data to remote";
// send collected data to remote and clear the local data
string url = getPostDataUrl();
string agentId = Singleton::Consume<I_AgentDetails>::by<WaapComponent>()->getAgentId();
SourcesRequestsReport currentWindow(m_sourcesRequests, agentId);
bool ok = sendNoReplyObjectWithRetry(currentWindow,
HTTPMethod::PUT,
url);
if (!ok) {
dbgError(D_WAAP_CONFIDENCE_CALCULATOR) << "Failed to post collected data to: " << url;
}
dbgInfo(D_WAAP_CONFIDENCE_CALCULATOR) << "Data sent to remote: " << ok;
m_sourcesRequests.clear();
return ok;
}
void SourcesRequestMonitor::serialize(ostream& stream)
{
cereal::JSONOutputArchive archive(stream);
archive(m_sourcesRequests);
}
void SourcesRequestMonitor::deserialize(istream& stream)
{
cereal::JSONInputArchive archive(stream);
archive(m_sourcesRequests);
}

View File

@@ -0,0 +1,33 @@
#ifndef __REQUESTS_MONITOR_H__
#define __REQUESTS_MONITOR_H__
#include "i_serialize.h"
typedef std::map<uint64_t, std::map<std::string, size_t>> MonitorData;
class SourcesRequestMonitor : public SerializeToLocalAndRemoteSyncBase
{
public:
SourcesRequestMonitor(
const std::string& filePath,
const std::string& remotePath,
const std::string& assetId,
const std::string& owner);
virtual ~SourcesRequestMonitor();
virtual void syncWorker() override;
void logSourceHit(const std::string& source);
protected:
virtual void pullData(const std::vector<std::string> &data) override;
virtual void processData() override;
virtual void postProcessedData() override;
virtual void pullProcessedData(const std::vector<std::string> &data) override;
virtual void updateState(const std::vector<std::string> &data) override;
virtual bool postData() override;
void serialize(std::ostream& stream);
void deserialize(std::istream& stream);
private:
// map of sources and their requests per minute (UNIX)
MonitorData m_sourcesRequests;
};
#endif // __REQUESTS_MONITOR_H__

View File

@@ -407,6 +407,7 @@ SerializeToLocalAndRemoteSyncBase::SerializeToLocalAndRemoteSyncBase(
m_remotePath(replaceAllCopy(remotePath, "//", "/")),
m_interval(0),
m_owner(owner),
m_assetId(replaceAllCopy(assetId, "/", "")),
m_pMainLoop(nullptr),
m_waitForSync(waitForSync),
m_workerRoutineId(0),
@@ -414,7 +415,6 @@ SerializeToLocalAndRemoteSyncBase::SerializeToLocalAndRemoteSyncBase(
m_windowsCount(0),
m_intervalsCounter(0),
m_remoteSyncEnabled(true),
m_assetId(replaceAllCopy(assetId, "/", "")),
m_isAssetIdUuid(Waap::Util::isUuid(assetId)),
m_shared_storage_host(genError("not set")),
m_learning_host(genError("not set"))
@@ -469,6 +469,15 @@ bool SerializeToLocalAndRemoteSyncBase::isBase()
return m_remotePath == "";
}
void SerializeToLocalAndRemoteSyncBase::waitSync()
{
if (m_pMainLoop == nullptr)
{
return;
}
m_pMainLoop->yield(m_waitForSync);
}
string SerializeToLocalAndRemoteSyncBase::getUri()
{
static const string hybridModeUri = "/api";
@@ -484,6 +493,11 @@ size_t SerializeToLocalAndRemoteSyncBase::getIntervalsCount()
return m_intervalsCounter;
}
void SerializeToLocalAndRemoteSyncBase::incrementIntervalsCount()
{
m_intervalsCounter++;
}
SerializeToLocalAndRemoteSyncBase::~SerializeToLocalAndRemoteSyncBase()
{
@@ -659,7 +673,7 @@ void SerializeToLocalAndRemoteSyncBase::syncWorker()
{
dbgInfo(D_WAAP_CONFIDENCE_CALCULATOR) << "Running the sync worker for assetId='" << m_assetId << "', owner='" <<
m_owner << "'" << " last modified state: " << m_lastProcessedModified;
m_intervalsCounter++;
incrementIntervalsCount();
OrchestrationMode mode = Singleton::exists<I_AgentDetails>() ?
Singleton::Consume<I_AgentDetails>::by<WaapComponent>()->getOrchestrationMode() : OrchestrationMode::ONLINE;
@@ -678,7 +692,7 @@ void SerializeToLocalAndRemoteSyncBase::syncWorker()
}
dbgTrace(D_WAAP_CONFIDENCE_CALCULATOR) << "Waiting for all agents to post their data";
m_pMainLoop->yield(m_waitForSync);
waitSync();
// check if learning service is operational
if (m_lastProcessedModified == "")
{

View File

@@ -33,6 +33,7 @@ WaapTelemetryBase::sendLog(const LogRest &metric_client_rest) const
OrchestrationMode mode = Singleton::Consume<I_AgentDetails>::by<GenericMetric>()->getOrchestrationMode();
GenericMetric::sendLog(metric_client_rest);
dbgTrace(D_WAAP) << "Waap telemetry log sent: " << metric_client_rest.genJson().unpack();
if (mode == OrchestrationMode::ONLINE) {
return;
@@ -79,7 +80,16 @@ void
WaapTelemetrics::updateMetrics(const string &asset_id, const DecisionTelemetryData &data)
{
initMetrics();
requests.report(1);
auto is_keep_alive_ctx = Singleton::Consume<I_Environment>::by<GenericMetric>()->get<bool>(
"keep_alive_request_ctx"
);
if (!is_keep_alive_ctx.ok() || !*is_keep_alive_ctx) {
requests.report(1);
} else {
dbgTrace(D_WAAP) << "Not increasing the number of requests due to keep alive";
}
if (sources_seen.find(data.source) == sources_seen.end()) {
if (sources.getCounter() == 0) sources_seen.clear();
sources_seen.insert(data.source);
@@ -274,7 +284,9 @@ WaapMetricWrapper::upon(const WaapTelemetryEvent &event)
ReportIS::IssuingEngine::AGENT_CORE,
chrono::minutes(LOGGING_INTERVAL_IN_MINUTES),
true,
ReportIS::Audience::INTERNAL
ReportIS::Audience::INTERNAL,
false,
asset_id
);
metrics[asset_id]->registerListener();
}
@@ -286,7 +298,9 @@ WaapMetricWrapper::upon(const WaapTelemetryEvent &event)
ReportIS::IssuingEngine::AGENT_CORE,
chrono::minutes(LOGGING_INTERVAL_IN_MINUTES),
true,
ReportIS::Audience::INTERNAL
ReportIS::Audience::INTERNAL,
false,
asset_id
);
attack_types[asset_id]->registerListener();
}

View File

@@ -135,6 +135,7 @@ WaapAssetState::WaapAssetState(std::shared_ptr<Signatures> signatures,
m_Signatures(signatures),
m_waapDataFileName(waapDataFileName),
m_assetId(assetId),
m_requestsMonitor(nullptr),
scoreBuilder(this),
m_rateLimitingState(nullptr),
m_errorLimitingState(nullptr),
@@ -152,10 +153,14 @@ WaapAssetState::WaapAssetState(std::shared_ptr<Signatures> signatures,
I_AgentDetails* agentDetails = Singleton::Consume<I_AgentDetails>::by<WaapComponent>();
std::string path = agentDetails->getTenantId() + "/" + assetId;
m_filtersMngr = std::make_shared<IndicatorsFiltersManager>(path, assetId, this);
m_requestsMonitor = std::make_shared<SourcesRequestMonitor>
(getWaapDataDir() + "/monitor.data", path, assetId, "State");
}
else
{
m_filtersMngr = std::make_shared<IndicatorsFiltersManager>("", "", this);
m_requestsMonitor = std::make_shared<SourcesRequestMonitor>
(getWaapDataDir() + "/monitor.data", "", assetId, "State");
}
// Load keyword scores - copy from ScoreBuilder
updateScores();

View File

@@ -33,6 +33,7 @@
#include "KeywordTypeValidator.h"
#include "ScanResult.h"
#include "WaapSampleValue.h"
#include "RequestsMonitor.h"
enum space_stage {SPACE_SYNBOL, BR_SYMBOL, BN_SYMBOL, BRN_SEQUENCE, BNR_SEQUENCE, NO_SPACES};
@@ -67,6 +68,8 @@ public:
const std::string m_assetId;
std::shared_ptr<SourcesRequestMonitor> m_requestsMonitor;
ScoreBuilder scoreBuilder;
std::shared_ptr<Waap::RateLimiting::State> m_rateLimitingState;
std::shared_ptr<Waap::RateLimiting::State> m_errorLimitingState;
@@ -90,6 +93,7 @@ public:
void logIndicatorsInFilters(const std::string &param, Waap::Keywords::KeywordsSet& keywords,
IWaf2Transaction* pTransaction);
void logParamHit(Waf2ScanResult& res, IWaf2Transaction* pTransaction);
void logSourceHit(const std::string& source);
void filterKeywords(const std::string &param, Waap::Keywords::KeywordsSet& keywords,
std::vector<std::string>& filteredKeywords);
void clearFilterVerbose();

View File

@@ -329,14 +329,37 @@ const std::string& WaapConfigBase::get_AssetName() const
return m_assetName;
}
const std::string& WaapConfigBase::get_PracticeId() const
const std::string& WaapConfigBase::get_PracticeIdByPactice(DecisionType practiceType) const
{
return m_practiceId;
switch (practiceType)
{
case DecisionType::AUTONOMOUS_SECURITY_DECISION:
return m_practiceId;
default:
dbgError(D_WAAP)
<< "Can't find practice type for practice ID by practice: "
<< practiceType
<< ", return web app practice ID";
return m_practiceId;
}
}
const std::string& WaapConfigBase::get_PracticeName() const
const std::string& WaapConfigBase::get_PracticeNameByPactice(DecisionType practiceType) const
{
return m_practiceName;
switch (practiceType)
{
case DecisionType::AUTONOMOUS_SECURITY_DECISION:
return m_practiceName;
default:
dbgError(D_WAAP)
<< "Can't find practice type for practice name by practice: "
<< practiceType
<< ", return web app practice name";
return m_practiceName;
}
}
const std::string& WaapConfigBase::get_RuleId() const

View File

@@ -39,8 +39,8 @@ public:
virtual const std::string& get_AssetId() const;
virtual const std::string& get_AssetName() const;
virtual const BlockingLevel& get_BlockingLevel() const;
virtual const std::string& get_PracticeId() const;
virtual const std::string& get_PracticeName() const;
virtual const std::string& get_PracticeIdByPactice(DecisionType practiceType) const;
virtual const std::string& get_PracticeNameByPactice(DecisionType practiceType) const;
virtual const std::string& get_RuleId() const;
virtual const std::string& get_RuleName() const;
virtual const bool& get_WebAttackMitigation() const;

View File

@@ -89,7 +89,7 @@ bool WaapOverrideFunctor::operator()(
}
else if (tagLower == "url") {
for (const auto &rx : rxes) {
if (W2T_REGX_MATCH(getUriStr)) return true;
if (W2T_REGX_MATCH(getUri)) return true;
}
return false;
}

View File

@@ -23,6 +23,7 @@ ResponseInjectReasons::ResponseInjectReasons()
:
csrf(false),
antibot(false),
captcha(false),
securityHeaders(false)
{
}
@@ -53,6 +54,13 @@ ResponseInjectReasons::setAntibot(bool flag)
antibot = flag;
}
void
ResponseInjectReasons::setCaptcha(bool flag)
{
dbgTrace(D_WAAP) << "Change ResponseInjectReasons(Captcha) " << captcha << " to " << flag;
captcha = flag;
}
void
ResponseInjectReasons::setCsrf(bool flag)
{
@@ -74,6 +82,13 @@ ResponseInjectReasons::shouldInjectAntibot() const
return antibot;
}
bool
ResponseInjectReasons::shouldInjectCaptcha() const
{
dbgTrace(D_WAAP) << "shouldInjectCaptcha():: " << captcha;
return captcha;
}
bool
ResponseInjectReasons::shouldInjectCsrf() const
{

View File

@@ -21,14 +21,17 @@ public:
void clear();
bool shouldInject() const;
void setAntibot(bool flag);
void setCaptcha(bool flag);
void setCsrf(bool flag);
void setSecurityHeaders(bool flag);
bool shouldInjectAntibot() const;
bool shouldInjectCaptcha() const;
bool shouldInjectCsrf() const;
bool shouldInjectSecurityHeaders() const;
private:
bool csrf;
bool antibot;
bool captcha;
bool securityHeaders;
};

View File

@@ -1098,6 +1098,7 @@ void Waf2Transaction::end_request_hdrs() {
// but the State itself is not needed now
Waap::Override::State overrideState = getOverrideState(m_siteConfig);
}
m_pWaapAssetState->m_requestsMonitor->logSourceHit(m_source_identifier);
IdentifiersEvent ids(m_source_identifier, m_pWaapAssetState->m_assetId);
ids.notify();
// Read relevant headers and extract meta information such as host name
@@ -1421,6 +1422,15 @@ Waf2Transaction::completeInjectionResponseBody(std::string& strInjection)
m_responseInjectReasons.setAntibot(false);
}
if(m_responseInjectReasons.shouldInjectCaptcha()) {
dbgTrace(D_WAAP_BOT_PROTECTION) <<
"Waf2Transaction::completeInjectionResponseBody(): Injecting data (captcha)";
//todo add captcha script
strInjection += "<script src=\"cp-cp.js\"></script>";
// No need to inject more than once
m_responseInjectReasons.setCaptcha(false);
}
if (m_responseInjectReasons.shouldInjectCsrf()) {
dbgTrace(D_WAAP) << "Waf2Transaction::completeInjectionResponseBody(): Injecting data (csrf)";
strInjection += "<script src=\"cp-csrf.js\"></script>";
@@ -1567,7 +1577,7 @@ Waf2Transaction::decideFinal(
dbgTrace(D_WAAP) << "Waf2Transaction::decideFinal(): got relevant API configuration from the I/S";
sitePolicy = &ngenAPIConfig;
m_overrideState = getOverrideState(sitePolicy);
shouldBlock = (getUserLimitVerdict() == ngx_http_cp_verdict_e::TRAFFIC_VERDICT_DROP);
}
else if (WaapConfigApplication::getWaapSiteConfig(ngenSiteConfig)) {
dbgTrace(D_WAAP) << "Waf2Transaction::decideFinal(): got relevant Application configuration from the I/S";
@@ -1646,7 +1656,9 @@ void Waf2Transaction::appendCommonLogFields(LogGen& waapLog,
const std::shared_ptr<Waap::Trigger::Log> &triggerLog,
bool shouldBlock,
const std::string& logOverride,
const std::string& incidentType) const
const std::string& incidentType,
const std::string& practiceID,
const std::string& practiceName) const
{
auto env = Singleton::Consume<I_Environment>::by<WaapComponent>();
auto active_id = env->get<std::string>("ActiveTenantId");
@@ -1737,8 +1749,8 @@ void Waf2Transaction::appendCommonLogFields(LogGen& waapLog,
waapLog << LogField("practiceType", "Threat Prevention");
waapLog << LogField("practiceSubType", m_siteConfig->get_PracticeSubType());
waapLog << LogField("ruleName", m_siteConfig->get_RuleName());
waapLog << LogField("practiceId", m_siteConfig->get_PracticeId());
waapLog << LogField("practiceName", m_siteConfig->get_PracticeName());
waapLog << LogField("practiceId", practiceID);
waapLog << LogField("practiceName", practiceName);
waapLog << LogField("waapIncidentType", incidentType);
// Registering this value would append the list of matched override IDs to the unified log
@@ -1805,8 +1817,8 @@ Waf2Transaction::sendLog()
telemetryData.source = getSourceIdentifier();
telemetryData.assetName = m_siteConfig->get_AssetName();
telemetryData.practiceId = m_siteConfig->get_PracticeId();
telemetryData.practiceName = m_siteConfig->get_PracticeName();
telemetryData.practiceId = m_siteConfig->get_PracticeIdByPactice(AUTONOMOUS_SECURITY_DECISION);
telemetryData.practiceName = m_siteConfig->get_PracticeNameByPactice(AUTONOMOUS_SECURITY_DECISION);
if (m_scanResult) {
telemetryData.attackTypes = m_scanResult->attack_types;
}
@@ -1947,7 +1959,11 @@ Waf2Transaction::sendLog()
shouldBlock);
LogGen& waap_log = logGenWrapper.getLogGen();
appendCommonLogFields(waap_log, triggerLog, shouldBlock, logOverride, incidentType);
appendCommonLogFields(
waap_log, triggerLog, shouldBlock, logOverride, incidentType,
m_siteConfig->get_PracticeIdByPactice(AUTONOMOUS_SECURITY_DECISION),
m_siteConfig->get_PracticeNameByPactice(AUTONOMOUS_SECURITY_DECISION)
);
waap_log << LogField("waapIncidentDetails", incidentDetails);
waap_log << LogField("eventConfidence", "High");
break;
@@ -1980,7 +1996,11 @@ Waf2Transaction::sendLog()
waap_log << LogField("waapFoundIndicators", getKeywordMatchesStr(), LogFieldOption::XORANDB64);
}
appendCommonLogFields(waap_log, triggerLog, shouldBlock, logOverride, incidentType);
appendCommonLogFields(
waap_log, triggerLog, shouldBlock, logOverride, incidentType,
m_siteConfig->get_PracticeIdByPactice(AUTONOMOUS_SECURITY_DECISION),
m_siteConfig->get_PracticeNameByPactice(AUTONOMOUS_SECURITY_DECISION)
);
waap_log << LogField("waapIncidentDetails", incidentDetails);
break;
@@ -1996,7 +2016,11 @@ Waf2Transaction::sendLog()
shouldBlock);
LogGen& waap_log = logGenWrapper.getLogGen();
appendCommonLogFields(waap_log, triggerLog, shouldBlock, logOverride, "Cross Site Request Forgery");
appendCommonLogFields(
waap_log, triggerLog, shouldBlock, logOverride, "Cross Site Request Forgery",
m_siteConfig->get_PracticeIdByPactice(AUTONOMOUS_SECURITY_DECISION),
m_siteConfig->get_PracticeNameByPactice(AUTONOMOUS_SECURITY_DECISION)
);
waap_log << LogField("waapIncidentDetails", "CSRF Attack discovered.");
break;
}
@@ -2177,14 +2201,13 @@ Waf2Transaction::decideAutonomousSecurity(
" effective overrides count: " << m_effectiveOverrideIds.size() <<
" learned overrides count: " << m_exceptionLearned.size();
bool log_all = false;
const std::shared_ptr<Waap::Trigger::Policy> triggerPolicy = sitePolicy.get_TriggerPolicy();
if (triggerPolicy) {
const std::shared_ptr<Waap::Trigger::Log> triggerLog = getTriggerLog(triggerPolicy);
if (triggerLog && triggerLog->webRequests) log_all = true;
}
if(decision->getThreatLevel() <= ThreatLevel::THREAT_INFO && !log_all) {
decision->setLog(false);
} else {

View File

@@ -247,7 +247,9 @@ private:
const std::shared_ptr<Waap::Trigger::Log> &triggerLog,
bool shouldBlock,
const std::string& logOverride,
const std::string& incidentType) const;
const std::string& incidentType,
const std::string& practiceID,
const std::string& practiceName) const;
std::string getUserReputationStr(double relativeReputation) const;
bool isTrustedSource() const;

View File

@@ -381,7 +381,11 @@ void Waf2Transaction::sendAutonomousSecurityLog(
waap_log << LogField("eventConfidence", confidence);
}
appendCommonLogFields(waap_log, triggerLog, shouldBlock, logOverride, attackTypes);
appendCommonLogFields(
waap_log, triggerLog, shouldBlock, logOverride, attackTypes,
m_siteConfig->get_PracticeIdByPactice(AUTONOMOUS_SECURITY_DECISION),
m_siteConfig->get_PracticeNameByPactice(AUTONOMOUS_SECURITY_DECISION)
);
std::string sampleString = getSample();
if (sampleString.length() > MAX_LOG_FIELD_SIZE) {