initial code repo
[stor4nfv.git] / src / ceph / src / rgw / rgw_acl.cc
diff --git a/src/ceph/src/rgw/rgw_acl.cc b/src/ceph/src/rgw/rgw_acl.cc
new file mode 100644 (file)
index 0000000..0f24670
--- /dev/null
@@ -0,0 +1,172 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include <string.h>
+
+#include <iostream>
+#include <map>
+
+#include "include/types.h"
+
+#include "common/Formatter.h"
+
+#include "rgw_acl.h"
+#include "rgw_user.h"
+
+#define dout_subsys ceph_subsys_rgw
+
+using namespace std;
+
+void RGWAccessControlList::_add_grant(ACLGrant *grant)
+{
+  ACLPermission& perm = grant->get_permission();
+  ACLGranteeType& type = grant->get_type();
+  switch (type.get_type()) {
+  case ACL_TYPE_REFERER:
+    referer_list.emplace_back(grant->get_referer(), perm.get_permissions());
+
+    /* We're specially handling the Swift's .r:* as the S3 API has a similar
+     * concept and thus we can have a small portion of compatibility here. */
+     if (grant->get_referer() == RGW_REFERER_WILDCARD) {
+       acl_group_map[ACL_GROUP_ALL_USERS] |= perm.get_permissions();
+     }
+    break;
+  case ACL_TYPE_GROUP:
+    acl_group_map[grant->get_group()] |= perm.get_permissions();
+    break;
+  default:
+    {
+      rgw_user id;
+      if (!grant->get_id(id)) {
+        ldout(cct, 0) << "ERROR: grant->get_id() failed" << dendl;
+      }
+      acl_user_map[id.to_str()] |= perm.get_permissions();
+    }
+  }
+}
+
+void RGWAccessControlList::add_grant(ACLGrant *grant)
+{
+  rgw_user id;
+  grant->get_id(id); // not that this will return false for groups, but that's ok, we won't search groups
+  grant_map.insert(pair<string, ACLGrant>(id.to_str(), *grant));
+  _add_grant(grant);
+}
+
+uint32_t RGWAccessControlList::get_perm(const rgw::auth::Identity& auth_identity,
+                                        const uint32_t perm_mask)
+{
+  ldout(cct, 5) << "Searching permissions for identity=" << auth_identity
+                << " mask=" << perm_mask << dendl;
+
+  return perm_mask & auth_identity.get_perms_from_aclspec(acl_user_map);
+}
+
+uint32_t RGWAccessControlList::get_group_perm(ACLGroupTypeEnum group,
+                                              const uint32_t perm_mask)
+{
+  ldout(cct, 5) << "Searching permissions for group=" << (int)group
+                << " mask=" << perm_mask << dendl;
+
+  const auto iter = acl_group_map.find((uint32_t)group);
+  if (iter != acl_group_map.end()) {
+    ldout(cct, 5) << "Found permission: " << iter->second << dendl;
+    return iter->second & perm_mask;
+  }
+  ldout(cct, 5) << "Permissions for group not found" << dendl;
+  return 0;
+}
+
+uint32_t RGWAccessControlList::get_referer_perm(const uint32_t current_perm,
+                                                const std::string http_referer,
+                                                const uint32_t perm_mask)
+{
+  ldout(cct, 5) << "Searching permissions for referer=" << http_referer
+                << " mask=" << perm_mask << dendl;
+
+  /* This function is bacically a transformation from current perm to
+   * a new one that takes into consideration the Swift's HTTP referer-
+   * based ACLs. We need to go through all items to respect negative
+   * grants. */
+  uint32_t referer_perm = current_perm;
+  for (const auto& r : referer_list) {
+    if (r.is_match(http_referer)) {
+       referer_perm = r.perm;
+    }
+  }
+
+  ldout(cct, 5) << "Found referer permission=" << referer_perm << dendl;
+  return referer_perm & perm_mask;
+}
+
+uint32_t RGWAccessControlPolicy::get_perm(const rgw::auth::Identity& auth_identity,
+                                          const uint32_t perm_mask,
+                                          const char * const http_referer)
+{
+  ldout(cct, 20) << "-- Getting permissions begin with perm_mask=" << perm_mask
+                 << dendl;
+
+  uint32_t perm = acl.get_perm(auth_identity, perm_mask);
+
+  if (auth_identity.is_owner_of(owner.get_id())) {
+    perm |= perm_mask & (RGW_PERM_READ_ACP | RGW_PERM_WRITE_ACP);
+  }
+
+  if (perm == perm_mask) {
+    return perm;
+  }
+
+  /* should we continue looking up? */
+  if ((perm & perm_mask) != perm_mask) {
+    perm |= acl.get_group_perm(ACL_GROUP_ALL_USERS, perm_mask);
+
+    if (false == auth_identity.is_owner_of(rgw_user(RGW_USER_ANON_ID))) {
+      /* this is not the anonymous user */
+      perm |= acl.get_group_perm(ACL_GROUP_AUTHENTICATED_USERS, perm_mask);
+    }
+  }
+
+  /* Should we continue looking up even deeper? */
+  if (nullptr != http_referer && (perm & perm_mask) != perm_mask) {
+    perm = acl.get_referer_perm(perm, http_referer, perm_mask);
+  }
+
+  ldout(cct, 5) << "-- Getting permissions done for identity=" << auth_identity
+                << ", owner=" << owner.get_id()
+                << ", perm=" << perm << dendl;
+
+  return perm;
+}
+
+bool RGWAccessControlPolicy::verify_permission(const rgw::auth::Identity& auth_identity,
+                                               const uint32_t user_perm_mask,
+                                               const uint32_t perm,
+                                               const char * const http_referer)
+{
+  uint32_t test_perm = perm | RGW_PERM_READ_OBJS | RGW_PERM_WRITE_OBJS;
+
+  uint32_t policy_perm = get_perm(auth_identity, test_perm, http_referer);
+
+  /* the swift WRITE_OBJS perm is equivalent to the WRITE obj, just
+     convert those bits. Note that these bits will only be set on
+     buckets, so the swift READ permission on bucket will allow listing
+     the bucket content */
+  if (policy_perm & RGW_PERM_WRITE_OBJS) {
+    policy_perm |= (RGW_PERM_WRITE | RGW_PERM_WRITE_ACP);
+  }
+  if (policy_perm & RGW_PERM_READ_OBJS) {
+    policy_perm |= (RGW_PERM_READ | RGW_PERM_READ_ACP);
+  }
+   
+  uint32_t acl_perm = policy_perm & perm & user_perm_mask;
+
+  ldout(cct, 10) << " identity=" << auth_identity
+                 << " requested perm (type)=" << perm
+                 << ", policy perm=" << policy_perm
+                 << ", user_perm_mask=" << user_perm_mask
+                 << ", acl perm=" << acl_perm << dendl;
+
+  return (perm == acl_perm);
+}
+
+