From 11d4370eaf70bd48e582f658aae0f2120d04adf2 Mon Sep 17 00:00:00 2001 From: Radoslaw Zarzynski Date: Wed, 5 Apr 2017 14:57:06 +0200 Subject: [PATCH 1/2] rgw: partially respect Swift's negative, HTTP referer-based ACLs. For the sake of simplicity this patch doesn't handle the case of having multiple ".r:*" in a single ACL like: .r:*,.r:-.example.com,.r:* The global wildcard (.r:*) is handled specifically because of S3. Next patch will brings full support. Signed-off-by: Radoslaw Zarzynski --- src/rgw/rgw_acl.cc | 29 ++++++++++++++--------------- src/rgw/rgw_acl.h | 4 +++- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/rgw/rgw_acl.cc b/src/rgw/rgw_acl.cc index 1cebae0d1862c..b4b8f8970a508 100644 --- a/src/rgw/rgw_acl.cc +++ b/src/rgw/rgw_acl.cc @@ -71,27 +71,26 @@ uint32_t RGWAccessControlList::get_group_perm(ACLGroupTypeEnum group, return 0; } -uint32_t RGWAccessControlList::get_referer_perm(const std::string http_referer, +uint32_t RGWAccessControlList::get_referer_perm(const uint32_t current_perm, + const std::string http_referer, const uint32_t perm_mask) { ldout(cct, 5) << "Searching permissions for referer=" << http_referer << " mask=" << perm_mask << dendl; - /* FIXME: C++11 doesn't have std::rbegin nor std::rend. We would like to - * switch when C++14 becomes available. */ - const auto iter = std::find_if(referer_list.crbegin(), referer_list.crend(), - [&http_referer](const ACLReferer& r) -> bool { - return r.is_match(http_referer); + /* This function is bacically a transformation from current perm to + * a new one that takes into consideration the Swift's HTTP referer- + * based ACLs. We need to go through all items to respect negative + * grants. */ + uint32_t referer_perm = current_perm; + for (const auto& r : referer_list) { + if (r.is_match(http_referer)) { + referer_perm = r.perm; } - ); - - if (referer_list.crend() == iter) { - ldout(cct, 5) << "Permissions for referer not found" << dendl; - return 0; - } else { - ldout(cct, 5) << "Found referer permission=" << iter->perm << dendl; - return iter->perm & perm_mask; } + + ldout(cct, 5) << "Found referer permission=" << referer_perm << dendl; + return referer_perm & perm_mask; } uint32_t RGWAccessControlPolicy::get_perm(const rgw::auth::Identity& auth_identity, @@ -123,7 +122,7 @@ uint32_t RGWAccessControlPolicy::get_perm(const rgw::auth::Identity& auth_identi /* Should we continue looking up even deeper? */ if (nullptr != http_referer && (perm & perm_mask) != perm_mask) { - perm |= acl.get_referer_perm(http_referer, perm_mask); + perm = acl.get_referer_perm(perm, http_referer, perm_mask); } ldout(cct, 5) << "-- Getting permissions done for identity=" << auth_identity diff --git a/src/rgw/rgw_acl.h b/src/rgw/rgw_acl.h index 24567677e8e17..c1711e7597f9f 100644 --- a/src/rgw/rgw_acl.h +++ b/src/rgw/rgw_acl.h @@ -302,7 +302,9 @@ class RGWAccessControlList uint32_t get_perm(const rgw::auth::Identity& auth_identity, uint32_t perm_mask); uint32_t get_group_perm(ACLGroupTypeEnum group, uint32_t perm_mask); - uint32_t get_referer_perm(const std::string http_referer, uint32_t perm_mask); + uint32_t get_referer_perm(uint32_t current_perm, + std::string http_referer, + uint32_t perm_mask); void encode(bufferlist& bl) const { ENCODE_START(4, 3, bl); bool maps_initialized = true; From 7e1615e2ef9ae5567f0af462d3b25de9746df020 Mon Sep 17 00:00:00 2001 From: Radoslaw Zarzynski Date: Wed, 5 Apr 2017 21:00:23 +0200 Subject: [PATCH 2/2] rgw: fully respect Swift's negative, HTTP referer-based ACLs. Fixes: http://tracker.ceph.com/issues/18841 Signed-off-by: Radoslaw Zarzynski --- src/rgw/rgw_acl.cc | 6 ++++++ src/rgw/rgw_acl.h | 6 ++++++ src/rgw/rgw_acl_swift.cc | 13 ++++++------- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/rgw/rgw_acl.cc b/src/rgw/rgw_acl.cc index b4b8f8970a508..0f246706abbad 100644 --- a/src/rgw/rgw_acl.cc +++ b/src/rgw/rgw_acl.cc @@ -24,6 +24,12 @@ void RGWAccessControlList::_add_grant(ACLGrant *grant) switch (type.get_type()) { case ACL_TYPE_REFERER: referer_list.emplace_back(grant->get_referer(), perm.get_permissions()); + + /* We're specially handling the Swift's .r:* as the S3 API has a similar + * concept and thus we can have a small portion of compatibility here. */ + if (grant->get_referer() == RGW_REFERER_WILDCARD) { + acl_group_map[ACL_GROUP_ALL_USERS] |= perm.get_permissions(); + } break; case ACL_TYPE_GROUP: acl_group_map[grant->get_group()] |= perm.get_permissions(); diff --git a/src/rgw/rgw_acl.h b/src/rgw/rgw_acl.h index c1711e7597f9f..ed149afff461e 100644 --- a/src/rgw/rgw_acl.h +++ b/src/rgw/rgw_acl.h @@ -29,6 +29,8 @@ using namespace std; #define RGW_PERM_ALL_S3 RGW_PERM_FULL_CONTROL #define RGW_PERM_INVALID 0xFF00 +static constexpr char RGW_REFERER_WILDCARD[] = "*"; + enum ACLGranteeTypeEnum { /* numbers are encoded, should not change */ ACL_TYPE_CANON_USER = 0, @@ -223,6 +225,10 @@ struct ACLReferer { return false; } + if ("*" == url_spec) { + return true; + } + if (http_host->compare(url_spec) == 0) { return true; } diff --git a/src/rgw/rgw_acl_swift.cc b/src/rgw/rgw_acl_swift.cc index 78b60124ba64b..6e9fe014e28c4 100644 --- a/src/rgw/rgw_acl_swift.cc +++ b/src/rgw/rgw_acl_swift.cc @@ -90,11 +90,7 @@ static boost::optional referrer_to_grant(std::string url_spec, is_negative = false; } - /* We're specially handling the .r:* as the S3 API has a similar concept - * and thus we can have a small portion of compatibility here. */ - if (url_spec == "*") { - grant.set_group(ACL_GROUP_ALL_USERS, is_negative ? 0 : perm); - } else { + if (url_spec != RGW_REFERER_WILDCARD) { if ('*' == url_spec[0]) { url_spec = url_spec.substr(1); boost::algorithm::trim(url_spec); @@ -103,10 +99,13 @@ static boost::optional referrer_to_grant(std::string url_spec, if (url_spec.empty() || url_spec == ".") { return boost::none; } - - grant.set_referer(url_spec, is_negative ? 0 : perm); + } else { + /* Please be aware we're specially handling the .r:* in _add_grant() + * of RGWAccessControlList as the S3 API has a similar concept, and + * thus we can have a small portion of compatibility. */ } + grant.set_referer(url_spec, is_negative ? 0 : perm); return grant; } catch (std::out_of_range) { return boost::none;