diff --git a/Documentation/Filters/Database-Firewall-Filter.md b/Documentation/Filters/Database-Firewall-Filter.md index 18eb8dd2a..704b585c4 100644 --- a/Documentation/Filters/Database-Firewall-Filter.md +++ b/Documentation/Filters/Database-Firewall-Filter.md @@ -355,6 +355,12 @@ After the matching part comes the rules keyword after which a list of rule names is expected. This allows reusing of the rules and enables varying levels of query restriction. +If a particular _NAME_ appears on several `users` lines, then when an +actual user matches that name, the rules of each line are checked +independently until there is a match for the statement in question. That +is, the rules of each `users` line are treated in an _OR_ fashion with +respect to each other. + ## Module commands Read [Module Commands](../Reference/Module-Commands.md) documentation for diff --git a/server/modules/filter/dbfwfilter/dbfwfilter.cc b/server/modules/filter/dbfwfilter/dbfwfilter.cc index fd5e85fb6..1c0aaa95e 100644 --- a/server/modules/filter/dbfwfilter/dbfwfilter.cc +++ b/server/modules/filter/dbfwfilter/dbfwfilter.cc @@ -1029,7 +1029,7 @@ static bool process_user_templates(UserMap& users, const TemplateList& templates if (newrules.size() > 0) { - user->append_rules(ut->type, newrules); + user->add_rules(ut->type, newrules); } } diff --git a/server/modules/filter/dbfwfilter/user.cc b/server/modules/filter/dbfwfilter/user.cc index 0792283ce..ee225333c 100644 --- a/server/modules/filter/dbfwfilter/user.cc +++ b/server/modules/filter/dbfwfilter/user.cc @@ -31,20 +31,20 @@ const char* User::name() const return m_name.c_str(); } -void User::append_rules(match_type mode, const RuleList& rules) +void User::add_rules(match_type mode, const RuleList& rules) { switch (mode) { case FWTOK_MATCH_ANY: - rules_or.insert(rules_or.end(), rules.begin(), rules.end()); + rules_or_vector.push_back(rules); break; case FWTOK_MATCH_ALL: - rules_and.insert(rules_and.end(), rules.begin(), rules.end()); + rules_and_vector.push_back(rules); break; case FWTOK_MATCH_STRICT_ALL: - rules_strict_and.insert(rules_strict_and.end(), rules.begin(), rules.end()); + rules_strict_and_vector.push_back(rules); break; default: @@ -73,28 +73,39 @@ bool User::match_any(Dbfw* my_instance, DbfwSession* my_session, bool rval = false; - if (rules_or.size() > 0 && should_match(queue)) + for (RuleListVector::iterator i = rules_or_vector.begin(); i != rules_or_vector.end(); ++i) { - char *fullquery = modutil_get_SQL(queue); + RuleList& rules_or = *i; - if (fullquery) + if (rules_or.size() > 0 && should_match(queue)) { - for (RuleList::iterator it = rules_or.begin(); it != rules_or.end(); it++) + char *fullquery = modutil_get_SQL(queue); + + if (fullquery) { - if (rule_is_active(*it)) + for (RuleList::iterator j = rules_or.begin(); j != rules_or.end(); j++) { - if (rule_matches(my_instance, my_session, queue, *it, fullquery)) + if (rule_is_active(*j)) { - *rulename = MXS_STRDUP_A((*it)->name().c_str()); - rval = true; - break; + if (rule_matches(my_instance, my_session, queue, *j, fullquery)) + { + *rulename = MXS_STRDUP_A((*j)->name().c_str()); + rval = true; + break; + } } } - } - MXS_FREE(fullquery); + MXS_FREE(fullquery); + } + } + + if (rval) + { + break; } } + return rval; } @@ -116,44 +127,54 @@ bool User::do_match(Dbfw* my_instance, DbfwSession* my_session, bool rval = false; bool have_active_rule = false; std::string matching_rules; - RuleList& rules = mode == User::ALL ? rules_and : rules_strict_and; + RuleListVector& rules_vector = (mode == User::ALL ? rules_and_vector : rules_strict_and_vector); - if (rules.size() > 0 && should_match(queue)) + for (RuleListVector::iterator i = rules_vector.begin(); i != rules_vector.end(); ++i) { - char *fullquery = modutil_get_SQL(queue); + RuleList& rules = *i; - if (fullquery) + if (rules.size() > 0 && should_match(queue)) { - rval = true; - for (RuleList::iterator it = rules.begin(); it != rules.end(); it++) + char *fullquery = modutil_get_SQL(queue); + + if (fullquery) { - if (rule_is_active(*it)) + rval = true; + for (RuleList::iterator j = rules.begin(); j != rules.end(); j++) { - have_active_rule = true; - - if (rule_matches(my_instance, my_session, queue, *it, fullquery)) + if (rule_is_active(*j)) { - matching_rules += (*it)->name(); - matching_rules += " "; - } - else - { - rval = false; + have_active_rule = true; - if (mode == User::STRICT) + if (rule_matches(my_instance, my_session, queue, *j, fullquery)) { - break; + matching_rules += (*j)->name(); + matching_rules += " "; + } + else + { + rval = false; + + if (mode == User::STRICT) + { + break; + } } } } - } - if (!have_active_rule) - { - /** No active rules */ - rval = false; + if (!have_active_rule) + { + /** No active rules */ + rval = false; + } + MXS_FREE(fullquery); } - MXS_FREE(fullquery); + } + + if (rval) + { + break; } } diff --git a/server/modules/filter/dbfwfilter/user.hh b/server/modules/filter/dbfwfilter/user.hh index 5c537389b..f80eb5254 100644 --- a/server/modules/filter/dbfwfilter/user.hh +++ b/server/modules/filter/dbfwfilter/user.hh @@ -57,12 +57,12 @@ public: const char* name() const; /** - * Append new rules to existing rules + * Add new rules to existing rules * * @param mode Matching mode for the rule * @param rules Rules to append */ - void append_rules(match_type mode, const RuleList& rules); + void add_rules(match_type mode, const RuleList& rules); /** * Check if a query matches some rule @@ -84,11 +84,13 @@ private: STRICT }; - RuleList rules_or; /*< If any of these rules match the action is triggered */ - RuleList rules_and; /*< All of these rules must match for the action to trigger */ - RuleList rules_strict_and; /*< rules that skip the rest of the rules if one of them - * fails. This is only for rules paired with 'match strict_all'. */ - std::string m_name; /*< Name of the user */ + typedef std::vector RuleListVector; + + RuleListVector rules_or_vector; /*< If any of these rules match the action is triggered */ + RuleListVector rules_and_vector; /*< All of these rules must match for the action to trigger */ + RuleListVector rules_strict_and_vector;/*< rules that skip the rest of the rules if one of them + * fails. This is only for rules paired with 'match strict_all'. */ + std::string m_name; /*< Name of the user */ /** * Functions for matching rules