1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
9 #include "include/types.h"
11 #include "common/Formatter.h"
14 #include "rgw_acl_s3.h"
17 #define dout_subsys ceph_subsys_rgw
21 bool operator==(const ACLPermission
& lhs
, const ACLPermission
& rhs
) {
22 return lhs
.flags
== rhs
.flags
;
24 bool operator!=(const ACLPermission
& lhs
, const ACLPermission
& rhs
) {
28 bool operator==(const ACLGranteeType
& lhs
, const ACLGranteeType
& rhs
) {
29 return lhs
.type
== rhs
.type
;
31 bool operator!=(const ACLGranteeType
& lhs
, const ACLGranteeType
& rhs
) {
32 return lhs
.type
!= rhs
.type
;
35 bool operator==(const ACLGrant
& lhs
, const ACLGrant
& rhs
) {
36 return lhs
.type
== rhs
.type
&& lhs
.id
== rhs
.id
37 && lhs
.email
== rhs
.email
&& lhs
.permission
== rhs
.permission
38 && lhs
.name
== rhs
.name
&& lhs
.group
== rhs
.group
39 && lhs
.url_spec
== rhs
.url_spec
;
41 bool operator!=(const ACLGrant
& lhs
, const ACLGrant
& rhs
) {
45 bool operator==(const ACLReferer
& lhs
, const ACLReferer
& rhs
) {
46 return lhs
.url_spec
== rhs
.url_spec
&& lhs
.perm
== rhs
.perm
;
48 bool operator!=(const ACLReferer
& lhs
, const ACLReferer
& rhs
) {
52 bool operator==(const RGWAccessControlList
& lhs
,
53 const RGWAccessControlList
& rhs
) {
54 return lhs
.acl_user_map
== rhs
.acl_user_map
55 && lhs
.acl_group_map
== rhs
.acl_group_map
56 && lhs
.referer_list
== rhs
.referer_list
57 && lhs
.grant_map
== rhs
.grant_map
;
59 bool operator!=(const RGWAccessControlList
& lhs
,
60 const RGWAccessControlList
& rhs
) {
64 bool operator==(const ACLOwner
& lhs
, const ACLOwner
& rhs
) {
65 return lhs
.id
== rhs
.id
&& lhs
.display_name
== rhs
.display_name
;
67 bool operator!=(const ACLOwner
& lhs
, const ACLOwner
& rhs
) {
71 bool operator==(const RGWAccessControlPolicy
& lhs
,
72 const RGWAccessControlPolicy
& rhs
) {
73 return lhs
.acl
== rhs
.acl
&& lhs
.owner
== rhs
.owner
;
75 bool operator!=(const RGWAccessControlPolicy
& lhs
,
76 const RGWAccessControlPolicy
& rhs
) {
80 void RGWAccessControlList::_add_grant(ACLGrant
*grant
)
82 ACLPermission
& perm
= grant
->get_permission();
83 ACLGranteeType
& type
= grant
->get_type();
84 switch (type
.get_type()) {
85 case ACL_TYPE_REFERER
:
86 referer_list
.emplace_back(grant
->get_referer(), perm
.get_permissions());
88 /* We're specially handling the Swift's .r:* as the S3 API has a similar
89 * concept and thus we can have a small portion of compatibility here. */
90 if (grant
->get_referer() == RGW_REFERER_WILDCARD
) {
91 acl_group_map
[ACL_GROUP_ALL_USERS
] |= perm
.get_permissions();
95 acl_group_map
[grant
->get_group()] |= perm
.get_permissions();
100 if (!grant
->get_id(id
)) {
101 ldout(cct
, 0) << "ERROR: grant->get_id() failed" << dendl
;
103 acl_user_map
[id
.to_str()] |= perm
.get_permissions();
108 void RGWAccessControlList::add_grant(ACLGrant
*grant
)
111 grant
->get_id(id
); // not that this will return false for groups, but that's ok, we won't search groups
112 grant_map
.insert(pair
<string
, ACLGrant
>(id
.to_str(), *grant
));
116 void RGWAccessControlList::remove_canon_user_grant(rgw_user
& user_id
)
118 auto multi_map_iter
= grant_map
.find(user_id
.to_str());
119 if(multi_map_iter
!= grant_map
.end()) {
120 auto grants
= grant_map
.equal_range(user_id
.to_str());
121 grant_map
.erase(grants
.first
, grants
.second
);
124 auto map_iter
= acl_user_map
.find(user_id
.to_str());
125 if (map_iter
!= acl_user_map
.end()){
126 acl_user_map
.erase(map_iter
);
130 uint32_t RGWAccessControlList::get_perm(const DoutPrefixProvider
* dpp
,
131 const rgw::auth::Identity
& auth_identity
,
132 const uint32_t perm_mask
)
134 ldpp_dout(dpp
, 5) << "Searching permissions for identity=" << auth_identity
135 << " mask=" << perm_mask
<< dendl
;
137 return perm_mask
& auth_identity
.get_perms_from_aclspec(dpp
, acl_user_map
);
140 uint32_t RGWAccessControlList::get_group_perm(const DoutPrefixProvider
*dpp
,
141 ACLGroupTypeEnum group
,
142 const uint32_t perm_mask
) const
144 ldpp_dout(dpp
, 5) << "Searching permissions for group=" << (int)group
145 << " mask=" << perm_mask
<< dendl
;
147 const auto iter
= acl_group_map
.find((uint32_t)group
);
148 if (iter
!= acl_group_map
.end()) {
149 ldpp_dout(dpp
, 5) << "Found permission: " << iter
->second
<< dendl
;
150 return iter
->second
& perm_mask
;
152 ldpp_dout(dpp
, 5) << "Permissions for group not found" << dendl
;
156 uint32_t RGWAccessControlList::get_referer_perm(const DoutPrefixProvider
*dpp
,
157 const uint32_t current_perm
,
158 const std::string http_referer
,
159 const uint32_t perm_mask
)
161 ldpp_dout(dpp
, 5) << "Searching permissions for referer=" << http_referer
162 << " mask=" << perm_mask
<< dendl
;
164 /* This function is basically a transformation from current perm to
165 * a new one that takes into consideration the Swift's HTTP referer-
166 * based ACLs. We need to go through all items to respect negative
168 uint32_t referer_perm
= current_perm
;
169 for (const auto& r
: referer_list
) {
170 if (r
.is_match(http_referer
)) {
171 referer_perm
= r
.perm
;
175 ldpp_dout(dpp
, 5) << "Found referer permission=" << referer_perm
<< dendl
;
176 return referer_perm
& perm_mask
;
179 uint32_t RGWAccessControlPolicy::get_perm(const DoutPrefixProvider
* dpp
,
180 const rgw::auth::Identity
& auth_identity
,
181 const uint32_t perm_mask
,
182 const char * const http_referer
,
183 bool ignore_public_acls
)
185 ldpp_dout(dpp
, 20) << "-- Getting permissions begin with perm_mask=" << perm_mask
188 uint32_t perm
= acl
.get_perm(dpp
, auth_identity
, perm_mask
);
190 if (auth_identity
.is_owner_of(owner
.get_id())) {
191 perm
|= perm_mask
& (RGW_PERM_READ_ACP
| RGW_PERM_WRITE_ACP
);
194 if (perm
== perm_mask
) {
198 /* should we continue looking up? */
199 if (!ignore_public_acls
&& ((perm
& perm_mask
) != perm_mask
)) {
200 perm
|= acl
.get_group_perm(dpp
, ACL_GROUP_ALL_USERS
, perm_mask
);
202 if (false == auth_identity
.is_owner_of(rgw_user(RGW_USER_ANON_ID
))) {
203 /* this is not the anonymous user */
204 perm
|= acl
.get_group_perm(dpp
, ACL_GROUP_AUTHENTICATED_USERS
, perm_mask
);
208 /* Should we continue looking up even deeper? */
209 if (nullptr != http_referer
&& (perm
& perm_mask
) != perm_mask
) {
210 perm
= acl
.get_referer_perm(dpp
, perm
, http_referer
, perm_mask
);
213 ldpp_dout(dpp
, 5) << "-- Getting permissions done for identity=" << auth_identity
214 << ", owner=" << owner
.get_id()
215 << ", perm=" << perm
<< dendl
;
220 bool RGWAccessControlPolicy::verify_permission(const DoutPrefixProvider
* dpp
,
221 const rgw::auth::Identity
& auth_identity
,
222 const uint32_t user_perm_mask
,
224 const char * const http_referer
,
225 bool ignore_public_acls
)
227 uint32_t test_perm
= perm
| RGW_PERM_READ_OBJS
| RGW_PERM_WRITE_OBJS
;
229 uint32_t policy_perm
= get_perm(dpp
, auth_identity
, test_perm
, http_referer
, ignore_public_acls
);
231 /* the swift WRITE_OBJS perm is equivalent to the WRITE obj, just
232 convert those bits. Note that these bits will only be set on
233 buckets, so the swift READ permission on bucket will allow listing
234 the bucket content */
235 if (policy_perm
& RGW_PERM_WRITE_OBJS
) {
236 policy_perm
|= (RGW_PERM_WRITE
| RGW_PERM_WRITE_ACP
);
238 if (policy_perm
& RGW_PERM_READ_OBJS
) {
239 policy_perm
|= (RGW_PERM_READ
| RGW_PERM_READ_ACP
);
242 uint32_t acl_perm
= policy_perm
& perm
& user_perm_mask
;
244 ldpp_dout(dpp
, 10) << " identity=" << auth_identity
245 << " requested perm (type)=" << perm
246 << ", policy perm=" << policy_perm
247 << ", user_perm_mask=" << user_perm_mask
248 << ", acl perm=" << acl_perm
<< dendl
;
250 return (perm
== acl_perm
);
254 bool RGWAccessControlPolicy::is_public(const DoutPrefixProvider
*dpp
) const
257 static constexpr auto public_groups
= {ACL_GROUP_ALL_USERS
,
258 ACL_GROUP_AUTHENTICATED_USERS
};
259 return std::any_of(public_groups
.begin(), public_groups
.end(),
260 [&, dpp
](ACLGroupTypeEnum g
) {
261 auto p
= acl
.get_group_perm(dpp
, g
, RGW_PERM_FULL_CONTROL
);
262 return (p
!= RGW_PERM_NONE
) && (p
!= RGW_PERM_INVALID
);
268 void ACLPermission::generate_test_instances(list
<ACLPermission
*>& o
)
270 ACLPermission
*p
= new ACLPermission
;
271 p
->set_permissions(RGW_PERM_WRITE_ACP
);
273 o
.push_back(new ACLPermission
);
276 void ACLPermission::dump(Formatter
*f
) const
278 f
->dump_int("flags", flags
);
281 void ACLGranteeType::dump(Formatter
*f
) const
283 f
->dump_unsigned("type", type
);
286 void ACLGrant::dump(Formatter
*f
) const
288 f
->open_object_section("type");
292 f
->dump_string("id", id
.to_str());
293 f
->dump_string("email", email
);
295 f
->open_object_section("permission");
299 f
->dump_string("name", name
);
300 f
->dump_int("group", (int)group
);
301 f
->dump_string("url_spec", url_spec
);
304 void ACLGrant::generate_test_instances(list
<ACLGrant
*>& o
)
311 ACLGrant
*g1
= new ACLGrant
;
312 g1
->set_canon(id
, name
, RGW_PERM_READ
);
316 ACLGrant
*g2
= new ACLGrant
;
317 g1
->set_group(ACL_GROUP_AUTHENTICATED_USERS
, RGW_PERM_WRITE
);
320 o
.push_back(new ACLGrant
);
323 void ACLGranteeType::generate_test_instances(list
<ACLGranteeType
*>& o
)
325 ACLGranteeType
*t
= new ACLGranteeType
;
326 t
->set(ACL_TYPE_CANON_USER
);
328 o
.push_back(new ACLGranteeType
);
331 void RGWAccessControlList::generate_test_instances(list
<RGWAccessControlList
*>& o
)
333 RGWAccessControlList
*acl
= new RGWAccessControlList(NULL
);
335 list
<ACLGrant
*> glist
;
336 list
<ACLGrant
*>::iterator iter
;
338 ACLGrant::generate_test_instances(glist
);
339 for (iter
= glist
.begin(); iter
!= glist
.end(); ++iter
) {
340 ACLGrant
*grant
= *iter
;
341 acl
->add_grant(grant
);
346 o
.push_back(new RGWAccessControlList(NULL
));
349 void ACLOwner::generate_test_instances(list
<ACLOwner
*>& o
)
351 ACLOwner
*owner
= new ACLOwner
;
353 owner
->display_name
= "Mr. RGW";
355 o
.push_back(new ACLOwner
);
358 void RGWAccessControlPolicy::generate_test_instances(list
<RGWAccessControlPolicy
*>& o
)
360 list
<RGWAccessControlList
*> acl_list
;
361 list
<RGWAccessControlList
*>::iterator iter
;
362 for (iter
= acl_list
.begin(); iter
!= acl_list
.end(); ++iter
) {
363 RGWAccessControlList::generate_test_instances(acl_list
);
364 iter
= acl_list
.begin();
366 RGWAccessControlPolicy
*p
= new RGWAccessControlPolicy(NULL
);
367 RGWAccessControlList
*l
= *iter
;
370 string name
= "radosgw";
372 p
->owner
.set_name(name
);
380 o
.push_back(new RGWAccessControlPolicy(NULL
));
383 void RGWAccessControlList::dump(Formatter
*f
) const
385 map
<string
, int>::const_iterator acl_user_iter
= acl_user_map
.begin();
386 f
->open_array_section("acl_user_map");
387 for (; acl_user_iter
!= acl_user_map
.end(); ++acl_user_iter
) {
388 f
->open_object_section("entry");
389 f
->dump_string("user", acl_user_iter
->first
);
390 f
->dump_int("acl", acl_user_iter
->second
);
395 map
<uint32_t, int>::const_iterator acl_group_iter
= acl_group_map
.begin();
396 f
->open_array_section("acl_group_map");
397 for (; acl_group_iter
!= acl_group_map
.end(); ++acl_group_iter
) {
398 f
->open_object_section("entry");
399 f
->dump_unsigned("group", acl_group_iter
->first
);
400 f
->dump_int("acl", acl_group_iter
->second
);
405 multimap
<string
, ACLGrant
>::const_iterator giter
= grant_map
.begin();
406 f
->open_array_section("grant_map");
407 for (; giter
!= grant_map
.end(); ++giter
) {
408 f
->open_object_section("entry");
409 f
->dump_string("id", giter
->first
);
410 f
->open_object_section("grant");
411 giter
->second
.dump(f
);
418 void ACLOwner::dump(Formatter
*f
) const
420 encode_json("id", id
.to_str(), f
);
421 encode_json("display_name", display_name
, f
);
424 void ACLOwner::decode_json(JSONObj
*obj
) {
426 JSONDecoder::decode_json("id", id_str
, obj
);
428 JSONDecoder::decode_json("display_name", display_name
, obj
);
431 void RGWAccessControlPolicy::dump(Formatter
*f
) const
433 encode_json("acl", acl
, f
);
434 encode_json("owner", owner
, f
);
437 ACLGroupTypeEnum
ACLGrant::uri_to_group(string
& uri
)
439 // this is required for backward compatibility
440 return ACLGrant_S3::uri_to_group(uri
);