1/*-
2 * Copyright (c) 2013 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Portions Copyright (c) 2013 Apple Inc. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <CoreFoundation/CoreFoundation.h>
31#include <CoreFoundation/CFRuntime.h>
32#include <CoreFoundation/CFXPCBridge.h>
33#include <xpc/xpc.h>
34
35#include "common.h"
36
37
38
39#define HEIMCRED_CONST(_t,_c) \
40    const _t _c = (_t)CFSTR(#_c); \
41    const char *_c##xpc = #_c
42
43#include "heimcred-const.h"
44
45/*
46 * auth
47 */
48
49HEIMCRED_CONST(CFTypeRef, kHEIMTargetName);
50
51#undef HEIMCRED_CONST
52
53/*
54 *
55 */
56
57HeimCredContext HeimCredCTX;
58
59/*
60 *
61 */
62
63CFUUIDRef
64HeimCredCopyUUID(xpc_object_t object, const char *key)
65{
66    CFUUIDBytes bytes;
67    const void *data = xpc_dictionary_get_uuid(object, key);
68    if (data == NULL)
69	return NULL;
70    memcpy(&bytes, data, sizeof(bytes));
71    return CFUUIDCreateFromUUIDBytes(NULL, bytes);
72}
73
74CFTypeRef
75HeimCredMessageCopyAttributes(xpc_object_t object, const char *key, CFTypeID type)
76{
77    xpc_object_t xpcattrs = xpc_dictionary_get_value(object, key);
78    CFTypeRef item;
79    if (xpcattrs == NULL)
80	return NULL;
81    item = _CFXPCCreateCFObjectFromXPCObject(xpcattrs);
82    if (item && CFGetTypeID(item) != type) {
83	CFRelease(item);
84	item = NULL;
85    }
86    return item;
87}
88
89void
90HeimCredMessageSetAttributes(xpc_object_t object, const char *key, CFTypeRef attrs)
91{
92    xpc_object_t xpcattrs = _CFXPCCreateXPCObjectFromCFObject(attrs);
93    if (xpcattrs == NULL)
94	return;
95    xpc_dictionary_set_value(object, key, xpcattrs);
96    xpc_release(xpcattrs);
97}
98
99
100void
101HeimCredSetUUID(xpc_object_t object, const char *key, CFUUIDRef uuid)
102{
103    CFUUIDBytes bytes = CFUUIDGetUUIDBytes(uuid);
104    uuid_t u;
105    memcpy(&u, &bytes, sizeof(u));
106    xpc_dictionary_set_uuid(object, key, u);
107}
108
109static CFStringRef
110HeimCredCopyFormatString(CFTypeRef cf, CFDictionaryRef formatOptions)
111{
112    return CFSTR("format");
113}
114
115static CFStringRef
116HeimCredCopyDebugName(CFTypeRef cf)
117{
118    HeimCredRef cred = (HeimCredRef)cf;
119    if (cred->attributes) {
120	CFTypeRef client = CFDictionaryGetValue(cred->attributes, kHEIMAttrClientName);
121	CFTypeRef server = CFDictionaryGetValue(cred->attributes, kHEIMAttrServerName);
122	CFTypeRef parent = CFDictionaryGetValue(cred->attributes, kHEIMAttrParentCredential);
123	CFTypeRef group = CFDictionaryGetValue(cred->attributes, kHEIMAttrLeadCredential);
124
125	int lead = group ? CFBooleanGetValue(group) : false;
126	CFTypeRef acl = CFDictionaryGetValue(cred->attributes, kHEIMAttrBundleIdentifierACL);
127	return CFStringCreateWithFormat(NULL, NULL, CFSTR("HeimCred<%@ group: %@ parent: %@ client: %@ server: %@ lead: %s ACL: %@>"),
128					cred->uuid, group, parent, client, server, lead ? "yes" : "no", acl ? acl : CFSTR(""));
129    } else {
130	return CFStringCreateWithFormat(NULL, NULL, CFSTR("HeimCred<%@>"), cred->uuid);
131    }
132}
133
134static void
135HeimCredReleaseItem(CFTypeRef item)
136{
137    HeimCredRef cred = (HeimCredRef)item;
138    CFRELEASE_NULL(cred->uuid);
139    CFRELEASE_NULL(cred->attributes);
140}
141
142void
143_HeimCredInitCommon(void)
144{
145    static dispatch_once_t once;
146
147    dispatch_once(&once, ^{
148	    static const CFRuntimeClass HeimCredClass = {
149		0,
150		"HeimCredential",
151		NULL,
152		NULL,
153		HeimCredReleaseItem,
154		NULL,
155		NULL,
156		HeimCredCopyFormatString,
157		HeimCredCopyDebugName
158	    };
159	    HeimCredCTX.haid = _CFRuntimeRegisterClass(&HeimCredClass);
160
161	    HeimCredCTX.queue = dispatch_queue_create("HeimCred", NULL);
162
163#if HEIMCRED_SERVER
164	    HeimCredCTX.sessions = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
165#else
166	    HeimCredCTX.items = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
167#endif
168	});
169}
170
171CFTypeID
172HeimCredGetTypeID(void)
173{
174    _HeimCredInitCommon();
175    return HeimCredCTX.haid;
176}
177
178
179HeimCredRef
180HeimCredCreateItem(CFUUIDRef uuid)
181{
182    HeimCredRef cred = (HeimCredRef)_CFRuntimeCreateInstance(NULL, HeimCredCTX.haid, sizeof(struct HeimCred_s) - sizeof(CFRuntimeBase), NULL);
183    if (cred == NULL)
184	return NULL;
185
186    CFRetain(uuid);
187    cred->uuid = uuid;
188    return cred;
189}
190
191