diff --git a/headers/modsecurity/audit_log.h b/headers/modsecurity/audit_log.h index ab1e798dd7..025788ef26 100644 --- a/headers/modsecurity/audit_log.h +++ b/headers/modsecurity/audit_log.h @@ -168,6 +168,7 @@ class AuditLog { bool setType(AuditLogType audit_type); bool init(std::string *error); + bool reopen(std::string *error); virtual bool close(); bool saveIfRelevant(Transaction *transaction); diff --git a/headers/modsecurity/debug_log.h b/headers/modsecurity/debug_log.h index f56bc4c694..95f6c9bd16 100644 --- a/headers/modsecurity/debug_log.h +++ b/headers/modsecurity/debug_log.h @@ -47,6 +47,7 @@ class DebugLog { virtual bool isLogLevelSet(); virtual void setDebugLogLevel(int level); virtual void setDebugLogFile(const std::string &fileName, std::string *error); + virtual bool reopenDebugLogFile(std::string *error); virtual const std::string& getDebugLogFile(); virtual int getDebugLogLevel(); diff --git a/headers/modsecurity/rules_set.h b/headers/modsecurity/rules_set.h index bcf70a17bf..800804d6c3 100644 --- a/headers/modsecurity/rules_set.h +++ b/headers/modsecurity/rules_set.h @@ -105,6 +105,7 @@ int msc_rules_add_file(RulesSet *rules, const char *file, const char **error); int msc_rules_add(RulesSet *rules, const char *plain_rules, const char **error); void msc_rules_error_cleanup(const char *error); int msc_rules_cleanup(RulesSet *rules); +int msc_rules_reopen_logs(RulesSet *rules, const char **error); #ifdef __cplusplus } diff --git a/src/audit_log/audit_log.cc b/src/audit_log/audit_log.cc index 4115d5f34a..ac7b1485d6 100644 --- a/src/audit_log/audit_log.cc +++ b/src/audit_log/audit_log.cc @@ -325,6 +325,14 @@ bool AuditLog::saveIfRelevant(Transaction *transaction, int parts) { } +bool AuditLog::reopen(std::string *error) { + if (m_writer != nullptr) { + return m_writer->reopen(error); + } + return true; +} + + bool AuditLog::close() { return true; } diff --git a/src/audit_log/writer/https.h b/src/audit_log/writer/https.h index 12988953e1..80b1f0837a 100644 --- a/src/audit_log/writer/https.h +++ b/src/audit_log/writer/https.h @@ -42,6 +42,9 @@ class Https : public Writer { bool init(std::string *error) override; bool write(Transaction *transaction, int parts, std::string *error) override; + bool reopen(std::string *error) override { + return true; + } }; } // namespace writer diff --git a/src/audit_log/writer/parallel.cc b/src/audit_log/writer/parallel.cc index 5f3055f4c7..abbbaedca7 100644 --- a/src/audit_log/writer/parallel.cc +++ b/src/audit_log/writer/parallel.cc @@ -195,6 +195,36 @@ bool Parallel::write(Transaction *transaction, int parts, std::string *error) { return true; } + +bool Parallel::reopen(std::string *error) { + bool success1 = true; + bool success2 = true; + std::string error1; + std::string error2; + + if (!m_audit->m_path1.empty()) { + success1 = utils::SharedFiles::getInstance().reopen( + m_audit->m_path1, &error1); + } + if (!m_audit->m_path2.empty()) { + success2 = utils::SharedFiles::getInstance().reopen( + m_audit->m_path2, &error2); + } + + if (!success1 || !success2) { + std::string msg = "Failed to reopen parallel audit logs."; + if (!success1 && !error1.empty()) { + msg += " " + error1; + } + if (!success2 && !error2.empty()) { + msg += " " + error2; + } + error->assign(msg); + } + + return success1 && success2; +} + } // namespace writer } // namespace audit_log } // namespace modsecurity diff --git a/src/audit_log/writer/parallel.h b/src/audit_log/writer/parallel.h index 43423d783e..363fe19580 100644 --- a/src/audit_log/writer/parallel.h +++ b/src/audit_log/writer/parallel.h @@ -40,6 +40,7 @@ class Parallel : public Writer { bool init(std::string *error) override; bool write(Transaction *transaction, int parts, std::string *error) override; + bool reopen(std::string *error) override; /** diff --git a/src/audit_log/writer/serial.cc b/src/audit_log/writer/serial.cc index 9ceddf252b..7215609b3f 100644 --- a/src/audit_log/writer/serial.cc +++ b/src/audit_log/writer/serial.cc @@ -49,6 +49,17 @@ bool Serial::write(Transaction *transaction, int parts, std::string *error) { error); } + +bool Serial::reopen(std::string *error) { + bool success = utils::SharedFiles::getInstance().reopen( + m_audit->m_path1, error); + if (!success) { + std::string detail = *error; + error->assign("Failed to reopen serial audit log. " + detail); + } + return success; +} + } // namespace writer } // namespace audit_log } // namespace modsecurity diff --git a/src/audit_log/writer/serial.h b/src/audit_log/writer/serial.h index 34afa8643d..3d8c475834 100644 --- a/src/audit_log/writer/serial.h +++ b/src/audit_log/writer/serial.h @@ -47,6 +47,7 @@ class Serial : public Writer { bool init(std::string *error) override; bool write(Transaction *transaction, int parts, std::string *error) override; + bool reopen(std::string *error) override; }; } // namespace writer diff --git a/src/audit_log/writer/writer.h b/src/audit_log/writer/writer.h index 56dada0622..4494b9d565 100644 --- a/src/audit_log/writer/writer.h +++ b/src/audit_log/writer/writer.h @@ -51,6 +51,7 @@ class Writer { virtual bool init(std::string *error) = 0; virtual bool write(Transaction *transaction, int parts, std::string *error) = 0; + virtual bool reopen(std::string *error) = 0; static void generateBoundary(std::string *boundary); diff --git a/src/debug_log/debug_log.cc b/src/debug_log/debug_log.cc index e883177ca4..ffc288e848 100644 --- a/src/debug_log/debug_log.cc +++ b/src/debug_log/debug_log.cc @@ -39,6 +39,14 @@ void DebugLog::setDebugLogFile(const std::string& fileName, } +bool DebugLog::reopenDebugLogFile(std::string *error) { + if (!isLogFileSet()) { + return true; + } + return DebugLogWriter::reopen(m_fileName, error); +} + + void DebugLog::setDebugLogLevel(int level) { m_debugLevel = level; } diff --git a/src/debug_log/debug_log_writer.cc b/src/debug_log/debug_log_writer.cc index b7bb1ff265..b9ef21fff4 100644 --- a/src/debug_log/debug_log_writer.cc +++ b/src/debug_log/debug_log_writer.cc @@ -31,6 +31,11 @@ void DebugLogWriter::close(const std::string& fileName) { } +bool DebugLogWriter::reopen(const std::string& fileName, std::string *error) { + return utils::SharedFiles::getInstance().reopen(fileName, error); +} + + void DebugLogWriter::write_log(const std::string& fileName, const std::string &msg) { std::string err; diff --git a/src/debug_log/debug_log_writer.h b/src/debug_log/debug_log_writer.h index 46b641d686..7d9bfdd539 100644 --- a/src/debug_log/debug_log_writer.h +++ b/src/debug_log/debug_log_writer.h @@ -35,6 +35,7 @@ class DebugLogWriter { static void write_log(const std::string& file, const std::string& msg); static void close(const std::string& m_fileName); static int open(const std::string& m_fileName, std::string *error); + static bool reopen(const std::string& fileName, std::string *error); private: DebugLogWriter() = default; diff --git a/src/rules_set.cc b/src/rules_set.cc index 96bfa689ad..c5c0c50ff0 100644 --- a/src/rules_set.cc +++ b/src/rules_set.cc @@ -347,3 +347,39 @@ extern "C" int msc_rules_cleanup(RulesSet *rules) { } // namespace modsecurity + +extern "C" int msc_rules_reopen_logs(modsecurity::RulesSet *rules, + const char **error) { + bool succeeded = true; + std::string errorStr; + + if (rules->m_auditLog != nullptr) { + std::string auditError; + if (!rules->m_auditLog->reopen(&auditError)) { + succeeded = false; + errorStr += auditError; + } + } + + if (rules->m_debugLog != nullptr) { + std::string debugError; + if (!rules->m_debugLog->reopenDebugLogFile(&debugError)) { + succeeded = false; + if (!errorStr.empty()) { + errorStr += " "; + } + errorStr += debugError; + } + } + + if (!succeeded) { + if (!errorStr.empty()) { + *error = strdup(errorStr.c_str()); + } else { + *error = strdup("Unknown error reopening logs"); + } + } + + return succeeded ? 0 : -1; +} + diff --git a/src/utils/shared_files.cc b/src/utils/shared_files.cc index 6982d0d6e9..33e6637a10 100644 --- a/src/utils/shared_files.cc +++ b/src/utils/shared_files.cc @@ -16,10 +16,16 @@ #include "src/utils/shared_files.h" #include +#include +#include #ifdef WIN32 #include #endif +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + namespace modsecurity { namespace utils { @@ -81,6 +87,43 @@ bool SharedFiles::open(const std::string& fileName, std::string *error) { } +bool SharedFiles::reopen(const std::string& fileName, std::string *error) { + auto it = m_handlers.find(fileName); + if (it == m_handlers.end()) { + error->assign("Cannot find open file to reopen: " + fileName); + return false; + } + + struct stat target_stat; + struct stat current_stat; + + if ( + stat(fileName.c_str(), &target_stat) == 0 && + fstat(fileno(it->second.fp), ¤t_stat) == 0 && + current_stat.st_dev == target_stat.st_dev && + current_stat.st_ino == target_stat.st_ino + ) { + return true; + } + + FILE *fp; +#ifdef WIN32 + fopen_s(&fp, fileName.c_str(), "a"); +#else + fp = fopen(fileName.c_str(), "a"); +#endif + if (fp == nullptr) { + error->assign("Failed to reopen file: " + fileName); + return false; + } + + fclose(it->second.fp); + it->second.fp = fp; + + return true; +} + + void SharedFiles::close(const std::string& fileName) { if (fileName.empty()) return; diff --git a/src/utils/shared_files.h b/src/utils/shared_files.h index fcc78c9863..f9dd43fbff 100644 --- a/src/utils/shared_files.h +++ b/src/utils/shared_files.h @@ -33,6 +33,7 @@ namespace utils { class SharedFiles { public: bool open(const std::string& fileName, std::string *error); + bool reopen(const std::string& fileName, std::string *error); void close(const std::string& fileName); bool write(const std::string& fileName, const std::string &msg, std::string *error);