1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
9 #include "include/types.h"
11 #include "common/Formatter.h"
16 #define dout_subsys ceph_subsys_rgw
20 void RGWAccessControlList::_add_grant(ACLGrant
*grant
)
22 ACLPermission
& perm
= grant
->get_permission();
23 ACLGranteeType
& type
= grant
->get_type();
24 switch (type
.get_type()) {
25 case ACL_TYPE_REFERER
:
26 referer_list
.emplace_back(grant
->get_referer(), perm
.get_permissions());
28 /* We're specially handling the Swift's .r:* as the S3 API has a similar
29 * concept and thus we can have a small portion of compatibility here. */
30 if (grant
->get_referer() == RGW_REFERER_WILDCARD
) {
31 acl_group_map
[ACL_GROUP_ALL_USERS
] |= perm
.get_permissions();
35 acl_group_map
[grant
->get_group()] |= perm
.get_permissions();
40 if (!grant
->get_id(id
)) {
41 ldout(cct
, 0) << "ERROR: grant->get_id() failed" << dendl
;
43 acl_user_map
[id
.to_str()] |= perm
.get_permissions();
48 void RGWAccessControlList::add_grant(ACLGrant
*grant
)
51 grant
->get_id(id
); // not that this will return false for groups, but that's ok, we won't search groups
52 grant_map
.insert(pair
<string
, ACLGrant
>(id
.to_str(), *grant
));
56 uint32_t RGWAccessControlList::get_perm(const rgw::auth::Identity
& auth_identity
,
57 const uint32_t perm_mask
)
59 ldout(cct
, 5) << "Searching permissions for identity=" << auth_identity
60 << " mask=" << perm_mask
<< dendl
;
62 return perm_mask
& auth_identity
.get_perms_from_aclspec(acl_user_map
);
65 uint32_t RGWAccessControlList::get_group_perm(ACLGroupTypeEnum group
,
66 const uint32_t perm_mask
)
68 ldout(cct
, 5) << "Searching permissions for group=" << (int)group
69 << " mask=" << perm_mask
<< dendl
;
71 const auto iter
= acl_group_map
.find((uint32_t)group
);
72 if (iter
!= acl_group_map
.end()) {
73 ldout(cct
, 5) << "Found permission: " << iter
->second
<< dendl
;
74 return iter
->second
& perm_mask
;
76 ldout(cct
, 5) << "Permissions for group not found" << dendl
;
80 uint32_t RGWAccessControlList::get_referer_perm(const uint32_t current_perm
,
81 const std::string http_referer
,
82 const uint32_t perm_mask
)
84 ldout(cct
, 5) << "Searching permissions for referer=" << http_referer
85 << " mask=" << perm_mask
<< dendl
;
87 /* This function is bacically a transformation from current perm to
88 * a new one that takes into consideration the Swift's HTTP referer-
89 * based ACLs. We need to go through all items to respect negative
91 uint32_t referer_perm
= current_perm
;
92 for (const auto& r
: referer_list
) {
93 if (r
.is_match(http_referer
)) {
94 referer_perm
= r
.perm
;
98 ldout(cct
, 5) << "Found referer permission=" << referer_perm
<< dendl
;
99 return referer_perm
& perm_mask
;
102 uint32_t RGWAccessControlPolicy::get_perm(const rgw::auth::Identity
& auth_identity
,
103 const uint32_t perm_mask
,
104 const char * const http_referer
)
106 ldout(cct
, 20) << "-- Getting permissions begin with perm_mask=" << perm_mask
109 uint32_t perm
= acl
.get_perm(auth_identity
, perm_mask
);
111 if (auth_identity
.is_owner_of(owner
.get_id())) {
112 perm
|= perm_mask
& (RGW_PERM_READ_ACP
| RGW_PERM_WRITE_ACP
);
115 if (perm
== perm_mask
) {
119 /* should we continue looking up? */
120 if ((perm
& perm_mask
) != perm_mask
) {
121 perm
|= acl
.get_group_perm(ACL_GROUP_ALL_USERS
, perm_mask
);
123 if (false == auth_identity
.is_owner_of(rgw_user(RGW_USER_ANON_ID
))) {
124 /* this is not the anonymous user */
125 perm
|= acl
.get_group_perm(ACL_GROUP_AUTHENTICATED_USERS
, perm_mask
);
129 /* Should we continue looking up even deeper? */
130 if (nullptr != http_referer
&& (perm
& perm_mask
) != perm_mask
) {
131 perm
= acl
.get_referer_perm(perm
, http_referer
, perm_mask
);
134 ldout(cct
, 5) << "-- Getting permissions done for identity=" << auth_identity
135 << ", owner=" << owner
.get_id()
136 << ", perm=" << perm
<< dendl
;
141 bool RGWAccessControlPolicy::verify_permission(const rgw::auth::Identity
& auth_identity
,
142 const uint32_t user_perm_mask
,
144 const char * const http_referer
)
146 uint32_t test_perm
= perm
| RGW_PERM_READ_OBJS
| RGW_PERM_WRITE_OBJS
;
148 uint32_t policy_perm
= get_perm(auth_identity
, test_perm
, http_referer
);
150 /* the swift WRITE_OBJS perm is equivalent to the WRITE obj, just
151 convert those bits. Note that these bits will only be set on
152 buckets, so the swift READ permission on bucket will allow listing
153 the bucket content */
154 if (policy_perm
& RGW_PERM_WRITE_OBJS
) {
155 policy_perm
|= (RGW_PERM_WRITE
| RGW_PERM_WRITE_ACP
);
157 if (policy_perm
& RGW_PERM_READ_OBJS
) {
158 policy_perm
|= (RGW_PERM_READ
| RGW_PERM_READ_ACP
);
161 uint32_t acl_perm
= policy_perm
& perm
& user_perm_mask
;
163 ldout(cct
, 10) << " identity=" << auth_identity
164 << " requested perm (type)=" << perm
165 << ", policy perm=" << policy_perm
166 << ", user_perm_mask=" << user_perm_mask
167 << ", acl perm=" << acl_perm
<< dendl
;
169 return (perm
== acl_perm
);