#ifndef _CSSMACL
#define _CSSMACL
#include <Security/cssmaclpod.h>
#include <Security/cssmcred.h>
#include <Security/refcount.h>
#include <Security/globalizer.h>
#include <Security/memutils.h>
#include <map>
#include <set>
#include <string>
#include <limits.h>
namespace Security {
class AclValidationContext;
class AclSubject : public RefCount {
public:
typedef LowLevelMemoryUtilities::Writer Writer;
typedef LowLevelMemoryUtilities::Reader Reader;
typedef uint8 Version; static const int versionShift = 24; static const uint32 versionMask = 0xff000000;
AclSubject(uint32 type) : mType(type), mVersion(0) { assert(!(type & versionMask)); }
virtual ~AclSubject();
uint32 type() const { return mType; }
virtual bool validate(const AclValidationContext &ctx) const = 0;
virtual CssmList toList(CssmAllocator &alloc) const = 0;
virtual void exportBlob(Writer::Counter &pub, Writer::Counter &priv);
virtual void exportBlob(Writer &pub, Writer &priv);
virtual void importBlob(Reader &pub, Reader &priv);
Version version() const { return mVersion; }
void version(Version v) { mVersion = v; }
virtual void debugDump() const;
private:
CSSM_ACL_SUBJECT_TYPE mType;
Version mVersion;
public:
class Maker {
public:
Maker(CSSM_ACL_SUBJECT_TYPE type);
virtual ~Maker();
uint32 type() const { return myType; }
virtual AclSubject *make(const TypedList &list) const = 0;
virtual AclSubject *make(Version version, Reader &pub, Reader &priv) const = 0;
protected:
static void crack(const CssmList &list, uint32 count,
ListElement **array = NULL, ...);
static CSSM_WORDID_TYPE getWord(const ListElement &list,
int min = 0, int max = INT_MAX);
private:
CSSM_ACL_SUBJECT_TYPE myType;
};
};
class SimpleAclSubject : public AclSubject {
public:
SimpleAclSubject(CSSM_ACL_SUBJECT_TYPE su, CSSM_SAMPLE_TYPE sa)
: AclSubject(su), acceptingSamples(sa) { }
bool validate(const AclValidationContext &ctx) const;
virtual bool validate(const AclValidationContext &baseCtx,
const TypedList &sample) const = 0;
const CSSM_SAMPLE_TYPE acceptingSamples;
};
class AclValidationEnvironment {
public:
virtual ~AclValidationEnvironment(); };
class AclValidationContext {
public:
AclValidationContext(const AccessCredentials *cred,
AclAuthorization auth, AclValidationEnvironment *env = NULL)
: mCred(cred), mAuth(auth), mEnv(env) { }
AclValidationContext(const AclValidationContext &ctx)
: mCred(ctx.mCred), mAuth(ctx.mAuth), mEnv(ctx.mEnv) { }
virtual ~AclValidationContext();
virtual uint32 count() const = 0; virtual const TypedList &sample(uint32 n) const = 0; const TypedList &operator [] (uint32 n) const { return sample(n); }
AclAuthorization authorization() const { return mAuth; }
template <class Env>
Env *environment() const { return dynamic_cast<Env *>(mEnv); }
protected:
const AccessCredentials *mCred; AclAuthorization mAuth; AclValidationEnvironment *mEnv; };
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(CssmAllocator &alloc);
ObjectAcl(const AclEntryPrototype &proto, CssmAllocator &alloc);
virtual ~ObjectAcl();
CssmAllocator &allocator;
void validate(AclAuthorization auth, const AccessCredentials *cred,
AclValidationEnvironment *env = NULL) const;
void validateOwner(AclAuthorization authorizationHint, const AccessCredentials *cred,
AclValidationEnvironment *env = NULL) const;
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);
virtual void debugDump(const char *what = NULL) const;
public:
class Entry {
public:
AclSubjectPointer subject; bool delegate;
Entry() { }
void toOwnerInfo(CSSM_ACL_OWNER_PROTOTYPE &info,
CssmAllocator &alloc) const;
virtual bool authorizes(AclAuthorization auth) const = 0;
virtual bool validate(const AclValidationContext &ctx) const = 0;
template <class Action>
void ObjectAcl::Entry::exportBlob(Action &pub, Action &priv)
{
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) { }
OwnerEntry(const AclSubjectPointer &subject) : Entry(subject) { }
bool authorizes(AclAuthorization auth) const;
bool validate(const AclValidationContext &ctx) const;
};
class AclEntry : public Entry {
public:
std::string tag; AclAuthorizationSet authorizations; bool authorizesAnything; uint32 handle;
AclEntry() { } AclEntry(const AclSubjectPointer &subject);
AclEntry(const AclEntryPrototype &proto);
void toEntryInfo(CSSM_ACL_ENTRY_PROTOTYPE &info,
CssmAllocator &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) {
uint32 count = authorizations.size(); pub(count);
for (AclAuthorizationSet::iterator it = authorizations.begin();
it != authorizations.end(); it++) {
AclAuthorization auth = *it; pub(auth);
}
}
}
void importBlob(Reader &pub, Reader &priv);
IFDUMP(void debugDump() const);
};
public:
template <class Action>
static void ObjectAcl::exportSubject(AclSubject *subject, Action &pub, Action &priv)
{
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;
typedef EntryMap::iterator Iterator;
typedef EntryMap::const_iterator ConstIterator;
Iterator begin() { return entries.begin(); }
Iterator end() { return entries.end(); }
ConstIterator begin() const { return entries.begin(); }
ConstIterator end() const { return entries.end(); }
unsigned int getRange(const char *tag, pair<ConstIterator, ConstIterator> &range) const;
Iterator findEntryHandle(CSSM_ACL_HANDLE handle);
static AclSubject *make(const TypedList &list); static AclSubject *make(uint32 typeAndVersion,
Reader &pub, Reader &priv);
private:
EntryMap entries; OwnerEntry owner; uint32 nextHandle;
private:
typedef map<CSSM_ACL_SUBJECT_TYPE, AclSubject::Maker *> MakerMap;
static ModuleNexus<MakerMap> makers;
static AclSubject::Maker &makerFor(CSSM_ACL_SUBJECT_TYPE type);
};
class ResourceControlContext : public PodWrapper<ResourceControlContext, CSSM_RESOURCE_CONTROL_CONTEXT> {
public:
ResourceControlContext() { }
ResourceControlContext(const AclEntryInput &initial, AccessCredentials *cred = NULL)
{ InitialAclEntry = initial; AccessCred = cred; }
AclEntryInput &input() { return AclEntryInput::overlay(InitialAclEntry); }
operator AclEntryInput &() { return input(); }
AccessCredentials *credentials() const { return AccessCredentials::overlay(AccessCred); }
void credentials(const CSSM_ACCESS_CREDENTIALS *creds)
{ AccessCred = const_cast<CSSM_ACCESS_CREDENTIALS *>(creds); }
};
}
#endif //_CSSMACL