MXS-1346: Move matching implementation into classes

Added the implementations of the query_matches method for the RegexRule,
WhereClauseRule and WildCardRule classes and moved the query matching code
into these functions.
This commit is contained in:
Markus Mäkelä
2017-08-31 23:25:20 +03:00
parent f5d7919dbb
commit 1d11a12dcf
3 changed files with 84 additions and 75 deletions

View File

@ -130,11 +130,6 @@ static void rule_free_all(Rule* rule);
static bool process_rule_file(const char* filename, RuleList* rules, UserMap* users);
bool replace_rules(FW_INSTANCE* instance);
static inline bool query_is_sql(GWBUF* query)
{
return modutil_is_SQL(query) || modutil_is_SQL_prepare(query);
}
static void print_rule(Rule *rules, char *dest)
{
int type = 0;
@ -1017,9 +1012,7 @@ void define_wildcard_rule(void* scanner)
{
struct parser_stack* rstack = (struct parser_stack*)dbfw_yyget_extra((yyscan_t) scanner);
ss_dassert(rstack);
Rule* rule = create_rule(rstack->name);
rule->type = RT_WILDCARD;
rstack->rule.push_front(SRule(rule));
rstack->rule.push_front(SRule(new WildCardRule(rstack->name)));
}
/**
@ -1081,10 +1074,7 @@ void define_where_clause_rule(void* scanner)
{
struct parser_stack* rstack = (struct parser_stack*)dbfw_yyget_extra((yyscan_t) scanner);
ss_dassert(rstack);
Rule* rule = create_rule(rstack->name);
rule->type = RT_CLAUSE;
rstack->rule.push_front(SRule(rule));
rstack->rule.push_front(SRule(new NoWhereClauseRule(rstack->name)));
}
/**
@ -1124,10 +1114,7 @@ bool define_regex_rule(void* scanner, char* pattern)
{
struct parser_stack* rstack = (struct parser_stack*)dbfw_yyget_extra((yyscan_t) scanner);
ss_dassert(rstack);
Rule* rule = create_rule(rstack->name);
rule->type = RT_REGEX;
rule->data = re;
rstack->rule.push_front(SRule(rule));
rstack->rule.push_front(SRule(new RegexRule(rstack->name, re)));
}
else
{
@ -1661,31 +1648,6 @@ bool match_throttle(FW_SESSION* my_session, SRule rule, char **msg)
return matches;
}
void match_regex(SRule rule, const char *query, bool *matches, char **msg)
{
pcre2_match_data *mdata = pcre2_match_data_create_from_pattern((pcre2_code*)rule->data, NULL);
if (mdata)
{
if (pcre2_match((pcre2_code*)rule->data,
(PCRE2_SPTR)query, PCRE2_ZERO_TERMINATED,
0, 0, mdata, NULL) > 0)
{
MXS_NOTICE("rule '%s': regex matched on query", rule->name.c_str());
*matches = true;
*msg = create_error("Permission denied, query matched regular expression.");
}
pcre2_match_data_free(mdata);
}
else
{
MXS_ERROR("Allocation of matching data for PCRE2 failed."
" This is most likely caused by a lack of memory");
}
}
void match_column(SRule rule, GWBUF *queue, bool *matches, char **msg)
{
const QC_FIELD_INFO* infos;
@ -1772,23 +1734,6 @@ void match_function_usage(SRule rule, GWBUF *queue, enum fw_actions mode,
}
}
void match_wildcard(SRule rule, GWBUF *queue, bool *matches, char **msg)
{
const QC_FIELD_INFO* infos;
size_t n_infos;
qc_get_field_info(queue, &infos, &n_infos);
for (size_t i = 0; i < n_infos; ++i)
{
if (strcmp(infos[i].column, "*") == 0)
{
MXS_NOTICE("rule '%s': query contains a wildcard.", rule->name.c_str());
*matches = true;
*msg = create_error("Usage of wildcard denied.");
}
}
}
/**
* Check if a query matches a single rule
* @param my_instance Fwfilter instance
@ -1843,7 +1788,7 @@ bool rule_matches(FW_INSTANCE* my_instance,
break;
case RT_REGEX:
match_regex(rule, query, &matches, &msg);
/** Handled in RegexRule::query_matches */
break;
case RT_PERMISSION:
@ -1872,10 +1817,7 @@ bool rule_matches(FW_INSTANCE* my_instance,
break;
case RT_WILDCARD:
if (is_sql)
{
match_wildcard(rule, queue, &matches, &msg);
}
/** Handled in WildCardRule::query_matches */
break;
case RT_THROTTLE:
@ -1883,13 +1825,7 @@ bool rule_matches(FW_INSTANCE* my_instance,
break;
case RT_CLAUSE:
if (is_sql && !qc_query_has_clause(queue))
{
matches = true;
msg = create_error("Required WHERE/HAVING clause is missing.");
MXS_NOTICE("rule '%s': query has no where/having "
"clause, query is denied.", rule->name.c_str());
}
/** Handled in WhereClauseRule::query_matches */
break;
default:

View File

@ -13,10 +13,17 @@
#include "rules.hh"
#include <maxscale/alloc.h>
#include <maxscale/buffer.h>
#include <maxscale/log_manager.h>
#include <maxscale/modutil.h>
#include <maxscale/protocol/mysql.h>
static inline bool query_is_sql(GWBUF* query)
{
return modutil_is_SQL(query) || modutil_is_SQL_prepare(query);
}
Rule::Rule(std::string name):
data(NULL),
name(name),
@ -74,3 +81,69 @@ bool Rule::matches_query_type(GWBUF* buffer)
(MYSQL_IS_COM_INIT_DB(GWBUF_DATA(buffer)) &&
(on_queries & FW_OP_CHANGE_DB));
}
bool WildCardRule::matches_query(GWBUF *queue, char **msg)
{
bool rval = false;
if (query_is_sql(queue))
{
const QC_FIELD_INFO* infos;
size_t n_infos;
qc_get_field_info(queue, &infos, &n_infos);
for (size_t i = 0; i < n_infos; ++i)
{
if (strcmp(infos[i].column, "*") == 0)
{
MXS_NOTICE("rule '%s': query contains a wildcard.", name.c_str());
rval = true;
*msg = create_error("Usage of wildcard denied.");
}
}
}
return rval;
}
bool NoWhereClauseRule::matches_query(GWBUF* buffer, char** msg)
{
bool rval = false;
if (query_is_sql(buffer) && !qc_query_has_clause(buffer))
{
rval = true;
*msg = create_error("Required WHERE/HAVING clause is missing.");
MXS_NOTICE("rule '%s': query has no where/having "
"clause, query is denied.", name.c_str());
}
return rval;
}
bool RegexRule::matches_query(GWBUF* buffer, char** msg)
{
bool rval = false;
if (query_is_sql(buffer))
{
pcre2_code* re = m_re.get();
pcre2_match_data *mdata = pcre2_match_data_create_from_pattern(re, NULL);
MXS_ABORT_IF_NULL(mdata);
char* sql;
int len;
modutil_extract_SQL(buffer, &sql, &len);
if (pcre2_match(re, (PCRE2_SPTR)sql, (size_t)len, 0, 0, mdata, NULL) > 0)
{
MXS_NOTICE("rule '%s': regex matched on query", name.c_str());
rval = true;
*msg = create_error("Permission denied, query matched regular expression.");
}
pcre2_match_data_free(mdata);
}
return rval;
}

View File

@ -71,18 +71,18 @@ public:
/**
* Matches if a query has no WHERE clause
*/
class WhereClauseRule: public Rule
class NoWhereClauseRule: public Rule
{
WhereClauseRule(const WhereClauseRule&);
WhereClauseRule& operator=(const WhereClauseRule&);
NoWhereClauseRule(const NoWhereClauseRule&);
NoWhereClauseRule& operator=(const NoWhereClauseRule&);
public:
WhereClauseRule(std::string name):
NoWhereClauseRule(std::string name):
Rule(name)
{
}
~WhereClauseRule()
~NoWhereClauseRule()
{
}