374 lines
14 KiB
C
374 lines
14 KiB
C
|
|
// Copyright (c) 2013, IOnU Security, Inc.
|
||
|
|
// Copyright (c) 2016, Sequence Logic, Inc. All rights reserved.
|
||
|
|
|
||
|
|
/**
|
||
|
|
* The Permissions class...
|
||
|
|
*/
|
||
|
|
#ifndef PERMISSIONS
|
||
|
|
#define PERMISSIONS
|
||
|
|
|
||
|
|
#include "../../libeye/eyeconstants.h"
|
||
|
|
|
||
|
|
#include <vector>
|
||
|
|
#include <set>
|
||
|
|
#include <map>
|
||
|
|
#include <memory>
|
||
|
|
#include <string>
|
||
|
|
|
||
|
|
// If this is being included in the shell extension, don't decorate the class with DLL export/import
|
||
|
|
#if defined(WIN32) && !defined(SL_SHELL_EXT)
|
||
|
|
#ifdef SL_CPPCORE_DLLEXPORT
|
||
|
|
#define SL_CPPCORE_EXPORT __declspec(dllexport)
|
||
|
|
#else
|
||
|
|
#define SL_CPPCORE_EXPORT __declspec(dllimport)
|
||
|
|
#endif
|
||
|
|
#else
|
||
|
|
#define SL_CPPCORE_EXPORT
|
||
|
|
#endif
|
||
|
|
|
||
|
|
namespace sequencelogic
|
||
|
|
{
|
||
|
|
class CloudGuardURN;
|
||
|
|
|
||
|
|
typedef std::set<CloudGuardURN> CloudGuardURNSet;
|
||
|
|
typedef CloudGuardURNSet::iterator CloudGuardURNSetIter;
|
||
|
|
typedef std::map<CloudGuardURN, CloudGuardURNSet> CloudGuardURNToURNSetMap;
|
||
|
|
typedef CloudGuardURNToURNSetMap::iterator CloudGuardURNToURNSetMapIter;
|
||
|
|
typedef CloudGuardURNToURNSetMap::const_iterator CloudGuardURNToURNSetMapCIter;
|
||
|
|
|
||
|
|
class Permissions;
|
||
|
|
typedef std::shared_ptr<Permissions> PermissionsPtr;
|
||
|
|
|
||
|
|
class JSONArray;
|
||
|
|
typedef std::shared_ptr<JSONArray> JSONArrayPtr;
|
||
|
|
|
||
|
|
class JSONObject;
|
||
|
|
typedef std::shared_ptr<JSONObject> JSONObjectPtr;
|
||
|
|
|
||
|
|
#if defined(WIN32) || defined(_WIN32)
|
||
|
|
#pragma warning(push)
|
||
|
|
#pragma warning(disable:4251 4275) // Disable the dumbass XXXX needs to have dll-interface.
|
||
|
|
#endif
|
||
|
|
/**
|
||
|
|
* Permissions (the object and the concept) both track user rights to operations, and provide a host
|
||
|
|
* of methods to manipulate rights.
|
||
|
|
* <p>Every permissions object has an owner, which is a PMO UUID; this is not a full URN, but just the office
|
||
|
|
* identifier portion. Ownership cannot be changed, at present. So this also signifies the creator of
|
||
|
|
* any given permission object.
|
||
|
|
* <p>An authority can be set on a permissions instance. The authority is the PMO UUID on whose behalf
|
||
|
|
* a change is requested. Often, the owner and authority are the same ID. However, another user may be the
|
||
|
|
* authority, attempt to assign a rights value, and will only succeed if the authority in question has
|
||
|
|
* the Assign right for the actual right in question.
|
||
|
|
* <p>The rights are: read, readAssign, write, writeAssign, admin, adminAssign, doorway (out) and doorwayAssign
|
||
|
|
* and stream/streamAssign. Various methods below set, assign, check and validate these rights.
|
||
|
|
* <p>There is also hide and hideAssign which indicate that a file exists but cannot be displayed.
|
||
|
|
* <p>Any given right can be granted to "owner", a specific PMO UUID or a group identifier:
|
||
|
|
* <code>g@{van}:{pmo}:{device}:{groupDocID}</code>. Note that this form is not a fully qualified URN
|
||
|
|
* (it lacks the prefix "urn:sl:"). The group document URN identifies a set of users belonging to a group.
|
||
|
|
*
|
||
|
|
* @author tim, viggy
|
||
|
|
*/
|
||
|
|
class SL_CPPCORE_EXPORT Permissions
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
static const char* PERMISSION_KEYS[];
|
||
|
|
static const int NUM_PERMISSION_KEYS;
|
||
|
|
static const char SIGNATURE_KEY[];
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Construct with default permissions.
|
||
|
|
*/
|
||
|
|
Permissions();
|
||
|
|
Permissions(const PermissionsPtr pOrigObj);
|
||
|
|
Permissions(const std::string &permStr);
|
||
|
|
virtual ~Permissions() {}
|
||
|
|
Permissions(const Permissions &origObj);
|
||
|
|
Permissions(const JSONObject &origObj);
|
||
|
|
Permissions& operator=(const Permissions &rhs);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Comparison.
|
||
|
|
*/
|
||
|
|
bool operator==(const Permissions &rhs);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Construct from a parent object
|
||
|
|
* @param pParent
|
||
|
|
* @return
|
||
|
|
*/
|
||
|
|
static PermissionsPtr createFromParent(const JSONObject &parent);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Construct from a device local file.
|
||
|
|
* @param fileName
|
||
|
|
* @param ownerAuthority
|
||
|
|
* @return
|
||
|
|
*/
|
||
|
|
static PermissionsPtr createFromDeviceFile(const std::string &fileName, const CloudGuardURN &ownerAuthority);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Construct from a flattened non-json string.
|
||
|
|
* @param owner
|
||
|
|
* @param authority
|
||
|
|
* @param string read=something,else | write=something ...
|
||
|
|
* @return
|
||
|
|
*/
|
||
|
|
static PermissionsPtr createFromFlatString(const std::string &owner, const std::string &string, const std::string &authority = "");
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Creates a Permission object that references ONLY a single office. Typically this office
|
||
|
|
* will be the client office.
|
||
|
|
* @param pmoUrn
|
||
|
|
* @return
|
||
|
|
*/
|
||
|
|
static PermissionsPtr createFromOffice(const CloudGuardURN &pmoUrn);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Creates a Permission object that references a team
|
||
|
|
* @param teamUrn
|
||
|
|
* @return
|
||
|
|
*/
|
||
|
|
static PermissionsPtr createFromTeam(const CloudGuardURN &teamUrn);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Given two or more URNs, create Permissions object.
|
||
|
|
* At least one URN must NOT be a group. This function *will* reorder the vector (sorted by URN string)
|
||
|
|
* @param urns - at least two, with at least one being a non-group
|
||
|
|
* @return
|
||
|
|
*/
|
||
|
|
static PermissionsPtr createFromUrnList(std::vector<CloudGuardURN> &urns);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Incoming userPermissions is of form:
|
||
|
|
* <pre>
|
||
|
|
* {
|
||
|
|
* "id": "me",
|
||
|
|
* "role": "owner",
|
||
|
|
* "selfLink": "https:\/\/www.googleapis.com\/drive\/v2\/files\/0ByK--JTHkV6AZzB5LXlpR2RnMU0\/permissions\/me",
|
||
|
|
* "type": "user",
|
||
|
|
* "etag": "\"Q0cVodxX8sh4vfxZTlOyWcmmc0k\/m7evUIvideYSbzR6BMwMo0JTKWU\"",
|
||
|
|
* "kind": "drive#permission"
|
||
|
|
* },
|
||
|
|
* </pre>
|
||
|
|
* @param userPermissions
|
||
|
|
* @param ownerAuthority - if google perms indicate ownership of file then this will be assigned to our
|
||
|
|
* owner and authority; if we are NOT the owner, then those fields are NOT set
|
||
|
|
* @return
|
||
|
|
* @see https://developers.google.com/drive/v2/reference/permissions#resource
|
||
|
|
*/
|
||
|
|
static PermissionsPtr createFromGoogleUserPermissions(const std::shared_ptr<JSONObject> pUserPermissions, const CloudGuardURN &ownerAuthority);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Guarantee consistent ordering of hash keys...
|
||
|
|
* @return
|
||
|
|
*/
|
||
|
|
std::string toOrderedString() const;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* For UX display of short rights string.
|
||
|
|
* @param user
|
||
|
|
* @return
|
||
|
|
*/
|
||
|
|
std::string toRightsString(const std::string &user) const;
|
||
|
|
|
||
|
|
std::string rightsString(const std::string &perm, const std::string &user) const;
|
||
|
|
|
||
|
|
std::string getDigest() { return getPermittedRightsSignature(); }
|
||
|
|
std::string getPermittedRightsSignature();
|
||
|
|
/**
|
||
|
|
* Gets a 12 character digest (one way hash) of the ordered permissions. Identical (equivalent ignoring
|
||
|
|
* key ordering JSON issues and ignoring permissions) permissions will thus
|
||
|
|
* have the same digest value.
|
||
|
|
* @return
|
||
|
|
*/
|
||
|
|
std::string getSignature(const CloudGuardURN &van) const;
|
||
|
|
|
||
|
|
std::string getSignaturePath(const CloudGuardURN &van) const;
|
||
|
|
|
||
|
|
void getPermittedItems(const CloudGuardURN &van, JSONArray &permittedItems) const;
|
||
|
|
|
||
|
|
std::string getOrderedReferences(const CloudGuardURN &van) const;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Gets a set of referenced user values. This does NOT reference 'mbrs' data but inspects
|
||
|
|
* individual rights.
|
||
|
|
* @param van tell us what van we are operating within
|
||
|
|
* @param Return set, possibly empty list of group document URN's
|
||
|
|
*/
|
||
|
|
void getReferencedUsers(const CloudGuardURN &van, CloudGuardURNSet &referencedUsers) const;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Gets a set of referenced group values. This does NOT reference 'mbrs' data but inspects
|
||
|
|
* individual rights.
|
||
|
|
* @param Return set, possibly empty list of group document URN's
|
||
|
|
*/
|
||
|
|
void getReferencedGroups(CloudGuardURNSet &referencedGroups) const;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get all references, both users and groups (you need to check the group device ID to see what's
|
||
|
|
* a group and what is a normal user).
|
||
|
|
* @param van
|
||
|
|
*/
|
||
|
|
void getAllReferences(const CloudGuardURN &van, CloudGuardURNSet &allReferences) const;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Same results as getAllReferences but in JSONArray format with each element being a string.
|
||
|
|
* @param van
|
||
|
|
* @return
|
||
|
|
*/
|
||
|
|
JSONArrayPtr getAllReferencesAsStringArray (const CloudGuardURN &vanUrn) const;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Updates members array by adding all unique UUID values referenced by this object and
|
||
|
|
* any referenced groups. Membership simply means that you are named in a *some* permission.
|
||
|
|
* It's useful for indexing and having a list of everyone who can interact with a document.
|
||
|
|
*
|
||
|
|
* @param van - tell us van we are operating within
|
||
|
|
* @param groupMap - null (no group resolution) or map of group doc URN to UUID values.
|
||
|
|
* @param Return set of members (PMO urn's) - internal 'mbrs' array is also set on this object
|
||
|
|
*/
|
||
|
|
void updateMembers(const CloudGuardURN &van, const CloudGuardURNToURNSetMap &groupMap, CloudGuardURNSet &curMembers);
|
||
|
|
|
||
|
|
std::string getAuthority() const { return _authority; }
|
||
|
|
|
||
|
|
void setAuthority(const std::string &authority) { _authority = authority; }
|
||
|
|
|
||
|
|
void setOwner(const std::string &owner);
|
||
|
|
|
||
|
|
std::string getOwner() const;
|
||
|
|
|
||
|
|
std::string getName() const;
|
||
|
|
|
||
|
|
void setName(const std::string &name);
|
||
|
|
|
||
|
|
void setType(const std::string &type);
|
||
|
|
|
||
|
|
std::string getType() const;
|
||
|
|
|
||
|
|
bool isGroup() const;
|
||
|
|
|
||
|
|
bool canRead(const std::string &user) const;
|
||
|
|
bool canWrite(const std::string &user) const;
|
||
|
|
bool isAdmin(const std::string &user) const;
|
||
|
|
bool canDoorway(const std::string &user) const;
|
||
|
|
bool canStream(const std::string &user) const;
|
||
|
|
bool canHide(const std::string &user) const;
|
||
|
|
|
||
|
|
bool assignRead(const std::string &user);
|
||
|
|
bool assignRead(const std::vector<std::string> &users);
|
||
|
|
bool assignWrite(const std::string &user);
|
||
|
|
bool assignWrite(const std::vector<std::string> &users);
|
||
|
|
bool assignAdmin(const std::string &user);
|
||
|
|
bool assignAdmin(const std::vector<std::string> &users);
|
||
|
|
bool assignDoorway(const std::string &user);
|
||
|
|
bool assignDoorway(const std::vector<std::string> &users);
|
||
|
|
bool assignStream(const std::string &user);
|
||
|
|
bool assignStream(const std::vector<std::string> &users);
|
||
|
|
bool assignHide(const std::string &user);
|
||
|
|
bool assignHide(const std::vector<std::string> &users);
|
||
|
|
|
||
|
|
PermissionsPtr merge(const Permissions &permissions);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Merge, or copy, perms into this permissions object.
|
||
|
|
*/
|
||
|
|
void simpleMerge(const Permissions &perms);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Remove the indicated permission, ignoring any access/assignment rights checking.
|
||
|
|
* @param perm
|
||
|
|
* @param user
|
||
|
|
*/
|
||
|
|
void remove(const std::string &perm, const std::string &user);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Set the indicated permission, ignoring any access/assignment rights checking.
|
||
|
|
* @param perm
|
||
|
|
* @param user - no validation is performed on this value
|
||
|
|
*/
|
||
|
|
void set(const std::string &perm, const std::string &user);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Does the user have the indicated permission?
|
||
|
|
* @param obj
|
||
|
|
* @param perm either a perm (read) or assignment (readAssign)
|
||
|
|
* @param user
|
||
|
|
* @return
|
||
|
|
*/
|
||
|
|
static bool can(const Permissions &obj, const std::string &perm, const std::string &user, std::string *pWhyReturn = NULL);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Can the user assign a permission
|
||
|
|
* @param obj
|
||
|
|
* @param perm simple perm never with assignment suffix
|
||
|
|
* @param user
|
||
|
|
* @return
|
||
|
|
*/
|
||
|
|
static bool canAssign(const Permissions &obj, const std::string &perm, const std::string &user)
|
||
|
|
{ return canAssign(obj._pData.get(), perm, user); }
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Assign 'perm' to 'user', but only if 'auth' has assign* priv.
|
||
|
|
* @param obj - Permissions object
|
||
|
|
* @param perm -
|
||
|
|
* @param auth
|
||
|
|
* @param user - no validation is performed on this value
|
||
|
|
* @return true if assignment successful; false if it was not
|
||
|
|
*/
|
||
|
|
static bool assign(Permissions &obj, const std::string &perm, const std::string &auth, const std::string &user)
|
||
|
|
{ return assign(obj._pData.get(), perm, auth, user); }
|
||
|
|
static bool assign(Permissions &obj, const std::string &perm, const std::string &auth, const std::vector<std::string> &users)
|
||
|
|
{ return assign(obj._pData.get(), perm, auth, users); }
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Set a value, and it's 'assign' counterpart.
|
||
|
|
*/
|
||
|
|
void setWithAssign(const std::string &perm, const std::string &user);
|
||
|
|
void removeWithAssign(const std::string &perm, const std::string &user);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Accessors for the underlying JSON object.
|
||
|
|
*/
|
||
|
|
bool HasMember(const std::string &memberName) const;
|
||
|
|
std::string toString() const;
|
||
|
|
bool LoadFromFile(const std::string &fileName);
|
||
|
|
bool SaveToFile(const std::string &fileName) const;
|
||
|
|
|
||
|
|
JSONArray getUserArray(const std::string &arrayName) const;
|
||
|
|
|
||
|
|
void setKeys(const JSONArray &keys);
|
||
|
|
bool hasKeys() const;
|
||
|
|
void clearKeys();
|
||
|
|
|
||
|
|
bool isEmpty() const;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get a list of users, based on a permission key.
|
||
|
|
*/
|
||
|
|
void getUsers(const CloudGuardURN &van, const std::string &key, std::vector<CloudGuardURN> &users) const;
|
||
|
|
std::string getUserAndGroupSig(const CloudGuardURN &van) const;
|
||
|
|
|
||
|
|
private:
|
||
|
|
std::string _authority;
|
||
|
|
JSONObjectPtr _pData;
|
||
|
|
|
||
|
|
void collectMembers(const CloudGuardURN &van, const CloudGuardURNToURNSetMap &groupMap, const JSONArray &permArray, CloudGuardURNSet &mbrs);
|
||
|
|
|
||
|
|
std::string getPermittedRightsSig() const;
|
||
|
|
|
||
|
|
void mergeDefaultPermissions();
|
||
|
|
|
||
|
|
static bool can(const JSONObject *pObj, const std::string &perm, const std::string &user, bool bRemove, std::string *pWhyReturn = NULL);
|
||
|
|
static bool canAssign(const JSONObject *pObj, const std::string &perm, const std::string &user);
|
||
|
|
static bool assign(JSONObject *pObj, const std::string &perm, const std::string &auth, const std::string &user);
|
||
|
|
static bool assign(JSONObject *pObj, const std::string &perm, const std::string &auth, const std::vector<std::string> &users);
|
||
|
|
|
||
|
|
static void mergePermissions(Permissions *pDest, const Permissions &src, bool bAssign);
|
||
|
|
};
|
||
|
|
#if defined(WIN32) || defined(_WIN32)
|
||
|
|
#pragma warning(pop)
|
||
|
|
#endif
|
||
|
|
};
|
||
|
|
|
||
|
|
#endif
|