From 38b992470503943bee204ab4937edc9f2d2cbb1f Mon Sep 17 00:00:00 2001 From: Felipe Zimmerle Date: Tue, 11 Nov 2014 14:02:00 -0800 Subject: [PATCH] Adds the SecRemoteRulesFailAction directive This directive allows the user to set a default action whenever the SecRemoteRules failed to download a set of rules. Current the supported values are: Warn and Abort. By default `Abort' is selected. --- apache2/apache2_config.c | 31 +++++++++++++++++++++++++++++++ apache2/mod_security2.c | 2 ++ apache2/modsecurity.h | 4 ++++ apache2/msc_remote_rules.c | 27 ++++++++++++++++++++++++--- 4 files changed, 61 insertions(+), 3 deletions(-) diff --git a/apache2/apache2_config.c b/apache2/apache2_config.c index e1506ba8..e9052455 100644 --- a/apache2/apache2_config.c +++ b/apache2/apache2_config.c @@ -2213,6 +2213,28 @@ static const char *cmd_rule_engine(cmd_parms *cmd, void *_dcfg, const char *p1) return NULL; } +static const char *cmd_remote_rules_fail(cmd_parms *cmd, void *_dcfg, const char *p1) +{ + directory_config *dcfg = (directory_config *)_dcfg; + if (dcfg == NULL) return NULL; + + if (strncasecmp(p1, "warn", 4) == 0) + { + remote_rules_fail_action = REMOTE_RULES_WARN_ON_FAIL; + } + else if (strncasecmp(p1, "abort", 5) == 0) + { + remote_rules_fail_action = REMOTE_RULES_ABORT_ON_FAIL; + } + else + { + return apr_psprintf(cmd->pool, "ModSecurity: Invalid value for " \ + "SecRemoteRulesFailAction, expected: Abort or Warn."); + } + + return NULL; +} + static const char *cmd_remote_rules(cmd_parms *cmd, void *_dcfg, const char *p1, const char *p2) { @@ -3552,6 +3574,15 @@ const command_rec module_directives[] = { "key and URI to the remote rules" ), + AP_INIT_TAKE1 ( + "SecRemoteRulesFailAction", + cmd_remote_rules_fail, + NULL, + CMD_SCOPE_ANY, + "Abort or Warn" + ), + + AP_INIT_TAKE1 ( "SecXmlExternalEntity", cmd_xml_external_entity, diff --git a/apache2/mod_security2.c b/apache2/mod_security2.c index 3f601979..86109e30 100644 --- a/apache2/mod_security2.c +++ b/apache2/mod_security2.c @@ -69,6 +69,7 @@ unsigned long int DSOLOCAL msc_pcre_match_limit = 0; unsigned long int DSOLOCAL msc_pcre_match_limit_recursion = 0; msc_remote_rules_server DSOLOCAL *remote_rules_server = NULL; +int DSOLOCAL remote_rules_fail_action = REMOTE_RULES_ABORT_ON_FAIL; int DSOLOCAL status_engine_state = STATUS_ENGINE_DISABLED; @@ -82,6 +83,7 @@ unsigned long int DSOLOCAL conn_write_state_limit = 0; TreeRoot DSOLOCAL *conn_write_state_whitelist = 0; TreeRoot DSOLOCAL *conn_write_state_suspicious_list = 0; + #if defined(WIN32) || defined(VERSION_NGINX) int (*modsecDropAction)(request_rec *r) = NULL; #endif diff --git a/apache2/modsecurity.h b/apache2/modsecurity.h index aebe1189..fa19605b 100644 --- a/apache2/modsecurity.h +++ b/apache2/modsecurity.h @@ -146,6 +146,7 @@ extern DSOLOCAL unsigned long int msc_pcre_match_limit; extern DSOLOCAL unsigned long int msc_pcre_match_limit_recursion; extern DSOLOCAL msc_remote_rules_server *remote_rules_server; +extern DSOLOCAL int remote_rules_fail_action; extern DSOLOCAL int status_engine_state; @@ -198,6 +199,9 @@ extern DSOLOCAL int *unicode_map_table; #define STATUS_ENGINE_ENABLED 1 #define STATUS_ENGINE_DISABLED 0 +#define REMOTE_RULES_ABORT_ON_FAIL 0 +#define REMOTE_RULES_WARN_ON_FAIL 1 + #define HASH_DISABLED 0 #define HASH_ENABLED 1 diff --git a/apache2/msc_remote_rules.c b/apache2/msc_remote_rules.c index 1bdb4258..1d19864d 100644 --- a/apache2/msc_remote_rules.c +++ b/apache2/msc_remote_rules.c @@ -300,8 +300,19 @@ int msc_remote_grab_content(apr_pool_t *mp, const char *uri, const char *key, if (res != CURLE_OK) { - *error_msg = apr_psprintf(mp, "Failed to fetch \"%s\" error: %s ", + if (remote_rules_fail_action == REMOTE_RULES_WARN_ON_FAIL) + { + ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, NULL, + "Failed to fetch \"%s\" error: %s ", + remote_rules_server->uri, curl_easy_strerror(res)); + } + else + { + *error_msg = apr_psprintf(mp, "Failed to fetch \"%s\" " \ + "error: %s ", remote_rules_server->uri, curl_easy_strerror(res)); + } + return -1; } @@ -444,7 +455,8 @@ int msc_remote_decrypt(apr_pool_t *pool, // at least size of IV + Salt if (chunk->size < 16+16+1) { - *error_msg = "Unexpected content."; + *error_msg = "Failed to download rules from a remote server: " \ + "Unexpected content."; return -1; } iv = chunk->memory; @@ -574,6 +586,7 @@ int msc_remote_add_rules_from_uri(cmd_parms *orig_parms, int start = 0; int end = 0; int added_rules = 0; + int res = 0; apr_size_t plain_text_len = 0; apr_pool_t *mp = orig_parms->pool; @@ -581,13 +594,21 @@ int msc_remote_add_rules_from_uri(cmd_parms *orig_parms, chunk_encrypted.size = 0; chunk_encrypted.memory = NULL; - msc_remote_grab_content(mp, remote_rules_server->uri, + res = msc_remote_grab_content(mp, remote_rules_server->uri, remote_rules_server->key, &chunk_encrypted, error_msg); if (*error_msg != NULL) { return -1; } + /* error_msg is not filled when the user set SecRemoteRulesFailAction + * to warn + */ + if (res != 0) + { + return res; + } + msc_remote_decrypt(mp, remote_rules_server->key, &chunk_encrypted, &plain_text, &plain_text_len,