Merge branch '2.3' into develop
This commit is contained in:
@ -128,6 +128,48 @@ private:
|
||||
};
|
||||
|
||||
thread_local DbfwThread* this_thread = NULL;
|
||||
|
||||
// TODO: In 2.4 move to query_classifier.hh.
|
||||
class EnableOption
|
||||
{
|
||||
public:
|
||||
EnableOption(const EnableOption&) = delete;
|
||||
EnableOption& operator=(const EnableOption&) = delete;
|
||||
|
||||
EnableOption(uint32_t option)
|
||||
: m_option(option)
|
||||
, m_options(0)
|
||||
, m_disable(false)
|
||||
{
|
||||
if (m_option)
|
||||
{
|
||||
m_options = qc_get_options();
|
||||
|
||||
if (!(m_options & m_option))
|
||||
{
|
||||
uint32_t options = (m_options | m_option);
|
||||
MXB_AT_DEBUG(bool rv = )qc_set_options(options);
|
||||
mxb_assert(rv);
|
||||
m_disable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~EnableOption()
|
||||
{
|
||||
if (m_disable)
|
||||
{
|
||||
MXB_AT_DEBUG(bool rv = )qc_set_options(m_options);
|
||||
mxb_assert(rv);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t m_option;
|
||||
uint32_t m_options;
|
||||
bool m_disable;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bool parse_at_times(const char** tok, char** saveptr, Rule* ruledef);
|
||||
@ -584,6 +626,16 @@ MXS_MODULE* MXS_CREATE_MODULE()
|
||||
MXS_MODULE_OPT_ENUM_UNIQUE,
|
||||
action_values
|
||||
},
|
||||
{
|
||||
"treat_string_arg_as_field",
|
||||
MXS_MODULE_PARAM_BOOL,
|
||||
"true"
|
||||
},
|
||||
{
|
||||
"treat_string_as_field",
|
||||
MXS_MODULE_PARAM_BOOL,
|
||||
"true"
|
||||
},
|
||||
{MXS_END_MODULE_PARAMS}
|
||||
}
|
||||
};
|
||||
@ -1199,6 +1251,8 @@ int global_version = 1;
|
||||
Dbfw::Dbfw(MXS_CONFIG_PARAMETER* params)
|
||||
: m_action((enum fw_actions)params->get_enum("action", action_values))
|
||||
, m_log_match(0)
|
||||
, m_treat_string_as_field(params->get_bool("treat_string_as_field"))
|
||||
, m_treat_string_arg_as_field(params->get_bool("treat_string_arg_as_field"))
|
||||
, m_filename(params->get_string("rules"))
|
||||
, m_version(atomic_add(&global_version, 1))
|
||||
{
|
||||
@ -1227,6 +1281,26 @@ Dbfw* Dbfw::create(const char* zName, MXS_CONFIG_PARAMETER* pParams)
|
||||
if (process_rule_file(file, &rules, &users))
|
||||
{
|
||||
rval = new(std::nothrow) Dbfw(pParams);
|
||||
|
||||
if (rval)
|
||||
{
|
||||
if (rval->treat_string_as_field() || rval->treat_string_arg_as_field())
|
||||
{
|
||||
QC_CACHE_PROPERTIES cache_properties;
|
||||
qc_get_cache_properties(&cache_properties);
|
||||
|
||||
if (cache_properties.max_size != 0)
|
||||
{
|
||||
MXS_NOTICE("The parameter 'treat_string_arg_as_field' or(and) "
|
||||
"'treat_string_as_field' is enabled for %s, "
|
||||
"disabling the query classifier cache.",
|
||||
zName);
|
||||
|
||||
cache_properties.max_size = 0;
|
||||
qc_set_cache_properties(&cache_properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rval;
|
||||
@ -1468,6 +1542,19 @@ int DbfwSession::routeQuery(GWBUF* buffer)
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t option = 0;
|
||||
|
||||
if (m_instance->treat_string_as_field())
|
||||
{
|
||||
option |= QC_OPTION_STRING_AS_FIELD;
|
||||
}
|
||||
|
||||
if (m_instance->treat_string_arg_as_field())
|
||||
{
|
||||
option |= QC_OPTION_STRING_ARG_AS_FIELD;
|
||||
}
|
||||
|
||||
EnableOption enable(option);
|
||||
GWBUF* analyzed_queue = buffer;
|
||||
|
||||
// QUERY_TYPE_PREPARE_STMT need not be handled separately as the
|
||||
|
||||
@ -224,6 +224,26 @@ public:
|
||||
*/
|
||||
fw_actions get_action() const;
|
||||
|
||||
/**
|
||||
* Should strings be treated as fields?
|
||||
*
|
||||
* @return True, if they should, false otherwise.
|
||||
*/
|
||||
bool treat_string_as_field() const
|
||||
{
|
||||
return m_treat_string_as_field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should string args be treated as fields?
|
||||
*
|
||||
* @return True, if they should, false otherwise.
|
||||
*/
|
||||
bool treat_string_arg_as_field() const
|
||||
{
|
||||
return m_treat_string_arg_as_field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get logging option bitmask
|
||||
*
|
||||
@ -267,6 +287,8 @@ public:
|
||||
private:
|
||||
fw_actions m_action; /*< Default operation mode, defaults to deny */
|
||||
int m_log_match; /*< Log matching and/or non-matching queries */
|
||||
bool m_treat_string_as_field;
|
||||
bool m_treat_string_arg_as_field;
|
||||
mutable std::mutex m_lock; /*< Instance spinlock */
|
||||
std::string m_filename; /*< Path to the rule file */
|
||||
int m_version; /*< Latest rule file version, incremented on reload */
|
||||
|
||||
@ -145,6 +145,12 @@ extern "C" MXS_MODULE* MXS_CREATE_MODULE()
|
||||
Config::require_fully_parsed_default,
|
||||
MXS_MODULE_OPT_NONE,
|
||||
},
|
||||
{
|
||||
Config::treat_string_arg_as_field_name,
|
||||
MXS_MODULE_PARAM_BOOL,
|
||||
Config::treat_string_arg_as_field_default,
|
||||
MXS_MODULE_OPT_NONE
|
||||
},
|
||||
{MXS_END_MODULE_PARAMS}
|
||||
}
|
||||
};
|
||||
@ -179,6 +185,22 @@ MaskingFilter* MaskingFilter::create(const char* zName, MXS_CONFIG_PARAMETER* pP
|
||||
if (sRules.get())
|
||||
{
|
||||
pFilter = new MaskingFilter(config, sRules);
|
||||
|
||||
if (config.treat_string_arg_as_field())
|
||||
{
|
||||
QC_CACHE_PROPERTIES cache_properties;
|
||||
qc_get_cache_properties(&cache_properties);
|
||||
|
||||
if (cache_properties.max_size != 0)
|
||||
{
|
||||
MXS_NOTICE("The parameter 'treat_string_arg_as_field' is enabled for %s, "
|
||||
"disabling the query classifier cache.",
|
||||
zName);
|
||||
|
||||
cache_properties.max_size = 0;
|
||||
qc_set_cache_properties(&cache_properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pFilter;
|
||||
|
||||
@ -17,14 +17,15 @@
|
||||
namespace
|
||||
{
|
||||
|
||||
const char config_name_check_subqueries[] = "check_subqueries";
|
||||
const char config_name_check_unions[] = "check_unions";
|
||||
const char config_name_check_user_variables[] = "check_user_variables";
|
||||
const char config_name_large_payload[] = "large_payload";
|
||||
const char config_name_prevent_function_usage[] = "prevent_function_usage";
|
||||
const char config_name_require_fully_parsed[] = "require_fully_parsed";
|
||||
const char config_name_rules[] = "rules";
|
||||
const char config_name_warn_type_mismatch[] = "warn_type_mismatch";
|
||||
const char config_name_check_subqueries[] = "check_subqueries";
|
||||
const char config_name_check_unions[] = "check_unions";
|
||||
const char config_name_check_user_variables[] = "check_user_variables";
|
||||
const char config_name_large_payload[] = "large_payload";
|
||||
const char config_name_prevent_function_usage[] = "prevent_function_usage";
|
||||
const char config_name_require_fully_parsed[] = "require_fully_parsed";
|
||||
const char config_name_rules[] = "rules";
|
||||
const char config_name_warn_type_mismatch[] = "warn_type_mismatch";
|
||||
const char config_name_treat_string_arg_as_field[] = "treat_string_arg_as_field";
|
||||
|
||||
|
||||
const char config_value_abort[] = "abort";
|
||||
@ -105,7 +106,11 @@ const char* MaskingFilterConfig::check_subqueries_default = config_value_true;
|
||||
const char* MaskingFilterConfig::require_fully_parsed_name = config_name_require_fully_parsed;
|
||||
const char* MaskingFilterConfig::require_fully_parsed_default = config_name_require_fully_parsed;
|
||||
|
||||
|
||||
/*
|
||||
* PARAM treat_string_arg_as_field
|
||||
*/
|
||||
const char* MaskingFilterConfig::treat_string_arg_as_field_name = config_name_treat_string_arg_as_field;
|
||||
const char* MaskingFilterConfig::treat_string_arg_as_field_default = config_value_true;
|
||||
/*
|
||||
* MaskingFilterConfig
|
||||
*/
|
||||
@ -161,3 +166,9 @@ bool MaskingFilterConfig::get_require_fully_parsed(const MXS_CONFIG_PARAMETER* p
|
||||
{
|
||||
return pParams->get_bool(require_fully_parsed_name);
|
||||
}
|
||||
|
||||
// static
|
||||
bool MaskingFilterConfig::get_treat_string_arg_as_field(const MXS_CONFIG_PARAMETER* pParams)
|
||||
{
|
||||
return pParams->get_bool(treat_string_arg_as_field_name);
|
||||
}
|
||||
|
||||
@ -57,6 +57,9 @@ public:
|
||||
static const char* require_fully_parsed_name;
|
||||
static const char* require_fully_parsed_default;
|
||||
|
||||
static const char* treat_string_arg_as_field_name;
|
||||
static const char* treat_string_arg_as_field_default;
|
||||
|
||||
MaskingFilterConfig(const char* zName, const MXS_CONFIG_PARAMETER* pParams)
|
||||
: m_name(zName)
|
||||
, m_large_payload(get_large_payload(pParams))
|
||||
@ -67,6 +70,7 @@ public:
|
||||
, m_check_unions(get_check_unions(pParams))
|
||||
, m_check_subqueries(get_check_subqueries(pParams))
|
||||
, m_require_fully_parsed(get_require_fully_parsed(pParams))
|
||||
, m_treat_string_arg_as_field(get_treat_string_arg_as_field(pParams))
|
||||
{
|
||||
}
|
||||
|
||||
@ -119,6 +123,11 @@ public:
|
||||
return m_require_fully_parsed;
|
||||
}
|
||||
|
||||
bool treat_string_arg_as_field() const
|
||||
{
|
||||
return m_treat_string_arg_as_field;
|
||||
}
|
||||
|
||||
void set_large_payload(large_payload_t l)
|
||||
{
|
||||
m_large_payload = l;
|
||||
@ -158,6 +167,11 @@ public:
|
||||
m_require_fully_parsed = b;
|
||||
}
|
||||
|
||||
void set_treat_string_arg_as_field(bool b)
|
||||
{
|
||||
m_treat_string_arg_as_field = b;
|
||||
}
|
||||
|
||||
bool is_parsing_needed() const
|
||||
{
|
||||
return prevent_function_usage() || check_user_variables() || check_unions() || check_subqueries();
|
||||
@ -171,6 +185,7 @@ public:
|
||||
static bool get_check_unions(const MXS_CONFIG_PARAMETER* pParams);
|
||||
static bool get_check_subqueries(const MXS_CONFIG_PARAMETER* pParams);
|
||||
static bool get_require_fully_parsed(const MXS_CONFIG_PARAMETER* pParams);
|
||||
static bool get_treat_string_arg_as_field(const MXS_CONFIG_PARAMETER* pParams);
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
@ -182,4 +197,5 @@ private:
|
||||
bool m_check_unions;
|
||||
bool m_check_subqueries;
|
||||
bool m_require_fully_parsed;
|
||||
bool m_treat_string_arg_as_field;
|
||||
};
|
||||
|
||||
@ -48,6 +48,47 @@ GWBUF* create_parse_error_response()
|
||||
return create_error_response(zMessage);
|
||||
}
|
||||
|
||||
// TODO: In 2.4 move to query_classifier.hh.
|
||||
class EnableOption
|
||||
{
|
||||
public:
|
||||
EnableOption(const EnableOption&) = delete;
|
||||
EnableOption& operator=(const EnableOption&) = delete;
|
||||
|
||||
EnableOption(uint32_t option)
|
||||
: m_option(option)
|
||||
, m_options(0)
|
||||
, m_disable(false)
|
||||
{
|
||||
if (m_option)
|
||||
{
|
||||
m_options = qc_get_options();
|
||||
|
||||
if (!(m_options & m_option))
|
||||
{
|
||||
uint32_t options = (m_options | m_option);
|
||||
MXB_AT_DEBUG(bool rv = )qc_set_options(options);
|
||||
mxb_assert(rv);
|
||||
m_disable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~EnableOption()
|
||||
{
|
||||
if (m_disable)
|
||||
{
|
||||
MXB_AT_DEBUG(bool rv = )qc_set_options(m_options);
|
||||
mxb_assert(rv);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t m_option;
|
||||
uint32_t m_options;
|
||||
bool m_disable;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
MaskingFilterSession::MaskingFilterSession(MXS_SESSION* pSession, const MaskingFilter* pFilter)
|
||||
@ -127,6 +168,9 @@ bool MaskingFilterSession::check_textual_query(GWBUF* pPacket)
|
||||
{
|
||||
bool rv = false;
|
||||
|
||||
uint32_t option = m_filter.config().treat_string_arg_as_field() ? QC_OPTION_STRING_ARG_AS_FIELD : 0;
|
||||
EnableOption enable(option);
|
||||
|
||||
if (qc_parse(pPacket, QC_COLLECT_FIELDS | QC_COLLECT_FUNCTIONS) == QC_QUERY_PARSED
|
||||
|| !m_filter.config().require_fully_parsed())
|
||||
{
|
||||
@ -166,6 +210,9 @@ bool MaskingFilterSession::check_binary_query(GWBUF* pPacket)
|
||||
{
|
||||
bool rv = false;
|
||||
|
||||
uint32_t option = m_filter.config().treat_string_arg_as_field() ? QC_OPTION_STRING_ARG_AS_FIELD : 0;
|
||||
EnableOption enable(option);
|
||||
|
||||
if (qc_parse(pPacket, QC_COLLECT_FIELDS | QC_COLLECT_FUNCTIONS) == QC_QUERY_PARSED
|
||||
|| !m_filter.config().require_fully_parsed())
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user