Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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