#ifndef _OBJECTACL
#define _OBJECTACL
#include <security_cdsa_utilities/aclsubject.h>
#include <security_utilities/globalizer.h>
#include <map>
#include <set>
#include <limits.h>
namespace Security {
class ObjectAcl {
friend AclSubject::Maker::Maker(CSSM_ACL_SUBJECT_TYPE);
public:
typedef RefPointer<AclSubject> AclSubjectPointer;
typedef LowLevelMemoryUtilities::Writer Writer;
typedef LowLevelMemoryUtilities::Reader Reader;
public:
ObjectAcl(Allocator &alloc);
ObjectAcl(const AclEntryPrototype &proto, Allocator &alloc);
virtual ~ObjectAcl();
Allocator &allocator;
void validate(AclAuthorization auth, const AccessCredentials *cred,
AclValidationEnvironment *env = NULL);
void validate(AclValidationContext &ctx);
bool validates(AclAuthorization auth, const AccessCredentials *cred,
AclValidationEnvironment *env = NULL);
bool validates(AclValidationContext &ctx);
void validateOwner(AclAuthorization authorizationHint, const AccessCredentials *cred,
AclValidationEnvironment *env = NULL);
void validateOwner(AclValidationContext &ctx);
void cssmGetAcl(const char *tag, uint32 &count, AclEntryInfo * &acls);
void cssmChangeAcl(const AclEdit &edit, const AccessCredentials *cred,
AclValidationEnvironment *env = NULL);
void cssmGetOwner(AclOwnerPrototype &owner);
void cssmChangeOwner(const AclOwnerPrototype &newOwner, const AccessCredentials *cred,
AclValidationEnvironment *env = NULL);
void cssmSetInitial(const AclEntryPrototype &proto);
void cssmSetInitial(const AclSubjectPointer &subject);
void exportBlob(CssmData &publicBlob, CssmData &privateBlob);
void importBlob(const void *publicBlob, const void *privateBlob);
void clear();
virtual void instantiateAcl(); virtual void changedAcl();
virtual void debugDump(const char *what = NULL) const;
public:
class Entry {
public:
AclSubjectPointer subject; bool delegate;
Entry() { }
void toOwnerInfo(CSSM_ACL_OWNER_PROTOTYPE &info,
Allocator &alloc) const;
virtual bool authorizes(AclAuthorization auth) const = 0;
virtual bool validate(const AclValidationContext &ctx) const = 0;
template <class Action>
void exportBlob(Action &pub, Action &priv)
{
Endian<uint32> del = delegate; pub(del); exportSubject(subject, pub, priv); }
void importBlob(Reader &pub, Reader &priv);
IFDUMP(virtual void debugDump() const);
private:
void init(const AclSubjectPointer &subject, bool delegate = false);
void init(const TypedList &subject, bool delegate = false) { init(make(subject), delegate); }
protected:
Entry(const AclEntryPrototype &proto) { init(proto.subject(), proto.delegate()); }
Entry(const AclOwnerPrototype &proto) { init(proto.subject()); }
Entry(const AclSubjectPointer &subject) { init(subject); }
virtual ~Entry();
};
class OwnerEntry : public Entry {
public:
OwnerEntry() { } template <class Input>
OwnerEntry(const Input &owner) : Entry(owner) { }
bool authorizes(AclAuthorization auth) const;
bool validate(const AclValidationContext &ctx) const;
};
class AclEntry : public Entry {
public:
std::string tag; AclAuthorizationSet authorizations; bool authorizesAnything; CSSM_ACL_HANDLE handle;
AclEntry() { } AclEntry(const AclSubjectPointer &subject);
AclEntry(const AclEntryPrototype &proto);
void toEntryInfo(CSSM_ACL_ENTRY_PROTOTYPE &info,
Allocator &alloc) const;
bool authorizes(AclAuthorization auth) const;
bool validate(const AclValidationContext &ctx) const;
template <class Action>
void exportBlob(Action &pub, Action &priv)
{
Entry::exportBlob(pub, priv);
const char *s = tag.c_str(); pub(s);
uint32 aa = authorizesAnything; pub(aa);
if (!authorizesAnything) {
Endian<uint32> count = authorizations.size(); pub(count);
for (AclAuthorizationSet::iterator it = authorizations.begin();
it != authorizations.end(); it++) {
Endian<AclAuthorization> auth = *it; pub(auth);
}
}
}
void importBlob(Reader &pub, Reader &priv);
IFDUMP(void debugDump() const);
};
public:
template <class Action>
static void exportSubject(AclSubject *subject, Action &pub, Action &priv)
{
Endian<uint32> typeAndVersion = subject->type() | subject->version() << AclSubject::versionShift;
pub(typeAndVersion);
subject->exportBlob(pub, priv);
}
static AclSubject *importSubject(Reader &pub, Reader &priv);
public:
typedef std::multimap<string, AclEntry> EntryMap;
EntryMap::iterator begin() { return mEntries.begin(); }
EntryMap::iterator end() { return mEntries.end(); }
EntryMap::const_iterator begin() const { return mEntries.begin(); }
EntryMap::const_iterator end() const { return mEntries.end(); }
unsigned int getRange(const std::string &tag,
pair<EntryMap::const_iterator, EntryMap::const_iterator> &range) const;
EntryMap::iterator findEntryHandle(CSSM_ACL_HANDLE handle);
static AclSubject *make(const TypedList &list); static AclSubject *make(uint32 typeAndVersion,
Reader &pub, Reader &priv);
protected:
template <class Input>
void owner(const Input &input);
void entries(uint32 count, const AclEntryInfo *infos);
private:
void add(const std::string &tag, const AclEntry &newEntry);
void add(const std::string &tag, AclEntry newEntry, CSSM_ACL_HANDLE handle);
private:
EntryMap mEntries; OwnerEntry mOwner; CSSM_ACL_HANDLE mNextHandle;
private:
typedef map<CSSM_ACL_SUBJECT_TYPE, AclSubject::Maker *> MakerMap;
static ModuleNexus<MakerMap> makers;
static AclSubject::Maker &makerFor(CSSM_ACL_SUBJECT_TYPE type);
};
}
#endif //_OBJECTACL