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