2 * Copyright (c) 2007-2017 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
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>
29 #include <Security/SecureObjectSync/SOSControlServer.h>
30 #include <Security/SecBase.h>
31 #include <Security/SecBasePriv.h>
32 #include <Security/SecCertificatePriv.h>
33 #include <Security/SecEntitlements.h>
34 #include <Security/SecInternal.h>
35 #include <Security/SecItem.h>
36 #include <Security/SecItemPriv.h>
37 #include <Security/SecPolicy.h>
38 #include <Security/SecPolicyInternal.h>
39 #include <Security/SecTask.h>
40 #include <Security/SecTrustInternal.h>
41 #include <Security/SecuritydXPC.h>
42 #include <securityd/OTATrustUtilities.h>
43 #include <securityd/SOSCloudCircleServer.h>
44 #include <securityd/SecItemBackupServer.h>
45 #include <securityd/SecItemServer.h>
46 #include <securityd/SecLogSettingsServer.h>
47 #include <securityd/SecOTRRemote.h>
48 #include <securityd/SecTrustServer.h>
49 #include <securityd/SecTrustStoreServer.h>
50 #include <securityd/iCloudTrace.h>
51 #include <securityd/spi.h>
52 #include <utilities/SecCFError.h>
53 #include <utilities/SecCFWrappers.h>
54 #include <utilities/SecDb.h>
55 #include <utilities/SecIOFormat.h>
56 #include <utilities/SecXPCError.h>
57 #include <utilities/debugging.h>
58 #include <utilities/SecInternalReleasePriv.h>
59 #include <utilities/der_plist_internal.h>
60 #include <utilities/der_plist.h>
61 #include <securityd/personalization.h>
62 #include <securityd/SecPinningDb.h>
63 #include <securityd/SFKeychainControlManager.h>
65 #include <keychain/ckks/CKKS.h>
66 #include <keychain/ckks/CKKSControlServer.h>
67 #include "keychain/ot/OctagonControlServer.h"
69 #include <securityd/SFKeychainServer.h>
71 #include <AssertMacros.h>
72 #include <CoreFoundation/CFXPCBridge.h>
73 #include <CoreFoundation/CoreFoundation.h>
74 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
77 #include <Security/SecTaskPriv.h>
78 #include <login/SessionAgentStatusCom.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>
88 #include <sys/queue.h>
89 #include <sys/sysctl.h>
91 #include <xpc/private.h>
94 #include <ipc/server_security_helpers.h>
95 #include <ipc/server_entitlement_helpers.h>
103 static bool accessGroupPermitted(SecurityClient
* client
, CFArrayRef accessGroups
, CFStringRef accessGroup
) {
104 /* NULL accessGroups is wildcard. */
107 /* Make sure we have a string. */
108 if (!isString(accessGroup
))
111 /* Having the special accessGroup "*" allows access to all accessGroups. */
112 CFRange range
= { 0, CFArrayGetCount(accessGroups
) };
114 (CFArrayContainsValue(accessGroups
, range
, accessGroup
) ||
115 CFArrayContainsValue(accessGroups
, range
, CFSTR("*"))))
121 static bool extractAccessGroup(SecurityClient
*client
, CFStringRef requestedAgrp
, CFStringRef
*resolvedAgrp
, CFErrorRef
*error
) {
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("*")))
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
);
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);
142 if (agrp
&& resolvedAgrp
)
143 *resolvedAgrp
= agrp
;
147 static 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
);
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
);
154 CFDataRef user_password
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
);
155 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
157 action(user_label
, user_password
);
159 CFReleaseNull(user_password
);
160 CFReleaseNull(user_label
);
164 static 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
);
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
);
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
);
176 action(user_label
, user_password
, dsid
);
179 CFReleaseNull(user_password
);
180 CFReleaseNull(user_label
);
184 static 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
);
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
);
191 action(user_label
, number
);
192 CFReleaseNull(user_label
);
196 static CFArrayRef
SecXPCDictionaryCopyPeerInfoArray(xpc_object_t dictionary
, const char *key
, CFErrorRef
*error
) {
197 return CreateArrayOfPeerInfoWithXPCObject(xpc_dictionary_get_value(dictionary
, key
), error
);
200 static CFDataRef
SecXPCDictionaryCopyCFDataRef(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
201 CFDataRef retval
= NULL
;
202 const uint8_t *bytes
= NULL
;
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
));
213 static 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")));
217 require_action_quiet(xpc_get_type(xpcSetDER
) == XPC_TYPE_DATA
, errOut
, SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, error
, NULL
, CFSTR("xpcSetDER not data, got %@"), xpcSetDER
));
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"));
228 CFReleaseNull(retval
);
232 static SOSPeerInfoRef
SecXPCDictionaryCopyPeerInfo(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
234 const uint8_t *der
= xpc_dictionary_get_data(message
, key
, &length
);
236 return SecRequirementError(der
!= NULL
, error
, CFSTR("No data for key %s"), key
) ? SOSPeerInfoCreateFromDER(kCFAllocatorDefault
, error
, &der
, der
+ length
) : NULL
;
239 static 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
);
249 void xpc_dictionary_set_and_consume_CFArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef 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
);
255 CFReleaseNull(cf_array
);
259 bool xpc_dictionary_set_and_consume_PeerInfoArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
, CFErrorRef
*error
) {
262 xpc_object_t xpc_array
= CreateXPCObjectWithArrayOfPeerInfo(cf_array
, error
);
264 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
265 xpc_release(xpc_array
);
270 CFReleaseNull(cf_array
);
275 SecDataCopyMmapFileDescriptor(int fd
, void **mem
, size_t *size
, CFErrorRef
*error
)
278 if (fstat(fd
, &sb
) < 0) {
282 *size
= (size_t)sb
.st_size
;
283 if ((off_t
)*size
!= sb
.st_size
) {
287 *mem
= mmap(NULL
, *size
, PROT_READ
, MAP_SHARED
, fd
, 0);
288 if (*mem
== MAP_FAILED
) {
292 return CFDataCreateWithBytesNoCopy(NULL
, *mem
, *size
, kCFAllocatorNull
);
296 SecDataWriteFileDescriptor(int fd
, CFDataRef data
)
298 CFIndex count
= CFDataGetLength(data
);
299 const uint8_t *ptr
= CFDataGetBytePtr(data
);
300 bool writeResult
= false;
303 ssize_t ret
= write(fd
, ptr
, count
);
316 // Returns error if entitlement isn't present.
318 EntitlementPresentAndTrue(uint64_t op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
320 if (!SecTaskGetBooleanValueForEntitlement(clientTask
, entitlement
)) {
321 SecError(errSecMissingEntitlement
, error
, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
)op
), clientTask
, entitlement
);
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
330 EntitlementPresentOrWhine(uint64_t op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
332 if (!SecTaskGetBooleanValueForEntitlement(clientTask
, entitlement
))
333 secnotice("serverxpc", "%@: %@ lacks entitlement %@", SOSCCGetOperationDescription((enum SecXPCOperation
)op
), clientTask
, entitlement
);
340 EntitlementAbsentOrFalse(uint64_t op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
342 if (SecTaskGetBooleanValueForEntitlement(clientTask
, entitlement
)) {
343 SecError(errSecNotAvailable
, error
, CFSTR("%@: %@ has entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
) op
), clientTask
, entitlement
);
349 static void securityd_xpc_dictionary_handler(const xpc_connection_t connection
, xpc_object_t event
) {
350 xpc_type_t type
= xpc_get_type(event
);
351 __block CFErrorRef error
= NULL
;
352 xpc_object_t xpcError
= NULL
;
353 xpc_object_t replyMessage
= NULL
;
354 CFDataRef clientAuditToken
= NULL
;
355 CFArrayRef domains
= NULL
;
356 SecurityClient client
= {
358 .accessGroups
= NULL
,
360 .uid
= xpc_connection_get_euid(connection
),
361 .allowSystemKeychain
= false,
362 .allowSyncBubbleKeychain
= false,
363 .isNetworkExtension
= false,
364 .canAccessNetworkExtensionAccessGroups
= false,
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
);
372 uint64_t operation
= xpc_dictionary_get_uint64(event
, kSecXPCKeyOperation
);
374 audit_token_t auditToken
= {};
375 xpc_connection_get_audit_token(connection
, &auditToken
);
376 clientAuditToken
= CFDataCreate(kCFAllocatorDefault
, (const UInt8
*)&auditToken
, sizeof(auditToken
));
378 fill_security_client(&client
, xpc_connection_get_euid(connection
), auditToken
);
381 if (operation
== sec_add_shared_web_credential_id
|| operation
== sec_copy_shared_web_credential_id
) {
382 domains
= SecTaskCopySharedWebCredentialDomains(client
.task
);
385 secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64
")", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), operation
);
389 case sec_item_add_id
:
391 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
392 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
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
);
402 if (entitlementsCorrect
&& CFDictionaryGetValue(query
, kSecAttrSysBound
)) {
403 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_add_id
, client
.task
, kSecEntitlementPrivateSysBound
, &error
);
406 CFTypeRef result
= NULL
;
407 if(entitlementsCorrect
) {
408 if (_SecItemAdd(query
, &client
, &result
, &error
) && result
) {
409 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
410 CFReleaseNull(result
);
413 CFReleaseNull(query
);
418 case sec_item_copy_matching_id
:
420 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
421 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
423 CFTypeRef result
= NULL
;
424 if (_SecItemCopyMatching(query
, &client
, &result
, &error
) && result
) {
425 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
426 CFReleaseNull(result
);
428 CFReleaseNull(query
);
433 case sec_item_update_id
:
435 if (EntitlementAbsentOrFalse(sec_item_update_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
436 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
438 CFDictionaryRef attributesToUpdate
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyAttributesToUpdate
, &error
);
439 if (attributesToUpdate
) {
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
);
448 if (entitlementsCorrect
&& CFDictionaryGetValue(query
, kSecAttrSysBound
)) {
449 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_update_id
, client
.task
, kSecEntitlementPrivateSysBound
, &error
);
452 if(entitlementsCorrect
) {
453 bool result
= _SecItemUpdate(query
, attributesToUpdate
, &client
, &error
);
454 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
456 CFReleaseNull(attributesToUpdate
);
458 CFReleaseNull(query
);
463 case sec_item_delete_id
:
465 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
466 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
468 bool result
= _SecItemDelete(query
, &client
, &error
);
469 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
470 CFReleaseNull(query
);
475 case sec_item_update_token_items_id
:
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
);
481 bool result
= _SecItemUpdateTokenItems(tokenID
, attributes
, &client
, &error
);
482 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
484 CFReleaseNull(tokenID
);
485 CFReleaseNull(attributes
);
489 case sec_delete_all_id
:
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"));
498 if (isBuddy
|| EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateDeleteAll
, &error
))
500 retval
= _SecItemDeleteAll(&error
);
503 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
506 case sec_keychain_backup_id
:
508 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
509 CFDataRef keybag
= NULL
, passcode
= NULL
;
510 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybag
, &error
)) {
511 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
512 bool emcs
= SecXPCDictionaryGetBool(event
, kSecXPCKeyEMCSBackup
, NULL
);
513 CFDataRef backup
= _SecServerKeychainCreateBackup(&client
, keybag
, passcode
, emcs
, &error
);
515 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
517 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, backup
, &error
);
519 bool writeResult
= SecDataWriteFileDescriptor(fd
, backup
);
523 SecError(errSecIO
, &error
, CFSTR("Failed to write backup file: %d"), errno
);
524 SecXPCDictionarySetBool(replyMessage
, kSecXPCKeyResult
, writeResult
, NULL
);
528 CFReleaseSafe(passcode
);
530 CFReleaseSafe(keybag
);
535 case sec_keychain_restore_id
:
537 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
538 CFDataRef backup
= NULL
;
542 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
544 backup
= SecDataCopyMmapFileDescriptor(fd
, &mem
, &size
, &error
);
546 backup
= SecXPCDictionaryCopyData(event
, kSecXPCKeyBackup
, &error
);
549 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
551 CFDataRef passcode
= NULL
;
552 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
553 bool result
= _SecServerKeychainRestore(backup
, &client
, keybag
, passcode
, &error
);
554 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
555 CFReleaseSafe(passcode
);
558 CFReleaseNull(keybag
);
560 CFReleaseNull(backup
);
569 case sec_keychain_backup_keybag_uuid_id
:
571 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
572 CFDataRef backup
= NULL
;
573 CFStringRef uuid
= NULL
;
577 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
579 backup
= SecDataCopyMmapFileDescriptor(fd
, &mem
, &size
, &error
);
581 uuid
= _SecServerBackupCopyUUID(backup
, &error
);
584 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, uuid
, &error
);
586 CFReleaseNull(backup
);
596 case sec_keychain_sync_update_message_id
:
598 CFDictionaryRef updates
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
600 CFArrayRef result
= _SecServerKeychainSyncUpdateMessage(updates
, &error
);
601 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
602 CFReleaseNull(result
);
604 CFReleaseNull(updates
);
607 case sec_keychain_backup_syncable_id
:
609 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
610 CFDictionaryRef oldbackup
= NULL
;
611 if (SecXPCDictionaryCopyDictionaryOptional(event
, kSecXPCKeyBackup
, &oldbackup
, &error
)) {
612 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
614 CFDataRef passcode
= NULL
;
615 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
616 CFDictionaryRef newbackup
= _SecServerBackupSyncable(oldbackup
, keybag
, passcode
, &error
);
618 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, newbackup
, &error
);
619 CFRelease(newbackup
);
621 CFReleaseSafe(passcode
);
623 CFReleaseNull(keybag
);
625 CFReleaseSafe(oldbackup
);
630 case sec_keychain_restore_syncable_id
:
632 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
633 CFDictionaryRef backup
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyBackup
, &error
);
635 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
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
);
643 CFReleaseNull(keybag
);
645 CFReleaseNull(backup
);
650 case sec_item_backup_copy_names_id
:
652 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
653 CFArrayRef names
= SecServerItemBackupCopyNames(&error
);
654 SecXPCDictionarySetPListOptional(replyMessage
, kSecXPCKeyResult
, names
, &error
);
655 CFReleaseSafe(names
);
659 case sec_item_backup_handoff_fd_id
:
661 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
662 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
665 fd
= SecServerItemBackupHandoffFD(backupName
, &error
);
666 CFRelease(backupName
);
668 SecXPCDictionarySetFileDescriptor(replyMessage
, kSecXPCKeyResult
, fd
, &error
);
674 case sec_item_backup_set_confirmed_manifest_id
:
676 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
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
);
683 bool result
= SecServerItemBackupSetConfirmedManifest(backupName
, keybagDigest
, manifest
, &error
);
684 CFRelease(backupName
);
685 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
687 CFReleaseSafe(manifest
);
690 CFReleaseNull(keybagDigest
);
694 case sec_item_backup_restore_id
:
696 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
698 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
700 CFStringRef peerID
= NULL
;
701 if (SecXPCDictionaryCopyStringOptional(event
, kSecXPCKeyDigest
, &peerID
, &error
)) {
702 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
704 CFDataRef secret
= SecXPCDictionaryCopyData(event
, kSecXPCKeyUserPassword
, &error
);
706 CFDataRef backup
= SecXPCDictionaryCopyData(event
, kSecXPCData
, &error
);
708 result
= SecServerItemBackupRestore(backupName
, peerID
, keybag
, secret
, backup
, &error
);
715 CFReleaseSafe(peerID
);
717 CFRelease(backupName
);
719 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
723 case sec_add_shared_web_credential_id
:
725 #if TARGET_OS_IOS && !TARGET_OS_BRIDGE
726 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
728 CFTypeRef result
= NULL
;
730 CFStringRef appID
= (client
.task
) ? SecTaskCopyApplicationIdentifier(client
.task
) : NULL
;
731 if (_SecAddSharedWebCredential(query
, &client
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
732 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
733 CFReleaseNull(result
);
735 CFReleaseSafe(appID
);
736 CFReleaseNull(query
);
739 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, kCFBooleanFalse
, &error
);
743 case sec_copy_shared_web_credential_id
:
745 #if TARGET_OS_IOS && !TARGET_OS_BRIDGE
746 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
748 CFTypeRef result
= NULL
;
749 CFStringRef appID
= (client
.task
) ? SecTaskCopyApplicationIdentifier(client
.task
) : NULL
;
750 if (_SecCopySharedWebCredential(query
, &client
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
751 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
752 CFReleaseNull(result
);
754 CFReleaseSafe(appID
);
755 CFReleaseNull(query
);
758 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, kCFBooleanFalse
, &error
);
762 case sec_get_log_settings_id
:
764 CFPropertyListRef currentList
= SecCopyLogSettings_Server(&error
);
766 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, currentList
, &error
);
768 CFReleaseSafe(currentList
);
771 case sec_set_xpc_log_settings_id
:
773 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
775 SecSetXPCLogSettings_Server(newSettings
, &error
);
777 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
778 CFReleaseNull(newSettings
);
781 case sec_set_circle_log_settings_id
:
783 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
785 SecSetCircleLogSettings_Server(newSettings
, &error
);
787 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
788 CFReleaseNull(newSettings
);
791 case sec_otr_session_create_remote_id
:
793 CFDataRef publicPeerId
= NULL
;
794 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCPublicPeerId
, &publicPeerId
, &error
)) {
795 CFDataRef otrSession
= _SecOTRSessionCreateRemote(publicPeerId
, &error
);
797 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, otrSession
, &error
);
798 CFReleaseNull(otrSession
);
800 CFReleaseSafe(publicPeerId
);
804 case sec_otr_session_process_packet_remote_id
:
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
);
812 SecXPCDictionarySetData(replyMessage
, kSecXPCOTRSession
, outputSessionData
, &error
);
813 SecXPCDictionarySetData(replyMessage
, kSecXPCData
, outputPacket
, &error
);
814 xpc_dictionary_set_bool(replyMessage
, kSecXPCOTRReady
, readyForMessages
);
815 CFReleaseNull(outputSessionData
);
816 CFReleaseNull(outputPacket
);
818 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
820 CFReleaseSafe(inputPacket
);
822 CFReleaseSafe(sessionData
);
826 case kSecXPCOpTryUserCredentials
:
827 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
828 with_label_and_password_and_dsid(event
, ^(CFStringRef label
, CFDataRef password
, CFStringRef dsid
) {
829 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
830 SOSCCTryUserCredentials_Server(label
, password
, dsid
, &error
));
834 case kSecXPCOpSetUserCredentials
:
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
));
842 case kSecXPCOpSetUserCredentialsAndDSID
:
843 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
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
));
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
));
857 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCSetUserCredentialsAndDSID_Server(label
, password
, dsid
, &error
));
859 CFReleaseNull(parentEvent
);
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
));
871 case kSecXPCOpViewSet
:
872 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
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
);
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
));
888 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCViewSet_Server(enabledViews
, disabledViews
));
890 CFReleaseNull(enabledViews
);
891 CFReleaseNull(disabledViews
);
892 CFReleaseNull(parentEvent
);
895 case kSecXPCOpCanAuthenticate
:
896 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
897 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
898 SOSCCCanAuthenticate_Server(&error
));
901 case kSecXPCOpPurgeUserCredentials
:
902 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
903 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
904 SOSCCPurgeUserCredentials_Server(&error
));
907 case kSecXPCOpDeviceInCircle
:
908 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
909 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
910 SOSCCThisDeviceIsInCircle_Server(&error
));
913 case kSecXPCOpRequestToJoin
:
914 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
915 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
916 SOSCCRequestToJoinCircle_Server(&error
));
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
));
925 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRequestToJoinCircle_Server(&error
));
927 CFReleaseNull(parentEvent
);
930 case kSecXPCOpAccountHasPublicKey
:
931 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
932 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
933 SOSCCAccountHasPublicKey_Server(&error
));
936 case kSecXPCOpAccountIsNew
:
937 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
938 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
939 SOSCCAccountIsNew_Server(&error
));
942 case kSecXPCOpRequestToJoinAfterRestore
:
943 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
944 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
945 SOSCCRequestToJoinCircleAfterRestore_Server(&error
));
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
));
954 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRequestToJoinCircleAfterRestore_Server(&error
));
956 CFReleaseNull(parentEvent
);
959 case kSecXPCOpRequestEnsureFreshParameters
:
960 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
961 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
962 SOSCCRequestEnsureFreshParameters_Server(&error
));
965 case kSecXPCOpGetAllTheRings
:
966 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
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
);
973 case kSecXPCOpApplyToARing
:
974 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
975 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
976 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCApplyToARing_Server(ringName
, &error
));
977 CFReleaseNull(ringName
);
980 case kSecXPCOpWithdrawlFromARing
:
981 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
982 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
983 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCWithdrawlFromARing_Server(ringName
, &error
));
984 CFReleaseNull(ringName
);
987 case kSecXPCOpRingStatus
:
988 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
989 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
990 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRingStatus_Server(ringName
, &error
));
991 CFReleaseNull(ringName
);
994 case kSecXPCOpEnableRing
:
995 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
996 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
997 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCEnableRing_Server(ringName
, &error
));
998 CFReleaseNull(ringName
);
1001 case kSecXPCOpRequestDeviceID
:
1002 case kSecXPCOpSetDeviceID
:
1003 case kSecXPCOpHandleIDSMessage
:
1004 case kSecXPCOpSyncWithIDSPeer
:
1005 case kSecXPCOpSendIDSMessage
:
1006 case kSecXPCOpPingTest
:
1007 case kSecXPCOpIDSDeviceID
:
1008 case kSecXPCOpSyncWithKVSPeerIDOnly
:{
1009 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyError
, errSecUnimplemented
);
1012 case kSecXPCOpAccountSetToNew
:
1013 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1014 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCAccountSetToNew_Server(&error
));
1017 case kSecXPCOpResetToOffering
:
1018 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1019 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1020 SOSCCResetToOffering_Server(&error
));
1023 case kSecXPCOpResetToEmpty
:
1024 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1025 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1026 SOSCCResetToEmpty_Server(&error
));
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
));
1035 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCResetToEmpty_Server(&error
));
1039 case kSecXPCOpRemoveThisDeviceFromCircle
:
1040 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1041 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1042 SOSCCRemoveThisDeviceFromCircle_Server(&error
));
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
));
1051 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRemoveThisDeviceFromCircle_Server(&error
));
1053 CFReleaseNull(parentEvent
);
1056 case kSecXPCOpRemovePeersFromCircle
:
1057 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1058 CFArrayRef applicants
= SecXPCDictionaryCopyPeerInfoArray(event
, kSecXPCKeyPeerInfoArray
, &error
);
1059 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1060 SOSCCRemovePeersFromCircle_Server(applicants
, &error
));
1061 CFReleaseNull(applicants
);
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
));
1071 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRemovePeersFromCircle_Server(applicants
, &error
));
1073 CFReleaseNull(parentEvent
);
1074 CFReleaseNull(applicants
);
1077 case kSecXPCOpLoggedOutOfAccount
:
1078 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1079 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1080 SOSCCLoggedOutOfAccount_Server(&error
));
1083 case kSecXPCOpBailFromCircle
:
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
));
1090 case kSecXPCOpAcceptApplicants
:
1091 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1092 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfoArray
);
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
);
1099 case kSecXPCOpRejectApplicants
:
1100 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1101 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfoArray
);
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
);
1108 case kSecXPCOpSetNewPublicBackupKey
:
1110 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
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
);
1116 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1117 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1118 xpc_release(xpc_object
);
1120 CFReleaseNull(peerInfoData
);
1121 CFReleaseSafe(publicBackupKey
);
1126 case kSecXPCOpRegisterRecoveryPublicKey
:
1128 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1129 CFDataRef recovery_key
= SecXPCDictionaryCopyData(event
, kSecXPCKeyRecoveryPublicKey
, &error
);
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
);
1135 CFReleaseNull(nullData
);
1136 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRegisterRecoveryPublicKey_Server(recovery_key
, &error
));
1137 CFReleaseNull(recovery_key
);
1141 case kSecXPCOpGetRecoveryPublicKey
:
1143 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1144 xpc_object_t xpc_recovery_object
= NULL
;
1145 CFDataRef recovery
= SOSCCCopyRecoveryPublicKey(&error
);
1147 xpc_recovery_object
= _CFXPCCreateXPCObjectFromCFObject(recovery
);
1149 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_recovery_object
);
1150 CFReleaseNull(recovery
);
1154 case kSecXPCOpSetBagForAllSlices
:
1156 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
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
);
1164 case kSecXPCOpCopyApplicantPeerInfo
:
1165 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1166 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1167 SOSCCCopyApplicantPeerInfo_Server(&error
),
1171 case kSecXPCOpCopyValidPeerPeerInfo
:
1172 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1173 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1174 SOSCCCopyValidPeerPeerInfo_Server(&error
),
1178 case kSecXPCOpValidateUserPublic
:
1179 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1180 bool trusted
= SOSCCValidateUserPublic_Server(&error
);
1181 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, trusted
);
1184 case kSecXPCOpCopyNotValidPeerPeerInfo
:
1185 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1186 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1187 SOSCCCopyNotValidPeerPeerInfo_Server(&error
),
1191 case kSecXPCOpCopyGenerationPeerInfo
:
1192 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1193 xpc_dictionary_set_and_consume_CFArray(replyMessage
, kSecXPCKeyResult
,
1194 SOSCCCopyGenerationPeerInfo_Server(&error
));
1197 case kSecXPCOpCopyRetirementPeerInfo
:
1198 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1199 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1200 SOSCCCopyRetirementPeerInfo_Server(&error
),
1204 case kSecXPCOpCopyViewUnawarePeerInfo
:
1205 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1206 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1207 SOSCCCopyViewUnawarePeerInfo_Server(&error
),
1211 case kSecXPCOpCopyAccountData
:
1213 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1214 xpc_object_t xpc_account_object
= NULL
;
1215 CFDataRef accountData
= SOSCCCopyAccountState_Server(&error
);
1217 xpc_account_object
= _CFXPCCreateXPCObjectFromCFObject(accountData
);
1219 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_account_object
);
1220 CFReleaseNull(accountData
);
1224 case kSecXPCOpDeleteAccountData
:
1226 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1227 bool status
= SOSCCDeleteAccountState_Server(&error
);
1228 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, status
);
1232 case kSecXPCOpCopyEngineData
:
1234 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1236 xpc_object_t xpc_engine_object
= NULL
;
1237 CFDataRef engineData
= SOSCCCopyEngineData_Server(&error
);
1239 xpc_engine_object
= _CFXPCCreateXPCObjectFromCFObject(engineData
);
1241 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_engine_object
);
1242 CFReleaseNull(engineData
);
1247 case kSecXPCOpDeleteEngineData
:
1249 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1250 bool status
= SOSCCDeleteEngineState_Server(&error
);
1251 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, status
);
1255 case kSecXPCOpCopyEngineState
:
1257 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1258 CFArrayRef array
= SOSCCCopyEngineState_Server(&error
);
1259 CFDataRef derData
= NULL
;
1261 require_quiet(array
, done
);
1262 derData
= CFPropertyListCreateDERData(kCFAllocatorDefault
, array
, &error
);
1264 require_quiet(derData
, done
);
1265 xpc_dictionary_set_data(replyMessage
, kSecXPCKeyResult
, CFDataGetBytePtr(derData
), CFDataGetLength(derData
));
1267 CFReleaseNull(derData
);
1268 CFReleaseNull(array
);
1272 case kSecXPCOpCopyPeerPeerInfo
:
1273 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1274 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1275 SOSCCCopyPeerPeerInfo_Server(&error
),
1279 case kSecXPCOpCopyConcurringPeerPeerInfo
:
1280 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1281 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1282 SOSCCCopyConcurringPeerPeerInfo_Server(&error
),
1286 case kSecXPCOpCopyMyPeerInfo
:
1287 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1288 SOSPeerInfoRef peerInfo
= SOSCCCopyMyPeerInfo_Server(&error
);
1289 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1290 CFReleaseNull(peerInfo
);
1292 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1293 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1294 xpc_release(xpc_object
);
1296 CFReleaseNull(peerInfoData
);
1299 case kSecXPCOpGetLastDepartureReason
:
1300 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1301 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1302 SOSCCGetLastDepartureReason_Server(&error
));
1305 case kSecXPCOpSetLastDepartureReason
:
1306 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1307 int32_t reason
= (int32_t) xpc_dictionary_get_int64(event
, kSecXPCKeyReason
);
1308 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1309 SOSCCSetLastDepartureReason_Server(reason
, &error
));
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
);
1319 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
1321 CFReleaseNull(result
);
1323 CFReleaseNull(peers
);
1324 CFReleaseNull(backupPeers
);
1327 case kSecXPCOpProcessSyncWithAllPeers
:
1328 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1329 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1330 SOSCCProcessSyncWithAllPeers_Server(&error
));
1333 case soscc_EnsurePeerRegistration_id
:
1334 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1335 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1336 SOSCCProcessEnsurePeerRegistration_Server(&error
));
1339 case kSecXPCOpCopyIncompatibilityInfo
:
1340 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1341 CFStringRef iis
= SOSCCCopyIncompatibilityInfo_Server(&error
);
1342 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, iis
, &error
);
1346 case kSecXPCOpRollKeys
:
1348 bool force
= xpc_dictionary_get_bool(event
, "force");
1349 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1350 _SecServerRollKeys(force
, &client
, &error
));
1353 case kSecXPCOpWaitForInitialSync
:
1354 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1355 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1356 SOSCCWaitForInitialSync_Server(&error
));
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
));
1366 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCWaitForInitialSync_Server(&error
));
1368 CFReleaseNull(parentEvent
);
1371 case kSecXPCOpCopyYetToSyncViews
:
1372 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1373 CFArrayRef array
= SOSCCCopyYetToSyncViewsList_Server(&error
);
1375 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1376 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1377 xpc_release(xpc_array
);
1379 CFReleaseNull(array
);
1382 case kSecXPCOpSetEscrowRecord
:
1383 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1384 CFStringRef escrow_label
= SecXPCDictionaryCopyString(event
, kSecXPCKeyEscrowLabel
, &error
);
1385 uint64_t tries
= xpc_dictionary_get_int64(event
, kSecXPCKeyTriesLabel
);
1387 bool result
= SOSCCSetEscrowRecord_Server(escrow_label
, tries
, &error
);
1389 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1391 CFReleaseNull(escrow_label
);
1394 case kSecXPCOpGetEscrowRecord
:
1395 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1396 CFDictionaryRef record
= SOSCCCopyEscrowRecord_Server(&error
);
1398 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(record
);
1399 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1400 xpc_release(xpc_dictionary
);
1402 CFReleaseNull(record
);
1405 case kSecXPCOpCopyBackupInformation
:
1406 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1407 CFDictionaryRef record
= SOSCCCopyBackupInformation_Server(&error
);
1409 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(record
);
1410 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1411 xpc_release(xpc_dictionary
);
1413 CFReleaseNull(record
);
1417 case kSecXPCOpIsThisDeviceLastBackup
:
1418 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1419 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCkSecXPCOpIsThisDeviceLastBackup_Server(&error
));
1422 case kSecXPCOpPeersHaveViewsEnabled
:
1424 CFArrayRef viewSet
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyArray
, &error
);
1426 CFBooleanRef result
= SOSCCPeersHaveViewsEnabled_Server(viewSet
, &error
);
1427 if (result
!= NULL
) {
1428 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
!= kCFBooleanFalse
);
1431 CFReleaseNull(viewSet
);
1435 case kSecXPCOpWhoAmI
:
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);
1445 case kSecXPCOpTransmogrifyToSyncBubble
:
1447 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainSyncBubble
, &error
)) {
1449 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1450 CFArrayRef services
= SecXPCDictionaryCopyArray(event
, "services", &error
);
1452 if (uid
&& services
) {
1453 res
= _SecServerTransmogrifyToSyncBubble(services
, uid
, &client
, &error
);
1455 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1456 CFReleaseNull(services
);
1458 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1463 case kSecXPCOpTransmogrifyToSystemKeychain
:
1465 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
)) {
1467 bool res
= _SecServerTransmogrifyToSystemKeychain(&client
, &error
);
1468 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1470 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1476 case kSecXPCOpDeleteUserView
:
1478 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
)) {
1481 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1483 res
= _SecServerDeleteMUSERViews(&client
, uid
, &error
);
1486 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1491 case kSecXPCOpWrapToBackupSliceKeyBagForView
:
1493 CFStringRef viewname
= SecXPCDictionaryCopyString(event
, kSecXPCKeyViewName
, &error
);
1495 CFDataRef plaintext
= SecXPCDictionaryCopyData(event
, kSecXPCData
, &error
);
1497 CFDataRef ciphertext
= NULL
;
1498 CFDataRef bskbEncoded
= NULL
;
1500 bool result
= SOSWrapToBackupSliceKeyBagForView_Server(viewname
, plaintext
, &ciphertext
, &bskbEncoded
, &error
);
1501 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1503 if(!error
&& result
) {
1505 xpc_dictionary_set_data(replyMessage
, kSecXPCData
, CFDataGetBytePtr(ciphertext
), CFDataGetLength(ciphertext
));
1508 xpc_dictionary_set_data(replyMessage
, kSecXPCKeyKeybag
, CFDataGetBytePtr(bskbEncoded
), CFDataGetLength(bskbEncoded
));
1511 CFReleaseSafe(ciphertext
);
1512 CFReleaseSafe(bskbEncoded
);
1514 CFReleaseSafe(plaintext
);
1516 CFReleaseNull(viewname
);
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
);
1525 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1526 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1527 xpc_release(xpc_object
);
1529 CFReleaseNull(peerInfoData
);
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
);
1538 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(pbblob
);
1539 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1540 xpc_release(xpc_object
);
1542 CFReleaseNull(pbblob
);
1543 CFReleaseNull(applicant
);
1544 CFReleaseNull(appBlob
);
1547 case kSecXPCOpCopyInitialSyncBlob
:
1548 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1549 CFDataRef initialblob
= SOSCCCopyInitialSyncData_Server(&error
);
1551 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(initialblob
);
1552 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1553 xpc_release(xpc_object
);
1555 CFReleaseNull(initialblob
);
1558 case kSecXPCOpJoinWithCircleJoiningBlob
:
1559 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1560 CFDataRef joiningBlob
= SecXPCDictionaryCopyCFDataRef(event
, kSecXPCData
, &error
);
1561 uint64_t version
= xpc_dictionary_get_uint64(event
, kSecXPCVersion
);
1562 bool retval
= SOSCCJoinWithCircleJoiningBlob_Server(joiningBlob
, (PiggyBackProtocolVersion
) version
, &error
);
1563 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1564 CFReleaseNull(joiningBlob
);
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
);
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
);
1580 case kSecXPCOpMessageFromPeerIsPending
:
1582 SOSPeerInfoRef peer
= SecXPCDictionaryCopyPeerInfo(event
, kSecXPCKeyPeerInfo
, &error
);
1584 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1585 SOSCCMessageFromPeerIsPending_Server(peer
, &error
));
1587 CFReleaseNull(peer
);
1590 case kSecXPCOpSendToPeerIsPending
:
1592 SOSPeerInfoRef peer
= SecXPCDictionaryCopyPeerInfo(event
, kSecXPCKeyPeerInfo
, &error
);
1594 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1595 SOSCCSendToPeerIsPending(peer
, &error
));
1597 CFReleaseNull(peer
);
1600 case sec_delete_items_with_access_groups_id
:
1602 bool retval
= false;
1603 #if TARGET_OS_IPHONE
1604 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateUninstallDeletion
, &error
)) {
1605 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyAccessGroups
, &error
);
1608 retval
= _SecItemServerDeleteAllWithAccessGroups(accessGroups
, &client
, &error
);
1610 CFReleaseNull(accessGroups
);
1613 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1616 case sec_item_copy_parent_certificates_id
:
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
);
1625 CFReleaseNull(issuer
);
1626 CFReleaseNull(accessGroups
);
1628 SecXPCDictionarySetPListOptional(replyMessage
, kSecXPCKeyResult
, results
, &error
);
1629 CFReleaseNull(results
);
1632 case sec_item_certificate_exists_id
:
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
);
1642 CFReleaseNull(issuer
);
1643 CFReleaseNull(serialNum
);
1644 CFReleaseNull(accessGroups
);
1646 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
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
);
1657 added
&= SecXPCDictionarySetDataOptional(replyMessage
, kSecXPCKeyBackupKeybagIdentifier
, identifier
, &error
);
1658 added
&= SecXPCDictionarySetDataOptional(replyMessage
, kSecXPCKeyBackupKeybagPath
, pathinfo
, &error
);
1659 SecXPCDictionarySetBool(replyMessage
, kSecXPCKeyResult
, added
, NULL
);
1661 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1664 CFReleaseSafe(passcode
);
1665 CFReleaseSafe(keybag
);
1669 case kSecXPCOpBackupKeybagDelete
: {
1671 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementBackupTableOperations
, &error
)) {
1672 bool deleted
= false;
1673 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
1675 CFTypeRef matchLimit
= CFDictionaryGetValue(query
, kSecMatchLimit
);
1676 bool deleteAll
= matchLimit
&& CFEqualSafe(matchLimit
, kSecMatchLimitAll
);
1678 if (deleteAll
&& !EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementBackupTableOperationsDeleteAll
, &error
)) {
1679 // require special entitlement to delete all backup keybags
1681 CFMutableDictionaryRef attributes
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, query
);
1682 CFStringRef requestedAgrp
= CFDictionaryGetValue(attributes
, kSecAttrAccessGroup
);
1683 CFStringRef resolvedAgrp
= NULL
;
1685 CFDictionarySetValue(attributes
, kSecAttrMultiUser
, client
.musr
);
1687 if (extractAccessGroup(&client
, requestedAgrp
, &resolvedAgrp
, &error
)) {
1689 CFDictionarySetValue(attributes
, kSecAttrAccessGroup
, resolvedAgrp
);
1691 deleted
= _SecServerBackupKeybagDelete(attributes
, deleteAll
, &error
);
1693 CFReleaseNull(attributes
);
1696 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, deleted
);
1697 CFReleaseNull(query
);
1701 case kSecXPCOpKeychainControlEndpoint
: {
1702 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainControl
, &error
)) {
1703 xpc_endpoint_t endpoint
= SecServerCreateKeychainControlEndpoint();
1705 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyEndpoint
, endpoint
);
1706 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1707 xpc_release(endpoint
);
1709 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1720 if(SecErrorGetOSStatus(error
) == errSecItemNotFound
|| isSOSErrorCoded(error
, kSOSErrorPublicKeyAbsent
))
1721 secdebug("ipc", "%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1722 else if (SecErrorGetOSStatus(error
) == errSecAuthNeeded
)
1723 secwarning("Authentication is needed %@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1725 secerror("%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1727 xpcError
= SecCreateXPCObjectWithCFError(error
);
1729 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyError
, xpcError
);
1731 } else if (replyMessage
) {
1732 secdebug("ipc", "%@ %@ responding %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyMessage
);
1735 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, &error
, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event
);
1736 secerror("%@: returning error: %@", client
.task
, error
);
1737 xpcError
= SecCreateXPCObjectWithCFError(error
);
1738 replyMessage
= xpc_create_reply_with_format(event
, "{%string: %value}", kSecXPCKeyError
, xpcError
);
1742 xpc_connection_send_message(connection
, replyMessage
);
1743 xpc_release(replyMessage
);
1746 xpc_release(xpcError
);
1747 CFReleaseSafe(error
);
1748 CFReleaseSafe(client
.accessGroups
);
1749 CFReleaseSafe(client
.musr
);
1750 CFReleaseSafe(client
.task
);
1751 CFReleaseSafe(domains
);
1752 CFReleaseSafe(clientAuditToken
);
1755 static void securityd_xpc_init(const char *service_name
)
1757 secdebug("serverxpc", "start");
1758 xpc_connection_t listener
= xpc_connection_create_mach_service(service_name
, NULL
, XPC_CONNECTION_MACH_SERVICE_LISTENER
);
1760 seccritical("security failed to register xpc listener for %s, exiting", service_name
);
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
) {
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.
1774 uint64_t operation
= xpc_dictionary_get_uint64(event
, kSecXPCKeyOperation
);
1775 if (operation
== sec_item_copy_matching_id
) {
1776 securityd_xpc_dictionary_handler(connection
, event
);
1778 xpc_retain(connection
);
1780 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
1781 securityd_xpc_dictionary_handler(connection
, event
);
1783 xpc_release(connection
);
1788 xpc_connection_resume(connection
);
1791 xpc_connection_resume(listener
);
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();
1804 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1806 #if TARGET_OS_EMBEDDED
1807 static void securityd_soscc_lock_hack() {
1808 dispatch_queue_t soscc_lock_queue
= dispatch_queue_create("soscc_lock_queue", DISPATCH_QUEUE_PRIORITY_DEFAULT
);
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
);
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");
1823 CFErrorRef error
= NULL
;
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
1828 xpc_transaction_begin();
1830 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, one_minute
*NSEC_PER_SEC
), soscc_lock_queue
, ^{
1831 CFErrorRef localError
= NULL
;
1832 if(!SecAKSUnLockUserKeybag(&localError
))
1833 secerror("failed to unlock: %@", localError
);
1834 CFReleaseNull(localError
);
1835 xpc_transaction_end();
1838 secerror("Failed to take device lock assertion: %@", error
);
1840 CFReleaseNull(error
);
1841 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync => done");
1851 static char homeDir
[PATH_MAX
] = {};
1853 if (homeDir
[0] == '\0') {
1854 struct passwd
* pwd
= getpwuid(getuid());
1858 if (realpath(pwd
->pw_dir
, homeDir
) == NULL
) {
1859 strlcpy(homeDir
, pwd
->pw_dir
, sizeof(homeDir
));
1867 int main(int argc
, char *argv
[])
1869 char *wait4debugger
= getenv("WAIT4DEBUGGER");
1870 if (wait4debugger
&& !strcasecmp("YES", wait4debugger
)) {
1871 seccritical("SIGSTOPing self, awaiting debugger");
1872 kill(getpid(), SIGSTOP
);
1873 seccritical("Again, for good luck (or bad debuggers)");
1874 kill(getpid(), SIGSTOP
);
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.
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();
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");
1900 char *errorbuf
= NULL
;
1901 const char *sandbox_params
[] = {
1907 rc
= sandbox_init_with_parameters(SECD_PROFILE_NAME
, SANDBOX_NAMED
, sandbox_params
, &errorbuf
);
1909 err(1, "Failed to process in a sandbox: %d %s", rc
, errorbuf
);
1910 #endif /* TARGET_OS_OSX */
1912 const char *serviceName
= kSecuritydXPCServiceName
;
1913 /* setup SQDLite before some other component have a chance to create a database connection */
1914 _SecDbServerSetup();
1916 securityd_init_server();
1917 securityd_xpc_init(serviceName
);
1919 SecCreateSecuritydXPCServer();
1920 CKKSControlServerInitialize();
1921 SOSControlServerInitialize();
1922 OctagonControlServerInitialize();
1923 SFKeychainServerInitialize();
1925 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1926 #if TARGET_OS_EMBEDDED
1927 securityd_soscc_lock_hack();
1933 /* vi:set ts=4 sw=4 et: */