]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_acl.cc
update sources to v12.1.0
[ceph.git] / ceph / src / rgw / rgw_acl.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include <string.h>
5
6 #include <iostream>
7 #include <map>
8
9 #include "include/types.h"
10
11 #include "common/Formatter.h"
12
13 #include "rgw_acl.h"
14 #include "rgw_user.h"
15
16 #define dout_subsys ceph_subsys_rgw
17
18 using namespace std;
19
20 void RGWAccessControlList::_add_grant(ACLGrant *grant)
21 {
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());
27
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();
32 }
33 break;
34 case ACL_TYPE_GROUP:
35 acl_group_map[grant->get_group()] |= perm.get_permissions();
36 break;
37 default:
38 {
39 rgw_user id;
40 if (!grant->get_id(id)) {
41 ldout(cct, 0) << "ERROR: grant->get_id() failed" << dendl;
42 }
43 acl_user_map[id.to_str()] |= perm.get_permissions();
44 }
45 }
46 }
47
48 void RGWAccessControlList::add_grant(ACLGrant *grant)
49 {
50 rgw_user id;
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));
53 _add_grant(grant);
54 }
55
56 uint32_t RGWAccessControlList::get_perm(const rgw::auth::Identity& auth_identity,
57 const uint32_t perm_mask)
58 {
59 ldout(cct, 5) << "Searching permissions for identity=" << auth_identity
60 << " mask=" << perm_mask << dendl;
61
62 return perm_mask & auth_identity.get_perms_from_aclspec(acl_user_map);
63 }
64
65 uint32_t RGWAccessControlList::get_group_perm(ACLGroupTypeEnum group,
66 const uint32_t perm_mask)
67 {
68 ldout(cct, 5) << "Searching permissions for group=" << (int)group
69 << " mask=" << perm_mask << dendl;
70
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;
75 }
76 ldout(cct, 5) << "Permissions for group not found" << dendl;
77 return 0;
78 }
79
80 uint32_t RGWAccessControlList::get_referer_perm(const uint32_t current_perm,
81 const std::string http_referer,
82 const uint32_t perm_mask)
83 {
84 ldout(cct, 5) << "Searching permissions for referer=" << http_referer
85 << " mask=" << perm_mask << dendl;
86
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
90 * grants. */
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;
95 }
96 }
97
98 ldout(cct, 5) << "Found referer permission=" << referer_perm << dendl;
99 return referer_perm & perm_mask;
100 }
101
102 uint32_t RGWAccessControlPolicy::get_perm(const rgw::auth::Identity& auth_identity,
103 const uint32_t perm_mask,
104 const char * const http_referer)
105 {
106 ldout(cct, 20) << "-- Getting permissions begin with perm_mask=" << perm_mask
107 << dendl;
108
109 uint32_t perm = acl.get_perm(auth_identity, perm_mask);
110
111 if (auth_identity.is_owner_of(owner.get_id())) {
112 perm |= perm_mask & (RGW_PERM_READ_ACP | RGW_PERM_WRITE_ACP);
113 }
114
115 if (perm == perm_mask) {
116 return perm;
117 }
118
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);
122
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);
126 }
127 }
128
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);
132 }
133
134 ldout(cct, 5) << "-- Getting permissions done for identity=" << auth_identity
135 << ", owner=" << owner.get_id()
136 << ", perm=" << perm << dendl;
137
138 return perm;
139 }
140
141 bool RGWAccessControlPolicy::verify_permission(const rgw::auth::Identity& auth_identity,
142 const uint32_t user_perm_mask,
143 const uint32_t perm,
144 const char * const http_referer)
145 {
146 uint32_t test_perm = perm | RGW_PERM_READ_OBJS | RGW_PERM_WRITE_OBJS;
147
148 uint32_t policy_perm = get_perm(auth_identity, test_perm, http_referer);
149
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);
156 }
157 if (policy_perm & RGW_PERM_READ_OBJS) {
158 policy_perm |= (RGW_PERM_READ | RGW_PERM_READ_ACP);
159 }
160
161 uint32_t acl_perm = policy_perm & perm & user_perm_mask;
162
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;
168
169 return (perm == acl_perm);
170 }
171
172