diff --git a/Documentation/Filters/Database-Firewall-Filter.md b/Documentation/Filters/Database-Firewall-Filter.md index d16add626..34ca1ade8 100644 --- a/Documentation/Filters/Database-Firewall-Filter.md +++ b/Documentation/Filters/Database-Firewall-Filter.md @@ -146,6 +146,16 @@ query itself is logged. The log messages are logged at the notice level. Log all queries that do not match a rule. The matched user and the query is logged. The log messages are logged at the notice level. +#### `treat_string_arg_as_field` +This optional parameter specifies how the database firewall should treat +strings used as arguments to functions. If true, they will be handled +as fields, which will cause fields to be masked even if `ANSI_QUOTES` has +been enabled and `"` is used instead of backtick. +``` +treat_string_arg_as_field=false +``` +The default value is `true`. + ## Rule syntax The rules are defined by using the following syntax: diff --git a/server/modules/filter/dbfwfilter/dbfwfilter.cc b/server/modules/filter/dbfwfilter/dbfwfilter.cc index 908fe9e80..ab3911e93 100644 --- a/server/modules/filter/dbfwfilter/dbfwfilter.cc +++ b/server/modules/filter/dbfwfilter/dbfwfilter.cc @@ -129,6 +129,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); @@ -585,6 +627,11 @@ MXS_MODULE* MXS_CREATE_MODULE() MXS_MODULE_OPT_ENUM_UNIQUE, action_values }, + { + "treat_string_arg_as_field", + MXS_MODULE_PARAM_BOOL, + "true" + }, {MXS_END_MODULE_PARAMS} } }; @@ -1200,6 +1247,7 @@ int global_version = 1; Dbfw::Dbfw(MXS_CONFIG_PARAMETER* params) : m_action((enum fw_actions)config_get_enum(params, "action", action_values)) , m_log_match(0) + , m_treat_string_arg_as_field(config_get_bool(params, "treat_string_arg_as_field")) , m_filename(config_get_string(params, "rules")) , m_version(atomic_add(&global_version, 1)) { @@ -1469,6 +1517,8 @@ int DbfwSession::routeQuery(GWBUF* buffer) } else { + uint32_t option = m_instance->treat_string_arg_as_field() ? QC_OPTION_STRING_ARG_AS_FIELD : 0; + EnableOption enable(option); GWBUF* analyzed_queue = buffer; // QUERY_TYPE_PREPARE_STMT need not be handled separately as the diff --git a/server/modules/filter/dbfwfilter/dbfwfilter.hh b/server/modules/filter/dbfwfilter/dbfwfilter.hh index 7c69a25ff..3ff2b8d63 100644 --- a/server/modules/filter/dbfwfilter/dbfwfilter.hh +++ b/server/modules/filter/dbfwfilter/dbfwfilter.hh @@ -224,6 +224,16 @@ public: */ fw_actions get_action() const; + /** + * 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 +277,7 @@ 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_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 */ diff --git a/server/modules/filter/masking/maskingfiltersession.cc b/server/modules/filter/masking/maskingfiltersession.cc index a2276e1a7..397ba850e 100644 --- a/server/modules/filter/masking/maskingfiltersession.cc +++ b/server/modules/filter/masking/maskingfiltersession.cc @@ -48,6 +48,7 @@ GWBUF* create_parse_error_response() return create_error_response(zMessage); } +// TODO: In 2.4 move to query_classifier.hh. class EnableOption { public: