Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / rgw / rgw_acl_s3.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 "rgw_acl_s3.h"
12 #include "rgw_user.h"
13
14 #define dout_subsys ceph_subsys_rgw
15
16 using namespace std;
17
18
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"
21
22 static string rgw_uri_all_users = RGW_URI_ALL_USERS;
23 static string rgw_uri_auth_users = RGW_URI_AUTH_USERS;
24
25 void ACLPermission_S3::to_xml(ostream& out)
26 {
27   if ((flags & RGW_PERM_FULL_CONTROL) == RGW_PERM_FULL_CONTROL) {
28    out << "<Permission>FULL_CONTROL</Permission>";
29   } else {
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>";
38   }
39 }
40
41 bool ACLPermission_S3::
42 xml_end(const char *el)
43 {
44   const char *s = data.c_str();
45   if (strcasecmp(s, "READ") == 0) {
46     flags |= RGW_PERM_READ;
47     return true;
48   } else if (strcasecmp(s, "WRITE") == 0) {
49     flags |= RGW_PERM_WRITE;
50     return true;
51   } else if (strcasecmp(s, "READ_ACP") == 0) {
52     flags |= RGW_PERM_READ_ACP;
53     return true;
54   } else if (strcasecmp(s, "WRITE_ACP") == 0) {
55     flags |= RGW_PERM_WRITE_ACP;
56     return true;
57   } else if (strcasecmp(s, "FULL_CONTROL") == 0) {
58     flags |= RGW_PERM_FULL_CONTROL;
59     return true;
60   }
61   return false;
62 }
63
64
65 class ACLGranteeType_S3 {
66 public:
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";
73     case ACL_TYPE_GROUP:
74       return "Group";
75      default:
76       return "unknown";
77     }
78   }
79
80   static void set(const char *s, ACLGranteeType& type) {
81     if (!s) {
82       type.set(ACL_TYPE_UNKNOWN);
83       return;
84     }
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);
91     else
92       type.set(ACL_TYPE_UNKNOWN);
93   }
94 };
95
96 class ACLID_S3 : public XMLObj
97 {
98 public:
99   ACLID_S3() {}
100   ~ACLID_S3() override {}
101   string& to_str() { return data; }
102 };
103
104 class ACLURI_S3 : public XMLObj
105 {
106 public:
107   ACLURI_S3() {}
108   ~ACLURI_S3() override {}
109 };
110
111 class ACLEmail_S3 : public XMLObj
112 {
113 public:
114   ACLEmail_S3() {}
115   ~ACLEmail_S3() override {}
116 };
117
118 class ACLDisplayName_S3 : public XMLObj
119 {
120 public:
121  ACLDisplayName_S3() {}
122  ~ACLDisplayName_S3() override {}
123 };
124
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"));
128
129   // ID is mandatory
130   if (!acl_id)
131     return false;
132   id = acl_id->get_data();
133
134   // DisplayName is optional
135   if (acl_name)
136     display_name = acl_name->get_data();
137   else
138     display_name = "";
139
140   return true;
141 }
142
143 void  ACLOwner_S3::to_xml(ostream& out) {
144   string s;
145   id.to_str(s);
146   if (s.empty())
147     return;
148   out << "<Owner>" << "<ID>" << s << "</ID>";
149   if (!display_name.empty())
150     out << "<DisplayName>" << display_name << "</DisplayName>";
151   out << "</Owner>";
152 }
153
154 bool ACLGrant_S3::xml_end(const char *el) {
155   ACLGrantee_S3 *acl_grantee;
156   ACLID_S3 *acl_id;
157   ACLURI_S3 *acl_uri;
158   ACLEmail_S3 *acl_email;
159   ACLPermission_S3 *acl_permission;
160   ACLDisplayName_S3 *acl_name;
161   string uri;
162
163   acl_grantee = static_cast<ACLGrantee_S3 *>(find_first("Grantee"));
164   if (!acl_grantee)
165     return false;
166   string type_str;
167   if (!acl_grantee->get_attr("xsi:type", type_str))
168     return false;
169   ACLGranteeType_S3::set(type_str.c_str(), type);
170   
171   acl_permission = static_cast<ACLPermission_S3 *>(find_first("Permission"));
172   if (!acl_permission)
173     return false;
174
175   permission = *acl_permission;
176
177   id.clear();
178   name.clear();
179   email.clear();
180
181   switch (type.get_type()) {
182   case ACL_TYPE_CANON_USER:
183     acl_id = static_cast<ACLID_S3 *>(acl_grantee->find_first("ID"));
184     if (!acl_id)
185       return false;
186     id = acl_id->to_str();
187     acl_name = static_cast<ACLDisplayName_S3 *>(acl_grantee->find_first("DisplayName"));
188     if (acl_name)
189       name = acl_name->get_data();
190     break;
191   case ACL_TYPE_GROUP:
192     acl_uri = static_cast<ACLURI_S3 *>(acl_grantee->find_first("URI"));
193     if (!acl_uri)
194       return false;
195     uri = acl_uri->get_data();
196     group = uri_to_group(uri);
197     break;
198   case ACL_TYPE_EMAIL_USER:
199     acl_email = static_cast<ACLEmail_S3 *>(acl_grantee->find_first("EmailAddress"));
200     if (!acl_email)
201       return false;
202     email = acl_email->get_data();
203     break;
204   default:
205     // unknown user type
206     return false;
207   };
208   return true;
209 }
210
211 void ACLGrant_S3::to_xml(CephContext *cct, ostream& out) {
212   ACLPermission_S3& perm = static_cast<ACLPermission_S3 &>(permission);
213
214   /* only show s3 compatible permissions */
215   if (!(perm.get_permissions() & RGW_PERM_ALL_S3))
216     return;
217
218   string uri;
219
220   out << "<Grant>" <<
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>";
225     if (name.size()) {
226       out << "<DisplayName>" << name << "</DisplayName>";
227     }
228     break;
229   case ACL_TYPE_EMAIL_USER:
230     out << "<EmailAddress>" << email << "</EmailAddress>";
231     break;
232   case ACL_TYPE_GROUP:
233     if (!group_to_uri(group, uri)) {
234       ldout(cct, 0) << "ERROR: group_to_uri failed with group=" << (int)group << dendl;
235       break;
236     }
237     out << "<URI>" << uri << "</URI>";
238     break;
239   default:
240     break;
241   }
242   out << "</Grantee>";
243   perm.to_xml(out);
244   out << "</Grant>";
245 }
246
247 bool ACLGrant_S3::group_to_uri(ACLGroupTypeEnum group, string& uri)
248 {
249   switch (group) {
250   case ACL_GROUP_ALL_USERS:
251     uri = rgw_uri_all_users;
252     return true;
253   case ACL_GROUP_AUTHENTICATED_USERS:
254     uri = rgw_uri_auth_users;
255     return true;
256   default:
257     return false;
258   }
259 }
260
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());
264   while (grant) {
265     add_grant(grant);
266     grant = static_cast<ACLGrant_S3 *>(iter.get_next());
267   }
268   return true;
269 }
270
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);
277   }
278   out << "</AccessControlList>";
279 }
280
281 struct s3_acl_header {
282   int rgw_perm;
283   const char *http_header;
284 };
285
286 static const char *get_acl_header(const RGWEnv *env,
287         const struct s3_acl_header *perm)
288 {
289   const char *header = perm->http_header;
290
291   return env->get(header, NULL);
292 }
293
294 static int parse_grantee_str(RGWRados *store, string& grantee_str,
295         const struct s3_acl_header *perm, ACLGrant& grant)
296 {
297   string id_type, id_val_quoted;
298   int rgw_perm = perm->rgw_perm;
299   int ret;
300
301   RGWUserInfo info;
302
303   ret = parse_key_value(grantee_str, id_type, id_val_quoted);
304   if (ret < 0)
305     return ret;
306
307   string id_val = rgw_trim_quotes(id_val_quoted);
308
309   if (strcasecmp(id_type.c_str(), "emailAddress") == 0) {
310     ret = rgw_get_user_info_by_email(store, id_val, info);
311     if (ret < 0)
312       return ret;
313
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);
318     if (ret < 0)
319       return ret;
320
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)
325       return -EINVAL;
326
327     grant.set_group(gid, rgw_perm);
328   } else {
329     return -EINVAL;
330   }
331
332   return 0;
333 }
334
335 static int parse_acl_header(RGWRados *store, const RGWEnv *env,
336          const struct s3_acl_header *perm, std::list<ACLGrant>& _grants)
337 {
338   std::list<string> grantees;
339   std::string hacl_str;
340
341   const char *hacl = get_acl_header(env, perm);
342   if (hacl == NULL)
343     return 0;
344
345   hacl_str = hacl;
346   get_str_list(hacl_str, ",", grantees);
347
348   for (list<string>::iterator it = grantees.begin(); it != grantees.end(); ++it) {
349     ACLGrant grant;
350     int ret = parse_grantee_str(store, *it, perm, grant);
351     if (ret < 0)
352       return ret;
353
354     _grants.push_back(grant);
355   }
356
357   return 0;
358 }
359
360 int RGWAccessControlList_S3::create_canned(ACLOwner& owner, ACLOwner& bucket_owner, const string& canned_acl)
361 {
362   acl_user_map.clear();
363   grant_map.clear();
364
365   ACLGrant owner_grant;
366
367   rgw_user bid = bucket_owner.get_id();
368   string bname = bucket_owner.get_display_name();
369
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);
373
374   if (canned_acl.size() == 0 || canned_acl.compare("private") == 0) {
375     return 0;
376   }
377
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);
399   } else {
400     return -EINVAL;
401   }
402
403   return 0;
404 }
405
406 int RGWAccessControlList_S3::create_from_grants(std::list<ACLGrant>& grants)
407 {
408   if (grants.empty())
409     return -EINVAL;
410
411   acl_user_map.clear();
412   grant_map.clear();
413
414   for (std::list<ACLGrant>::iterator it = grants.begin(); it != grants.end(); ++it) {
415     ACLGrant g = *it;
416     add_grant(&g);
417   }
418
419   return 0;
420 }
421
422 bool RGWAccessControlPolicy_S3::xml_end(const char *el) {
423   RGWAccessControlList_S3 *s3acl =
424       static_cast<RGWAccessControlList_S3 *>(find_first("AccessControlList"));
425   if (!s3acl)
426     return false;
427
428   acl = *s3acl;
429
430   ACLOwner *owner_p = static_cast<ACLOwner_S3 *>(find_first("Owner"));
431   if (!owner_p)
432     return false;
433   owner = *owner_p;
434   return true;
435 }
436
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);
441   _owner.to_xml(out);
442   _acl.to_xml(out);
443   out << "</AccessControlPolicy>";
444 }
445
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"},
452   {0, NULL}
453 };
454
455 int RGWAccessControlPolicy_S3::create_from_headers(RGWRados *store, const RGWEnv *env, ACLOwner& _owner)
456 {
457   std::list<ACLGrant> grants;
458
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)
461       return false;
462   }
463
464   RGWAccessControlList_S3& _acl = static_cast<RGWAccessControlList_S3 &>(acl);
465   int r = _acl.create_from_grants(grants);
466
467   owner = _owner;
468
469   return r;
470 }
471
472 /*
473   can only be called on object that was parsed
474  */
475 int RGWAccessControlPolicy_S3::rebuild(RGWRados *store, ACLOwner *owner, RGWAccessControlPolicy& dest)
476 {
477   if (!owner)
478     return -EINVAL;
479
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)
484       return -EPERM;
485   }
486
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;
490     return -EINVAL;
491   }
492   ACLOwner& dest_owner = dest.get_owner();
493   dest_owner.set_id(owner->get_id());
494   dest_owner.set_name(owner_info.display_name);
495
496   ldout(cct, 20) << "owner id=" << owner->get_id() << dendl;
497   ldout(cct, 20) << "dest owner id=" << dest.get_owner().get_id() << dendl;
498
499   RGWAccessControlList& dst_acl = dest.get_acl();
500
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();
506     ACLGrant new_grant;
507     bool grant_ok = false;
508     rgw_user uid;
509     RGWUserInfo grant_user;
510     switch (type.get_type()) {
511     case ACL_TYPE_EMAIL_USER:
512       {
513         string email;
514         rgw_user u;
515         if (!src_grant.get_id(u)) {
516           ldout(cct, 0) << "ERROR: src_grant.get_id() failed" << dendl;
517           return -EINVAL;
518         }
519         email = u.id;
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;
524         }
525         uid = grant_user.user_id;
526       }
527     case ACL_TYPE_CANON_USER:
528       {
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;
532             return -EINVAL;
533           }
534         }
535     
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;
538           return -EINVAL;
539         } else {
540           ACLPermission& perm = src_grant.get_permission();
541           new_grant.set_canon(uid, grant_user.display_name, perm.get_permissions());
542           grant_ok = true;
543           rgw_user new_id;
544           new_grant.get_id(new_id);
545           ldout(cct, 10) << "new grant: " << new_id << ":" << grant_user.display_name << dendl;
546         }
547       }
548       break;
549     case ACL_TYPE_GROUP:
550       {
551         string uri;
552         if (ACLGrant_S3::group_to_uri(src_grant.get_group(), uri)) {
553           new_grant = src_grant;
554           grant_ok = true;
555           ldout(cct, 10) << "new grant: " << uri << dendl;
556         } else {
557           ldout(cct, 10) << "bad grant group:" << (int)src_grant.get_group() << dendl;
558           return -EINVAL;
559         }
560       }
561     default:
562       break;
563     }
564     if (grant_ok) {
565       dst_acl.add_grant(&new_grant);
566     }
567   }
568
569   return 0; 
570 }
571
572 bool RGWAccessControlPolicy_S3::compare_group_name(string& id, ACLGroupTypeEnum group)
573 {
574   switch (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);
579   default:
580     return id.empty();
581   }
582
583   // shouldn't get here
584   return false;
585 }
586
587 XMLObj *RGWACLXMLParser_S3::alloc_obj(const char *el)
588 {
589   XMLObj * obj = NULL;
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();
610   }
611
612   return obj;
613 }
614