From d9a26780abe3e2d7d40b3c4e1b5cf95e1942dca7 Mon Sep 17 00:00:00 2001 From: brectanus Date: Wed, 25 Apr 2007 20:46:23 +0000 Subject: [PATCH] Add SecAuditLog2 directive (trac #102) --- CHANGES | 3 ++ apache2/apache2_config.c | 58 ++++++++++++++++++++++++++- apache2/modsecurity.h | 5 ++- apache2/msc_logging.c | 11 +++++ doc/modsecurity2-apache-reference.xml | 28 +++++++++++++ 5 files changed, 103 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 0ffc25b2..de9e3909 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,9 @@ ?? ??? 2007 - trunk ------------------- + * Added SecAuditLog2 directive to allow redundent concurrent audit log + index files. This will allow sending audit data to two consoles, etc. + * Removed CGI style HTTP_* variables in favor of REQUEST_HEADERS:Header-Name. * Store filename/line for each rule and display it and the ID (if available) diff --git a/apache2/apache2_config.c b/apache2/apache2_config.c index 5c64b820..0642109b 100644 --- a/apache2/apache2_config.c +++ b/apache2/apache2_config.c @@ -58,7 +58,9 @@ void *create_directory_config(apr_pool_t *mp, char *path) { dcfg->auditlog_flag = NOT_SET; dcfg->auditlog_type = NOT_SET; dcfg->auditlog_name = NOT_SET_P; + dcfg->auditlog2_name = NOT_SET_P; dcfg->auditlog_fd = NOT_SET_P; + dcfg->auditlog2_fd = NOT_SET_P; dcfg->auditlog_storage_dir = NOT_SET_P; dcfg->auditlog_parts = NOT_SET_P; dcfg->auditlog_relevant_regex = NOT_SET_P; @@ -324,6 +326,13 @@ void *merge_directory_configs(apr_pool_t *mp, void *_parent, void *_child) { merged->auditlog_fd = parent->auditlog_fd; merged->auditlog_name = parent->auditlog_name; } + if (child->auditlog2_fd != NOT_SET_P) { + merged->auditlog2_fd = child->auditlog2_fd; + merged->auditlog2_name = child->auditlog2_name; + } else { + merged->auditlog2_fd = parent->auditlog2_fd; + merged->auditlog2_name = parent->auditlog2_name; + } merged->auditlog_storage_dir = (child->auditlog_storage_dir == NOT_SET_P ? parent->auditlog_storage_dir : child->auditlog_storage_dir); merged->auditlog_parts = (child->auditlog_parts == NOT_SET_P @@ -389,7 +398,9 @@ void init_directory_config(directory_config *dcfg) { if (dcfg->auditlog_flag == NOT_SET) dcfg->auditlog_flag = 0; if (dcfg->auditlog_type == NOT_SET) dcfg->auditlog_type = AUDITLOG_SERIAL; if (dcfg->auditlog_fd == NOT_SET_P) dcfg->auditlog_fd = NULL; + if (dcfg->auditlog2_fd == NOT_SET_P) dcfg->auditlog2_fd = NULL; if (dcfg->auditlog_name == NOT_SET_P) dcfg->auditlog_name = NULL; + if (dcfg->auditlog2_name == NOT_SET_P) dcfg->auditlog2_name = NULL; if (dcfg->auditlog_storage_dir == NOT_SET_P) dcfg->auditlog_storage_dir = NULL; if (dcfg->auditlog_parts == NOT_SET_P) dcfg->auditlog_parts = "ABCFHZ"; if (dcfg->auditlog_relevant_regex == NOT_SET_P) dcfg->auditlog_relevant_regex = NULL; @@ -566,6 +577,43 @@ static const char *cmd_audit_log(cmd_parms *cmd, void *_dcfg, const char *p1) { return NULL; } +static const char *cmd_audit_log2(cmd_parms *cmd, void *_dcfg, const char *p1) { + directory_config *dcfg = _dcfg; + + if (dcfg->auditlog_name == NOT_SET_P) { + return apr_psprintf(cmd->pool, "ModSecurity: Cannot configure a secondary audit log without a primary defined: %s", p1); + } + + dcfg->auditlog2_name = (char *)p1; + + if (dcfg->auditlog2_name[0] == '|') { + const char *pipe_name = ap_server_root_relative(cmd->pool, dcfg->auditlog2_name + 1); + piped_log *pipe_log; + + pipe_log = ap_open_piped_log(cmd->pool, pipe_name); + if (pipe_log == NULL) { + return apr_psprintf(cmd->pool, "ModSecurity: Failed to open the secondary audit log pipe: %s", + pipe_name); + } + dcfg->auditlog2_fd = ap_piped_log_write_fd(pipe_log); + } + else { + const char *file_name = ap_server_root_relative(cmd->pool, dcfg->auditlog2_name); + apr_status_t rc; + + rc = apr_file_open(&dcfg->auditlog2_fd, file_name, + APR_WRITE | APR_APPEND | APR_CREATE | APR_BINARY, + CREATEMODE, cmd->pool); + + if (rc != APR_SUCCESS) { + return apr_psprintf(cmd->pool, "ModSecurity: Failed to open the secondary audit log file: %s", + file_name); + } + } + + return NULL; +} + static const char *cmd_audit_log_parts(cmd_parms *cmd, void *_dcfg, const char *p1) { directory_config *dcfg = _dcfg; @@ -1076,7 +1124,15 @@ const command_rec module_directives[] = { cmd_audit_log, NULL, CMD_SCOPE_ANY, - "The filename of the audit log file" + "The filename of the primary audit log file" + ), + + AP_INIT_TAKE1 ( + "SecAuditLog2", + cmd_audit_log2, + NULL, + CMD_SCOPE_ANY, + "The filename of the secondary audit log file" ), AP_INIT_TAKE1 ( diff --git a/apache2/modsecurity.h b/apache2/modsecurity.h index 95f9c6a0..23bec806 100644 --- a/apache2/modsecurity.h +++ b/apache2/modsecurity.h @@ -349,9 +349,12 @@ struct directory_config { * name of the index file (for the new audit log type) */ char *auditlog_name; + /* The name of the secondary index file */ + char *auditlog2_name; - /* The file descriptor for the file above */ + /* The file descriptors for the files above */ apr_file_t *auditlog_fd; + apr_file_t *auditlog2_fd; /* For the new-style audit log only, the path where * audit log entries will be stored diff --git a/apache2/msc_logging.c b/apache2/msc_logging.c index 55abb11b..abe5a2a6 100644 --- a/apache2/msc_logging.c +++ b/apache2/msc_logging.c @@ -886,5 +886,16 @@ void sec_audit_logger(modsec_rec *msr) { if (text == NULL) return; nbytes = strlen(text); + if (msr->txcfg->debuglog_level >= 9) { + msr_log(msr, 9, "Audit Log: Writing %d bytes to primary concurrent index", nbytes); + } apr_file_write_full(msr->txcfg->auditlog_fd, text, nbytes, &nbytes_written); + + /* Write to the secondary audit log if we have one */ + if (msr->txcfg->auditlog2_fd != NULL) { + if (msr->txcfg->debuglog_level >= 9) { + msr_log(msr, 9, "Audit Log: Writing %d bytes to secondary concurrent index", nbytes); + } + apr_file_write_full(msr->txcfg->auditlog2_fd, text, nbytes, &nbytes_written); + } } diff --git a/doc/modsecurity2-apache-reference.xml b/doc/modsecurity2-apache-reference.xml index 351abd44..2e608548 100644 --- a/doc/modsecurity2-apache-reference.xml +++ b/doc/modsecurity2-apache-reference.xml @@ -568,6 +568,34 @@ SecAuditLogStorageDir logs/audit "|/path/modsec-auditlog-collector.pl /path/SecAuditLogDataDir /path/SecAuditLog" +
+ <literal>SecAuditLog2</literal> + + Description: Defines the path to + the secondary audit log index file when concurrent logging is enabled. + See SecAuditLog2 for more + details. + + Syntax: SecAuditLog2 /path/to/auditlog2 + + Example Usage: SecAuditLog2 + /usr/local/apache/logs/audit2.log + + Processing Phase: N/A + + Scope: + Any + + Dependencies/Notes: A main audit + log must be defined via SecAuditLog + before this directive may be used. Additionally, this log is only used + for replicating the main audit log index file when concurrent audit + logging is used. It will not be used + for non-concurrent audit logging. +
+
<literal>SecAuditLogParts</literal>