diff --git a/Documentation/Filters/Database-Firewall-Filter.md b/Documentation/Filters/Database-Firewall-Filter.md index 228c2c410..18eb8dd2a 100644 --- a/Documentation/Filters/Database-Firewall-Filter.md +++ b/Documentation/Filters/Database-Firewall-Filter.md @@ -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 diff --git a/server/modules/filter/dbfwfilter/dbfwfilter.cc b/server/modules/filter/dbfwfilter/dbfwfilter.cc index d664d0838..cf9ab4c3a 100644 --- a/server/modules/filter/dbfwfilter/dbfwfilter.cc +++ b/server/modules/filter/dbfwfilter/dbfwfilter.cc @@ -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)); } /** diff --git a/server/modules/filter/dbfwfilter/dbfwfilter.h b/server/modules/filter/dbfwfilter/dbfwfilter.h index 505e00500..76db56cf4 100644 --- a/server/modules/filter/dbfwfilter/dbfwfilter.h +++ b/server/modules/filter/dbfwfilter/dbfwfilter.h @@ -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); diff --git a/server/modules/filter/dbfwfilter/ruleparser.y b/server/modules/filter/dbfwfilter/ruleparser.y index 52874e609..61a834476 100644 --- a/server/modules/filter/dbfwfilter/ruleparser.y +++ b/server/modules/filter/dbfwfilter/ruleparser.y @@ -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 FWTOK_FLOAT FWTOK_TIME 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);} ; diff --git a/server/modules/filter/dbfwfilter/rules.hh b/server/modules/filter/dbfwfilter/rules.hh index a7ee17c0a..db4535183 100644 --- a/server/modules/filter/dbfwfilter/rules.hh +++ b/server/modules/filter/dbfwfilter/rules.hh @@ -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,16 +218,18 @@ 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) { } bool matches_query(DbfwSession* session, GWBUF* buffer, char** msg) const; private: - ValueList m_columns; /*< List of columns to match */ + ValueList m_columns; /*< List of columns to match */ + bool m_inverted; /*< Should the match be inverted. */ }; /** diff --git a/server/modules/filter/dbfwfilter/token.l b/server/modules/filter/dbfwfilter/token.l index cada1606f..ba8f49206 100644 --- a/server/modules/filter/dbfwfilter/token.l +++ b/server/modules/filter/dbfwfilter/token.l @@ -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;