]> git.saurik.com Git - apple/security.git/blame - OSX/sec/ipc/server.c
Security-58286.240.4.tar.gz
[apple/security.git] / OSX / sec / ipc / server.c
CommitLineData
b1ab9ed8 1/*
866f8763 2 * Copyright (c) 2007-2017 Apple Inc. All Rights Reserved.
b1ab9ed8
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5c19dc3a 5 *
b1ab9ed8
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
5c19dc3a 12 *
b1ab9ed8
A
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
5c19dc3a 20 *
b1ab9ed8
A
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
5c19dc3a
A
24#include <Security/SecureObjectSync/SOSPeerInfoDER.h>
25#include <Security/SecureObjectSync/SOSCloudCircle.h>
26#include <Security/SecureObjectSync/SOSCloudCircleInternal.h>
27#include <Security/SecureObjectSync/SOSInternal.h>
28#include <Security/SecureObjectSync/SOSPeerInfoCollections.h>
ecaf5866 29#include <Security/SecureObjectSync/SOSControlServer.h>
866f8763 30#include <Security/SecBase.h>
b1ab9ed8 31#include <Security/SecBasePriv.h>
427c49bc 32#include <Security/SecCertificatePriv.h>
d8f41ccd
A
33#include <Security/SecEntitlements.h>
34#include <Security/SecInternal.h>
866f8763 35#include <Security/SecItem.h>
ecaf5866 36#include <Security/SecItemPriv.h>
866f8763 37#include <Security/SecPolicy.h>
427c49bc 38#include <Security/SecPolicyInternal.h>
d8f41ccd 39#include <Security/SecTask.h>
fa7225c8 40#include <Security/SecTrustInternal.h>
d8f41ccd
A
41#include <Security/SecuritydXPC.h>
42#include <securityd/OTATrustUtilities.h>
43#include <securityd/SOSCloudCircleServer.h>
5c19dc3a 44#include <securityd/SecItemBackupServer.h>
427c49bc 45#include <securityd/SecItemServer.h>
d8f41ccd
A
46#include <securityd/SecLogSettingsServer.h>
47#include <securityd/SecOTRRemote.h>
427c49bc
A
48#include <securityd/SecTrustServer.h>
49#include <securityd/SecTrustStoreServer.h>
d8f41ccd 50#include <securityd/iCloudTrace.h>
b1ab9ed8 51#include <securityd/spi.h>
427c49bc 52#include <utilities/SecCFError.h>
d8f41ccd
A
53#include <utilities/SecCFWrappers.h>
54#include <utilities/SecDb.h>
55#include <utilities/SecIOFormat.h>
427c49bc 56#include <utilities/SecXPCError.h>
d8f41ccd 57#include <utilities/debugging.h>
822b670c 58#include <utilities/SecInternalReleasePriv.h>
866f8763 59#include <utilities/der_plist_internal.h>
6b200bc3
A
60#include <utilities/der_plist.h>
61#include <securityd/personalization.h>
866f8763 62#include <securityd/SecPinningDb.h>
ecaf5866 63#include <securityd/SFKeychainControlManager.h>
866f8763
A
64
65#include <keychain/ckks/CKKS.h>
ecaf5866
A
66#include <keychain/ckks/CKKSControlServer.h>
67#include "keychain/ot/OctagonControlServer.h"
b1ab9ed8 68
79b9da22
A
69#include <securityd/SFKeychainServer.h>
70
427c49bc 71#include <AssertMacros.h>
d8f41ccd
A
72#include <CoreFoundation/CFXPCBridge.h>
73#include <CoreFoundation/CoreFoundation.h>
e0e0d90e 74// <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
6b200bc3 75
6b200bc3 76#if TARGET_OS_OSX
e3d460c9 77#include <Security/SecTaskPriv.h>
fa7225c8 78#include <login/SessionAgentStatusCom.h>
e3d460c9 79#endif
d8f41ccd
A
80#include <asl.h>
81#include <bsm/libbsm.h>
82#include <ipc/securityd_client.h>
83#include <libkern/OSAtomic.h>
84#include <mach/mach.h>
85#include <mach/message.h>
e0e0d90e 86#include <notify.h>
d8f41ccd
A
87#include <stdlib.h>
88#include <sys/queue.h>
427c49bc 89#include <sys/sysctl.h>
d8f41ccd
A
90#include <syslog.h>
91#include <xpc/private.h>
92#include <xpc/xpc.h>
b1ab9ed8 93
866f8763
A
94#include <ipc/server_security_helpers.h>
95#include <ipc/server_entitlement_helpers.h>
b1ab9ed8 96
866f8763
A
97#if TARGET_OS_OSX
98#include <sandbox.h>
99#include <pwd.h>
100#include <err.h>
101#endif
b1ab9ed8 102
866f8763
A
103static bool accessGroupPermitted(SecurityClient* client, CFArrayRef accessGroups, CFStringRef accessGroup) {
104 /* NULL accessGroups is wildcard. */
105 if (!accessGroups)
106 return true;
107 /* Make sure we have a string. */
108 if (!isString(accessGroup))
109 return false;
427c49bc 110
866f8763
A
111 /* Having the special accessGroup "*" allows access to all accessGroups. */
112 CFRange range = { 0, CFArrayGetCount(accessGroups) };
113 if (range.length &&
114 (CFArrayContainsValue(accessGroups, range, accessGroup) ||
115 CFArrayContainsValue(accessGroups, range, CFSTR("*"))))
116 return true;
d8f41ccd 117
866f8763 118 return false;
d8f41ccd 119}
b1ab9ed8 120
866f8763
A
121static bool extractAccessGroup(SecurityClient *client, CFStringRef requestedAgrp, CFStringRef *resolvedAgrp, CFErrorRef *error) {
122 bool ok = true;
123
124 /* Access group sanity checking.
125 Similar to accessGroupsAllows, but ignores accessGroupIsNetworkExtensionAndClientIsEntitled */
126 CFArrayRef accessGroups = client->accessGroups;
127 CFStringRef agrp = requestedAgrp;
128 /* Having the special accessGroup "*" allows access to all accessGroups. */
129 if (CFArrayContainsValue(accessGroups, CFRangeMake(0,CFArrayGetCount(accessGroups)), CFSTR("*")))
130 accessGroups = NULL;
131
132 if (requestedAgrp) {
133 /* The user specified an explicit access group, validate it. */
134 if (!accessGroupPermitted(client, accessGroups, requestedAgrp))
135 ok = SecError(errSecMissingEntitlement, error, CFSTR("explicit accessGroup %@ not in client access %@"), requestedAgrp, accessGroups);
d8f41ccd 136 } else {
866f8763
A
137 // We are using an implicit access group
138 // Add it as if the user specified it as an attribute.
139 agrp = (CFStringRef)CFArrayGetValueAtIndex(client->accessGroups, 0);
e0e0d90e 140 }
e0e0d90e 141
866f8763
A
142 if (agrp && resolvedAgrp)
143 *resolvedAgrp = agrp;
427c49bc 144 return ok;
b1ab9ed8
A
145}
146
427c49bc
A
147static void with_label_and_password(xpc_object_t message, void (^action)(CFStringRef label, CFDataRef password)) {
148 const char *label_utf8 = xpc_dictionary_get_string(message, kSecXPCKeyUserLabel);
5c19dc3a
A
149
150 if (label_utf8) { // Anything we would do here requires a user label
151 size_t password_length = 0;
152 const void *password_data = xpc_dictionary_get_data(message, kSecXPCKeyUserPassword, &password_length);
153
154 CFDataRef user_password = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, password_data, password_length, kCFAllocatorNull);
155 CFStringRef user_label = CFStringCreateWithCString(kCFAllocatorDefault, label_utf8, kCFStringEncodingUTF8);
156
157 action(user_label, user_password);
b1ab9ed8 158
5c19dc3a
A
159 CFReleaseNull(user_password);
160 CFReleaseNull(user_label);
161 }
162}
b1ab9ed8 163
5c19dc3a
A
164static void with_label_and_password_and_dsid(xpc_object_t message, void (^action)(CFStringRef label, CFDataRef password, CFStringRef dsid)) {
165 const char *label_utf8 = xpc_dictionary_get_string(message, kSecXPCKeyUserLabel);
166
167 if (label_utf8) { // Anything we would do here requires a user label
168 size_t password_length = 0;
169 const void *password_data = xpc_dictionary_get_data(message, kSecXPCKeyUserPassword, &password_length);
170 const char *xdsid = xpc_dictionary_get_string(message, kSecXPCKeyDSID);
171
172 CFDataRef user_password = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, password_data, password_length, kCFAllocatorNull);
173 CFStringRef user_label = CFStringCreateWithCString(kCFAllocatorDefault, label_utf8, kCFStringEncodingUTF8);
174 CFStringRef dsid = CFStringCreateWithCString(kCFAllocatorDefault, xdsid, kCFStringEncodingUTF8);
175
176 action(user_label, user_password, dsid);
177
178 CFReleaseNull(dsid);
179 CFReleaseNull(user_password);
180 CFReleaseNull(user_label);
181 }
182}
b1ab9ed8 183
5c19dc3a
A
184static void with_label_and_number(xpc_object_t message, void (^action)(CFStringRef label, uint64_t number)) {
185 const char *label_utf8 = xpc_dictionary_get_string(message, kSecXPCKeyViewName);
b1ab9ed8 186
29734401
A
187 if (label_utf8) { // Anything we would do here requires a user label
188 const int64_t number = xpc_dictionary_get_int64(message, kSecXPCKeyViewActionCode);
189 CFStringRef user_label = CFStringCreateWithCString(kCFAllocatorDefault, label_utf8, kCFStringEncodingUTF8);
190
191 action(user_label, number);
192 CFReleaseNull(user_label);
193 }
b1ab9ed8 194}
b1ab9ed8 195
e0e0d90e
A
196static CFArrayRef SecXPCDictionaryCopyPeerInfoArray(xpc_object_t dictionary, const char *key, CFErrorRef *error) {
197 return CreateArrayOfPeerInfoWithXPCObject(xpc_dictionary_get_value(dictionary, key), error);
198}
199
fa7225c8
A
200static CFDataRef SecXPCDictionaryCopyCFDataRef(xpc_object_t message, const char *key, CFErrorRef *error) {
201 CFDataRef retval = NULL;
202 const uint8_t *bytes = NULL;
203 size_t len = 0;
204
205 bytes = xpc_dictionary_get_data(message, key, &len);
206 require_action_quiet(bytes, errOut, SOSCreateError(kSOSErrorBadKey, CFSTR("missing CFDataRef info"), NULL, error));
207 retval = CFDataCreate(NULL, bytes, len);
208 require_action_quiet(retval, errOut, SOSCreateError(kSOSErrorBadKey, CFSTR("could not allocate CFDataRef info"), NULL, error));
209errOut:
210 return retval;
211}
212
866f8763
A
213static CFSetRef CreateCFSetRefFromXPCObject(xpc_object_t xpcSetDER, CFErrorRef* error) {
214 CFSetRef retval = NULL;
215 require_action_quiet(xpcSetDER, errOut, SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedNull, sSecXPCErrorDomain, NULL, error, NULL, CFSTR("Unexpected Null Set to decode")));
216
217 require_action_quiet(xpc_get_type(xpcSetDER) == XPC_TYPE_DATA, errOut, SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, error, NULL, CFSTR("xpcSetDER not data, got %@"), xpcSetDER));
218
219 const uint8_t* der = xpc_data_get_bytes_ptr(xpcSetDER);
220 const uint8_t* der_end = der + xpc_data_get_length(xpcSetDER);
221 der = der_decode_set(kCFAllocatorDefault, kCFPropertyListMutableContainersAndLeaves, &retval, error, der, der_end);
222 if (der != der_end) {
223 SecError(errSecDecode, error, CFSTR("trailing garbage at end of SecAccessControl data"));
224 goto errOut;
5c19dc3a 225 }
866f8763
A
226 return retval;
227errOut:
228 CFReleaseNull(retval);
229 return NULL;
5c19dc3a
A
230}
231
6b200bc3
A
232static SOSPeerInfoRef SecXPCDictionaryCopyPeerInfo(xpc_object_t message, const char *key, CFErrorRef *error) {
233 size_t length = 0;
234 const uint8_t *der = xpc_dictionary_get_data(message, key, &length);
235
866f8763 236 return SecRequirementError(der != NULL, error, CFSTR("No data for key %s"), key) ? SOSPeerInfoCreateFromDER(kCFAllocatorDefault, error, &der, der + length) : NULL;
6b200bc3
A
237}
238
5c19dc3a
A
239static CFSetRef SecXPCSetCreateFromXPCDictionaryElement(xpc_object_t event, const char *key) {
240 CFErrorRef error = NULL;
241 xpc_object_t object = xpc_dictionary_get_value(event, key);
242 CFSetRef retval = NULL;
243 if(object) retval = CreateCFSetRefFromXPCObject(object, &error);
244 CFReleaseNull(error);
245 return retval;
246}
247
e0e0d90e
A
248static inline
249void xpc_dictionary_set_and_consume_CFArray(xpc_object_t xdict, const char *key, CF_CONSUMED CFArrayRef cf_array) {
250 if (cf_array) {
251 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(cf_array);
252 xpc_dictionary_set_value(xdict, key, xpc_array);
253 xpc_release(xpc_array);
254 }
255 CFReleaseNull(cf_array);
256}
257
258static inline
259bool xpc_dictionary_set_and_consume_PeerInfoArray(xpc_object_t xdict, const char *key, CF_CONSUMED CFArrayRef cf_array, CFErrorRef *error) {
260 bool success = true;
261 if (cf_array) {
262 xpc_object_t xpc_array = CreateXPCObjectWithArrayOfPeerInfo(cf_array, error);
263 if (xpc_array) {
264 xpc_dictionary_set_value(xdict, key, xpc_array);
265 xpc_release(xpc_array);
266 } else {
267 success = false;
268 }
269 }
270 CFReleaseNull(cf_array);
271 return success;
272}
273
e3d460c9
A
274static CFDataRef
275SecDataCopyMmapFileDescriptor(int fd, void **mem, size_t *size, CFErrorRef *error)
276{
277 struct stat sb;
278 if (fstat(fd, &sb) < 0) {
279 return NULL;
280 }
281
282 *size = (size_t)sb.st_size;
283 if ((off_t)*size != sb.st_size) {
284 return NULL;
285 }
286
287 *mem = mmap(NULL, *size, PROT_READ, MAP_SHARED, fd, 0);
288 if (*mem == MAP_FAILED) {
289 return NULL;
290 }
291
292 return CFDataCreateWithBytesNoCopy(NULL, *mem, *size, kCFAllocatorNull);
293}
294
6b200bc3 295static bool
e3d460c9
A
296SecDataWriteFileDescriptor(int fd, CFDataRef data)
297{
298 CFIndex count = CFDataGetLength(data);
299 const uint8_t *ptr = CFDataGetBytePtr(data);
300 bool writeResult = false;
301
302 while (count) {
303 ssize_t ret = write(fd, ptr, count);
304 if (ret <= 0)
305 break;
306 count -= ret;
307 ptr += ret;
308 }
309 if (count == 0)
310 writeResult = true;
311
312 return writeResult;
313}
314
315
fa7225c8
A
316// Returns error if entitlement isn't present.
317static bool
318EntitlementPresentAndTrue(uint64_t op, SecTaskRef clientTask, CFStringRef entitlement, CFErrorRef *error)
319{
320 if (!SecTaskGetBooleanValueForEntitlement(clientTask, entitlement)) {
321 SecError(errSecMissingEntitlement, error, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation)op), clientTask, entitlement);
322 return false;
323 }
324 return true;
325}
e3d460c9 326
fa7225c8
A
327// Per <rdar://problem/13315020> Disable the entitlement check for "keychain-cloud-circle"
328// we disable entitlement enforcement. However, we still log so we know who needs the entitlement
822b670c 329static bool
fa7225c8 330EntitlementPresentOrWhine(uint64_t op, SecTaskRef clientTask, CFStringRef entitlement, CFErrorRef *error)
822b670c 331{
fa7225c8
A
332 if (!SecTaskGetBooleanValueForEntitlement(clientTask, entitlement))
333 secnotice("serverxpc", "%@: %@ lacks entitlement %@", SOSCCGetOperationDescription((enum SecXPCOperation)op), clientTask, entitlement);
334
335 return true;
822b670c
A
336}
337
338
fa7225c8
A
339static bool
340EntitlementAbsentOrFalse(uint64_t op, SecTaskRef clientTask, CFStringRef entitlement, CFErrorRef *error)
341{
342 if (SecTaskGetBooleanValueForEntitlement(clientTask, entitlement)) {
343 SecError(errSecNotAvailable, error, CFSTR("%@: %@ has entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation) op), clientTask, entitlement);
344 return false;
345 }
346 return true;
347}
348
427c49bc 349static void securityd_xpc_dictionary_handler(const xpc_connection_t connection, xpc_object_t event) {
5c19dc3a 350 xpc_type_t type = xpc_get_type(event);
427c49bc
A
351 __block CFErrorRef error = NULL;
352 xpc_object_t xpcError = NULL;
353 xpc_object_t replyMessage = NULL;
5c19dc3a 354 CFDataRef clientAuditToken = NULL;
d8f41ccd 355 CFArrayRef domains = NULL;
e3d460c9
A
356 SecurityClient client = {
357 .task = NULL,
358 .accessGroups = NULL,
359 .musr = NULL,
360 .uid = xpc_connection_get_euid(connection),
361 .allowSystemKeychain = false,
362 .allowSyncBubbleKeychain = false,
363 .isNetworkExtension = false,
866f8763 364 .canAccessNetworkExtensionAccessGroups = false,
e3d460c9 365 };
427c49bc
A
366
367 secdebug("serverxpc", "entering");
368 if (type == XPC_TYPE_DICTIONARY) {
369 // TODO: Find out what we're dispatching.
370 replyMessage = xpc_dictionary_create_reply(event);
371
372 uint64_t operation = xpc_dictionary_get_uint64(event, kSecXPCKeyOperation);
427c49bc 373
427c49bc
A
374 audit_token_t auditToken = {};
375 xpc_connection_get_audit_token(connection, &auditToken);
5c19dc3a 376 clientAuditToken = CFDataCreate(kCFAllocatorDefault, (const UInt8*)&auditToken, sizeof(auditToken));
866f8763
A
377
378 fill_security_client(&client, xpc_connection_get_euid(connection), auditToken);
b04fe171
A
379
380#if TARGET_OS_IOS
d8f41ccd 381 if (operation == sec_add_shared_web_credential_id || operation == sec_copy_shared_web_credential_id) {
e3d460c9
A
382 domains = SecTaskCopySharedWebCredentialDomains(client.task);
383 }
b04fe171 384#endif
e3d460c9 385 secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64 ")", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), operation);
5c19dc3a 386
6b200bc3 387 switch (operation)
427c49bc
A
388 {
389 case sec_item_add_id:
390 {
fa7225c8
A
391 if (EntitlementAbsentOrFalse(sec_item_add_id, client.task, kSecEntitlementKeychainDeny, &error)) {
392 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
393 if (query) {
866f8763
A
394 // Check for any entitlement-required attributes
395 bool entitlementsCorrect = true;
396 if(CFDictionaryGetValue(query, kSecAttrDeriveSyncIDFromItemAttributes) ||
397 CFDictionaryGetValue(query, kSecAttrPCSPlaintextServiceIdentifier) ||
398 CFDictionaryGetValue(query, kSecAttrPCSPlaintextPublicKey) ||
399 CFDictionaryGetValue(query, kSecAttrPCSPlaintextPublicIdentity)) {
400 entitlementsCorrect = EntitlementPresentAndTrue(sec_item_add_id, client.task, kSecEntitlementPrivateCKKSPlaintextFields, &error);
401 }
402 if (entitlementsCorrect && CFDictionaryGetValue(query, kSecAttrSysBound)) {
403 entitlementsCorrect = EntitlementPresentAndTrue(sec_item_add_id, client.task, kSecEntitlementPrivateSysBound, &error);
404 }
405
fa7225c8 406 CFTypeRef result = NULL;
866f8763
A
407 if(entitlementsCorrect) {
408 if (_SecItemAdd(query, &client, &result, &error) && result) {
409 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
410 CFReleaseNull(result);
411 }
fa7225c8
A
412 }
413 CFReleaseNull(query);
427c49bc 414 }
fa7225c8 415 break;
427c49bc 416 }
427c49bc
A
417 }
418 case sec_item_copy_matching_id:
419 {
fa7225c8
A
420 if (EntitlementAbsentOrFalse(sec_item_add_id, client.task, kSecEntitlementKeychainDeny, &error)) {
421 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
422 if (query) {
423 CFTypeRef result = NULL;
424 if (_SecItemCopyMatching(query, &client, &result, &error) && result) {
425 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
426 CFReleaseNull(result);
427 }
428 CFReleaseNull(query);
427c49bc 429 }
fa7225c8 430 break;
427c49bc 431 }
427c49bc
A
432 }
433 case sec_item_update_id:
434 {
866f8763 435 if (EntitlementAbsentOrFalse(sec_item_update_id, client.task, kSecEntitlementKeychainDeny, &error)) {
fa7225c8
A
436 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
437 if (query) {
438 CFDictionaryRef attributesToUpdate = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyAttributesToUpdate, &error);
439 if (attributesToUpdate) {
866f8763
A
440 // Check for any entitlement-required attributes
441 bool entitlementsCorrect = true;
442 if(CFDictionaryGetValue(query, kSecAttrDeriveSyncIDFromItemAttributes) ||
443 CFDictionaryGetValue(attributesToUpdate, kSecAttrPCSPlaintextServiceIdentifier) ||
444 CFDictionaryGetValue(attributesToUpdate, kSecAttrPCSPlaintextPublicKey) ||
445 CFDictionaryGetValue(attributesToUpdate, kSecAttrPCSPlaintextPublicIdentity)) {
446 entitlementsCorrect = EntitlementPresentAndTrue(sec_item_update_id, client.task, kSecEntitlementPrivateCKKSPlaintextFields, &error);
447 }
448 if (entitlementsCorrect && CFDictionaryGetValue(query, kSecAttrSysBound)) {
449 entitlementsCorrect = EntitlementPresentAndTrue(sec_item_update_id, client.task, kSecEntitlementPrivateSysBound, &error);
450 }
451
452 if(entitlementsCorrect) {
453 bool result = _SecItemUpdate(query, attributesToUpdate, &client, &error);
454 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
455 }
fa7225c8
A
456 CFReleaseNull(attributesToUpdate);
457 }
458 CFReleaseNull(query);
427c49bc 459 }
427c49bc 460 }
b1ab9ed8 461 break;
427c49bc
A
462 }
463 case sec_item_delete_id:
464 {
fa7225c8
A
465 if (EntitlementAbsentOrFalse(sec_item_add_id, client.task, kSecEntitlementKeychainDeny, &error)) {
466 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
467 if (query) {
468 bool result = _SecItemDelete(query, &client, &error);
469 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
470 CFReleaseNull(query);
471 }
472 }
473 break;
474 }
475 case sec_item_update_token_items_id:
476 {
477 if (EntitlementAbsentOrFalse(sec_item_add_id, client.task, kSecEntitlementKeychainDeny, &error)) {
478 CFStringRef tokenID = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
479 CFArrayRef attributes = SecXPCDictionaryCopyArray(event, kSecXPCKeyQuery, &error);
480 if (tokenID) {
481 bool result = _SecItemUpdateTokenItems(tokenID, attributes, &client, &error);
482 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
483 }
484 CFReleaseNull(tokenID);
485 CFReleaseNull(attributes);
427c49bc 486 }
b1ab9ed8 487 break;
427c49bc 488 }
427c49bc 489 case sec_delete_all_id:
ecaf5866
A
490 {
491 bool retval = false;
492#if TARGET_OS_IPHONE
493 /* buddy is temporary allowed to do this */
494 CFStringRef applicationIdentifier = SecTaskCopyApplicationIdentifier(client.task);
495 bool isBuddy = applicationIdentifier &&
496 CFEqual(applicationIdentifier, CFSTR("com.apple.purplebuddy"));
497
498 if (isBuddy || EntitlementPresentAndTrue(operation, client.task, kSecEntitlementPrivateDeleteAll, &error))
499 {
500 retval = _SecItemDeleteAll(&error);
501 }
502#endif
503 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, retval);
427c49bc 504 break;
ecaf5866 505 }
427c49bc
A
506 case sec_keychain_backup_id:
507 {
fa7225c8 508 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
822b670c
A
509 CFDataRef keybag = NULL, passcode = NULL;
510 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyKeybag, &keybag, &error)) {
511 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
ecaf5866
A
512 bool emcs = SecXPCDictionaryGetBool(event, kSecXPCKeyEMCSBackup, NULL);
513 CFDataRef backup = _SecServerKeychainCreateBackup(&client, keybag, passcode, emcs, &error);
822b670c 514 if (backup) {
e3d460c9
A
515 int fd = SecXPCDictionaryDupFileDescriptor(event, kSecXPCKeyFileDescriptor, NULL);
516 if (fd < 0) {
517 SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, backup, &error);
518 } else {
519 bool writeResult = SecDataWriteFileDescriptor(fd, backup);
520 if (close(fd) != 0)
521 writeResult = false;
522 if (!writeResult)
523 SecError(errSecIO, &error, CFSTR("Failed to write backup file: %d"), errno);
524 SecXPCDictionarySetBool(replyMessage, kSecXPCKeyResult, writeResult, NULL);
525 }
822b670c
A
526 CFRelease(backup);
527 }
528 CFReleaseSafe(passcode);
427c49bc 529 }
822b670c 530 CFReleaseSafe(keybag);
427c49bc 531 }
b1ab9ed8 532 }
427c49bc 533 break;
b1ab9ed8 534 }
427c49bc 535 case sec_keychain_restore_id:
5c19dc3a 536 {
fa7225c8 537 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
e3d460c9
A
538 CFDataRef backup = NULL;
539 void *mem = NULL;
540 size_t size = 0;
541
542 int fd = SecXPCDictionaryDupFileDescriptor(event, kSecXPCKeyFileDescriptor, NULL);
543 if (fd != -1) {
544 backup = SecDataCopyMmapFileDescriptor(fd, &mem, &size, &error);
545 } else {
546 backup = SecXPCDictionaryCopyData(event, kSecXPCKeyBackup, &error);
547 }
822b670c
A
548 if (backup) {
549 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
550 if (keybag) {
551 CFDataRef passcode = NULL;
552 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
e3d460c9 553 bool result = _SecServerKeychainRestore(backup, &client, keybag, passcode, &error);
822b670c
A
554 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
555 CFReleaseSafe(passcode);
556 }
427c49bc 557 }
fa7225c8
A
558 CFReleaseNull(keybag);
559 }
560 CFReleaseNull(backup);
561 if (fd != -1)
562 close(fd);
563 if (mem) {
564 munmap(mem, size);
565 }
566 }
567 break;
568 }
569 case sec_keychain_backup_keybag_uuid_id:
570 {
571 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
572 CFDataRef backup = NULL;
573 CFStringRef uuid = NULL;
574 void *mem = NULL;
575 size_t size = 0;
576
577 int fd = SecXPCDictionaryDupFileDescriptor(event, kSecXPCKeyFileDescriptor, NULL);
578 if (fd != -1) {
579 backup = SecDataCopyMmapFileDescriptor(fd, &mem, &size, &error);
580 if (backup)
581 uuid = _SecServerBackupCopyUUID(backup, &error);
d8f41ccd 582 }
fa7225c8
A
583 if (uuid)
584 SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, uuid, &error);
585
586 CFReleaseNull(backup);
587 if (fd != -1)
588 close(fd);
e3d460c9
A
589 if (mem) {
590 munmap(mem, size);
591 }
fa7225c8 592 CFReleaseNull(uuid);
b1ab9ed8 593 }
5c19dc3a
A
594 break;
595 }
596 case sec_keychain_sync_update_message_id:
597 {
598 CFDictionaryRef updates = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
599 if (updates) {
600 CFArrayRef result = _SecServerKeychainSyncUpdateMessage(updates, &error);
601 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
602 CFReleaseNull(result);
d8f41ccd 603 }
5c19dc3a
A
604 CFReleaseNull(updates);
605 break;
606 }
607 case sec_keychain_backup_syncable_id:
608 {
fa7225c8 609 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
822b670c
A
610 CFDictionaryRef oldbackup = NULL;
611 if (SecXPCDictionaryCopyDictionaryOptional(event, kSecXPCKeyBackup, &oldbackup, &error)) {
612 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
613 if (keybag) {
614 CFDataRef passcode = NULL;
615 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
616 CFDictionaryRef newbackup = _SecServerBackupSyncable(oldbackup, keybag, passcode, &error);
617 if (newbackup) {
618 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, newbackup, &error);
619 CFRelease(newbackup);
620 }
621 CFReleaseSafe(passcode);
427c49bc 622 }
fa7225c8 623 CFReleaseNull(keybag);
427c49bc 624 }
822b670c 625 CFReleaseSafe(oldbackup);
427c49bc 626 }
b1ab9ed8 627 }
427c49bc 628 break;
b1ab9ed8 629 }
427c49bc
A
630 case sec_keychain_restore_syncable_id:
631 {
fa7225c8 632 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
822b670c
A
633 CFDictionaryRef backup = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyBackup, &error);
634 if (backup) {
635 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
636 if (keybag) {
637 CFDataRef passcode = NULL;
638 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
639 bool result = _SecServerRestoreSyncable(backup, keybag, passcode, &error);
640 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
641 CFReleaseSafe(passcode);
642 }
fa7225c8 643 CFReleaseNull(keybag);
427c49bc 644 }
fa7225c8 645 CFReleaseNull(backup);
427c49bc 646 }
b1ab9ed8 647 }
427c49bc 648 break;
b1ab9ed8 649 }
5c19dc3a
A
650 case sec_item_backup_copy_names_id:
651 {
fa7225c8 652 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
822b670c
A
653 CFArrayRef names = SecServerItemBackupCopyNames(&error);
654 SecXPCDictionarySetPListOptional(replyMessage, kSecXPCKeyResult, names, &error);
655 CFReleaseSafe(names);
822b670c 656 }
5c19dc3a
A
657 break;
658 }
659 case sec_item_backup_handoff_fd_id:
660 {
fa7225c8 661 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
822b670c
A
662 CFStringRef backupName = SecXPCDictionaryCopyString(event, kSecXPCKeyBackup, &error);
663 int fd = -1;
664 if (backupName) {
665 fd = SecServerItemBackupHandoffFD(backupName, &error);
666 CFRelease(backupName);
667 }
668 SecXPCDictionarySetFileDescriptor(replyMessage, kSecXPCKeyResult, fd, &error);
669 if (fd != -1)
670 close(fd);
5c19dc3a 671 }
5c19dc3a
A
672 break;
673 }
674 case sec_item_backup_set_confirmed_manifest_id:
675 {
fa7225c8 676 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
822b670c
A
677 CFDataRef keybagDigest = NULL;
678 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyKeybag, &keybagDigest, &error)) {
679 CFDataRef manifest = NULL;
680 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCData, &manifest, &error)) {
681 CFStringRef backupName = SecXPCDictionaryCopyString(event, kSecXPCKeyBackup, &error);
682 if (backupName) {
683 bool result = SecServerItemBackupSetConfirmedManifest(backupName, keybagDigest, manifest, &error);
684 CFRelease(backupName);
685 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
686 }
687 CFReleaseSafe(manifest);
5c19dc3a 688 }
5c19dc3a 689 }
fa7225c8 690 CFReleaseNull(keybagDigest);
5c19dc3a
A
691 }
692 break;
693 }
694 case sec_item_backup_restore_id:
695 {
fa7225c8 696 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
822b670c
A
697 bool result = false;
698 CFStringRef backupName = SecXPCDictionaryCopyString(event, kSecXPCKeyBackup, &error);
699 if (backupName) {
700 CFStringRef peerID = NULL;
701 if (SecXPCDictionaryCopyStringOptional(event, kSecXPCKeyDigest, &peerID, &error)) {
702 CFDataRef keybag = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
703 if (keybag) {
704 CFDataRef secret = SecXPCDictionaryCopyData(event, kSecXPCKeyUserPassword, &error);
705 if (secret) {
706 CFDataRef backup = SecXPCDictionaryCopyData(event, kSecXPCData, &error);
707 if (backup) {
708 result = SecServerItemBackupRestore(backupName, peerID, keybag, secret, backup, &error);
709 CFRelease(backup);
710 }
711 CFRelease(secret);
5c19dc3a 712 }
822b670c 713 CFRelease(keybag);
5c19dc3a 714 }
822b670c 715 CFReleaseSafe(peerID);
5c19dc3a 716 }
822b670c 717 CFRelease(backupName);
5c19dc3a 718 }
822b670c 719 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
5c19dc3a 720 }
5c19dc3a
A
721 break;
722 }
d8f41ccd
A
723 case sec_add_shared_web_credential_id:
724 {
866f8763 725#if TARGET_OS_IOS && !TARGET_OS_BRIDGE
d8f41ccd
A
726 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
727 if (query) {
728 CFTypeRef result = NULL;
b04fe171 729
e3d460c9 730 CFStringRef appID = (client.task) ? SecTaskCopyApplicationIdentifier(client.task) : NULL;
641423b6 731 if (_SecAddSharedWebCredential(query, &client, &auditToken, appID, domains, &result, &error) && result) {
d8f41ccd 732 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
fa7225c8 733 CFReleaseNull(result);
d8f41ccd
A
734 }
735 CFReleaseSafe(appID);
fa7225c8 736 CFReleaseNull(query);
d8f41ccd 737 }
b04fe171
A
738#else
739 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, kCFBooleanFalse, &error);
740#endif
d8f41ccd
A
741 break;
742 }
743 case sec_copy_shared_web_credential_id:
744 {
866f8763 745#if TARGET_OS_IOS && !TARGET_OS_BRIDGE
d8f41ccd
A
746 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
747 if (query) {
748 CFTypeRef result = NULL;
e3d460c9 749 CFStringRef appID = (client.task) ? SecTaskCopyApplicationIdentifier(client.task) : NULL;
641423b6 750 if (_SecCopySharedWebCredential(query, &client, &auditToken, appID, domains, &result, &error) && result) {
d8f41ccd 751 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
fa7225c8 752 CFReleaseNull(result);
d8f41ccd
A
753 }
754 CFReleaseSafe(appID);
fa7225c8 755 CFReleaseNull(query);
d8f41ccd 756 }
b04fe171
A
757#else
758 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, kCFBooleanFalse, &error);
759#endif
d8f41ccd
A
760 break;
761 }
762 case sec_get_log_settings_id:
763 {
764 CFPropertyListRef currentList = SecCopyLogSettings_Server(&error);
765 if (currentList) {
766 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, currentList, &error);
767 }
768 CFReleaseSafe(currentList);
769 break;
770 }
771 case sec_set_xpc_log_settings_id:
772 {
773 CFPropertyListRef newSettings = SecXPCDictionaryCopyPList(event, kSecXPCKeyQuery, &error);
774 if (newSettings) {
775 SecSetXPCLogSettings_Server(newSettings, &error);
776 }
777 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true);
778 CFReleaseNull(newSettings);
779 break;
780 }
5c19dc3a
A
781 case sec_set_circle_log_settings_id:
782 {
783 CFPropertyListRef newSettings = SecXPCDictionaryCopyPList(event, kSecXPCKeyQuery, &error);
784 if (newSettings) {
785 SecSetCircleLogSettings_Server(newSettings, &error);
786 }
787 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true);
788 CFReleaseNull(newSettings);
789 break;
790 }
d8f41ccd
A
791 case sec_otr_session_create_remote_id:
792 {
793 CFDataRef publicPeerId = NULL;
794 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCPublicPeerId, &publicPeerId, &error)) {
795 CFDataRef otrSession = _SecOTRSessionCreateRemote(publicPeerId, &error);
796 if (otrSession) {
797 SecXPCDictionarySetData(replyMessage, kSecXPCKeyResult, otrSession, &error);
fa7225c8 798 CFReleaseNull(otrSession);
d8f41ccd
A
799 }
800 CFReleaseSafe(publicPeerId);
801 }
802 break;
803 }
804 case sec_otr_session_process_packet_remote_id:
805 {
806 CFDataRef sessionData = NULL, inputPacket = NULL, outputSessionData = NULL, outputPacket = NULL;
807 bool readyForMessages = false;
808 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCOTRSession, &sessionData, &error)) {
809 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCData, &inputPacket, &error)) {
810 bool result = _SecOTRSessionProcessPacketRemote(sessionData, inputPacket, &outputSessionData, &outputPacket, &readyForMessages, &error);
811 if (result) {
812 SecXPCDictionarySetData(replyMessage, kSecXPCOTRSession, outputSessionData, &error);
813 SecXPCDictionarySetData(replyMessage, kSecXPCData, outputPacket, &error);
814 xpc_dictionary_set_bool(replyMessage, kSecXPCOTRReady, readyForMessages);
fa7225c8
A
815 CFReleaseNull(outputSessionData);
816 CFReleaseNull(outputPacket);
d8f41ccd
A
817 }
818 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
5c19dc3a 819
d8f41ccd
A
820 CFReleaseSafe(inputPacket);
821 }
822 CFReleaseSafe(sessionData);
823 }
824 break;
825 }
427c49bc 826 case kSecXPCOpTryUserCredentials:
fa7225c8 827 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
ecaf5866 828 with_label_and_password_and_dsid(event, ^(CFStringRef label, CFDataRef password, CFStringRef dsid) {
fa7225c8 829 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
ecaf5866 830 SOSCCTryUserCredentials_Server(label, password, dsid, &error));
fa7225c8
A
831 });
832 }
427c49bc
A
833 break;
834 case kSecXPCOpSetUserCredentials:
fa7225c8
A
835 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
836 with_label_and_password(event, ^(CFStringRef label, CFDataRef password) {
837 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
838 SOSCCSetUserCredentials_Server(label, password, &error));
839 });
840 }
427c49bc 841 break;
5c19dc3a 842 case kSecXPCOpSetUserCredentialsAndDSID:
fa7225c8 843 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
5c19dc3a
A
844 with_label_and_password_and_dsid(event, ^(CFStringRef label, CFDataRef password, CFStringRef dsid) {
845 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
846 SOSCCSetUserCredentialsAndDSID_Server(label, password, dsid, &error));
847 });
fa7225c8
A
848 }
849 break;
79b9da22
A
850 case kSecXPCOpSetUserCredentialsAndDSIDWithAnalytics:
851 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
852 with_label_and_password_and_dsid(event, ^(CFStringRef label, CFDataRef password, CFStringRef dsid) {
853 CFDataRef parentEvent = NULL;
854 if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error) && parentEvent != NULL){
855 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCSetUserCredentialsAndDSIDWithAnalytics_Server(label, password, dsid, parentEvent, &error));
856 }else{
857 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCSetUserCredentialsAndDSID_Server(label, password, dsid, &error));
858 }
859 CFReleaseNull(parentEvent);
860 });
861 }
862 break;
5c19dc3a 863 case kSecXPCOpView:
fa7225c8
A
864 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
865 with_label_and_number(event, ^(CFStringRef view, uint64_t actionCode) {
866 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
867 SOSCCView_Server(view, (SOSViewActionCode)actionCode, &error));
868 });
869 }
5c19dc3a
A
870 break;
871 case kSecXPCOpViewSet:
fa7225c8 872 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
5c19dc3a
A
873 CFSetRef enabledViews = SecXPCSetCreateFromXPCDictionaryElement(event, kSecXPCKeyEnabledViewsKey);
874 CFSetRef disabledViews = SecXPCSetCreateFromXPCDictionaryElement(event, kSecXPCKeyDisabledViewsKey);
875 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCViewSet_Server(enabledViews, disabledViews));
876 CFReleaseNull(enabledViews);
877 CFReleaseNull(disabledViews);
878 }
879 break;
79b9da22
A
880 case kSecXPCOpViewSetWithAnalytics:
881 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
882 CFSetRef enabledViews = SecXPCSetCreateFromXPCDictionaryElement(event, kSecXPCKeyEnabledViewsKey);
883 CFSetRef disabledViews = SecXPCSetCreateFromXPCDictionaryElement(event, kSecXPCKeyDisabledViewsKey);
884 CFDataRef parentEvent = NULL;
885 if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error) && parentEvent != NULL){
886 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCViewSetWithAnalytics_Server(enabledViews, disabledViews, parentEvent));
887 }else{
888 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCViewSet_Server(enabledViews, disabledViews));
889 }
890 CFReleaseNull(enabledViews);
891 CFReleaseNull(disabledViews);
892 CFReleaseNull(parentEvent);
893 }
5c19dc3a 894 break;
427c49bc 895 case kSecXPCOpCanAuthenticate:
fa7225c8
A
896 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
897 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
898 SOSCCCanAuthenticate_Server(&error));
899 }
427c49bc
A
900 break;
901 case kSecXPCOpPurgeUserCredentials:
fa7225c8
A
902 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
903 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
904 SOSCCPurgeUserCredentials_Server(&error));
905 }
427c49bc
A
906 break;
907 case kSecXPCOpDeviceInCircle:
fa7225c8
A
908 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
909 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
910 SOSCCThisDeviceIsInCircle_Server(&error));
911 }
427c49bc
A
912 break;
913 case kSecXPCOpRequestToJoin:
fa7225c8
A
914 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
915 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
916 SOSCCRequestToJoinCircle_Server(&error));
917 }
918 break;
79b9da22
A
919 case kSecXPCOpRequestToJoinWithAnalytics:
920 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
921 CFDataRef parentEvent = NULL;
922 if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error) && parentEvent != NULL){
923 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRequestToJoinCircleWithAnalytics_Server(parentEvent, &error));
924 }else{
925 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRequestToJoinCircle_Server(&error));
926 }
927 CFReleaseNull(parentEvent);
928 }
929 break;
fa7225c8
A
930 case kSecXPCOpAccountHasPublicKey:
931 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
932 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
933 SOSCCAccountHasPublicKey_Server(&error));
934 }
935 break;
936 case kSecXPCOpAccountIsNew:
937 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
938 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
939 SOSCCAccountIsNew_Server(&error));
940 }
427c49bc
A
941 break;
942 case kSecXPCOpRequestToJoinAfterRestore:
fa7225c8
A
943 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
944 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
945 SOSCCRequestToJoinCircleAfterRestore_Server(&error));
946 }
427c49bc 947 break;
79b9da22
A
948 case kSecXPCOpRequestToJoinAfterRestoreWithAnalytics:
949 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
950 CFDataRef parentEvent = NULL;
951 if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error) && parentEvent != NULL){
952 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRequestToJoinCircleAfterRestoreWithAnalytics_Server(parentEvent, &error));
953 }else{
954 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRequestToJoinCircleAfterRestore_Server(&error));
955 }
956 CFReleaseNull(parentEvent);
957 }
958 break;
d8f41ccd 959 case kSecXPCOpRequestEnsureFreshParameters:
fa7225c8
A
960 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
961 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
962 SOSCCRequestEnsureFreshParameters_Server(&error));
963 }
d8f41ccd 964 break;
5c19dc3a 965 case kSecXPCOpGetAllTheRings:
29734401 966 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
5c19dc3a
A
967 CFStringRef ringDescriptions = SOSCCGetAllTheRings_Server(&error);
968 xpc_object_t xpc_dictionary = _CFXPCCreateXPCObjectFromCFObject(ringDescriptions);
969 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_dictionary);
970 xpc_release(xpc_dictionary);
971 }
972 break;
973 case kSecXPCOpApplyToARing:
29734401 974 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
5c19dc3a
A
975 CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
976 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCApplyToARing_Server(ringName, &error));
977 CFReleaseNull(ringName);
978 }
979 break;
980 case kSecXPCOpWithdrawlFromARing:
29734401 981 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
5c19dc3a
A
982 CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
983 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCWithdrawlFromARing_Server(ringName, &error));
984 CFReleaseNull(ringName);
985 }
986 break;
987 case kSecXPCOpRingStatus:
29734401 988 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
5c19dc3a
A
989 CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
990 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRingStatus_Server(ringName, &error));
991 CFReleaseNull(ringName);
992 }
993 break;
994 case kSecXPCOpEnableRing:
29734401 995 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
5c19dc3a
A
996 CFStringRef ringName = SecXPCDictionaryCopyString(event, kSecXPCKeyString, &error);
997 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCEnableRing_Server(ringName, &error));
998 CFReleaseNull(ringName);
999 }
1000 break;
d8f41ccd 1001 case kSecXPCOpRequestDeviceID:
d8f41ccd 1002 case kSecXPCOpSetDeviceID:
5c19dc3a 1003 case kSecXPCOpHandleIDSMessage:
79b9da22 1004 case kSecXPCOpSyncWithIDSPeer:
5c19dc3a 1005 case kSecXPCOpSendIDSMessage:
5c19dc3a 1006 case kSecXPCOpPingTest:
5c19dc3a 1007 case kSecXPCOpIDSDeviceID:
79b9da22
A
1008 case kSecXPCOpSyncWithKVSPeerIDOnly:{
1009 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyError, errSecUnimplemented);
5c19dc3a
A
1010 }
1011 break;
1012 case kSecXPCOpAccountSetToNew:
fa7225c8
A
1013 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1014 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCAccountSetToNew_Server(&error));
1015 }
5c19dc3a 1016 break;
427c49bc 1017 case kSecXPCOpResetToOffering:
fa7225c8
A
1018 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1019 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1020 SOSCCResetToOffering_Server(&error));
1021 }
427c49bc
A
1022 break;
1023 case kSecXPCOpResetToEmpty:
fa7225c8
A
1024 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1025 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1026 SOSCCResetToEmpty_Server(&error));
1027 }
427c49bc 1028 break;
79b9da22
A
1029 case kSecXPCOpResetToEmptyWithAnalytics:
1030 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1031 CFDataRef parentEvent = NULL;
1032 if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error) && parentEvent != NULL){
1033 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCResetToEmptyWithAnalytics_Server(parentEvent, &error));
1034 }else{
1035 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCResetToEmpty_Server(&error));
1036 }
1037 }
1038 break;
427c49bc 1039 case kSecXPCOpRemoveThisDeviceFromCircle:
fa7225c8
A
1040 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1041 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1042 SOSCCRemoveThisDeviceFromCircle_Server(&error));
1043 }
e0e0d90e 1044 break;
79b9da22
A
1045 case kSecXPCOpRemoveThisDeviceFromCircleWithAnalytics:
1046 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1047 CFDataRef parentEvent = NULL;
1048 if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error) && parentEvent != NULL){
1049 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRemoveThisDeviceFromCircleWithAnalytics_Server(parentEvent, &error));
1050 }else{
1051 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRemoveThisDeviceFromCircle_Server(&error));
1052 }
1053 CFReleaseNull(parentEvent);
1054 }
1055 break;
e0e0d90e 1056 case kSecXPCOpRemovePeersFromCircle:
fa7225c8 1057 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
6b200bc3 1058 CFArrayRef applicants = SecXPCDictionaryCopyPeerInfoArray(event, kSecXPCKeyPeerInfoArray, &error);
5c19dc3a 1059 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
e0e0d90e
A
1060 SOSCCRemovePeersFromCircle_Server(applicants, &error));
1061 CFReleaseNull(applicants);
1062 }
1063 break;
79b9da22
A
1064 case kSecXPCOpRemovePeersFromCircleWithAnalytics:
1065 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1066 CFArrayRef applicants = SecXPCDictionaryCopyPeerInfoArray(event, kSecXPCKeyPeerInfoArray, &error);
1067 CFDataRef parentEvent = NULL;
1068 if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error) && parentEvent != NULL){
1069 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRemovePeersFromCircleWithAnalytics_Server(applicants, parentEvent, &error));
1070 }else{
1071 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRemovePeersFromCircle_Server(applicants, &error));
1072 }
1073 CFReleaseNull(parentEvent);
1074 CFReleaseNull(applicants);
1075 }
1076 break;
e0e0d90e 1077 case kSecXPCOpLoggedOutOfAccount:
fa7225c8
A
1078 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1079 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1080 SOSCCLoggedOutOfAccount_Server(&error));
1081 }
e0e0d90e 1082 break;
427c49bc 1083 case kSecXPCOpBailFromCircle:
fa7225c8
A
1084 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1085 uint64_t limit_in_seconds = xpc_dictionary_get_uint64(event, kSecXPCLimitInMinutes);
1086 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1087 SOSCCBailFromCircle_Server(limit_in_seconds, &error));
427c49bc
A
1088 }
1089 break;
1090 case kSecXPCOpAcceptApplicants:
fa7225c8 1091 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
6b200bc3 1092 xpc_object_t xapplicants = xpc_dictionary_get_value(event, kSecXPCKeyPeerInfoArray);
427c49bc
A
1093 CFArrayRef applicants = CreateArrayOfPeerInfoWithXPCObject(xapplicants, &error); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1094 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1095 (applicants && SOSCCAcceptApplicants_Server(applicants, &error)));
1096 CFReleaseSafe(applicants);
1097 }
1098 break;
1099 case kSecXPCOpRejectApplicants:
fa7225c8 1100 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
6b200bc3 1101 xpc_object_t xapplicants = xpc_dictionary_get_value(event, kSecXPCKeyPeerInfoArray);
427c49bc
A
1102 CFArrayRef applicants = CreateArrayOfPeerInfoWithXPCObject(xapplicants, &error); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1103 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1104 (applicants && SOSCCRejectApplicants_Server(applicants, &error)));
1105 CFReleaseSafe(applicants);
1106 }
1107 break;
5c19dc3a
A
1108 case kSecXPCOpSetNewPublicBackupKey:
1109 {
fa7225c8 1110 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
822b670c
A
1111 CFDataRef publicBackupKey = SecXPCDictionaryCopyData(event, kSecXPCKeyNewPublicBackupKey, &error);
1112 SOSPeerInfoRef peerInfo = SOSCCSetNewPublicBackupKey_Server(publicBackupKey, &error);
1113 CFDataRef peerInfoData = peerInfo ? SOSPeerInfoCopyEncodedData(peerInfo, kCFAllocatorDefault, &error) : NULL;
1114 CFReleaseNull(peerInfo);
1115 if (peerInfoData) {
1116 xpc_object_t xpc_object = _CFXPCCreateXPCObjectFromCFObject(peerInfoData);
1117 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_object);
1118 xpc_release(xpc_object);
1119 }
1120 CFReleaseNull(peerInfoData);
1121 CFReleaseSafe(publicBackupKey);
5c19dc3a 1122
822b670c 1123 }
5c19dc3a
A
1124 }
1125 break;
6b200bc3
A
1126 case kSecXPCOpRegisterRecoveryPublicKey:
1127 {
1128 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
1129 CFDataRef recovery_key = SecXPCDictionaryCopyData(event, kSecXPCKeyRecoveryPublicKey, &error);
8a50f688
A
1130 uint8_t zero = 0;
1131 CFDataRef nullData = CFDataCreate(kCFAllocatorDefault, &zero, 1); // token we send if we really wanted to send NULL
1132 if(CFEqual(recovery_key, nullData)) {
1133 CFReleaseNull(recovery_key);
1134 }
1135 CFReleaseNull(nullData);
6b200bc3
A
1136 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCRegisterRecoveryPublicKey_Server(recovery_key, &error));
1137 CFReleaseNull(recovery_key);
1138 }
1139 }
1140 break;
1141 case kSecXPCOpGetRecoveryPublicKey:
1142 {
1143 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
1144 xpc_object_t xpc_recovery_object = NULL;
1145 CFDataRef recovery = SOSCCCopyRecoveryPublicKey(&error);
1146 if(recovery)
1147 xpc_recovery_object = _CFXPCCreateXPCObjectFromCFObject(recovery);
1148
1149 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_recovery_object);
1150 CFReleaseNull(recovery);
1151 }
1152 }
1153 break;
5c19dc3a
A
1154 case kSecXPCOpSetBagForAllSlices:
1155 {
fa7225c8 1156 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementRestoreKeychain, &error)) {
822b670c
A
1157 CFDataRef backupSlice = SecXPCDictionaryCopyData(event, kSecXPCKeyKeybag, &error);
1158 bool includeV0 = xpc_dictionary_get_bool(event, kSecXPCKeyIncludeV0);
1159 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, backupSlice && SOSCCRegisterSingleRecoverySecret_Server(backupSlice, includeV0, &error));
1160 CFReleaseSafe(backupSlice);
822b670c 1161 }
5c19dc3a
A
1162 }
1163 break;
427c49bc 1164 case kSecXPCOpCopyApplicantPeerInfo:
fa7225c8
A
1165 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1166 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1167 SOSCCCopyApplicantPeerInfo_Server(&error),
1168 &error);
1169 }
427c49bc 1170 break;
d8f41ccd 1171 case kSecXPCOpCopyValidPeerPeerInfo:
fa7225c8
A
1172 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1173 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1174 SOSCCCopyValidPeerPeerInfo_Server(&error),
1175 &error);
1176 }
d8f41ccd
A
1177 break;
1178 case kSecXPCOpValidateUserPublic:
fa7225c8 1179 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
d8f41ccd
A
1180 bool trusted = SOSCCValidateUserPublic_Server(&error);
1181 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, trusted);
1182 }
1183 break;
1184 case kSecXPCOpCopyNotValidPeerPeerInfo:
fa7225c8
A
1185 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1186 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1187 SOSCCCopyNotValidPeerPeerInfo_Server(&error),
1188 &error);
1189 }
d8f41ccd
A
1190 break;
1191 case kSecXPCOpCopyGenerationPeerInfo:
fa7225c8
A
1192 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1193 xpc_dictionary_set_and_consume_CFArray(replyMessage, kSecXPCKeyResult,
1194 SOSCCCopyGenerationPeerInfo_Server(&error));
1195 }
d8f41ccd
A
1196 break;
1197 case kSecXPCOpCopyRetirementPeerInfo:
fa7225c8
A
1198 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1199 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1200 SOSCCCopyRetirementPeerInfo_Server(&error),
1201 &error);
1202 }
e0e0d90e
A
1203 break;
1204 case kSecXPCOpCopyViewUnawarePeerInfo:
fa7225c8
A
1205 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1206 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1207 SOSCCCopyViewUnawarePeerInfo_Server(&error),
1208 &error);
1209 }
d8f41ccd 1210 break;
e3d460c9
A
1211 case kSecXPCOpCopyAccountData:
1212 {
fa7225c8 1213 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
e3d460c9
A
1214 xpc_object_t xpc_account_object = NULL;
1215 CFDataRef accountData = SOSCCCopyAccountState_Server(&error);
1216 if(accountData)
1217 xpc_account_object = _CFXPCCreateXPCObjectFromCFObject(accountData);
1218
1219 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_account_object);
1220 CFReleaseNull(accountData);
1221 }
e3d460c9
A
1222 break;
1223 }
1224 case kSecXPCOpDeleteAccountData:
1225 {
fa7225c8 1226 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
e3d460c9
A
1227 bool status = SOSCCDeleteAccountState_Server(&error);
1228 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, status);
1229 }
e3d460c9
A
1230 break;
1231 }
1232 case kSecXPCOpCopyEngineData:
fa7225c8
A
1233 {
1234 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1235
1236 xpc_object_t xpc_engine_object = NULL;
1237 CFDataRef engineData = SOSCCCopyEngineData_Server(&error);
1238 if(engineData)
1239 xpc_engine_object = _CFXPCCreateXPCObjectFromCFObject(engineData);
1240
1241 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_engine_object);
1242 CFReleaseNull(engineData);
1243
1244 }
1245 break;
e3d460c9 1246 }
e3d460c9 1247 case kSecXPCOpDeleteEngineData:
fa7225c8
A
1248 {
1249 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1250 bool status = SOSCCDeleteEngineState_Server(&error);
1251 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, status);
1252 }
1253 break;
e3d460c9 1254 }
5c19dc3a
A
1255 case kSecXPCOpCopyEngineState:
1256 {
fa7225c8 1257 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
e3d460c9 1258 CFArrayRef array = SOSCCCopyEngineState_Server(&error);
6b200bc3
A
1259 CFDataRef derData = NULL;
1260
1261 require_quiet(array, done);
1262 derData = CFPropertyListCreateDERData(kCFAllocatorDefault, array, &error);
1263
1264 require_quiet(derData, done);
1265 xpc_dictionary_set_data(replyMessage, kSecXPCKeyResult, CFDataGetBytePtr(derData), CFDataGetLength(derData));
1266 done:
1267 CFReleaseNull(derData);
e3d460c9
A
1268 CFReleaseNull(array);
1269 }
5c19dc3a
A
1270 }
1271 break;
427c49bc 1272 case kSecXPCOpCopyPeerPeerInfo:
fa7225c8
A
1273 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1274 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1275 SOSCCCopyPeerPeerInfo_Server(&error),
1276 &error);
1277 }
427c49bc
A
1278 break;
1279 case kSecXPCOpCopyConcurringPeerPeerInfo:
fa7225c8
A
1280 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1281 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage, kSecXPCKeyResult,
1282 SOSCCCopyConcurringPeerPeerInfo_Server(&error),
1283 &error);
1284 }
427c49bc 1285 break;
5c19dc3a 1286 case kSecXPCOpCopyMyPeerInfo:
fa7225c8 1287 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
5c19dc3a
A
1288 SOSPeerInfoRef peerInfo = SOSCCCopyMyPeerInfo_Server(&error);
1289 CFDataRef peerInfoData = peerInfo ? SOSPeerInfoCopyEncodedData(peerInfo, kCFAllocatorDefault, &error) : NULL;
1290 CFReleaseNull(peerInfo);
1291 if (peerInfoData) {
1292 xpc_object_t xpc_object = _CFXPCCreateXPCObjectFromCFObject(peerInfoData);
1293 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_object);
1294 xpc_release(xpc_object);
1295 }
1296 CFReleaseNull(peerInfoData);
1297 }
1298 break;
427c49bc 1299 case kSecXPCOpGetLastDepartureReason:
fa7225c8
A
1300 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1301 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1302 SOSCCGetLastDepartureReason_Server(&error));
1303 }
e0e0d90e 1304 break;
5c19dc3a 1305 case kSecXPCOpSetLastDepartureReason:
fa7225c8 1306 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
e0e0d90e
A
1307 int32_t reason = (int32_t) xpc_dictionary_get_int64(event, kSecXPCKeyReason);
1308 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1309 SOSCCSetLastDepartureReason_Server(reason, &error));
e0e0d90e 1310 }
6b200bc3
A
1311 break;
1312 case kSecXPCOpProcessSyncWithPeers:
1313 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainSyncUpdates, &error)) {
1314 CFSetRef peers = SecXPCDictionaryCopySet(event, kSecXPCKeySet, &error);
1315 CFSetRef backupPeers = SecXPCDictionaryCopySet(event, kSecXPCKeySet2, &error);
1316 if (peers && backupPeers) {
1317 CFSetRef result = SOSCCProcessSyncWithPeers_Server(peers, backupPeers, &error);
1318 if (result) {
1319 SecXPCDictionarySetPList(replyMessage, kSecXPCKeyResult, result, &error);
1320 }
1321 CFReleaseNull(result);
1322 }
1323 CFReleaseNull(peers);
1324 CFReleaseNull(backupPeers);
1325 }
1326 break;
427c49bc 1327 case kSecXPCOpProcessSyncWithAllPeers:
6b200bc3 1328 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainSyncUpdates, &error)) {
fa7225c8
A
1329 xpc_dictionary_set_int64(replyMessage, kSecXPCKeyResult,
1330 SOSCCProcessSyncWithAllPeers_Server(&error));
1331 }
e0e0d90e 1332 break;
d8f41ccd 1333 case soscc_EnsurePeerRegistration_id:
6b200bc3 1334 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainSyncUpdates, &error)) {
fa7225c8
A
1335 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1336 SOSCCProcessEnsurePeerRegistration_Server(&error));
1337 }
427c49bc 1338 break;
e0e0d90e 1339 case kSecXPCOpCopyIncompatibilityInfo:
fa7225c8 1340 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
e0e0d90e
A
1341 CFStringRef iis = SOSCCCopyIncompatibilityInfo_Server(&error);
1342 SecXPCDictionarySetString(replyMessage, kSecXPCKeyResult, iis, &error);
1343 CFReleaseSafe(iis);
e0e0d90e 1344 }
6b200bc3 1345 break;
d8f41ccd
A
1346 case kSecXPCOpRollKeys:
1347 {
1348 bool force = xpc_dictionary_get_bool(event, "force");
1349 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
e3d460c9 1350 _SecServerRollKeys(force, &client, &error));
d8f41ccd
A
1351 }
1352 break;
5c19dc3a 1353 case kSecXPCOpWaitForInitialSync:
fa7225c8
A
1354 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1355 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1356 SOSCCWaitForInitialSync_Server(&error));
1357 }
e0e0d90e 1358 break;
5c19dc3a 1359
79b9da22
A
1360 case kSecXPCOpWaitForInitialSyncWithAnalytics:
1361 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1362 CFDataRef parentEvent = NULL;
1363 if(SecXPCDictionaryCopyDataOptional(event, kSecXPCKeySignInAnalytics, &parentEvent, &error) && parentEvent != NULL){
1364 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCWaitForInitialSyncWithAnalytics_Server(parentEvent, &error));
1365 }else{
1366 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCWaitForInitialSync_Server(&error));
1367 }
1368 CFReleaseNull(parentEvent);
1369 }
1370 break;
5c19dc3a 1371 case kSecXPCOpCopyYetToSyncViews:
fa7225c8 1372 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
5c19dc3a
A
1373 CFArrayRef array = SOSCCCopyYetToSyncViewsList_Server(&error);
1374 if (array) {
1375 xpc_object_t xpc_array = _CFXPCCreateXPCObjectFromCFObject(array);
1376 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_array);
1377 xpc_release(xpc_array);
1378 }
1379 CFReleaseNull(array);
1380 }
427c49bc 1381 break;
e0e0d90e 1382 case kSecXPCOpSetEscrowRecord:
fa7225c8 1383 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
e0e0d90e
A
1384 CFStringRef escrow_label = SecXPCDictionaryCopyString(event, kSecXPCKeyEscrowLabel, &error);
1385 uint64_t tries = xpc_dictionary_get_int64(event, kSecXPCKeyTriesLabel);
5c19dc3a 1386
e0e0d90e
A
1387 bool result = SOSCCSetEscrowRecord_Server(escrow_label, tries, &error);
1388 if (result) {
1389 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
1390 }
1391 CFReleaseNull(escrow_label);
1392 }
1393 break;
1394 case kSecXPCOpGetEscrowRecord:
fa7225c8 1395 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
e0e0d90e
A
1396 CFDictionaryRef record = SOSCCCopyEscrowRecord_Server(&error);
1397 if (record) {
1398 xpc_object_t xpc_dictionary = _CFXPCCreateXPCObjectFromCFObject(record);
1399 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_dictionary);
1400 xpc_release(xpc_dictionary);
1401 }
1402 CFReleaseNull(record);
1403 }
1404 break;
6b200bc3
A
1405 case kSecXPCOpCopyBackupInformation:
1406 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1407 CFDictionaryRef record = SOSCCCopyBackupInformation_Server(&error);
1408 if (record) {
1409 xpc_object_t xpc_dictionary = _CFXPCCreateXPCObjectFromCFObject(record);
1410 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_dictionary);
1411 xpc_release(xpc_dictionary);
1412 }
1413 CFReleaseNull(record);
1414 }
1415 break;
fa7225c8
A
1416
1417 case kSecXPCOpIsThisDeviceLastBackup:
1418 if (EntitlementPresentOrWhine(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1419 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, SOSCCkSecXPCOpIsThisDeviceLastBackup_Server(&error));
1420 }
1421 break;
1422 case kSecXPCOpPeersHaveViewsEnabled:
1423 {
1424 CFArrayRef viewSet = SecXPCDictionaryCopyArray(event, kSecXPCKeyArray, &error);
1425 if (viewSet) {
1426 CFBooleanRef result = SOSCCPeersHaveViewsEnabled_Server(viewSet, &error);
ecaf5866 1427 if (result != NULL) {
fa7225c8
A
1428 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result != kCFBooleanFalse);
1429 }
1430 }
1431 CFReleaseNull(viewSet);
1432 }
1433 break;
1434
e3d460c9
A
1435 case kSecXPCOpWhoAmI:
1436 {
1437 if (client.musr)
1438 xpc_dictionary_set_data(replyMessage, "musr", CFDataGetBytePtr(client.musr), CFDataGetLength(client.musr));
1439 xpc_dictionary_set_bool(replyMessage, "system-keychain", client.allowSystemKeychain);
1440 xpc_dictionary_set_bool(replyMessage, "syncbubble-keychain", client.allowSyncBubbleKeychain);
1441 xpc_dictionary_set_bool(replyMessage, "network-extension", client.isNetworkExtension);
1442 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true);
1443 }
1444 break;
1445 case kSecXPCOpTransmogrifyToSyncBubble:
1446 {
fa7225c8 1447 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementPrivateKeychainSyncBubble, &error)) {
e3d460c9
A
1448#if TARGET_OS_IOS
1449 uid_t uid = (uid_t)xpc_dictionary_get_int64(event, "uid");
1450 CFArrayRef services = SecXPCDictionaryCopyArray(event, "services", &error);
1451 bool res = false;
1452 if (uid && services) {
1453 res = _SecServerTransmogrifyToSyncBubble(services, uid, &client, &error);
1454 }
1455 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, res);
1456 CFReleaseNull(services);
1457#else
1458 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, false);
1459#endif
e3d460c9
A
1460 }
1461 }
1462 break;
1463 case kSecXPCOpTransmogrifyToSystemKeychain:
1464 {
fa7225c8 1465 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementPrivateKeychainMigrateSystemKeychain, &error)) {
e3d460c9
A
1466#if TARGET_OS_IOS
1467 bool res = _SecServerTransmogrifyToSystemKeychain(&client, &error);
1468 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, res);
1469#else
1470 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, false);
1471#endif
1472
e3d460c9
A
1473 }
1474 }
1475 break;
1476 case kSecXPCOpDeleteUserView:
1477 {
fa7225c8 1478 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementPrivateKeychainMigrateSystemKeychain, &error)) {
e3d460c9
A
1479 bool res = false;
1480#if TARGET_OS_IOS
1481 uid_t uid = (uid_t)xpc_dictionary_get_int64(event, "uid");
1482 if (uid) {
1483 res = _SecServerDeleteMUSERViews(&client, uid, &error);
1484 }
1485#endif
1486 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, res);
1487
e3d460c9
A
1488 }
1489 }
6b200bc3 1490 break;
e3d460c9
A
1491 case kSecXPCOpWrapToBackupSliceKeyBagForView:
1492 {
1493 CFStringRef viewname = SecXPCDictionaryCopyString(event, kSecXPCKeyViewName, &error);
1494 if(viewname) {
1495 CFDataRef plaintext = SecXPCDictionaryCopyData(event, kSecXPCData, &error);
1496 if (plaintext) {
1497 CFDataRef ciphertext = NULL;
1498 CFDataRef bskbEncoded = NULL;
1499
1500 bool result = SOSWrapToBackupSliceKeyBagForView_Server(viewname, plaintext, &ciphertext, &bskbEncoded, &error);
1501 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
1502
fa7225c8 1503 if(!error && result) {
e3d460c9
A
1504 if(ciphertext) {
1505 xpc_dictionary_set_data(replyMessage, kSecXPCData, CFDataGetBytePtr(ciphertext), CFDataGetLength(ciphertext));
1506 }
1507 if(bskbEncoded) {
1508 xpc_dictionary_set_data(replyMessage, kSecXPCKeyKeybag, CFDataGetBytePtr(bskbEncoded), CFDataGetLength(bskbEncoded));
1509 }
1510 }
fa7225c8
A
1511 CFReleaseSafe(ciphertext);
1512 CFReleaseSafe(bskbEncoded);
e3d460c9
A
1513 }
1514 CFReleaseSafe(plaintext);
1515 }
1516 CFReleaseNull(viewname);
1517 }
1518 break;
fa7225c8
A
1519 case kSecXPCOpCopyApplication:
1520 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementCircleJoin, &error)) {
1521 SOSPeerInfoRef peerInfo = SOSCCCopyApplication_Server(&error);
1522 CFDataRef peerInfoData = peerInfo ? SOSPeerInfoCopyEncodedData(peerInfo, kCFAllocatorDefault, &error) : NULL;
1523 CFReleaseNull(peerInfo);
1524 if (peerInfoData) {
1525 xpc_object_t xpc_object = _CFXPCCreateXPCObjectFromCFObject(peerInfoData);
1526 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_object);
1527 xpc_release(xpc_object);
1528 }
1529 CFReleaseNull(peerInfoData);
1530 }
1531 break;
1532 case kSecXPCOpCopyCircleJoiningBlob:
1533 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementCircleJoin, &error)) {
1534 CFDataRef appBlob = SecXPCDictionaryCopyCFDataRef(event, kSecXPCData, &error);
1535 SOSPeerInfoRef applicant = SOSPeerInfoCreateFromData(kCFAllocatorDefault, &error, appBlob);
1536 CFDataRef pbblob = SOSCCCopyCircleJoiningBlob_Server(applicant, &error);
1537 if (pbblob) {
1538 xpc_object_t xpc_object = _CFXPCCreateXPCObjectFromCFObject(pbblob);
1539 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_object);
1540 xpc_release(xpc_object);
1541 }
1542 CFReleaseNull(pbblob);
1543 CFReleaseNull(applicant);
1544 CFReleaseNull(appBlob);
1545 }
1546 break;
866f8763
A
1547 case kSecXPCOpCopyInitialSyncBlob:
1548 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementCircleJoin, &error)) {
1549 CFDataRef initialblob = SOSCCCopyInitialSyncData_Server(&error);
1550 if (initialblob) {
1551 xpc_object_t xpc_object = _CFXPCCreateXPCObjectFromCFObject(initialblob);
1552 xpc_dictionary_set_value(replyMessage, kSecXPCKeyResult, xpc_object);
1553 xpc_release(xpc_object);
1554 }
1555 CFReleaseNull(initialblob);
1556 }
1557 break;
fa7225c8
A
1558 case kSecXPCOpJoinWithCircleJoiningBlob:
1559 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementCircleJoin, &error)) {
1560 CFDataRef joiningBlob = SecXPCDictionaryCopyCFDataRef(event, kSecXPCData, &error);
866f8763
A
1561 uint64_t version = xpc_dictionary_get_uint64(event, kSecXPCVersion);
1562 bool retval = SOSCCJoinWithCircleJoiningBlob_Server(joiningBlob, (PiggyBackProtocolVersion) version, &error);
fa7225c8
A
1563 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, retval);
1564 CFReleaseNull(joiningBlob);
1565 }
1566 break;
866f8763
A
1567
1568 case kSecXPCOpKVSKeyCleanup:
1569 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1570 bool retval = SOSCCCleanupKVSKeys_Server(&error);
1571 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, retval);
1572 }
1573 break;
1574 case kSecXPCOpPopulateKVS:
1575 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainCloudCircle, &error)) {
1576 bool retval = SOSCCTestPopulateKVSWithBadKeys_Server(&error);
1577 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, retval);
1578 }
1579 break;
6b200bc3
A
1580 case kSecXPCOpMessageFromPeerIsPending:
1581 {
1582 SOSPeerInfoRef peer = SecXPCDictionaryCopyPeerInfo(event, kSecXPCKeyPeerInfo, &error);
1583 if (peer) {
1584 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1585 SOSCCMessageFromPeerIsPending_Server(peer, &error));
1586 }
1587 CFReleaseNull(peer);
1588 break;
1589 }
1590 case kSecXPCOpSendToPeerIsPending:
1591 {
1592 SOSPeerInfoRef peer = SecXPCDictionaryCopyPeerInfo(event, kSecXPCKeyPeerInfo, &error);
1593 if (peer) {
1594 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult,
1595 SOSCCSendToPeerIsPending(peer, &error));
1596 }
1597 CFReleaseNull(peer);
1598 break;
1599 }
fa7225c8
A
1600 case sec_delete_items_with_access_groups_id:
1601 {
1602 bool retval = false;
1603#if TARGET_OS_IPHONE
1604 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementPrivateUninstallDeletion, &error)) {
1605 CFArrayRef accessGroups = SecXPCDictionaryCopyArray(event, kSecXPCKeyAccessGroups, &error);
1606
1607 if (accessGroups) {
1608 retval = _SecItemServerDeleteAllWithAccessGroups(accessGroups, &client, &error);
1609 }
fa7225c8
A
1610 CFReleaseNull(accessGroups);
1611 }
1612#endif
1613 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, retval);
1614 }
1615 break;
866f8763
A
1616 case sec_item_copy_parent_certificates_id:
1617 {
1618 CFArrayRef results = NULL;
1619 if(EntitlementPresentAndTrue(operation, client.task, kSecEntitlementPrivateCertificateAllAccess, &error)) {
1620 CFDataRef issuer = SecXPCDictionaryCopyData(event, kSecXPCKeyNormalizedIssuer, &error);
1621 CFArrayRef accessGroups = SecXPCDictionaryCopyArray(event, kSecXPCKeyAccessGroups, &error);
1622 if (issuer && accessGroups) {
1623 results = _SecItemCopyParentCertificates(issuer, accessGroups, &error);
1624 }
1625 CFReleaseNull(issuer);
1626 CFReleaseNull(accessGroups);
1627 }
1628 SecXPCDictionarySetPListOptional(replyMessage, kSecXPCKeyResult, results, &error);
1629 CFReleaseNull(results);
1630 }
1631 break;
1632 case sec_item_certificate_exists_id:
1633 {
1634 bool result = false;
1635 if(EntitlementPresentAndTrue(operation, client.task, kSecEntitlementPrivateCertificateAllAccess, &error)) {
1636 CFDataRef issuer = SecXPCDictionaryCopyData(event, kSecXPCKeyNormalizedIssuer, &error);
1637 CFDataRef serialNum = SecXPCDictionaryCopyData(event, kSecXPCKeySerialNumber, &error);
1638 CFArrayRef accessGroups = SecXPCDictionaryCopyArray(event, kSecXPCKeyAccessGroups, &error);
1639 if (issuer && serialNum && accessGroups) {
1640 result = _SecItemCertificateExists(issuer, serialNum, accessGroups, &error);
1641 }
1642 CFReleaseNull(issuer);
1643 CFReleaseNull(serialNum);
1644 CFReleaseNull(accessGroups);
1645 }
1646 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, result);
1647 }
1648 break;
866f8763
A
1649 case kSecXPCOpBackupKeybagAdd: {
1650 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementBackupTableOperations, &error)) {
1651 CFDataRef keybag = NULL, passcode = NULL;
1652 if (SecXPCDictionaryCopyDataOptional(event, kSecXPCKeyUserPassword, &passcode, &error)) {
1653 CFDataRef identifier = NULL;
1654 CFDataRef pathinfo = NULL; // really a CFURLRef
1655 bool added = _SecServerBackupKeybagAdd(&client, passcode, &identifier, &pathinfo, &error);
1656 if (added) {
1657 added &= SecXPCDictionarySetDataOptional(replyMessage, kSecXPCKeyBackupKeybagIdentifier, identifier, &error);
1658 added &= SecXPCDictionarySetDataOptional(replyMessage, kSecXPCKeyBackupKeybagPath, pathinfo, &error);
1659 SecXPCDictionarySetBool(replyMessage, kSecXPCKeyResult, added, NULL);
1660 } else {
1661 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, false);
1662 }
1663 }
1664 CFReleaseSafe(passcode);
1665 CFReleaseSafe(keybag);
1666 }
1667 break;
1668 }
1669 case kSecXPCOpBackupKeybagDelete: {
1670 // >>>
1671 if (EntitlementPresentAndTrue(operation, client.task, kSecEntitlementBackupTableOperations, &error)) {
1672 bool deleted = false;
1673 CFDictionaryRef query = SecXPCDictionaryCopyDictionary(event, kSecXPCKeyQuery, &error);
1674 if (query) {
1675 CFTypeRef matchLimit = CFDictionaryGetValue(query, kSecMatchLimit);
1676 bool deleteAll = matchLimit && CFEqualSafe(matchLimit, kSecMatchLimitAll);
1677
1678 if (deleteAll && !EntitlementPresentAndTrue(operation, client.task, kSecEntitlementBackupTableOperationsDeleteAll, &error)) {
1679 // require special entitlement to delete all backup keybags
1680 } else {
1681 CFMutableDictionaryRef attributes = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, query);
1682 CFStringRef requestedAgrp = CFDictionaryGetValue(attributes, kSecAttrAccessGroup);
1683 CFStringRef resolvedAgrp = NULL;
1684 if (client.musr) {
1685 CFDictionarySetValue(attributes, kSecAttrMultiUser, client.musr);
1686 }
1687 if (extractAccessGroup(&client, requestedAgrp, &resolvedAgrp, &error)) {
1688 if (resolvedAgrp) {
1689 CFDictionarySetValue(attributes, kSecAttrAccessGroup, resolvedAgrp);
1690 }
1691 deleted = _SecServerBackupKeybagDelete(attributes, deleteAll, &error);
1692 }
866f8763
A
1693 CFReleaseNull(attributes);
1694 }
1695 }
1696 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, deleted);
1697 CFReleaseNull(query);
1698 }
1699 break;
1700 }
ecaf5866
A
1701 case kSecXPCOpKeychainControlEndpoint: {
1702 if(EntitlementPresentAndTrue(operation, client.task, kSecEntitlementKeychainControl, &error)) {
1703 xpc_endpoint_t endpoint = SecServerCreateKeychainControlEndpoint();
1704 if (endpoint) {
1705 xpc_dictionary_set_value(replyMessage, kSecXPCKeyEndpoint, endpoint);
1706 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, true);
1707 xpc_release(endpoint);
1708 } else {
1709 xpc_dictionary_set_bool(replyMessage, kSecXPCKeyResult, false);
1710 }
1711 }
1712 break;
1713 }
e3d460c9 1714 default:
5c19dc3a 1715 break;
427c49bc 1716 }
5c19dc3a 1717
427c49bc
A
1718 if (error)
1719 {
d8f41ccd 1720 if(SecErrorGetOSStatus(error) == errSecItemNotFound || isSOSErrorCoded(error, kSOSErrorPublicKeyAbsent))
e3d460c9 1721 secdebug("ipc", "%@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
5c19dc3a 1722 else if (SecErrorGetOSStatus(error) == errSecAuthNeeded)
e3d460c9 1723 secwarning("Authentication is needed %@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
427c49bc 1724 else
e3d460c9 1725 secerror("%@ %@ %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), error);
4d3cab3d 1726
427c49bc 1727 xpcError = SecCreateXPCObjectWithCFError(error);
5c19dc3a
A
1728 if (replyMessage) {
1729 xpc_dictionary_set_value(replyMessage, kSecXPCKeyError, xpcError);
1730 }
427c49bc 1731 } else if (replyMessage) {
e3d460c9 1732 secdebug("ipc", "%@ %@ responding %@", client.task, SOSCCGetOperationDescription((enum SecXPCOperation)operation), replyMessage);
427c49bc
A
1733 }
1734 } else {
d8f41ccd 1735 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, &error, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event);
e3d460c9 1736 secerror("%@: returning error: %@", client.task, error);
427c49bc
A
1737 xpcError = SecCreateXPCObjectWithCFError(error);
1738 replyMessage = xpc_create_reply_with_format(event, "{%string: %value}", kSecXPCKeyError, xpcError);
b1ab9ed8
A
1739 }
1740
427c49bc
A
1741 if (replyMessage) {
1742 xpc_connection_send_message(connection, replyMessage);
1743 xpc_release(replyMessage);
1744 }
1745 if (xpcError)
1746 xpc_release(xpcError);
1747 CFReleaseSafe(error);
e3d460c9
A
1748 CFReleaseSafe(client.accessGroups);
1749 CFReleaseSafe(client.musr);
1750 CFReleaseSafe(client.task);
d8f41ccd 1751 CFReleaseSafe(domains);
5c19dc3a 1752 CFReleaseSafe(clientAuditToken);
b1ab9ed8
A
1753}
1754
5c19dc3a 1755static void securityd_xpc_init(const char *service_name)
b1ab9ed8 1756{
427c49bc 1757 secdebug("serverxpc", "start");
5c19dc3a 1758 xpc_connection_t listener = xpc_connection_create_mach_service(service_name, NULL, XPC_CONNECTION_MACH_SERVICE_LISTENER);
427c49bc 1759 if (!listener) {
5c19dc3a 1760 seccritical("security failed to register xpc listener for %s, exiting", service_name);
427c49bc 1761 abort();
b1ab9ed8 1762 }
b1ab9ed8 1763
427c49bc
A
1764 xpc_connection_set_event_handler(listener, ^(xpc_object_t connection) {
1765 if (xpc_get_type(connection) == XPC_TYPE_CONNECTION) {
1766 xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
1767 if (xpc_get_type(event) == XPC_TYPE_DICTIONARY) {
79b9da22
A
1768 /*
1769 * rdar://problem/37690394&39323293
1770 * Some operations cannot be performed synchronously.
1771 * SecItemCopyMatching is particularly important, and
1772 * should be safe to perform synchronously.
1773 */
1774 uint64_t operation = xpc_dictionary_get_uint64(event, kSecXPCKeyOperation);
1775 if (operation == sec_item_copy_matching_id) {
427c49bc 1776 securityd_xpc_dictionary_handler(connection, event);
79b9da22
A
1777 } else {
1778 xpc_retain(connection);
1779 xpc_retain(event);
1780 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
1781 securityd_xpc_dictionary_handler(connection, event);
1782 xpc_release(event);
1783 xpc_release(connection);
1784 });
1785 }
427c49bc
A
1786 }
1787 });
1788 xpc_connection_resume(connection);
1789 }
1790 });
1791 xpc_connection_resume(listener);
866f8763
A
1792
1793#if OCTAGON
1794 xpc_activity_register("com.apple.securityd.daily", XPC_ACTIVITY_CHECK_IN, ^(xpc_activity_t activity) {
1795 xpc_activity_state_t activityState = xpc_activity_get_state(activity);
1796 if (activityState == XPC_ACTIVITY_STATE_RUN) {
1797 SecCKKS24hrNotification();
1798 }
1799 });
1800#endif
427c49bc 1801}
b1ab9ed8 1802
5c19dc3a 1803
e0e0d90e
A
1804// <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1805
e3d460c9 1806#if TARGET_OS_EMBEDDED
e0e0d90e
A
1807static void securityd_soscc_lock_hack() {
1808 dispatch_queue_t soscc_lock_queue = dispatch_queue_create("soscc_lock_queue", DISPATCH_QUEUE_PRIORITY_DEFAULT);
1809 int soscc_tok;
e0e0d90e
A
1810
1811 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1812 // FIXME: securityd isn't currently registering for any other notifyd events. If/when it does,
1813 // this code will need to be generalized / migrated away from just this specific purpose.
1814 xpc_set_event_stream_handler("com.apple.notifyd.matching", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(xpc_object_t object) {
1815 char *event_description = xpc_copy_description(object);
1816 secnotice("events", "%s", event_description);
1817 free(event_description);
1818 });
1819
fa7225c8
A
1820 secnotice("lockassertion", "notify_register_dispatch(kSOSCCHoldLockForInitialSync)");
1821 notify_register_dispatch(kSOSCCHoldLockForInitialSync, &soscc_tok, soscc_lock_queue, ^(int token __unused) {
1822 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync: grabbing the lock");
e3d460c9 1823 CFErrorRef error = NULL;
fa7225c8 1824
e3d460c9
A
1825 uint64_t one_minute = 60ull;
1826 if(SecAKSLockUserKeybag(one_minute, &error)){
1827 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
fa7225c8 1828 xpc_transaction_begin();
e0e0d90e 1829
fa7225c8 1830 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, one_minute*NSEC_PER_SEC), soscc_lock_queue, ^{
e3d460c9
A
1831 CFErrorRef localError = NULL;
1832 if(!SecAKSUnLockUserKeybag(&localError))
1833 secerror("failed to unlock: %@", localError);
1834 CFReleaseNull(localError);
1835 xpc_transaction_end();
fa7225c8 1836 });
e0e0d90e 1837 } else {
e3d460c9 1838 secerror("Failed to take device lock assertion: %@", error);
e0e0d90e 1839 }
fa7225c8 1840 CFReleaseNull(error);
e0e0d90e 1841 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync => done");
e0e0d90e
A
1842 });
1843}
e3d460c9 1844#endif
5c19dc3a 1845
866f8763
A
1846#if TARGET_OS_OSX
1847
1848static char *
1849homedirPath(void)
1850{
1851 static char homeDir[PATH_MAX] = {};
1852
1853 if (homeDir[0] == '\0') {
1854 struct passwd* pwd = getpwuid(getuid());
1855 if (pwd == NULL)
1856 return NULL;
1857
1858 if (realpath(pwd->pw_dir, homeDir) == NULL) {
1859 strlcpy(homeDir, pwd->pw_dir, sizeof(homeDir));
1860 }
1861 }
1862 return homeDir;
fa7225c8
A
1863}
1864#endif
1865
866f8763 1866
b1ab9ed8
A
1867int main(int argc, char *argv[])
1868{
427c49bc
A
1869 char *wait4debugger = getenv("WAIT4DEBUGGER");
1870 if (wait4debugger && !strcasecmp("YES", wait4debugger)) {
1871 seccritical("SIGSTOPing self, awaiting debugger");
1872 kill(getpid(), SIGSTOP);
fa7225c8 1873 seccritical("Again, for good luck (or bad debuggers)");
427c49bc
A
1874 kill(getpid(), SIGSTOP);
1875 }
1876
fa7225c8
A
1877/* <rdar://problem/15792007> Users with network home folders are unable to use/save password for Mail/Cal/Contacts/websites
1878 Secd doesn't realize DB connections get invalidated when network home directory users logout
1879 and their home gets unmounted. Exit secd, start fresh when user logs back in.
1880*/
866f8763 1881#if TARGET_OS_OSX
fa7225c8
A
1882 int sessionstatechanged_tok;
1883 notify_register_dispatch(kSA_SessionStateChangedNotification, &sessionstatechanged_tok, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(int token __unused) {
1884 // we could be a process running as root.
1885 // However, since root never logs out this isn't an issue.
1886 if (SASSessionStateForUser(getuid()) == kSA_state_loggingout_pointofnoreturn) {
1887 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3ull*NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
1888 xpc_transaction_exit_clean();
1889 });
1890 }
1891 });
1892#endif
641423b6 1893
866f8763
A
1894#if TARGET_OS_OSX
1895#define SECD_PROFILE_NAME "com.apple.secd"
1896 const char *homedir = homedirPath();
1897 if (homedir == NULL)
1898 errx(1, "failed to get home directory for secd");
1899
1900 char *errorbuf = NULL;
1901 const char *sandbox_params[] = {
1902 "_HOME", homedir,
1903 NULL
1904 };
1905 int32_t rc;
1906
1907 rc = sandbox_init_with_parameters(SECD_PROFILE_NAME, SANDBOX_NAMED, sandbox_params, &errorbuf);
1908 if (rc)
1909 err(1, "Failed to process in a sandbox: %d %s", rc, errorbuf);
1910#endif /* TARGET_OS_OSX */
1911
641423b6 1912 const char *serviceName = kSecuritydXPCServiceName;
fa7225c8 1913 /* setup SQDLite before some other component have a chance to create a database connection */
866f8763 1914 _SecDbServerSetup();
fa7225c8 1915
641423b6
A
1916 securityd_init_server();
1917 securityd_xpc_init(serviceName);
1918
ecaf5866
A
1919 SecCreateSecuritydXPCServer();
1920 CKKSControlServerInitialize();
1921 SOSControlServerInitialize();
1922 OctagonControlServerInitialize();
79b9da22 1923 SFKeychainServerInitialize();
ecaf5866 1924
e0e0d90e 1925 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
e3d460c9 1926#if TARGET_OS_EMBEDDED
e0e0d90e 1927 securityd_soscc_lock_hack();
e3d460c9 1928#endif
e0e0d90e 1929
427c49bc 1930 dispatch_main();
b1ab9ed8
A
1931}
1932
1933/* vi:set ts=4 sw=4 et: */