MODSEC-57

This commit is contained in:
brenosilva
2011-02-24 15:03:50 +00:00
parent e0a49f0b04
commit d170dd4ebe
4 changed files with 294 additions and 63 deletions

View File

@@ -121,7 +121,6 @@ void *create_directory_config(apr_pool_t *mp, char *path)
dcfg->component_signatures = apr_array_make(mp, 16, sizeof(char *));
dcfg->request_encoding = NOT_SET_P;
dcfg->disable_backend_compression = NOT_SET;
return dcfg;
@@ -905,6 +904,156 @@ static const char *update_rule_action(cmd_parms *cmd, directory_config *dcfg,
return NULL;
}
char *update_rule_target(cmd_parms *cmd, directory_config *dcfg,
msre_ruleset *rset, const char *p1, const char *p2, const char *p3)
{
msre_var **targets = NULL;
msre_rule *rule = NULL;
msre_ruleset *ruleset = NULL;
const char *curr_targets = NULL;
char *my_error_msg = NULL;
char *p = NULL;
char *savedptr = NULL;
char *target_list = NULL;
char *replace = NULL;
int is_negated = 0;
int is_counting = 0;
int name_len = 0;
int value_len = 0;
char *name = NULL, *value = NULL;
char *opt = NULL;
char *param = NULL;
int i, rc, match = 0;
if(p1 == NULL || p2 == NULL || (dcfg == NULL && rset == NULL)) {
return 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);
if (rule == NULL) {
if (cmd != NULL) {
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_NOERRNO, 0, cmd->pool,
"Update rule id=\"%s\" with targets \"%s\" failed: Rule not found.", p1, p2);
}
return NULL;
}
target_list = strdup(p2);
if(target_list == NULL)
return NULL;
if(p3 != NULL) {
replace = strdup(p3);
if(replace == NULL) {
free(target_list);
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);
if(strchr(value,':') != NULL) {
goto end;
}
} 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((strncasecmp(targets[i]->name,name,name_len) == 0) &&
(targets[i]->is_negated == is_negated) &&
(targets[i]->is_counting == is_counting)) {
if(value != NULL && targets[i]->param != NULL) {
if(strncasecmp(targets[i]->param,value,value_len) == 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;
}
}
}
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 {
rc = msre_parse_targets(ruleset, p, rule->targets, &my_error_msg);
if (rc < 0) {
goto end;
}
}
p = apr_strtok(NULL,",",&savedptr);
}
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)
free(target_list);
if(replace != NULL)
free(replace);
return NULL;
}
/* -- Configuration directives -- */
static const char *cmd_action(cmd_parms *cmd, void *_dcfg, const char *p1)
@@ -1620,6 +1769,23 @@ 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
*/
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);
}
static const char *cmd_rule(cmd_parms *cmd, void *_dcfg,
const char *p1, const char *p2, const char *p3)
{
@@ -2374,6 +2540,14 @@ const command_rec module_directives[] = {
"updated action list"
),
AP_INIT_TAKE23 (
"SecRuleUpdateTargetById",
cmd_rule_update_target_by_id,
NULL,
CMD_SCOPE_ANY,
"updated target list"
),
AP_INIT_TAKE1 (
"SecServerSignature",
cmd_server_signature,

View File

@@ -60,11 +60,35 @@ static void msre_actionset_cardinality_fixup(msre_actionset *actionset, msre_act
}
}
char *msre_generate_target_string(apr_pool_t *pool, msre_rule *rule) {
char *target_str = NULL;
msre_var **targets = NULL;
int i = 0, count = 0;
targets = (msre_var **)rule->targets->elts;
for (i = 0; i < rule->targets->nelts; i++) {
if(targets[i]->name != NULL && strlen(targets[i]->name) > 0) {
target_str = apr_pstrcat(pool,
(target_str == NULL) ? "" : apr_psprintf(pool, "%s|", target_str),
(targets[i]->is_negated == 0) ? "" : "!",
(targets[i]->is_counting == 0) ? "" : "&",
(targets[i]->name == NULL) ? "" : targets[i]->name,
(targets[i]->param == NULL) ? "" : apr_psprintf(pool, ":%s", targets[i]->param),
NULL);
}
}
return target_str;
}
/**
* Generate an action string from an actionset.
*/
char *msre_actionset_generate_action_string(apr_pool_t *pool, const msre_actionset *actionset)
{
char *msre_actionset_generate_action_string(apr_pool_t *pool, const msre_actionset *actionset) {
const apr_array_header_t *tarr = NULL;
const apr_table_entry_t *telts = NULL;
char *actions = NULL;
@@ -280,15 +304,15 @@ msre_var *msre_create_var_ex(apr_pool_t *pool, msre_engine *engine, const char *
/* Handle negation and member counting */
if (name[0] == '!') {
var->is_negated = 1;
var->name = name + 1;
var->name = (char *)name + 1;
}
else
if (name[0] == '&') {
var->is_counting = 1;
var->name = name + 1;
var->name = (char *)name + 1;
}
else {
var->name = name;
var->name = (char *)name;
}
/* Treat HTTP_* targets as an alias for REQUEST_HEADERS:* */
@@ -334,7 +358,8 @@ msre_var *msre_create_var_ex(apr_pool_t *pool, msre_engine *engine, const char *
return NULL;
}
var->param = varparam;
var->param = (char *)varparam;
}
return var;

View File

@@ -45,12 +45,14 @@ typedef struct msre_cache_rec msre_cache_rec;
#include "msc_pcre.h"
#include "persist_dbm.h"
#include "apache2.h"
#include "http_config.h"
#if defined(WITH_LUA)
#include "msc_lua.h"
#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);
apr_status_t DSOLOCAL collection_original_setvar(modsec_rec *msr, const char *col_name, const msc_string *orig_var);
@@ -277,10 +279,10 @@ struct msre_var_metadata {
};
struct msre_var {
const char *name;
char *name;
const char *value;
unsigned int value_len;
const char *param;
char *param;
const void *param_data;
msre_var_metadata *metadata;
msc_regex_t *param_regex;
@@ -327,6 +329,8 @@ struct msre_actionset {
char DSOLOCAL *msre_actionset_generate_action_string(apr_pool_t *pool, const msre_actionset *actionset);
char DSOLOCAL *msre_generate_target_string(apr_pool_t *pool, msre_rule *rule);
void DSOLOCAL msre_engine_variable_register(msre_engine *engine, const char *name,
unsigned int type, unsigned int argc_min, unsigned int argc_max,
fn_var_validate_t validate, fn_var_generate_t generate,
@@ -411,7 +415,6 @@ apr_status_t DSOLOCAL msre_parse_vars(msre_ruleset *ruleset, const char *text,
char DSOLOCAL *msre_format_metadata(modsec_rec *msr, msre_actionset *actionset);
/* -- Data Cache -- */
struct msre_cache_rec {

View File

@@ -815,6 +815,17 @@ static char *msre_action_ctl_validate(msre_engine *engine, msre_action *action)
"the hard limit: %ld", RESPONSE_BODY_HARD_LIMIT);
}
return NULL;
} else
if (strcasecmp(name, "ruleUpdateTargetById") == 0) {
char *parm = NULL;
char *savedptr = NULL;
parm = apr_strtok(value,";",&savedptr);
if(parm == NULL && savedptr == NULL)
return apr_psprintf(engine->mp, "ruleUpdateTargetById must has at least id;append_value");
return NULL;
}
else {
@@ -1018,6 +1029,24 @@ static apr_status_t msre_action_ctl_execute(modsec_rec *msr, apr_pool_t *mptmp,
msr_log(msr, 4, "Ctl: Set responseBodyLimit to %ld.", limit);
}
return 1;
} else
if (strcasecmp(name, "ruleUpdateTargetById") == 0) {
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: ruleUpdateTargetById id=%s append=%s replace=%s", p1, p2, p3);
}
update_rule_target(NULL, NULL, rule->ruleset, p1, p2, p3);
return 1;
}
else {