MXS-1461 Introduce 'not_function' rule

Using 'not_function' it is possible to match functions other than
a specific set of ones. That will make it significantly easier to
allow certain functions to be used with certain columns.

The special handling of no arguments to `function` in conjunction
with an allowing filter has been removed. The same effect can now
be achieved, without special handling, using `not_function`, no
arguments and a blocking filter.

Implementation will follow in a subsequent commit.
This commit is contained in:
Johan Wikman
2017-11-10 09:25:09 +02:00
parent ced93acc20
commit 3215458b30
6 changed files with 77 additions and 27 deletions

View File

@ -161,24 +161,36 @@ matched. The symbolic comparison operators (`<`, `>`, `>=` etc.) are also
considered functions whereas the text versions (`NOT`, `IS`, `IS NOT` etc.) are
not considered functions.
If the rule is given no values then the rule will match any query which does not
use functions. By combining this with the `action=allow` parameter, it is
possible to enable whitelisting of all queries which do not use functions. One
such use case is preventing functions from being used to circumvent masking done
by the masking filter.
When the filter is in whitelist mode (`action=allow`) the function rule
will match any query that does not use a function. This means that queries
that do not use functions will be allowed through a function type rule.
##### Example
Deny SUM and COUNT functions:
Match queries using the _sum_ and _count_ functions:
```
rule examplerule match function sum count
```
#### `not_function`
This rule expects a list of values after the `not_function` keyword. These values
are interpreted as function names and if a query uses any function other than these,
it is matched. The symbolic comparison operators (`<`, `>`, `>=` etc.) are also
considered functions whereas the text versions (`NOT`, `IS`, `IS NOT` etc.) are
not considered functions.
If the rule is given no values, then the rule will match a query using any function.
#### Example
Match queries using other functions but the _length_ function:
```
rule examplerule match not_function length
```
Match queries using functions:
```
rule examplerule match not_function
```
#### `uses_function`
This rule expects a list of column names after the keyword. If any of the
@ -207,6 +219,31 @@ Deny use of the _sum_ function with _name_ or _address_ columns:
rule examplerule match function sum columns name address
```
#### `not_function` and `columns`
This rule combines the `not_function` and `columns` type rules to match if
one of the listed columns is used in conjunction with functions other than
the listed ones. The rule expects the `not_function` and `columns` keywords
both followed by a list of values.
If `not_function` is not provided with a list of values, then the rule
matches if any of the columns is used with any function.
##### Example
Match if any other function but _length_ is used with the _name_ or _address_
columns:
```
rule examplerule match not_function length columns name address
```
Match if any function is used with the _ssn_column:
```
rule examplerule match not_function columns ssn
```
#### `regex`
This rule blocks all queries matching a regex enclosed in single or double

View File

@ -870,11 +870,11 @@ void define_columns_rule(void* scanner)
*
* @param scanner Current scanner
*/
void define_function_rule(void* scanner)
void define_function_rule(void* scanner, bool inverted)
{
struct parser_stack* rstack = (struct parser_stack*)dbfw_yyget_extra((yyscan_t) scanner);
ss_dassert(rstack);
rstack->add(new FunctionRule(rstack->name, rstack->values));
rstack->add(new FunctionRule(rstack->name, rstack->values, inverted));
}
/**
@ -894,11 +894,11 @@ void define_function_usage_rule(void* scanner)
*
* @param scanner Current scanner
*/
void define_column_function_rule(void* scanner)
void define_column_function_rule(void* scanner, bool inverted)
{
struct parser_stack* rstack = (struct parser_stack*)dbfw_yyget_extra((yyscan_t) scanner);
ss_dassert(rstack);
rstack->add(new ColumnFunctionRule(rstack->name, rstack->values, rstack->auxiliary_values));
rstack->add(new ColumnFunctionRule(rstack->name, rstack->values, rstack->auxiliary_values, inverted));
}
/**

View File

@ -43,9 +43,9 @@ void define_wildcard_rule(void* scanner);
void define_where_clause_rule(void* scanner);
bool define_regex_rule(void* scanner, char* pattern);
void define_columns_rule(void* scanner);
void define_function_rule(void* scanner);
void define_function_rule(void* scanner, bool inverted);
void define_function_usage_rule(void* scanner);
void define_column_function_rule(void* scanner);
void define_column_function_rule(void* scanner, bool inverted);
void define_limit_queries_rule(void* scanner, int max, int timeperiod, int holdoff);
bool add_at_times_rule(void* scanner, const char* range);
void add_on_queries_rule(void* scanner, const char* sql);

View File

@ -37,7 +37,7 @@
%token FWTOK_RULE FWTOK_USERS FWTOK_RULES FWTOK_ANY FWTOK_ALL
%token FWTOK_STRICT_ALL FWTOK_MATCH FWTOK_WILDCARD FWTOK_COLUMNS FWTOK_REGEX
%token FWTOK_LIMIT_QUERIES FWTOK_WHERE_CLAUSE FWTOK_AT_TIMES FWTOK_ON_QUERIES
%token FWTOK_FUNCTION FWTOK_USES_FUNCTION FWTOK_COMMENT FWTOK_PIPE
%token FWTOK_FUNCTION FWTOK_USES_FUNCTION FWTOK_COMMENT FWTOK_PIPE FWTOK_NOT_FUNCTION
/** Terminal typed symbols */
%token <floatval>FWTOK_FLOAT <strval>FWTOK_TIME <strval>FWTOK_BTSTR
@ -124,9 +124,15 @@ mandatory
{define_limit_queries_rule(scanner, $2, $3, $4);}
| FWTOK_REGEX FWTOK_QUOTEDSTR {define_regex_rule(scanner, $2);}
| FWTOK_COLUMNS valuelist {define_columns_rule(scanner);}
| FWTOK_FUNCTION valuelist {define_function_rule(scanner);}
| FWTOK_FUNCTION {define_function_rule(scanner);}
| FWTOK_FUNCTION valuelist FWTOK_COLUMNS auxiliaryvaluelist {define_column_function_rule(scanner);}
| FWTOK_FUNCTION valuelist {define_function_rule(scanner, false);}
| FWTOK_NOT_FUNCTION valuelist {define_function_rule(scanner, true);}
| FWTOK_NOT_FUNCTION {define_function_rule(scanner, true);}
| FWTOK_FUNCTION valuelist FWTOK_COLUMNS auxiliaryvaluelist
{define_column_function_rule(scanner, false);}
| FWTOK_NOT_FUNCTION valuelist FWTOK_COLUMNS auxiliaryvaluelist
{define_column_function_rule(scanner, true);}
| FWTOK_NOT_FUNCTION FWTOK_COLUMNS auxiliaryvaluelist
{define_column_function_rule(scanner, true);}
| FWTOK_USES_FUNCTION valuelist {define_function_usage_rule(scanner);}
;

View File

@ -180,12 +180,16 @@ class FunctionRule: public ValueListRule
FunctionRule& operator=(const FunctionRule&);
public:
FunctionRule(std::string name, const ValueList& values):
ValueListRule(name, "FUNCTION", values)
FunctionRule(std::string name, const ValueList& values, bool inverted):
ValueListRule(name, inverted ? "NOT_FUNCTION" : "FUNCTION", values),
m_inverted(inverted)
{
}
bool matches_query(DbfwSession* session, GWBUF* buffer, char** msg) const;
private:
bool m_inverted; /*< Should the match be inverted. */
};
/**
@ -214,9 +218,10 @@ class ColumnFunctionRule: public ValueListRule
ColumnFunctionRule& operator=(const ColumnFunctionRule&);
public:
ColumnFunctionRule(std::string name, const ValueList& values, const ValueList& columns):
ValueListRule(name, "COLUMN_FUNCTION", values),
m_columns(columns)
ColumnFunctionRule(std::string name, const ValueList& values, const ValueList& columns, bool inverted):
ValueListRule(name, inverted ? "NOT_COLUMN_FUNCTION" : "COLUMN_FUNCTION", values),
m_columns(columns),
m_inverted(inverted)
{
}
@ -224,6 +229,7 @@ public:
private:
ValueList m_columns; /*< List of columns to match */
bool m_inverted; /*< Should the match be inverted. */
};
/**

View File

@ -40,6 +40,7 @@ CMP [=<>!]+
deny|allow MXS_WARNING("Use of '%s' is deprecated, use 'match' instead", yytext);return FWTOK_MATCH;
rule return FWTOK_RULE;
function return FWTOK_FUNCTION;
not_function return FWTOK_NOT_FUNCTION;
uses_function return FWTOK_USES_FUNCTION;
no_where_clause return FWTOK_WHERE_CLAUSE;
wildcard return FWTOK_WILDCARD;