From f3391c2dd4384c6d6878956f78c81f3d826acc22 Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Fri, 21 Jul 2017 11:33:03 -0400 Subject: [PATCH] rgw: split match into match_policy, match_wildcards Signed-off-by: Casey Bodley --- src/rgw/CMakeLists.txt | 1 + src/rgw/rgw_common.cc | 81 ++++++++------------------------------- src/rgw/rgw_common.h | 14 +++---- src/rgw/rgw_iam_policy.cc | 8 ++-- src/rgw/rgw_string.cc | 45 ++++++++++++++++++++++ src/rgw/rgw_string.h | 10 +++++ 6 files changed, 83 insertions(+), 76 deletions(-) create mode 100644 src/rgw/rgw_string.cc diff --git a/src/rgw/CMakeLists.txt b/src/rgw/CMakeLists.txt index c5017c7654e..fc3a33a0fdf 100644 --- a/src/rgw/CMakeLists.txt +++ b/src/rgw/CMakeLists.txt @@ -110,6 +110,7 @@ set(rgw_a_srcs rgw_rest_usage.cc rgw_rest_user.cc rgw_role.cc + rgw_string.cc rgw_swift_auth.cc rgw_tag.cc rgw_tag_s3.cc diff --git a/src/rgw/rgw_common.cc b/src/rgw/rgw_common.cc index caad672c120..f6230b1d2c4 100644 --- a/src/rgw/rgw_common.cc +++ b/src/rgw/rgw_common.cc @@ -1849,77 +1849,28 @@ int rgw_parse_op_type_list(const string& str, uint32_t *perm) return parse_list_of_flags(op_type_mapping, str, perm); } -static int match_internal(boost::string_ref pattern, boost::string_ref input, int (*function)(const char&, const char&)) -{ - boost::string_ref::iterator it1 = pattern.begin(); - boost::string_ref::iterator it2 = input.begin(); - while(true) { - if (it1 == pattern.end() && it2 == input.end()) - return 1; - if (it1 == pattern.end() || it2 == input.end()) - return 0; - if (*it1 == '*' && (it1 + 1) == pattern.end() && it2 != input.end()) - return 1; - if (*it1 == '*' && (it1 + 1) == pattern.end() && it2 == input.end()) - return 0; - if (function(*it1, *it2) || *it1 == '?') { - ++it1; - ++it2; - continue; - } - if (*it1 == '*') { - if (function(*(it1 + 1), *it2)) - ++it1; - else - ++it2; - continue; - } - return 0; - } - return 0; -} - -static int matchcase(const char& c1, const char& c2) -{ - if (c1 == c2) - return 1; - return 0; -} - -static int matchignorecase(const char& c1, const char& c2) -{ - if (tolower(c1) == tolower(c2)) - return 1; - return 0; -} - -int match(const string& pattern, const string& input, uint32_t flag) +bool match_policy(boost::string_view pattern, boost::string_view input, + uint32_t flag) { - auto last_pos_input = 0, last_pos_pattern = 0; + const uint32_t flag2 = flag & (MATCH_POLICY_ACTION|MATCH_POLICY_ARN) ? + MATCH_CASE_INSENSITIVE : 0; - while(true) { + const auto npos = boost::string_view::npos; + boost::string_view::size_type last_pos_input = 0, last_pos_pattern = 0; + while (true) { auto cur_pos_input = input.find(":", last_pos_input); auto cur_pos_pattern = pattern.find(":", last_pos_pattern); - string substr_input = input.substr(last_pos_input, cur_pos_input); - string substr_pattern = pattern.substr(last_pos_pattern, cur_pos_pattern); + auto substr_input = input.substr(last_pos_input, cur_pos_input); + auto substr_pattern = pattern.substr(last_pos_pattern, cur_pos_pattern); - int res; - if (substr_pattern == "*") { - res = 1; - } else if (flag & MATCH_POLICY_ACTION || flag & MATCH_POLICY_ARN) { - res = match_internal(substr_pattern, substr_input, &matchignorecase); - } else { - res = match_internal(substr_pattern, substr_input, &matchcase); - } - if (res == 0) - return 0; - - if (cur_pos_pattern == string::npos && cur_pos_input == string::npos) - return 1; - else if ((cur_pos_pattern == string::npos && cur_pos_input != string::npos) || - (cur_pos_pattern != string::npos && cur_pos_input == string::npos)) - return 0; + if (!match_wildcards(substr_pattern, substr_input, flag2)) + return false; + + if (cur_pos_pattern == npos) + return cur_pos_input == npos; + if (cur_pos_input == npos) + return false; last_pos_pattern = cur_pos_pattern + 1; last_pos_input = cur_pos_input + 1; diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index 6129d24e86b..a6871d7a4b8 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -2307,12 +2307,12 @@ extern std::string calc_hash_sha256_restart_stream(ceph::crypto::SHA256** phash) extern int rgw_parse_op_type_list(const string& str, uint32_t *perm); -namespace { - constexpr uint32_t MATCH_POLICY_ACTION = 0x01; - constexpr uint32_t MATCH_POLICY_RESOURCE = 0x02; - constexpr uint32_t MATCH_POLICY_ARN = 0x04; - constexpr uint32_t MATCH_POLICY_STRING = 0x08; -} +static constexpr uint32_t MATCH_POLICY_ACTION = 0x01; +static constexpr uint32_t MATCH_POLICY_RESOURCE = 0x02; +static constexpr uint32_t MATCH_POLICY_ARN = 0x04; +static constexpr uint32_t MATCH_POLICY_STRING = 0x08; + +extern bool match_policy(boost::string_view pattern, boost::string_view input, + uint32_t flag); -int match(const std::string& pattern, const std::string& input, uint32_t flag); #endif diff --git a/src/rgw/rgw_iam_policy.cc b/src/rgw/rgw_iam_policy.cc index e79468e79cb..d5ce7313082 100644 --- a/src/rgw/rgw_iam_policy.cc +++ b/src/rgw/rgw_iam_policy.cc @@ -389,15 +389,15 @@ bool ARN::match(const ARN& candidate) const { return false; } - if (!::match(region, candidate.region, MATCH_POLICY_ARN)) { + if (!match_policy(region, candidate.region, MATCH_POLICY_ARN)) { return false; } - if (!::match(account, candidate.account, MATCH_POLICY_ARN)) { + if (!match_policy(account, candidate.account, MATCH_POLICY_ARN)) { return false; } - if (!::match(resource, candidate.resource, MATCH_POLICY_ARN)) { + if (!match_policy(resource, candidate.resource, MATCH_POLICY_ARN)) { return false; } @@ -802,7 +802,7 @@ bool ParseState::do_string(CephContext* cct, const char* s, size_t l) { } else if ((w->id == TokenID::Action) || (w->id == TokenID::NotAction)) { for (auto& p : actpairs) { - if (match({s, l}, p.name, MATCH_POLICY_ACTION)) { + if (match_policy({s, l}, p.name, MATCH_POLICY_ACTION)) { (w->id == TokenID::Action ? t->action : t->notaction) |= p.bit; } } diff --git a/src/rgw/rgw_string.cc b/src/rgw/rgw_string.cc new file mode 100644 index 00000000000..d49bba71e17 --- /dev/null +++ b/src/rgw/rgw_string.cc @@ -0,0 +1,45 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "rgw_string.h" + +static bool char_eq(char c1, char c2) +{ + return c1 == c2; +} + +static bool ci_char_eq(char c1, char c2) +{ + return tolower(c1) == tolower(c2); +} + +bool match_wildcards(boost::string_view pattern, boost::string_view input, + uint32_t flags) +{ + const auto eq = (flags & MATCH_CASE_INSENSITIVE) ? &ci_char_eq : &char_eq; + + auto it1 = pattern.begin(); + auto it2 = input.begin(); + while (true) { + if (it1 == pattern.end()) + return it2 == input.end(); + if (*it1 == '*') { + if (it1 + 1 == pattern.end()) + return true; + if (it2 == input.end() || eq(*(it1 + 1), *it2)) + ++it1; + else + ++it2; + continue; + } + if (it2 == input.end()) + return false; + if (*it1 == '?' || eq(*it1, *it2)) { + ++it1; + ++it2; + continue; + } + return false; + } + return false; +} diff --git a/src/rgw/rgw_string.h b/src/rgw/rgw_string.h index 062880cc1ac..c56667533c0 100644 --- a/src/rgw/rgw_string.h +++ b/src/rgw/rgw_string.h @@ -223,4 +223,14 @@ std::string string_join_reserve(char delim, const Args&... args) return string_join_reserve(boost::string_view{&delim, 1}, args...); } + +/// use case-insensitive comparison in match_wildcards() +static constexpr uint32_t MATCH_CASE_INSENSITIVE = 0x01; + +/// attempt to match the given input string with the pattern, which may contain +/// the wildcard characters * and ? +extern bool match_wildcards(boost::string_view pattern, + boost::string_view input, + uint32_t flags = 0); + #endif -- 2.39.5