Added @within string comparison operator with support for macro expansion. See #134.

This commit is contained in:
brectanus 2007-06-21 02:21:06 +00:00
parent b58efb3466
commit 19887f9cc6
3 changed files with 91 additions and 1 deletions

View File

@ -2,6 +2,8 @@
?? ??? 2007 - 2.5.0-trunk
-------------------------
* Added @within string comparison operator with support for macro expansion.
* Removed experimental variable RESPONSE_CONTENT_ENCODING which was not
working as intended.

View File

@ -331,6 +331,69 @@ static int msre_op_pm_execute(modsec_rec *msr, msre_rule *rule, msre_var *var, c
return rc;
}
/* within */
static int msre_op_within_execute(modsec_rec *msr, msre_rule *rule, msre_var *var, char **error_msg) {
msc_string *str = (msc_string *)apr_pcalloc(msr->mp, sizeof(msc_string));
const char *match = NULL;
const char *target;
unsigned int match_length;
unsigned int target_length = 0;
unsigned int i, i_max;
str->value = (char *)rule->op_param;
str->value_len = strlen(str->value);
if (error_msg == NULL) return -1;
*error_msg = NULL;
if (str->value == NULL) {
*error_msg = "Internal Error: match string is null.";
return -1;
}
expand_macros(msr, str, rule, msr->mp);
match = (const char *)str->value;
match_length = str->value_len;
/* If the given target is null we give up without a match */
if (var->value == NULL) {
/* No match. */
return 0;
}
target = var->value;
target_length = var->value_len;
/* These are impossible to match */
if ((match_length == 0) || (target_length > match_length)) {
/* No match. */
return 0;
}
/* scan for first character, then compare from there until we
* have a match or there is no room left in the target
*/
msr_log(msr, 9, "match[%d]='%s' target[%d]='%s'", match_length, match, target_length, target);
i_max = match_length - target_length;
for (i = 0; i <= i_max; i++) {
if (match[i] == target[0]) {
if (strncmp(target, (match + i), target_length) == 0) {
/* match. */
*error_msg = apr_psprintf(msr->mp, "String match %s=\"%s\" within \"%s\".",
var->name,
log_escape_ex(msr->mp, target, target_length),
log_escape_ex(msr->mp, match, match_length));
return 1;
}
}
}
/* No match. */
return 0;
}
/* contains */
static int msre_op_contains_execute(modsec_rec *msr, msre_rule *rule, msre_var *var, char **error_msg) {
@ -338,7 +401,7 @@ static int msre_op_contains_execute(modsec_rec *msr, msre_rule *rule, msre_var *
const char *match = NULL;
const char *target;
unsigned int match_length;
unsigned int target_length;
unsigned int target_length = 0;
unsigned int i, i_max;
str->value = (char *)rule->op_param;
@ -1381,6 +1444,13 @@ void msre_engine_register_default_operators(msre_engine *engine) {
msre_op_pm_execute
);
/* within */
msre_engine_op_register(engine,
"within",
NULL, /* ENH init function to flag var substitution */
msre_op_within_execute
);
/* contains */
msre_engine_op_register(engine,
"contains",

View File

@ -4649,5 +4649,23 @@ SecRule XML "<emphasis role="bold">@validateSchema /path/to/apache2/conf/xml.xsd
</listitem>
</itemizedlist>
</section>
<section>
<title><literal>within</literal></title>
<para><emphasis role="bold">Description: </emphasis>This operator is a
string comparison similar to <literal>@contains</literal>, except that
the target and match values are reversed. It returns true if the input
value is found anywhere within the parameter value. Macro expansion is
performed so you may use variable names such as %{TX.1}, etc.</para>
<para>Example:</para>
<programlisting format="linespecific">SecRule REQUEST_METHOD "!<emphasis
role="bold">@within get,post,head</emphasis>" t:lowercase,deny,status:403
SecAction "pass,setvar:'tx.allowed_methods=get,post,head'"
SecRule REQUEST_METHOD "!<emphasis role="bold">@within %{tx.allowed_methods}</emphasis>" t:lowercase,deny,status:403</programlisting>
</section>
</section>
</article>