#import <CoreFoundation/CoreFoundation.h>
#import <CoreFoundation/CFRuntime.h>
#import <CoreFoundation/CFXPCBridge.h>
#import <xpc/xpc.h>
#import "common.h"
#define HEIMCRED_CONST(_t,_c) \
const _t _c = (_t)CFSTR(#_c); \
const char *_c##xpc = #_c;
#include "heimcred-const.h"
HEIMCRED_CONST(CFTypeRef, kHEIMTargetName);
#undef HEIMCRED_CONST
HeimCredContext HeimCredCTX;
CFUUIDRef
HeimCredCopyUUID(xpc_object_t object, const char *key)
{
CFUUIDBytes bytes;
const void *data = xpc_dictionary_get_uuid(object, key);
if (data == NULL)
return NULL;
memcpy(&bytes, data, sizeof(bytes));
return CFUUIDCreateFromUUIDBytes(NULL, bytes);
}
CFDictionaryRef
HeimCredMessageCopyAttributes(xpc_object_t object, const char *key)
{
xpc_object_t xpcattrs = xpc_dictionary_get_value(object, key);
if (xpcattrs == NULL)
return NULL;
return _CFXPCCreateCFObjectFromXPCObject(xpcattrs);
}
void
HeimCredMessageSetAttributes(xpc_object_t object, const char *key, CFTypeRef attrs)
{
xpc_object_t xpcattrs = _CFXPCCreateXPCObjectFromCFObject(attrs);
if (xpcattrs == NULL)
return;
xpc_dictionary_set_value(object, key, xpcattrs);
xpc_release(xpcattrs);
}
void
HeimCredSetUUID(xpc_object_t object, const char *key, CFUUIDRef uuid)
{
CFUUIDBytes bytes = CFUUIDGetUUIDBytes(uuid);
uuid_t u;
memcpy(&u, &bytes, sizeof(u));
xpc_dictionary_set_uuid(object, key, u);
}
static CFStringRef
HeimCredCopyFormatString(CFTypeRef cf, CFDictionaryRef formatOptions)
{
return CFSTR("format");
}
static CFStringRef
HeimCredCopyDebugName(CFTypeRef cf)
{
HeimCredRef cred = (HeimCredRef)cf;
CFTypeRef client = CFDictionaryGetValue(cred->attributes, kHEIMAttrClientName);
CFTypeRef server = CFDictionaryGetValue(cred->attributes, kHEIMAttrServerName);
CFTypeRef group = CFDictionaryGetValue(cred->attributes, kHEIMAttrCredentialGroup);
CFTypeRef parent = CFDictionaryGetValue(cred->attributes, kHEIMAttrParentCredential);
CFTypeRef lead = CFDictionaryGetValue(cred->attributes, kHEIMAttrCredentialGroupLead);
CFTypeRef acl = CFDictionaryGetValue(cred->attributes, kHEIMAttrBundleIdentifierACL);
return CFStringCreateWithFormat(NULL, NULL, CFSTR("HeimCred<%@ group: %@ parent: %@ client: %@ server: %@ lead: %s ACL: %@>"),
cred->uuid, group, parent, client, server, lead ? "yes" : "no", acl ? acl : CFSTR(""));
}
static void
HeimCredReleaseItem(CFTypeRef item)
{
HeimCredRef cred = (HeimCredRef)item;
CFRELEASE_NULL(cred->uuid);
CFRELEASE_NULL(cred->attributes);
}
void
_HeimCredInitCommon(void)
{
static dispatch_once_t once;
dispatch_once(&once, ^{
static const CFRuntimeClass HeimCredClass = {
0,
"HeimCredential",
NULL,
NULL,
HeimCredReleaseItem,
NULL,
NULL,
HeimCredCopyFormatString,
HeimCredCopyDebugName
};
HeimCredCTX.haid = _CFRuntimeRegisterClass(&HeimCredClass);
HeimCredCTX.queue = dispatch_queue_create("HeimCred", NULL);
HeimCredCTX.items = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
});
}
HeimCredRef
HeimCredCreateItem(CFUUIDRef uuid)
{
HeimCredRef cred = (HeimCredRef)_CFRuntimeCreateInstance(NULL, HeimCredCTX.haid, sizeof(struct HeimCred_s) - sizeof(CFRuntimeBase), NULL);
if (cred == NULL)
return NULL;
CFRetain(uuid);
cred->uuid = uuid;
return cred;
}