Merge pull request #263 from openappsec/Feb_27_2025-Dev

Feb 27 2025 dev
This commit is contained in:
Daniel-Eisenberg 2025-03-02 18:23:10 +02:00 committed by GitHub
commit bd35c421c6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 624 additions and 192 deletions

View File

@ -285,17 +285,21 @@ Maybe<string>
UsersAllIdentifiersConfig::parseXForwardedFor(const string &str, ExtractType type) const UsersAllIdentifiersConfig::parseXForwardedFor(const string &str, ExtractType type) const
{ {
vector<string> header_values = split(str); vector<string> header_values = split(str);
if (header_values.empty()) return genError("No IP found in the xff header list"); if (header_values.empty()) return genError("No IP found in the xff header list");
vector<string> xff_values = getHeaderValuesFromConfig("x-forwarded-for"); vector<string> xff_values = getHeaderValuesFromConfig("x-forwarded-for");
vector<CIDRSData> cidr_values(xff_values.begin(), xff_values.end()); vector<CIDRSData> cidr_values(xff_values.begin(), xff_values.end());
string last_valid_ip;
for (auto it = header_values.rbegin(); it != header_values.rend() - 1; ++it) { for (auto it = header_values.rbegin(); it != header_values.rend() - 1; ++it) {
if (!IPAddr::createIPAddr(*it).ok()) { if (!IPAddr::createIPAddr(*it).ok()) {
dbgWarning(D_NGINX_ATTACHMENT_PARSER) << "Invalid IP address found in the xff header IPs list: " << *it; dbgWarning(D_NGINX_ATTACHMENT_PARSER) << "Invalid IP address found in the xff header IPs list: " << *it;
return genError("Invalid IP address"); if (last_valid_ip.empty()) {
return genError("Invalid IP address");
}
return last_valid_ip;
} }
last_valid_ip = *it;
if (type == ExtractType::PROXYIP) continue; if (type == ExtractType::PROXYIP) continue;
if (!isIpTrusted(*it, cidr_values)) { if (!isIpTrusted(*it, cidr_values)) {
dbgDebug(D_NGINX_ATTACHMENT_PARSER) << "Found untrusted IP in the xff header IPs list: " << *it; dbgDebug(D_NGINX_ATTACHMENT_PARSER) << "Found untrusted IP in the xff header IPs list: " << *it;
@ -307,7 +311,10 @@ UsersAllIdentifiersConfig::parseXForwardedFor(const string &str, ExtractType typ
dbgWarning(D_NGINX_ATTACHMENT_PARSER) dbgWarning(D_NGINX_ATTACHMENT_PARSER)
<< "Invalid IP address found in the xff header IPs list: " << "Invalid IP address found in the xff header IPs list: "
<< header_values[0]; << header_values[0];
return genError("Invalid IP address"); if (last_valid_ip.empty()) {
return genError("No Valid Ip address was found");
}
return last_valid_ip;
} }
return header_values[0]; return header_values[0];

View File

@ -179,7 +179,7 @@ private:
Maybe<void> Maybe<void>
configureSyslog() configureSyslog()
{ {
if (!getProfileAgentSettingWithDefault<bool>(true, "centralNginxManagement.syslogEnabled")) { if (!getProfileAgentSettingWithDefault<bool>(false, "centralNginxManagement.syslogEnabled")) {
dbgTrace(D_NGINX_MANAGER) << "Syslog is disabled via settings"; dbgTrace(D_NGINX_MANAGER) << "Syslog is disabled via settings";
return {}; return {};
} }
@ -331,6 +331,8 @@ public:
logError("Could not reload central NGINX configuration. Error: " + reload_result.getErr()); logError("Could not reload central NGINX configuration. Error: " + reload_result.getErr());
return; return;
} }
logInfo("Central NGINX configuration has been successfully reloaded");
} }
void void
@ -351,11 +353,37 @@ private:
{ {
LogGen log( LogGen log(
error, error,
ReportIS::Level::ACTION,
ReportIS::Audience::SECURITY, ReportIS::Audience::SECURITY,
ReportIS::Severity::CRITICAL, ReportIS::Severity::CRITICAL,
ReportIS::Priority::HIGH, ReportIS::Priority::URGENT,
ReportIS::Tags::POLICY_INSTALLATION ReportIS::Tags::POLICY_INSTALLATION
); );
log.addToOrigin(LogField("eventTopic", "Central NGINX Management"));
log << LogField("notificationId", "4165c3b1-e9bc-44c3-888b-863e204c1bfb");
log << LogField(
"eventRemediation",
"Please verify your NGINX configuration and enforce policy again. "
"Contact Check Point support if the issue persists."
);
}
void
logInfo(const string &info)
{
LogGen log(
info,
ReportIS::Level::ACTION,
ReportIS::Audience::SECURITY,
ReportIS::Severity::INFO,
ReportIS::Priority::LOW,
ReportIS::Tags::POLICY_INSTALLATION
);
log.addToOrigin(LogField("eventTopic", "Central NGINX Management"));
log << LogField("notificationId", "4165c3b1-e9bc-44c3-888b-863e204c1bfb");
log << LogField("eventRemediation", "No action required");
} }
I_MainLoop *i_mainloop = nullptr; I_MainLoop *i_mainloop = nullptr;

View File

@ -80,7 +80,9 @@ DetailsResolver::Impl::getHostname()
Maybe<string> Maybe<string>
DetailsResolver::Impl::getPlatform() DetailsResolver::Impl::getPlatform()
{ {
#if defined(gaia) #if defined(gaia_arm)
return string("gaia_arm");
#elif defined(gaia)
return string("gaia"); return string("gaia");
#elif defined(arm32_rpi) #elif defined(arm32_rpi)
return string("glibc"); return string("glibc");

View File

@ -71,7 +71,18 @@ checkPepIdaIdnStatus(const string &command_output)
Maybe<string> Maybe<string>
getRequiredNanoServices(const string &command_output) getRequiredNanoServices(const string &command_output)
{ {
return command_output; string idaRequiredServices[2] = {"idaSaml", "idaIdn"};
string platform_str = "gaia";
#if defined(gaia_arm)
platform_str = "gaia_arm";
#endif // gaia_arm
string result = "";
for(const string &serv : idaRequiredServices) {
string add_service = serv + "_" + platform_str;
result = result + add_service + ";";
}
command_output.empty(); // overcome unused variable
return result;
} }
Maybe<string> Maybe<string>
@ -342,6 +353,28 @@ getSMCBasedMgmtName(const string &command_output)
return getAttr(command_output, "Mgmt object Name was not found"); return getAttr(command_output, "Mgmt object Name was not found");
} }
Maybe<string>
getSmbObjectUid(const string &command_output)
{
static const char centrally_managed_comd_output = '0';
if (command_output.empty() || command_output[0] != centrally_managed_comd_output) {
return genError("Object UUID was not found");
}
Maybe<string> obj_uuid = getAttrFromCpsdwanGetDataJson("uuid");
if (obj_uuid.ok()) {
return obj_uuid.unpack();
}
static const string obj_path = (getenv("FWDIR") ? string(getenv("FWDIR")) : "") + "/database/myown.C";
auto file_stream = std::make_shared<std::ifstream>(obj_path);
if (!file_stream->is_open()) {
return genError("Failed to open the object file");
}
return getMgmtObjAttr(file_stream, "uuid ");
}
Maybe<string> Maybe<string>
getSmbObjectName(const string &command_output) getSmbObjectName(const string &command_output)
{ {

View File

@ -42,11 +42,6 @@ SHELL_PRE_CMD("gunzip local.cfg", "gunzip -c $FWDIR/state/local/FW1/local.cfg.gz
#ifdef SHELL_CMD_HANDLER #ifdef SHELL_CMD_HANDLER
#if defined(gaia) || defined(smb) || defined(smb_thx_v3) || defined(smb_sve_v2) || defined(smb_mrv_v1) #if defined(gaia) || defined(smb) || defined(smb_thx_v3) || defined(smb_sve_v2) || defined(smb_mrv_v1)
SHELL_CMD_HANDLER("cpProductIntegrationMgmtObjectType", "cpprod_util CPPROD_IsMgmtMachine", getMgmtObjType) SHELL_CMD_HANDLER("cpProductIntegrationMgmtObjectType", "cpprod_util CPPROD_IsMgmtMachine", getMgmtObjType)
SHELL_CMD_HANDLER(
"cpProductIntegrationMgmtObjectUid",
"mgmt_cli --format json -r true show-session | jq -r '.[\"connected-server\"].uid'",
getMgmtObjUid
)
SHELL_CMD_HANDLER("prerequisitesForHorizonTelemetry", SHELL_CMD_HANDLER("prerequisitesForHorizonTelemetry",
"FS_PATH=<FILESYSTEM-PREFIX>; [ -f ${FS_PATH}/cp-nano-horizon-telemetry-prerequisites.log ] " "FS_PATH=<FILESYSTEM-PREFIX>; [ -f ${FS_PATH}/cp-nano-horizon-telemetry-prerequisites.log ] "
"&& head -1 ${FS_PATH}/cp-nano-horizon-telemetry-prerequisites.log || echo ''", "&& head -1 ${FS_PATH}/cp-nano-horizon-telemetry-prerequisites.log || echo ''",
@ -150,12 +145,17 @@ SHELL_CMD_HANDLER("hasSAMLSupportedBlade", "enabled_blades", checkSAMLSupportedB
SHELL_CMD_HANDLER("hasIDABlade", "enabled_blades", checkIDABlade) SHELL_CMD_HANDLER("hasIDABlade", "enabled_blades", checkIDABlade)
SHELL_CMD_HANDLER("hasSAMLPortal", "mpclient status nac", checkSAMLPortal) SHELL_CMD_HANDLER("hasSAMLPortal", "mpclient status nac", checkSAMLPortal)
SHELL_CMD_HANDLER("hasIdaIdnEnabled", "fw ctl get int nac_pep_identity_next_enabled", checkPepIdaIdnStatus) SHELL_CMD_HANDLER("hasIdaIdnEnabled", "fw ctl get int nac_pep_identity_next_enabled", checkPepIdaIdnStatus)
SHELL_CMD_HANDLER("requiredNanoServices", "echo 'idaSaml_gaia;idaIdn_gaia;'", getRequiredNanoServices) SHELL_CMD_HANDLER("requiredNanoServices", "echo ida", getRequiredNanoServices)
SHELL_CMD_HANDLER( SHELL_CMD_HANDLER(
"cpProductIntegrationMgmtObjectName", "cpProductIntegrationMgmtObjectName",
"mgmt_cli --format json -r true show-session | jq -r '.[\"connected-server\"].name'", "mgmt_cli --format json -r true show-session | jq -r '.[\"connected-server\"].name'",
getMgmtObjName getMgmtObjName
) )
SHELL_CMD_HANDLER(
"cpProductIntegrationMgmtObjectUid",
"mgmt_cli --format json -r true show-session | jq -r '.[\"connected-server\"].uid'",
getMgmtObjUid
)
SHELL_CMD_HANDLER( SHELL_CMD_HANDLER(
"cpProductIntegrationMgmtParentObjectName", "cpProductIntegrationMgmtParentObjectName",
"cat $FWDIR/database/myself_objects.C " "cat $FWDIR/database/myself_objects.C "
@ -227,6 +227,11 @@ SHELL_CMD_HANDLER(
"cpprod_util FwIsLocalMgmt", "cpprod_util FwIsLocalMgmt",
getSmbObjectName getSmbObjectName
) )
SHELL_CMD_HANDLER(
"cpProductIntegrationMgmtObjectUid",
"cpprod_util FwIsLocalMgmt",
getSmbObjectUid
)
SHELL_CMD_HANDLER( SHELL_CMD_HANDLER(
"Application Control", "Application Control",
"cat $FWDIR/conf/active_blades.txt | grep -o 'APCL [01]' | cut -d ' ' -f2", "cat $FWDIR/conf/active_blades.txt | grep -o 'APCL [01]' | cut -d ' ' -f2",

View File

@ -1470,9 +1470,10 @@ private:
string cc_opt; string cc_opt;
tie(config_opt, cc_opt, nginx_version) = nginx_data.unpack(); tie(config_opt, cc_opt, nginx_version) = nginx_data.unpack();
agent_data_report agent_data_report
<< make_pair("nginxVersion", nginx_version) << make_pair("attachmentVersion", "Legacy")
<< make_pair("configureOpt", config_opt) << make_pair("nginxVersion", nginx_version)
<< make_pair("extraCompilerOpt", cc_opt); << make_pair("configureOpt", config_opt)
<< make_pair("extraCompilerOpt", cc_opt);
} else { } else {
dbgDebug(D_ORCHESTRATOR) << nginx_data.getErr(); dbgDebug(D_ORCHESTRATOR) << nginx_data.getErr();
} }
@ -1528,7 +1529,7 @@ private:
} else { } else {
curr_agent_data_report = agent_data_report; curr_agent_data_report = agent_data_report;
curr_agent_data_report.disableReportSending(); curr_agent_data_report.disableReportSending();
agent_data_report << AgentReportFieldWithLabel("report_timestamp", i_time->getWalltimeStr()); agent_data_report << AgentReportFieldWithLabel("timestamp", i_time->getWalltimeStr());
} }
} }

View File

@ -208,6 +208,7 @@ ServiceDetails::sendNewConfigurations(int configuration_id, const string &policy
MessageMetadata new_config_req_md("127.0.0.1", service_port); MessageMetadata new_config_req_md("127.0.0.1", service_port);
new_config_req_md.setConnectioFlag(MessageConnectionConfig::ONE_TIME_CONN); new_config_req_md.setConnectioFlag(MessageConnectionConfig::ONE_TIME_CONN);
new_config_req_md.setConnectioFlag(MessageConnectionConfig::UNSECURE_CONN); new_config_req_md.setConnectioFlag(MessageConnectionConfig::UNSECURE_CONN);
new_config_req_md.setSuspension(false);
auto res = messaging->sendSyncMessage( auto res = messaging->sendSyncMessage(
HTTPMethod::POST, HTTPMethod::POST,
"/set-new-configuration", "/set-new-configuration",

View File

@ -113,6 +113,9 @@ DeepParser::onKv(const char *k, size_t k_len, const char *v, size_t v_len, int f
<< parser_depth << parser_depth
<< " v_len = " << " v_len = "
<< v_len; << v_len;
dbgTrace(D_WAAP_DEEP_PARSER) << m_key;
// Decide whether to push/pop the value in the keystack. // Decide whether to push/pop the value in the keystack.
bool shouldUpdateKeyStack = (flags & BUFFERED_RECEIVER_F_UNNAMED) == 0; bool shouldUpdateKeyStack = (flags & BUFFERED_RECEIVER_F_UNNAMED) == 0;
@ -275,13 +278,23 @@ DeepParser::onKv(const char *k, size_t k_len, const char *v, size_t v_len, int f
// Detect and decode potential base64 chunks in the value before further processing // Detect and decode potential base64 chunks in the value before further processing
bool base64ParamFound = false; bool base64ParamFound = false;
size_t base64_offset = 0;
Waap::Util::BinaryFileType base64BinaryFileType = Waap::Util::BinaryFileType::FILE_TYPE_NONE; Waap::Util::BinaryFileType base64BinaryFileType = Waap::Util::BinaryFileType::FILE_TYPE_NONE;
if (m_depth == 1 && flags == BUFFERED_RECEIVER_F_MIDDLE && m_key.depth() == 1 && m_key.first() != "#base64"){ if (m_depth == 1 && flags == BUFFERED_RECEIVER_F_MIDDLE && m_key.depth() == 1 && m_key.first() != "#base64"){
dbgTrace(D_WAAP_DEEP_PARSER) << " === will not check base64 since prev data block was not b64-encoded ==="; dbgTrace(D_WAAP_DEEP_PARSER) << " === will not check base64 since prev data block was not b64-encoded ===";
} else { } else {
dbgTrace(D_WAAP_DEEP_PARSER) << " ===Processing potential base64==="; dbgTrace(D_WAAP_DEEP_PARSER) << " ===Processing potential base64===";
if (isUrlPayload && m_depth == 1 && cur_val[0] == '/') {
dbgTrace(D_WAAP_DEEP_PARSER) << "removing leading '/' from URL param value";
base64_offset = 1;
}
std::string decoded_val, decoded_key; std::string decoded_val, decoded_key;
base64_variants base64_status = Waap::Util::b64Test(cur_val, decoded_key, decoded_val, base64BinaryFileType); base64_variants base64_status = Waap::Util::b64Test(
cur_val,
decoded_key,
decoded_val,
base64BinaryFileType,
base64_offset);
dbgTrace(D_WAAP_DEEP_PARSER) dbgTrace(D_WAAP_DEEP_PARSER)
<< " status = " << " status = "
@ -289,16 +302,50 @@ DeepParser::onKv(const char *k, size_t k_len, const char *v, size_t v_len, int f
<< " key = " << " key = "
<< decoded_key << decoded_key
<< " value = " << " value = "
<< decoded_val; << decoded_val
<< "m_depth = "
<< m_depth;
switch (base64_status) { switch (base64_status) {
case SINGLE_B64_CHUNK_CONVERT: case SINGLE_B64_CHUNK_CONVERT:
cur_val = decoded_val; if (base64_offset) {
cur_val = "/" + decoded_val;
} else {
cur_val = decoded_val;
}
base64ParamFound = true; base64ParamFound = true;
break; break;
case CONTINUE_DUAL_SCAN:
if (decoded_val.size() > 0) {
decoded_key = "#base64";
base64ParamFound = false;
if (base64_offset) {
decoded_val = "/" + decoded_val;
}
dbgTrace(D_WAAP_DEEP_PARSER) << m_key;
rc = onKv(
decoded_key.c_str(),
decoded_key.size(),
decoded_val.data(),
decoded_val.size(),
flags,
parser_depth
);
dbgTrace(D_WAAP_DEEP_PARSER) << "After call to onKv with suspected value rc = " << rc;
dbgTrace(D_WAAP_DEEP_PARSER) << m_key;
break;
} else {
dbgTrace(D_WAAP) << "base64 decode suspected and empty value. Skipping.";
base64ParamFound = false;
break;
}
break;
case KEY_VALUE_B64_PAIR: case KEY_VALUE_B64_PAIR:
// going deep with new pair in case value is not empty // going deep with new pair in case value is not empty
if (decoded_val.size() > 0) { if (decoded_val.size() > 0) {
if (base64_offset) {
decoded_key = "/" + decoded_key;
}
cur_val = decoded_val; cur_val = decoded_val;
base64ParamFound = true; base64ParamFound = true;
rc = onKv( rc = onKv(
@ -309,9 +356,13 @@ DeepParser::onKv(const char *k, size_t k_len, const char *v, size_t v_len, int f
flags, flags,
parser_depth parser_depth
); );
dbgTrace(D_WAAP_DEEP_PARSER) << "After call to onKv with suspected value rc = " << rc;
dbgTrace(D_WAAP_DEEP_PARSER) << " rc = " << rc; dbgTrace(D_WAAP_DEEP_PARSER) << m_key;
if (rc != CONTINUE_PARSING) { if (rc != CONTINUE_PARSING) {
if (shouldUpdateKeyStack) {
m_key.pop("deep parser key");
}
m_depth--;
return rc; return rc;
} }
} }
@ -323,7 +374,7 @@ DeepParser::onKv(const char *k, size_t k_len, const char *v, size_t v_len, int f
} }
if (base64ParamFound) { if (base64ParamFound) {
dbgTrace(D_WAAP_DEEP_PARSER) << "DeepParser::onKv(): pushing #base64 prefix to the key."; dbgTrace(D_WAAP_DEEP_PARSER) << "pushing #base64 prefix to the key.";
m_key.push("#base64", 7, false); m_key.push("#base64", 7, false);
} }
} }
@ -437,7 +488,6 @@ DeepParser::onKv(const char *k, size_t k_len, const char *v, size_t v_len, int f
if (shouldUpdateKeyStack) { if (shouldUpdateKeyStack) {
m_key.pop("deep parser key"); m_key.pop("deep parser key");
} }
m_depth--; m_depth--;
return rc; return rc;
} }
@ -587,7 +637,6 @@ DeepParser::parseBuffer(
if (shouldUpdateKeyStack) { if (shouldUpdateKeyStack) {
m_key.pop("deep parser key"); m_key.pop("deep parser key");
} }
m_depth--; m_depth--;
return DONE_PARSING; return DONE_PARSING;
} }
@ -909,7 +958,6 @@ DeepParser::parseAfterMisleadingMultipartBoundaryCleaned(
return rc; return rc;
} }
} }
return rc; return rc;
} }
@ -1081,7 +1129,7 @@ DeepParser::createInternalParser(
<< " isBodyPayload = " << " isBodyPayload = "
<< isBodyPayload; << isBodyPayload;
//Detect sensor_data format in body and just use dedicated filter for it //Detect sensor_data format in body and just use dedicated filter for it
if (m_depth == 1 if ((m_depth == 1)
&& isBodyPayload && isBodyPayload
&& Waap::Util::detectKnownSource(cur_val) == Waap::Util::SOURCE_TYPE_SENSOR_DATA) { && Waap::Util::detectKnownSource(cur_val) == Waap::Util::SOURCE_TYPE_SENSOR_DATA) {
m_parsersDeque.push_back( m_parsersDeque.push_back(

View File

@ -37,14 +37,24 @@ void KeyStack::push(const char* subkey, size_t subkeySize, bool countDepth) {
m_nameDepth++; m_nameDepth++;
} }
dbgTrace(D_WAAP) << "KeyStack(" << m_name << ")::push(): '" << std::string(subkey, subkeySize) << dbgTrace(D_WAAP)
"' => full_key='" << std::string(m_key.data(), m_key.size()) << "'"; << "KeyStack("
<< m_name
<< ")::push(): '"
<< std::string(subkey, subkeySize)
<< "' => full_key='"
<< std::string(m_key.data(), m_key.size())
<< "'";
} }
void KeyStack::pop(const char* log, bool countDepth) { void KeyStack::pop(const char* log, bool countDepth) {
// Keep depth balanced even if m_key[] buffer is full // Keep depth balanced even if m_key[] buffer is full
if (m_key.empty() || m_stack.empty()) { if (m_key.empty() || m_stack.empty()) {
dbgDebug(D_WAAP) << "KeyStack(" << m_name << ")::pop(): [ERROR] ATTEMPT TO POP FROM EMPTY KEY STACK! " << log; dbgDebug(D_WAAP)
<< "KeyStack("
<< m_name
<< ")::pop(): [ERROR] ATTEMPT TO POP FROM EMPTY KEY STACK! "
<< log;
return; return;
} }
@ -55,6 +65,22 @@ void KeyStack::pop(const char* log, bool countDepth) {
// Remove last subkey. // Remove last subkey.
m_key.erase(m_stack.back()); m_key.erase(m_stack.back());
m_stack.pop_back(); m_stack.pop_back();
dbgTrace(D_WAAP) << "KeyStack(" << m_name << ")::pop(): full_key='" << dbgTrace(D_WAAP)
std::string(m_key.data(), (int)m_key.size()) << "': pop_key=" << log << "'"; << "KeyStack("
<< m_name
<< ")::pop(): full_key='"
<< std::string(m_key.data(), (int)m_key.size())
<< "': pop_key="
<< log
<< "'";
}
void KeyStack::print(std::ostream &os) const
{
os
<< "KeyStack("
<< m_name
<< ")::show(): full_key='"
<< std::string(m_key.data(), (int)m_key.size())
<< "'";
} }

View File

@ -28,6 +28,7 @@ public:
void pop(const char* log, bool countDepth=true); void pop(const char* log, bool countDepth=true);
bool empty() const { return m_key.empty(); } bool empty() const { return m_key.empty(); }
void clear() { m_key.clear(); m_stack.clear(); } void clear() { m_key.clear(); m_stack.clear(); }
void print(std::ostream &os) const;
size_t depth() const { return m_nameDepth; } size_t depth() const { return m_nameDepth; }
size_t size() const { size_t size() const {
return str().size(); return str().size();

View File

@ -111,8 +111,7 @@ int BufferedReceiver::onKvDone()
// This must be called even if m_value is empty in order to signal the BUFFERED_RECEIVER_F_LAST flag to the // This must be called even if m_value is empty in order to signal the BUFFERED_RECEIVER_F_LAST flag to the
// receiver! // receiver!
dbgTrace(D_WAAP_PARSER) dbgTrace(D_WAAP_PARSER)
<< " Call onKv on the remainder of the buffer not yet pushed to the receiver " << " Call onKv on the remainder of the buffer not yet pushed to the receiver calling onKv()";
<< "calling onKv()";
int rc = onKv(m_key.data(), m_key.size(), m_value.data(), m_value.size(), m_flags, m_parser_depth); int rc = onKv(m_key.data(), m_key.size(), m_value.data(), m_value.size(), m_flags, m_parser_depth);
// Reset the object's state to allow reuse for other parsers // Reset the object's state to allow reuse for other parsers

View File

@ -21,6 +21,7 @@ USE_DEBUG_FLAG(D_WAAP);
const std::string ParserPDF::m_parserName = "ParserPDF"; const std::string ParserPDF::m_parserName = "ParserPDF";
const char* PDF_TAIL = "%%EOF"; const char* PDF_TAIL = "%%EOF";
const size_t PDF_TAIL_LEN = 5;
ParserPDF::ParserPDF( ParserPDF::ParserPDF(
IParserStreamReceiver &receiver, IParserStreamReceiver &receiver,
@ -44,16 +45,21 @@ ParserPDF::push(const char *buf, size_t len)
<< "' len=" << "' len="
<< len; << len;
const char *c;
if (m_state == s_error) { if (m_state == s_error) {
return 0; return 0;
} }
if (len == 0)
{
dbgTrace(D_WAAP_PARSER_PDF) << "ParserPDF::push(): end of stream. m_state=" << m_state;
if (m_state == s_end) { if (len == 0) {
dbgTrace(D_WAAP_PARSER_PDF) << "ParserPDF::push(): end of stream. m_state=" << m_state;
if (m_state == s_body && m_tailOffset >= PDF_TAIL_LEN) {
if (m_receiver.onKey("PDF", 3) != 0) {
m_state = s_error;
return 0;
}
if (m_receiver.onValue("", 0) != 0) {
m_state = s_error;
return 0;
}
m_receiver.onKvDone(); m_receiver.onKvDone();
} else { } else {
m_state = s_error; m_state = s_error;
@ -61,38 +67,43 @@ ParserPDF::push(const char *buf, size_t len)
return 0; return 0;
} }
size_t start = (len > MAX_PDF_TAIL_LOOKUP) ? len - MAX_PDF_TAIL_LOOKUP : 0;
switch (m_state) { switch (m_state) {
case s_start: case s_start:
m_state = s_body; m_state = s_body;
CP_FALL_THROUGH; CP_FALL_THROUGH;
case s_body: case s_body:
{ for (size_t i = start; i < len; i++) {
size_t tail_lookup_offset = (len > MAX_PDF_TAIL_LOOKUP) ? len - MAX_PDF_TAIL_LOOKUP : 0;
c = strstr(buf + tail_lookup_offset, PDF_TAIL);
dbgTrace(D_WAAP_PARSER_PDF) dbgTrace(D_WAAP_PARSER_PDF)
<< "string to search: " << std::string(buf + tail_lookup_offset) << "ParserPDF::push(): m_tailOffset="
<< " c=" << c; << m_tailOffset
if (c) { << " buf[i]="
m_state = s_end; << buf[i];
CP_FALL_THROUGH; if (m_tailOffset <= PDF_TAIL_LEN - 1) {
if (buf[i] == PDF_TAIL[m_tailOffset]) {
m_tailOffset++;
} else {
m_tailOffset = 0;
}
} else { } else {
break; if (buf[i] == '\r' || buf[i] == '\n' || buf[i] == ' ' || buf[i] == 0) {
m_tailOffset++;
} else {
m_tailOffset = 0;
i--;
}
} }
} }
case s_end: dbgTrace(D_WAAP_PARSER_PDF)
if (m_receiver.onKey("PDF", 3) != 0) { << "ParserPDF::push()->s_body: m_tailOffset="
m_state = s_error; << m_tailOffset;
return 0;
}
if (m_receiver.onValue("", 0) != 0) {
m_state = s_error;
return 0;
}
break; break;
case s_error: case s_error:
break; break;
default: default:
dbgTrace(D_WAAP_PARSER_PDF) << "ParserPDF::push(): unknown state: " << m_state; dbgTrace(D_WAAP_PARSER_PDF)
<< "ParserPDF::push(): unknown state: "
<< m_state;
m_state = s_error; m_state = s_error;
return 0; return 0;
} }

View File

@ -34,7 +34,6 @@ private:
enum state { enum state {
s_start, s_start,
s_body, s_body,
s_end,
s_error s_error
}; };
@ -42,6 +41,7 @@ private:
enum state m_state; enum state m_state;
static const std::string m_parserName; static const std::string m_parserName;
size_t m_parser_depth; size_t m_parser_depth;
size_t m_tailOffset = 0;
}; };
#endif // __PARSER_PDF_H__ #endif // __PARSER_PDF_H__

View File

@ -617,6 +617,17 @@ void SerializeToLocalAndRemoteSyncBase::setInterval(ch::seconds newInterval)
bool SerializeToLocalAndRemoteSyncBase::localSyncAndProcess() bool SerializeToLocalAndRemoteSyncBase::localSyncAndProcess()
{ {
bool isBackupSyncEnabled = getProfileAgentSettingWithDefault<bool>(
true,
"appsecLearningSettings.backupLocalSync");
if (!isBackupSyncEnabled) {
dbgInfo(D_WAAP_CONFIDENCE_CALCULATOR) << "Local sync is disabled";
processData();
saveData();
return true;
}
RemoteFilesList rawDataFiles; RemoteFilesList rawDataFiles;
dbgTrace(D_WAAP_CONFIDENCE_CALCULATOR) << "Getting files of all agents"; dbgTrace(D_WAAP_CONFIDENCE_CALCULATOR) << "Getting files of all agents";

View File

@ -97,7 +97,9 @@ calcIndividualKeywords(
std::sort(keywords.begin(), keywords.end()); std::sort(keywords.begin(), keywords.end());
for (auto pKeyword = keywords.begin(); pKeyword != keywords.end(); ++pKeyword) { for (auto pKeyword = keywords.begin(); pKeyword != keywords.end(); ++pKeyword) {
addKeywordScore(scoreBuilder, poolName, *pKeyword, 2.0f, 0.3f, scoresArray, coefArray); addKeywordScore(
scoreBuilder, poolName, *pKeyword, DEFAULT_KEYWORD_SCORE, DEFAULT_KEYWORD_COEF, scoresArray, coefArray
);
} }
} }
@ -112,8 +114,6 @@ calcCombinations(
std::vector<std::string>& keyword_combinations) std::vector<std::string>& keyword_combinations)
{ {
keyword_combinations.clear(); keyword_combinations.clear();
static const double max_combi_score = 1.0f;
double default_coef = 0.8f;
for (size_t i = 0; i < keyword_matches.size(); ++i) { for (size_t i = 0; i < keyword_matches.size(); ++i) {
std::vector<std::string> combinations; std::vector<std::string> combinations;
@ -137,8 +137,10 @@ calcCombinations(
default_score += scoreBuilder.getSnapshotKeywordScore(*it, 0.0f, poolName); default_score += scoreBuilder.getSnapshotKeywordScore(*it, 0.0f, poolName);
} }
// set default combination score to be the sum of its keywords, bounded by 1 // set default combination score to be the sum of its keywords, bounded by 1
default_score = std::min(default_score, max_combi_score); default_score = std::min(default_score, DEFAULT_COMBI_SCORE);
addKeywordScore(scoreBuilder, poolName, combination, default_score, default_coef, scoresArray, coefArray); addKeywordScore(
scoreBuilder, poolName, combination, default_score, DEFAULT_COMBI_COEF, scoresArray, coefArray
);
keyword_combinations.push_back(combination); keyword_combinations.push_back(combination);
} }
} }
@ -155,7 +157,7 @@ calcArrayScore(std::vector<double>& scoreArray)
// *pScore is always positive and there's a +10 offset // *pScore is always positive and there's a +10 offset
score = 10.0f - left * 10.0f / divisor; score = 10.0f - left * 10.0f / divisor;
} }
dbgTrace(D_WAAP_SCORE_BUILDER) << "calculated score: " << score; dbgDebug(D_WAAP_SCORE_BUILDER) << "calculated score: " << score;
return score; return score;
} }
@ -171,7 +173,9 @@ calcLogisticRegressionScore(std::vector<double> &coefArray, double intercept, do
} }
// Apply the expit function to the log-odds to obtain the probability, // Apply the expit function to the log-odds to obtain the probability,
// and multiply by 10 to obtain a 'score' in the range [0, 10] // and multiply by 10 to obtain a 'score' in the range [0, 10]
return 1.0f / (1.0f + exp(-log_odds)) * 10.0f; double score = 1.0f / (1.0f + exp(-log_odds)) * 10.0f;
dbgDebug(D_WAAP_SCORE_BUILDER) << "calculated score (log_odds): " << score << " (" << log_odds << ")";
return score;
} }
} }

View File

@ -32,6 +32,11 @@ struct ModelLoggingSettings {
bool logToStream; bool logToStream;
}; };
static const double DEFAULT_KEYWORD_COEF = 0.3f;
static const double DEFAULT_KEYWORD_SCORE = 2.0f;
static const double DEFAULT_COMBI_COEF = 0.8f;
static const double DEFAULT_COMBI_SCORE = 1.0f;
std::string getScorePoolNameByLocation(const std::string &location); std::string getScorePoolNameByLocation(const std::string &location);
std::string getOtherScorePoolName(); std::string getOtherScorePoolName();
ModelLoggingSettings getModelLoggingSettings(); ModelLoggingSettings getModelLoggingSettings();

View File

@ -40,6 +40,7 @@
#include "WaapOpenRedirectPolicy.h" #include "WaapOpenRedirectPolicy.h"
#include "WaapErrorDisclosurePolicy.h" #include "WaapErrorDisclosurePolicy.h"
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/regex.hpp>
#include "generic_rulebase/parameters_config.h" #include "generic_rulebase/parameters_config.h"
#include <iostream> #include <iostream>
#include "ParserDelimiter.h" #include "ParserDelimiter.h"
@ -1390,6 +1391,20 @@ Waf2Transaction::findHtmlTagToInject(const char* data, int data_len, int& pos)
size_t tagHistPosCheck = m_tagHistPos; size_t tagHistPosCheck = m_tagHistPos;
for (size_t i=0; i < tagSize; ++i) { for (size_t i=0; i < tagSize; ++i) {
if (tag[i] != ::tolower(m_tagHist[tagHistPosCheck])) { if (tag[i] != ::tolower(m_tagHist[tagHistPosCheck])) {
if (i == tagSize - 1 && m_tagHist[tagHistPosCheck] == ' ') {
// match regex on head element with attributes
string dataStr = Waap::Util::charToString(data + pos, data_len - pos);
dataStr = dataStr.substr(0, dataStr.find('>')+1);
tagMatches = NGEN::Regex::regexMatch(
__FILE__,
__LINE__,
dataStr,
boost::regex("(?:\\s+[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\\s*=\\s*(\"[^\"]*\"|'[^']*'|[^\\s\"'>]*))?)*\\s*>")
);
pos += dataStr.length() - 1;
dbgTrace(D_WAAP_BOT_PROTECTION) << "matching head element with attributes: " << dataStr << ". match: " << tagMatches;
break;
}
tagMatches = false; tagMatches = false;
break; break;
} }
@ -1403,12 +1418,8 @@ Waf2Transaction::findHtmlTagToInject(const char* data, int data_len, int& pos)
} }
} }
if(!headFound) dbgTrace(D_WAAP_BOT_PROTECTION) << "head element tag found: " << headFound;
{ return headFound;
return false;
}
return true;
} }
void void
@ -1577,6 +1588,8 @@ Waf2Transaction::decideFinal(
dbgTrace(D_WAAP) << "Waf2Transaction::decideFinal(): got relevant API configuration from the I/S"; dbgTrace(D_WAAP) << "Waf2Transaction::decideFinal(): got relevant API configuration from the I/S";
sitePolicy = &ngenAPIConfig; sitePolicy = &ngenAPIConfig;
m_overrideState = getOverrideState(sitePolicy); m_overrideState = getOverrideState(sitePolicy);
// User limits
shouldBlock = (getUserLimitVerdict() == ngx_http_cp_verdict_e::TRAFFIC_VERDICT_DROP); shouldBlock = (getUserLimitVerdict() == ngx_http_cp_verdict_e::TRAFFIC_VERDICT_DROP);
} }
else if (WaapConfigApplication::getWaapSiteConfig(ngenSiteConfig)) { else if (WaapConfigApplication::getWaapSiteConfig(ngenSiteConfig)) {
@ -2322,10 +2335,11 @@ bool Waf2Transaction::decideResponse()
bool bool
Waf2Transaction::reportScanResult(const Waf2ScanResult &res) { Waf2Transaction::reportScanResult(const Waf2ScanResult &res) {
if (get_ignoreScore() || (res.score >= SCORE_THRESHOLD && if ((get_ignoreScore() || res.score >= SCORE_THRESHOLD) &&
(m_scanResult == nullptr || res.score > m_scanResult->score))) (m_scanResult == nullptr || res.score > m_scanResult->score))
{ {
// Forget any previous scan result and replace with new dbgTrace(D_WAAP) << "Setting scan result. New score: " << res.score;
// Forget any previous scan result and replace wit, h new
delete m_scanResult; delete m_scanResult;
m_scanResult = new Waf2ScanResult(res); m_scanResult = new Waf2ScanResult(res);
return true; return true;

View File

@ -952,6 +952,145 @@ string filterUTF7(const string& text) {
return result; return result;
} }
// Decides the status of a Base64 decoded string based on various parameters.
// @param decoded The decoded string.
// @param entropy The entropy of the original encoded string.
// @param decoded_entropy The entropy of the decoded string.
// @param spacer_count The number of spacer characters in the decoded string.
// @param nonPrintableCharsCount The count of non-printable characters in the decoded string.
// @param clear_on_error Flag indicating whether to clear the decoded string on error.
// @param terminatorCharsSeen The number of terminator characters seen.
// @param called_with_prefix Flag indicating if the function was called with a prefix.
// @return The status of the Base64 decoding process.
//
// Idea:
// Check if input chunk should be replaced by decoded, suspected to be checked both as encoded and decoded
// or cleaned as binary data. Additional case - define as not base64 encoded.
// - in case decoded size less 5 - return invalid
// - check entropy delta based on that base64 encoded data has higher entropy than decoded, usually delta = 0.25
// - this check should rize suspect but cannot work vice versa
// check if decoded chunk has more than 10% of non-printable characters - this is supect for binary data encoded
// - if no suspect for binary data and entropy is suspected, check empiric conditions to decide if this binary data
// or invalid decoding
// - if suspect for binary data, first check is we have entropy suspection
// - if entropy is suspected and chunk is short and it have more than 25% of nonprintables, return invalid
// since this is not base64 encoded data
// - if entropy is not suspected and chunk is short and it have more than 50% of nonprintables, return invalid
// since this is not base64 encoded data
// - if entropy is suspected and chunk size is between 64-1024, perform additional empiric test
// This test will define if returm value should be treated as suspected or as binary data(cleared)
base64_decode_status decideStatusBase64Decoded(
string& decoded,
double entropy,
double decoded_entropy,
size_t spacer_count,
size_t nonPrintableCharsCount,
bool clear_on_error,
double terminatorCharsSeen,
bool called_with_prefix
)
{
base64_decode_status tmp_status = B64_DECODE_OK;
if (entropy - decoded_entropy + terminatorCharsSeen < BASE64_ENTROPY_THRESHOLD_DELTA) {
dbgTrace(D_WAAP_BASE64)
<< "The chunk is under suspect to be base64,"
<< "use dual processing because entropy delta is too low";
tmp_status = B64_DECODE_SUSPECTED;
}
bool empiric_condition = false;
if (decoded.size() >= 5) {
if (spacer_count > 1) {
nonPrintableCharsCount = nonPrintableCharsCount - spacer_count + 1;
}
dbgTrace(D_WAAP_BASE64)
<< "(before test for unprintables): decoded.size="
<< decoded.size()
<< ", nonPrintableCharsCount="
<< nonPrintableCharsCount
<< ", clear_on_error="
<< clear_on_error
<< ", called_with_prefix="
<< called_with_prefix;
if (nonPrintableCharsCount * 10 < decoded.size()) {
dbgTrace(D_WAAP_BASE64)
<< "(decode/replace due to small amount of nonprintables): will decide based on entropy values";
} else { // more than 10% of non-printable characters
dbgTrace(D_WAAP_BASE64) << "large amount of nonporintables";
if (tmp_status == B64_DECODE_SUSPECTED) {
// entropy - decoded_entropy + terminatorCharsSeen < 0.25
if (decoded.size() < 16 && nonPrintableCharsCount * 4 > decoded.size()) {
decoded.clear();
return B64_DECODE_INVALID;
}
dbgTrace(D_WAAP_BASE64)
<< "(large amount of nonporintables + entropy suspect), check emprirics because decoded."
<< " terminatorCharsSeen="
<< terminatorCharsSeen;
// empiric test based on investigation of real payloads
empiric_condition = entropy < decoded_entropy
&& entropy > BASE64_ENTROPY_BASE_THRESHOLD
&& decoded_entropy > BASE64_ENTROPY_DECODED_THRESHOLD
&& !called_with_prefix
&& decoded.size() > BASE64_MIN_SIZE_LIMIT
&& decoded.size() < BASE64_MAX_SIZE_LIMIT
&& terminatorCharsSeen != 0;
if (!empiric_condition) {
if (clear_on_error) decoded.clear();
return B64_DECODE_SUSPECTED;
} else {
if (clear_on_error) decoded.clear();
tmp_status = B64_DECODE_OK;
}
} else { // entropy - decoded_entropy + terminatorCharsSeen >= 0.25
// one more empiric based on uT and real payloads
if (decoded.size() < 16
&& nonPrintableCharsCount * 2 > decoded.size()
&& terminatorCharsSeen == 0) {
decoded.clear();
return B64_DECODE_INVALID;
}
dbgTrace(D_WAAP_BASE64)
<< "(delete as binary content) because decoded. Return B64_DECODE_INCOMPLETE";
if (clear_on_error) decoded.clear();
return B64_DECODE_INCOMPLETE;
}
} // less than 10% of non-printable characters
dbgTrace(D_WAAP_BASE64)
<< "After handling unprintables checking status";
if (tmp_status == B64_DECODE_OK) {
dbgTrace(D_WAAP_BASE64) << "replacing with decoded data, return B64_DECODE_OK";
return B64_DECODE_OK;
} else { // tmp_status == B64_DECODE_SUSPECTED, entropy - decoded_entropy + terminatorCharsSeen < 0.25
dbgTrace(D_WAAP_BASE64) << "Suspected due to entropy, making empiric test";
// and one more empiric test based on investigation of real payloads
empiric_condition = entropy < decoded_entropy
&& entropy > BASE64_ENTROPY_BASE_THRESHOLD
&& decoded_entropy > BASE64_ENTROPY_DECODED_THRESHOLD
&& !called_with_prefix
&& decoded.size() > BASE64_MIN_SIZE_LIMIT
&& decoded.size() < BASE64_MAX_SIZE_LIMIT;
if (empiric_condition) {
dbgTrace(D_WAAP_BASE64) << "Empiric test failed, non-base64 chunk, return B64_DECODE_INVALID";
decoded.clear();
return B64_DECODE_INVALID;
}
dbgTrace(D_WAAP_BASE64) << "Empiric test passed, return B64_DECODE_SUSPECTED";
return B64_DECODE_SUSPECTED;
}
return B64_DECODE_OK; // successfully decoded. Returns decoded data in "decoded" parameter
}
// If decoded size is too small - leave the encoded value (return false)
decoded.clear(); // discard partial data
dbgTrace(D_WAAP_BASE64)
<< "(leave as-is) because decoded too small. decoded.size="
<< decoded.size();
return B64_DECODE_INVALID;
}
// Attempts to validate and decode base64-encoded chunk. // Attempts to validate and decode base64-encoded chunk.
// Value is the full value inside which potential base64-encoded chunk was found, // Value is the full value inside which potential base64-encoded chunk was found,
// it and end point to start and end of that chunk. // it and end point to start and end of that chunk.
@ -980,18 +1119,28 @@ base64_decode_status decodeBase64Chunk(
uint32_t spacer_count = 0; uint32_t spacer_count = 0;
uint32_t length = end - it; uint32_t length = end - it;
dbgTrace(D_WAAP) << "decodeBase64Chunk: value='" << value << "' match='" << string(it, end) << "'"; dbgTrace(D_WAAP)
<< "value='"
<< value
<< "' match='"
<< string(it, end)
<< "' clear_on_error='"
<< clear_on_error
<< "' called_with_prefix='"
<< called_with_prefix
<< "'";
string::const_iterator begin = it; string::const_iterator begin = it;
// The encoded data length (without the "base64," prefix) should be exactly divisible by 4 // The encoded data length (without the "base64," prefix) should be exactly divisible by 4
// len % 4 is not 0 i.e. this is not base64 // len % 4 is not 0 i.e. this is not base64
if ((end - it) % 4 != 0) { if ((end - it) % 4 == 1) {
dbgTrace(D_WAAP_BASE64) << dbgTrace(D_WAAP_BASE64)
"b64DecodeChunk: (leave as-is) because encoded data length should be exactly divisible by 4."; << "(leave as-is) because encoded data length should not be <4*x + 1>.";
return B64_DECODE_INVALID; return B64_DECODE_INVALID;
} }
std::unordered_map<char, double> frequency; std::unordered_map<char, double> original_occurences_counter;
std::unordered_map<char, double> decoded_occurences_counter;
while (it != end) { while (it != end) {
unsigned char c = *it; unsigned char c = *it;
@ -999,9 +1148,8 @@ base64_decode_status decodeBase64Chunk(
if (terminatorCharsSeen) { if (terminatorCharsSeen) {
// terminator characters must all be '=', until end of match. // terminator characters must all be '=', until end of match.
if (c != '=') { if (c != '=') {
dbgTrace(D_WAAP_BASE64) << dbgTrace(D_WAAP_BASE64)
"decodeBase64Chunk: (leave as-is) because terminator characters must all be '='," << << "(leave as-is) because terminator characters must all be '=' until end of match.";
"until end of match.";
return B64_DECODE_INVALID; return B64_DECODE_INVALID;
} }
@ -1009,13 +1157,13 @@ base64_decode_status decodeBase64Chunk(
terminatorCharsSeen++; terminatorCharsSeen++;
if (terminatorCharsSeen > 2) { if (terminatorCharsSeen > 2) {
dbgTrace(D_WAAP_BASE64) << "decodeBase64Chunk: (leave as-is) because terminatorCharsSeen > 2"; dbgTrace(D_WAAP_BASE64) << "(leave as-is) because terminatorCharsSeen > 2";
return B64_DECODE_INVALID; return B64_DECODE_INVALID;
} }
// allow for more terminator characters // allow for more terminator characters
it++; it++;
frequency[c]++; original_occurences_counter[c]++;
continue; continue;
} }
@ -1040,12 +1188,18 @@ base64_decode_status decodeBase64Chunk(
// Start tracking terminator characters // Start tracking terminator characters
terminatorCharsSeen++; terminatorCharsSeen++;
it++; it++;
frequency[c]++; original_occurences_counter[c]++;
continue; continue;
} }
else { else {
dbgTrace(D_WAAP_BASE64) << "decodeBase64Chunk: (leave as-is) because of non-base64 character ('" << dbgTrace(D_WAAP_BASE64)
c << "', ASCII " << (unsigned int)c << ", offset " << (it-begin) << ")"; << "(leave as-is) because of non-base64 character ('"
<< c
<< "', ASCII "
<< (unsigned int)c
<< ", offset "
<< (it-begin)
<< ")";
return B64_DECODE_INVALID; // non-base64 character return B64_DECODE_INVALID; // non-base64 character
} }
@ -1068,18 +1222,19 @@ base64_decode_status decodeBase64Chunk(
} }
decoded += (char)code; decoded += (char)code;
decoded_occurences_counter[(char)code]++;
} }
it++; it++;
frequency[c]++; original_occurences_counter[c]++;
} }
// end of encoded sequence decoded. // end of encoded sequence decoded.
dbgTrace(D_WAAP_BASE64) dbgTrace(D_WAAP_BASE64)
<< "decodeBase64Chunk: decoded.size=" << "decoding done: decoded.size="
<< decoded.size() << decoded.size()
<< ", nonPrintableCharsCount=" << ", uncorrected nonPrintableCharsCount="
<< nonPrintableCharsCount << nonPrintableCharsCount
<< ", spacer_count = " << ", spacer_count = "
<< spacer_count << spacer_count
@ -1088,56 +1243,42 @@ base64_decode_status decodeBase64Chunk(
<< "; decoded='" << "; decoded='"
<< decoded << "'"; << decoded << "'";
// Check if entropy is correlates with b64 threshold (initially > 4.5) double entropy = 0;
if (!called_with_prefix) { double p = 0;
double entropy = 0; double decoded_entropy = 0;
double p = 0; for (const auto& pair : original_occurences_counter) {
for (const auto& pair : frequency) { p = pair.second / length;
p = pair.second / length; entropy -= p * std::log2(p);
entropy -= p * std::log2(p);
}
dbgTrace(D_WAAP_BASE64) << " ===b64Test===: base entropy = " << entropy << "length = " << length;
// Add short payload factor
if (length < 16)
entropy = entropy * 16 / length;
// Enforce tailoring '=' characters
entropy+=terminatorCharsSeen;
dbgTrace(D_WAAP_BASE64) << " ===b64Test===: corrected entropy = " << entropy << "length = " << length;
if (entropy <= base64_entropy_threshold) {
return B64_DECODE_INVALID;
}
} }
for (const auto &pair : decoded_occurences_counter) {
// Return success only if decoded.size>=5 and there are less than 10% of non-printable p = pair.second / decoded.size();
// characters in output. decoded_entropy -= p * std::log2(p);
if (decoded.size() >= 5) {
if (spacer_count > 1) {
nonPrintableCharsCount = nonPrintableCharsCount - spacer_count + 1;
}
if (nonPrintableCharsCount * 10 < decoded.size()) {
dbgTrace(D_WAAP_BASE64) << "decodeBase64Chunk: (decode/replace) decoded.size=" << decoded.size() <<
", nonPrintableCharsCount=" << nonPrintableCharsCount << ": replacing with decoded data";
}
else {
dbgTrace(D_WAAP_BASE64) << "decodeBase64Chunk: (delete) because decoded.size=" << decoded.size() <<
", nonPrintableCharsCount=" << nonPrintableCharsCount <<
", clear_on_error=" << clear_on_error;
if (clear_on_error) decoded.clear();
return B64_DECODE_INCOMPLETE;
}
dbgTrace(D_WAAP_BASE64) << "returning true: successfully decoded."
<< " Returns decoded data in \"decoded\" parameter";
return B64_DECODE_OK; // successfully decoded. Returns decoded data in "decoded" parameter
} }
dbgTrace(D_WAAP_BASE64)
<< "Base entropy = "
<< entropy
<< " Decoded_entropy = "
<< decoded_entropy
<< "length = "
<< length;
base64_decode_status return_status = decideStatusBase64Decoded(
decoded,
entropy,
decoded_entropy,
spacer_count,
nonPrintableCharsCount,
clear_on_error,
terminatorCharsSeen,
called_with_prefix
);
dbgTrace(D_WAAP_BASE64)
<< "After decideStatusBase64Decoded return_status="
<< return_status;
return return_status;
// If decoded size is too small - leave the encoded value (return false)
decoded.clear(); // discard partial data
dbgTrace(D_WAAP_BASE64) << "decodeBase64Chunk: (leave as-is) because decoded too small. decoded.size=" <<
decoded.size() <<
", nonPrintableCharsCount=" << nonPrintableCharsCount <<
", clear_on_error=" << clear_on_error;
return B64_DECODE_INVALID;
} }
// Attempts to detect and validate base64 chunk. // Attempts to detect and validate base64 chunk.
@ -1180,8 +1321,9 @@ b64DecodeChunk(
return false; return false;
} }
} }
base64_decode_status status = decodeBase64Chunk(value, it, end, decoded);
return decodeBase64Chunk(value, it, end, decoded) != B64_DECODE_INVALID; dbgTrace(D_WAAP_BASE64) << "b64DecodeChunk: status = " << status;
return status != B64_DECODE_INVALID;
} }
vector<string> split(const string& s, char delim) { vector<string> split(const string& s, char delim) {
@ -1281,6 +1423,7 @@ static void b64TestChunk(const string &s,
int &deletedCount, int &deletedCount,
string &outStr) string &outStr)
{ {
dbgTrace(D_WAAP_BASE64) << " ===b64TestChunk===: starting with = '" << s << "'";
size_t chunkLen = (chunkEnd - chunkStart); size_t chunkLen = (chunkEnd - chunkStart);
if ((chunkEnd - chunkStart) > static_cast<int>(b64_prefix.size()) && if ((chunkEnd - chunkStart) > static_cast<int>(b64_prefix.size()) &&
@ -1289,11 +1432,9 @@ static void b64TestChunk(const string &s,
chunkLen -= b64_prefix.size(); chunkLen -= b64_prefix.size();
} }
size_t chunkRem = chunkLen % 4;
// Only match chunk whose length is divisible by 4
string repl; string repl;
if (chunkRem == 0 && cb(s, chunkStart, chunkEnd, repl)) { dbgTrace(D_WAAP_BASE64) << " ===b64TestChunk===: chunkLen = " << chunkLen;
if (cb(s, chunkStart, chunkEnd, repl)) {
// Succesfully matched b64 chunk // Succesfully matched b64 chunk
if (!repl.empty()) { if (!repl.empty()) {
outStr += repl; outStr += repl;
@ -1340,9 +1481,7 @@ bool detectBase64Chunk(
dbgTrace(D_WAAP_BASE64) << " ===detectBase64Chunk===: isB64AlphaChar = true, '" << *it << "'"; dbgTrace(D_WAAP_BASE64) << " ===detectBase64Chunk===: isB64AlphaChar = true, '" << *it << "'";
start = it; start = it;
end = s.end(); end = s.end();
if ((end - start) % 4 == 0) { return true;
return true;
}
} }
// non base64 before supposed chunk - will not process // non base64 before supposed chunk - will not process
return false; return false;
@ -1381,17 +1520,31 @@ bool isBase64PrefixProcessingOK (
if (detectBase64Chunk(s, start, end)) { if (detectBase64Chunk(s, start, end)) {
dbgTrace(D_WAAP_BASE64) << " ===isBase64PrefixProcessingOK===: chunk detected"; dbgTrace(D_WAAP_BASE64) << " ===isBase64PrefixProcessingOK===: chunk detected";
if ((start != s.end()) && (end == s.end())) { if ((start != s.end()) && (end == s.end())) {
dbgTrace(D_WAAP_BASE64) << " ===isBase64PrefixProcessingOK===: chunk detected but not complete";
retVal = processDecodedChunk(s, start, end, value, binaryFileType, true); retVal = processDecodedChunk(s, start, end, value, binaryFileType, true);
dbgTrace(D_WAAP_BASE64)
<< " ===isBase64PrefixProcessingOK===: after processDecodedChunk retVal = "
<< retVal
<< " binaryFileType = "
<< binaryFileType;
} }
} else if (start != s.end()) { } else if (start != s.end()) {
dbgTrace(D_WAAP_BASE64) << " ===isBase64PrefixProcessingOK===: chunk not detected." dbgTrace(D_WAAP_BASE64)
" searching for known file header only"; << " ===isBase64PrefixProcessingOK===: chunk not detected. searching for known file header only";
end = (start + MAX_HEADER_LOOKUP < s.end()) ? start + MAX_HEADER_LOOKUP : s.end(); end = (start + MAX_HEADER_LOOKUP < s.end()) ? start + MAX_HEADER_LOOKUP : s.end();
processDecodedChunk(s, start, end, value, binaryFileType); processDecodedChunk(s, start, end, value, binaryFileType);
value.clear(); value.clear();
dbgTrace(D_WAAP_BASE64)
<< " ===isBase64PrefixProcessingOK===: after processDecodedChunk binaryFileType = "
<< binaryFileType;
return binaryFileType != Waap::Util::BinaryFileType::FILE_TYPE_NONE; return binaryFileType != Waap::Util::BinaryFileType::FILE_TYPE_NONE;
} }
} }
dbgTrace(D_WAAP_BASE64)
<< " ===isBase64PrefixProcessingOK===: retVal = "
<< retVal
<< " binaryFileType = "
<< binaryFileType;
return retVal != B64_DECODE_INVALID; return retVal != B64_DECODE_INVALID;
} }
@ -1399,23 +1552,31 @@ base64_variants b64Test (
const string &s, const string &s,
string &key, string &key,
string &value, string &value,
BinaryFileType &binaryFileType) BinaryFileType &binaryFileType,
const size_t offset)
{ {
key.clear(); key.clear();
bool retVal;
binaryFileType = Waap::Util::BinaryFileType::FILE_TYPE_NONE; binaryFileType = Waap::Util::BinaryFileType::FILE_TYPE_NONE;
auto begin = s.begin() + offset;
dbgTrace(D_WAAP_BASE64)
<< " ===b64Test===: string = "
<< s
<< " key = "
<< key
<< " value = "
<< value
<< " offset = "
<< offset;
dbgTrace(D_WAAP_BASE64) << " ===b64Test===: string = " << s
<< " key = " << key << " value = " << value;
// Minimal length // Minimal length
if (s.size() < 8) { if (s.size() < 8 + offset) {
return CONTINUE_AS_IS; return CONTINUE_AS_IS;
} }
dbgTrace(D_WAAP_BASE64) << " ===b64Test===: minimal lenght test passed"; dbgTrace(D_WAAP_BASE64) << " ===b64Test===: minimal lenght test passed";
std::string prefix_decoded_val; std::string prefix_decoded_val;
string::const_iterator it = s.begin(); auto it = begin;
// 1st check if we have key candidate // 1st check if we have key candidate
if (base64_key_value_detector_re.hasMatch(s)) { if (base64_key_value_detector_re.hasMatch(s)) {
@ -1433,7 +1594,7 @@ base64_variants b64Test (
break; break;
case EQUAL: case EQUAL:
if (*it == '=') { if (*it == '=') {
it = s.begin(); it = begin;
state=MISDETECT; state=MISDETECT;
continue; continue;
} }
@ -1455,7 +1616,7 @@ base64_variants b64Test (
if (it == s.end() || state == MISDETECT) { if (it == s.end() || state == MISDETECT) {
dbgTrace(D_WAAP_BASE64) << " ===b64Test===: detected *it = s.end()" << *it; dbgTrace(D_WAAP_BASE64) << " ===b64Test===: detected *it = s.end()" << *it;
if (key.size() > 0) { if (key.size() > 0) {
it = s.begin(); it = begin;
key.clear(); key.clear();
} }
} else { } else {
@ -1479,7 +1640,7 @@ base64_variants b64Test (
} }
} }
string::const_iterator start = s.end(); auto start = s.end();
dbgTrace(D_WAAP_BASE64) << " ===b64Test===: B64 itself = " << *it << " ======="; dbgTrace(D_WAAP_BASE64) << " ===b64Test===: B64 itself = " << *it << " =======";
bool isB64AlphaChar = Waap::Util::isAlphaAsciiFast(*it) || isdigit(*it) || *it=='/' || *it=='+'; bool isB64AlphaChar = Waap::Util::isAlphaAsciiFast(*it) || isdigit(*it) || *it=='/' || *it=='+';
if (isB64AlphaChar) { if (isB64AlphaChar) {
@ -1487,11 +1648,6 @@ base64_variants b64Test (
dbgTrace(D_WAAP_BASE64) << dbgTrace(D_WAAP_BASE64) <<
" ===b64Test===: Start tracking potential b64 chunk = " << *it << " ======="; " ===b64Test===: Start tracking potential b64 chunk = " << *it << " =======";
start = it; start = it;
if ((s.end() - start) % 4 != 0) {
key.clear();
value.clear();
return CONTINUE_AS_IS;
}
} }
else { else {
dbgTrace(D_WAAP_BASE64) << dbgTrace(D_WAAP_BASE64) <<
@ -1512,17 +1668,37 @@ base64_variants b64Test (
key.pop_back(); key.pop_back();
dbgTrace(D_WAAP_BASE64) << " ===b64Test===: FINAL key = '" << key << "'"; dbgTrace(D_WAAP_BASE64) << " ===b64Test===: FINAL key = '" << key << "'";
} }
retVal = decodeBase64Chunk(s, start, s.end(), value) != B64_DECODE_INVALID; base64_decode_status decode_chunk_status = decodeBase64Chunk(s, start, s.end(), value);
dbgTrace(D_WAAP_BASE64) << " ===b64Test===: After testing and conversion value = " dbgTrace(D_WAAP_BASE64)
<< value << "retVal = '" << retVal <<"'"; << " ===b64Test===: After testing and conversion value = "
if (!retVal) { << value
<< "decode_chunk_status = '"
<< decode_chunk_status
<<"'";
if (decode_chunk_status == B64_DECODE_INVALID) {
key.clear(); key.clear();
value.clear(); value.clear();
return CONTINUE_AS_IS; return CONTINUE_AS_IS;
} }
dbgTrace(D_WAAP_BASE64) << " ===b64Test===: After tpassed retVal check = "
<< value << "retVal = '" << retVal <<"'" << "key = '" << key << "'"; if (decode_chunk_status == B64_DECODE_INCOMPLETE) {
value.clear();
}
if (decode_chunk_status == B64_DECODE_SUSPECTED) {
return CONTINUE_DUAL_SCAN;
}
dbgTrace(D_WAAP_BASE64)
<< " ===b64Test===: After tpassed retVal check = "
<< value
<< "decode_chunk_status = '"
<< decode_chunk_status
<<"'"
<< "key = '"
<< key
<< "'";
if (key.empty()) { if (key.empty()) {
return SINGLE_B64_CHUNK_CONVERT; return SINGLE_B64_CHUNK_CONVERT;
} else { } else {
@ -1548,7 +1724,7 @@ void b64Decode(
deletedCount = 0; deletedCount = 0;
outStr = ""; outStr = "";
int offsetFix = 0; int offsetFix = 0;
dbgTrace(D_WAAP_BASE64) << " ===b64Decode===: starting with = '" << s << "'";
string::const_iterator it = s.begin(); string::const_iterator it = s.begin();
// Minimal length // Minimal length
@ -1596,6 +1772,11 @@ void b64Decode(
} }
// Decode and add chunk // Decode and add chunk
dbgTrace(D_WAAP_BASE64)
<< " ===b64Decode===: chunkStart = "
<< *chunkStart
<< " it = "
<< *it;
b64TestChunk(s, chunkStart, it, cb, decodedCount, deletedCount, outStr); b64TestChunk(s, chunkStart, it, cb, decodedCount, deletedCount, outStr);
// stop tracking b64 chunk // stop tracking b64 chunk
@ -1607,6 +1788,7 @@ void b64Decode(
} }
if (chunkStart != s.end()) { if (chunkStart != s.end()) {
dbgTrace(D_WAAP_BASE64) << " ===b64Decode===: chunkStart = " << *chunkStart;
b64TestChunk(s, chunkStart, it, cb, decodedCount, deletedCount, outStr); b64TestChunk(s, chunkStart, it, cb, decodedCount, deletedCount, outStr);
} }
} }

View File

@ -32,9 +32,15 @@
#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
enum base64_variants {SINGLE_B64_CHUNK_CONVERT, KEY_VALUE_B64_PAIR, CONTINUE_AS_IS}; enum base64_variants {SINGLE_B64_CHUNK_CONVERT, KEY_VALUE_B64_PAIR, CONTINUE_AS_IS, CONTINUE_DUAL_SCAN};
enum base64_stage {BEFORE_EQUAL, EQUAL, DONE, MISDETECT}; enum base64_stage {BEFORE_EQUAL, EQUAL, DONE, MISDETECT};
enum base64_decode_status {B64_DECODE_INVALID, B64_DECODE_OK, B64_DECODE_INCOMPLETE}; enum base64_decode_status {B64_DECODE_INVALID, B64_DECODE_OK, B64_DECODE_INCOMPLETE, B64_DECODE_SUSPECTED};
#define BASE64_ENTROPY_BASE_THRESHOLD 5.0
#define BASE64_ENTROPY_DECODED_THRESHOLD 5.4
#define BASE64_ENTROPY_THRESHOLD_DELTA 0.25
#define BASE64_MIN_SIZE_LIMIT 16
#define BASE64_MAX_SIZE_LIMIT 1024
// This is portable version of stricmp(), which is non-standard function (not even in C). // This is portable version of stricmp(), which is non-standard function (not even in C).
// Contrary to stricmp(), for a slight optimization, s2 is ASSUMED to be already in lowercase. // Contrary to stricmp(), for a slight optimization, s2 is ASSUMED to be already in lowercase.
@ -865,6 +871,17 @@ void unescapeUnicode(std::string &text);
// Try to find and decode UTF7 chunks // Try to find and decode UTF7 chunks
std::string filterUTF7(const std::string &text); std::string filterUTF7(const std::string &text);
base64_decode_status
decideStatusBase64Decoded(
std::string& decoded,
double entropy,
double decoded_entropy,
size_t spacer_count,
size_t nonPrintableCharsCount,
bool clear_on_error,
double terminatorCharsSeen,
bool called_with_prefix);
base64_decode_status base64_decode_status
decodeBase64Chunk( decodeBase64Chunk(
const std::string &value, const std::string &value,
@ -926,7 +943,8 @@ namespace Util {
const std::string &s, const std::string &s,
std::string &key, std::string &key,
std::string &value, std::string &value,
BinaryFileType &binaryFileType); BinaryFileType &binaryFileType,
size_t offset = 0);
// The original stdlib implementation of isalpha() supports locale settings which we do not really need. // The original stdlib implementation of isalpha() supports locale settings which we do not really need.
// It is also proven to contribute to slow performance in some of the algorithms using it. // It is also proven to contribute to slow performance in some of the algorithms using it.

View File

@ -20,6 +20,7 @@
#include <vector> #include <vector>
#include <dirent.h> #include <dirent.h>
#include <boost/regex.hpp> #include <boost/regex.hpp>
#include <algorithm>
#include "debug.h" #include "debug.h"
#include "maybe_res.h" #include "maybe_res.h"
@ -75,13 +76,13 @@ NginxConfCollector::expandIncludes(const string &include_pattern) const {
struct dirent *entry; struct dirent *entry;
while ((entry = readdir(dir)) != nullptr) { while ((entry = readdir(dir)) != nullptr) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue;
if (NGEN::Regex::regexMatch(__FILE__, __LINE__, entry->d_name, pattern)) { if (NGEN::Regex::regexMatch(__FILE__, __LINE__, entry->d_name, pattern)) {
matching_files.push_back(maybe_directory + "/" + entry->d_name); matching_files.push_back(maybe_directory + "/" + entry->d_name);
dbgTrace(D_NGINX_MANAGER) << "Matched file: " << maybe_directory << '/' << entry->d_name; dbgTrace(D_NGINX_MANAGER) << "Matched file: " << maybe_directory << '/' << entry->d_name;
} }
} }
closedir(dir); closedir(dir);
sort(matching_files.begin(), matching_files.end());
return matching_files; return matching_files;
} }

View File

@ -436,6 +436,7 @@ AgentDetails::loadProxyType(const string &proxy_type)
} }
#ifdef gaia #ifdef gaia
(void)proxy_type;
I_ShellCmd *shell_cmd = Singleton::Consume<I_ShellCmd>::by<AgentDetails>(); I_ShellCmd *shell_cmd = Singleton::Consume<I_ShellCmd>::by<AgentDetails>();
auto proxy_ip = shell_cmd->getExecOutput("dbget proxy:ip-address| tr -d '\n'"); auto proxy_ip = shell_cmd->getExecOutput("dbget proxy:ip-address| tr -d '\n'");
if (!proxy_ip.ok()) return proxy_ip; if (!proxy_ip.ok()) return proxy_ip;

View File

@ -203,6 +203,7 @@ private:
MessageMetadata service_config_req_md("127.0.0.1", 7777); MessageMetadata service_config_req_md("127.0.0.1", 7777);
service_config_req_md.setConnectioFlag(MessageConnectionConfig::ONE_TIME_CONN); service_config_req_md.setConnectioFlag(MessageConnectionConfig::ONE_TIME_CONN);
service_config_req_md.setConnectioFlag(MessageConnectionConfig::UNSECURE_CONN); service_config_req_md.setConnectioFlag(MessageConnectionConfig::UNSECURE_CONN);
service_config_req_md.setSuspension(false);
auto service_config_status = messaging->sendSyncMessage( auto service_config_status = messaging->sendSyncMessage(
HTTPMethod::POST, HTTPMethod::POST,
"/set-nano-service-config", "/set-nano-service-config",
@ -214,6 +215,7 @@ private:
MessageMetadata secondary_port_req_md("127.0.0.1", 7778); MessageMetadata secondary_port_req_md("127.0.0.1", 7778);
secondary_port_req_md.setConnectioFlag(MessageConnectionConfig::ONE_TIME_CONN); secondary_port_req_md.setConnectioFlag(MessageConnectionConfig::ONE_TIME_CONN);
secondary_port_req_md.setConnectioFlag(MessageConnectionConfig::UNSECURE_CONN); secondary_port_req_md.setConnectioFlag(MessageConnectionConfig::UNSECURE_CONN);
secondary_port_req_md.setSuspension(false);
service_config_status = messaging->sendSyncMessage( service_config_status = messaging->sendSyncMessage(
HTTPMethod::POST, HTTPMethod::POST,
"/set-nano-service-config", "/set-nano-service-config",
@ -251,6 +253,7 @@ private:
MessageMetadata service_config_req_md("127.0.0.1", 7777); MessageMetadata service_config_req_md("127.0.0.1", 7777);
service_config_req_md.setConnectioFlag(MessageConnectionConfig::ONE_TIME_CONN); service_config_req_md.setConnectioFlag(MessageConnectionConfig::ONE_TIME_CONN);
service_config_req_md.setConnectioFlag(MessageConnectionConfig::UNSECURE_CONN); service_config_req_md.setConnectioFlag(MessageConnectionConfig::UNSECURE_CONN);
service_config_req_md.setSuspension(false);
bool service_config_status = messaging->sendSyncMessageWithoutResponse( bool service_config_status = messaging->sendSyncMessageWithoutResponse(
HTTPMethod::POST, HTTPMethod::POST,
"/set-reconf-status", "/set-reconf-status",
@ -262,6 +265,7 @@ private:
MessageMetadata secondary_port_req_md("127.0.0.1", 7778); MessageMetadata secondary_port_req_md("127.0.0.1", 7778);
secondary_port_req_md.setConnectioFlag(MessageConnectionConfig::ONE_TIME_CONN); secondary_port_req_md.setConnectioFlag(MessageConnectionConfig::ONE_TIME_CONN);
secondary_port_req_md.setConnectioFlag(MessageConnectionConfig::UNSECURE_CONN); secondary_port_req_md.setConnectioFlag(MessageConnectionConfig::UNSECURE_CONN);
secondary_port_req_md.setSuspension(false);
service_config_status = messaging->sendSyncMessageWithoutResponse( service_config_status = messaging->sendSyncMessageWithoutResponse(
HTTPMethod::POST, HTTPMethod::POST,
"/set-reconf-status", "/set-reconf-status",

View File

@ -527,7 +527,7 @@ Debug::preload()
active_streams["FOG"] = make_shared<DebugFogStream>(); active_streams["FOG"] = make_shared<DebugFogStream>();
string branch = Version::getBranch(); string branch = Version::getBranch();
if (branch == "master" || branch.substr(0, 6) == "hotfix") { if (branch == "open-source" || branch == "master" || branch.substr(0, 6) == "hotfix") {
should_assert_optional = false; should_assert_optional = false;
} else { } else {
should_assert_optional = true; should_assert_optional = true;

View File

@ -69,14 +69,16 @@ public:
uint16_t _port_num, uint16_t _port_num,
Flags<MessageConnectionConfig> _conn_flags, Flags<MessageConnectionConfig> _conn_flags,
bool _should_buffer = false, bool _should_buffer = false,
bool _is_to_fog = false bool _is_to_fog = false,
bool _should_suspend = true
) : ) :
host_name(_host_name), host_name(_host_name),
port_num(_port_num), port_num(_port_num),
conn_flags(_conn_flags), conn_flags(_conn_flags),
should_buffer(_should_buffer), should_buffer(_should_buffer),
is_to_fog(_is_to_fog), is_to_fog(_is_to_fog),
should_send_access_token(true) should_send_access_token(true),
should_suspend(_should_suspend)
{} {}
const bool & const bool &
@ -193,6 +195,12 @@ public:
is_dual_auth = true; is_dual_auth = true;
} }
void
setSuspension(bool _should_suspend)
{
should_suspend = _should_suspend;
}
void void
setExternalCertificate(const std::string &_external_certificate) setExternalCertificate(const std::string &_external_certificate)
{ {
@ -211,6 +219,12 @@ public:
return should_buffer; return should_buffer;
} }
bool
shouldSuspend() const
{
return should_suspend;
}
bool bool
isProxySet() const isProxySet() const
{ {
@ -314,6 +328,7 @@ private:
bool is_rate_limit_block = false; bool is_rate_limit_block = false;
uint rate_limit_block_time = 0; uint rate_limit_block_time = 0;
bool should_send_access_token = true; bool should_send_access_token = true;
bool should_suspend = true;
}; };
#endif // __MESSAGING_METADATA_H__ #endif // __MESSAGING_METADATA_H__

View File

@ -22,7 +22,7 @@ using namespace std;
USE_DEBUG_FLAG(D_INTELLIGENCE); USE_DEBUG_FLAG(D_INTELLIGENCE);
static const unsigned int upper_assets_limit = 50; static const unsigned int upper_assets_limit = 200;
static const unsigned int upper_confidence_limit = 1000; static const unsigned int upper_confidence_limit = 1000;
Maybe<void> Maybe<void>

View File

@ -125,7 +125,9 @@ MessagingComp::sendMessage(
} }
Connection conn = maybe_conn.unpack(); Connection conn = maybe_conn.unpack();
if (conn.isSuspended()) return suspendMessage(body, method, uri, category, message_metadata); if (message_metadata.shouldSuspend() && conn.isSuspended()) {
return suspendMessage(body, method, uri, category, message_metadata);
}
bool is_to_fog = isMessageToFog(message_metadata); bool is_to_fog = isMessageToFog(message_metadata);
auto metadata = message_metadata; auto metadata = message_metadata;

View File

@ -110,8 +110,14 @@ if [ $retval -eq 0 ]; then
fi fi
if [ $var_gaia_release -eq 0 ] || [ $var_mds_release -eq 0 ]; then if [ $var_gaia_release -eq 0 ] || [ $var_mds_release -eq 0 ]; then
var_arch="gaia" arch=$(uname -a | awk '{print $(NF -1) }')
var_arch_flag="--gaia" if test "${arch}" == "aarch64"; then
var_arch="gaia_arm"
var_arch_flag="--gaia_arm"
else
var_arch="gaia"
var_arch_flag="--gaia"
fi
elif [ $var_alpine_release -eq 0 ]; then elif [ $var_alpine_release -eq 0 ]; then
var_is_alpine=true var_is_alpine=true
else else
@ -322,7 +328,7 @@ while true; do
LOG_FILE_PATH=$1 LOG_FILE_PATH=$1
fi fi
echo "Log files path: ${LOG_FILE_PATH}" echo "Log files path: ${LOG_FILE_PATH}"
elif [ "$1" = "--arm64_trustbox" ] || [ "$1" = "--arm64_linaro" ] || [ "$1" = "--arm32_rpi" ] || [ "$1" = "--gaia" ] || [ "$1" = "--smb_mrv_v1" ] || [ "$1" = "--smb_sve_v2" ] || [ "$1" = "--smb_thx_v3" ] || [ "$1" = "--x86" ] || [ "$1" = "./orchestration_package.sh" ]; then elif [ "$1" = "--arm64_trustbox" ] || [ "$1" = "--arm64_linaro" ] || [ "$1" = "--arm32_rpi" ] || [ "$1" = "--gaia" ] || [ "$1" = "--gaia_arm" ] || [ "$1" = "--smb_mrv_v1" ] || [ "$1" = "--smb_sve_v2" ] || [ "$1" = "--smb_thx_v3" ] || [ "$1" = "--x86" ] || [ "$1" = "./orchestration_package.sh" ]; then
shift shift
continue continue
elif [ "$1" = "--skip_registration" ]; then elif [ "$1" = "--skip_registration" ]; then
@ -416,7 +422,7 @@ if command -v which &>/dev/null; then
var_which_cmd_exists=1 var_which_cmd_exists=1
fi fi
if [ $var_arch != "gaia" ] && [ $var_which_cmd_exists -eq 1 ]; then if [ $var_arch != "gaia" ] && [ $var_arch != "gaia_arm" ] && [ $var_which_cmd_exists -eq 1 ]; then
if [ -n "$(which systemctl)" ]; then if [ -n "$(which systemctl)" ]; then
var_startup_service="systemd" var_startup_service="systemd"
else else
@ -490,12 +496,12 @@ cp_copy() # Initials - cc
update_cloudguard_appsec_manifest() update_cloudguard_appsec_manifest()
{ {
if [ -z ${CLOUDGUARD_APPSEC_STANDALONE} ] || [ -z ${DOCKER_RPM_ENABLED} ]; then if [ -z ${INFINITY_NEXT_NANO_AGENT} ] && { [ -z ${CLOUDGUARD_APPSEC_STANDALONE} ] || [ -z ${DOCKER_RPM_ENABLED} ]; }; then
return return
fi fi
selected_cloudguard_appsec_manifest_path="${TMP_FOLDER}/cloudguard_appsec_manifest.json" selected_cloudguard_appsec_manifest_path="${TMP_FOLDER}/cloudguard_appsec_manifest.json"
if [ "${DOCKER_RPM_ENABLED}" = "false" ]; then if [ "${DOCKER_RPM_ENABLED}" = "false" ] || [ "${INFINITY_NEXT_NANO_AGENT}" = "TRUE" ]; then
selected_cloudguard_appsec_manifest_path="${TMP_FOLDER}/self_managed_cloudguard_appsec_manifest.json" selected_cloudguard_appsec_manifest_path="${TMP_FOLDER}/self_managed_cloudguard_appsec_manifest.json"
fi fi
@ -564,7 +570,7 @@ install_watchdog_gaia()
# Add cp-nano-watchdog to DB # Add cp-nano-watchdog to DB
dbset process:${watchdog_pm_name} t dbset process:${watchdog_pm_name} t
dbset process:${watchdog_pm_name}:path ${FILESYSTEM_PATH}/${WATCHDOG_PATH} dbset process:${watchdog_pm_name}:path ${FILESYSTEM_PATH}/${WATCHDOG_PATH}
dbset process:${watchdog_pm_name}:arg:1 --gaia dbset process:${watchdog_pm_name}:arg:1 ${var_arch_flag}
dbset process:${watchdog_pm_name}:runlevel 1 dbset process:${watchdog_pm_name}:runlevel 1
dbset :save dbset :save
tellpm ${watchdog_pm_name} t tellpm ${watchdog_pm_name} t
@ -616,7 +622,7 @@ install_watchdog()
cp_copy service/smb/nano_agent.init /storage/nano_agent/etc/nano_agent.init cp_copy service/smb/nano_agent.init /storage/nano_agent/etc/nano_agent.init
chmod +rx /storage/nano_agent/etc/nano_agent.init chmod +rx /storage/nano_agent/etc/nano_agent.init
elif [ $var_container_mode = false ]; then elif [ $var_container_mode = false ]; then
if [ $var_arch = "gaia" ]; then if [ $var_arch = "gaia" ] || [ $var_arch = "gaia_arm" ]; then
cp_exec "ln -s ${FWDIR}/bin/curl_cli ${FWDIR}/bin/curl" cp_exec "ln -s ${FWDIR}/bin/curl_cli ${FWDIR}/bin/curl"
cp_exec "ln -s ${CPDIR}/bin/cpopenssl ${CPDIR}/bin/openssl" cp_exec "ln -s ${CPDIR}/bin/cpopenssl ${CPDIR}/bin/openssl"
cp_copy watchdog/access_pre_init $INIT_D_PATH/access_pre_init cp_copy watchdog/access_pre_init $INIT_D_PATH/access_pre_init
@ -657,7 +663,7 @@ install_watchdog()
cp_exec "$INIT_D_PATH/nano_agent.init start" cp_exec "$INIT_D_PATH/nano_agent.init start"
elif [ "$is_smb" = "1" ]; then elif [ "$is_smb" = "1" ]; then
cp_exec "/storage/nano_agent/etc/nano_agent.init start" cp_exec "/storage/nano_agent/etc/nano_agent.init start"
elif [ $var_arch = "gaia" ]; then elif [ $var_arch = "gaia" ] || [ $var_arch = "gaia_arm" ]; then
install_watchdog_gaia install_watchdog_gaia
else else
cp_exec "service $NANO_AGENT_SERVICE_NAME start" cp_exec "service $NANO_AGENT_SERVICE_NAME start"
@ -785,7 +791,7 @@ upgrade_conf_if_needed()
cp_exec "cp -f configuration/orchestration.cfg ${FILESYSTEM_PATH}/${SERVICE_PATH}/${ORCHESTRATION_FILE_NAME}.cfg" cp_exec "cp -f configuration/orchestration.cfg ${FILESYSTEM_PATH}/${SERVICE_PATH}/${ORCHESTRATION_FILE_NAME}.cfg"
execution_flags="execution_flags=\"--orchestration-mode=${var_orchestration_mode}\"" execution_flags="execution_flags=\"--orchestration-mode=${var_orchestration_mode}\""
echo $execution_flags >> ${FILESYSTEM_PATH}/${SERVICE_PATH}/${ORCHESTRATION_FILE_NAME}.cfg echo $execution_flags >> ${FILESYSTEM_PATH}/${SERVICE_PATH}/${ORCHESTRATION_FILE_NAME}.cfg
if [ $var_arch = "gaia" -o "$is_smb" = "1" ]; then if [ $var_arch = "gaia" -o $var_arch = "gaia_arm" -o "$is_smb" = "1" ]; then
if [ -z "${gaia_ld_path}" ]; then if [ -z "${gaia_ld_path}" ]; then
gaia_ld_path="${LD_LIBRARY_PATH}" gaia_ld_path="${LD_LIBRARY_PATH}"
fi fi
@ -1001,7 +1007,7 @@ install_orchestration()
cp_exec "cp -f configuration/orchestration.cfg ${FILESYSTEM_PATH}/${SERVICE_PATH}/${ORCHESTRATION_FILE_NAME}.cfg" cp_exec "cp -f configuration/orchestration.cfg ${FILESYSTEM_PATH}/${SERVICE_PATH}/${ORCHESTRATION_FILE_NAME}.cfg"
execution_flags="execution_flags=\"--orchestration-mode=${var_orchestration_mode}\"" execution_flags="execution_flags=\"--orchestration-mode=${var_orchestration_mode}\""
echo $execution_flags >> ${FILESYSTEM_PATH}/${SERVICE_PATH}/${ORCHESTRATION_FILE_NAME}.cfg echo $execution_flags >> ${FILESYSTEM_PATH}/${SERVICE_PATH}/${ORCHESTRATION_FILE_NAME}.cfg
if [ $var_arch = "gaia" -o "$is_smb" = "1" ]; then if [ $var_arch = "gaia" -o $var_arch = "gaia_arm" -o "$is_smb" = "1" ]; then
if [ -z "${gaia_ld_path}" ]; then if [ -z "${gaia_ld_path}" ]; then
gaia_ld_path="${LD_LIBRARY_PATH}" gaia_ld_path="${LD_LIBRARY_PATH}"
fi fi
@ -1101,7 +1107,14 @@ install_orchestration()
if [ -z "${var_token}" ] && [ ${var_hybrid_mode} = false ] && [ ${var_offline_mode} = false ] && [ -z ${EGG_MODE} ] && [ ${var_no_otp} = false ]; then if [ -z "${var_token}" ] && [ ${var_hybrid_mode} = false ] && [ ${var_offline_mode} = false ] && [ -z ${EGG_MODE} ] && [ ${var_no_otp} = false ]; then
cp_print "Please enter OTP token []:" ${FORCE_STDOUT} cp_print "Please enter OTP token []:" ${FORCE_STDOUT}
read -r var_token read -r var_token
attempts=0
max_attempts=3
while [ -z "$var_token" ]; do while [ -z "$var_token" ]; do
attempts=$((attempts + 1))
if [ "$attempts" -gt "$max_attempts" ]; then
cp_print "Maximum attempts exceeded. open-appsec Nano Agent registration failed. Failed to get token" ${FORCE_STDOUT}
exit 1
fi
cp_print "You must enter OTP token[]:" ${FORCE_STDOUT} cp_print "You must enter OTP token[]:" ${FORCE_STDOUT}
read -r var_token read -r var_token
done done
@ -1201,7 +1214,7 @@ install_orchestration()
execution_flags="execution_flags=\"--orchestration-mode=${var_orchestration_mode}\"" execution_flags="execution_flags=\"--orchestration-mode=${var_orchestration_mode}\""
echo $execution_flags >> ${FILESYSTEM_PATH}/${SERVICE_PATH}/${ORCHESTRATION_FILE_NAME}.cfg echo $execution_flags >> ${FILESYSTEM_PATH}/${SERVICE_PATH}/${ORCHESTRATION_FILE_NAME}.cfg
if [ $var_arch = "gaia" -o "$is_smb" = "1" ]; then if [ $var_arch = "gaia" -o $var_arch = "gaia_arm" -o "$is_smb" = "1" ]; then
sed -i '1i gaia_ld_path='"$LD_LIBRARY_PATH"'' ${FILESYSTEM_PATH}/${SERVICE_PATH}/${ORCHESTRATION_FILE_NAME}.cfg sed -i '1i gaia_ld_path='"$LD_LIBRARY_PATH"'' ${FILESYSTEM_PATH}/${SERVICE_PATH}/${ORCHESTRATION_FILE_NAME}.cfg
fi fi