#include <Security/SecACL.h>
#include <security_keychain/ACL.h>
#include <security_keychain/Access.h>
#include <security_keychain/SecAccessPriv.h>
#include "SecBridge.h"
sint32 GetACLAuthorizationTagFromString(CFStringRef aclStr);
CFStringRef GetAuthStringFromACLAuthorizationTag(sint32 tag);
static void setApplications(ACL *acl, CFArrayRef applicationList);
CFTypeID
SecACLGetTypeID(void)
{
BEGIN_SECAPI
return gTypes().ACL.typeID;
END_SECAPI1(_kCFRuntimeNotATypeID)
}
OSStatus SecACLCreateFromSimpleContents(SecAccessRef accessRef,
CFArrayRef applicationList,
CFStringRef description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector,
SecACLRef *newAcl)
{
BEGIN_SECAPI
SecPointer<Access> access = Access::required(accessRef);
SecPointer<ACL> acl = new ACL(*access, cfString(description), *promptSelector);
if (applicationList) {
acl->form(ACL::appListForm);
setApplications(acl, applicationList);
} else {
acl->form(ACL::allowAllForm);
}
access->add(acl.get());
Required(newAcl) = acl->handle();
END_SECAPI
}
OSStatus SecACLCreateWithSimpleContents(SecAccessRef access,
CFArrayRef applicationList,
CFStringRef description,
SecKeychainPromptSelector promptSelector,
SecACLRef *newAcl)
{
CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector;
cdsaPromptSelector.version = CSSM_ACL_KEYCHAIN_PROMPT_CURRENT_VERSION;
cdsaPromptSelector.flags = promptSelector;
return SecACLCreateFromSimpleContents(access, applicationList, description, &cdsaPromptSelector, newAcl);
}
OSStatus SecACLRemove(SecACLRef aclRef)
{
BEGIN_SECAPI
ACL::required(aclRef)->remove();
END_SECAPI
}
static SecTrustedApplicationRef
convert(const SecPointer<TrustedApplication> &trustedApplication)
{
return *trustedApplication;
}
OSStatus SecACLCopySimpleContents(SecACLRef aclRef,
CFArrayRef *applicationList,
CFStringRef *promptDescription, CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector)
{
BEGIN_SECAPI
SecPointer<ACL> acl = ACL::required(aclRef);
switch (acl->form()) {
case ACL::allowAllForm:
Required(applicationList) = NULL;
Required(promptDescription) =
acl->promptDescription().empty() ? NULL
: makeCFString(acl->promptDescription());
Required(promptSelector) = acl->promptSelector();
break;
case ACL::appListForm:
Required(applicationList) =
makeCFArray(convert, acl->applications());
Required(promptDescription) = makeCFString(acl->promptDescription());
Required(promptSelector) = acl->promptSelector();
break;
default:
return errSecACLNotSimple; }
END_SECAPI
}
OSStatus SecACLCopyContents(SecACLRef acl,
CFArrayRef *applicationList,
CFStringRef *description,
SecKeychainPromptSelector *promptSelector)
{
CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector;
memset(&cdsaPromptSelector, 0, sizeof(cdsaPromptSelector));
OSStatus err = noErr;
err = SecACLCopySimpleContents(acl, applicationList, description, &cdsaPromptSelector);
*promptSelector = cdsaPromptSelector.flags;
return err;
}
OSStatus SecACLSetSimpleContents(SecACLRef aclRef,
CFArrayRef applicationList,
CFStringRef description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector)
{
BEGIN_SECAPI
SecPointer<ACL> acl = ACL::required(aclRef);
acl->promptDescription() = description ? cfString(description) : "";
acl->promptSelector() = promptSelector ? *promptSelector : ACL::defaultSelector;
if (applicationList) {
acl->form(ACL::appListForm);
setApplications(acl, applicationList);
} else {
acl->form(ACL::allowAllForm);
}
acl->modify();
END_SECAPI
}
OSStatus SecACLSetContents(SecACLRef acl,
CFArrayRef applicationList,
CFStringRef description,
SecKeychainPromptSelector promptSelector)
{
CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cdsaPromptSelector;
cdsaPromptSelector.version = CSSM_ACL_PROCESS_SELECTOR_CURRENT_VERSION;
cdsaPromptSelector.flags = promptSelector;
return SecACLSetSimpleContents(acl, applicationList, description, &cdsaPromptSelector);
}
static void setApplications(ACL *acl, CFArrayRef applicationList)
{
ACL::ApplicationList &appList = acl->applications();
appList.clear();
CFIndex count = CFArrayGetCount(applicationList);
for (CFIndex n = 0; n < count; n++)
appList.push_back(TrustedApplication::required(
SecTrustedApplicationRef(CFArrayGetValueAtIndex(applicationList, n))));
}
OSStatus SecACLGetAuthorizations(SecACLRef acl,
CSSM_ACL_AUTHORIZATION_TAG *tags, uint32 *tagCount)
{
BEGIN_SECAPI
AclAuthorizationSet auths = ACL::required(acl)->authorizations();
if (Required(tagCount) < auths.size()) { *tagCount = auths.size(); CssmError::throwMe(paramErr);
}
*tagCount = auths.size();
copy(auths.begin(), auths.end(), tags);
END_SECAPI
}
CFArrayRef SecACLCopyAuthorizations(SecACLRef acl)
{
CFArrayRef result = NULL;
if (NULL == acl)
{
return result;
}
AclAuthorizationSet auths = ACL::required(acl)->authorizations();
uint32 numAuths = auths.size();
CSSM_ACL_AUTHORIZATION_TAG* tags = new CSSM_ACL_AUTHORIZATION_TAG[numAuths];
int i;
for (i = 0; i < numAuths; ++i)
{
tags[i] = NULL;
}
OSStatus err = SecACLGetAuthorizations(acl, tags, &numAuths);
if (noErr != err)
{
return result;
}
CFTypeRef* strings = new CFTypeRef[numAuths];
for (i = 0; i < numAuths; ++i)
{
strings[i] = NULL;
}
for (size_t iCnt = 0; iCnt < numAuths; iCnt++)
{
strings[iCnt] = (CFTypeRef)GetAuthStringFromACLAuthorizationTag(tags[iCnt]);
}
result = CFArrayCreate(kCFAllocatorDefault, (const void **)strings, numAuths, NULL);
delete[] strings;
delete[] tags;
return result;
}
OSStatus SecACLSetAuthorizations(SecACLRef aclRef,
CSSM_ACL_AUTHORIZATION_TAG *tags, uint32 tagCount)
{
BEGIN_SECAPI
SecPointer<ACL> acl = ACL::required(aclRef);
if (acl->isOwner()) MacOSError::throwMe(errSecInvalidOwnerEdit);
AclAuthorizationSet &auths = acl->authorizations();
auths.clear();
copy(tags, tags + tagCount, insert_iterator<AclAuthorizationSet>(auths, auths.begin()));
acl->modify();
END_SECAPI
}
OSStatus SecACLUpdateAuthorizations(SecACLRef acl, CFArrayRef authorizations)
{
if (NULL == acl || NULL == authorizations)
{
return paramErr;
}
uint32 tagCount = CFArrayGetCount(authorizations);
size_t tagSize = (tagCount * sizeof(CSSM_ACL_AUTHORIZATION_TAG));
CSSM_ACL_AUTHORIZATION_TAG* tags = (CSSM_ACL_AUTHORIZATION_TAG*)malloc(tagSize);
memset(tags, 0, tagSize);
for (uint32 iCnt = 0; iCnt < tagCount; iCnt++)
{
tags[iCnt] = GetACLAuthorizationTagFromString((CFStringRef)CFArrayGetValueAtIndex(authorizations, iCnt));
}
OSStatus result = SecACLSetAuthorizations(acl, tags, tagCount);
free(tags);
return result;
}