From e673c3eab00b64ddf1a70b0835c8c1a282e90211 Mon Sep 17 00:00:00 2001 From: Johan Wikman Date: Thu, 5 Dec 2019 13:44:18 +0200 Subject: [PATCH] MXS-2788 Use case-insensitive string comparisons When names are matched in rules and in resultsets, case insensitive matching must be used. --- server/modules/filter/masking/maskingrules.cc | 23 +++++++--- server/modules/filter/masking/mysql.hh | 44 +++++++++++++++++-- 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/server/modules/filter/masking/maskingrules.cc b/server/modules/filter/masking/maskingrules.cc index e0a4485d6..e2d856c3e 100644 --- a/server/modules/filter/masking/maskingrules.cc +++ b/server/modules/filter/masking/maskingrules.cc @@ -430,6 +430,17 @@ bool create_rules_from_root(json_t* pRoot, return parsed; } + +inline bool is_same_name(const std::string& s, const char* zS) +{ + return strcasecmp(s.c_str(), zS) == 0; +} + +inline bool is_same_name(const std::string& lhs, const LEncString& rhs) +{ + return rhs.case_eq(lhs); +} + } // @@ -1063,9 +1074,9 @@ bool MaskingRules::Rule::matches(const ComQueryResponse::ColumnDef& column_def, // Otherwise it would be easy to bypass a table/database rule. bool match = - (m_column == column_def.org_name()) - && (m_table.empty() || table.empty() || (m_table == table)) - && (m_database.empty() || database.empty() || (m_database == database)); + is_same_name(m_column, column_def.org_name()) + && (m_table.empty() || table.empty() || is_same_name(m_table, table)) + && (m_database.empty() || database.empty() || is_same_name(m_database, database)); if (match) { @@ -1094,9 +1105,9 @@ bool MaskingRules::Rule::matches(const QC_FIELD_INFO& field, // Otherwise it would be easy to bypass a table/database rule. bool match = - (m_column == zColumn) - && (m_table.empty() || !zTable || (m_table == zTable)) - && (m_database.empty() || !zDatabase || (m_database == zDatabase)); + is_same_name(m_column, zColumn) + && (m_table.empty() || !zTable || is_same_name(m_table, zTable)) + && (m_database.empty() || !zDatabase || is_same_name(m_database, zDatabase)); if (match) { diff --git a/server/modules/filter/masking/mysql.hh b/server/modules/filter/masking/mysql.hh index b25d45ebc..4920b8fd1 100644 --- a/server/modules/filter/masking/mysql.hh +++ b/server/modules/filter/masking/mysql.hh @@ -294,7 +294,7 @@ public: } /** - * Compare for equality. + * Compare for equality in a case-sensitive fashion. * * @param s The string to compare with. * @@ -306,7 +306,19 @@ public: } /** - * Compare for equality. + * Compare for equality in case-insensitive fashion. + * + * @param s The string to compare with. + * + * @return True, if the strings are equal. + */ + bool case_eq(const LEncString& s) const + { + return m_length == s.m_length ? (strncasecmp(m_pString, s.m_pString, m_length) == 0) : false; + } + + /** + * Compare for equality in a case-sensitive fashion * * @param s The string to compare with. * @@ -320,7 +332,21 @@ public: } /** - * Compare for equality. + * Compare for equality in a case-insensitive fashion. + * + * @param s The string to compare with. + * + * @return True, if the strings are equal. + */ + bool case_eq(const char* zString) const + { + size_t length = strlen(zString); + + return m_length == length ? (strncasecmp(m_pString, zString, m_length) == 0) : false; + } + + /** + * Compare for equality in a case-sensitive fashion * * @param s The string to compare with. * @@ -331,6 +357,18 @@ public: return m_length == s.length() ? (memcmp(m_pString, s.data(), m_length) == 0) : false; } + /** + * Compare for equality in a case-insensitive fashion + * + * @param s The string to compare with. + * + * @return True, if the strings are equal. + */ + bool case_eq(const std::string& s) const + { + return m_length == s.length() ? (strncasecmp(m_pString, s.data(), m_length) == 0) : false; + } + /** * Convert a @c LEncString to the equivalent @c std::string. *