#include <security_cdsa_utilities/cssmaclpod.h>
#include <security_cdsa_utilities/cssmwalkers.h>
#include <cstdarg>
namespace Security {
AclAuthorizationSet::AclAuthorizationSet(AclAuthorization auth0, AclAuthorization auth, ...)
{
insert(auth0);
va_list args;
va_start(args, auth);
while (auth) {
insert(auth);
auth = va_arg(args, AclAuthorization);
}
va_end(args);
}
AuthorizationGroup::AuthorizationGroup(const AclAuthorizationSet &auths, Allocator &alloc)
{
NumberOfAuthTags = auths.size();
AuthTags = alloc.alloc<CSSM_ACL_AUTHORIZATION_TAG>(NumberOfAuthTags);
copy(auths.begin(), auths.end(), AuthTags); }
AuthorizationGroup::AuthorizationGroup(CSSM_ACL_AUTHORIZATION_TAG tag, Allocator &alloc)
{
AuthTags = alloc.alloc<CSSM_ACL_AUTHORIZATION_TAG>(1);
AuthTags[0] = tag;
NumberOfAuthTags = 1;
}
void AuthorizationGroup::destroy(Allocator &alloc)
{
alloc.free(AuthTags);
}
bool AuthorizationGroup::contains(CSSM_ACL_AUTHORIZATION_TAG tag) const
{
return find(AuthTags, &AuthTags[NumberOfAuthTags], tag) != &AuthTags[NumberOfAuthTags];
}
AuthorizationGroup::operator AclAuthorizationSet() const
{
return AclAuthorizationSet(AuthTags, &AuthTags[NumberOfAuthTags]);
}
AclEntryPrototype::AclEntryPrototype(const AclOwnerPrototype &proto)
{
memset(this, 0, sizeof(*this));
TypedSubject = proto.subject(); Delegate = proto.delegate();
}
void AclEntryPrototype::tag(const char *tagString)
{
if (tagString == NULL)
EntryTag[0] = '\0';
else if (strlen(tagString) > CSSM_MODULE_STRING_SIZE)
CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_ENTRY_TAG);
else
strcpy(EntryTag, tagString);
}
void AclEntryPrototype::tag(const string &tagString)
{
if (tagString.length() > CSSM_MODULE_STRING_SIZE)
CssmError::throwMe(CSSM_ERRCODE_INVALID_ACL_ENTRY_TAG);
else
memcpy(EntryTag, tagString.c_str(), tagString.length() + 1);
}
AclOwnerPrototype *AutoAclOwnerPrototype::make()
{
if (!mAclOwnerPrototype) {
mAclOwnerPrototype = new AclOwnerPrototype;
mAclOwnerPrototype->clearPod();
}
return mAclOwnerPrototype;
}
AutoAclOwnerPrototype::~AutoAclOwnerPrototype()
{
if (mAllocator)
DataWalkers::chunkFree(mAclOwnerPrototype, *mAllocator);
}
void
AutoAclOwnerPrototype::allocator(Allocator &allocator)
{
mAllocator = &allocator;
}
void AutoAclEntryInfoList::size(uint32 newSize)
{
assert(mAllocator);
mEntries = mAllocator->alloc<AclEntryInfo>(mEntries, newSize);
for (uint32 n = mCount; n < newSize; n++)
mEntries[n].clearPod();
mCount = newSize;
}
AclEntryInfo &AutoAclEntryInfoList::at(uint32 ix)
{
if (ix >= mCount)
size(ix + 1); return mEntries[ix];
}
void AutoAclEntryInfoList::clear()
{
if (mAllocator)
{
DataWalkers::ChunkFreeWalker w(*mAllocator);
for (uint32 ix = 0; ix < mCount; ix++)
walk(w, mEntries[ix]);
mAllocator->free(mEntries);
mEntries = NULL;
mCount = 0;
}
}
void AutoAclEntryInfoList::allocator(Allocator &allocator)
{
mAllocator = &allocator;
}
void AutoAclEntryInfoList::add(const TypedList &subj, const AclAuthorizationSet &auths, const char *tag )
{
AclEntryInfo &info = at(size());
info.proto() = AclEntryPrototype(subj);
info.proto().authorization() = AuthorizationGroup(auths, allocator());
info.proto().tag(tag);
info.handle(size());
}
void AutoAclEntryInfoList::addPin(const TypedList &subj, uint32 slot)
{
char tag[20];
snprintf(tag, sizeof(tag), "PIN%d", slot);
add(subj, CSSM_ACL_AUTHORIZATION_PREAUTH(slot), tag);
}
void AutoAclEntryInfoList::addPinState(uint32 slot, uint32 status)
{
char tag[20];
snprintf(tag, sizeof(tag), "PIN%d?", slot);
TypedList subj(allocator(), CSSM_WORDID_PIN,
new(allocator()) ListElement(slot),
new(allocator()) ListElement(status));
add(subj, CSSM_WORDID_PIN, tag);
}
void AutoAclEntryInfoList::addPinState(uint32 slot, uint32 status, uint32 count)
{
char tag[20];
snprintf(tag, sizeof(tag), "PIN%d?", slot);
TypedList subj(allocator(), CSSM_WORDID_PIN,
new(allocator()) ListElement(slot),
new(allocator()) ListElement(status),
new(allocator()) ListElement(count));
add(subj, CSSM_WORDID_PIN, tag);
}
uint32 pinFromAclTag(const char *tag, const char *suffix )
{
if (tag) {
char format[20];
snprintf(format, sizeof(format), "PIN%%d%s%%n", suffix ? suffix : "");
uint32 pin;
unsigned consumed;
sscanf(tag, format, &pin, &consumed);
if (consumed == strlen(tag)) return pin;
}
return 0;
}
}