1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
9 #include "include/types.h"
11 #include "rgw_acl_s3.h"
15 #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"
24 static string rgw_uri_all_users
= RGW_URI_ALL_USERS
;
25 static string rgw_uri_auth_users
= RGW_URI_AUTH_USERS
;
27 void ACLPermission_S3::to_xml(ostream
& out
)
29 if ((flags
& RGW_PERM_FULL_CONTROL
) == RGW_PERM_FULL_CONTROL
) {
30 out
<< "<Permission>FULL_CONTROL</Permission>";
32 if (flags
& RGW_PERM_READ
)
33 out
<< "<Permission>READ</Permission>";
34 if (flags
& RGW_PERM_WRITE
)
35 out
<< "<Permission>WRITE</Permission>";
36 if (flags
& RGW_PERM_READ_ACP
)
37 out
<< "<Permission>READ_ACP</Permission>";
38 if (flags
& RGW_PERM_WRITE_ACP
)
39 out
<< "<Permission>WRITE_ACP</Permission>";
43 bool ACLPermission_S3::
44 xml_end(const char *el
)
46 const char *s
= data
.c_str();
47 if (strcasecmp(s
, "READ") == 0) {
48 flags
|= RGW_PERM_READ
;
50 } else if (strcasecmp(s
, "WRITE") == 0) {
51 flags
|= RGW_PERM_WRITE
;
53 } else if (strcasecmp(s
, "READ_ACP") == 0) {
54 flags
|= RGW_PERM_READ_ACP
;
56 } else if (strcasecmp(s
, "WRITE_ACP") == 0) {
57 flags
|= RGW_PERM_WRITE_ACP
;
59 } else if (strcasecmp(s
, "FULL_CONTROL") == 0) {
60 flags
|= RGW_PERM_FULL_CONTROL
;
67 class ACLGranteeType_S3
{
69 static const char *to_string(ACLGranteeType
& type
) {
70 switch (type
.get_type()) {
71 case ACL_TYPE_CANON_USER
:
72 return "CanonicalUser";
73 case ACL_TYPE_EMAIL_USER
:
74 return "AmazonCustomerByEmail";
82 static void set(const char *s
, ACLGranteeType
& type
) {
84 type
.set(ACL_TYPE_UNKNOWN
);
87 if (strcmp(s
, "CanonicalUser") == 0)
88 type
.set(ACL_TYPE_CANON_USER
);
89 else if (strcmp(s
, "AmazonCustomerByEmail") == 0)
90 type
.set(ACL_TYPE_EMAIL_USER
);
91 else if (strcmp(s
, "Group") == 0)
92 type
.set(ACL_TYPE_GROUP
);
94 type
.set(ACL_TYPE_UNKNOWN
);
98 class ACLID_S3
: public XMLObj
102 ~ACLID_S3() override
{}
103 string
& to_str() { return data
; }
106 class ACLURI_S3
: public XMLObj
110 ~ACLURI_S3() override
{}
113 class ACLEmail_S3
: public XMLObj
117 ~ACLEmail_S3() override
{}
120 class ACLDisplayName_S3
: public XMLObj
123 ACLDisplayName_S3() {}
124 ~ACLDisplayName_S3() override
{}
127 bool ACLOwner_S3::xml_end(const char *el
) {
128 ACLID_S3
*acl_id
= static_cast<ACLID_S3
*>(find_first("ID"));
129 ACLID_S3
*acl_name
= static_cast<ACLID_S3
*>(find_first("DisplayName"));
134 id
= acl_id
->get_data();
136 // DisplayName is optional
138 display_name
= acl_name
->get_data();
145 void ACLOwner_S3::to_xml(ostream
& out
) {
150 out
<< "<Owner>" << "<ID>" << s
<< "</ID>";
151 if (!display_name
.empty())
152 out
<< "<DisplayName>" << display_name
<< "</DisplayName>";
156 bool ACLGrant_S3::xml_end(const char *el
) {
157 ACLGrantee_S3
*acl_grantee
;
160 ACLEmail_S3
*acl_email
;
161 ACLPermission_S3
*acl_permission
;
162 ACLDisplayName_S3
*acl_name
;
165 acl_grantee
= static_cast<ACLGrantee_S3
*>(find_first("Grantee"));
169 if (!acl_grantee
->get_attr("xsi:type", type_str
))
171 ACLGranteeType_S3::set(type_str
.c_str(), type
);
173 acl_permission
= static_cast<ACLPermission_S3
*>(find_first("Permission"));
177 permission
= *acl_permission
;
183 switch (type
.get_type()) {
184 case ACL_TYPE_CANON_USER
:
185 acl_id
= static_cast<ACLID_S3
*>(acl_grantee
->find_first("ID"));
188 id
= acl_id
->to_str();
189 acl_name
= static_cast<ACLDisplayName_S3
*>(acl_grantee
->find_first("DisplayName"));
191 name
= acl_name
->get_data();
194 acl_uri
= static_cast<ACLURI_S3
*>(acl_grantee
->find_first("URI"));
197 uri
= acl_uri
->get_data();
198 group
= uri_to_group(uri
);
200 case ACL_TYPE_EMAIL_USER
:
201 acl_email
= static_cast<ACLEmail_S3
*>(acl_grantee
->find_first("EmailAddress"));
204 email
= acl_email
->get_data();
213 void ACLGrant_S3::to_xml(CephContext
*cct
, ostream
& out
) {
214 ACLPermission_S3
& perm
= static_cast<ACLPermission_S3
&>(permission
);
216 /* only show s3 compatible permissions */
217 if (!(perm
.get_permissions() & RGW_PERM_ALL_S3
))
223 "<Grantee xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"" << ACLGranteeType_S3::to_string(type
) << "\">";
224 switch (type
.get_type()) {
225 case ACL_TYPE_CANON_USER
:
226 out
<< "<ID>" << id
<< "</ID>";
228 out
<< "<DisplayName>" << name
<< "</DisplayName>";
231 case ACL_TYPE_EMAIL_USER
:
232 out
<< "<EmailAddress>" << email
<< "</EmailAddress>";
235 if (!group_to_uri(group
, uri
)) {
236 ldout(cct
, 0) << "ERROR: group_to_uri failed with group=" << (int)group
<< dendl
;
239 out
<< "<URI>" << uri
<< "</URI>";
249 bool ACLGrant_S3::group_to_uri(ACLGroupTypeEnum group
, string
& uri
)
252 case ACL_GROUP_ALL_USERS
:
253 uri
= rgw_uri_all_users
;
255 case ACL_GROUP_AUTHENTICATED_USERS
:
256 uri
= rgw_uri_auth_users
;
263 bool RGWAccessControlList_S3::xml_end(const char *el
) {
264 XMLObjIter iter
= find("Grant");
265 ACLGrant_S3
*grant
= static_cast<ACLGrant_S3
*>(iter
.get_next());
268 grant
= static_cast<ACLGrant_S3
*>(iter
.get_next());
273 void RGWAccessControlList_S3::to_xml(ostream
& out
) {
274 multimap
<string
, ACLGrant
>::iterator iter
;
275 out
<< "<AccessControlList>";
276 for (iter
= grant_map
.begin(); iter
!= grant_map
.end(); ++iter
) {
277 ACLGrant_S3
& grant
= static_cast<ACLGrant_S3
&>(iter
->second
);
278 grant
.to_xml(cct
, out
);
280 out
<< "</AccessControlList>";
283 struct s3_acl_header
{
285 const char *http_header
;
288 static const char *get_acl_header(const RGWEnv
*env
,
289 const struct s3_acl_header
*perm
)
291 const char *header
= perm
->http_header
;
293 return env
->get(header
, NULL
);
296 static int parse_grantee_str(const DoutPrefixProvider
*dpp
, rgw::sal::Store
* store
, string
& grantee_str
,
297 const struct s3_acl_header
*perm
, ACLGrant
& grant
)
299 string id_type
, id_val_quoted
;
300 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 std::unique_ptr
<rgw::sal::User
> user
;
311 ret
= store
->get_user_by_email(dpp
, id_val
, null_yield
, &user
);
315 grant
.set_canon(user
->get_id(), user
->get_display_name(), rgw_perm
);
316 } else if (strcasecmp(id_type
.c_str(), "id") == 0) {
317 std::unique_ptr
<rgw::sal::User
> user
= store
->get_user(rgw_user(id_val
));
318 ret
= user
->load_user(dpp
, null_yield
);
322 grant
.set_canon(user
->get_id(), user
->get_display_name(), rgw_perm
);
323 } else if (strcasecmp(id_type
.c_str(), "uri") == 0) {
324 ACLGroupTypeEnum gid
= grant
.uri_to_group(id_val
);
325 if (gid
== ACL_GROUP_NONE
)
328 grant
.set_group(gid
, rgw_perm
);
336 static int parse_acl_header(const DoutPrefixProvider
*dpp
, rgw::sal::Store
* store
,
337 const RGWEnv
*env
, const struct s3_acl_header
*perm
,
338 std::list
<ACLGrant
>& _grants
)
340 std::list
<string
> grantees
;
341 std::string hacl_str
;
343 const char *hacl
= get_acl_header(env
, perm
);
348 get_str_list(hacl_str
, ",", grantees
);
350 for (list
<string
>::iterator it
= grantees
.begin(); it
!= grantees
.end(); ++it
) {
352 int ret
= parse_grantee_str(dpp
, store
, *it
, perm
, grant
);
356 _grants
.push_back(grant
);
362 int RGWAccessControlList_S3::create_canned(ACLOwner
& owner
, ACLOwner
& bucket_owner
, const string
& canned_acl
)
364 acl_user_map
.clear();
367 ACLGrant owner_grant
;
369 rgw_user bid
= bucket_owner
.get_id();
370 string bname
= bucket_owner
.get_display_name();
372 /* owner gets full control */
373 owner_grant
.set_canon(owner
.get_id(), owner
.get_display_name(), RGW_PERM_FULL_CONTROL
);
374 add_grant(&owner_grant
);
376 if (canned_acl
.size() == 0 || canned_acl
.compare("private") == 0) {
380 ACLGrant bucket_owner_grant
;
381 ACLGrant group_grant
;
382 if (canned_acl
.compare("public-read") == 0) {
383 group_grant
.set_group(ACL_GROUP_ALL_USERS
, RGW_PERM_READ
);
384 add_grant(&group_grant
);
385 } else if (canned_acl
.compare("public-read-write") == 0) {
386 group_grant
.set_group(ACL_GROUP_ALL_USERS
, RGW_PERM_READ
);
387 add_grant(&group_grant
);
388 group_grant
.set_group(ACL_GROUP_ALL_USERS
, RGW_PERM_WRITE
);
389 add_grant(&group_grant
);
390 } else if (canned_acl
.compare("authenticated-read") == 0) {
391 group_grant
.set_group(ACL_GROUP_AUTHENTICATED_USERS
, RGW_PERM_READ
);
392 add_grant(&group_grant
);
393 } else if (canned_acl
.compare("bucket-owner-read") == 0) {
394 bucket_owner_grant
.set_canon(bid
, bname
, RGW_PERM_READ
);
395 if (bid
.compare(owner
.get_id()) != 0)
396 add_grant(&bucket_owner_grant
);
397 } else if (canned_acl
.compare("bucket-owner-full-control") == 0) {
398 bucket_owner_grant
.set_canon(bid
, bname
, RGW_PERM_FULL_CONTROL
);
399 if (bid
.compare(owner
.get_id()) != 0)
400 add_grant(&bucket_owner_grant
);
408 int RGWAccessControlList_S3::create_from_grants(std::list
<ACLGrant
>& grants
)
413 acl_user_map
.clear();
416 for (std::list
<ACLGrant
>::iterator it
= grants
.begin(); it
!= grants
.end(); ++it
) {
424 bool RGWAccessControlPolicy_S3::xml_end(const char *el
) {
425 RGWAccessControlList_S3
*s3acl
=
426 static_cast<RGWAccessControlList_S3
*>(find_first("AccessControlList"));
432 ACLOwner
*owner_p
= static_cast<ACLOwner_S3
*>(find_first("Owner"));
439 void RGWAccessControlPolicy_S3::to_xml(ostream
& out
) {
440 out
<< "<AccessControlPolicy xmlns=\"" << XMLNS_AWS_S3
<< "\">";
441 ACLOwner_S3
& _owner
= static_cast<ACLOwner_S3
&>(owner
);
442 RGWAccessControlList_S3
& _acl
= static_cast<RGWAccessControlList_S3
&>(acl
);
445 out
<< "</AccessControlPolicy>";
448 static const s3_acl_header acl_header_perms
[] = {
449 {RGW_PERM_READ
, "HTTP_X_AMZ_GRANT_READ"},
450 {RGW_PERM_WRITE
, "HTTP_X_AMZ_GRANT_WRITE"},
451 {RGW_PERM_READ_ACP
,"HTTP_X_AMZ_GRANT_READ_ACP"},
452 {RGW_PERM_WRITE_ACP
, "HTTP_X_AMZ_GRANT_WRITE_ACP"},
453 {RGW_PERM_FULL_CONTROL
, "HTTP_X_AMZ_GRANT_FULL_CONTROL"},
457 int RGWAccessControlPolicy_S3::create_from_headers(const DoutPrefixProvider
*dpp
,
458 rgw::sal::Store
* store
,
459 const RGWEnv
*env
, ACLOwner
& _owner
)
461 std::list
<ACLGrant
> grants
;
464 for (const struct s3_acl_header
*p
= acl_header_perms
; p
->rgw_perm
; p
++) {
465 r
= parse_acl_header(dpp
, store
, env
, p
, grants
);
471 RGWAccessControlList_S3
& _acl
= static_cast<RGWAccessControlList_S3
&>(acl
);
472 r
= _acl
.create_from_grants(grants
);
480 can only be called on object that was parsed
482 int RGWAccessControlPolicy_S3::rebuild(const DoutPrefixProvider
*dpp
,
483 rgw::sal::Store
* store
, ACLOwner
*owner
,
484 RGWAccessControlPolicy
& dest
, std::string
&err_msg
)
489 ACLOwner
*requested_owner
= static_cast<ACLOwner_S3
*>(find_first("Owner"));
490 if (requested_owner
) {
491 rgw_user
& requested_id
= requested_owner
->get_id();
492 if (!requested_id
.empty() && requested_id
.compare(owner
->get_id()) != 0)
496 std::unique_ptr
<rgw::sal::User
> user
= store
->get_user(owner
->get_id());
497 if (user
->load_user(dpp
, null_yield
) < 0) {
498 ldpp_dout(dpp
, 10) << "owner info does not exist" << dendl
;
499 err_msg
= "Invalid id";
502 ACLOwner
& dest_owner
= dest
.get_owner();
503 dest_owner
.set_id(owner
->get_id());
504 dest_owner
.set_name(user
->get_display_name());
506 ldpp_dout(dpp
, 20) << "owner id=" << owner
->get_id() << dendl
;
507 ldpp_dout(dpp
, 20) << "dest owner id=" << dest
.get_owner().get_id() << dendl
;
509 RGWAccessControlList
& dst_acl
= dest
.get_acl();
511 multimap
<string
, ACLGrant
>& grant_map
= acl
.get_grant_map();
512 multimap
<string
, ACLGrant
>::iterator iter
;
513 for (iter
= grant_map
.begin(); iter
!= grant_map
.end(); ++iter
) {
514 ACLGrant
& src_grant
= iter
->second
;
515 ACLGranteeType
& type
= src_grant
.get_type();
517 bool grant_ok
= false;
519 RGWUserInfo grant_user
;
520 switch (type
.get_type()) {
521 case ACL_TYPE_EMAIL_USER
:
525 if (!src_grant
.get_id(u
)) {
526 ldpp_dout(dpp
, 0) << "ERROR: src_grant.get_id() failed" << dendl
;
530 ldpp_dout(dpp
, 10) << "grant user email=" << email
<< dendl
;
531 if (store
->get_user_by_email(dpp
, email
, null_yield
, &user
) < 0) {
532 ldpp_dout(dpp
, 10) << "grant user email not found or other error" << dendl
;
533 err_msg
= "The e-mail address you provided does not match any account on record.";
534 return -ERR_UNRESOLVABLE_EMAIL
;
536 grant_user
= user
->get_info();
537 uid
= grant_user
.user_id
;
539 case ACL_TYPE_CANON_USER
:
541 if (type
.get_type() == ACL_TYPE_CANON_USER
) {
542 if (!src_grant
.get_id(uid
)) {
543 ldpp_dout(dpp
, 0) << "ERROR: src_grant.get_id() failed" << dendl
;
544 err_msg
= "Invalid id";
549 if (grant_user
.user_id
.empty()) {
550 user
= store
->get_user(uid
);
551 if (user
->load_user(dpp
, null_yield
) < 0) {
552 ldpp_dout(dpp
, 10) << "grant user does not exist:" << uid
<< dendl
;
553 err_msg
= "Invalid id";
556 grant_user
= user
->get_info();
559 ACLPermission
& perm
= src_grant
.get_permission();
560 new_grant
.set_canon(uid
, grant_user
.display_name
, perm
.get_permissions());
563 new_grant
.get_id(new_id
);
564 ldpp_dout(dpp
, 10) << "new grant: " << new_id
<< ":" << grant_user
.display_name
<< dendl
;
570 if (ACLGrant_S3::group_to_uri(src_grant
.get_group(), uri
)) {
571 new_grant
= src_grant
;
573 ldpp_dout(dpp
, 10) << "new grant: " << uri
<< dendl
;
575 ldpp_dout(dpp
, 10) << "bad grant group:" << (int)src_grant
.get_group() << dendl
;
576 err_msg
= "Invalid group uri";
584 dst_acl
.add_grant(&new_grant
);
591 bool RGWAccessControlPolicy_S3::compare_group_name(string
& id
, ACLGroupTypeEnum group
)
594 case ACL_GROUP_ALL_USERS
:
595 return (id
.compare(RGW_USER_ANON_ID
) == 0);
596 case ACL_GROUP_AUTHENTICATED_USERS
:
597 return (id
.compare(rgw_uri_auth_users
) == 0);
602 // shouldn't get here
606 XMLObj
*RGWACLXMLParser_S3::alloc_obj(const char *el
)
609 if (strcmp(el
, "AccessControlPolicy") == 0) {
610 obj
= new RGWAccessControlPolicy_S3(cct
);
611 } else if (strcmp(el
, "Owner") == 0) {
612 obj
= new ACLOwner_S3();
613 } else if (strcmp(el
, "AccessControlList") == 0) {
614 obj
= new RGWAccessControlList_S3(cct
);
615 } else if (strcmp(el
, "ID") == 0) {
616 obj
= new ACLID_S3();
617 } else if (strcmp(el
, "DisplayName") == 0) {
618 obj
= new ACLDisplayName_S3();
619 } else if (strcmp(el
, "Grant") == 0) {
620 obj
= new ACLGrant_S3();
621 } else if (strcmp(el
, "Grantee") == 0) {
622 obj
= new ACLGrantee_S3();
623 } else if (strcmp(el
, "Permission") == 0) {
624 obj
= new ACLPermission_S3();
625 } else if (strcmp(el
, "URI") == 0) {
626 obj
= new ACLURI_S3();
627 } else if (strcmp(el
, "EmailAddress") == 0) {
628 obj
= new ACLEmail_S3();
634 ACLGroupTypeEnum
ACLGrant_S3::uri_to_group(string
& uri
)
636 if (uri
.compare(rgw_uri_all_users
) == 0)
637 return ACL_GROUP_ALL_USERS
;
638 else if (uri
.compare(rgw_uri_auth_users
) == 0)
639 return ACL_GROUP_AUTHENTICATED_USERS
;
641 return ACL_GROUP_NONE
;