#include <Security/Authorization.h>
#include <Security/AuthorizationDB.h>
#include <Security/AuthorizationPriv.h>
#include <Security/AuthSession.h>
#include "AuthorizationWalkers.h"
#include <Security/mach++.h>
#include <Security/globalizer.h>
#include <Security/cssmalloc.h>
#include <Security/ssclient.h>
#include <Security/ktracecodes.h>
using namespace SecurityServer;
using namespace MachPlusPlus;
class AuthClient : public SecurityServer::ClientSession {
public:
AuthClient()
: SecurityServer::ClientSession(CssmAllocator::standard(), CssmAllocator::standard())
{ }
};
static ModuleNexus<AuthClient> server;
OSStatus AuthorizationCreate(const AuthorizationRights *rights,
const AuthorizationEnvironment *environment,
AuthorizationFlags flags,
AuthorizationRef *authorization)
{
Debug::trace(kSecTraceAuthorizationCreateStart);
BEGIN_API
AuthorizationBlob result;
server().authCreate(rights, environment, flags, result);
if (authorization)
{
*authorization =
(AuthorizationRef) new(server().returnAllocator) AuthorizationBlob(result);
}
else
{
server().authRelease(result, flags);
}
Debug::trace(kSecTraceAuthorizationCreateEnd);
END_API(CSSM)
}
OSStatus AuthorizationFree(AuthorizationRef authorization, AuthorizationFlags flags)
{
BEGIN_API
AuthorizationBlob *auth = (AuthorizationBlob *)authorization;
server().authRelease(Required(auth, errAuthorizationInvalidRef), flags);
server().returnAllocator.free(auth);
END_API(CSSM)
}
OSStatus AuthorizationCopyRights(AuthorizationRef authorization,
const AuthorizationRights *rights,
const AuthorizationEnvironment *environment,
AuthorizationFlags flags,
AuthorizationRights **authorizedRights)
{
Debug::trace(kSecTraceAuthorizationCopyRightsStart);
BEGIN_API
AuthorizationBlob *auth = (AuthorizationBlob *)authorization;
server().authCopyRights(Required(auth, errAuthorizationInvalidRef),
rights, environment, flags, authorizedRights);
Debug::trace(kSecTraceAuthorizationCopyRightsEnd);
END_API(CSSM)
}
OSStatus AuthorizationCopyInfo(AuthorizationRef authorization,
AuthorizationString tag,
AuthorizationItemSet **info)
{
Debug::trace(kSecTraceAuthorizationCopyInfoStart);
BEGIN_API
AuthorizationBlob *auth = (AuthorizationBlob *)authorization;
server().authCopyInfo(Required(auth, errAuthorizationInvalidRef),
tag, Required(info));
Debug::trace(kSecTraceAuthorizationCopyInfoEnd);
END_API(CSSM)
}
OSStatus AuthorizationMakeExternalForm(AuthorizationRef authorization,
AuthorizationExternalForm *extForm)
{
BEGIN_API
AuthorizationBlob *auth = (AuthorizationBlob *)authorization;
server().authExternalize(Required(auth, errAuthorizationInvalidRef), *extForm);
END_API(CSSM)
}
OSStatus AuthorizationCreateFromExternalForm(const AuthorizationExternalForm *extForm,
AuthorizationRef *authorization)
{
BEGIN_API
AuthorizationBlob result;
server().authInternalize(*extForm, result);
Required(authorization, errAuthorizationInvalidRef) =
(AuthorizationRef) new(server().returnAllocator) AuthorizationBlob(result);
END_API(CSSM)
}
OSStatus AuthorizationFreeItemSet(AuthorizationItemSet *set)
{
BEGIN_API
server().returnAllocator.free(set);
return errAuthorizationSuccess;
END_API(CSSM)
}
OSStatus SessionGetInfo(SecuritySessionId session,
SecuritySessionId *sessionId,
SessionAttributeBits *attributes)
{
BEGIN_API
SecuritySessionId sid = session;
server().getSessionInfo(sid, *attributes);
if (sessionId)
*sessionId = sid;
END_API(CSSM)
}
OSStatus SessionCreate(SessionCreationFlags flags,
SessionAttributeBits attributes)
{
BEGIN_API
Bootstrap bootstrap;
if (!(flags & sessionKeepCurrentBootstrap)) {
TaskPort self;
bootstrap = bootstrap.subset(TaskPort());
self.bootstrap(bootstrap);
}
server().setupSession(flags, attributes);
SecuritySessionId id = callerSecuritySession;
SessionAttributeBits attrs;
server().getSessionInfo(id, attrs);
char idString[80];
snprintf(idString, sizeof(idString), "%lx", id);
setenv("SECURITYSESSIONID", idString, 1);
END_API(CSSM)
}
OSStatus AuthorizationRightGet(const char *rightName, CFDictionaryRef *rightDefinition)
{
BEGIN_API;
Required(rightName);
CssmDataContainer definition(server().returnAllocator);
server().authorizationdbGet(rightName, definition, server().returnAllocator);
if (rightDefinition)
{
CFRef<CFDataRef> data(CFDataCreate(NULL, static_cast<UInt8 *>(definition.data()), definition.length()));
if (!data)
CssmError::throwMe(errAuthorizationInternal);
CFRef<CFDictionaryRef> rightDict(static_cast<CFDictionaryRef>(CFPropertyListCreateFromXMLData(NULL, data, kCFPropertyListImmutable, NULL)));
if (!rightDict
|| CFGetTypeID(rightDict) != CFDictionaryGetTypeID())
CssmError::throwMe(errAuthorizationInternal);
CFRetain(rightDict);
*rightDefinition = rightDict;
}
END_API(CSSM);
}
OSStatus AuthorizationRightSet(AuthorizationRef authRef,
const char *rightName, CFTypeRef rightDefinition,
CFStringRef descriptionKey, CFBundleRef bundle, CFStringRef tableName)
{
BEGIN_API;
Required(rightName);
AuthorizationBlob *auth = (AuthorizationBlob *)authRef;
CFRef<CFMutableDictionaryRef> rightDefinitionDict;
if (rightDefinition && (CFGetTypeID(rightDefinition) == CFStringGetTypeID()))
{
rightDefinitionDict = CFDictionaryCreateMutable(NULL, 10, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
if (!rightDefinitionDict)
CssmError::throwMe(errAuthorizationInternal);
CFDictionarySetValue(rightDefinitionDict, CFSTR(kAuthorizationRightRule), rightDefinition);
}
else
if (rightDefinition && (CFGetTypeID(rightDefinition) == CFDictionaryGetTypeID()))
{
rightDefinitionDict = CFDictionaryCreateMutableCopy(NULL, 0, static_cast<CFDictionaryRef>(rightDefinition));
if (!rightDefinitionDict)
CssmError::throwMe(errAuthorizationInternal);
}
else
CssmError::throwMe(errAuthorizationDenied);
if (rightDefinitionDict)
CFRelease(rightDefinitionDict);
if (descriptionKey)
{
CFRef<CFMutableDictionaryRef> localizedDescriptions(CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
if (!localizedDescriptions)
CssmError::throwMe(errAuthorizationInternal);
CFRef<CFBundleRef> clientBundle = bundle ? bundle : CFBundleGetMainBundle();
CFRef<CFArrayRef> localizations(CFBundleCopyBundleLocalizations(clientBundle));
if (localizations)
{
CFIndex locIndex, allLocs = CFArrayGetCount(localizations);
for (locIndex = 0; locIndex < allLocs; locIndex++)
{
CFStringRef oneLocalization = static_cast<CFStringRef>(CFArrayGetValueAtIndex(localizations, locIndex));
if (!oneLocalization)
continue;
CFRef<CFURLRef> locURL(CFBundleCopyResourceURLForLocalization(clientBundle, tableName ? tableName : CFSTR("Localizable"), CFSTR("strings"), NULL , oneLocalization));
if (!locURL)
continue;
CFDataRef tableData;
SInt32 errCode;
CFStringRef errStr;
CFPropertyListRef stringTable;
CFURLCreateDataAndPropertiesFromResource(CFGetAllocator(clientBundle), locURL, &tableData, NULL, NULL, &errCode);
if (errCode)
{
CFRelease(tableData);
continue;
}
stringTable = CFPropertyListCreateFromXMLData(CFGetAllocator(clientBundle), tableData, kCFPropertyListImmutable, &errStr);
if (errStr != NULL) {
CFRelease(errStr);
errStr = NULL;
}
CFRelease(tableData);
CFStringRef value = static_cast<CFStringRef>(CFDictionaryGetValue(static_cast<CFDictionaryRef>(stringTable), descriptionKey));
if (value == NULL || CFEqual(value, CFSTR(""))) {
CFRelease(stringTable);
continue;
} else {
CFDictionarySetValue(localizedDescriptions, oneLocalization, value);
CFRelease(stringTable);
}
}
}
CFDictionarySetValue(localizedDescriptions, CFSTR(""), descriptionKey);
CFDictionarySetValue(rightDefinitionDict, CFSTR(kAuthorizationRuleParameterDefaultPrompt), localizedDescriptions);
}
CFDataRef rightDefinitionXML = CFPropertyListCreateXMLData(NULL, rightDefinitionDict);
server().authorizationdbSet(Required(auth), rightName, CFDataGetLength(rightDefinitionXML), CFDataGetBytePtr(rightDefinitionXML));
END_API(CSSM);
}
OSStatus AuthorizationRightRemove(AuthorizationRef authRef, const char *rightName)
{
BEGIN_API;
Required(rightName);
AuthorizationBlob *auth = (AuthorizationBlob *)authRef;
server().authorizationdbRemove(Required(auth), rightName);
END_API(CSSM);
}