]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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()); | |
31f18b77 FG |
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 | } | |
7c673cae FG |
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 | ||
31f18b77 FG |
80 | uint32_t RGWAccessControlList::get_referer_perm(const uint32_t current_perm, |
81 | const std::string http_referer, | |
7c673cae FG |
82 | const uint32_t perm_mask) |
83 | { | |
84 | ldout(cct, 5) << "Searching permissions for referer=" << http_referer | |
85 | << " mask=" << perm_mask << dendl; | |
86 | ||
31f18b77 FG |
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; | |
7c673cae | 95 | } |
7c673cae | 96 | } |
31f18b77 FG |
97 | |
98 | ldout(cct, 5) << "Found referer permission=" << referer_perm << dendl; | |
99 | return referer_perm & perm_mask; | |
7c673cae FG |
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) { | |
31f18b77 | 131 | perm = acl.get_referer_perm(perm, http_referer, perm_mask); |
7c673cae FG |
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 |