Update trunk for 2.7
This commit is contained in:
Родитель
4bebeb6dd7
Коммит
866cb6d6b4
116
CHANGES
116
CHANGES
|
@ -1,3 +1,117 @@
|
|||
XX NNN 2012 - 2.7.0-rc1
|
||||
-------------------
|
||||
|
||||
* Added SecEncryptionEngine. Initial crypt engine support, at the momment it will sign some Html
|
||||
and Response Header options.
|
||||
|
||||
* Added SecEncryptionKey to define the a rand or static key for crypt engine.
|
||||
|
||||
* Added SecEncryptionParam to define the new parameter name.
|
||||
|
||||
* Added SecEncryptionMethodRx used with a regular expression to inspect the html in response
|
||||
body/header and decide what to protect.
|
||||
|
||||
* Added SecEncryptionMethodPm used with multiple or single strings to inspect the html in response
|
||||
body/header and decide what to protect.
|
||||
|
||||
* Added ctl encryptionEngine as a per transaction version of SecEncryptionEgine diretive.
|
||||
|
||||
* Added ctl encryptionEnforcement that will allow the engine to sign the data but the enforcement is
|
||||
disabled.
|
||||
|
||||
* Added validateEncryption operator to enforce the signed elements.
|
||||
|
||||
* Added rsub operator supports the syntax |hex| allowing users to use special chars like \n \r.
|
||||
|
||||
* Added SecRuleUpdateTargetById now supports id range.
|
||||
|
||||
* Added SecRuleUpdateTargetByMsg and its ctl version (Thanks Scott Gifford).
|
||||
|
||||
* Added SecRuleUpdateTargetByTag and its ctl version (Thanks Scott Gifford).
|
||||
|
||||
* Added SecRulePerfTime when greater than zero it will fill rule id's execution time into PERF_RULE
|
||||
and log id=usec information in the new Perf-rule-info: line in part H.
|
||||
|
||||
* Added PERF_RULES variable that contains rule execution time.
|
||||
|
||||
* Added Engine-mode: section in part H.
|
||||
|
||||
* Added ruleRemoveByMsg ctl version.
|
||||
|
||||
* Added removeCommentsChar and removeComments now can work with <!-- --> style.
|
||||
|
||||
* Added SecArgumentSeparator and SecCookieFormat can be used in different scope locations.
|
||||
|
||||
* Added Rules must have ID action and must be numeric.
|
||||
|
||||
* Added The use of tfns are deprecated in SecDefaultAction. Should be forbid in the future.
|
||||
|
||||
* Added Macro expansion support to the action pause.
|
||||
|
||||
* Added IpmatchFromFile/IpmatchF operator.
|
||||
|
||||
* Added New setrsc action, the RESOURCE collection used SecWebAppId Name Space
|
||||
|
||||
* Added Configure option --enable-cache-lua that allows reuse of Lua VM per transaction.
|
||||
It will only take any effect when ModSecurity has multiple scripts to run per transaction.
|
||||
|
||||
* Added Configure option --enable-pcre-jit that allows ModSecurity regex engine to use PCRE Jit support.
|
||||
|
||||
* Added Configure option --enable-request-early that allows ModSecurity run phase 1 in post_read_request hook.
|
||||
|
||||
* Added RBL operator now support the httpBl api (http://www.projecthoneypot.org/httpbl_api.php).
|
||||
|
||||
* Added SecHttpBlKey to be used with httpBl api.
|
||||
|
||||
* Added SecSensorId will specify the modsecurity sensor name into audit log part H.
|
||||
|
||||
* Added aliases to phase:2 (phase:request), phase:4 (phase:response) and phase:5 (phase:logging).
|
||||
|
||||
* Added USERAGENT_IP variable. Created when Apache24 is used with mod_remoteip to know the real
|
||||
client ip address.
|
||||
|
||||
* Fixed Variable DURATION contains the elapsed time in microseconds for compatible reasons with apache and
|
||||
other variables.
|
||||
|
||||
* Fixed Preserve names/identity of the variables going into MATCHED_VARS.
|
||||
|
||||
* Fixed Redirect macro expansion does not work in SecDefaultAction when SecRule uses block action.
|
||||
|
||||
* Fixed rsub operator does not work as expect if regex contains parentheses (Thanks Jerome Freilinger).
|
||||
|
||||
* Current Google Safe Browsing implementation is deprecated. Google changed the API and does not allow
|
||||
anymore the malware database for download.
|
||||
|
||||
20 Mar 2012 - 2.6.5
|
||||
-------------------
|
||||
|
||||
* Fixed increased a specific message debug level in SBDM code (MODSEC-293).
|
||||
|
||||
* Cleanup build system.
|
||||
|
||||
09 Mar 2012 - 2.6.4
|
||||
-------------------
|
||||
|
||||
* Fixed Mlogc 100% CPU consume (Thanks Klaubert Herr and Ebrahim Khalilzadeh).
|
||||
|
||||
* Fixed ModSecurity cannot load session and user sdbm data.
|
||||
|
||||
* Fixed updateTargetById was creating rule unparsed content making apache memory grow.
|
||||
|
||||
* Code cleanup.
|
||||
|
||||
23 Feb 2012 - 2.6.4-rc1
|
||||
-------------------
|
||||
|
||||
* Fixed @rsub adding garbage data into stream variables.
|
||||
|
||||
* Fixed regex for section A into mlogc-batch-load.pl (Thanks Ebrahim Khalilzadeh).
|
||||
|
||||
* Fixed logdata cuts message without closing it with final chars.
|
||||
|
||||
* Added sanitizeMatchedBytes support to verifyCPF, verifyCC and verifySSN.
|
||||
|
||||
|
||||
06 Dec 2011 - 2.6.3-rc1
|
||||
-------------------
|
||||
|
||||
|
@ -29,7 +143,7 @@
|
|||
|
||||
* Added new transformations removeComments and removeCommentsChars
|
||||
|
||||
* Fixed collection names are not case-sensitive anymore.
|
||||
* Fixed colletion names are not case-sensitive anymore.
|
||||
|
||||
* Fixed compilation errors with apache 2.0.
|
||||
|
||||
|
|
|
@ -26,8 +26,9 @@ MAINTAINERCLEANFILES += $(CLEANFILES) \
|
|||
ext/Makefile.in \
|
||||
mlogc/Makefile.in \
|
||||
modsecurity_config_auto.h.in~ \
|
||||
tests/Makefile.in \
|
||||
tools/Makefile.in
|
||||
config.log \
|
||||
Makefile \
|
||||
config.status
|
||||
|
||||
# Alias for "check"
|
||||
test: check
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
#include "msc_logging.h"
|
||||
#include "msc_util.h"
|
||||
#include "http_log.h"
|
||||
#include "apr_lib.h"
|
||||
#include "acmp.h"
|
||||
#include "msc_crypt.h"
|
||||
|
||||
#if defined(WITH_LUA)
|
||||
#include "msc_lua.h"
|
||||
|
@ -64,10 +67,12 @@ void *create_directory_config(apr_pool_t *mp, char *path)
|
|||
|
||||
dcfg->rule_inheritance = NOT_SET;
|
||||
dcfg->rule_exceptions = apr_array_make(mp, 16, sizeof(rule_exception *));
|
||||
dcfg->encryption_method = apr_array_make(mp, 16, sizeof(encryption_method *));
|
||||
|
||||
/* audit log variables */
|
||||
dcfg->auditlog_flag = NOT_SET;
|
||||
dcfg->auditlog_type = NOT_SET;
|
||||
dcfg->max_rule_time = NOT_SET;
|
||||
dcfg->auditlog_dirperms = NOT_SET;
|
||||
dcfg->auditlog_fileperms = NOT_SET;
|
||||
dcfg->auditlog_name = NOT_SET_P;
|
||||
|
@ -96,6 +101,7 @@ void *create_directory_config(apr_pool_t *mp, char *path)
|
|||
/* Misc */
|
||||
dcfg->data_dir = NOT_SET_P;
|
||||
dcfg->webappid = NOT_SET_P;
|
||||
dcfg->sensor_id = NOT_SET_P;
|
||||
dcfg->httpBlkey = NOT_SET_P;
|
||||
|
||||
/* Content injection. */
|
||||
|
@ -129,6 +135,23 @@ void *create_directory_config(apr_pool_t *mp, char *path)
|
|||
/* Collection timeout */
|
||||
dcfg->col_timeout = NOT_SET;
|
||||
|
||||
dcfg->crypto_key = NOT_SET_P;
|
||||
dcfg->crypto_key_add = NOT_SET;
|
||||
dcfg->crypto_param_name = NOT_SET_P;
|
||||
dcfg->encryption_is_enabled = NOT_SET;
|
||||
dcfg->encryption_enforcement = NOT_SET;
|
||||
dcfg->crypto_hash_href_rx = NOT_SET;
|
||||
dcfg->crypto_hash_faction_rx = NOT_SET;
|
||||
dcfg->crypto_hash_location_rx = NOT_SET;
|
||||
dcfg->crypto_hash_iframesrc_rx = NOT_SET;
|
||||
dcfg->crypto_hash_framesrc_rx = NOT_SET;
|
||||
dcfg->crypto_hash_href_pm = NOT_SET;
|
||||
dcfg->crypto_hash_faction_pm = NOT_SET;
|
||||
dcfg->crypto_hash_location_pm = NOT_SET;
|
||||
dcfg->crypto_hash_iframesrc_pm = NOT_SET;
|
||||
dcfg->crypto_hash_framesrc_pm = NOT_SET;
|
||||
|
||||
|
||||
return dcfg;
|
||||
}
|
||||
|
||||
|
@ -422,11 +445,16 @@ void *merge_directory_configs(apr_pool_t *mp, void *_parent, void *_child)
|
|||
merged->rule_exceptions = apr_array_append(mp, parent->rule_exceptions,
|
||||
child->rule_exceptions);
|
||||
|
||||
merged->encryption_method = apr_array_append(mp, parent->encryption_method,
|
||||
child->encryption_method);
|
||||
|
||||
/* audit log variables */
|
||||
merged->auditlog_flag = (child->auditlog_flag == NOT_SET
|
||||
? parent->auditlog_flag : child->auditlog_flag);
|
||||
merged->auditlog_type = (child->auditlog_type == NOT_SET
|
||||
? parent->auditlog_type : child->auditlog_type);
|
||||
merged->max_rule_time = (child->max_rule_time == NOT_SET
|
||||
? parent->max_rule_time : child->max_rule_time);
|
||||
merged->auditlog_dirperms = (child->auditlog_dirperms == NOT_SET
|
||||
? parent->auditlog_dirperms : child->auditlog_dirperms);
|
||||
merged->auditlog_fileperms = (child->auditlog_fileperms == NOT_SET
|
||||
|
@ -471,6 +499,8 @@ void *merge_directory_configs(apr_pool_t *mp, void *_parent, void *_child)
|
|||
? parent->data_dir : child->data_dir);
|
||||
merged->webappid = (child->webappid == NOT_SET_P
|
||||
? parent->webappid : child->webappid);
|
||||
merged->sensor_id = (child->sensor_id == NOT_SET_P
|
||||
? parent->sensor_id : child->sensor_id);
|
||||
merged->httpBlkey = (child->httpBlkey == NOT_SET_P
|
||||
? parent->httpBlkey : child->httpBlkey);
|
||||
|
||||
|
@ -521,6 +551,38 @@ void *merge_directory_configs(apr_pool_t *mp, void *_parent, void *_child)
|
|||
merged->col_timeout = (child->col_timeout == NOT_SET
|
||||
? parent->col_timeout : child->col_timeout);
|
||||
|
||||
/* Encryption */
|
||||
merged->crypto_key = (child->crypto_key == NOT_SET_P
|
||||
? parent->crypto_key : child->crypto_key);
|
||||
merged->crypto_key_add = (child->crypto_key_add == NOT_SET
|
||||
? parent->crypto_key_add : child->crypto_key_add);
|
||||
merged->crypto_param_name = (child->crypto_param_name == NOT_SET_P
|
||||
? parent->crypto_param_name : child->crypto_param_name);
|
||||
merged->encryption_is_enabled = (child->encryption_is_enabled == NOT_SET
|
||||
? parent->encryption_is_enabled : child->encryption_is_enabled);
|
||||
merged->encryption_enforcement = (child->encryption_enforcement == NOT_SET
|
||||
? parent->encryption_enforcement : child->encryption_enforcement);
|
||||
merged->crypto_hash_href_rx = (child->crypto_hash_href_rx == NOT_SET
|
||||
? parent->crypto_hash_href_rx : child->crypto_hash_href_rx);
|
||||
merged->crypto_hash_faction_rx = (child->crypto_hash_faction_rx == NOT_SET
|
||||
? parent->crypto_hash_faction_rx : child->crypto_hash_faction_rx);
|
||||
merged->crypto_hash_location_rx = (child->crypto_hash_location_rx == NOT_SET
|
||||
? parent->crypto_hash_location_rx : child->crypto_hash_location_rx);
|
||||
merged->crypto_hash_iframesrc_rx = (child->crypto_hash_iframesrc_rx == NOT_SET
|
||||
? parent->crypto_hash_iframesrc_rx : child->crypto_hash_iframesrc_rx);
|
||||
merged->crypto_hash_framesrc_rx = (child->crypto_hash_framesrc_rx == NOT_SET
|
||||
? parent->crypto_hash_framesrc_rx : child->crypto_hash_framesrc_rx);
|
||||
merged->crypto_hash_href_pm = (child->crypto_hash_href_pm == NOT_SET
|
||||
? parent->crypto_hash_href_pm : child->crypto_hash_href_pm);
|
||||
merged->crypto_hash_faction_pm = (child->crypto_hash_faction_pm == NOT_SET
|
||||
? parent->crypto_hash_faction_pm : child->crypto_hash_faction_pm);
|
||||
merged->crypto_hash_location_pm = (child->crypto_hash_location_pm == NOT_SET
|
||||
? parent->crypto_hash_location_pm : child->crypto_hash_location_pm);
|
||||
merged->crypto_hash_iframesrc_pm = (child->crypto_hash_iframesrc_pm == NOT_SET
|
||||
? parent->crypto_hash_iframesrc_pm : child->crypto_hash_iframesrc_pm);
|
||||
merged->crypto_hash_framesrc_pm = (child->crypto_hash_framesrc_pm == NOT_SET
|
||||
? parent->crypto_hash_framesrc_pm : child->crypto_hash_framesrc_pm);
|
||||
|
||||
return merged;
|
||||
}
|
||||
|
||||
|
@ -568,6 +630,7 @@ void init_directory_config(directory_config *dcfg)
|
|||
/* audit log variables */
|
||||
if (dcfg->auditlog_flag == NOT_SET) dcfg->auditlog_flag = 0;
|
||||
if (dcfg->auditlog_type == NOT_SET) dcfg->auditlog_type = AUDITLOG_SERIAL;
|
||||
if (dcfg->max_rule_time == NOT_SET) dcfg->max_rule_time = 0;
|
||||
if (dcfg->auditlog_dirperms == NOT_SET) dcfg->auditlog_dirperms = CREATEMODE_DIR;
|
||||
if (dcfg->auditlog_fileperms == NOT_SET) dcfg->auditlog_fileperms = CREATEMODE;
|
||||
if (dcfg->auditlog_fd == NOT_SET_P) dcfg->auditlog_fd = NULL;
|
||||
|
@ -589,6 +652,7 @@ void init_directory_config(directory_config *dcfg)
|
|||
/* Misc */
|
||||
if (dcfg->data_dir == NOT_SET_P) dcfg->data_dir = NULL;
|
||||
if (dcfg->webappid == NOT_SET_P) dcfg->webappid = "default";
|
||||
if (dcfg->sensor_id == NOT_SET_P) dcfg->sensor_id = "default";
|
||||
if (dcfg->httpBlkey == NOT_SET_P) dcfg->httpBlkey = NULL;
|
||||
|
||||
/* Content injection. */
|
||||
|
@ -619,6 +683,24 @@ void init_directory_config(directory_config *dcfg)
|
|||
if (dcfg->disable_backend_compression == NOT_SET) dcfg->disable_backend_compression = 0;
|
||||
|
||||
if (dcfg->col_timeout == NOT_SET) dcfg->col_timeout = 3600;
|
||||
|
||||
/* Encryption */
|
||||
if (dcfg->crypto_key == NOT_SET_P) dcfg->crypto_key = getkey(dcfg->mp);
|
||||
if (dcfg->crypto_key_add == NOT_SET) dcfg->crypto_key_add = ENCRYPTION_KEYONLY;
|
||||
if (dcfg->crypto_param_name == NOT_SET_P) dcfg->crypto_param_name = "crypt";
|
||||
if (dcfg->encryption_is_enabled == NOT_SET) dcfg->encryption_is_enabled = ENCRYPTION_DISABLED;
|
||||
if (dcfg->encryption_enforcement == NOT_SET) dcfg->encryption_enforcement = ENCRYPTION_DISABLED;
|
||||
if (dcfg->crypto_hash_href_rx == NOT_SET) dcfg->crypto_hash_href_rx = 0;
|
||||
if (dcfg->crypto_hash_faction_rx == NOT_SET) dcfg->crypto_hash_faction_rx = 0;
|
||||
if (dcfg->crypto_hash_location_rx == NOT_SET) dcfg->crypto_hash_location_rx = 0;
|
||||
if (dcfg->crypto_hash_iframesrc_rx == NOT_SET) dcfg->crypto_hash_iframesrc_rx = 0;
|
||||
if (dcfg->crypto_hash_framesrc_rx == NOT_SET) dcfg->crypto_hash_framesrc_rx = 0;
|
||||
if (dcfg->crypto_hash_href_pm == NOT_SET) dcfg->crypto_hash_href_pm = 0;
|
||||
if (dcfg->crypto_hash_faction_pm == NOT_SET) dcfg->crypto_hash_faction_pm = 0;
|
||||
if (dcfg->crypto_hash_location_pm == NOT_SET) dcfg->crypto_hash_location_pm = 0;
|
||||
if (dcfg->crypto_hash_iframesrc_pm == NOT_SET) dcfg->crypto_hash_iframesrc_pm = 0;
|
||||
if (dcfg->crypto_hash_framesrc_pm == NOT_SET) dcfg->crypto_hash_framesrc_pm = 0;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -628,8 +710,9 @@ static const char *add_rule(cmd_parms *cmd, directory_config *dcfg, int type,
|
|||
const char *p1, const char *p2, const char *p3)
|
||||
{
|
||||
char *my_error_msg = NULL;
|
||||
msre_rule *rule = NULL;
|
||||
msre_rule *rule = NULL, *tmp_rule = NULL;
|
||||
extern msc_engine *modsecurity;
|
||||
int offset = 0;
|
||||
|
||||
#ifdef DEBUG_CONF
|
||||
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_NOERRNO, 0, cmd->pool,
|
||||
|
@ -660,6 +743,32 @@ static const char *add_rule(cmd_parms *cmd, directory_config *dcfg, int type,
|
|||
return my_error_msg;
|
||||
}
|
||||
|
||||
/* Rules must have uniq ID */
|
||||
if (
|
||||
#if defined(WITH_LUA)
|
||||
type != RULE_TYPE_LUA &&
|
||||
#endif
|
||||
(dcfg->tmp_chain_starter == NULL))
|
||||
if(rule->actionset == NULL)
|
||||
return "Rules must have at least id action";
|
||||
|
||||
if(rule->actionset != NULL && (dcfg->tmp_chain_starter == NULL)) {
|
||||
if(rule->actionset->id == NOT_SET_P
|
||||
#if defined(WITH_LUA)
|
||||
&& (type != RULE_TYPE_LUA)
|
||||
#endif
|
||||
)
|
||||
return "No action id present within the rule";
|
||||
#if defined(WITH_LUA)
|
||||
if(type != RULE_TYPE_LUA)
|
||||
#endif
|
||||
{
|
||||
tmp_rule = msre_ruleset_fetch_rule(dcfg->ruleset, rule->actionset->id, offset);
|
||||
if(tmp_rule != NULL)
|
||||
return "Found another rule with the same id";
|
||||
}
|
||||
}
|
||||
|
||||
/* Create default actionset if one does not already exist. */
|
||||
if (dcfg->tmp_default_actionset == NULL) {
|
||||
dcfg->tmp_default_actionset = msre_actionset_create_default(modsecurity->msre);
|
||||
|
@ -1261,6 +1370,16 @@ static const char *cmd_debug_log(cmd_parms *cmd, void *_dcfg, const char *p1)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Add SecCollectionTimeout configuration option
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
* \param _dcfg Pointer to directory configuration
|
||||
* \param p1 Pointer to configuration option
|
||||
*
|
||||
* \retval NULL On failure
|
||||
* \retval apr_psprintf On Success
|
||||
*/
|
||||
static const char *cmd_collection_timeout(cmd_parms *cmd, void *_dcfg,
|
||||
const char *p1)
|
||||
{
|
||||
|
@ -1329,6 +1448,14 @@ static const char *cmd_default_action(cmd_parms *cmd, void *_dcfg,
|
|||
cmd->directive->filename, cmd->directive->line_num);
|
||||
}
|
||||
|
||||
if (apr_table_get(dcfg->tmp_default_actionset->actions, "t")) {
|
||||
ap_log_perror(APLOG_MARK,
|
||||
APLOG_STARTUP|APLOG_WARNING|APLOG_NOERRNO, 0, cmd->pool,
|
||||
"ModSecurity: WARNING Using transformations in "
|
||||
"SecDefaultAction is deprecated (%s:%d).",
|
||||
cmd->directive->filename, cmd->directive->line_num);
|
||||
}
|
||||
|
||||
/* Must not use chain. */
|
||||
if (dcfg->tmp_default_actionset->is_chained != NOT_SET) {
|
||||
return apr_psprintf(cmd->pool, "ModSecurity: SecDefaultAction must not "
|
||||
|
@ -1409,7 +1536,7 @@ static const char *cmd_guardian_log(cmd_parms *cmd, void *_dcfg,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* \brief Add SecStreamInBodyInspection configuration option
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
|
@ -1428,7 +1555,7 @@ static const char *cmd_stream_inbody_inspection(cmd_parms *cmd, void *_dcfg, int
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
* \brief Add SecStreamOutBodyInspection configuration option
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
|
@ -1445,8 +1572,35 @@ static const char *cmd_stream_outbody_inspection(cmd_parms *cmd, void *_dcfg, in
|
|||
dcfg->stream_outbody_inspection = flag;
|
||||
return NULL;
|
||||
}
|
||||
/**
|
||||
* \brief Add SecRulePerfTime configuration option
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
* \param _dcfg Pointer to directory configuration
|
||||
* \param p1 Pointer to configuration option
|
||||
*
|
||||
* \retval NULL On failure
|
||||
* \retval apr_psprintf On Success
|
||||
*/
|
||||
static const char *cmd_rule_perf_time(cmd_parms *cmd, void *_dcfg,
|
||||
const char *p1)
|
||||
{
|
||||
directory_config *dcfg = (directory_config *)_dcfg;
|
||||
long int limit;
|
||||
|
||||
/*
|
||||
if (dcfg == NULL) return NULL;
|
||||
|
||||
limit = strtol(p1, NULL, 10);
|
||||
if ((limit == LONG_MAX)||(limit == LONG_MIN)||(limit <= 0)) {
|
||||
return apr_psprintf(cmd->pool, "ModSecurity: Invalid value for SecRulePerfTime: %s", p1);
|
||||
}
|
||||
|
||||
dcfg->max_rule_time = limit;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Add SecReadStateLimit configuration option
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
|
@ -1474,7 +1628,7 @@ static const char *cmd_conn_read_state_limit(cmd_parms *cmd, void *_dcfg,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* \brief Add SecWriteStateLimit configuration option
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
|
@ -1572,6 +1726,16 @@ static const char *cmd_request_body_access(cmd_parms *cmd, void *_dcfg,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Add SecInterceptOnError configuration option
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
* \param _dcfg Pointer to directory configuration
|
||||
* \param p1 Pointer to configuration option
|
||||
*
|
||||
* \retval NULL On failure
|
||||
* \retval apr_psprintf On success
|
||||
*/
|
||||
static const char *cmd_request_intercept_on_error(cmd_parms *cmd, void *_dcfg,
|
||||
const char *p1)
|
||||
{
|
||||
|
@ -1656,6 +1820,16 @@ static const char *cmd_response_body_limit_action(cmd_parms *cmd, void *_dcfg,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Add SecRequestBodyLimitAction configuration option
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
* \param _dcfg Pointer to directory configuration
|
||||
* \param p1 Pointer to configuration option
|
||||
*
|
||||
* \retval NULL On failure
|
||||
* \retval apr_psprintf On success
|
||||
*/
|
||||
static const char *cmd_resquest_body_limit_action(cmd_parms *cmd, void *_dcfg,
|
||||
const char *p1)
|
||||
{
|
||||
|
@ -1709,23 +1883,107 @@ static const char *cmd_response_body_mime_types_clear(cmd_parms *cmd,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* \brief Add SecRuleUpdateTargetById
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
* \param _dcfg Pointer to directory configuration
|
||||
* \param p1 Pointer to configuration option
|
||||
* \param p2 Pointer to configuration option
|
||||
* \param p3 Pointer to configuration option
|
||||
*
|
||||
* \retval NULL On failure|Success
|
||||
*/
|
||||
/**
|
||||
* \brief Add SecRuleUpdateTargetById
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
* \param _dcfg Pointer to directory configuration
|
||||
* \param p1 Pointer to configuration option
|
||||
* \param p2 Pointer to configuration option
|
||||
* \param p3 Pointer to configuration option
|
||||
*
|
||||
* \retval NULL On failure|Success
|
||||
*/
|
||||
static const char *cmd_rule_update_target_by_id(cmd_parms *cmd, void *_dcfg,
|
||||
const char *p1, const char *p2, const char *p3)
|
||||
{
|
||||
return update_rule_target(cmd, (directory_config *)_dcfg, NULL, p1, p2, p3);
|
||||
directory_config *dcfg = (directory_config *)_dcfg;
|
||||
rule_exception *re = apr_pcalloc(cmd->pool, sizeof(rule_exception));
|
||||
if (dcfg == NULL) return NULL;
|
||||
|
||||
if(p1 == NULL) {
|
||||
return apr_psprintf(cmd->pool, "Updating target by ID with no ID");
|
||||
}
|
||||
|
||||
re->type = RULE_EXCEPTION_REMOVE_ID;
|
||||
/* TODO: Validate the range here, while we can still tell the user if it's invalid */
|
||||
re->param = p1;
|
||||
|
||||
return msre_ruleset_rule_update_target_matching_exception(NULL, dcfg->ruleset, re, p2, p3);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Add SecRuleUpdateTargetByTag configuration option
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
* \param _dcfg Pointer to directory configuration
|
||||
* \param p1 Pointer to configuration option RULETAG
|
||||
* \param p2 Pointer to configuration option TARGET
|
||||
* \param p3 Pointer to configuration option REPLACED_TARGET
|
||||
* \todo Finish documenting
|
||||
*
|
||||
* \retval NULL On success
|
||||
* \retval apr_psprintf On failure
|
||||
*
|
||||
* \todo Figure out error checking
|
||||
*/
|
||||
static const char *cmd_rule_update_target_by_tag(cmd_parms *cmd, void *_dcfg,
|
||||
const char *p1, const char *p2, const char *p3)
|
||||
{
|
||||
directory_config *dcfg = (directory_config *)_dcfg;
|
||||
rule_exception *re = apr_pcalloc(cmd->pool, sizeof(rule_exception));
|
||||
if (dcfg == NULL) return NULL;
|
||||
|
||||
if(p1 == NULL) {
|
||||
return apr_psprintf(cmd->pool, "Updating target by tag with no tag");
|
||||
}
|
||||
|
||||
re->type = RULE_EXCEPTION_REMOVE_TAG;
|
||||
re->param = p1;
|
||||
re->param_data = msc_pregcomp(cmd->pool, p1, 0, NULL, NULL);
|
||||
if (re->param_data == NULL) {
|
||||
return apr_psprintf(cmd->pool, "ModSecurity: Invalid regular expression: %s", p1);
|
||||
}
|
||||
|
||||
return msre_ruleset_rule_update_target_matching_exception(NULL, dcfg->ruleset, re, p2, p3);
|
||||
}
|
||||
/**
|
||||
* \brief Add SecRuleUpdateTargetByMsg configuration option
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
* \param _dcfg Pointer to directory configuration
|
||||
* \param p1 Pointer to configuration option RULEMSG
|
||||
* \param p2 Pointer to configuration option TARGET
|
||||
* \param p3 Pointer to configuration option REPLACED_TARGET
|
||||
* \todo Finish documenting
|
||||
*
|
||||
* \retval NULL On success
|
||||
* \retval apr_psprintf On failure
|
||||
*
|
||||
* \todo Figure out error checking
|
||||
*/
|
||||
static const char *cmd_rule_update_target_by_msg(cmd_parms *cmd, void *_dcfg,
|
||||
const char *p1, const char *p2, const char *p3)
|
||||
{
|
||||
directory_config *dcfg = (directory_config *)_dcfg;
|
||||
rule_exception *re = apr_pcalloc(cmd->pool, sizeof(rule_exception));
|
||||
if (dcfg == NULL) return NULL;
|
||||
|
||||
if(p1 == NULL) {
|
||||
return apr_psprintf(cmd->pool, "Updating target by message with no message");
|
||||
}
|
||||
|
||||
re->type = RULE_EXCEPTION_REMOVE_MSG;
|
||||
re->param = p1;
|
||||
re->param_data = msc_pregcomp(cmd->pool, p1, 0, NULL, NULL);
|
||||
if (re->param_data == NULL) {
|
||||
return apr_psprintf(cmd->pool, "ModSecurity: Invalid regular expression: %s", p1);
|
||||
}
|
||||
|
||||
return msre_ruleset_rule_update_target_matching_exception(NULL, dcfg->ruleset, re, p2, p3);
|
||||
}
|
||||
|
||||
|
||||
static const char *cmd_rule(cmd_parms *cmd, void *_dcfg,
|
||||
const char *p1, const char *p2, const char *p3)
|
||||
{
|
||||
|
@ -1788,6 +2046,16 @@ static const char *cmd_rule_remove_by_id(cmd_parms *cmd, void *_dcfg,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Add SecRuleRemoveByTag configuration option
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
* \param _dcfg Pointer to directory configuration
|
||||
* \param p1 Pointer to configuration option
|
||||
*
|
||||
* \retval NULL On failure
|
||||
* \retval apr_psprintf On success
|
||||
*/
|
||||
static const char *cmd_rule_remove_by_tag(cmd_parms *cmd, void *_dcfg,
|
||||
const char *p1)
|
||||
{
|
||||
|
@ -1965,6 +2233,277 @@ static const char *cmd_web_app_id(cmd_parms *cmd, void *_dcfg, const char *p1)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *cmd_sensor_id(cmd_parms *cmd, void *_dcfg, const char *p1)
|
||||
{
|
||||
directory_config *dcfg = (directory_config *)_dcfg;
|
||||
|
||||
/* ENH enforce format (letters, digits, ., _, -) */
|
||||
dcfg->sensor_id = p1;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Add SecEncryption configuration option
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
* \param _dcfg Pointer to directory configuration
|
||||
* \param p1 Pointer to configuration option
|
||||
*
|
||||
* \retval NULL On failure
|
||||
* \retval apr_psprintf On Success
|
||||
*/
|
||||
static const char *cmd_encryption_engine(cmd_parms *cmd, void *_dcfg, const char *p1)
|
||||
{
|
||||
directory_config *dcfg = (directory_config *)_dcfg;
|
||||
if (dcfg == NULL) return NULL;
|
||||
|
||||
if (strcasecmp(p1, "on") == 0) {
|
||||
dcfg->encryption_is_enabled = ENCRYPTION_ENABLED;
|
||||
dcfg->encryption_enforcement = ENCRYPTION_ENABLED;
|
||||
}
|
||||
else if (strcasecmp(p1, "off") == 0) {
|
||||
dcfg->encryption_is_enabled = ENCRYPTION_DISABLED;
|
||||
dcfg->encryption_enforcement = ENCRYPTION_DISABLED;
|
||||
}
|
||||
else return apr_psprintf(cmd->pool, "ModSecurity: Invalid value for SecRuleEngine: %s", p1);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Add SecEncryptionPram configuration option
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
* \param _dcfg Pointer to directory configuration
|
||||
* \param p1 Pointer to configuration option
|
||||
*
|
||||
* \retval NULL On success
|
||||
*/
|
||||
static const char *cmd_encryption_param(cmd_parms *cmd, void *_dcfg, const char *p1)
|
||||
{
|
||||
directory_config *dcfg = (directory_config *)_dcfg;
|
||||
|
||||
if (dcfg == NULL) return NULL;
|
||||
|
||||
if (p1 == NULL) return NULL;
|
||||
dcfg->crypto_param_name = p1;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Add SecEncryptionKey configuration option
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
* \param _dcfg Pointer to directory configuration
|
||||
* \param _p1 Pointer to configuration option
|
||||
* \param _p2 Pointer to configuration option
|
||||
*
|
||||
* \retval NULL On success
|
||||
*/
|
||||
static const char *cmd_encryption_key(cmd_parms *cmd, void *_dcfg, const char *_p1, const char *_p2)
|
||||
{
|
||||
directory_config *dcfg = (directory_config *)_dcfg;
|
||||
char *p1 = NULL;
|
||||
|
||||
if (dcfg == NULL) return NULL;
|
||||
|
||||
if (p1 == NULL) return NULL;
|
||||
if (strcasecmp(p1, "Rand") == 0) {
|
||||
p1 = apr_pstrdup(cmd->pool, getkey(cmd->pool));
|
||||
dcfg->crypto_key = p1;
|
||||
dcfg->crypto_key_len = strlen(dcfg->crypto_key);
|
||||
} else {
|
||||
p1 = apr_pstrdup(cmd->pool, _p1);
|
||||
dcfg->crypto_key = p1;
|
||||
dcfg->crypto_key_len = strlen(p1);
|
||||
}
|
||||
|
||||
if(_p2 == NULL) {
|
||||
return NULL;
|
||||
} else {
|
||||
if (strcasecmp(_p2, "KeyOnly") == 0)
|
||||
dcfg->crypto_key_add = ENCRYPTION_KEYONLY;
|
||||
else if (strcasecmp(_p2, "SessionID") == 0)
|
||||
dcfg->crypto_key_add = ENCRYPTION_SESSIONID;
|
||||
else if (strcasecmp(_p2, "RemoteIP") == 0)
|
||||
dcfg->crypto_key_add = ENCRYPTION_REMOTEIP;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Add SecEncryptionMethodPm configuration option
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
* \param _dcfg Pointer to directory configuration
|
||||
* \param p1 Pointer to configuration option
|
||||
* \param p2 Pointer to configuration option
|
||||
*
|
||||
* \retval NULL On failure
|
||||
* \retval apr_psprintf On Success
|
||||
*/
|
||||
static const char *cmd_encryption_method_pm(cmd_parms *cmd, void *_dcfg,
|
||||
const char *p1, const char *p2)
|
||||
{
|
||||
directory_config *dcfg = (directory_config *)_dcfg;
|
||||
rule_exception *re = apr_pcalloc(cmd->pool, sizeof(encryption_method));
|
||||
const char *_p2 = apr_pstrdup(cmd->pool, p2);
|
||||
ACMP *p = NULL;
|
||||
const char *phrase = NULL;
|
||||
const char *next = NULL;
|
||||
|
||||
if (dcfg == NULL) return NULL;
|
||||
|
||||
p = acmp_create(0, cmd->pool);
|
||||
if (p == NULL) return NULL;
|
||||
|
||||
if(phrase == NULL)
|
||||
phrase = apr_pstrdup(cmd->pool, _p2);
|
||||
|
||||
for (;;) {
|
||||
while((apr_isspace(*phrase) != 0) && (*phrase != '\0')) phrase++;
|
||||
if (*phrase == '\0') break;
|
||||
next = phrase;
|
||||
while((apr_isspace(*next) == 0) && (*next != 0)) next++;
|
||||
acmp_add_pattern(p, phrase, NULL, NULL, next - phrase);
|
||||
phrase = next;
|
||||
}
|
||||
|
||||
acmp_prepare(p);
|
||||
|
||||
if (strcasecmp(p1, "HashHref") == 0) {
|
||||
re->type = ENCRYPTION_URL_HREF_HASH_PM;
|
||||
re->param = _p2;
|
||||
re->param_data = (void *)p;
|
||||
if (re->param_data == NULL) {
|
||||
return apr_psprintf(cmd->pool, "ModSecurity: Invalid pattern: %s", p2);
|
||||
}
|
||||
dcfg->crypto_hash_href_pm = 1;
|
||||
}
|
||||
else if (strcasecmp(p1, "HashFormAction") == 0) {
|
||||
re->type = ENCRYPTION_URL_FACTION_HASH_PM;
|
||||
re->param = _p2;
|
||||
re->param_data = (void *)p;
|
||||
if (re->param_data == NULL) {
|
||||
return apr_psprintf(cmd->pool, "ModSecurity: Invalid pattern: %s", p2);
|
||||
}
|
||||
dcfg->crypto_hash_faction_pm = 1;
|
||||
}
|
||||
else if (strcasecmp(p1, "HashLocation") == 0) {
|
||||
re->type = ENCRYPTION_URL_LOCATION_HASH_PM;
|
||||
re->param = _p2;
|
||||
re->param_data = (void *)p;
|
||||
if (re->param_data == NULL) {
|
||||
return apr_psprintf(cmd->pool, "ModSecurity: Invalid pattern: %s", p2);
|
||||
}
|
||||
dcfg->crypto_hash_location_pm = 1;
|
||||
}
|
||||
else if (strcasecmp(p1, "HashIframeSrc") == 0) {
|
||||
re->type = ENCRYPTION_URL_IFRAMESRC_HASH_PM;
|
||||
re->param = _p2;
|
||||
re->param_data = (void *)p;
|
||||
if (re->param_data == NULL) {
|
||||
return apr_psprintf(cmd->pool, "ModSecurity: Invalid pattern: %s", p2);
|
||||
}
|
||||
dcfg->crypto_hash_iframesrc_pm = 1;
|
||||
}
|
||||
else if (strcasecmp(p1, "HashFrameSrc") == 0) {
|
||||
re->type = ENCRYPTION_URL_FRAMESRC_HASH_PM;
|
||||
re->param = _p2;
|
||||
re->param_data = (void *)p;
|
||||
if (re->param_data == NULL) {
|
||||
return apr_psprintf(cmd->pool, "ModSecurity: Invalid pattern: %s", p2);
|
||||
}
|
||||
dcfg->crypto_hash_framesrc_pm = 1;
|
||||
}
|
||||
|
||||
*(encryption_method **)apr_array_push(dcfg->encryption_method) = re;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Add SecEncryptionMethodRx configuration option
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
* \param _dcfg Pointer to directory configuration
|
||||
* \param p1 Pointer to configuration option
|
||||
* \param p2 Pointer to configuration option
|
||||
*
|
||||
* \retval NULL On failure
|
||||
* \retval apr_psprintf On Success
|
||||
*/
|
||||
static const char *cmd_encryption_method_rx(cmd_parms *cmd, void *_dcfg,
|
||||
const char *p1, const char *p2)
|
||||
{
|
||||
directory_config *dcfg = (directory_config *)_dcfg;
|
||||
rule_exception *re = apr_pcalloc(cmd->pool, sizeof(encryption_method));
|
||||
const char *_p2 = apr_pstrdup(cmd->pool, p2);
|
||||
if (dcfg == NULL) return NULL;
|
||||
|
||||
if (strcasecmp(p1, "HashHref") == 0) {
|
||||
re->type = ENCRYPTION_URL_HREF_HASH_RX;
|
||||
re->param = _p2;
|
||||
re->param_data = msc_pregcomp(cmd->pool, p2, 0, NULL, NULL);
|
||||
if (re->param_data == NULL) {
|
||||
return apr_psprintf(cmd->pool, "ModSecurity: Invalid regular expression: %s", p2);
|
||||
}
|
||||
dcfg->crypto_hash_href_rx = 1;
|
||||
}
|
||||
else if (strcasecmp(p1, "HashFormAction") == 0) {
|
||||
re->type = ENCRYPTION_URL_FACTION_HASH_RX;
|
||||
re->param = _p2;
|
||||
re->param_data = msc_pregcomp(cmd->pool, p2, 0, NULL, NULL);
|
||||
if (re->param_data == NULL) {
|
||||
return apr_psprintf(cmd->pool, "ModSecurity: Invalid regular expression: %s", p2);
|
||||
}
|
||||
dcfg->crypto_hash_faction_rx = 1;
|
||||
}
|
||||
else if (strcasecmp(p1, "HashLocation") == 0) {
|
||||
re->type = ENCRYPTION_URL_LOCATION_HASH_RX;
|
||||
re->param = _p2;
|
||||
re->param_data = msc_pregcomp(cmd->pool, p2, 0, NULL, NULL);
|
||||
if (re->param_data == NULL) {
|
||||
return apr_psprintf(cmd->pool, "ModSecurity: Invalid regular expression: %s", p2);
|
||||
}
|
||||
dcfg->crypto_hash_location_rx = 1;
|
||||
}
|
||||
else if (strcasecmp(p1, "HashIframeSrc") == 0) {
|
||||
re->type = ENCRYPTION_URL_IFRAMESRC_HASH_RX;
|
||||
re->param = _p2;
|
||||
re->param_data = msc_pregcomp(cmd->pool, p2, 0, NULL, NULL);
|
||||
if (re->param_data == NULL) {
|
||||
return apr_psprintf(cmd->pool, "ModSecurity: Invalid regular expression: %s", p2);
|
||||
}
|
||||
dcfg->crypto_hash_iframesrc_rx = 1;
|
||||
}
|
||||
else if (strcasecmp(p1, "HashFrameSrc") == 0) {
|
||||
re->type = ENCRYPTION_URL_FRAMESRC_HASH_RX;
|
||||
re->param = _p2;
|
||||
re->param_data = msc_pregcomp(cmd->pool, p2, 0, NULL, NULL);
|
||||
if (re->param_data == NULL) {
|
||||
return apr_psprintf(cmd->pool, "ModSecurity: Invalid regular expression: %s", p2);
|
||||
}
|
||||
dcfg->crypto_hash_framesrc_rx = 1;
|
||||
}
|
||||
|
||||
*(encryption_method **)apr_array_push(dcfg->encryption_method) = re;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Add SecHttpBlKey configuration option
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
* \param _dcfg Pointer to directory configuration
|
||||
* \param p1 Pointer to configuration option
|
||||
*
|
||||
* \retval NULL On success
|
||||
*/
|
||||
static const char *cmd_httpBl_key(cmd_parms *cmd, void *_dcfg, const char *p1)
|
||||
{
|
||||
directory_config *dcfg = (directory_config *)_dcfg;
|
||||
|
@ -1980,7 +2519,7 @@ static const char *cmd_httpBl_key(cmd_parms *cmd, void *_dcfg, const char *p1)
|
|||
/* PCRE Limits */
|
||||
|
||||
static const char *cmd_pcre_match_limit(cmd_parms *cmd,
|
||||
void *_dcfg, const char *p1)
|
||||
void *_dcfg, const char *p1)
|
||||
{
|
||||
long val;
|
||||
|
||||
|
@ -1991,7 +2530,7 @@ static const char *cmd_pcre_match_limit(cmd_parms *cmd,
|
|||
val = atol(p1);
|
||||
if (val <= 0) {
|
||||
return apr_psprintf(cmd->pool, "ModSecurity: Invalid setting for "
|
||||
"SecPcreMatchLimit: %s", p1);
|
||||
"SecPcreMatchLimit: %s", p1);
|
||||
}
|
||||
msc_pcre_match_limit = (unsigned long int)val;
|
||||
|
||||
|
@ -1999,7 +2538,7 @@ static const char *cmd_pcre_match_limit(cmd_parms *cmd,
|
|||
}
|
||||
|
||||
static const char *cmd_pcre_match_limit_recursion(cmd_parms *cmd,
|
||||
void *_dcfg, const char *p1)
|
||||
void *_dcfg, const char *p1)
|
||||
{
|
||||
long val;
|
||||
|
||||
|
@ -2010,7 +2549,7 @@ static const char *cmd_pcre_match_limit_recursion(cmd_parms *cmd,
|
|||
val = atol(p1);
|
||||
if (val <= 0) {
|
||||
return apr_psprintf(cmd->pool, "ModSecurity: Invalid setting for "
|
||||
"SecPcreMatchLimitRecursion: %s", p1);
|
||||
"SecPcreMatchLimitRecursion: %s", p1);
|
||||
}
|
||||
msc_pcre_match_limit_recursion = (unsigned long int)val;
|
||||
|
||||
|
@ -2021,7 +2560,7 @@ static const char *cmd_pcre_match_limit_recursion(cmd_parms *cmd,
|
|||
/* -- Geo Lookup configuration -- */
|
||||
|
||||
static const char *cmd_geo_lookup_db(cmd_parms *cmd, void *_dcfg,
|
||||
const char *p1)
|
||||
const char *p1)
|
||||
{
|
||||
const char *filename = resolve_relative_path(cmd->pool, cmd->directive->filename, p1);
|
||||
char *error_msg;
|
||||
|
@ -2035,8 +2574,15 @@ static const char *cmd_geo_lookup_db(cmd_parms *cmd, void *_dcfg,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Unicode CodePage */
|
||||
|
||||
/**
|
||||
* \brief Add SecUnicodeCodePage configuration option
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
* \param _dcfg Pointer to directory configuration
|
||||
* \param p1 Pointer to configuration option
|
||||
*
|
||||
* \retval NULL On success
|
||||
*/
|
||||
static const char *cmd_unicode_codepage(cmd_parms *cmd,
|
||||
void *_dcfg, const char *p1)
|
||||
{
|
||||
|
@ -2053,8 +2599,15 @@ static const char *cmd_unicode_codepage(cmd_parms *cmd,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Unicode Map */
|
||||
|
||||
/**
|
||||
* \brief Add SecUnicodeMapFile configuration option
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
* \param _dcfg Pointer to directory configuration
|
||||
* \param p1 Pointer to configuration option
|
||||
*
|
||||
* \retval NULL On success
|
||||
*/
|
||||
static const char *cmd_unicode_map(cmd_parms *cmd, void *_dcfg,
|
||||
const char *p1)
|
||||
{
|
||||
|
@ -2070,8 +2623,15 @@ static const char *cmd_unicode_map(cmd_parms *cmd, void *_dcfg,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* Google safe browsing */
|
||||
|
||||
/**
|
||||
* \brief Add SecGsbLookupDb configuration option
|
||||
*
|
||||
* \param cmd Pointer to configuration data
|
||||
* \param _dcfg Pointer to directory configuration
|
||||
* \param p1 Pointer to configuration option
|
||||
*
|
||||
* \retval NULL On success
|
||||
*/
|
||||
static const char *cmd_gsb_lookup_db(cmd_parms *cmd, void *_dcfg,
|
||||
const char *p1)
|
||||
{
|
||||
|
@ -2211,7 +2771,7 @@ const command_rec module_directives[] = {
|
|||
"SecArgumentSeparator",
|
||||
cmd_argument_separator,
|
||||
NULL,
|
||||
CMD_SCOPE_MAIN,
|
||||
CMD_SCOPE_ANY,
|
||||
"character that will be used as separator when parsing application/x-www-form-urlencoded content."
|
||||
),
|
||||
|
||||
|
@ -2472,6 +3032,14 @@ const command_rec module_directives[] = {
|
|||
"On or Off"
|
||||
),
|
||||
|
||||
AP_INIT_TAKE1 (
|
||||
"SecRulePerfTime",
|
||||
cmd_rule_perf_time,
|
||||
NULL,
|
||||
CMD_SCOPE_ANY,
|
||||
"Threshold to log slow rules in usecs."
|
||||
),
|
||||
|
||||
AP_INIT_TAKE1 (
|
||||
"SecReadStateLimit",
|
||||
cmd_conn_read_state_limit,
|
||||
|
@ -2624,6 +3192,22 @@ const command_rec module_directives[] = {
|
|||
"rule message for removal"
|
||||
),
|
||||
|
||||
AP_INIT_TAKE2 (
|
||||
"SecEncryptionMethodPm",
|
||||
cmd_encryption_method_pm,
|
||||
NULL,
|
||||
CMD_SCOPE_ANY,
|
||||
"Encryption method and pattern"
|
||||
),
|
||||
|
||||
AP_INIT_TAKE2 (
|
||||
"SecEncryptionMethodRx",
|
||||
cmd_encryption_method_rx,
|
||||
NULL,
|
||||
CMD_SCOPE_ANY,
|
||||
"Encryption method and regex"
|
||||
),
|
||||
|
||||
AP_INIT_TAKE2 (
|
||||
"SecRuleUpdateActionById",
|
||||
cmd_rule_update_action_by_id,
|
||||
|
@ -2640,6 +3224,23 @@ const command_rec module_directives[] = {
|
|||
"updated target list"
|
||||
),
|
||||
|
||||
AP_INIT_TAKE23 (
|
||||
"SecRuleUpdateTargetByTag",
|
||||
cmd_rule_update_target_by_tag,
|
||||
NULL,
|
||||
CMD_SCOPE_ANY,
|
||||
"rule tag pattern and updated target list"
|
||||
),
|
||||
|
||||
AP_INIT_TAKE23 (
|
||||
"SecRuleUpdateTargetByMsg",
|
||||
cmd_rule_update_target_by_msg,
|
||||
NULL,
|
||||
CMD_SCOPE_ANY,
|
||||
"rule message pattern and updated target list"
|
||||
),
|
||||
|
||||
|
||||
AP_INIT_TAKE1 (
|
||||
"SecServerSignature",
|
||||
cmd_server_signature,
|
||||
|
@ -2696,6 +3297,14 @@ const command_rec module_directives[] = {
|
|||
"id"
|
||||
),
|
||||
|
||||
AP_INIT_TAKE1 (
|
||||
"SecSensorId",
|
||||
cmd_sensor_id,
|
||||
NULL,
|
||||
CMD_SCOPE_MAIN,
|
||||
"sensor id"
|
||||
),
|
||||
|
||||
AP_INIT_TAKE1 (
|
||||
"SecHttpBlKey",
|
||||
cmd_httpBl_key,
|
||||
|
@ -2704,5 +3313,29 @@ const command_rec module_directives[] = {
|
|||
"httpBl access key"
|
||||
),
|
||||
|
||||
AP_INIT_TAKE1 (
|
||||
"SecEncryptionEngine",
|
||||
cmd_encryption_engine,
|
||||
NULL,
|
||||
CMD_SCOPE_ANY,
|
||||
"On or Off"
|
||||
),
|
||||
|
||||
AP_INIT_TAKE2 (
|
||||
"SecEncryptionKey",
|
||||
cmd_encryption_key,
|
||||
NULL,
|
||||
CMD_SCOPE_ANY,
|
||||
"Set Encrytion key"
|
||||
),
|
||||
|
||||
AP_INIT_TAKE1 (
|
||||
"SecEncryptionParam",
|
||||
cmd_encryption_param,
|
||||
NULL,
|
||||
CMD_SCOPE_ANY,
|
||||
"Set Encryption parameter"
|
||||
),
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
/*
|
||||
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
|
||||
* Copyright (c) 2004-2011 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.
|
||||
*/
|
||||
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
|
||||
* Copyright (c) 2004-2011 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 <util_filter.h>
|
||||
|
||||
#include "modsecurity.h"
|
||||
#include "apache2.h"
|
||||
#include "msc_crypt.h"
|
||||
|
||||
/* -- Input filter -- */
|
||||
|
||||
|
@ -29,7 +30,7 @@ static void dummy_free_func(void *data) {}
|
|||
* processing module).
|
||||
*/
|
||||
apr_status_t input_filter(ap_filter_t *f, apr_bucket_brigade *bb_out,
|
||||
ap_input_mode_t mode, apr_read_type_e block, apr_off_t nbytes)
|
||||
ap_input_mode_t mode, apr_read_type_e block, apr_off_t nbytes)
|
||||
{
|
||||
modsec_rec *msr = (modsec_rec *)f->ctx;
|
||||
msc_data_chunk *chunk = NULL;
|
||||
|
@ -39,7 +40,7 @@ apr_status_t input_filter(ap_filter_t *f, apr_bucket_brigade *bb_out,
|
|||
|
||||
if (msr == NULL) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, f->r->server,
|
||||
"ModSecurity: Internal error in input filter: msr is null.");
|
||||
"ModSecurity: Internal error in input filter: msr is null.");
|
||||
ap_remove_input_filter(f);
|
||||
return APR_EGENERAL;
|
||||
}
|
||||
|
@ -48,8 +49,8 @@ apr_status_t input_filter(ap_filter_t *f, apr_bucket_brigade *bb_out,
|
|||
msr->r = f->r;
|
||||
|
||||
if (msr->phase < PHASE_REQUEST_BODY) {
|
||||
msr_log(msr, 1, "Internal error: REQUEST_BODY phase incomplete for input filter in phase %d", msr->phase);
|
||||
return APR_EGENERAL;
|
||||
msr_log(msr, 1, "Internal error: REQUEST_BODY phase incomplete for input filter in phase %d", msr->phase);
|
||||
return APR_EGENERAL;
|
||||
}
|
||||
|
||||
if ((msr->if_status == IF_STATUS_COMPLETE)||(msr->if_status == IF_STATUS_NONE)) {
|
||||
|
@ -62,7 +63,7 @@ apr_status_t input_filter(ap_filter_t *f, apr_bucket_brigade *bb_out,
|
|||
|
||||
if (msr->txcfg->debuglog_level >= 4) {
|
||||
msr_log(msr, 4, "Input filter: Forwarding input: mode=%d, block=%d, nbytes=%" APR_OFF_T_FMT
|
||||
" (f %pp, r %pp).", mode, block, nbytes, f, f->r);
|
||||
" (f %pp, r %pp).", mode, block, nbytes, f, f->r);
|
||||
}
|
||||
|
||||
if (msr->if_started_forwarding == 0) {
|
||||
|
@ -87,24 +88,24 @@ apr_status_t input_filter(ap_filter_t *f, apr_bucket_brigade *bb_out,
|
|||
if (chunk && (!msr->txcfg->stream_inbody_inspection || (msr->txcfg->stream_inbody_inspection && msr->if_stream_changed == 0))) {
|
||||
/* Copy the data we received in the chunk */
|
||||
bucket = apr_bucket_heap_create(chunk->data, chunk->length, NULL,
|
||||
f->r->connection->bucket_alloc);
|
||||
f->r->connection->bucket_alloc);
|
||||
|
||||
#if 0
|
||||
#if 0
|
||||
|
||||
It would seem that we cannot prevent other filters in the chain
|
||||
from modifying data in-place. Hence we copy.
|
||||
from modifying data in-place. Hence we copy.
|
||||
|
||||
if (chunk->is_permanent) {
|
||||
/* Do not make a copy of the data we received in the chunk. */
|
||||
bucket = apr_bucket_heap_create(chunk->data, chunk->length, dummy_free_func,
|
||||
f->r->connection->bucket_alloc);
|
||||
} else {
|
||||
/* Copy the data we received in the chunk. */
|
||||
bucket = apr_bucket_heap_create(chunk->data, chunk->length, NULL,
|
||||
f->r->connection->bucket_alloc);
|
||||
}
|
||||
if (chunk->is_permanent) {
|
||||
/* Do not make a copy of the data we received in the chunk. */
|
||||
bucket = apr_bucket_heap_create(chunk->data, chunk->length, dummy_free_func,
|
||||
f->r->connection->bucket_alloc);
|
||||
} else {
|
||||
/* Copy the data we received in the chunk. */
|
||||
bucket = apr_bucket_heap_create(chunk->data, chunk->length, NULL,
|
||||
f->r->connection->bucket_alloc);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (bucket == NULL) return APR_EGENERAL;
|
||||
APR_BRIGADE_INSERT_TAIL(bb_out, bucket);
|
||||
|
@ -226,8 +227,8 @@ apr_status_t read_request_body(modsec_rec *msr, char **error_msg) {
|
|||
* to extract the size of the data available.
|
||||
*/
|
||||
for(bucket = APR_BRIGADE_FIRST(bb_in);
|
||||
bucket != APR_BRIGADE_SENTINEL(bb_in);
|
||||
bucket = APR_BUCKET_NEXT(bucket))
|
||||
bucket != APR_BRIGADE_SENTINEL(bb_in);
|
||||
bucket = APR_BUCKET_NEXT(bucket))
|
||||
{
|
||||
const char *buf;
|
||||
apr_size_t buflen;
|
||||
|
@ -240,7 +241,7 @@ apr_status_t read_request_body(modsec_rec *msr, char **error_msg) {
|
|||
|
||||
if (msr->txcfg->debuglog_level >= 9) {
|
||||
msr_log(msr, 9, "Input filter: Bucket type %s contains %" APR_SIZE_T_FMT " bytes.",
|
||||
bucket->type->name, buflen);
|
||||
bucket->type->name, buflen);
|
||||
}
|
||||
|
||||
/* Check request body limit (should only trigger on chunked requests). */
|
||||
|
@ -393,7 +394,7 @@ static int output_filter_should_run(modsec_rec *msr, request_rec *r) {
|
|||
* Initialises the output filter.
|
||||
*/
|
||||
static apr_status_t output_filter_init(modsec_rec *msr, ap_filter_t *f,
|
||||
apr_bucket_brigade *bb_in)
|
||||
apr_bucket_brigade *bb_in)
|
||||
{
|
||||
request_rec *r = f->r;
|
||||
const char *s_content_length = NULL;
|
||||
|
@ -434,7 +435,7 @@ static apr_status_t output_filter_init(modsec_rec *msr, ap_filter_t *f,
|
|||
len = strtol(s_content_length, NULL, 10);
|
||||
if ((len == LONG_MIN)||(len == LONG_MAX)||(len < 0)||(len >= 1073741824)) {
|
||||
msr_log(msr, 1, "Output filter: Invalid Content-Length: %s", log_escape_nq(r->pool,
|
||||
(char *)s_content_length));
|
||||
(char *)s_content_length));
|
||||
return -1; /* Invalid. */
|
||||
}
|
||||
|
||||
|
@ -448,7 +449,7 @@ static apr_status_t output_filter_init(modsec_rec *msr, ap_filter_t *f,
|
|||
|
||||
if (len > msr->txcfg->of_limit) {
|
||||
msr_log(msr, 1, "Output filter: Content-Length (%s) over the limit (%ld).",
|
||||
log_escape_nq(r->pool, (char *)s_content_length), msr->txcfg->of_limit);
|
||||
log_escape_nq(r->pool, (char *)s_content_length), msr->txcfg->of_limit);
|
||||
msr->outbound_error = 1;
|
||||
return -2; /* Over the limit. */
|
||||
}
|
||||
|
@ -480,12 +481,12 @@ static apr_status_t send_of_brigade(modsec_rec *msr, ap_filter_t *f) {
|
|||
/* Look like this is caused by the error
|
||||
* already being handled, so we should ignore it
|
||||
*
|
||||
msr_log(msr, log_level, "Output filter: Error while forwarding response data (%d): Filter error", rc);
|
||||
msr_log(msr, log_level, "Output filter: Error while forwarding response data (%d): Filter error", rc);
|
||||
*/
|
||||
break;
|
||||
default :
|
||||
msr_log(msr, log_level, "Output filter: Error while forwarding response data (%d): %s",
|
||||
rc, get_apr_error(msr->mp, rc));
|
||||
rc, get_apr_error(msr->mp, rc));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -496,6 +497,12 @@ static apr_status_t send_of_brigade(modsec_rec *msr, ap_filter_t *f) {
|
|||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Inject data into brigade
|
||||
*
|
||||
* \param msr ModSecurity transation resource
|
||||
* \param ap_filter_t Apache filter
|
||||
*
|
||||
*/
|
||||
static void inject_content_to_of_brigade(modsec_rec *msr, ap_filter_t *f) {
|
||||
apr_bucket *b;
|
||||
|
||||
|
@ -567,7 +574,7 @@ static int flatten_response_body(modsec_rec *msr) {
|
|||
msr->resbody_data[msr->resbody_length] = '\0';
|
||||
msr->resbody_status = RESBODY_STATUS_READ;
|
||||
|
||||
if (msr->txcfg->stream_outbody_inspection) {
|
||||
if (msr->txcfg->stream_outbody_inspection && msr->txcfg->encryption_is_enabled == ENCRYPTION_DISABLED) {
|
||||
|
||||
msr->stream_output_length = msr->resbody_length;
|
||||
|
||||
|
@ -580,6 +587,36 @@ static int flatten_response_body(modsec_rec *msr) {
|
|||
memset(msr->stream_output_data, 0, msr->stream_output_length+1);
|
||||
strncpy(msr->stream_output_data, msr->resbody_data, msr->stream_output_length);
|
||||
msr->stream_output_data[msr->stream_output_length] = '\0';
|
||||
} else if (msr->txcfg->stream_outbody_inspection && msr->txcfg->encryption_is_enabled == ENCRYPTION_ENABLED) {
|
||||
int retval = 0;
|
||||
apr_time_t time1 = apr_time_now();
|
||||
|
||||
retval = init_response_body_html_parser(msr);
|
||||
|
||||
if(retval == 1) {
|
||||
retval = encrypt_response_body_links(msr);
|
||||
if(retval > 0) {
|
||||
retval = inject_encrypted_response_body(msr, retval);
|
||||
if (msr->txcfg->debuglog_level >= 4) {
|
||||
msr_log(msr, 4, "Encryption completed in %" APR_TIME_T_FMT " usec.", (apr_time_now() - time1));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(msr->of_stream_changed == 0) {
|
||||
msr->stream_output_length = msr->resbody_length;
|
||||
|
||||
if (msr->stream_output_data == NULL) {
|
||||
msr_log(msr, 1, "Output filter: Stream Response body data memory allocation failed. Asked for: %" APR_SIZE_T_FMT,
|
||||
msr->stream_output_length + 1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(msr->stream_output_data, 0, msr->stream_output_length+1);
|
||||
strncpy(msr->stream_output_data, msr->resbody_data, msr->stream_output_length);
|
||||
msr->stream_output_data[msr->stream_output_length] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -598,7 +635,7 @@ apr_status_t output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
|
|||
/* Do we have the context? */
|
||||
if (msr == NULL) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, f->r->server,
|
||||
"ModSecurity: Internal Error: msr is null in output filter.");
|
||||
"ModSecurity: Internal Error: msr is null in output filter.");
|
||||
ap_remove_output_filter(f);
|
||||
return send_error_bucket(msr, f, HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
@ -631,8 +668,12 @@ apr_status_t output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
|
|||
msr->r = r;
|
||||
msr->response_status = r->status;
|
||||
msr->status_line = ((r->status_line != NULL)
|
||||
? r->status_line : ap_get_status_line(r->status));
|
||||
? r->status_line : ap_get_status_line(r->status));
|
||||
msr->response_protocol = get_response_protocol(r);
|
||||
|
||||
if(msr->txcfg->crypto_hash_location_rx == 1 || msr->txcfg->crypto_hash_location_pm == 1)
|
||||
rc = modify_response_header(msr);
|
||||
|
||||
msr->response_headers = apr_table_overlay(msr->mp, r->err_headers_out, r->headers_out);
|
||||
|
||||
/* Process phase RESPONSE_HEADERS */
|
||||
|
@ -702,28 +743,28 @@ apr_status_t output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
|
|||
/* Content injection (prepend & non-buffering). */
|
||||
if ((msr->txcfg->content_injection_enabled) && (msr->content_prepend) && (msr->of_skipping)) {
|
||||
apr_bucket *bucket_ci = apr_bucket_heap_create(msr->content_prepend,
|
||||
msr->content_prepend_len, NULL, f->r->connection->bucket_alloc);
|
||||
msr->content_prepend_len, NULL, f->r->connection->bucket_alloc);
|
||||
APR_BRIGADE_INSERT_HEAD(bb_in, bucket_ci);
|
||||
|
||||
if (msr->txcfg->debuglog_level >= 9) {
|
||||
msr_log(msr, 9, "Content Injection (nb): Added content to top: %s",
|
||||
log_escape_nq_ex(msr->mp, msr->content_prepend, msr->content_prepend_len));
|
||||
log_escape_nq_ex(msr->mp, msr->content_prepend, msr->content_prepend_len));
|
||||
}
|
||||
}
|
||||
} else
|
||||
if (msr->of_status == OF_STATUS_COMPLETE) {
|
||||
msr_log(msr, 1, "Output filter: Internal error: output filtering complete yet filter was invoked.");
|
||||
ap_remove_output_filter(f);
|
||||
return APR_EGENERAL;
|
||||
}
|
||||
if (msr->of_status == OF_STATUS_COMPLETE) {
|
||||
msr_log(msr, 1, "Output filter: Internal error: output filtering complete yet filter was invoked.");
|
||||
ap_remove_output_filter(f);
|
||||
return APR_EGENERAL;
|
||||
}
|
||||
|
||||
|
||||
/* Loop through the buckets in the brigade in order
|
||||
* to extract the size of the data available.
|
||||
*/
|
||||
for(bucket = APR_BRIGADE_FIRST(bb_in);
|
||||
bucket != APR_BRIGADE_SENTINEL(bb_in);
|
||||
bucket = APR_BUCKET_NEXT(bucket)) {
|
||||
bucket != APR_BRIGADE_SENTINEL(bb_in);
|
||||
bucket = APR_BUCKET_NEXT(bucket)) {
|
||||
const char *buf;
|
||||
apr_size_t buflen;
|
||||
|
||||
|
@ -738,7 +779,7 @@ apr_status_t output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
|
|||
msr->resbody_status = RESBODY_STATUS_ERROR;
|
||||
|
||||
msr_log(msr, 1, "Output filter: Failed to read bucket (rc %d): %s",
|
||||
rc, get_apr_error(r->pool, rc));
|
||||
rc, get_apr_error(r->pool, rc));
|
||||
|
||||
ap_remove_output_filter(f);
|
||||
return send_error_bucket(msr, f, HTTP_INTERNAL_SERVER_ERROR);
|
||||
|
@ -746,7 +787,7 @@ apr_status_t output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
|
|||
|
||||
if (msr->txcfg->debuglog_level >= 9) {
|
||||
msr_log(msr, 9, "Output filter: Bucket type %s contains %" APR_SIZE_T_FMT " bytes.",
|
||||
bucket->type->name, buflen);
|
||||
bucket->type->name, buflen);
|
||||
}
|
||||
|
||||
/* Check the response size. */
|
||||
|
@ -759,7 +800,7 @@ apr_status_t output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
|
|||
if (msr->txcfg->of_limit_action == RESPONSE_BODY_LIMIT_ACTION_REJECT) {
|
||||
/* Reject response. */
|
||||
msr_log(msr, 1, "Output filter: Response body too large (over limit of %ld, "
|
||||
"total not specified).", msr->txcfg->of_limit);
|
||||
"total not specified).", msr->txcfg->of_limit);
|
||||
|
||||
msr->of_status = OF_STATUS_COMPLETE;
|
||||
msr->resbody_status = RESBODY_STATUS_PARTIAL;
|
||||
|
@ -773,7 +814,7 @@ apr_status_t output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
|
|||
|
||||
if (msr->txcfg->debuglog_level >= 4) {
|
||||
msr_log(msr, 4, "Output filter: Processing partial response body (limit %ld)",
|
||||
msr->txcfg->of_limit);
|
||||
msr->txcfg->of_limit);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -787,17 +828,17 @@ apr_status_t output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
|
|||
|
||||
/* Inject content (append & non-buffering). */
|
||||
if ((msr->txcfg->content_injection_enabled) && (msr->content_append)
|
||||
&& (msr->of_skipping || msr->of_partial || start_skipping))
|
||||
&& (msr->of_skipping || msr->of_partial || start_skipping))
|
||||
{
|
||||
apr_bucket *bucket_ci = NULL;
|
||||
|
||||
bucket_ci = apr_bucket_heap_create(msr->content_append,
|
||||
msr->content_append_len, NULL, f->r->connection->bucket_alloc);
|
||||
msr->content_append_len, NULL, f->r->connection->bucket_alloc);
|
||||
APR_BUCKET_INSERT_BEFORE(bucket, bucket_ci);
|
||||
|
||||
if (msr->txcfg->debuglog_level >= 9) {
|
||||
msr_log(msr, 9, "Content-Injection (nb): Added content to bottom: %s",
|
||||
log_escape_nq_ex(msr->mp, msr->content_append, msr->content_append_len));
|
||||
log_escape_nq_ex(msr->mp, msr->content_append, msr->content_append_len));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -867,7 +908,7 @@ apr_status_t output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
|
|||
|
||||
if (msr->txcfg->debuglog_level >= 4) {
|
||||
msr_log(msr, 4, "Output filter: Completed receiving response body (buffered %s - %" APR_SIZE_T_FMT " bytes).",
|
||||
(msr->of_partial ? "partial" : "full"), msr->resbody_length);
|
||||
(msr->of_partial ? "partial" : "full"), msr->resbody_length);
|
||||
}
|
||||
} else { /* Not looking at response data. */
|
||||
if (msr->of_done_reading == 0) {
|
||||
|
@ -950,12 +991,12 @@ apr_status_t output_filter(ap_filter_t *f, apr_bucket_brigade *bb_in) {
|
|||
apr_bucket *bucket_ci = NULL;
|
||||
|
||||
bucket_ci = apr_bucket_heap_create(msr->content_append,
|
||||
msr->content_append_len, NULL, f->r->connection->bucket_alloc);
|
||||
msr->content_append_len, NULL, f->r->connection->bucket_alloc);
|
||||
APR_BUCKET_INSERT_BEFORE(eos_bucket, bucket_ci);
|
||||
|
||||
if (msr->txcfg->debuglog_level >= 9) {
|
||||
msr_log(msr, 9, "Content-Injection (b): Added content to bottom: %s",
|
||||
log_escape_nq_ex(msr->mp, msr->content_append, msr->content_append_len));
|
||||
log_escape_nq_ex(msr->mp, msr->content_append, msr->content_append_len));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,11 @@
|
|||
|
||||
#include "apr_version.h"
|
||||
|
||||
#if defined(WITH_LUA)
|
||||
#include "msc_lua.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* ModSecurity structure */
|
||||
|
||||
msc_engine DSOLOCAL *modsecurity = NULL;
|
||||
|
@ -68,7 +73,7 @@ typedef struct {
|
|||
|
||||
/* -- Miscellaneous functions -- */
|
||||
|
||||
/*
|
||||
/**
|
||||
* \brief Print informations from used libraries
|
||||
*
|
||||
* \param mp Pointer to memory pool
|
||||
|
@ -114,6 +119,7 @@ int perform_interception(modsec_rec *msr) {
|
|||
msre_actionset *actionset = NULL;
|
||||
const char *message = NULL;
|
||||
const char *phase_text = "";
|
||||
unsigned int pause = 0;
|
||||
int status = DECLINED;
|
||||
int log_level = 1;
|
||||
|
||||
|
@ -142,11 +148,31 @@ int perform_interception(modsec_rec *msr) {
|
|||
log_level = (actionset->log != 1) ? 4 : 1;
|
||||
|
||||
/* Pause the request first (if configured and the initial request). */
|
||||
if (actionset->intercept_pause) {
|
||||
msr_log(msr, (log_level > 3 ? log_level : log_level + 1), "Pausing transaction for "
|
||||
"%d msec.", actionset->intercept_pause);
|
||||
/* apr_sleep accepts microseconds */
|
||||
apr_sleep((apr_interval_time_t)(actionset->intercept_pause * 1000));
|
||||
if (actionset->intercept_pause != NULL) {
|
||||
if(strstr(actionset->intercept_pause,"%{") != NULL) {
|
||||
msc_string *var = (msc_string *)apr_pcalloc(msr->mp, sizeof(msc_string));
|
||||
|
||||
var->value = (char *)actionset->intercept_pause;
|
||||
var->value_len = strlen(actionset->intercept_pause);
|
||||
expand_macros(msr, var, NULL, msr->mp);
|
||||
|
||||
pause = atoi(var->value);
|
||||
if ((pause == LONG_MAX)||(pause == LONG_MIN)||(pause <= 0))
|
||||
pause = 0;
|
||||
|
||||
msr_log(msr, (log_level > 3 ? log_level : log_level + 1), "Pausing transaction for "
|
||||
"%d msec.", pause);
|
||||
/* apr_sleep accepts microseconds */
|
||||
apr_sleep((apr_interval_time_t)(pause * 1000));
|
||||
} else {
|
||||
pause = atoi(actionset->intercept_pause);
|
||||
if ((pause == LONG_MAX)||(pause == LONG_MIN)||(pause <= 0))
|
||||
pause = 0;
|
||||
msr_log(msr, (log_level > 3 ? log_level : log_level + 1), "Pausing transaction for "
|
||||
"%d msec.", pause);
|
||||
/* apr_sleep accepts microseconds */
|
||||
apr_sleep((apr_interval_time_t)(pause * 1000));
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine how to respond and prepare the log message. */
|
||||
|
@ -155,13 +181,13 @@ int perform_interception(modsec_rec *msr) {
|
|||
if (actionset->intercept_status != 0) {
|
||||
status = actionset->intercept_status;
|
||||
message = apr_psprintf(msr->mp, "Access denied with code %d%s.",
|
||||
status, phase_text);
|
||||
status, phase_text);
|
||||
} else {
|
||||
log_level = 1;
|
||||
status = HTTP_INTERNAL_SERVER_ERROR;
|
||||
message = apr_psprintf(msr->mp, "Access denied with code 500%s "
|
||||
"(Internal Error: Invalid status code requested %d).",
|
||||
phase_text, actionset->intercept_status);
|
||||
"(Internal Error: Invalid status code requested %d).",
|
||||
phase_text, actionset->intercept_status);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -233,18 +259,39 @@ int perform_interception(modsec_rec *msr) {
|
|||
break;
|
||||
|
||||
case ACTION_REDIRECT :
|
||||
apr_table_setn(msr->r->headers_out, "Location", actionset->intercept_uri);
|
||||
if ((actionset->intercept_status == 301)||(actionset->intercept_status == 302)
|
||||
||(actionset->intercept_status == 303)||(actionset->intercept_status == 307))
|
||||
{
|
||||
status = actionset->intercept_status;
|
||||
if(strstr(actionset->intercept_uri,"%{") != NULL) {
|
||||
msc_string *var = (msc_string *)apr_pcalloc(msr->mp, sizeof(msc_string));
|
||||
|
||||
var->value = (char *)actionset->intercept_uri;
|
||||
var->value_len = strlen(actionset->intercept_uri);
|
||||
expand_macros(msr, var, NULL, msr->mp);
|
||||
|
||||
apr_table_setn(msr->r->headers_out, "Location", var->value);
|
||||
if ((actionset->intercept_status == 301)||(actionset->intercept_status == 302)
|
||||
||(actionset->intercept_status == 303)||(actionset->intercept_status == 307))
|
||||
{
|
||||
status = actionset->intercept_status;
|
||||
} else {
|
||||
status = HTTP_MOVED_TEMPORARILY;
|
||||
}
|
||||
message = apr_psprintf(msr->mp, "Access denied with redirection to %s using "
|
||||
"status %d%s.",
|
||||
log_escape_nq(msr->mp, var->value), status,
|
||||
phase_text);
|
||||
} else {
|
||||
status = HTTP_MOVED_TEMPORARILY;
|
||||
apr_table_setn(msr->r->headers_out, "Location", actionset->intercept_uri);
|
||||
if ((actionset->intercept_status == 301)||(actionset->intercept_status == 302)
|
||||
||(actionset->intercept_status == 303)||(actionset->intercept_status == 307))
|
||||
{
|
||||
status = actionset->intercept_status;
|
||||
} else {
|
||||
status = HTTP_MOVED_TEMPORARILY;
|
||||
}
|
||||
message = apr_psprintf(msr->mp, "Access denied with redirection to %s using "
|
||||
"status %d%s.",
|
||||
log_escape_nq(msr->mp, actionset->intercept_uri), status,
|
||||
phase_text);
|
||||
}
|
||||
message = apr_psprintf(msr->mp, "Access denied with redirection to %s using "
|
||||
"status %d%s.",
|
||||
log_escape_nq(msr->mp, actionset->intercept_uri), status,
|
||||
phase_text);
|
||||
break;
|
||||
|
||||
case ACTION_ALLOW :
|
||||
|
@ -272,8 +319,8 @@ int perform_interception(modsec_rec *msr) {
|
|||
log_level = 1;
|
||||
status = HTTP_INTERNAL_SERVER_ERROR;
|
||||
message = apr_psprintf(msr->mp, "Access denied with code 500%s "
|
||||
"(Internal Error: invalid interception action %d).",
|
||||
phase_text, actionset->intercept_action);
|
||||
"(Internal Error: invalid interception action %d).",
|
||||
phase_text, actionset->intercept_action);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -365,7 +412,15 @@ static modsec_rec *create_tx_context(request_rec *r) {
|
|||
msr->r_early = r;
|
||||
msr->request_time = r->request_time;
|
||||
msr->dcfg1 = (directory_config *)ap_get_module_config(r->per_dir_config,
|
||||
&security2_module);
|
||||
&security2_module);
|
||||
|
||||
#if defined(WITH_LUA)
|
||||
#ifdef CACHE_LUA
|
||||
msr->L = lua_open();
|
||||
luaL_openlibs(msr->L);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Create a special user configuration. This is where
|
||||
|
@ -393,7 +448,7 @@ static modsec_rec *create_tx_context(request_rec *r) {
|
|||
msr->txid = get_env_var(r, "UNIQUE_ID");
|
||||
if (msr->txid == NULL) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r->server,
|
||||
"ModSecurity: ModSecurity requires mod_unique_id to be installed.");
|
||||
"ModSecurity: ModSecurity requires mod_unique_id to be installed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -409,12 +464,13 @@ static modsec_rec *create_tx_context(request_rec *r) {
|
|||
msr->local_addr = r->connection->local_ip;
|
||||
msr->local_port = r->connection->local_addr->port;
|
||||
|
||||
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
|
||||
msr->remote_addr = r->connection->client_ip;
|
||||
msr->remote_port = r->connection->client_addr->port;
|
||||
#else
|
||||
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER < 3
|
||||
msr->remote_addr = r->connection->remote_ip;
|
||||
msr->remote_port = r->connection->remote_addr->port;
|
||||
#else
|
||||
msr->remote_addr = r->connection->client_ip;
|
||||
msr->remote_port = r->connection->client_addr->port;
|
||||
msr->useragent_ip = r->useragent_ip;
|
||||
#endif
|
||||
|
||||
msr->request_line = r->the_request;
|
||||
|
@ -459,7 +515,7 @@ static apr_status_t change_server_signature(server_rec *s) {
|
|||
|
||||
if (server_version == NULL) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, s,
|
||||
"SecServerSignature: Apache returned null as signature.");
|
||||
"SecServerSignature: Apache returned null as signature.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -468,8 +524,8 @@ static apr_status_t change_server_signature(server_rec *s) {
|
|||
}
|
||||
else {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, s,
|
||||
"SecServerSignature: original signature too short. Please set "
|
||||
"ServerTokens to Full.");
|
||||
"SecServerSignature: original signature too short. Please set "
|
||||
"ServerTokens to Full.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -520,7 +576,7 @@ static int hook_pre_config(apr_pool_t *mp, apr_pool_t *mp_log, apr_pool_t *mp_te
|
|||
modsecurity = modsecurity_create(mp, MODSEC_ONLINE);
|
||||
if (modsecurity == NULL) {
|
||||
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
|
||||
"ModSecurity: Failed to initialise engine.");
|
||||
"ModSecurity: Failed to initialise engine.");
|
||||
return HTTP_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
|
@ -548,7 +604,7 @@ static int hook_post_config(apr_pool_t *mp, apr_pool_t *mp_log, apr_pool_t *mp_t
|
|||
if (init_flag == NULL) {
|
||||
first_time = 1;
|
||||
apr_pool_userdata_set((const void *)1, "modsecurity-init-flag",
|
||||
apr_pool_cleanup_null, s->process->pool);
|
||||
apr_pool_cleanup_null, s->process->pool);
|
||||
} else {
|
||||
modsecurity_init(modsecurity, mp);
|
||||
}
|
||||
|
@ -562,7 +618,7 @@ static int hook_post_config(apr_pool_t *mp, apr_pool_t *mp_log, apr_pool_t *mp_t
|
|||
change_server_signature(s);
|
||||
}
|
||||
|
||||
#if (!(defined(WIN32) || defined(NETWARE)))
|
||||
#if (!(defined(WIN32) || defined(NETWARE)))
|
||||
|
||||
/* Internal chroot functionality */
|
||||
|
||||
|
@ -574,37 +630,37 @@ static int hook_post_config(apr_pool_t *mp, apr_pool_t *mp_log, apr_pool_t *mp_t
|
|||
|
||||
if (first_time == 0) {
|
||||
ap_log_error(APLOG_MARK, APLOG_NOTICE | APLOG_NOERRNO, 0, s,
|
||||
"ModSecurity: chroot checkpoint #2 (pid=%ld ppid=%ld)", (long)getpid(), (long)getppid());
|
||||
"ModSecurity: chroot checkpoint #2 (pid=%ld ppid=%ld)", (long)getpid(), (long)getppid());
|
||||
|
||||
if (chdir(chroot_dir) < 0) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, s,
|
||||
"ModSecurity: chroot failed, unable to chdir to %s, errno=%d (%s)",
|
||||
chroot_dir, errno, strerror(errno));
|
||||
"ModSecurity: chroot failed, unable to chdir to %s, errno=%d (%s)",
|
||||
chroot_dir, errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (chroot(chroot_dir) < 0) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, s,
|
||||
"ModSecurity: chroot failed, path=%s, errno=%d(%s)",
|
||||
chroot_dir, errno, strerror(errno));
|
||||
"ModSecurity: chroot failed, path=%s, errno=%d(%s)",
|
||||
chroot_dir, errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (chdir("/") < 0) {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, s,
|
||||
"ModSecurity: chdoot failed, unable to chdir to /, errno=%d (%s)",
|
||||
errno, strerror(errno));
|
||||
"ModSecurity: chdoot failed, unable to chdir to /, errno=%d (%s)",
|
||||
errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ap_log_error(APLOG_MARK, APLOG_NOTICE | APLOG_NOERRNO, 0, s,
|
||||
"ModSecurity: chroot successful, path=%s", chroot_dir);
|
||||
"ModSecurity: chroot successful, path=%s", chroot_dir);
|
||||
} else {
|
||||
ap_log_error(APLOG_MARK, APLOG_NOTICE | APLOG_NOERRNO, 0, s,
|
||||
"ModSecurity: chroot checkpoint #1 (pid=%ld ppid=%ld)", (long)getpid(), (long)getppid());
|
||||
"ModSecurity: chroot checkpoint #1 (pid=%ld ppid=%ld)", (long)getpid(), (long)getppid());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Schedule main cleanup for later, when the main pool is destroyed. */
|
||||
apr_pool_cleanup_register(mp, (void *)s, module_cleanup, apr_pool_cleanup_null);
|
||||
|
@ -619,7 +675,7 @@ static int hook_post_config(apr_pool_t *mp, apr_pool_t *mp_log, apr_pool_t *mp_t
|
|||
/* If we've changed the server signature make note of the original. */
|
||||
if (new_server_signature != NULL) {
|
||||
ap_log_error(APLOG_MARK, APLOG_NOTICE | APLOG_NOERRNO, 0, s,
|
||||
"Original server signature: %s", real_server_signature);
|
||||
"Original server signature: %s", real_server_signature);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -642,6 +698,7 @@ static void hook_child_init(apr_pool_t *mp, server_rec *s) {
|
|||
*/
|
||||
static int hook_request_early(request_rec *r) {
|
||||
modsec_rec *msr = NULL;
|
||||
int rc = DECLINED;
|
||||
|
||||
/* This function needs to run only once per transaction
|
||||
* (i.e. subrequests and redirects are excluded).
|
||||
|
@ -656,22 +713,35 @@ static int hook_request_early(request_rec *r) {
|
|||
msr = create_tx_context(r);
|
||||
if (msr == NULL) return DECLINED;
|
||||
|
||||
#if 0
|
||||
/* NOTE This check is not currently needed, but it may be needed in the
|
||||
* future when we add another early phase.
|
||||
*/
|
||||
#ifdef REQUEST_EARLY
|
||||
|
||||
/* Are we allowed to continue? */
|
||||
if (msr->txcfg->is_enabled == MODSEC_DISABLED) {
|
||||
if (msr->txcfg->debuglog_level >= 4) {
|
||||
msr_log(msr, 4, "Processing disabled, skipping (hook request_early).");
|
||||
}
|
||||
|
||||
return DECLINED;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return DECLINED;
|
||||
/* Process phase REQUEST_HEADERS */
|
||||
if (modsecurity_process_phase(msr, PHASE_REQUEST_HEADERS) > 0) {
|
||||
rc = perform_interception(msr);
|
||||
}
|
||||
|
||||
if ( (msr->txcfg->is_enabled != MODSEC_DISABLED)
|
||||
&& (msr->txcfg->reqbody_access == 1)
|
||||
&& (rc == DECLINED))
|
||||
{
|
||||
/* Check request body limit (non-chunked requests only). */
|
||||
if (msr->request_content_length > msr->txcfg->reqbody_limit) {
|
||||
msr_log(msr, 1, "Request body (Content-Length) is larger than the "
|
||||
"configured limit (%ld).", msr->txcfg->reqbody_limit);
|
||||
if(msr->txcfg->is_enabled != MODSEC_DETECTION_ONLY)
|
||||
return HTTP_REQUEST_ENTITY_TOO_LARGE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -712,7 +782,7 @@ static int hook_request_late(request_rec *r) {
|
|||
|
||||
/* Get the second configuration context. */
|
||||
msr->dcfg2 = (directory_config *)ap_get_module_config(r->per_dir_config,
|
||||
&security2_module);
|
||||
&security2_module);
|
||||
|
||||
/* Create a transaction context. */
|
||||
msr->txcfg = create_directory_config(msr->mp, NULL);
|
||||
|
@ -731,10 +801,10 @@ static int hook_request_late(request_rec *r) {
|
|||
if (msr->txcfg->debuglog_level >= 4) {
|
||||
msr_log(msr, 4, "Processing disabled, skipping (hook request_late).");
|
||||
}
|
||||
|
||||
return DECLINED;
|
||||
}
|
||||
|
||||
#ifndef REQUEST_EARLY
|
||||
/* Phase 1 */
|
||||
if (msr->txcfg->debuglog_level >= 4) {
|
||||
msr_log(msr, 4, "First phase starting (dcfg %pp).", msr->dcfg2);
|
||||
|
@ -749,6 +819,7 @@ static int hook_request_late(request_rec *r) {
|
|||
return rc;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The rule engine could have been disabled in phase 1. */
|
||||
if (msr->txcfg->is_enabled == MODSEC_DISABLED) {
|
||||
|
@ -933,8 +1004,8 @@ static void hook_error_log(const char *file, int line, int level, apr_status_t s
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (msr == NULL) return;
|
||||
|
||||
/* Store the error message for later */
|
||||
em = (error_message *)apr_pcalloc(msr->mp, sizeof(error_message));
|
||||
if (em == NULL) return;
|
||||
|
@ -952,7 +1023,6 @@ static void hook_error_log(const char *file, int line, int level, apr_status_t s
|
|||
em->status = status;
|
||||
if (fmt != NULL) em->message = apr_pstrdup(msr->mp, fmt);
|
||||
#endif
|
||||
|
||||
/* Remove \n from the end of the message */
|
||||
if (em->message != NULL) {
|
||||
char *p = (char *)em->message;
|
||||
|
@ -968,6 +1038,7 @@ static void hook_error_log(const char *file, int line, int level, apr_status_t s
|
|||
*(const error_message **)apr_array_push(msr->error_messages) = em;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Guardian logger is used to interface to the external
|
||||
* script for web server protection - httpd_guardian.
|
||||
|
@ -1007,7 +1078,7 @@ static void sec_guardian_logger(request_rec *r, request_rec *origr, modsec_rec *
|
|||
*/
|
||||
|
||||
str2 = apr_psprintf(msr->mp, "%" APR_TIME_T_FMT " %" APR_TIME_T_FMT " \"%s\" %d",
|
||||
duration, apr_time_sec(duration), log_escape(msr->mp, modsec_message), modsec_rating);
|
||||
duration, apr_time_sec(duration), log_escape(msr->mp, modsec_message), modsec_rating);
|
||||
if (str2 == NULL) return;
|
||||
|
||||
/* We do not want the index line to be longer than 3980 bytes. */
|
||||
|
@ -1087,7 +1158,7 @@ static int hook_log_transaction(request_rec *r) {
|
|||
msr->r = r;
|
||||
msr->response_status = r->status;
|
||||
msr->status_line = ((r->status_line != NULL)
|
||||
? r->status_line : ap_get_status_line(r->status));
|
||||
? r->status_line : ap_get_status_line(r->status));
|
||||
msr->response_protocol = get_response_protocol(origr);
|
||||
msr->response_headers = apr_table_copy(msr->mp, r->headers_out);
|
||||
if (!r->assbackwards) msr->response_headers_sent = 1;
|
||||
|
@ -1121,7 +1192,7 @@ static void hook_insert_filter(request_rec *r) {
|
|||
if (msr->if_status == IF_STATUS_WANTS_TO_RUN) {
|
||||
if (msr->txcfg->debuglog_level >= 4) {
|
||||
msr_log(msr, 4, "Hook insert_filter: Adding input forwarding filter %s(r %pp).",
|
||||
(((r->main != NULL)||(r->prev != NULL)) ? "for subrequest " : ""), r);
|
||||
(((r->main != NULL)||(r->prev != NULL)) ? "for subrequest " : ""), r);
|
||||
}
|
||||
|
||||
ap_add_input_filter("MODSECURITY_IN", msr, r, r->connection);
|
||||
|
@ -1220,15 +1291,15 @@ static void modsec_register_operator(const char *name, void *fn_init, void *fn_e
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* \brief Connetion hook to limit the number of
|
||||
* connections in BUSY state
|
||||
*
|
||||
* \param conn Pointer to connection struct
|
||||
*
|
||||
* \retval DECLINED On failure
|
||||
* \retval OK On Success
|
||||
*/
|
||||
/**
|
||||
* \brief Connetion hook to limit the number of
|
||||
* connections in BUSY state
|
||||
*
|
||||
* \param conn Pointer to connection struct
|
||||
*
|
||||
* \retval DECLINED On failure
|
||||
* \retval OK On Success
|
||||
*/
|
||||
static int hook_connection_early(conn_rec *conn)
|
||||
{
|
||||
sb_handle *sb = conn->sbh;
|
||||
|
|
|
@ -260,6 +260,12 @@ static apr_status_t modsecurity_tx_cleanup(void *data) {
|
|||
msr_log(msr, 1, "%s", my_error_msg);
|
||||
}
|
||||
|
||||
#if defined(WITH_LUA)
|
||||
#ifdef CACHE_LUA
|
||||
if(msr->L != NULL) lua_close(msr->L);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -378,6 +384,12 @@ apr_status_t modsecurity_tx_init(modsec_rec *msr) {
|
|||
if (msr->matched_vars == NULL) return -1;
|
||||
apr_table_clear(msr->matched_vars);
|
||||
|
||||
if(msr->txcfg->max_rule_time > 0) {
|
||||
msr->perf_rules = apr_table_make(msr->mp, 8);
|
||||
if (msr->perf_rules == NULL) return -1;
|
||||
apr_table_clear(msr->perf_rules);
|
||||
}
|
||||
|
||||
/* Locate the cookie headers and parse them */
|
||||
arr = apr_table_elts(msr->request_headers);
|
||||
te = (apr_table_entry_t *)arr->elts;
|
||||
|
@ -423,6 +435,9 @@ apr_status_t modsecurity_tx_init(modsec_rec *msr) {
|
|||
msr->removed_rules_tag = apr_array_make(msr->mp, 16, sizeof(char *));
|
||||
if (msr->removed_rules_tag == NULL) return -1;
|
||||
|
||||
msr->removed_rules_msg = apr_array_make(msr->mp, 16, sizeof(char *));
|
||||
if (msr->removed_rules_msg == NULL) return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,11 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <libxml/tree.h>
|
||||
#include <libxml/HTMLparser.h>
|
||||
|
||||
typedef struct rule_exception rule_exception;
|
||||
typedef struct rule_exception encryption_method;
|
||||
typedef struct modsec_rec modsec_rec;
|
||||
typedef struct directory_config directory_config;
|
||||
typedef struct error_message error_message;
|
||||
|
@ -40,6 +43,7 @@ typedef struct msc_parm msc_parm;
|
|||
#include "msc_gsb.h"
|
||||
#include "msc_unicode.h"
|
||||
#include "re.h"
|
||||
#include "msc_crypt.h"
|
||||
|
||||
#include "ap_config.h"
|
||||
#include "apr_md5.h"
|
||||
|
@ -50,6 +54,11 @@ typedef struct msc_parm msc_parm;
|
|||
#include "http_log.h"
|
||||
#include "http_protocol.h"
|
||||
|
||||
#if defined(WITH_LUA)
|
||||
#include "msc_lua.h"
|
||||
#endif
|
||||
|
||||
|
||||
#define PHASE_REQUEST_HEADERS 1
|
||||
#define PHASE_REQUEST_BODY 2
|
||||
#define PHASE_RESPONSE_HEADERS 3
|
||||
|
@ -101,7 +110,7 @@ typedef struct msc_parm msc_parm;
|
|||
|
||||
#define SECMARKER_TARGETS "REMOTE_ADDR"
|
||||
#define SECMARKER_ARGS "@noMatch"
|
||||
#define SECMARKER_BASE_ACTIONS "t:none,pass,id:"
|
||||
#define SECMARKER_BASE_ACTIONS "t:none,pass,marker:"
|
||||
|
||||
#if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
|
||||
#include "unixd.h"
|
||||
|
@ -172,6 +181,24 @@ extern DSOLOCAL int *unicode_map_table;
|
|||
#define MODSEC_DETECTION_ONLY 1
|
||||
#define MODSEC_ENABLED 2
|
||||
|
||||
#define ENCRYPTION_DISABLED 0
|
||||
#define ENCRYPTION_ENABLED 1
|
||||
|
||||
#define ENCRYPTION_URL_HREF_HASH_RX 0
|
||||
#define ENCRYPTION_URL_HREF_HASH_PM 1
|
||||
#define ENCRYPTION_URL_FACTION_HASH_RX 2
|
||||
#define ENCRYPTION_URL_FACTION_HASH_PM 3
|
||||
#define ENCRYPTION_URL_LOCATION_HASH_RX 4
|
||||
#define ENCRYPTION_URL_LOCATION_HASH_PM 5
|
||||
#define ENCRYPTION_URL_IFRAMESRC_HASH_RX 6
|
||||
#define ENCRYPTION_URL_IFRAMESRC_HASH_PM 7
|
||||
#define ENCRYPTION_URL_FRAMESRC_HASH_RX 8
|
||||
#define ENCRYPTION_URL_FRAMESRC_HASH_PM 9
|
||||
|
||||
#define ENCRYPTION_KEYONLY 0
|
||||
#define ENCRYPTION_SESSIONID 1
|
||||
#define ENCRYPTION_REMOTEIP 2
|
||||
|
||||
#define MODSEC_CACHE_DISABLED 0
|
||||
#define MODSEC_CACHE_ENABLED 1
|
||||
|
||||
|
@ -259,6 +286,9 @@ struct modsec_rec {
|
|||
unsigned int remote_port;
|
||||
const char *remote_user;
|
||||
|
||||
/* useragent */
|
||||
const char *useragent_ip;
|
||||
|
||||
/* request */
|
||||
|
||||
const char *request_line;
|
||||
|
@ -342,7 +372,7 @@ struct modsec_rec {
|
|||
const char *intercept_message;
|
||||
|
||||
/* performance measurement */
|
||||
apr_time_t request_time;
|
||||
apr_time_t request_time;
|
||||
apr_time_t time_phase1;
|
||||
apr_time_t time_phase2;
|
||||
apr_time_t time_phase3;
|
||||
|
@ -352,7 +382,8 @@ struct modsec_rec {
|
|||
apr_time_t time_storage_write;
|
||||
apr_time_t time_logging;
|
||||
apr_time_t time_gc;
|
||||
|
||||
apr_table_t *perf_rules;
|
||||
|
||||
apr_array_header_t *matched_rules;
|
||||
msc_string *matched_var;
|
||||
int highest_severity;
|
||||
|
@ -383,6 +414,7 @@ struct modsec_rec {
|
|||
/* removed rules */
|
||||
apr_array_header_t *removed_rules;
|
||||
apr_array_header_t *removed_rules_tag;
|
||||
apr_array_header_t *removed_rules_msg;
|
||||
|
||||
/* When "allow" is executed the variable below is
|
||||
* updated to contain the scope of the allow action. Set
|
||||
|
@ -397,6 +429,13 @@ struct modsec_rec {
|
|||
|
||||
/* Generic request body processor context to be used by custom parsers. */
|
||||
void *reqbody_processor_ctx;
|
||||
|
||||
htmlDocPtr crypto_html_tree;
|
||||
#if defined(WITH_LUA)
|
||||
#ifdef CACHE_LUA
|
||||
lua_State *L;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
struct directory_config {
|
||||
|
@ -432,6 +471,9 @@ struct directory_config {
|
|||
|
||||
/* -- Audit log -- */
|
||||
|
||||
/* Max rule time */
|
||||
int max_rule_time;
|
||||
|
||||
/* Whether audit log should be enabled in the context or not */
|
||||
int auditlog_flag;
|
||||
|
||||
|
@ -486,6 +528,7 @@ struct directory_config {
|
|||
/* Misc */
|
||||
const char *data_dir;
|
||||
const char *webappid;
|
||||
const char *sensor_id;
|
||||
const char *httpBlkey;
|
||||
|
||||
/* Content injection. */
|
||||
|
@ -523,6 +566,25 @@ struct directory_config {
|
|||
|
||||
/* Collection timeout */
|
||||
int col_timeout;
|
||||
|
||||
/* Encryption */
|
||||
apr_array_header_t *encryption_method;
|
||||
const char *crypto_key;
|
||||
int crypto_key_len;
|
||||
const char *crypto_param_name;
|
||||
int encryption_is_enabled;
|
||||
int encryption_enforcement;
|
||||
int crypto_key_add;
|
||||
int crypto_hash_href_rx;
|
||||
int crypto_hash_faction_rx;
|
||||
int crypto_hash_location_rx;
|
||||
int crypto_hash_iframesrc_rx;
|
||||
int crypto_hash_framesrc_rx;
|
||||
int crypto_hash_href_pm;
|
||||
int crypto_hash_faction_pm;
|
||||
int crypto_hash_location_pm;
|
||||
int crypto_hash_iframesrc_pm;
|
||||
int crypto_hash_framesrc_pm;
|
||||
};
|
||||
|
||||
struct error_message {
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
|
||||
* Copyright (c) 2004-2011 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.
|
||||
*/
|
||||
|
||||
#ifndef _MSC_CRYPT_H_
|
||||
#define _MSC_CRYPT_H_
|
||||
|
||||
#include "modsecurity.h"
|
||||
#include <libxml/HTMLparser.h>
|
||||
#include <libxml/xpath.h>
|
||||
|
||||
#define HMAC_PAD_SIZE 65
|
||||
#define HASH_ONLY 0
|
||||
#define FULL_LINK 1
|
||||
|
||||
#ifndef INT32_MAX
|
||||
#define INT32_MAX (2147483647)
|
||||
#endif
|
||||
|
||||
char DSOLOCAL *hmac(modsec_rec *msr,const unsigned char *key, int key_len,
|
||||
char *msg, int msglen);
|
||||
unsigned char DSOLOCAL *do_hash_link(modsec_rec *msr, char *link,
|
||||
int type);
|
||||
unsigned char DSOLOCAL *getkey(apr_pool_t *mp);
|
||||
|
||||
int DSOLOCAL init_response_body_html_parser(modsec_rec *msr);
|
||||
int DSOLOCAL encrypt_response_body_links(modsec_rec *msr);
|
||||
int DSOLOCAL inject_encrypted_response_body(modsec_rec *msr, int elts);
|
||||
int DSOLOCAL do_encryption_method(modsec_rec *msr, char *link, int type);
|
||||
int DSOLOCAL modify_response_header(modsec_rec *msr);
|
||||
char DSOLOCAL *normalize_path(modsec_rec *msr, char *input);
|
||||
#endif
|
|
@ -14,6 +14,14 @@
|
|||
|
||||
#include "msc_gsb.h"
|
||||
|
||||
/** \brief Load GSB database
|
||||
*
|
||||
* \param dcfg Pointer to directory configuration
|
||||
* \param error_msg Error message
|
||||
*
|
||||
* \retval 1 On Success
|
||||
* \retval 0 On Fail
|
||||
*/
|
||||
static int gsb_db_create(directory_config *dcfg, char **error_msg)
|
||||
{
|
||||
char errstr[1024];
|
||||
|
@ -89,8 +97,14 @@ static int gsb_db_create(directory_config *dcfg, char **error_msg)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialise Gsb malware data structure
|
||||
/** \brief Init GSB database
|
||||
*
|
||||
* \param dcfg Pointer to directory configuration
|
||||
* \param dbfn Database filename
|
||||
* \param error_msg Error message
|
||||
*
|
||||
* \retval gsb_db_create On Success
|
||||
* \retval -1 On Fail
|
||||
*/
|
||||
int gsb_db_init(directory_config *dcfg, const char *dbfn, char **error_msg)
|
||||
{
|
||||
|
|
|
@ -1050,6 +1050,41 @@ void sec_audit_logger(modsec_rec *msr) {
|
|||
msr->userid == NULL ? "-" : log_escape(msr->mp, msr->userid));
|
||||
sec_auditlog_write(msr, text, strlen(text));
|
||||
}
|
||||
|
||||
if ( ((msr->txcfg->sensor_id != NULL)&&(strcmp(msr->txcfg->sensor_id, "default") != 0)))
|
||||
{
|
||||
text = apr_psprintf(msr->mp, "Sensor-Id: \"%s\"\n",
|
||||
msr->txcfg->sensor_id == NULL ? "-" : log_escape(msr->mp, msr->txcfg->sensor_id)),
|
||||
sec_auditlog_write(msr, text, strlen(text));
|
||||
}
|
||||
|
||||
|
||||
if (msr->txcfg->is_enabled > 0) {
|
||||
text = apr_psprintf(msr->mp, "Engine-Mode: \"%s\"\n",
|
||||
msr->txcfg->is_enabled == 1 ? "DETECTION_ONLY" : "ENABLED"),
|
||||
sec_auditlog_write(msr, text, strlen(text));
|
||||
}
|
||||
|
||||
/* Rule performance time */
|
||||
if(msr->txcfg->max_rule_time > 0) {
|
||||
const apr_array_header_t *tarr;
|
||||
const apr_table_entry_t *telts;
|
||||
|
||||
tarr = apr_table_elts(msr->perf_rules);
|
||||
telts = (const apr_table_entry_t*)tarr->elts;
|
||||
|
||||
if (tarr->nelts > 0) {
|
||||
text = apr_psprintf(msr->mp, "Rules-Performance-Info: ");
|
||||
sec_auditlog_write(msr, text, strlen(text));
|
||||
}
|
||||
|
||||
for(i = 0; i < tarr->nelts; i++) {
|
||||
text = apr_psprintf(msr->mp, "%s\"%s=%s\"%s", ((i == 0) ? "" : ", "),
|
||||
log_escape(msr->mp, telts[i].key), log_escape(msr->mp, telts[i].val), ((i == (tarr->nelts - 1)) ? ".\n" : ""));
|
||||
sec_auditlog_write(msr, text, strlen(text));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* AUDITLOG_PART_UPLOADS */
|
||||
|
|
|
@ -393,7 +393,7 @@ static const struct luaL_Reg mylib[] = {
|
|||
int lua_execute(msc_script *script, char *param, modsec_rec *msr, msre_rule *rule, char **error_msg) {
|
||||
apr_time_t time_before;
|
||||
lua_State *L = NULL;
|
||||
int rc;
|
||||
int rc = 0;
|
||||
|
||||
if (error_msg == NULL) return -1;
|
||||
*error_msg = NULL;
|
||||
|
@ -404,10 +404,19 @@ int lua_execute(msc_script *script, char *param, modsec_rec *msr, msre_rule *rul
|
|||
|
||||
time_before = apr_time_now();
|
||||
|
||||
#ifdef CACHE_LUA
|
||||
L = msr->L;
|
||||
rc = lua_gettop(L);
|
||||
if(rc)
|
||||
lua_pop(L, rc);
|
||||
#else
|
||||
/* Create new state. */
|
||||
L = lua_open();
|
||||
|
||||
luaL_openlibs(L);
|
||||
#endif
|
||||
|
||||
if(L == NULL)
|
||||
return -1;
|
||||
|
||||
/* Associate msr with the state. */
|
||||
lua_pushlightuserdata(L, (void *)msr);
|
||||
|
@ -441,6 +450,11 @@ int lua_execute(msc_script *script, char *param, modsec_rec *msr, msre_rule *rul
|
|||
|
||||
if (lua_pcall(L, ((param != NULL) ? 1 : 0), 1, 0)) {
|
||||
*error_msg = apr_psprintf(msr->mp, "Lua: Script execution failed: %s", lua_tostring(L, -1));
|
||||
|
||||
if (msr->txcfg->debuglog_level >= 8) {
|
||||
msr_log(msr, 8, "Lua: Script execution failed: %s", lua_tostring(L, -1));
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -452,7 +466,9 @@ int lua_execute(msc_script *script, char *param, modsec_rec *msr, msre_rule *rul
|
|||
|
||||
/* Destroy state. */
|
||||
lua_pop(L, 1);
|
||||
#ifndef CACHE_LUA
|
||||
lua_close(L);
|
||||
#endif
|
||||
|
||||
/* Returns status code to caller. */
|
||||
if (msr->txcfg->debuglog_level >= 8) {
|
||||
|
|
|
@ -39,8 +39,8 @@
|
|||
#define MODSEC_VERSION_MAJOR "2"
|
||||
#define MODSEC_VERSION_MINOR "7"
|
||||
#define MODSEC_VERSION_MAINT "0"
|
||||
#define MODSEC_VERSION_TYPE "trunk"
|
||||
#define MODSEC_VERSION_RELEASE ""
|
||||
#define MODSEC_VERSION_TYPE "-rc"
|
||||
#define MODSEC_VERSION_RELEASE "1"
|
||||
|
||||
#define MODSEC_VERSION_SUFFIX MODSEC_VERSION_TYPE MODSEC_VERSION_RELEASE
|
||||
|
||||
|
|
|
@ -16,6 +16,14 @@
|
|||
|
||||
#define CODEPAGE_SEPARATORS " \t\n\r"
|
||||
|
||||
/** \brief Load Unicode file
|
||||
*
|
||||
* \param dcfg Pointer to directory configuration
|
||||
* \param error_msg Error message
|
||||
*
|
||||
* \retval 1 On Success
|
||||
* \retval 0 On Fail
|
||||
*/
|
||||
static int unicode_map_create(directory_config *dcfg, char **error_msg)
|
||||
{
|
||||
char errstr[1024];
|
||||
|
@ -129,8 +137,14 @@ static int unicode_map_create(directory_config *dcfg, char **error_msg)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialise Unicode Map data structure
|
||||
/** \brief Init unicode map
|
||||
*
|
||||
* \param dcfg Pointer to directory configuration
|
||||
* \param mapfn Unicode map filename
|
||||
* \param error_msg Error message
|
||||
*
|
||||
* \retval unicode_map_create On Success
|
||||
* \retval -1 On Fail
|
||||
*/
|
||||
int unicode_map_init(directory_config *dcfg, const char *mapfn, char **error_msg)
|
||||
{
|
||||
|
|
|
@ -74,7 +74,151 @@ static unsigned char *c2x(unsigned what, unsigned char *where);
|
|||
static unsigned char x2c(unsigned char *what);
|
||||
static unsigned char xsingle2c(unsigned char *what);
|
||||
|
||||
/* \brief Remove escape char
|
||||
/** \brief Interpret |HEX| syntax
|
||||
*
|
||||
* \param op_parm Pointer to operator input
|
||||
* \param op_len Operator input lenght
|
||||
* \param rule Pointer to rule struct
|
||||
* \param error_msg Pointer to error message
|
||||
*
|
||||
* \retval string On Success
|
||||
*/
|
||||
char *parse_pm_content(const char *op_parm, unsigned short int op_len, msre_rule *rule, char **error_msg) {
|
||||
char *parm = NULL;
|
||||
char *content = NULL;
|
||||
unsigned short int offset = 0;
|
||||
char converted = 0;
|
||||
int i, x;
|
||||
unsigned char bin = 0, esc = 0, bin_offset = 0;
|
||||
unsigned char bin_parm[3], c = 0;
|
||||
char *processed = NULL;
|
||||
|
||||
content = apr_pstrdup(rule->ruleset->mp, op_parm);
|
||||
|
||||
if (content == NULL) {
|
||||
*error_msg = apr_psprintf(rule->ruleset->mp, "Error allocating memory for pattern matching content.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (offset < op_len && apr_isspace(content[offset])) {
|
||||
offset++;
|
||||
};
|
||||
|
||||
op_len = strlen(content);
|
||||
|
||||
if (content[offset] == '\"' && content[op_len-1] == '\"') {
|
||||
parm = apr_pstrdup(rule->ruleset->mp, content + offset + 1);
|
||||
if (parm == NULL) {
|
||||
*error_msg = apr_psprintf(rule->ruleset->mp, "Error allocating memory for pattern matching content.");
|
||||
return NULL;
|
||||
}
|
||||
parm[op_len - offset - 2] = '\0';
|
||||
} else {
|
||||
parm = apr_pstrdup(rule->ruleset->mp, content + offset);
|
||||
if (parm == NULL) {
|
||||
*error_msg = apr_psprintf(rule->ruleset->mp, "Error allocating memory for pattern matching content.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
op_len = strlen(parm);
|
||||
|
||||
if (op_len == 0) {
|
||||
*error_msg = apr_psprintf(rule->ruleset->mp, "Content length is 0.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0, x = 0; i < op_len; i++) {
|
||||
if (parm[i] == '|') {
|
||||
if (bin) {
|
||||
bin = 0;
|
||||
} else {
|
||||
bin = 1;
|
||||
}
|
||||
} else if(!esc && parm[i] == '\\') {
|
||||
esc = 1;
|
||||
} else {
|
||||
if (bin) {
|
||||
if (apr_isdigit(parm[i]) ||
|
||||
parm[i] == 'A' || parm[i] == 'a' ||
|
||||
parm[i] == 'B' || parm[i] == 'b' ||
|
||||
parm[i] == 'C' || parm[i] == 'c' ||
|
||||
parm[i] == 'D' || parm[i] == 'd' ||
|
||||
parm[i] == 'E' || parm[i] == 'e' ||
|
||||
parm[i] == 'F' || parm[i] == 'f')
|
||||
{
|
||||
bin_parm[bin_offset] = (char)parm[i];
|
||||
bin_offset++;
|
||||
if (bin_offset == 2) {
|
||||
c = strtol((char *)bin_parm, (char **) NULL, 16) & 0xFF;
|
||||
bin_offset = 0;
|
||||
parm[x] = c;
|
||||
x++;
|
||||
converted = 1;
|
||||
}
|
||||
} else if (parm[i] == ' ') {
|
||||
}
|
||||
} else if (esc) {
|
||||
if (parm[i] == ':' ||
|
||||
parm[i] == ';' ||
|
||||
parm[i] == '\\' ||
|
||||
parm[i] == '\"')
|
||||
{
|
||||
parm[x] = parm[i];
|
||||
x++;
|
||||
} else {
|
||||
*error_msg = apr_psprintf(rule->ruleset->mp, "Unsupported escape sequence.");
|
||||
return NULL;
|
||||
}
|
||||
esc = 0;
|
||||
converted = 1;
|
||||
} else {
|
||||
parm[x] = parm[i];
|
||||
x++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (converted) {
|
||||
op_len = x;
|
||||
}
|
||||
|
||||
processed = apr_pstrmemdup(rule->ruleset->mp, parm, op_len);
|
||||
|
||||
if (processed == NULL) {
|
||||
*error_msg = apr_psprintf(rule->ruleset->mp, "Error allocating memory for pattern matching content.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return processed;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Remove quotes
|
||||
*
|
||||
* \param mptmp Pointer to the pool
|
||||
* \param input Pointer to input string
|
||||
* \param input_len Input data length
|
||||
*
|
||||
* \retval string On Success
|
||||
*/
|
||||
char *remove_quotes(apr_pool_t *mptmp, const char *input, int input_len) {
|
||||
char *parm = apr_palloc(mptmp, input_len);
|
||||
char *ret = parm;
|
||||
int len = input_len;
|
||||
|
||||
for(; *input !='\0' && len >=0; input++, len--) {
|
||||
if(*input != '\'' && *input != '\"') {
|
||||
*parm++ = *input;
|
||||
}
|
||||
}
|
||||
|
||||
*parm = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** \brief Remove escape char
|
||||
*
|
||||
* \param mptmp Pointer to the pool
|
||||
* \param input Pointer to input string
|
||||
|
@ -112,7 +256,7 @@ int parse_boolean(const char *input) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* \brief Decode Base64 data with special chars
|
||||
/** \brief Decode Base64 data with special chars
|
||||
*
|
||||
* \param plain_text Pointer to plain text data
|
||||
* \param input Pointer to input data
|
||||
|
@ -121,8 +265,7 @@ int parse_boolean(const char *input) {
|
|||
* \retval 0 On failure
|
||||
* \retval string length On Success
|
||||
*/
|
||||
int decode_base64_ext(char *plain_text, const unsigned char *input, int input_len)
|
||||
{
|
||||
int decode_base64_ext(char *plain_text, const unsigned char *input, int input_len) {
|
||||
const unsigned char *encoded = input;
|
||||
int i = 0, j = 0, k = 0;
|
||||
int ch = 0;
|
||||
|
@ -177,13 +320,14 @@ int decode_base64_ext(char *plain_text, const unsigned char *input, int input_le
|
|||
return j;
|
||||
}
|
||||
|
||||
/* \brief Convert const char to int
|
||||
/** \brief Convert const char to int
|
||||
*
|
||||
* \param c number string
|
||||
*
|
||||
* \retval n The converted number
|
||||
*/
|
||||
int convert_to_int(const char c) {
|
||||
int convert_to_int(const char c)
|
||||
{
|
||||
int n;
|
||||
if ((c>='0') && (c<='9'))
|
||||
n = c - '0';
|
||||
|
@ -196,7 +340,7 @@ int convert_to_int(const char c) {
|
|||
return n;
|
||||
}
|
||||
|
||||
/* \brief Set a match to tx.N
|
||||
/** \brief Set a match to tx.N
|
||||
*
|
||||
* \param msr Pointer to modsec resource
|
||||
* \param capture If ON match will be saved
|
||||
|
@ -223,6 +367,7 @@ int set_match_to_tx(modsec_rec *msr, int capture, const char *match, int tx_n)
|
|||
msr_log(msr, 9, "Added phrase match to TX.%d: %s",
|
||||
tx_n, log_escape_nq_ex(msr->mp, s->value, s->value_len));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -437,7 +582,7 @@ int sql_hex2bytes_inplace(unsigned char *data, int len) {
|
|||
}
|
||||
|
||||
*d = '\0';
|
||||
return strlen(begin);
|
||||
return strlen((char *)begin);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -632,13 +777,13 @@ char *current_filetime(apr_pool_t *mp) {
|
|||
/**
|
||||
*
|
||||
*/
|
||||
int msc_mkstemp_ex(char *template, int mode) {
|
||||
int msc_mkstemp_ex(char *templat, int mode) {
|
||||
int fd = -1;
|
||||
|
||||
/* ENH Use apr_file_mktemp instead. */
|
||||
|
||||
#if !(defined(WIN32)||defined(NETWARE))
|
||||
fd = mkstemp(template);
|
||||
fd = mkstemp(templat);
|
||||
#ifdef HAVE_FCHMOD
|
||||
if ((fd != -1) && (mode != 0)) {
|
||||
if (fchmod(fd, mode) == -1) {
|
||||
|
@ -647,8 +792,8 @@ int msc_mkstemp_ex(char *template, int mode) {
|
|||
}
|
||||
#endif /* HAVE_FCHMOD */
|
||||
#else
|
||||
if (mktemp(template) == NULL) return -1;
|
||||
fd = open(template, O_WRONLY | O_APPEND | O_CREAT | O_BINARY, mode);
|
||||
if (mktemp(templat) == NULL) return -1;
|
||||
fd = open(templat, O_WRONLY | O_APPEND | O_CREAT | O_BINARY, mode);
|
||||
#endif /* !(defined(WIN32)||defined(NETWARE)) */
|
||||
|
||||
return fd;
|
||||
|
@ -657,8 +802,8 @@ int msc_mkstemp_ex(char *template, int mode) {
|
|||
/**
|
||||
*
|
||||
*/
|
||||
int msc_mkstemp(char *template) {
|
||||
return msc_mkstemp_ex(template, CREATEMODE_UNISTD);
|
||||
int msc_mkstemp(char *templat) {
|
||||
return msc_mkstemp_ex(templat, CREATEMODE_UNISTD);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -26,11 +26,16 @@
|
|||
#endif
|
||||
|
||||
#include "modsecurity.h"
|
||||
#include "re.h"
|
||||
|
||||
int DSOLOCAL normalize_path_inplace(unsigned char *input, int len, int win, int *changed);
|
||||
|
||||
int DSOLOCAL parse_boolean(const char *input);
|
||||
|
||||
char DSOLOCAL *remove_quotes(apr_pool_t *mptmp, const char *input, int input_len);
|
||||
|
||||
char DSOLOCAL *parse_pm_content(const char *op_parm, unsigned short int op_len, msre_rule *rule, char **error_msg);
|
||||
|
||||
char DSOLOCAL *remove_escape(apr_pool_t *mptmp, const char *input, int input_len);
|
||||
|
||||
int DSOLOCAL parse_name_eq_value(apr_pool_t *mp, const char *input, char **name, char **value);
|
||||
|
@ -59,9 +64,9 @@ char DSOLOCAL *current_logtime(apr_pool_t *mp);
|
|||
|
||||
char DSOLOCAL *current_filetime(apr_pool_t *mp);
|
||||
|
||||
int DSOLOCAL msc_mkstemp_ex(char *template, int mode);
|
||||
int DSOLOCAL msc_mkstemp_ex(char *templat, int mode);
|
||||
|
||||
int DSOLOCAL msc_mkstemp(char *template);
|
||||
int DSOLOCAL msc_mkstemp(char *templat);
|
||||
|
||||
char DSOLOCAL *strtolower_inplace(unsigned char *str);
|
||||
|
||||
|
|
|
@ -108,10 +108,12 @@ static apr_table_t *collection_retrieve_ex(apr_sdbm_t *existing_dbm, modsec_rec
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
if(strstr(col_name,"USER") || strstr(col_name,"SESSION"))
|
||||
dbm_filename = apr_pstrcat(msr->mp, msr->txcfg->data_dir, "/", msr->txcfg->webappid, "_", col_name, NULL);
|
||||
else
|
||||
dbm_filename = apr_pstrcat(msr->mp, msr->txcfg->data_dir, "/", col_name, NULL);
|
||||
dbm_filename = apr_pstrcat(msr->mp, msr->txcfg->data_dir, "/", col_name, NULL);
|
||||
|
||||
if (msr->txcfg->debuglog_level >= 9) {
|
||||
msr_log(msr, 9, "collection_retrieve_ex: Retrieving collection (name \"%s\", filename \"%s\")",log_escape(msr->mp, col_name),
|
||||
log_escape(msr->mp, dbm_filename));
|
||||
}
|
||||
|
||||
key.dptr = (char *)col_key;
|
||||
key.dsize = col_key_len + 1;
|
||||
|
@ -353,6 +355,11 @@ int collection_store(modsec_rec *msr, apr_table_t *col) {
|
|||
// ENH: lowercase the var name in the filename
|
||||
dbm_filename = apr_pstrcat(msr->mp, msr->txcfg->data_dir, "/", var_name->value, NULL);
|
||||
|
||||
if (msr->txcfg->debuglog_level >= 9) {
|
||||
msr_log(msr, 9, "collection_store: Retrieving collection (name \"%s\", filename \"%s\")",log_escape(msr->mp, var_name->value),
|
||||
log_escape(msr->mp, dbm_filename));
|
||||
}
|
||||
|
||||
/* Delete IS_NEW on store. */
|
||||
apr_table_unset(col, "IS_NEW");
|
||||
|
||||
|
@ -579,16 +586,21 @@ int collections_remove_stale(modsec_rec *msr, const char *col_name) {
|
|||
goto error;
|
||||
}
|
||||
|
||||
if(strstr(col_name,"USER") || strstr(col_name,"SESSION"))
|
||||
if(strcasestr(col_name,"user") || strcasestr(col_name,"session") || strcasestr(col_name,"resource"))
|
||||
dbm_filename = apr_pstrcat(msr->mp, msr->txcfg->data_dir, "/", msr->txcfg->webappid, "_", col_name, NULL);
|
||||
else
|
||||
dbm_filename = apr_pstrcat(msr->mp, msr->txcfg->data_dir, "/", col_name, NULL);
|
||||
|
||||
if (msr->txcfg->debuglog_level >= 9) {
|
||||
msr_log(msr, 9, "collections_remove_stale: Retrieving collection (name \"%s\", filename \"%s\")",log_escape(msr->mp, col_name),
|
||||
log_escape(msr->mp, dbm_filename));
|
||||
}
|
||||
|
||||
rc = apr_sdbm_open(&dbm, dbm_filename, APR_CREATE | APR_WRITE | APR_SHARELOCK,
|
||||
CREATEMODE, msr->mp);
|
||||
CREATEMODE, msr->mp);
|
||||
if (rc != APR_SUCCESS) {
|
||||
msr_log(msr, 1, "Failed to access DBM file \"%s\": %s", log_escape(msr->mp, dbm_filename),
|
||||
get_apr_error(msr->mp, rc));
|
||||
get_apr_error(msr->mp, rc));
|
||||
dbm = NULL;
|
||||
goto error;
|
||||
}
|
||||
|
|
594
apache2/re.c
594
apache2/re.c
|
@ -42,147 +42,137 @@ static msre_action *msre_create_action(msre_engine *engine, const char *name,
|
|||
static apr_status_t msre_rule_process(msre_rule *rule, modsec_rec *msr);
|
||||
|
||||
/* -- Actions, variables, functions and operator functions ----------------- */
|
||||
/**
|
||||
* \brief Update target for all matching rules in set, in any phase
|
||||
*
|
||||
* \param msr ModSecurity transaction resource
|
||||
* \param ruleset Pointer to set of rules to modify
|
||||
* \param re Pointer to exception object describing which rules to modify
|
||||
* \param p2 Pointer to configuration option TARGET
|
||||
* \param p3 Pointer to configuration option REPLACED_TARGET
|
||||
*/
|
||||
char *msre_ruleset_rule_update_target_matching_exception(modsec_rec *msr, msre_ruleset *ruleset, rule_exception *re, const char *p2, const char *p3) {
|
||||
char *err;
|
||||
|
||||
char *update_rule_target(cmd_parms *cmd, directory_config *dcfg,
|
||||
msre_ruleset *rset, const char *p1, const char *p2, const char *p3)
|
||||
if(ruleset == NULL)
|
||||
return apr_psprintf(ruleset->mp, "No ruleset present");
|
||||
|
||||
if(p2 == NULL) {
|
||||
return apr_psprintf(ruleset->mp, "Trying to update without a target");
|
||||
}
|
||||
|
||||
if (NULL != (err = msre_ruleset_phase_rule_update_target_matching_exception(msr, ruleset, re, ruleset->phase_request_headers, p2, p3)))
|
||||
return err;
|
||||
if (NULL != (err = msre_ruleset_phase_rule_update_target_matching_exception(msr, ruleset, re, ruleset->phase_request_body, p2, p3)))
|
||||
return err;
|
||||
if (NULL != (err = msre_ruleset_phase_rule_update_target_matching_exception(msr, ruleset, re, ruleset->phase_response_headers, p2, p3)))
|
||||
return err;
|
||||
if (NULL != (err = msre_ruleset_phase_rule_update_target_matching_exception(msr, ruleset, re, ruleset->phase_response_body, p2, p3)))
|
||||
return err;
|
||||
if (NULL != (err = msre_ruleset_phase_rule_update_target_matching_exception(msr, ruleset, re, ruleset->phase_logging, p2, p3)))
|
||||
return err;
|
||||
|
||||
/* Everything worked! */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Update target for all matching rules in set for a specific phase
|
||||
*
|
||||
* \param msr ModSecurity transaction resource
|
||||
* \param ruleset Pointer to set of rules to modify
|
||||
* \param re Pointer to exception object describing which rules to modify
|
||||
* \param phase_arr Pointer to phase that should be edited
|
||||
* \param p2 Pointer to configuration option TARGET
|
||||
* \param p3 Pointer to configuration option REPLACED_TARGET
|
||||
*
|
||||
* \todo Figure out error checking
|
||||
*/
|
||||
char *msre_ruleset_phase_rule_update_target_matching_exception(modsec_rec *msr, msre_ruleset *ruleset, rule_exception *re,
|
||||
apr_array_header_t *phase_arr, const char *p2,
|
||||
const char *p3)
|
||||
{
|
||||
msre_rule **rules;
|
||||
int i, j, mode;
|
||||
char *err;
|
||||
|
||||
j = 0;
|
||||
mode = 0;
|
||||
rules = (msre_rule **)phase_arr->elts;
|
||||
for (i = 0; i < phase_arr->nelts; i++) {
|
||||
msre_rule *rule = (msre_rule *)rules[i];
|
||||
|
||||
if (mode == 0) { /* Looking for next rule. */
|
||||
if (msre_ruleset_rule_matches_exception(rule, re)) {
|
||||
|
||||
err = update_rule_target_ex(NULL, ruleset, rule, p2, p3);
|
||||
if (err) return err;
|
||||
if (rule->actionset->is_chained) mode = 2; /* Match all rules in this chain. */
|
||||
} else {
|
||||
if (rule->actionset->is_chained) mode = 1; /* Skip all rules in this chain. */
|
||||
}
|
||||
} else { /* Handling rule that is part of a chain. */
|
||||
if (mode == 2) { /* We want to change the rule. */
|
||||
err = update_rule_target_ex(msr, ruleset, rule, p2, p3);
|
||||
if (err) return err;
|
||||
} else {
|
||||
rules[j++] = rules[i];
|
||||
}
|
||||
|
||||
if ((rule->actionset == NULL)||(rule->actionset->is_chained == 0)) mode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
char *update_rule_target_ex(modsec_rec *msr, msre_ruleset *ruleset, msre_rule *rule, const char *p2,
|
||||
const char *p3) {
|
||||
|
||||
msre_var **targets = NULL;
|
||||
msre_rule *rule = NULL;
|
||||
msre_ruleset *ruleset = NULL;
|
||||
const char *curr_targets = NULL;
|
||||
const char *current_targets = NULL;
|
||||
char *my_error_msg = NULL, *target = NULL;
|
||||
char *p = NULL, *savedptr = NULL;
|
||||
char *target_list = NULL, *replace = NULL;
|
||||
unsigned int is_negated = 0, is_counting = 0;
|
||||
int name_len = 0, value_len = 0;
|
||||
char *name = NULL, *value = NULL;
|
||||
char *opt = NULL, *param = NULL;
|
||||
char *target_list = NULL, *replace = NULL;
|
||||
int i, rc, match = 0;
|
||||
int offset = 0;
|
||||
|
||||
if(p1 == NULL || p2 == NULL || (dcfg == NULL && rset == NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
if(rule != NULL) {
|
||||
|
||||
if(dcfg != NULL)
|
||||
ruleset = dcfg->ruleset;
|
||||
else if (rset != NULL)
|
||||
ruleset = rset;
|
||||
|
||||
/* Get the ruleset if one exists */
|
||||
if ((ruleset == NULL)||(ruleset == NOT_SET_P)) {
|
||||
return NULL;
|
||||
}
|
||||
rule = msre_ruleset_fetch_rule(ruleset, p1, offset);
|
||||
if (rule == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
target_list = strdup(p2);
|
||||
if(target_list == NULL)
|
||||
return NULL;
|
||||
|
||||
if(p3 != NULL) {
|
||||
replace = strdup(p3);
|
||||
if(replace == NULL) {
|
||||
free(target_list);
|
||||
target_list = NULL;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if(replace != NULL) {
|
||||
|
||||
opt = strchr(replace,'!');
|
||||
|
||||
if(opt != NULL) {
|
||||
*opt = '\0';
|
||||
opt++;
|
||||
param = opt;
|
||||
is_negated = 1;
|
||||
} else if ((opt = strchr(replace,'&')) != NULL) {
|
||||
*opt = '\0';
|
||||
opt++;
|
||||
param = opt;
|
||||
is_counting = 1;
|
||||
} else {
|
||||
param = replace;
|
||||
}
|
||||
|
||||
opt = strchr(param,':');
|
||||
|
||||
if(opt != NULL) {
|
||||
name = apr_strtok(param,":",&value);
|
||||
} else {
|
||||
name = param;
|
||||
}
|
||||
|
||||
name_len = strlen(name);
|
||||
|
||||
if(value != NULL)
|
||||
value_len = strlen(value);
|
||||
|
||||
targets = (msre_var **)rule->targets->elts;
|
||||
// TODO need a good way to remove the element from array, maybe change array by tables or rings
|
||||
for (i = 0; i < rule->targets->nelts; i++) {
|
||||
if((strlen(targets[i]->name) == strlen(name)) &&
|
||||
(strncasecmp(targets[i]->name,name,strlen(targets[i]->name)) == 0) &&
|
||||
(targets[i]->is_negated == is_negated) &&
|
||||
(targets[i]->is_counting == is_counting)) {
|
||||
|
||||
if(value != NULL && targets[i]->param != NULL) {
|
||||
if((strlen(targets[i]->param) == strlen(value)) &&
|
||||
strncasecmp(targets[i]->param,value,strlen(targets[i]->param)) == 0) {
|
||||
memset(targets[i]->name,0,strlen(targets[i]->name));
|
||||
memset(targets[i]->param,0,strlen(targets[i]->param));
|
||||
match = 1;
|
||||
}
|
||||
} else if (value == NULL && targets[i]->param == NULL){
|
||||
memset(targets[i]->name,0,strlen(targets[i]->name));
|
||||
match = 1;
|
||||
} else
|
||||
continue;
|
||||
target_list = strdup(p2);
|
||||
if(target_list == NULL)
|
||||
return apr_psprintf(ruleset->mp, "Error to update target - memory allocation");;
|
||||
|
||||
if(p3 != NULL) {
|
||||
replace = strdup(p3);
|
||||
if(replace == NULL) {
|
||||
free(target_list);
|
||||
target_list = NULL;
|
||||
return apr_psprintf(ruleset->mp, "Error to update target - memory allocation");;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p = apr_strtok(target_list, ",", &savedptr);
|
||||
|
||||
while(p != NULL) {
|
||||
|
||||
if(replace != NULL) {
|
||||
if(match == 1) {
|
||||
rc = msre_parse_targets(ruleset, p, rule->targets, &my_error_msg);
|
||||
if (rc < 0) {
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
|
||||
target = strdup(p);
|
||||
if(target == NULL)
|
||||
return NULL;
|
||||
|
||||
is_negated = is_counting = 0;
|
||||
param = name = value = NULL;
|
||||
|
||||
opt = strchr(target,'!');
|
||||
opt = strchr(replace,'!');
|
||||
|
||||
if(opt != NULL) {
|
||||
*opt = '\0';
|
||||
opt++;
|
||||
param = opt;
|
||||
is_negated = 1;
|
||||
} else if ((opt = strchr(target,'&')) != NULL) {
|
||||
} else if ((opt = strchr(replace,'&')) != NULL) {
|
||||
*opt = '\0';
|
||||
opt++;
|
||||
param = opt;
|
||||
is_counting = 1;
|
||||
} else {
|
||||
param = target;
|
||||
param = replace;
|
||||
}
|
||||
|
||||
opt = strchr(param,':');
|
||||
|
@ -193,14 +183,33 @@ char *update_rule_target(cmd_parms *cmd, directory_config *dcfg,
|
|||
name = param;
|
||||
}
|
||||
|
||||
if(apr_table_get(ruleset->engine->variables, name) == NULL) {
|
||||
if(target_list != NULL)
|
||||
free(target_list);
|
||||
if(replace != NULL)
|
||||
free(replace);
|
||||
if(msr) {
|
||||
msr_log(msr, 9, "Error to update target - [%s] is not valid target", name);
|
||||
}
|
||||
return apr_psprintf(ruleset->mp, "Error to update target - [%s] is not valid target", name);
|
||||
}
|
||||
|
||||
name_len = strlen(name);
|
||||
|
||||
if(value != NULL)
|
||||
value_len = strlen(value);
|
||||
|
||||
match = 0;
|
||||
if(msr) {
|
||||
msr_log(msr, 9, "Trying to replace by variable name [%s] value [%s]", name, value);
|
||||
}
|
||||
#if !defined(MSC_TEST)
|
||||
else {
|
||||
ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL, " ModSecurity: Trying to replace by variable name [%s] value [%s]", name, value);
|
||||
}
|
||||
#endif
|
||||
|
||||
targets = (msre_var **)rule->targets->elts;
|
||||
// TODO need a good way to remove the element from array, maybe change array by tables or rings
|
||||
for (i = 0; i < rule->targets->nelts; i++) {
|
||||
if((strlen(targets[i]->name) == strlen(name)) &&
|
||||
(strncasecmp(targets[i]->name,name,strlen(targets[i]->name)) == 0) &&
|
||||
|
@ -209,48 +218,258 @@ char *update_rule_target(cmd_parms *cmd, directory_config *dcfg,
|
|||
|
||||
if(value != NULL && targets[i]->param != NULL) {
|
||||
if((strlen(targets[i]->param) == strlen(value)) &&
|
||||
strncasecmp(targets[i]->param,value,strlen(targets[i]->param)) == 0) {
|
||||
strncasecmp(targets[i]->param,value,strlen(targets[i]->param)) == 0) {
|
||||
memset(targets[i]->name,0,strlen(targets[i]->name));
|
||||
memset(targets[i]->param,0,strlen(targets[i]->param));
|
||||
match = 1;
|
||||
}
|
||||
} else if (value == NULL && targets[i]->param == NULL){
|
||||
memset(targets[i]->name,0,strlen(targets[i]->name));
|
||||
match = 1;
|
||||
} else
|
||||
continue;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(target != NULL) {
|
||||
free(target);
|
||||
target = NULL;
|
||||
}
|
||||
|
||||
|
||||
if(match == 0 ) {
|
||||
rc = msre_parse_targets(ruleset, p, rule->targets, &my_error_msg);
|
||||
if (rc < 0) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p = apr_strtok(NULL,",",&savedptr);
|
||||
p = apr_strtok(target_list, ",", &savedptr);
|
||||
|
||||
while(p != NULL) {
|
||||
if(replace != NULL) {
|
||||
if(match == 1) {
|
||||
rc = msre_parse_targets(ruleset, p, rule->targets, &my_error_msg);
|
||||
if (rc < 0) {
|
||||
if(msr) {
|
||||
msr_log(msr, 9, "Error parsing rule targets to replace variable");
|
||||
}
|
||||
#if !defined(MSC_TEST)
|
||||
else {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, " ModSecurity: Error parseing rule targets to replace variable");
|
||||
}
|
||||
#endif
|
||||
goto end;
|
||||
}
|
||||
if(msr) {
|
||||
msr_log(msr, 9, "Successfuly replaced variable");
|
||||
}
|
||||
#if !defined(MSC_TEST)
|
||||
else {
|
||||
ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL, " ModSecurity: Successfuly replaced variable");
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if(msr) {
|
||||
msr_log(msr, 9, "Cannot find variable to replace");
|
||||
}
|
||||
#if !defined(MSC_TEST)
|
||||
else {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, " ModSecurity: Cannot find varibale to replace");
|
||||
}
|
||||
#endif
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
|
||||
target = strdup(p);
|
||||
if(target == NULL)
|
||||
return NULL;
|
||||
|
||||
is_negated = is_counting = 0;
|
||||
param = name = value = NULL;
|
||||
|
||||
opt = strchr(target,'!');
|
||||
|
||||
if(opt != NULL) {
|
||||
*opt = '\0';
|
||||
opt++;
|
||||
param = opt;
|
||||
is_negated = 1;
|
||||
} else if ((opt = strchr(target,'&')) != NULL) {
|
||||
*opt = '\0';
|
||||
opt++;
|
||||
param = opt;
|
||||
is_counting = 1;
|
||||
} else {
|
||||
param = target;
|
||||
}
|
||||
|
||||
opt = strchr(param,':');
|
||||
|
||||
if(opt != NULL) {
|
||||
name = apr_strtok(param,":",&value);
|
||||
} else {
|
||||
name = param;
|
||||
}
|
||||
|
||||
if(apr_table_get(ruleset->engine->variables, name) == NULL) {
|
||||
if(target_list != NULL)
|
||||
free(target_list);
|
||||
if(replace != NULL)
|
||||
free(replace);
|
||||
if(msr) {
|
||||
msr_log(msr, 9, "Error to update target - [%s] is not valid target", name);
|
||||
}
|
||||
return apr_psprintf(ruleset->mp, "Error to update target - [%s] is not valid target", name);
|
||||
}
|
||||
|
||||
name_len = strlen(name);
|
||||
|
||||
if(value != NULL)
|
||||
value_len = strlen(value);
|
||||
|
||||
if(msr) {
|
||||
msr_log(msr, 9, "Trying to append variable name [%s] value [%s]", name, value);
|
||||
}
|
||||
#if !defined(MSC_TEST)
|
||||
else {
|
||||
ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL, " ModSecurity: Trying to append variable name [%s] value [%s]", name, value);
|
||||
}
|
||||
#endif
|
||||
match = 0;
|
||||
|
||||
targets = (msre_var **)rule->targets->elts;
|
||||
for (i = 0; i < rule->targets->nelts; i++) {
|
||||
if((strlen(targets[i]->name) == strlen(name)) &&
|
||||
(strncasecmp(targets[i]->name,name,strlen(targets[i]->name)) == 0) &&
|
||||
(targets[i]->is_negated == is_negated) &&
|
||||
(targets[i]->is_counting == is_counting)) {
|
||||
|
||||
if(value != NULL && targets[i]->param != NULL) {
|
||||
if((strlen(targets[i]->param) == strlen(value)) &&
|
||||
strncasecmp(targets[i]->param,value,strlen(targets[i]->param)) == 0) {
|
||||
match = 1;
|
||||
}
|
||||
} else if (value == NULL && targets[i]->param == NULL){
|
||||
match = 1;
|
||||
} else
|
||||
continue;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(target != NULL) {
|
||||
free(target);
|
||||
target = NULL;
|
||||
}
|
||||
|
||||
if(match == 0 ) {
|
||||
rc = msre_parse_targets(ruleset, p, rule->targets, &my_error_msg);
|
||||
if (rc < 0) {
|
||||
if(msr) {
|
||||
msr_log(msr, 9, "Error parsing rule targets to append variable");
|
||||
}
|
||||
#if !defined(MSC_TEST)
|
||||
else {
|
||||
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, " ModSecurity: Error parseing rule targets to append variable");
|
||||
}
|
||||
#endif
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if(msr) {
|
||||
msr_log(msr, 9, "Skipping variable, already appended");
|
||||
}
|
||||
#if !defined(MSC_TEST)
|
||||
else {
|
||||
ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL, " ModSecurity: Skipping variable, already appended");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
p = apr_strtok(NULL,",",&savedptr);
|
||||
}
|
||||
|
||||
if(match == 0) {
|
||||
current_targets = msre_generate_target_string(ruleset->mp, rule);
|
||||
rule->unparsed = msre_rule_generate_unparsed(ruleset->mp, rule, current_targets, NULL, NULL);
|
||||
if(msr) {
|
||||
msr_log(msr, 9, "Successfuly appended variable");
|
||||
}
|
||||
#if !defined(MSC_TEST)
|
||||
else {
|
||||
ap_log_error(APLOG_MARK, APLOG_INFO, 0, NULL, " ModSecurity: Successfuly appended variable");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
curr_targets = msre_generate_target_string(ruleset->mp, rule);
|
||||
|
||||
rule->unparsed = msre_rule_generate_unparsed(ruleset->mp, rule, curr_targets, NULL, NULL);
|
||||
|
||||
end:
|
||||
if(target_list != NULL)
|
||||
if(target_list != NULL) {
|
||||
free(target_list);
|
||||
if(replace != NULL)
|
||||
target_list = NULL;
|
||||
}
|
||||
if(replace != NULL) {
|
||||
free(replace);
|
||||
if(target != NULL)
|
||||
replace = NULL;
|
||||
}
|
||||
if(target != NULL) {
|
||||
free(target);
|
||||
target = NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int msre_ruleset_rule_matches_exception(msre_rule *rule, rule_exception *re) {
|
||||
int match = 0;
|
||||
|
||||
/* Only remove non-placeholder rules */
|
||||
if (rule->placeholder == RULE_PH_NONE) {
|
||||
switch(re->type) {
|
||||
case RULE_EXCEPTION_REMOVE_ID :
|
||||
if ((rule->actionset != NULL)&&(rule->actionset->id != NULL)) {
|
||||
int ruleid = atoi(rule->actionset->id);
|
||||
|
||||
if (rule_id_in_range(ruleid, re->param)) {
|
||||
match = 1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case RULE_EXCEPTION_REMOVE_MSG :
|
||||
if ((rule->actionset != NULL)&&(rule->actionset->msg != NULL)) {
|
||||
char *my_error_msg = NULL;
|
||||
|
||||
int rc = msc_regexec(re->param_data,
|
||||
rule->actionset->msg, strlen(rule->actionset->msg),
|
||||
&my_error_msg);
|
||||
if (rc >= 0) {
|
||||
match = 1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case RULE_EXCEPTION_REMOVE_TAG :
|
||||
if ((rule->actionset != NULL)&&(apr_is_empty_table(rule->actionset->actions) == 0)) {
|
||||
char *my_error_msg = NULL;
|
||||
const apr_array_header_t *tarr = NULL;
|
||||
const apr_table_entry_t *telts = NULL;
|
||||
int act;
|
||||
|
||||
tarr = apr_table_elts(rule->actionset->actions);
|
||||
telts = (const apr_table_entry_t*)tarr->elts;
|
||||
|
||||
for (act = 0; act < tarr->nelts; act++) {
|
||||
msre_action *action = (msre_action *)telts[act].val;
|
||||
if((action != NULL) && (action->metadata != NULL) && (strcmp("tag", action->metadata->name) == 0)) {
|
||||
|
||||
int rc = msc_regexec(re->param_data,
|
||||
action->param, strlen(action->param),
|
||||
&my_error_msg);
|
||||
if (rc >= 0) {
|
||||
match = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Remove actions with the same cardinality group from the actionset.
|
||||
|
@ -824,7 +1043,7 @@ msre_actionset *msre_actionset_create(msre_engine *engine, const char *text,
|
|||
actionset->intercept_action = NOT_SET;
|
||||
actionset->intercept_uri = NOT_SET_P;
|
||||
actionset->intercept_status = NOT_SET;
|
||||
actionset->intercept_pause = NOT_SET;
|
||||
actionset->intercept_pause = NOT_SET_P;
|
||||
|
||||
/* Other */
|
||||
actionset->auditlog = NOT_SET;
|
||||
|
@ -907,7 +1126,7 @@ msre_actionset *msre_actionset_merge(msre_engine *engine, msre_actionset *parent
|
|||
}
|
||||
|
||||
if (child->intercept_status != NOT_SET) merged->intercept_status = child->intercept_status;
|
||||
if (child->intercept_pause != NOT_SET) merged->intercept_pause = child->intercept_pause;
|
||||
if (child->intercept_pause != NOT_SET_P) merged->intercept_pause = child->intercept_pause;
|
||||
|
||||
/* Other */
|
||||
if (child->auditlog != NOT_SET) merged->auditlog = child->auditlog;
|
||||
|
@ -962,7 +1181,7 @@ void msre_actionset_set_defaults(msre_actionset *actionset) {
|
|||
if (actionset->intercept_action == NOT_SET) actionset->intercept_action = ACTION_NONE;
|
||||
if (actionset->intercept_uri == NOT_SET_P) actionset->intercept_uri = NULL;
|
||||
if (actionset->intercept_status == NOT_SET) actionset->intercept_status = 403;
|
||||
if (actionset->intercept_pause == NOT_SET) actionset->intercept_pause = 0;
|
||||
if (actionset->intercept_pause == NOT_SET_P) actionset->intercept_pause = NULL;
|
||||
|
||||
/* Other */
|
||||
if (actionset->auditlog == NOT_SET) actionset->auditlog = 1;
|
||||
|
@ -1222,13 +1441,35 @@ static apr_status_t msre_ruleset_process_phase_(msre_ruleset *ruleset, modsec_re
|
|||
}
|
||||
|
||||
/* Check if this rule was removed at runtime */
|
||||
if (((rule->actionset->id !=NULL) && !apr_is_empty_array(msr->removed_rules)) || (apr_is_empty_array(msr->removed_rules_tag)==0)) {
|
||||
int j, act;
|
||||
if (((rule->actionset->id !=NULL) && !apr_is_empty_array(msr->removed_rules)) ||
|
||||
(apr_is_empty_array(msr->removed_rules_tag)==0) || (apr_is_empty_array(msr->removed_rules_msg)==0)) {
|
||||
int j, act, rc;
|
||||
int do_process = 1;
|
||||
const char *range;
|
||||
const char *range = NULL;
|
||||
rule_exception *re = NULL;
|
||||
char *my_error_msg, *error_msg;
|
||||
const apr_array_header_t *tag_tarr = NULL;
|
||||
const apr_table_entry_t *tag_telts = NULL;
|
||||
|
||||
for(j = 0; j < msr->removed_rules_msg->nelts; j++) {
|
||||
re = ((rule_exception **)msr->removed_rules_msg->elts)[j];
|
||||
|
||||
if(rule->actionset->msg !=NULL) {
|
||||
|
||||
if (msr->txcfg->debuglog_level >= 9) {
|
||||
msr_log(msr, 9, "Checking removal of rule msg=\"%s\" against: %s", rule->actionset->msg, re->param);
|
||||
}
|
||||
|
||||
rc = msc_regexec(re->param_data,
|
||||
rule->actionset->msg, strlen(rule->actionset->msg),
|
||||
&my_error_msg);
|
||||
if (rc >= 0) {
|
||||
do_process = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(j = 0; j < msr->removed_rules->nelts; j++) {
|
||||
range = ((const char**)msr->removed_rules->elts)[j];
|
||||
|
||||
|
@ -1254,7 +1495,7 @@ static apr_status_t msre_ruleset_process_phase_(msre_ruleset *ruleset, modsec_re
|
|||
if((action != NULL) && (action->metadata != NULL ) && strcmp("tag", action->metadata->name) == 0) {
|
||||
|
||||
for(j = 0; j < msr->removed_rules_tag->nelts; j++) {
|
||||
range = ((const char**)msr->removed_rules_tag->elts)[j];
|
||||
re = ((rule_exception **)msr->removed_rules_tag->elts)[j];
|
||||
|
||||
|
||||
if(action->param != NULL) {
|
||||
|
@ -1266,13 +1507,17 @@ static apr_status_t msre_ruleset_process_phase_(msre_ruleset *ruleset, modsec_re
|
|||
expand_macros(msr, var, NULL, msr->mp);
|
||||
|
||||
if (msr->txcfg->debuglog_level >= 9) {
|
||||
msr_log(msr, 9, "Checking removal of rule tag=\"%s\" against: %s", var->value, range);
|
||||
msr_log(msr, 9, "Checking removal of rule tag=\"%s\" against: %s", var->value, re->param);
|
||||
}
|
||||
|
||||
if (strncasecmp(var->value, range, strlen(range)) == 0) {
|
||||
rc = msc_regexec(re->param_data,
|
||||
var->value, strlen(var->value),
|
||||
&my_error_msg);
|
||||
if (rc >= 0) {
|
||||
do_process = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1785,8 +2030,9 @@ char *msre_format_metadata(modsec_rec *msr, msre_actionset *actionset) {
|
|||
var->value_len = strlen(actionset->logdata);
|
||||
expand_macros(msr, var, NULL, msr->mp);
|
||||
|
||||
logdata = apr_psprintf(msr->mp, " [data \"%s\"]",
|
||||
logdata = apr_psprintf(msr->mp, " [data \"%s",
|
||||
log_escape_hex(msr->mp, (unsigned char *)var->value, var->value_len));
|
||||
logdata = apr_pstrcat(msr->mp, logdata, "\"]", NULL);
|
||||
|
||||
/* If it is > 512 bytes, then truncate at 512 with ellipsis.
|
||||
* NOTE: 512 actual data + 9 bytes of label = 521
|
||||
|
@ -1892,7 +2138,7 @@ msre_rule *msre_rule_create(msre_ruleset *ruleset, int type,
|
|||
msre_rule *rule;
|
||||
char *my_error_msg;
|
||||
const char *argsp;
|
||||
int rc;
|
||||
int rc, idx;
|
||||
|
||||
if (error_msg == NULL) return NULL;
|
||||
*error_msg = NULL;
|
||||
|
@ -2125,7 +2371,6 @@ static int execute_operator(msre_var *var, msre_rule *rule, modsec_rec *msr,
|
|||
apr_time_t time_before_op = 0;
|
||||
char *my_error_msg = NULL;
|
||||
const char *full_varname = NULL;
|
||||
char *parm = NULL;
|
||||
int rc;
|
||||
|
||||
/* determine the full var name if not already resolved
|
||||
|
@ -2161,7 +2406,7 @@ static int execute_operator(msre_var *var, msre_rule *rule, modsec_rec *msr,
|
|||
#if defined(PERFORMANCE_MEASUREMENT)
|
||||
time_before_op = apr_time_now();
|
||||
#else
|
||||
if (msr->txcfg->debuglog_level >= 4) {
|
||||
if (msr->txcfg->debuglog_level >= 4 || msr->txcfg->max_rule_time > 0) {
|
||||
time_before_op = apr_time_now();
|
||||
}
|
||||
#endif
|
||||
|
@ -2179,7 +2424,26 @@ static int execute_operator(msre_var *var, msre_rule *rule, modsec_rec *msr,
|
|||
apr_time_t t1 = apr_time_now();
|
||||
msr_log(msr, 4, "Operator completed in %" APR_TIME_T_FMT " usec.", (t1 - time_before_op));
|
||||
}
|
||||
#endif
|
||||
|
||||
if(msr->txcfg->max_rule_time > 0) {
|
||||
apr_time_t t1 = apr_time_now();
|
||||
apr_time_t rule_time = 0;
|
||||
const char *rt_time = NULL;
|
||||
|
||||
if(rule->actionset->id != NULL) {
|
||||
rt_time = apr_table_get(msr->perf_rules, rule->actionset->id);
|
||||
if(rt_time == NULL) {
|
||||
rt_time = apr_psprintf(msr->mp, "%" APR_TIME_T_FMT, (t1 - time_before_op));
|
||||
apr_table_setn(msr->perf_rules, rule->actionset->id, rt_time);
|
||||
} else {
|
||||
rule_time = (apr_time_t)atoi(rt_time);
|
||||
rule_time += (t1 - time_before_op);
|
||||
rt_time = apr_psprintf(msr->mp, "%" APR_TIME_T_FMT, rule_time);
|
||||
apr_table_setn(msr->perf_rules, rule->actionset->id, rt_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rc < 0) {
|
||||
msr_log(msr, 4, "Operator error: %s", my_error_msg);
|
||||
|
@ -2211,36 +2475,20 @@ static int execute_operator(msre_var *var, msre_rule *rule, modsec_rec *msr,
|
|||
|
||||
/* Save the last matched var data */
|
||||
if(var != NULL && msr != NULL) {
|
||||
msc_string *mvar = NULL;
|
||||
|
||||
msr->matched_var->name = apr_pstrdup(msr->mp, var->name);
|
||||
msr->matched_var->name_len = strlen(msr->matched_var->name);
|
||||
msr->matched_var->value = apr_pmemdup(msr->mp, var->value, var->value_len);
|
||||
msr->matched_var->value_len = var->value_len;
|
||||
|
||||
parm = strchr(msr->matched_var->name,':');
|
||||
mvar = apr_palloc(msr->mp, sizeof(msc_string));
|
||||
mvar->name = apr_pstrdup(msr->mp, var->name);
|
||||
mvar->name_len = strlen(mvar->name);
|
||||
mvar->value = apr_pmemdup(msr->mp, var->value, var->value_len);
|
||||
mvar->value_len = var->value_len;
|
||||
|
||||
if(parm) {
|
||||
msc_string *mvar = NULL;
|
||||
|
||||
parm++;
|
||||
|
||||
mvar = apr_palloc(msr->mp, sizeof(msc_string));
|
||||
mvar->name = apr_pstrdup(msr->mp, parm);
|
||||
mvar->name_len = strlen(mvar->name);
|
||||
mvar->value = apr_pmemdup(msr->mp, var->value, var->value_len);
|
||||
mvar->value_len = var->value_len;
|
||||
|
||||
apr_table_addn(msr->matched_vars, parm, (void *)mvar);
|
||||
|
||||
} else {
|
||||
|
||||
msc_string *mvar = apr_palloc(msr->mp, sizeof(msc_string));
|
||||
mvar->name = apr_pstrdup(msr->mp, var->name);
|
||||
mvar->name_len = strlen(mvar->name);
|
||||
mvar->value = apr_pmemdup(msr->mp, var->value, var->value_len);
|
||||
mvar->value_len = var->value_len;
|
||||
|
||||
apr_table_addn(msr->matched_vars, mvar->name, (void *)mvar);
|
||||
}
|
||||
apr_table_addn(msr->matched_vars, mvar->name, (void *)mvar);
|
||||
|
||||
}
|
||||
|
||||
|
|
13
apache2/re.h
13
apache2/re.h
|
@ -47,7 +47,16 @@ typedef struct msre_cache_rec msre_cache_rec;
|
|||
#endif
|
||||
|
||||
/* Actions, variables, functions and operator functions */
|
||||
char DSOLOCAL *update_rule_target(cmd_parms *cmd, directory_config *dcfg, msre_ruleset *rset, const char *p1, const char *p2, const char *p3);
|
||||
char DSOLOCAL *update_rule_target_ex(modsec_rec *msr, msre_ruleset *ruleset, msre_rule *rule, const char *p2,
|
||||
const char *p3);
|
||||
|
||||
int DSOLOCAL msre_ruleset_rule_matches_exception(msre_rule *rule, rule_exception *re);
|
||||
|
||||
char DSOLOCAL *msre_ruleset_rule_update_target_matching_exception(modsec_rec *msr, msre_ruleset *ruleset, rule_exception *re,
|
||||
const char *p2, const char *p3);
|
||||
|
||||
char DSOLOCAL *msre_ruleset_phase_rule_update_target_matching_exception(modsec_rec *msr, msre_ruleset *ruleset, rule_exception *re,
|
||||
apr_array_header_t *phase_arr, const char *p2, const char *p3);
|
||||
|
||||
apr_status_t DSOLOCAL collection_original_setvar(modsec_rec *msr, const char *col_name, const msc_string *orig_var);
|
||||
|
||||
|
@ -295,7 +304,7 @@ struct msre_actionset {
|
|||
int intercept_action;
|
||||
const char *intercept_uri;
|
||||
int intercept_status;
|
||||
int intercept_pause;
|
||||
const char *intercept_pause;
|
||||
|
||||
/* "block" needs parent action to reset it */
|
||||
msre_action *parent_intercept_action_rec;
|
||||
|
|
|
@ -370,6 +370,14 @@ apr_status_t collection_original_setvar(modsec_rec *msr, const char *col_name, c
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* marker */
|
||||
static apr_status_t msre_action_marker_init(msre_engine *engine, msre_actionset *actionset,
|
||||
msre_action *action)
|
||||
{
|
||||
actionset->id = action->param;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* id */
|
||||
|
||||
static apr_status_t msre_action_id_init(msre_engine *engine, msre_actionset *actionset,
|
||||
|
@ -379,10 +387,27 @@ static apr_status_t msre_action_id_init(msre_engine *engine, msre_actionset *act
|
|||
return 1;
|
||||
}
|
||||
|
||||
static char *msre_action_id_validate(msre_engine *engine, msre_action *action) {
|
||||
int id;
|
||||
|
||||
if(action != NULL && action->param != NULL) {
|
||||
for(id=0;id<strlen(action->param);id++) {
|
||||
if(!apr_isdigit(action->param[id]))
|
||||
return apr_psprintf(engine->mp, "ModSecurity: Invalid value for action ID: %s", action->param);
|
||||
}
|
||||
id = atoi(action->param);
|
||||
if ((id == LONG_MAX)||(id == LONG_MIN)||(id <= 0)) {
|
||||
return apr_psprintf(engine->mp, "ModSecurity: Invalid value for action ID: %s", action->param);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* rev */
|
||||
|
||||
static apr_status_t msre_action_rev_init(msre_engine *engine, msre_actionset *actionset,
|
||||
msre_action *action)
|
||||
msre_action *action)
|
||||
{
|
||||
actionset->rev = action->param;
|
||||
return 1;
|
||||
|
@ -534,7 +559,7 @@ static char *msre_action_pause_validate(msre_engine *engine, msre_action *action
|
|||
static apr_status_t msre_action_pause_init(msre_engine *engine, msre_actionset *actionset,
|
||||
msre_action *action)
|
||||
{
|
||||
actionset->intercept_pause = atoi(action->param);
|
||||
actionset->intercept_pause = action->param;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -686,7 +711,15 @@ static char *msre_action_phase_validate(msre_engine *engine, msre_action *action
|
|||
static apr_status_t msre_action_phase_init(msre_engine *engine, msre_actionset *actionset,
|
||||
msre_action *action)
|
||||
{
|
||||
actionset->phase = atoi(action->param);
|
||||
if(strcasecmp(action->param,"request") == 0)
|
||||
actionset->phase = 2;
|
||||
else if(strcasecmp(action->param,"response") == 0)
|
||||
actionset->phase = 4;
|
||||
else if(strcasecmp(action->param,"logging") == 0)
|
||||
actionset->phase = 5;
|
||||
else
|
||||
actionset->phase = atoi(action->param);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -734,7 +767,13 @@ static char *msre_action_ctl_validate(msre_engine *engine, msre_action *action)
|
|||
return NULL;
|
||||
} else
|
||||
if (strcasecmp(name, "ruleRemoveByTag") == 0) {
|
||||
/* ENH nothing yet */
|
||||
if (!msc_pregcomp(engine->mp, value, 0, NULL, NULL))
|
||||
return apr_psprintf(engine->mp, "ModSecurity: Invalid regular expression \"%s\"", value);
|
||||
return NULL;
|
||||
} else
|
||||
if (strcasecmp(name, "ruleRemoveByMsg") == 0) {
|
||||
if (!msc_pregcomp(engine->mp, value, 0, NULL, NULL))
|
||||
return apr_psprintf(engine->mp, "ModSecurity: Invalid regular expression \"%s\"", value);
|
||||
return NULL;
|
||||
} else
|
||||
if (strcasecmp(name, "requestBodyAccess") == 0) {
|
||||
|
@ -828,11 +867,44 @@ static char *msre_action_ctl_validate(msre_engine *engine, msre_action *action)
|
|||
if(parm == NULL && savedptr == NULL)
|
||||
return apr_psprintf(engine->mp, "ruleUpdateTargetById must has at least id;append_value");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
} else
|
||||
if (strcasecmp(name,"ruleUpdateTargetByTag") == 0) {
|
||||
char *parm = NULL;
|
||||
char *savedptr = NULL;
|
||||
|
||||
parm = apr_strtok(value,";",&savedptr);
|
||||
if(parm == NULL && savedptr == NULL)
|
||||
return apr_psprintf(engine->mp, "ruleUpdateTargetByTag must has at least tag;append_value");
|
||||
if (!msc_pregcomp(engine->mp, parm, 0, NULL, NULL)) {
|
||||
return apr_psprintf(engine->mp, "ModSecurity: Invalid regular expression \"%s\"", parm);
|
||||
}
|
||||
return NULL;
|
||||
} else
|
||||
if (strcasecmp(name,"ruleUpdateTargetByMsg") == 0) {
|
||||
char *parm = NULL;
|
||||
char *savedptr = NULL;
|
||||
|
||||
parm = apr_strtok(value,";",&savedptr);
|
||||
if(parm == NULL && savedptr == NULL)
|
||||
return apr_psprintf(engine->mp, "ruleUpdateTargetByMsg must has at least msg;append_value");
|
||||
if (!msc_pregcomp(engine->mp, parm, 0, NULL, NULL)) {
|
||||
return apr_psprintf(engine->mp, "ModSecurity: Invalid regular expression \"%s\"", parm);
|
||||
}
|
||||
return NULL;
|
||||
} else
|
||||
if (strcasecmp(name, "EncryptionEnforcement") == 0) {
|
||||
if (strcasecmp(value, "on") == 0) return NULL;
|
||||
if (strcasecmp(value, "off") == 0) return NULL;
|
||||
return apr_psprintf(engine->mp, "Invalid setting for ctl name EncryptionEnforcement: %s", value);
|
||||
} else
|
||||
if (strcasecmp(name, "EncryptionEngine") == 0) {
|
||||
if (strcasecmp(value, "on") == 0) return NULL;
|
||||
if (strcasecmp(value, "off") == 0) return NULL;
|
||||
return apr_psprintf(engine->mp, "Invalid setting for ctl name EncryptionEngine: %s", value);
|
||||
} else {
|
||||
return apr_psprintf(engine->mp, "Invalid ctl name setting: %s", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static apr_status_t msre_action_ctl_init(msre_engine *engine, msre_actionset *actionset,
|
||||
|
@ -879,17 +951,51 @@ static apr_status_t msre_action_ctl_execute(modsec_rec *msr, apr_pool_t *mptmp,
|
|||
|
||||
return 1;
|
||||
} else
|
||||
if (strcasecmp(name, "EncryptionEnforcement") == 0) {
|
||||
if (strcasecmp(value, "on") == 0) {
|
||||
msr->txcfg->encryption_enforcement = ENCRYPTION_ENABLED;
|
||||
msr->usercfg->encryption_enforcement = ENCRYPTION_ENABLED;
|
||||
}
|
||||
if (strcasecmp(value, "off") == 0) {
|
||||
msr->txcfg->encryption_enforcement = ENCRYPTION_DISABLED;
|
||||
msr->usercfg->encryption_enforcement = ENCRYPTION_DISABLED;
|
||||
}
|
||||
if (msr->txcfg->debuglog_level >= 4) {
|
||||
msr_log(msr, 4, "Ctl: Set EncryptionEnforcement to %s.", value);
|
||||
}
|
||||
} else
|
||||
if (strcasecmp(name, "EncryptionEngine") == 0) {
|
||||
if (strcasecmp(value, "on") == 0) {
|
||||
msr->txcfg->encryption_is_enabled = ENCRYPTION_ENABLED;
|
||||
msr->usercfg->encryption_is_enabled = ENCRYPTION_ENABLED;
|
||||
}
|
||||
if (strcasecmp(value, "off") == 0) {
|
||||
msr->txcfg->encryption_is_enabled = ENCRYPTION_DISABLED;
|
||||
msr->usercfg->encryption_is_enabled = ENCRYPTION_DISABLED;
|
||||
}
|
||||
if (msr->txcfg->debuglog_level >= 4) {
|
||||
msr_log(msr, 4, "Ctl: Set EncryptionEngine to %s.", value);
|
||||
}
|
||||
} else
|
||||
if (strcasecmp(name, "ruleRemoveById") == 0) {
|
||||
*(const char **)apr_array_push(msr->removed_rules) = (const char *)apr_pstrdup(msr->mp, value);
|
||||
|
||||
if (msr->txcfg->debuglog_level >= 4) {
|
||||
msr_log(msr, 4, "Ctl: Removed rule by id : %s.", value);
|
||||
}
|
||||
|
||||
return 1;
|
||||
} else
|
||||
if (strcasecmp(name, "ruleRemoveByTag") == 0) {
|
||||
*(const char **)apr_array_push(msr->removed_rules_tag) = (const char *)apr_pstrdup(msr->mp, value);
|
||||
rule_exception *re = apr_pcalloc(mptmp, sizeof(rule_exception));
|
||||
re->type = RULE_EXCEPTION_REMOVE_TAG;
|
||||
re->param = (const char *)apr_pstrdup(msr->mp, value);;
|
||||
re->param_data = msc_pregcomp(msr->mp, re->param, 0, NULL, NULL);
|
||||
if (re->param_data == NULL) {
|
||||
msr_log(msr, 1, "ModSecurity: Invalid regular expression \"%s\"", re->param);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*(rule_exception **)apr_array_push(msr->removed_rules_tag) = re;
|
||||
|
||||
if (msr->txcfg->debuglog_level >= 4) {
|
||||
msr_log(msr, 4, "Ctl: Removed rule by tag : %s.", value);
|
||||
|
@ -897,6 +1003,24 @@ static apr_status_t msre_action_ctl_execute(modsec_rec *msr, apr_pool_t *mptmp,
|
|||
|
||||
return 1;
|
||||
} else
|
||||
if (strcasecmp(name, "ruleRemoveByMsg") == 0) {
|
||||
rule_exception *re = apr_pcalloc(mptmp, sizeof(rule_exception));
|
||||
re->type = RULE_EXCEPTION_REMOVE_MSG;
|
||||
re->param = (const char *)apr_pstrdup(msr->mp, value);;
|
||||
re->param_data = msc_pregcomp(msr->mp, re->param, 0, NULL, NULL);
|
||||
if (re->param_data == NULL) {
|
||||
msr_log(msr, 1, "ModSecurity: Invalid regular expression \"%s\"", re->param);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*(rule_exception **)apr_array_push(msr->removed_rules_msg) = re;
|
||||
|
||||
if (msr->txcfg->debuglog_level >= 4) {
|
||||
msr_log(msr, 4, "Ctl: Removed rule by msg : %s.", value);
|
||||
}
|
||||
|
||||
return 1;
|
||||
} else
|
||||
if (strcasecmp(name, "requestBodyAccess") == 0) {
|
||||
int pv = parse_boolean(value);
|
||||
|
||||
|
@ -1047,6 +1171,7 @@ static apr_status_t msre_action_ctl_execute(modsec_rec *msr, apr_pool_t *mptmp,
|
|||
return 1;
|
||||
} else
|
||||
if (strcasecmp(name, "ruleUpdateTargetById") == 0) {
|
||||
rule_exception *re = NULL;
|
||||
char *p1 = NULL, *p2 = NULL, *p3 = NULL;
|
||||
char *savedptr = NULL;
|
||||
|
||||
|
@ -1059,10 +1184,63 @@ static apr_status_t msre_action_ctl_execute(modsec_rec *msr, apr_pool_t *mptmp,
|
|||
if (msr->txcfg->debuglog_level >= 4) {
|
||||
msr_log(msr, 4, "Ctl: ruleUpdateTargetById id=%s append=%s replace=%s", p1, p2, p3);
|
||||
}
|
||||
re = apr_pcalloc(mptmp, sizeof(rule_exception));
|
||||
re->type = RULE_EXCEPTION_REMOVE_ID;
|
||||
re->param = p1;
|
||||
msre_ruleset_rule_update_target_matching_exception(msr, rule->ruleset, re, p2, p3);
|
||||
return 1;
|
||||
} else
|
||||
if (strcasecmp(name, "ruleUpdateTargetByTag") == 0) {
|
||||
rule_exception *re = NULL;
|
||||
char *p1 = NULL, *p2 = NULL, *p3 = NULL;
|
||||
char *savedptr = NULL;
|
||||
|
||||
update_rule_target(NULL, NULL, rule->ruleset, p1, p2, p3);
|
||||
p1 = apr_strtok(value,";",&savedptr);
|
||||
|
||||
return 1;
|
||||
p2 = apr_strtok(NULL,";",&savedptr);
|
||||
|
||||
p3 = apr_strtok(NULL,";",&savedptr);
|
||||
|
||||
if (msr->txcfg->debuglog_level >= 4) {
|
||||
msr_log(msr, 4, "Ctl: ruleUpdateTargetByTag tag=%s append=%s replace=%s", p1, p2, p3);
|
||||
}
|
||||
|
||||
re = apr_pcalloc(mptmp, sizeof(rule_exception));
|
||||
re->type = RULE_EXCEPTION_REMOVE_TAG;
|
||||
re->param = p1;
|
||||
re->param_data = msc_pregcomp(mptmp, p1, 0, NULL, NULL);
|
||||
if (re->param_data == NULL) {
|
||||
msr_log(msr, 1, "ModSecurity: Invalid regular expression \"%s\"", p1);
|
||||
return -1;
|
||||
}
|
||||
msre_ruleset_rule_update_target_matching_exception(msr, rule->ruleset, re, p2, p3);
|
||||
return 1;
|
||||
} else
|
||||
if (strcasecmp(name, "ruleUpdateTargetByMsg") == 0) {
|
||||
rule_exception *re = NULL;
|
||||
char *p1 = NULL, *p2 = NULL, *p3 = NULL;
|
||||
char *savedptr = NULL;
|
||||
|
||||
p1 = apr_strtok(value,";",&savedptr);
|
||||
|
||||
p2 = apr_strtok(NULL,";",&savedptr);
|
||||
|
||||
p3 = apr_strtok(NULL,";",&savedptr);
|
||||
|
||||
if (msr->txcfg->debuglog_level >= 4) {
|
||||
msr_log(msr, 4, "Ctl: ruleUpdateTargetByMsg tag=%s append=%s replace=%s", p1, p2, p3);
|
||||
}
|
||||
|
||||
re = apr_pcalloc(mptmp, sizeof(rule_exception));
|
||||
re->type = RULE_EXCEPTION_REMOVE_MSG;
|
||||
re->param = p1;
|
||||
re->param_data = msc_pregcomp(mptmp, p1, 0, NULL, NULL);
|
||||
if (re->param_data == NULL) {
|
||||
msr_log(msr, 1, "ModSecurity: Invalid regular expression \"%s\"", p1);
|
||||
return -1;
|
||||
}
|
||||
msre_ruleset_rule_update_target_matching_exception(msr, rule->ruleset, re, p2, p3);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
/* Should never happen, but log if it does. */
|
||||
|
@ -1855,7 +2033,7 @@ static apr_status_t msre_action_initcol_execute(modsec_rec *msr, apr_pool_t *mpt
|
|||
/* IMP1 We have a function for this now, parse_name_eq_value? */
|
||||
s = strstr(data, "=");
|
||||
if (s == NULL) return 0;
|
||||
col_name = strtolower_inplace(data);
|
||||
col_name = strtolower_inplace((unsigned char *)data);
|
||||
col_key = s + 1;
|
||||
*s = '\0';
|
||||
|
||||
|
@ -1919,6 +2097,29 @@ static apr_status_t msre_action_setuid_execute(modsec_rec *msr, apr_pool_t *mptm
|
|||
return init_collection(msr, real_col_name, "USER", col_key, col_key_len);
|
||||
}
|
||||
|
||||
/* setrsc */
|
||||
static apr_status_t msre_action_setrsc_execute(modsec_rec *msr, apr_pool_t *mptmp,
|
||||
msre_rule *rule, msre_action *action)
|
||||
{
|
||||
msc_string *var = NULL;
|
||||
char *real_col_name = NULL, *col_key = NULL;
|
||||
unsigned int col_key_len;
|
||||
|
||||
/* Construct user ID. */
|
||||
var = apr_pcalloc(mptmp, sizeof(msc_string));
|
||||
var->value = (char *)action->param;
|
||||
var->value_len = strlen(var->value);
|
||||
expand_macros(msr, var, rule, mptmp);
|
||||
|
||||
/* Construct collection name. */
|
||||
col_key = var->value;
|
||||
col_key_len = var->value_len;
|
||||
real_col_name = apr_psprintf(mptmp, "%s_RESOURCE", msr->txcfg->webappid);
|
||||
|
||||
/* Initialise collection. */
|
||||
return init_collection(msr, real_col_name, "RESOURCE", col_key, col_key_len);
|
||||
}
|
||||
|
||||
/* exec */
|
||||
static char *msre_action_exec_validate(msre_engine *engine, msre_action *action) {
|
||||
#if defined(WITH_LUA)
|
||||
|
@ -2027,11 +2228,24 @@ void msre_engine_register_default_actions(msre_engine *engine) {
|
|||
NO_PLUS_MINUS,
|
||||
ACTION_CARDINALITY_ONE,
|
||||
ACTION_CGROUP_NONE,
|
||||
NULL,
|
||||
msre_action_id_validate,
|
||||
msre_action_id_init,
|
||||
NULL
|
||||
);
|
||||
|
||||
/* marker */
|
||||
msre_engine_action_register(engine,
|
||||
"marker",
|
||||
ACTION_METADATA,
|
||||
1, 1,
|
||||
NO_PLUS_MINUS,
|
||||
ACTION_CARDINALITY_ONE,
|
||||
ACTION_CGROUP_NONE,
|
||||
NULL,
|
||||
msre_action_marker_init,
|
||||
NULL
|
||||
);
|
||||
|
||||
/* rev */
|
||||
msre_engine_action_register(engine,
|
||||
"rev",
|
||||
|
@ -2566,6 +2780,19 @@ void msre_engine_register_default_actions(msre_engine *engine) {
|
|||
msre_action_setsid_execute
|
||||
);
|
||||
|
||||
/* setuid */
|
||||
msre_engine_action_register(engine,
|
||||
"setrsc",
|
||||
ACTION_NON_DISRUPTIVE,
|
||||
1, 1,
|
||||
NO_PLUS_MINUS,
|
||||
ACTION_CARDINALITY_ONE,
|
||||
ACTION_CGROUP_NONE,
|
||||
NULL,
|
||||
NULL,
|
||||
msre_action_setrsc_execute
|
||||
);
|
||||
|
||||
/* setuid */
|
||||
msre_engine_action_register(engine,
|
||||
"setuid",
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -24,6 +24,18 @@
|
|||
|
||||
/* cmdline */
|
||||
|
||||
/**
|
||||
* \brief cmdline transformation function
|
||||
*
|
||||
* \param mptmp Pointer to resource pool
|
||||
* \param input Pointer to input data
|
||||
* \param input_len Input data length
|
||||
* \param rval Pointer to decoded buffer
|
||||
* \param rval_len Decoded buffer length
|
||||
*
|
||||
* \retval 0 On failure
|
||||
* \retval 1 On Success
|
||||
*/
|
||||
static int msre_fn_cmdline_execute(apr_pool_t *mptmp, unsigned char *input,
|
||||
long int input_len, char **rval, long int *rval_len)
|
||||
{
|
||||
|
@ -302,6 +314,15 @@ static int msre_fn_removeCommentsChar_execute(apr_pool_t *mptmp, unsigned char *
|
|||
} else if ((input[i] == '*')&&(i + 1 < input_len)&&(input[i + 1] == '/')) {
|
||||
changed = 1;
|
||||
i += 2;
|
||||
} else if ((input[i] == '<')&&(i + 1 < input_len)&&(input[i + 1] == '!')&&
|
||||
(i + 2 < input_len)&&(input[i+2] == '-')&&(i + 3 < input_len)&&
|
||||
(input[i + 3] == '-')) {
|
||||
changed = 1;
|
||||
i += 4;
|
||||
} else if ((input[i] == '-')&&(i + 1 < input_len)&&(input[i + 1] == '-')&&
|
||||
(i + 2 < input_len)&&(input[i+2] == '>')) {
|
||||
changed = 1;
|
||||
i += 3;
|
||||
} else if ((input[i] == '-')&&(i + 1 < input_len)&&(input[i + 1] == '-')) {
|
||||
changed = 1;
|
||||
i += 2;
|
||||
|
@ -337,16 +358,21 @@ static int msre_fn_removeComments_execute(apr_pool_t *mptmp, unsigned char *inpu
|
|||
changed = 1;
|
||||
incomment = 1;
|
||||
i += 2;
|
||||
} else if ((input[i] == '-')&&(i + 1 < input_len)&&(input[i + 1] == '-')) {
|
||||
} else if ((input[i] == '<')&&(i + 1 < input_len)&&(input[i + 1] == '!')&&
|
||||
(i + 2 < input_len)&&(input[i+2] == '-')&&(i + 3 < input_len)&&
|
||||
(input[i + 3] == '-') && (incomment == 0)) {
|
||||
incomment = 1;
|
||||
changed = 1;
|
||||
i += 4;
|
||||
} else if ((input[i] == '-')&&(i + 1 < input_len)&&(input[i + 1] == '-')
|
||||
&& (incomment == 0)) {
|
||||
changed = 1;
|
||||
input[i] = ' ';
|
||||
break;
|
||||
i += 2;
|
||||
} else if (input[i] == '#') {
|
||||
} else if (input[i] == '#' && (incomment == 0)) {
|
||||
changed = 1;
|
||||
input[i] = ' ';
|
||||
break;
|
||||
i++;
|
||||
} else {
|
||||
input[j] = input[i];
|
||||
i++;
|
||||
|
@ -359,6 +385,13 @@ static int msre_fn_removeComments_execute(apr_pool_t *mptmp, unsigned char *inpu
|
|||
input[j] = input[i];
|
||||
i++;
|
||||
j++;
|
||||
} else if ((input[i] == '-')&&(i + 1 < input_len)&&(input[i + 1] == '-')&&
|
||||
(i + 2 < input_len)&&(input[i+2] == '>')) {
|
||||
incomment = 0;
|
||||
i += 3;
|
||||
input[j] = input[i];
|
||||
i++;
|
||||
j++;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
|
@ -544,8 +577,18 @@ static int msre_fn_sha1_execute(apr_pool_t *mptmp, unsigned char *input,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* sqlHexDecode */
|
||||
|
||||
/**
|
||||
* \brief SqlHexDecode transformation function. Transform xNN data.
|
||||
*
|
||||
* \param mptmp Pointer to resource pool
|
||||
* \param input Pointer to input data
|
||||
* \param input_len Input data length
|
||||
* \param rval Pointer to decoded buffer
|
||||
* \param rval_len Decoded buffer length
|
||||
*
|
||||
* \retval 0 On failure
|
||||
* \retval 1 On Success
|
||||
*/
|
||||
static int msre_fn_sqlHexDecode_execute(apr_pool_t *mptmp, unsigned char *input,
|
||||
long int input_len, char **rval, long int *rval_len)
|
||||
{
|
||||
|
@ -720,10 +763,10 @@ static int msre_fn_parityOdd7bit_execute(apr_pool_t *mptmp, unsigned char *input
|
|||
return changed;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* \brief Base64 transformation function based on RFC2045
|
||||
*
|
||||
* \param mptmp Pointer to resource poil
|
||||
* \param mptmp Pointer to resource pool
|
||||
* \param input Pointer to input data
|
||||
* \param input_len Input data length
|
||||
* \param rval Pointer to decoded buffer
|
||||
|
|
|
@ -675,6 +675,14 @@ static int var_webserver_error_log_generate(modsec_rec *msr, msre_var *var, msre
|
|||
return count;
|
||||
}
|
||||
|
||||
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
|
||||
static int var_useragent_ip_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
|
||||
apr_table_t *vartab, apr_pool_t *mptmp)
|
||||
{
|
||||
return var_simple_generate(var, vartab, mptmp, msr->useragent_ip ? msr->useragent_ip : "0.0.0.0");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* REMOTE_ADDR */
|
||||
|
||||
static int var_remote_addr_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
|
||||
|
@ -1613,6 +1621,50 @@ static int var_perf_logging_generate(modsec_rec *msr, msre_var *var, msre_rule *
|
|||
return generate_performance_variable(msr, var, rule, vartab, mptmp, msr->time_logging);
|
||||
}
|
||||
|
||||
|
||||
/* PERF_RULES */
|
||||
|
||||
static int var_perf_rules_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
|
||||
apr_table_t *vartab, apr_pool_t *mptmp)
|
||||
{
|
||||
const apr_array_header_t *arr = NULL;
|
||||
const apr_table_entry_t *te = NULL;
|
||||
int i, count = 0;
|
||||
|
||||
arr = apr_table_elts(msr->perf_rules);
|
||||
te = (apr_table_entry_t *)arr->elts;
|
||||
for (i = 0; i < arr->nelts; i++) {
|
||||
int match = 0;
|
||||
|
||||
/* Figure out if we want to include this variable. */
|
||||
if (var->param == NULL) match = 1;
|
||||
else {
|
||||
if (var->param_data != NULL) { /* Regex. */
|
||||
char *my_error_msg = NULL;
|
||||
if (!(msc_regexec((msc_regex_t *)var->param_data, te[i].key,
|
||||
strlen(te[i].key), &my_error_msg) == PCRE_ERROR_NOMATCH)) match = 1;
|
||||
} else { /* Simple comparison. */
|
||||
if (strcasecmp(te[i].key, var->param) == 0) match = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we had a match add this argument to the collection. */
|
||||
if (match) {
|
||||
msre_var *rvar = apr_pmemdup(mptmp, var, sizeof(msre_var));
|
||||
|
||||
rvar->value = te[i].val;
|
||||
rvar->value_len = strlen(rvar->value);
|
||||
rvar->name = apr_psprintf(mptmp, "PERF_RULES:%s",
|
||||
log_escape_nq(mptmp, te[i].key));
|
||||
apr_table_addn(vartab, rvar->name, (void *)rvar);
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* DURATION */
|
||||
|
||||
static int var_duration_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
|
||||
|
@ -1622,9 +1674,8 @@ static int var_duration_generate(modsec_rec *msr, msre_var *var, msre_rule *rule
|
|||
|
||||
rvar = apr_pmemdup(mptmp, var, sizeof(msre_var));
|
||||
rvar->value = apr_psprintf(mptmp, "%" APR_TIME_T_FMT,
|
||||
(apr_time_msec(apr_time_now() - msr->r->request_time)));
|
||||
(apr_time_usec(apr_time_now() - msr->r->request_time)));
|
||||
rvar->value_len = strlen(rvar->value);
|
||||
|
||||
apr_table_addn(vartab, rvar->name, (void *)rvar);
|
||||
|
||||
return 1;
|
||||
|
@ -1875,7 +1926,7 @@ static int var_matched_vars_names_generate(modsec_rec *msr, msre_var *var, msre_
|
|||
|
||||
rvar->value = apr_pstrndup(mptmp, str->name, strlen(str->name));
|
||||
rvar->value_len = strlen(rvar->value);
|
||||
rvar->name = apr_psprintf(mptmp, "MATCHED_VARS_NAMES:%s",
|
||||
rvar->name = apr_psprintf(mptmp, "%s",
|
||||
log_escape_nq(mptmp, str->name));
|
||||
|
||||
if(var->is_counting == 0)
|
||||
|
@ -1891,7 +1942,7 @@ static int var_matched_vars_names_generate(modsec_rec *msr, msre_var *var, msre_
|
|||
apr_table_addn(vartab, rvar->name, (void *)rvar);
|
||||
|
||||
if (msr->txcfg->debuglog_level >= 9) {
|
||||
msr_log(msr, 9, "Set variable \"%s\" value \"%s\" size %d to collection.", rvar->name, rvar->value, rvar->value_len);
|
||||
msr_log(msr, 9, "Set variable \"%s\" size %d to collection.", rvar->name,rvar->value_len);
|
||||
}
|
||||
|
||||
count++;
|
||||
|
@ -1935,7 +1986,7 @@ static int var_matched_vars_generate(modsec_rec *msr, msre_var *var, msre_rule *
|
|||
|
||||
rvar->value = apr_pstrndup(mptmp, str->value, str->value_len);
|
||||
rvar->value_len = str->value_len;
|
||||
rvar->name = apr_psprintf(mptmp, "MATCHED_VARS:%s",
|
||||
rvar->name = apr_psprintf(mptmp, "%s",
|
||||
log_escape_nq(mptmp, str->name));
|
||||
|
||||
if(var->is_counting == 0)
|
||||
|
@ -2913,6 +2964,19 @@ void msre_engine_register_default_variables(msre_engine *engine) {
|
|||
PHASE_REQUEST_HEADERS
|
||||
);
|
||||
|
||||
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER > 2
|
||||
/* USERAGENT_IP */
|
||||
msre_engine_variable_register(engine,
|
||||
"USERAGENT_IP",
|
||||
VAR_SIMPLE,
|
||||
0, 0,
|
||||
NULL,
|
||||
var_useragent_ip_generate,
|
||||
VAR_CACHE,
|
||||
PHASE_REQUEST_HEADERS
|
||||
);
|
||||
#endif
|
||||
|
||||
/* REMOTE_ADDR */
|
||||
msre_engine_variable_register(engine,
|
||||
"REMOTE_ADDR",
|
||||
|
@ -3508,7 +3572,18 @@ void msre_engine_register_default_variables(msre_engine *engine) {
|
|||
VAR_DONT_CACHE, /* dynamic */
|
||||
PHASE_RESPONSE_HEADERS
|
||||
);
|
||||
|
||||
|
||||
/* PERF_RULES */
|
||||
msre_engine_variable_register(engine,
|
||||
"PERF_RULES",
|
||||
VAR_LIST,
|
||||
0, 1,
|
||||
var_generic_list_validate,
|
||||
var_perf_rules_generate,
|
||||
VAR_DONT_CACHE,
|
||||
PHASE_REQUEST_HEADERS
|
||||
);
|
||||
|
||||
/* PERF_ALL */
|
||||
msre_engine_variable_register(engine,
|
||||
"PERF_ALL",
|
||||
|
@ -3519,7 +3594,7 @@ void msre_engine_register_default_variables(msre_engine *engine) {
|
|||
VAR_DONT_CACHE,
|
||||
PHASE_REQUEST_HEADERS
|
||||
);
|
||||
|
||||
|
||||
/* PERF_COMBINED */
|
||||
msre_engine_variable_register(engine,
|
||||
"PERF_COMBINED",
|
||||
|
@ -3530,7 +3605,7 @@ void msre_engine_register_default_variables(msre_engine *engine) {
|
|||
VAR_DONT_CACHE,
|
||||
PHASE_REQUEST_HEADERS
|
||||
);
|
||||
|
||||
|
||||
/* PERF_GC */
|
||||
msre_engine_variable_register(engine,
|
||||
"PERF_GC",
|
||||
|
@ -3541,7 +3616,7 @@ void msre_engine_register_default_variables(msre_engine *engine) {
|
|||
VAR_DONT_CACHE,
|
||||
PHASE_REQUEST_HEADERS
|
||||
);
|
||||
|
||||
|
||||
/* PERF_LOGGING */
|
||||
msre_engine_variable_register(engine,
|
||||
"PERF_LOGGING",
|
||||
|
@ -3552,7 +3627,7 @@ void msre_engine_register_default_variables(msre_engine *engine) {
|
|||
VAR_DONT_CACHE,
|
||||
PHASE_REQUEST_HEADERS
|
||||
);
|
||||
|
||||
|
||||
/* PERF_PHASE1 */
|
||||
msre_engine_variable_register(engine,
|
||||
"PERF_PHASE1",
|
||||
|
@ -3563,7 +3638,7 @@ void msre_engine_register_default_variables(msre_engine *engine) {
|
|||
VAR_DONT_CACHE,
|
||||
PHASE_REQUEST_HEADERS
|
||||
);
|
||||
|
||||
|
||||
/* PERF_PHASE2 */
|
||||
msre_engine_variable_register(engine,
|
||||
"PERF_PHASE2",
|
||||
|
@ -3574,7 +3649,7 @@ void msre_engine_register_default_variables(msre_engine *engine) {
|
|||
VAR_DONT_CACHE,
|
||||
PHASE_REQUEST_HEADERS
|
||||
);
|
||||
|
||||
|
||||
/* PERF_PHASE3 */
|
||||
msre_engine_variable_register(engine,
|
||||
"PERF_PHASE3",
|
||||
|
@ -3585,7 +3660,7 @@ void msre_engine_register_default_variables(msre_engine *engine) {
|
|||
VAR_DONT_CACHE,
|
||||
PHASE_REQUEST_HEADERS
|
||||
);
|
||||
|
||||
|
||||
/* PERF_PHASE4 */
|
||||
msre_engine_variable_register(engine,
|
||||
"PERF_PHASE4",
|
||||
|
@ -3596,7 +3671,7 @@ void msre_engine_register_default_variables(msre_engine *engine) {
|
|||
VAR_DONT_CACHE,
|
||||
PHASE_REQUEST_HEADERS
|
||||
);
|
||||
|
||||
|
||||
/* PERF_PHASE5 */
|
||||
msre_engine_variable_register(engine,
|
||||
"PERF_PHASE5",
|
||||
|
@ -3607,7 +3682,7 @@ void msre_engine_register_default_variables(msre_engine *engine) {
|
|||
VAR_DONT_CACHE,
|
||||
PHASE_REQUEST_HEADERS
|
||||
);
|
||||
|
||||
|
||||
/* PERF_SREAD */
|
||||
msre_engine_variable_register(engine,
|
||||
"PERF_SREAD",
|
||||
|
@ -3618,7 +3693,7 @@ void msre_engine_register_default_variables(msre_engine *engine) {
|
|||
VAR_DONT_CACHE,
|
||||
PHASE_REQUEST_HEADERS
|
||||
);
|
||||
|
||||
|
||||
/* PERF_SWRITE */
|
||||
msre_engine_variable_register(engine,
|
||||
"PERF_SWRITE",
|
||||
|
@ -3629,7 +3704,7 @@ void msre_engine_register_default_variables(msre_engine *engine) {
|
|||
VAR_DONT_CACHE,
|
||||
PHASE_REQUEST_HEADERS
|
||||
);
|
||||
|
||||
|
||||
/* DURATION */
|
||||
msre_engine_variable_register(engine,
|
||||
"DURATION",
|
||||
|
|
36
configure.ac
36
configure.ac
|
@ -6,7 +6,7 @@ dnl
|
|||
|
||||
AC_PREREQ(2.63)
|
||||
|
||||
AC_INIT([modsecurity], [2.6], [support@modsecurity.org])
|
||||
AC_INIT([modsecurity], [2.7], [support@modsecurity.org])
|
||||
|
||||
AC_CONFIG_MACRO_DIR([build])
|
||||
AC_CONFIG_SRCDIR([LICENSE])
|
||||
|
@ -304,6 +304,38 @@ AC_ARG_ENABLE(pcre-match-limit-recursion,
|
|||
pcre_match_limit_recursion='-DMODSEC_PCRE_MATCH_LIMIT_RECURSION=1500'
|
||||
])
|
||||
|
||||
# Enable Lua per transaction cache
|
||||
AC_ARG_ENABLE(lua-cache,
|
||||
AS_HELP_STRING([--enable-lua-cache],
|
||||
[Enable Lua per transaction cache.]),
|
||||
[
|
||||
if test "$enableval" != "no"; then
|
||||
lua_cache="-DCACHE_LUA"
|
||||
MODSEC_EXTRA_CFLAGS="$MODSEC_EXTRA_CFLAGS $lua_cache"
|
||||
else
|
||||
lua_cache=
|
||||
fi
|
||||
],
|
||||
[
|
||||
lua_cache=
|
||||
])
|
||||
|
||||
# Enable phase-1 in post_read_request
|
||||
AC_ARG_ENABLE(request-early,
|
||||
AS_HELP_STRING([--enable-request-early],
|
||||
[Place phase1 into post_read_request hook.]),
|
||||
[
|
||||
if test "$enableval" != "no"; then
|
||||
request_early="-DREQUEST_EARLY"
|
||||
MODSEC_EXTRA_CFLAGS="$MODSEC_EXTRA_CFLAGS $request_early"
|
||||
else
|
||||
request_early=
|
||||
fi
|
||||
],
|
||||
[
|
||||
request_early='-DREQUEST_EARLY'
|
||||
])
|
||||
|
||||
# Ignore configure errors
|
||||
AC_ARG_ENABLE(errors,
|
||||
AS_HELP_STRING([--disable-errors],
|
||||
|
@ -567,7 +599,7 @@ else
|
|||
fi
|
||||
fi
|
||||
|
||||
MODSEC_EXTRA_CFLAGS="$pcre_study $pcre_match_limit $pcre_match_limit_recursion $pcre_jit $debug_conf $debug_cache $debug_acmp $debug_mem $perf_meas $modsec_api"
|
||||
MODSEC_EXTRA_CFLAGS="$pcre_study $pcre_match_limit $pcre_match_limit_recursion $pcre_jit $request_early $lua_cache $debug_conf $debug_cache $debug_acmp $debug_mem $perf_meas $modsec_api"
|
||||
|
||||
APXS_WRAPPER=build/apxs-wrapper
|
||||
APXS_EXTRA_CFLAGS=""
|
||||
|
|
Загрузка…
Ссылка в новой задаче