From c9620ac50fa6d76692985fa5180fd854c1568a47 Mon Sep 17 00:00:00 2001 From: Felipe Zimmerle Date: Fri, 10 Jul 2015 15:23:15 -0300 Subject: [PATCH] Writes audit log in parallel mode First version still missing the index among other things --- headers/modsecurity/assay.h | 11 ++--- src/assay.cc | 18 ++++---- src/audit_log.cc | 10 ++--- src/audit_log.h | 5 ++- src/audit_log_writer.cc | 4 +- src/audit_log_writer.h | 12 +++++- src/audit_log_writer_parallel.cc | 74 ++++++++++++++++++++++++++++++++ src/audit_log_writer_parallel.h | 34 ++++++++++++++- src/audit_log_writer_serial.cc | 2 +- src/audit_log_writer_serial.h | 6 ++- src/utils.cc | 15 +++++++ src/utils.h | 1 + test/regression/regression.cc | 2 +- 13 files changed, 164 insertions(+), 30 deletions(-) diff --git a/headers/modsecurity/assay.h b/headers/modsecurity/assay.h index 6524482c..295fa7f4 100644 --- a/headers/modsecurity/assay.h +++ b/headers/modsecurity/assay.h @@ -126,7 +126,7 @@ class Assay { int processResponseBody(); int appendResponseBody(const unsigned char *body, size_t size); - int processLogging(); + int processLogging(int status_code); ModSecurityIntervention *intervention(); @@ -149,12 +149,14 @@ class Assay { bool save_in_auditlog; bool do_not_save_in_auditlog; - int http_code_returned; + int httpCodeReturned; std::string to_json(int parts); - private: std::string id; + time_t timeStamp; + + private: std::ofstream myfile; Rules *m_rules; ModSecurity *m_ms; @@ -166,7 +168,6 @@ class Assay { const char *m_uri; const char *m_protocol; const char *m_httpVersion; - time_t m_timeStamp; std::ostringstream m_requestBody; std::ostringstream m_responseBody; @@ -236,7 +237,7 @@ void msc_assay_cleanup(Assay *assay); ModSecurityIntervention *msc_intervention(Assay *assay); /** @ingroup ModSecurity_C_API */ -int msc_process_logging(Assay *assay); +int msc_process_logging(Assay *assay, int code); #ifdef __cplusplus } diff --git a/src/assay.cc b/src/assay.cc index bffa2d2e..b3aff08c 100644 --- a/src/assay.cc +++ b/src/assay.cc @@ -87,10 +87,10 @@ Assay::Assay(ModSecurity *ms, Rules *rules) m_rules(rules), save_in_auditlog(false), do_not_save_in_auditlog(false), - m_timeStamp(std::time(NULL)), - http_code_returned(200), + timeStamp(std::time(NULL)), + httpCodeReturned(200), m_ms(ms) { - id = std::to_string(this->m_timeStamp) + \ + id = std::to_string(this->timeStamp) + \ std::to_string(generate_assay_unique_id()); m_rules->incrementReferenceCount(); this->debug(4, "Initialising transaction"); @@ -617,8 +617,9 @@ int Assay::getResponseBodyLenth() { * @retval false Operation failed. * */ -int Assay::processLogging() { +int Assay::processLogging(int returned_code) { debug(4, "Starting phase LOGGING. (SecRules 5)"); + this->httpCodeReturned = returned_code; this->m_rules->evaluate(ModSecurity::LoggingPhase, this); /* If relevant, save this assay information at the audit_logs */ @@ -691,7 +692,7 @@ std::string Assay::to_json(int parts) { const unsigned char *buf; size_t len; yajl_gen g = NULL; - std::string ts = ascTime(&m_timeStamp).c_str(); + std::string ts = ascTime(&timeStamp).c_str(); std::string uniqueId = UniqueId::uniqueId(); g = yajl_gen_alloc(NULL); @@ -754,7 +755,7 @@ std::string Assay::to_json(int parts) { yajl_gen_map_open(g); LOGFY_ADD("body", this->m_responseBody.str().c_str()); - LOGFY_ADD_NUM("http_code", http_code_returned); + LOGFY_ADD_NUM("http_code", httpCodeReturned); /* response headers */ yajl_gen_string(g, reinterpret_cast("headers"), @@ -1251,14 +1252,15 @@ extern "C" int msc_get_response_body_length(Assay *assay) { * delivered prior to the execution of this function. * * @param assay ModSecurity assay. + * @param code HTTP code returned to the user. * * @returns If the operation was successful or not. * @retval 1 Operation was successful. * @retval 0 Operation failed. * */ -extern "C" int msc_process_logging(Assay *assay) { - return assay->processLogging(); +extern "C" int msc_process_logging(Assay *assay, int code) { + return assay->processLogging(code); } } // namespace ModSecurity diff --git a/src/audit_log.cc b/src/audit_log.cc index 43ae85c8..516fda4f 100644 --- a/src/audit_log.cc +++ b/src/audit_log.cc @@ -102,11 +102,11 @@ bool AuditLog::setType(AuditLogType audit_type) { bool AuditLog::init() { if (m_type == ParallelAuditLogType) { - m_writer = new AuditLogWriterParallel(); + m_writer = new AuditLogWriterParallel(this); } if (m_type == SerialAuditLogType) { - m_writer = new AuditLogWriterSerial(); + m_writer = new AuditLogWriterSerial(this); } if (m_writer == NULL || m_writer->init() == false) { @@ -134,7 +134,7 @@ bool AuditLog::isRelevant(int status) { bool AuditLog::saveIfRelevant(Assay *assay) { - if (this->isRelevant(assay->http_code_returned) == false && + if (this->isRelevant(assay->httpCodeReturned) == false && assay->save_in_auditlog == false) { return true; } @@ -148,9 +148,7 @@ bool AuditLog::saveIfRelevant(Assay *assay) { return true; } - std::string log = assay->to_json(0); - - m_writer->write(log); + m_writer->write(assay); return true; } diff --git a/src/audit_log.h b/src/audit_log.h index df9a9a17..a21c206a 100644 --- a/src/audit_log.h +++ b/src/audit_log.h @@ -162,12 +162,13 @@ class AuditLog { bool saveIfRelevant(Assay *assay); bool isRelevant(int status); - private: - AuditLogStatus m_status; std::string m_path1; std::string m_path2; std::string m_storage_dir; + private: + AuditLogStatus m_status; + int m_file_permissions; int m_storage_permission; diff --git a/src/audit_log_writer.cc b/src/audit_log_writer.cc index e3667608..2c1967df 100644 --- a/src/audit_log_writer.cc +++ b/src/audit_log_writer.cc @@ -33,8 +33,8 @@ std::string AuditLogWriter::file_name(const std::string& unique_id) { * Temporary print the log into the std::cout to debug purposes. * */ -bool AuditLogWriter::write(const std::string& log) { - std::cout << log << std::endl; +bool AuditLogWriter::write(Assay *assay) { + std::cout << assay->to_json(0) << std::endl; return true; } diff --git a/src/audit_log_writer.h b/src/audit_log_writer.h index e939361f..421ae2bf 100644 --- a/src/audit_log_writer.h +++ b/src/audit_log_writer.h @@ -23,20 +23,28 @@ #include #endif +#include "modsecurity/assay.h" + + #ifdef __cplusplus namespace ModSecurity { +class AuditLog; /** @ingroup ModSecurity_CPP_API */ class AuditLogWriter : public std::ofstream { public: - AuditLogWriter() { } + explicit AuditLogWriter(AuditLog *audit) + : m_audit(audit) { } virtual bool close() { return true; } virtual bool init() { return true; } - virtual bool write(const std::string& log); + virtual bool write(Assay *assay); std::string file_name(const std::string& unique_id); + + protected: + AuditLog *m_audit; }; } // namespace ModSecurity diff --git a/src/audit_log_writer_parallel.cc b/src/audit_log_writer_parallel.cc index 3f12fd56..8f855a60 100644 --- a/src/audit_log_writer_parallel.cc +++ b/src/audit_log_writer_parallel.cc @@ -15,9 +15,83 @@ #include "src/audit_log_writer_parallel.h" +#include +#include +#include + +#include + +#include "src/audit_log.h" +#include "modsecurity/assay.h" +#include "src/utils.h" namespace ModSecurity { +inline std::string AuditLogWriterParallel::logFilePath(time_t *t, + int part) { + struct tm timeinfo; + char tstr[300]; + size_t len; + std::string name(""); + + localtime_r(t, &timeinfo); + + if (part & YearMonthDayDirectory) { + memset(tstr, '\0', 300); + strftime(tstr, 299, "/%Y%m%d", &timeinfo); + name = tstr; + } + + if (part & YearMonthDayAndTimeDirectory) { + memset(tstr, '\0', 300); + strftime(tstr, 299, "/%Y%m%d-%H%M", &timeinfo); + name = name + tstr; + } + + if (part & YearMonthDayAndTimeFileName) { + memset(tstr, '\0', 300); + strftime(tstr, 299, "/%Y%m%d-%H%M%S", &timeinfo); + name = name + tstr; + } + + return name; +} + + +bool AuditLogWriterParallel::init() { + /** TODO:: Check if the directory exists. */ + /** TODO:: Checking if we have permission to write in the target dir */ + return true; +} + + +bool AuditLogWriterParallel::close() { + return true; +} + + +bool AuditLogWriterParallel::write(Assay *assay) { + std::string log = assay->to_json(0); + std::string fileName = logFilePath(&assay->timeStamp, + YearMonthDayDirectory | YearMonthDayAndTimeDirectory + | YearMonthDayAndTimeFileName); + fileName = fileName + "-" + assay->id; + + std::string logPath = m_audit->m_storage_dir; + + createDir((logPath + + logFilePath(&assay->timeStamp, YearMonthDayDirectory)).c_str()); + createDir((logPath + + logFilePath(&assay->timeStamp, YearMonthDayDirectory + | YearMonthDayAndTimeDirectory)).c_str()); + + std::ofstream f; + f.open(logPath + fileName, std::fstream::out | std::fstream::app); + f << log; + f.close(); + + return true; +} } // namespace ModSecurity diff --git a/src/audit_log_writer_parallel.h b/src/audit_log_writer_parallel.h index 796ab9ef..66b795be 100644 --- a/src/audit_log_writer_parallel.h +++ b/src/audit_log_writer_parallel.h @@ -13,10 +13,13 @@ * */ +#include + #ifndef SRC_AUDIT_LOG_WRITER_PARALLEL_H_ #define SRC_AUDIT_LOG_WRITER_PARALLEL_H_ #include "src/audit_log_writer.h" +#include "modsecurity/assay.h" #ifdef __cplusplus @@ -25,7 +28,36 @@ namespace ModSecurity { /** @ingroup ModSecurity_CPP_API */ class AuditLogWriterParallel : public AuditLogWriter { public: - AuditLogWriterParallel() { } + explicit AuditLogWriterParallel(AuditLog *audit) + : AuditLogWriter(audit) { } + + bool init() override; + bool close() override; + bool write(Assay *assay) override; + + /** + * + * Audit log file is saved into a directory structure. This directory + * structure is based on the timestamp of the assay creation, at the exact + * moment that ModSecurity be aware of a particular request/transaction. + * The expect fromat is: + * + * [...]/YearMonthDay/YearMonthDayAndTime/YearMonthDayAndTime-RequestId + * + * Example: + * + * /20150710/20150710-1353/20150710-135353-143654723362.584244 + * + * This enumeration describes the subpaths of this structure. + * + */ + enum AuditLogFilePath { + YearMonthDayDirectory = 2, + YearMonthDayAndTimeDirectory = 4, + YearMonthDayAndTimeFileName = 8, + }; + + inline std::string logFilePath(time_t *t, int part); }; } // namespace ModSecurity diff --git a/src/audit_log_writer_serial.cc b/src/audit_log_writer_serial.cc index b1c02b61..8a365559 100644 --- a/src/audit_log_writer_serial.cc +++ b/src/audit_log_writer_serial.cc @@ -30,7 +30,7 @@ bool AuditLogWriterSerial::close() { } -bool AuditLogWriterSerial::write(const std::string& log) { +bool AuditLogWriterSerial::write(Assay *assay) { return true; } diff --git a/src/audit_log_writer_serial.h b/src/audit_log_writer_serial.h index eff58782..59a07fd0 100644 --- a/src/audit_log_writer_serial.h +++ b/src/audit_log_writer_serial.h @@ -23,6 +23,7 @@ #define SRC_AUDIT_LOG_WRITER_SERIAL_H_ #include "src/audit_log_writer.h" +#include "modsecurity/assay.h" #ifdef __cplusplus @@ -31,11 +32,12 @@ namespace ModSecurity { /** @ingroup ModSecurity_CPP_API */ class AuditLogWriterSerial : public AuditLogWriter { public: - AuditLogWriterSerial() { } + explicit AuditLogWriterSerial(AuditLog *audit) + : AuditLogWriter(audit) { } bool init() override; bool close() override; - bool write(const std::string& log) override; + bool write(Assay *assay) override; }; } // namespace ModSecurity diff --git a/src/utils.cc b/src/utils.cc index 658155a1..06e86240 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -24,6 +24,13 @@ #include #include +#if defined _MSC_VER +#include +#elif defined __GNUC__ +#include +#include +#endif + #include "modsecurity/modsecurity.h" namespace ModSecurity { @@ -62,5 +69,13 @@ std::string ascTime(time_t *t) { } +void createDir(std::string dir) { +#if defined _MSC_VER + _mkdir(dir.data()); +#elif defined __GNUC__ + mkdir(dir.data(), 0777); +#endif +} + } // namespace ModSecurity diff --git a/src/utils.h b/src/utils.h index b68538cc..5368d0f2 100644 --- a/src/utils.h +++ b/src/utils.h @@ -27,6 +27,7 @@ namespace ModSecurity { double random_number(const double from, const double to); double generate_assay_unique_id(); std::string ascTime(time_t *t); + void createDir(std::string dir); } // namespace ModSecurity #define SRC_UTILS_H_ diff --git a/test/regression/regression.cc b/test/regression/regression.cc index a57400bc..d372b70a 100644 --- a/test/regression/regression.cc +++ b/test/regression/regression.cc @@ -139,7 +139,7 @@ void perform_unit_test(std::vector *tests, } end: - modsec_assay->processLogging(); + modsec_assay->processLogging(r.status); CustomDebugLog *d = reinterpret_cast (modsec_rules->debug_log);