diff --git a/headers/modsecurity/assay.h b/headers/modsecurity/assay.h index c93b7af2..4e9d61a8 100644 --- a/headers/modsecurity/assay.h +++ b/headers/modsecurity/assay.h @@ -263,6 +263,7 @@ class Assay { std::list rulesMessages; std::list ruleTags; + std::list> auditLogModifier; private: std::ofstream myfile; ModSecurity *m_ms; diff --git a/src/Makefile.am b/src/Makefile.am index c5feab08..53ce09c0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -56,6 +56,7 @@ ACTIONS = \ actions/block.cc \ actions/capture.cc \ actions/chain.cc \ + actions/ctl_audit_log_parts.cc \ actions/log_data.cc \ actions/msg.cc \ actions/no_audit_log.cc \ diff --git a/src/actions/ctl_audit_log_parts.cc b/src/actions/ctl_audit_log_parts.cc new file mode 100644 index 00000000..5b48a104 --- /dev/null +++ b/src/actions/ctl_audit_log_parts.cc @@ -0,0 +1,45 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#include "actions/ctl_audit_log_parts.h" + +#include +#include + +#include "modsecurity/assay.h" + +namespace ModSecurity { +namespace actions { + +CtlAuditLogParts::CtlAuditLogParts(std::string action) + : Action(action, RunTimeOnlyIfMatchKind), + mPartsAction(0) +{ + std::string what(action, 18, 1); + mParts = std::string(action, 19, action.length()-19); + if (what == "+") { + mPartsAction = 0; + } else { + mPartsAction = 1; + } +} + +bool CtlAuditLogParts::evaluate(Rule *rule, Assay *assay) { + assay->auditLogModifier.push_back(std::make_pair(mPartsAction, mParts)); + return true; +} + +} // namespace actions +} // namespace ModSecurity diff --git a/src/actions/ctl_audit_log_parts.h b/src/actions/ctl_audit_log_parts.h new file mode 100644 index 00000000..336fb256 --- /dev/null +++ b/src/actions/ctl_audit_log_parts.h @@ -0,0 +1,40 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#include + +#include "actions/action.h" +#include "modsecurity/assay.h" + +#ifndef SRC_CLT_ACTIONS_AUDIT_LOG_PARTS_H_ +#define SRC_CLT_ACTIONS_AUDIT_LOG_PARTS_H_ + +namespace ModSecurity { +namespace actions { + + +class CtlAuditLogParts : public Action { + public: + explicit CtlAuditLogParts(std::string action); + + bool evaluate(Rule *rule, Assay *assay) override; + int mPartsAction; + std::string mParts; +}; + +} // namespace actions +} // namespace ModSecurity + +#endif // SRC_CLT_ACTIONS_AUDIT_LOG_PARTS_H_ diff --git a/src/assay.cc b/src/assay.cc index 228a1f0a..7aa21ea5 100644 --- a/src/assay.cc +++ b/src/assay.cc @@ -962,7 +962,31 @@ int Assay::processLogging(int returned_code) { /* If relevant, save this assay information at the audit_logs */ if (m_rules != NULL && m_rules->audit_log != NULL) { - this->m_rules->audit_log->saveIfRelevant(this); + debug(8, "Checking if this request is suitable to be saved as an audit log."); + int parts = -1; + + if (this->auditLogModifier.size() > 0) + { + debug(4, "There was an audit log modifier for this transaction."); + std::list>::iterator it; + parts = this->m_rules->audit_log->m_parts; + for (it = auditLogModifier.begin(); it != auditLogModifier.end(); ++it) { + std::pair p = *it; + if (p.first == 0) { // Add + parts = this->m_rules->audit_log->addParts(parts, p.second); + } else { // Remove + parts = this->m_rules->audit_log->removeParts(parts, p.second); + } + } + } + if (save_in_auditlog) { + debug(8, "This request was marked to be saved via auditlog action."); + } + + bool saved = this->m_rules->audit_log->saveIfRelevant(this, parts); + if (saved) { + debug(8, "Request was relevant to be saved."); + } } return 0; diff --git a/src/audit_log.cc b/src/audit_log.cc index 390034ef..84ea6941 100644 --- a/src/audit_log.cc +++ b/src/audit_log.cc @@ -28,7 +28,13 @@ #define PARTS_CONSTAINS(a, c) \ if (new_parts.find(toupper(a)) != std::string::npos \ || new_parts.find(tolower(a)) != std::string::npos) { \ - this->m_parts = this->m_parts | c; \ + parts = parts | c; \ + } + +#define PARTS_CONSTAINS_REM(a, c) \ + if (new_parts.find(toupper(a)) != std::string::npos \ + || new_parts.find(tolower(a)) != std::string::npos) { \ + parts = parts & ~c; \ } namespace ModSecurity { @@ -84,7 +90,7 @@ bool AuditLog::setStatus(AuditLogStatus new_status) { bool AuditLog::setRelevantStatus(const std::basic_string& status) { - this->m_relevant = status; + this->m_relevant = std::string(status); return true; } @@ -107,7 +113,7 @@ bool AuditLog::setFilePath2(const std::basic_string& path) { } -bool AuditLog::setParts(const std::basic_string& new_parts) { +int AuditLog::addParts(int parts, const std::string& new_parts) { PARTS_CONSTAINS('A', AAuditLogPart) PARTS_CONSTAINS('B', BAuditLogPart) PARTS_CONSTAINS('C', CAuditLogPart) @@ -121,6 +127,45 @@ bool AuditLog::setParts(const std::basic_string& new_parts) { PARTS_CONSTAINS('K', KAuditLogPart) PARTS_CONSTAINS('Z', ZAuditLogPart) + return parts; +} + + +int AuditLog::removeParts(int parts, const std::string& new_parts) { + PARTS_CONSTAINS_REM('A', AAuditLogPart) + PARTS_CONSTAINS_REM('B', BAuditLogPart) + PARTS_CONSTAINS_REM('C', CAuditLogPart) + PARTS_CONSTAINS_REM('D', DAuditLogPart) + PARTS_CONSTAINS_REM('E', EAuditLogPart) + PARTS_CONSTAINS_REM('F', FAuditLogPart) + PARTS_CONSTAINS_REM('G', GAuditLogPart) + PARTS_CONSTAINS_REM('H', HAuditLogPart) + PARTS_CONSTAINS_REM('I', IAuditLogPart) + PARTS_CONSTAINS_REM('J', JAuditLogPart) + PARTS_CONSTAINS_REM('K', KAuditLogPart) + PARTS_CONSTAINS_REM('Z', ZAuditLogPart) + + return parts; +} + + +bool AuditLog::setParts(const std::basic_string& new_parts) { + int parts = m_parts; + + PARTS_CONSTAINS('A', AAuditLogPart) + PARTS_CONSTAINS('B', BAuditLogPart) + PARTS_CONSTAINS('C', CAuditLogPart) + PARTS_CONSTAINS('D', DAuditLogPart) + PARTS_CONSTAINS('E', EAuditLogPart) + PARTS_CONSTAINS('F', FAuditLogPart) + PARTS_CONSTAINS('G', GAuditLogPart) + PARTS_CONSTAINS('H', HAuditLogPart) + PARTS_CONSTAINS('I', IAuditLogPart) + PARTS_CONSTAINS('J', JAuditLogPart) + PARTS_CONSTAINS('K', KAuditLogPart) + PARTS_CONSTAINS('Z', ZAuditLogPart) + + m_parts = parts; return true; } @@ -165,15 +210,24 @@ bool AuditLog::isRelevant(int status) { return false; } + if (sstatus.empty()) { + return true; + } + return Utils::regex_search(sstatus, Utils::Regex(m_relevant)) != 0; } bool AuditLog::saveIfRelevant(Assay *assay) { + return saveIfRelevant(assay, -1); +} + + +bool AuditLog::saveIfRelevant(Assay *assay, int parts) { if (this->isRelevant(assay->httpCodeReturned) == false && assay->save_in_auditlog == false) { - return true; + return false; } /** @@ -182,10 +236,14 @@ bool AuditLog::saveIfRelevant(Assay *assay) { * */ if (assay->do_not_save_in_auditlog == true) { - return true; + return false; } - m_writer->write(assay, m_parts); + if (parts == -1) + { + parts = m_parts; + } + m_writer->write(assay, parts); return true; } diff --git a/src/audit_log.h b/src/audit_log.h index d6703aaa..8a71281b 100644 --- a/src/audit_log.h +++ b/src/audit_log.h @@ -154,8 +154,12 @@ class AuditLog { bool close(); bool saveIfRelevant(Assay *assay); + bool saveIfRelevant(Assay *assay, int parts); bool isRelevant(int status); + int addParts(int parts, const std::string& new_parts); + int removeParts(int parts, const std::string& new_parts); + std::string m_path1; std::string m_path2; std::string m_storage_dir; @@ -163,11 +167,12 @@ class AuditLog { int filePermission; int directoryPermission; - private: + int m_parts; + +private: AuditLogStatus m_status; - int m_parts; AuditLogType m_type; std::string m_relevant; diff --git a/src/audit_log_writer_serial.cc b/src/audit_log_writer_serial.cc index dd7b8575..2325a859 100644 --- a/src/audit_log_writer_serial.cc +++ b/src/audit_log_writer_serial.cc @@ -25,7 +25,7 @@ namespace ModSecurity { AuditLogWriterSerial::~AuditLogWriterSerial() { - log.close(); + m_log.close(); } @@ -42,7 +42,7 @@ void AuditLogWriterSerial::generateBoundary(std::string *boundary) { bool AuditLogWriterSerial::init() { - log.open(m_audit->m_path1, std::fstream::out | std::fstream::app); + m_log.open(m_audit->m_path1, std::fstream::out | std::fstream::app); return true; } @@ -53,8 +53,12 @@ bool AuditLogWriterSerial::write(Assay *assay, int parts) { generateBoundary(&boundary); // serialLoggingMutex.lock(); - log << assay->toOldAuditLogFormat(parts, "-" + boundary + "--"); + + m_log << assay->toOldAuditLogFormat(parts, "-" + boundary + "--"); + m_log.flush(); + // serialLoggingMutex.unlock(); + return true; } diff --git a/src/audit_log_writer_serial.h b/src/audit_log_writer_serial.h index 48b05106..bf0a3743 100644 --- a/src/audit_log_writer_serial.h +++ b/src/audit_log_writer_serial.h @@ -45,17 +45,23 @@ class AuditLogWriterSerial : public AuditLogWriter { void refCountDecreaseAndCheck() override { + /* m_refereceCount--; + + if (m_refereceCount == 0) { - delete this; - } + */ + delete this; + /* + /} + */ } bool init() override;; bool write(Assay *assay, int parts) override; private: - std::ofstream log; + std::ofstream m_log; void generateBoundary(std::string *boundary); }; diff --git a/src/parser/driver.cc b/src/parser/driver.cc index 3cae46e7..e62235e1 100644 --- a/src/parser/driver.cc +++ b/src/parser/driver.cc @@ -28,10 +28,14 @@ Driver::Driver() : trace_scanning(false), trace_parsing(false) { audit_log = new AuditLog(); + audit_log->refCountIncrease(); } Driver::~Driver() { + if (audit_log != NULL) { + audit_log->refCountDecreaseAndCheck(); + } delete loc.back(); } diff --git a/src/parser/seclang-parser.yy b/src/parser/seclang-parser.yy index 6a2343d9..89b77954 100644 --- a/src/parser/seclang-parser.yy +++ b/src/parser/seclang-parser.yy @@ -18,6 +18,7 @@ class Driver; #include "actions/action.h" #include "actions/audit_log.h" +#include "actions/ctl_audit_log_parts.h" #include "actions/set_var.h" #include "actions/severity.h" #include "actions/msg.h" @@ -47,6 +48,7 @@ class Driver; #include "variables/time_year.h" using ModSecurity::actions::Action; +using ModSecurity::actions::CtlAuditLogParts; using ModSecurity::actions::SetVar; using ModSecurity::actions::Severity; using ModSecurity::actions::Tag; @@ -653,8 +655,7 @@ act: } | ACTION_CTL_AUDIT_LOG_PARTS { - /* not ready yet. */ - $$ = Action::instantiate($1); + $$ = new CtlAuditLogParts($1); } ; diff --git a/src/rules.cc b/src/rules.cc index 7f0a92f8..f2f7c47c 100644 --- a/src/rules.cc +++ b/src/rules.cc @@ -209,8 +209,15 @@ int Rules::merge(Driver *from) { this->responseBodyLimitAction = from->responseBodyLimitAction; - this->audit_log = from->audit_log; - this->audit_log->refCountIncrease(); + if (from->audit_log != NULL && this->audit_log != NULL) { + this->audit_log->refCountDecreaseAndCheck(); + } + if (from->audit_log) { + this->audit_log = from->audit_log; + } + if (this->audit_log != NULL) { + this->audit_log->refCountIncrease(); + } return amount_of_rules; } @@ -247,7 +254,12 @@ int Rules::merge(Rules *from) { from->m_debugLog->getDebugLogLevel()); } - this->audit_log = from->audit_log; + if (from->audit_log != NULL && this->audit_log != NULL) { + this->audit_log->refCountDecreaseAndCheck(); + } + if (from->audit_log) { + this->audit_log = from->audit_log; + } if (this->audit_log != NULL) { this->audit_log->refCountIncrease(); }