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 "rgw_acl_s3.h"
14 #define dout_subsys ceph_subsys_rgw
19 #define RGW_URI_ALL_USERS "http://acs.amazonaws.com/groups/global/AllUsers"
20 #define RGW_URI_AUTH_USERS "http://acs.amazonaws.com/groups/global/AuthenticatedUsers"
22 static string rgw_uri_all_users = RGW_URI_ALL_USERS;
23 static string rgw_uri_auth_users = RGW_URI_AUTH_USERS;
25 void ACLPermission_S3::to_xml(ostream& out)
27 if ((flags & RGW_PERM_FULL_CONTROL) == RGW_PERM_FULL_CONTROL) {
28 out << "<Permission>FULL_CONTROL</Permission>";
30 if (flags & RGW_PERM_READ)
31 out << "<Permission>READ</Permission>";
32 if (flags & RGW_PERM_WRITE)
33 out << "<Permission>WRITE</Permission>";
34 if (flags & RGW_PERM_READ_ACP)
35 out << "<Permission>READ_ACP</Permission>";
36 if (flags & RGW_PERM_WRITE_ACP)
37 out << "<Permission>WRITE_ACP</Permission>";
41 bool ACLPermission_S3::
42 xml_end(const char *el)
44 const char *s = data.c_str();
45 if (strcasecmp(s, "READ") == 0) {
46 flags |= RGW_PERM_READ;
48 } else if (strcasecmp(s, "WRITE") == 0) {
49 flags |= RGW_PERM_WRITE;
51 } else if (strcasecmp(s, "READ_ACP") == 0) {
52 flags |= RGW_PERM_READ_ACP;
54 } else if (strcasecmp(s, "WRITE_ACP") == 0) {
55 flags |= RGW_PERM_WRITE_ACP;
57 } else if (strcasecmp(s, "FULL_CONTROL") == 0) {
58 flags |= RGW_PERM_FULL_CONTROL;
65 class ACLGranteeType_S3 {
67 static const char *to_string(ACLGranteeType& type) {
68 switch (type.get_type()) {
69 case ACL_TYPE_CANON_USER:
70 return "CanonicalUser";
71 case ACL_TYPE_EMAIL_USER:
72 return "AmazonCustomerByEmail";
80 static void set(const char *s, ACLGranteeType& type) {
82 type.set(ACL_TYPE_UNKNOWN);
85 if (strcmp(s, "CanonicalUser") == 0)
86 type.set(ACL_TYPE_CANON_USER);
87 else if (strcmp(s, "AmazonCustomerByEmail") == 0)
88 type.set(ACL_TYPE_EMAIL_USER);
89 else if (strcmp(s, "Group") == 0)
90 type.set(ACL_TYPE_GROUP);
92 type.set(ACL_TYPE_UNKNOWN);
96 class ACLID_S3 : public XMLObj
100 ~ACLID_S3() override {}
101 string& to_str() { return data; }
104 class ACLURI_S3 : public XMLObj
108 ~ACLURI_S3() override {}
111 class ACLEmail_S3 : public XMLObj
115 ~ACLEmail_S3() override {}
118 class ACLDisplayName_S3 : public XMLObj
121 ACLDisplayName_S3() {}
122 ~ACLDisplayName_S3() override {}
125 bool ACLOwner_S3::xml_end(const char *el) {
126 ACLID_S3 *acl_id = static_cast<ACLID_S3 *>(find_first("ID"));
127 ACLID_S3 *acl_name = static_cast<ACLID_S3 *>(find_first("DisplayName"));
132 id = acl_id->get_data();
134 // DisplayName is optional
136 display_name = acl_name->get_data();
143 void ACLOwner_S3::to_xml(ostream& out) {
148 out << "<Owner>" << "<ID>" << s << "</ID>";
149 if (!display_name.empty())
150 out << "<DisplayName>" << display_name << "</DisplayName>";
154 bool ACLGrant_S3::xml_end(const char *el) {
155 ACLGrantee_S3 *acl_grantee;
158 ACLEmail_S3 *acl_email;
159 ACLPermission_S3 *acl_permission;
160 ACLDisplayName_S3 *acl_name;
163 acl_grantee = static_cast<ACLGrantee_S3 *>(find_first("Grantee"));
167 if (!acl_grantee->get_attr("xsi:type", type_str))
169 ACLGranteeType_S3::set(type_str.c_str(), type);
171 acl_permission = static_cast<ACLPermission_S3 *>(find_first("Permission"));
175 permission = *acl_permission;
181 switch (type.get_type()) {
182 case ACL_TYPE_CANON_USER:
183 acl_id = static_cast<ACLID_S3 *>(acl_grantee->find_first("ID"));
186 id = acl_id->to_str();
187 acl_name = static_cast<ACLDisplayName_S3 *>(acl_grantee->find_first("DisplayName"));
189 name = acl_name->get_data();
192 acl_uri = static_cast<ACLURI_S3 *>(acl_grantee->find_first("URI"));
195 uri = acl_uri->get_data();
196 group = uri_to_group(uri);
198 case ACL_TYPE_EMAIL_USER:
199 acl_email = static_cast<ACLEmail_S3 *>(acl_grantee->find_first("EmailAddress"));
202 email = acl_email->get_data();
211 void ACLGrant_S3::to_xml(CephContext *cct, ostream& out) {
212 ACLPermission_S3& perm = static_cast<ACLPermission_S3 &>(permission);
214 /* only show s3 compatible permissions */
215 if (!(perm.get_permissions() & RGW_PERM_ALL_S3))
221 "<Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"" << ACLGranteeType_S3::to_string(type) << "\">";
222 switch (type.get_type()) {
223 case ACL_TYPE_CANON_USER:
224 out << "<ID>" << id << "</ID>";
226 out << "<DisplayName>" << name << "</DisplayName>";
229 case ACL_TYPE_EMAIL_USER:
230 out << "<EmailAddress>" << email << "</EmailAddress>";
233 if (!group_to_uri(group, uri)) {
234 ldout(cct, 0) << "ERROR: group_to_uri failed with group=" << (int)group << dendl;
237 out << "<URI>" << uri << "</URI>";
247 bool ACLGrant_S3::group_to_uri(ACLGroupTypeEnum group, string& uri)
250 case ACL_GROUP_ALL_USERS:
251 uri = rgw_uri_all_users;
253 case ACL_GROUP_AUTHENTICATED_USERS:
254 uri = rgw_uri_auth_users;
261 bool RGWAccessControlList_S3::xml_end(const char *el) {
262 XMLObjIter iter = find("Grant");
263 ACLGrant_S3 *grant = static_cast<ACLGrant_S3 *>(iter.get_next());
266 grant = static_cast<ACLGrant_S3 *>(iter.get_next());
271 void RGWAccessControlList_S3::to_xml(ostream& out) {
272 multimap<string, ACLGrant>::iterator iter;
273 out << "<AccessControlList>";
274 for (iter = grant_map.begin(); iter != grant_map.end(); ++iter) {
275 ACLGrant_S3& grant = static_cast<ACLGrant_S3 &>(iter->second);
276 grant.to_xml(cct, out);
278 out << "</AccessControlList>";
281 struct s3_acl_header {
283 const char *http_header;
286 static const char *get_acl_header(const RGWEnv *env,
287 const struct s3_acl_header *perm)
289 const char *header = perm->http_header;
291 return env->get(header, NULL);
294 static int parse_grantee_str(RGWRados *store, string& grantee_str,
295 const struct s3_acl_header *perm, ACLGrant& grant)
297 string id_type, id_val_quoted;
298 int rgw_perm = perm->rgw_perm;
303 ret = parse_key_value(grantee_str, id_type, id_val_quoted);
307 string id_val = rgw_trim_quotes(id_val_quoted);
309 if (strcasecmp(id_type.c_str(), "emailAddress") == 0) {
310 ret = rgw_get_user_info_by_email(store, id_val, info);
314 grant.set_canon(info.user_id, info.display_name, rgw_perm);
315 } else if (strcasecmp(id_type.c_str(), "id") == 0) {
316 rgw_user user(id_val);
317 ret = rgw_get_user_info_by_uid(store, user, info);
321 grant.set_canon(info.user_id, info.display_name, rgw_perm);
322 } else if (strcasecmp(id_type.c_str(), "uri") == 0) {
323 ACLGroupTypeEnum gid = grant.uri_to_group(id_val);
324 if (gid == ACL_GROUP_NONE)
327 grant.set_group(gid, rgw_perm);
335 static int parse_acl_header(RGWRados *store, const RGWEnv *env,
336 const struct s3_acl_header *perm, std::list<ACLGrant>& _grants)
338 std::list<string> grantees;
339 std::string hacl_str;
341 const char *hacl = get_acl_header(env, perm);
346 get_str_list(hacl_str, ",", grantees);
348 for (list<string>::iterator it = grantees.begin(); it != grantees.end(); ++it) {
350 int ret = parse_grantee_str(store, *it, perm, grant);
354 _grants.push_back(grant);
360 int RGWAccessControlList_S3::create_canned(ACLOwner& owner, ACLOwner& bucket_owner, const string& canned_acl)
362 acl_user_map.clear();
365 ACLGrant owner_grant;
367 rgw_user bid = bucket_owner.get_id();
368 string bname = bucket_owner.get_display_name();
370 /* owner gets full control */
371 owner_grant.set_canon(owner.get_id(), owner.get_display_name(), RGW_PERM_FULL_CONTROL);
372 add_grant(&owner_grant);
374 if (canned_acl.size() == 0 || canned_acl.compare("private") == 0) {
378 ACLGrant bucket_owner_grant;
379 ACLGrant group_grant;
380 if (canned_acl.compare("public-read") == 0) {
381 group_grant.set_group(ACL_GROUP_ALL_USERS, RGW_PERM_READ);
382 add_grant(&group_grant);
383 } else if (canned_acl.compare("public-read-write") == 0) {
384 group_grant.set_group(ACL_GROUP_ALL_USERS, RGW_PERM_READ);
385 add_grant(&group_grant);
386 group_grant.set_group(ACL_GROUP_ALL_USERS, RGW_PERM_WRITE);
387 add_grant(&group_grant);
388 } else if (canned_acl.compare("authenticated-read") == 0) {
389 group_grant.set_group(ACL_GROUP_AUTHENTICATED_USERS, RGW_PERM_READ);
390 add_grant(&group_grant);
391 } else if (canned_acl.compare("bucket-owner-read") == 0) {
392 bucket_owner_grant.set_canon(bid, bname, RGW_PERM_READ);
393 if (bid.compare(owner.get_id()) != 0)
394 add_grant(&bucket_owner_grant);
395 } else if (canned_acl.compare("bucket-owner-full-control") == 0) {
396 bucket_owner_grant.set_canon(bid, bname, RGW_PERM_FULL_CONTROL);
397 if (bid.compare(owner.get_id()) != 0)
398 add_grant(&bucket_owner_grant);
406 int RGWAccessControlList_S3::create_from_grants(std::list<ACLGrant>& grants)
411 acl_user_map.clear();
414 for (std::list<ACLGrant>::iterator it = grants.begin(); it != grants.end(); ++it) {
422 bool RGWAccessControlPolicy_S3::xml_end(const char *el) {
423 RGWAccessControlList_S3 *s3acl =
424 static_cast<RGWAccessControlList_S3 *>(find_first("AccessControlList"));
430 ACLOwner *owner_p = static_cast<ACLOwner_S3 *>(find_first("Owner"));
437 void RGWAccessControlPolicy_S3::to_xml(ostream& out) {
438 out << "<AccessControlPolicy xmlns=\"" << XMLNS_AWS_S3 << "\">";
439 ACLOwner_S3& _owner = static_cast<ACLOwner_S3 &>(owner);
440 RGWAccessControlList_S3& _acl = static_cast<RGWAccessControlList_S3 &>(acl);
443 out << "</AccessControlPolicy>";
446 static const s3_acl_header acl_header_perms[] = {
447 {RGW_PERM_READ, "HTTP_X_AMZ_GRANT_READ"},
448 {RGW_PERM_WRITE, "HTTP_X_AMZ_GRANT_WRITE"},
449 {RGW_PERM_READ_ACP,"HTTP_X_AMZ_GRANT_READ_ACP"},
450 {RGW_PERM_WRITE_ACP, "HTTP_X_AMZ_GRANT_WRITE_ACP"},
451 {RGW_PERM_FULL_CONTROL, "HTTP_X_AMZ_GRANT_FULL_CONTROL"},
455 int RGWAccessControlPolicy_S3::create_from_headers(RGWRados *store, const RGWEnv *env, ACLOwner& _owner)
457 std::list<ACLGrant> grants;
459 for (const struct s3_acl_header *p = acl_header_perms; p->rgw_perm; p++) {
460 if (parse_acl_header(store, env, p, grants) < 0)
464 RGWAccessControlList_S3& _acl = static_cast<RGWAccessControlList_S3 &>(acl);
465 int r = _acl.create_from_grants(grants);
473 can only be called on object that was parsed
475 int RGWAccessControlPolicy_S3::rebuild(RGWRados *store, ACLOwner *owner, RGWAccessControlPolicy& dest)
480 ACLOwner *requested_owner = static_cast<ACLOwner_S3 *>(find_first("Owner"));
481 if (requested_owner) {
482 rgw_user& requested_id = requested_owner->get_id();
483 if (!requested_id.empty() && requested_id.compare(owner->get_id()) != 0)
487 RGWUserInfo owner_info;
488 if (rgw_get_user_info_by_uid(store, owner->get_id(), owner_info) < 0) {
489 ldout(cct, 10) << "owner info does not exist" << dendl;
492 ACLOwner& dest_owner = dest.get_owner();
493 dest_owner.set_id(owner->get_id());
494 dest_owner.set_name(owner_info.display_name);
496 ldout(cct, 20) << "owner id=" << owner->get_id() << dendl;
497 ldout(cct, 20) << "dest owner id=" << dest.get_owner().get_id() << dendl;
499 RGWAccessControlList& dst_acl = dest.get_acl();
501 multimap<string, ACLGrant>& grant_map = acl.get_grant_map();
502 multimap<string, ACLGrant>::iterator iter;
503 for (iter = grant_map.begin(); iter != grant_map.end(); ++iter) {
504 ACLGrant& src_grant = iter->second;
505 ACLGranteeType& type = src_grant.get_type();
507 bool grant_ok = false;
509 RGWUserInfo grant_user;
510 switch (type.get_type()) {
511 case ACL_TYPE_EMAIL_USER:
515 if (!src_grant.get_id(u)) {
516 ldout(cct, 0) << "ERROR: src_grant.get_id() failed" << dendl;
520 ldout(cct, 10) << "grant user email=" << email << dendl;
521 if (rgw_get_user_info_by_email(store, email, grant_user) < 0) {
522 ldout(cct, 10) << "grant user email not found or other error" << dendl;
523 return -ERR_UNRESOLVABLE_EMAIL;
525 uid = grant_user.user_id;
527 case ACL_TYPE_CANON_USER:
529 if (type.get_type() == ACL_TYPE_CANON_USER) {
530 if (!src_grant.get_id(uid)) {
531 ldout(cct, 0) << "ERROR: src_grant.get_id() failed" << dendl;
536 if (grant_user.user_id.empty() && rgw_get_user_info_by_uid(store, uid, grant_user) < 0) {
537 ldout(cct, 10) << "grant user does not exist:" << uid << dendl;
540 ACLPermission& perm = src_grant.get_permission();
541 new_grant.set_canon(uid, grant_user.display_name, perm.get_permissions());
544 new_grant.get_id(new_id);
545 ldout(cct, 10) << "new grant: " << new_id << ":" << grant_user.display_name << dendl;
552 if (ACLGrant_S3::group_to_uri(src_grant.get_group(), uri)) {
553 new_grant = src_grant;
555 ldout(cct, 10) << "new grant: " << uri << dendl;
557 ldout(cct, 10) << "bad grant group:" << (int)src_grant.get_group() << dendl;
565 dst_acl.add_grant(&new_grant);
572 bool RGWAccessControlPolicy_S3::compare_group_name(string& id, ACLGroupTypeEnum group)
575 case ACL_GROUP_ALL_USERS:
576 return (id.compare(RGW_USER_ANON_ID) == 0);
577 case ACL_GROUP_AUTHENTICATED_USERS:
578 return (id.compare(rgw_uri_auth_users) == 0);
583 // shouldn't get here
587 XMLObj *RGWACLXMLParser_S3::alloc_obj(const char *el)
590 if (strcmp(el, "AccessControlPolicy") == 0) {
591 obj = new RGWAccessControlPolicy_S3(cct);
592 } else if (strcmp(el, "Owner") == 0) {
593 obj = new ACLOwner_S3();
594 } else if (strcmp(el, "AccessControlList") == 0) {
595 obj = new RGWAccessControlList_S3(cct);
596 } else if (strcmp(el, "ID") == 0) {
597 obj = new ACLID_S3();
598 } else if (strcmp(el, "DisplayName") == 0) {
599 obj = new ACLDisplayName_S3();
600 } else if (strcmp(el, "Grant") == 0) {
601 obj = new ACLGrant_S3();
602 } else if (strcmp(el, "Grantee") == 0) {
603 obj = new ACLGrantee_S3();
604 } else if (strcmp(el, "Permission") == 0) {
605 obj = new ACLPermission_S3();
606 } else if (strcmp(el, "URI") == 0) {
607 obj = new ACLURI_S3();
608 } else if (strcmp(el, "EmailAddress") == 0) {
609 obj = new ACLEmail_S3();