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 <AssertMacros.h>
70 #include <CoreFoundation/CFXPCBridge.h>
71 #include <CoreFoundation/CoreFoundation.h>
72 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
75 #include <Security/SecTaskPriv.h>
76 #include <login/SessionAgentStatusCom.h>
79 #include <bsm/libbsm.h>
80 #include <ipc/securityd_client.h>
81 #include <libkern/OSAtomic.h>
82 #include <mach/mach.h>
83 #include <mach/message.h>
86 #include <sys/queue.h>
87 #include <sys/sysctl.h>
89 #include <xpc/private.h>
92 #include <ipc/server_security_helpers.h>
93 #include <ipc/server_entitlement_helpers.h>
101 static bool accessGroupPermitted(SecurityClient
* client
, CFArrayRef accessGroups
, CFStringRef accessGroup
) {
102 /* NULL accessGroups is wildcard. */
105 /* Make sure we have a string. */
106 if (!isString(accessGroup
))
109 /* Having the special accessGroup "*" allows access to all accessGroups. */
110 CFRange range
= { 0, CFArrayGetCount(accessGroups
) };
112 (CFArrayContainsValue(accessGroups
, range
, accessGroup
) ||
113 CFArrayContainsValue(accessGroups
, range
, CFSTR("*"))))
119 static bool extractAccessGroup(SecurityClient
*client
, CFStringRef requestedAgrp
, CFStringRef
*resolvedAgrp
, CFErrorRef
*error
) {
122 /* Access group sanity checking.
123 Similar to accessGroupsAllows, but ignores accessGroupIsNetworkExtensionAndClientIsEntitled */
124 CFArrayRef accessGroups
= client
->accessGroups
;
125 CFStringRef agrp
= requestedAgrp
;
126 /* Having the special accessGroup "*" allows access to all accessGroups. */
127 if (CFArrayContainsValue(accessGroups
, CFRangeMake(0,CFArrayGetCount(accessGroups
)), CFSTR("*")))
131 /* The user specified an explicit access group, validate it. */
132 if (!accessGroupPermitted(client
, accessGroups
, requestedAgrp
))
133 ok
= SecError(errSecMissingEntitlement
, error
, CFSTR("explicit accessGroup %@ not in client access %@"), requestedAgrp
, accessGroups
);
135 // We are using an implicit access group
136 // Add it as if the user specified it as an attribute.
137 agrp
= (CFStringRef
)CFArrayGetValueAtIndex(client
->accessGroups
, 0);
140 if (agrp
&& resolvedAgrp
)
141 *resolvedAgrp
= agrp
;
145 static void with_label_and_password(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
)) {
146 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyUserLabel
);
148 if (label_utf8
) { // Anything we would do here requires a user label
149 size_t password_length
= 0;
150 const void *password_data
= xpc_dictionary_get_data(message
, kSecXPCKeyUserPassword
, &password_length
);
152 CFDataRef user_password
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
);
153 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
155 action(user_label
, user_password
);
157 CFReleaseNull(user_password
);
158 CFReleaseNull(user_label
);
162 static void with_label_and_password_and_dsid(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
, CFStringRef dsid
)) {
163 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyUserLabel
);
165 if (label_utf8
) { // Anything we would do here requires a user label
166 size_t password_length
= 0;
167 const void *password_data
= xpc_dictionary_get_data(message
, kSecXPCKeyUserPassword
, &password_length
);
168 const char *xdsid
= xpc_dictionary_get_string(message
, kSecXPCKeyDSID
);
170 CFDataRef user_password
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
);
171 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
172 CFStringRef dsid
= CFStringCreateWithCString(kCFAllocatorDefault
, xdsid
, kCFStringEncodingUTF8
);
174 action(user_label
, user_password
, dsid
);
177 CFReleaseNull(user_password
);
178 CFReleaseNull(user_label
);
182 static void with_label_and_number(xpc_object_t message
, void (^action
)(CFStringRef label
, uint64_t number
)) {
183 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyViewName
);
185 if (label_utf8
) { // Anything we would do here requires a user label
186 const int64_t number
= xpc_dictionary_get_int64(message
, kSecXPCKeyViewActionCode
);
187 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
189 action(user_label
, number
);
190 CFReleaseNull(user_label
);
194 static CFArrayRef
SecXPCDictionaryCopyPeerInfoArray(xpc_object_t dictionary
, const char *key
, CFErrorRef
*error
) {
195 return CreateArrayOfPeerInfoWithXPCObject(xpc_dictionary_get_value(dictionary
, key
), error
);
198 static CFDataRef
SecXPCDictionaryCopyCFDataRef(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
199 CFDataRef retval
= NULL
;
200 const uint8_t *bytes
= NULL
;
203 bytes
= xpc_dictionary_get_data(message
, key
, &len
);
204 require_action_quiet(bytes
, errOut
, SOSCreateError(kSOSErrorBadKey
, CFSTR("missing CFDataRef info"), NULL
, error
));
205 retval
= CFDataCreate(NULL
, bytes
, len
);
206 require_action_quiet(retval
, errOut
, SOSCreateError(kSOSErrorBadKey
, CFSTR("could not allocate CFDataRef info"), NULL
, error
));
211 static CFSetRef
CreateCFSetRefFromXPCObject(xpc_object_t xpcSetDER
, CFErrorRef
* error
) {
212 CFSetRef retval
= NULL
;
213 require_action_quiet(xpcSetDER
, errOut
, SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedNull
, sSecXPCErrorDomain
, NULL
, error
, NULL
, CFSTR("Unexpected Null Set to decode")));
215 require_action_quiet(xpc_get_type(xpcSetDER
) == XPC_TYPE_DATA
, errOut
, SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, error
, NULL
, CFSTR("xpcSetDER not data, got %@"), xpcSetDER
));
217 const uint8_t* der
= xpc_data_get_bytes_ptr(xpcSetDER
);
218 const uint8_t* der_end
= der
+ xpc_data_get_length(xpcSetDER
);
219 der
= der_decode_set(kCFAllocatorDefault
, kCFPropertyListMutableContainersAndLeaves
, &retval
, error
, der
, der_end
);
220 if (der
!= der_end
) {
221 SecError(errSecDecode
, error
, CFSTR("trailing garbage at end of SecAccessControl data"));
226 CFReleaseNull(retval
);
230 static SOSPeerInfoRef
SecXPCDictionaryCopyPeerInfo(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
232 const uint8_t *der
= xpc_dictionary_get_data(message
, key
, &length
);
234 return SecRequirementError(der
!= NULL
, error
, CFSTR("No data for key %s"), key
) ? SOSPeerInfoCreateFromDER(kCFAllocatorDefault
, error
, &der
, der
+ length
) : NULL
;
237 static CFSetRef
SecXPCSetCreateFromXPCDictionaryElement(xpc_object_t event
, const char *key
) {
238 CFErrorRef error
= NULL
;
239 xpc_object_t object
= xpc_dictionary_get_value(event
, key
);
240 CFSetRef retval
= NULL
;
241 if(object
) retval
= CreateCFSetRefFromXPCObject(object
, &error
);
242 CFReleaseNull(error
);
247 void xpc_dictionary_set_and_consume_CFArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
) {
249 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(cf_array
);
250 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
251 xpc_release(xpc_array
);
253 CFReleaseNull(cf_array
);
257 bool xpc_dictionary_set_and_consume_PeerInfoArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
, CFErrorRef
*error
) {
260 xpc_object_t xpc_array
= CreateXPCObjectWithArrayOfPeerInfo(cf_array
, error
);
262 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
263 xpc_release(xpc_array
);
268 CFReleaseNull(cf_array
);
273 SecDataCopyMmapFileDescriptor(int fd
, void **mem
, size_t *size
, CFErrorRef
*error
)
276 if (fstat(fd
, &sb
) < 0) {
280 *size
= (size_t)sb
.st_size
;
281 if ((off_t
)*size
!= sb
.st_size
) {
285 *mem
= mmap(NULL
, *size
, PROT_READ
, MAP_SHARED
, fd
, 0);
286 if (*mem
== MAP_FAILED
) {
290 return CFDataCreateWithBytesNoCopy(NULL
, *mem
, *size
, kCFAllocatorNull
);
294 SecDataWriteFileDescriptor(int fd
, CFDataRef data
)
296 CFIndex count
= CFDataGetLength(data
);
297 const uint8_t *ptr
= CFDataGetBytePtr(data
);
298 bool writeResult
= false;
301 ssize_t ret
= write(fd
, ptr
, count
);
314 // Returns error if entitlement isn't present.
316 EntitlementPresentAndTrue(uint64_t op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
318 if (!SecTaskGetBooleanValueForEntitlement(clientTask
, entitlement
)) {
319 SecError(errSecMissingEntitlement
, error
, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
)op
), clientTask
, entitlement
);
325 // Per <rdar://problem/13315020> Disable the entitlement check for "keychain-cloud-circle"
326 // we disable entitlement enforcement. However, we still log so we know who needs the entitlement
328 EntitlementPresentOrWhine(uint64_t op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
330 if (!SecTaskGetBooleanValueForEntitlement(clientTask
, entitlement
))
331 secnotice("serverxpc", "%@: %@ lacks entitlement %@", SOSCCGetOperationDescription((enum SecXPCOperation
)op
), clientTask
, entitlement
);
338 EntitlementAbsentOrFalse(uint64_t op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
340 if (SecTaskGetBooleanValueForEntitlement(clientTask
, entitlement
)) {
341 SecError(errSecNotAvailable
, error
, CFSTR("%@: %@ has entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
) op
), clientTask
, entitlement
);
347 static void securityd_xpc_dictionary_handler(const xpc_connection_t connection
, xpc_object_t event
) {
348 xpc_type_t type
= xpc_get_type(event
);
349 __block CFErrorRef error
= NULL
;
350 xpc_object_t xpcError
= NULL
;
351 xpc_object_t replyMessage
= NULL
;
352 CFDataRef clientAuditToken
= NULL
;
353 CFArrayRef domains
= NULL
;
354 SecurityClient client
= {
356 .accessGroups
= NULL
,
358 .uid
= xpc_connection_get_euid(connection
),
359 .allowSystemKeychain
= false,
360 .allowSyncBubbleKeychain
= false,
361 .isNetworkExtension
= false,
362 .canAccessNetworkExtensionAccessGroups
= false,
365 secdebug("serverxpc", "entering");
366 if (type
== XPC_TYPE_DICTIONARY
) {
367 // TODO: Find out what we're dispatching.
368 replyMessage
= xpc_dictionary_create_reply(event
);
370 uint64_t operation
= xpc_dictionary_get_uint64(event
, kSecXPCKeyOperation
);
372 audit_token_t auditToken
= {};
373 xpc_connection_get_audit_token(connection
, &auditToken
);
374 clientAuditToken
= CFDataCreate(kCFAllocatorDefault
, (const UInt8
*)&auditToken
, sizeof(auditToken
));
376 fill_security_client(&client
, xpc_connection_get_euid(connection
), auditToken
);
379 if (operation
== sec_add_shared_web_credential_id
|| operation
== sec_copy_shared_web_credential_id
) {
380 domains
= SecTaskCopySharedWebCredentialDomains(client
.task
);
383 secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64
")", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), operation
);
387 case sec_item_add_id
:
389 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
390 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
392 // Check for any entitlement-required attributes
393 bool entitlementsCorrect
= true;
394 if(CFDictionaryGetValue(query
, kSecAttrDeriveSyncIDFromItemAttributes
) ||
395 CFDictionaryGetValue(query
, kSecAttrPCSPlaintextServiceIdentifier
) ||
396 CFDictionaryGetValue(query
, kSecAttrPCSPlaintextPublicKey
) ||
397 CFDictionaryGetValue(query
, kSecAttrPCSPlaintextPublicIdentity
)) {
398 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_add_id
, client
.task
, kSecEntitlementPrivateCKKSPlaintextFields
, &error
);
400 if (entitlementsCorrect
&& CFDictionaryGetValue(query
, kSecAttrSysBound
)) {
401 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_add_id
, client
.task
, kSecEntitlementPrivateSysBound
, &error
);
404 CFTypeRef result
= NULL
;
405 if(entitlementsCorrect
) {
406 if (_SecItemAdd(query
, &client
, &result
, &error
) && result
) {
407 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
408 CFReleaseNull(result
);
411 CFReleaseNull(query
);
416 case sec_item_copy_matching_id
:
418 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
419 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
421 CFTypeRef result
= NULL
;
422 if (_SecItemCopyMatching(query
, &client
, &result
, &error
) && result
) {
423 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
424 CFReleaseNull(result
);
426 CFReleaseNull(query
);
431 case sec_item_update_id
:
433 if (EntitlementAbsentOrFalse(sec_item_update_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
434 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
436 CFDictionaryRef attributesToUpdate
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyAttributesToUpdate
, &error
);
437 if (attributesToUpdate
) {
438 // Check for any entitlement-required attributes
439 bool entitlementsCorrect
= true;
440 if(CFDictionaryGetValue(query
, kSecAttrDeriveSyncIDFromItemAttributes
) ||
441 CFDictionaryGetValue(attributesToUpdate
, kSecAttrPCSPlaintextServiceIdentifier
) ||
442 CFDictionaryGetValue(attributesToUpdate
, kSecAttrPCSPlaintextPublicKey
) ||
443 CFDictionaryGetValue(attributesToUpdate
, kSecAttrPCSPlaintextPublicIdentity
)) {
444 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_update_id
, client
.task
, kSecEntitlementPrivateCKKSPlaintextFields
, &error
);
446 if (entitlementsCorrect
&& CFDictionaryGetValue(query
, kSecAttrSysBound
)) {
447 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_update_id
, client
.task
, kSecEntitlementPrivateSysBound
, &error
);
450 if(entitlementsCorrect
) {
451 bool result
= _SecItemUpdate(query
, attributesToUpdate
, &client
, &error
);
452 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
454 CFReleaseNull(attributesToUpdate
);
456 CFReleaseNull(query
);
461 case sec_item_delete_id
:
463 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
464 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
466 bool result
= _SecItemDelete(query
, &client
, &error
);
467 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
468 CFReleaseNull(query
);
473 case sec_item_update_token_items_id
:
475 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
476 CFStringRef tokenID
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
477 CFArrayRef attributes
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyQuery
, &error
);
479 bool result
= _SecItemUpdateTokenItems(tokenID
, attributes
, &client
, &error
);
480 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
482 CFReleaseNull(tokenID
);
483 CFReleaseNull(attributes
);
487 case sec_delete_all_id
:
491 /* buddy is temporary allowed to do this */
492 CFStringRef applicationIdentifier
= SecTaskCopyApplicationIdentifier(client
.task
);
493 bool isBuddy
= applicationIdentifier
&&
494 CFEqual(applicationIdentifier
, CFSTR("com.apple.purplebuddy"));
496 if (isBuddy
|| EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateDeleteAll
, &error
))
498 retval
= _SecItemDeleteAll(&error
);
501 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
504 case sec_keychain_backup_id
:
506 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
507 CFDataRef keybag
= NULL
, passcode
= NULL
;
508 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybag
, &error
)) {
509 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
510 bool emcs
= SecXPCDictionaryGetBool(event
, kSecXPCKeyEMCSBackup
, NULL
);
511 CFDataRef backup
= _SecServerKeychainCreateBackup(&client
, keybag
, passcode
, emcs
, &error
);
513 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
515 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, backup
, &error
);
517 bool writeResult
= SecDataWriteFileDescriptor(fd
, backup
);
521 SecError(errSecIO
, &error
, CFSTR("Failed to write backup file: %d"), errno
);
522 SecXPCDictionarySetBool(replyMessage
, kSecXPCKeyResult
, writeResult
, NULL
);
526 CFReleaseSafe(passcode
);
528 CFReleaseSafe(keybag
);
533 case sec_keychain_restore_id
:
535 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
536 CFDataRef backup
= NULL
;
540 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
542 backup
= SecDataCopyMmapFileDescriptor(fd
, &mem
, &size
, &error
);
544 backup
= SecXPCDictionaryCopyData(event
, kSecXPCKeyBackup
, &error
);
547 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
549 CFDataRef passcode
= NULL
;
550 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
551 bool result
= _SecServerKeychainRestore(backup
, &client
, keybag
, passcode
, &error
);
552 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
553 CFReleaseSafe(passcode
);
556 CFReleaseNull(keybag
);
558 CFReleaseNull(backup
);
567 case sec_keychain_backup_keybag_uuid_id
:
569 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
570 CFDataRef backup
= NULL
;
571 CFStringRef uuid
= NULL
;
575 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
577 backup
= SecDataCopyMmapFileDescriptor(fd
, &mem
, &size
, &error
);
579 uuid
= _SecServerBackupCopyUUID(backup
, &error
);
582 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, uuid
, &error
);
584 CFReleaseNull(backup
);
594 case sec_keychain_sync_update_message_id
:
596 CFDictionaryRef updates
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
598 CFArrayRef result
= _SecServerKeychainSyncUpdateMessage(updates
, &error
);
599 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
600 CFReleaseNull(result
);
602 CFReleaseNull(updates
);
605 case sec_keychain_backup_syncable_id
:
607 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
608 CFDictionaryRef oldbackup
= NULL
;
609 if (SecXPCDictionaryCopyDictionaryOptional(event
, kSecXPCKeyBackup
, &oldbackup
, &error
)) {
610 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
612 CFDataRef passcode
= NULL
;
613 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
614 CFDictionaryRef newbackup
= _SecServerBackupSyncable(oldbackup
, keybag
, passcode
, &error
);
616 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, newbackup
, &error
);
617 CFRelease(newbackup
);
619 CFReleaseSafe(passcode
);
621 CFReleaseNull(keybag
);
623 CFReleaseSafe(oldbackup
);
628 case sec_keychain_restore_syncable_id
:
630 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
631 CFDictionaryRef backup
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyBackup
, &error
);
633 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
635 CFDataRef passcode
= NULL
;
636 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
637 bool result
= _SecServerRestoreSyncable(backup
, keybag
, passcode
, &error
);
638 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
639 CFReleaseSafe(passcode
);
641 CFReleaseNull(keybag
);
643 CFReleaseNull(backup
);
648 case sec_item_backup_copy_names_id
:
650 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
651 CFArrayRef names
= SecServerItemBackupCopyNames(&error
);
652 SecXPCDictionarySetPListOptional(replyMessage
, kSecXPCKeyResult
, names
, &error
);
653 CFReleaseSafe(names
);
657 case sec_item_backup_handoff_fd_id
:
659 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
660 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
663 fd
= SecServerItemBackupHandoffFD(backupName
, &error
);
664 CFRelease(backupName
);
666 SecXPCDictionarySetFileDescriptor(replyMessage
, kSecXPCKeyResult
, fd
, &error
);
672 case sec_item_backup_set_confirmed_manifest_id
:
674 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
675 CFDataRef keybagDigest
= NULL
;
676 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybagDigest
, &error
)) {
677 CFDataRef manifest
= NULL
;
678 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &manifest
, &error
)) {
679 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
681 bool result
= SecServerItemBackupSetConfirmedManifest(backupName
, keybagDigest
, manifest
, &error
);
682 CFRelease(backupName
);
683 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
685 CFReleaseSafe(manifest
);
688 CFReleaseNull(keybagDigest
);
692 case sec_item_backup_restore_id
:
694 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
696 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
698 CFStringRef peerID
= NULL
;
699 if (SecXPCDictionaryCopyStringOptional(event
, kSecXPCKeyDigest
, &peerID
, &error
)) {
700 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
702 CFDataRef secret
= SecXPCDictionaryCopyData(event
, kSecXPCKeyUserPassword
, &error
);
704 CFDataRef backup
= SecXPCDictionaryCopyData(event
, kSecXPCData
, &error
);
706 result
= SecServerItemBackupRestore(backupName
, peerID
, keybag
, secret
, backup
, &error
);
713 CFReleaseSafe(peerID
);
715 CFRelease(backupName
);
717 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
721 case sec_add_shared_web_credential_id
:
723 #if TARGET_OS_IOS && !TARGET_OS_BRIDGE
724 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
726 CFTypeRef result
= NULL
;
728 CFStringRef appID
= (client
.task
) ? SecTaskCopyApplicationIdentifier(client
.task
) : NULL
;
729 if (_SecAddSharedWebCredential(query
, &client
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
730 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
731 CFReleaseNull(result
);
733 CFReleaseSafe(appID
);
734 CFReleaseNull(query
);
737 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, kCFBooleanFalse
, &error
);
741 case sec_copy_shared_web_credential_id
:
743 #if TARGET_OS_IOS && !TARGET_OS_BRIDGE
744 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
746 CFTypeRef result
= NULL
;
747 CFStringRef appID
= (client
.task
) ? SecTaskCopyApplicationIdentifier(client
.task
) : NULL
;
748 if (_SecCopySharedWebCredential(query
, &client
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
749 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
750 CFReleaseNull(result
);
752 CFReleaseSafe(appID
);
753 CFReleaseNull(query
);
756 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, kCFBooleanFalse
, &error
);
760 case sec_get_log_settings_id
:
762 CFPropertyListRef currentList
= SecCopyLogSettings_Server(&error
);
764 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, currentList
, &error
);
766 CFReleaseSafe(currentList
);
769 case sec_set_xpc_log_settings_id
:
771 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
773 SecSetXPCLogSettings_Server(newSettings
, &error
);
775 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
776 CFReleaseNull(newSettings
);
779 case sec_set_circle_log_settings_id
:
781 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
783 SecSetCircleLogSettings_Server(newSettings
, &error
);
785 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
786 CFReleaseNull(newSettings
);
789 case sec_otr_session_create_remote_id
:
791 CFDataRef publicPeerId
= NULL
;
792 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCPublicPeerId
, &publicPeerId
, &error
)) {
793 CFDataRef otrSession
= _SecOTRSessionCreateRemote(publicPeerId
, &error
);
795 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, otrSession
, &error
);
796 CFReleaseNull(otrSession
);
798 CFReleaseSafe(publicPeerId
);
802 case sec_otr_session_process_packet_remote_id
:
804 CFDataRef sessionData
= NULL
, inputPacket
= NULL
, outputSessionData
= NULL
, outputPacket
= NULL
;
805 bool readyForMessages
= false;
806 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCOTRSession
, &sessionData
, &error
)) {
807 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &inputPacket
, &error
)) {
808 bool result
= _SecOTRSessionProcessPacketRemote(sessionData
, inputPacket
, &outputSessionData
, &outputPacket
, &readyForMessages
, &error
);
810 SecXPCDictionarySetData(replyMessage
, kSecXPCOTRSession
, outputSessionData
, &error
);
811 SecXPCDictionarySetData(replyMessage
, kSecXPCData
, outputPacket
, &error
);
812 xpc_dictionary_set_bool(replyMessage
, kSecXPCOTRReady
, readyForMessages
);
813 CFReleaseNull(outputSessionData
);
814 CFReleaseNull(outputPacket
);
816 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
818 CFReleaseSafe(inputPacket
);
820 CFReleaseSafe(sessionData
);
824 case kSecXPCOpTryUserCredentials
:
825 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
826 with_label_and_password_and_dsid(event
, ^(CFStringRef label
, CFDataRef password
, CFStringRef dsid
) {
827 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
828 SOSCCTryUserCredentials_Server(label
, password
, dsid
, &error
));
832 case kSecXPCOpSetUserCredentials
:
833 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
834 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
835 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
836 SOSCCSetUserCredentials_Server(label
, password
, &error
));
840 case kSecXPCOpSetUserCredentialsAndDSID
:
841 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
842 with_label_and_password_and_dsid(event
, ^(CFStringRef label
, CFDataRef password
, CFStringRef dsid
) {
843 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
844 SOSCCSetUserCredentialsAndDSID_Server(label
, password
, dsid
, &error
));
849 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
850 with_label_and_number(event
, ^(CFStringRef view
, uint64_t actionCode
) {
851 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
852 SOSCCView_Server(view
, (SOSViewActionCode
)actionCode
, &error
));
856 case kSecXPCOpViewSet
:
857 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
858 CFSetRef enabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyEnabledViewsKey
);
859 CFSetRef disabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyDisabledViewsKey
);
860 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCViewSet_Server(enabledViews
, disabledViews
));
861 CFReleaseNull(enabledViews
);
862 CFReleaseNull(disabledViews
);
865 case kSecXPCOpSecurityProperty
:
866 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
867 with_label_and_number(event
, ^(CFStringRef property
, uint64_t actionCode
) {
868 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
869 SOSCCSecurityProperty_Server(property
, (SOSSecurityPropertyActionCode
)actionCode
, &error
));
873 case kSecXPCOpCanAuthenticate
:
874 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
875 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
876 SOSCCCanAuthenticate_Server(&error
));
879 case kSecXPCOpPurgeUserCredentials
:
880 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
881 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
882 SOSCCPurgeUserCredentials_Server(&error
));
885 case kSecXPCOpDeviceInCircle
:
886 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
887 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
888 SOSCCThisDeviceIsInCircle_Server(&error
));
891 case kSecXPCOpRequestToJoin
:
892 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
893 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
894 SOSCCRequestToJoinCircle_Server(&error
));
897 case kSecXPCOpAccountHasPublicKey
:
898 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
899 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
900 SOSCCAccountHasPublicKey_Server(&error
));
903 case kSecXPCOpAccountIsNew
:
904 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
905 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
906 SOSCCAccountIsNew_Server(&error
));
909 case kSecXPCOpRequestToJoinAfterRestore
:
910 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
911 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
912 SOSCCRequestToJoinCircleAfterRestore_Server(&error
));
915 case kSecXPCOpRequestEnsureFreshParameters
:
916 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
917 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
918 SOSCCRequestEnsureFreshParameters_Server(&error
));
921 case kSecXPCOpGetAllTheRings
:
922 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
923 CFStringRef ringDescriptions
= SOSCCGetAllTheRings_Server(&error
);
924 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(ringDescriptions
);
925 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
926 xpc_release(xpc_dictionary
);
929 case kSecXPCOpApplyToARing
:
930 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
931 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
932 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCApplyToARing_Server(ringName
, &error
));
933 CFReleaseNull(ringName
);
936 case kSecXPCOpWithdrawlFromARing
:
937 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
938 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
939 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCWithdrawlFromARing_Server(ringName
, &error
));
940 CFReleaseNull(ringName
);
943 case kSecXPCOpRingStatus
:
944 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
945 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
946 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRingStatus_Server(ringName
, &error
));
947 CFReleaseNull(ringName
);
950 case kSecXPCOpEnableRing
:
951 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
952 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
953 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCEnableRing_Server(ringName
, &error
));
954 CFReleaseNull(ringName
);
957 case kSecXPCOpRequestDeviceID
:
958 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
959 CFStringRef deviceID
= SOSCCCopyDeviceID_Server(&error
);
961 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, deviceID
, &error
);
963 CFReleaseNull(deviceID
);
966 case kSecXPCOpSetDeviceID
:
967 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
968 CFStringRef IDS
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
969 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCSetDeviceID_Server(IDS
, &error
));
973 case kSecXPCOpHandleIDSMessage
:
974 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
975 CFDictionaryRef IDS
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyIDSMessage
, &error
);
976 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
, SOSCCHandleIDSMessage_Server(IDS
, &error
));
980 case kSecXPCOpClearKVSPeerMessage
:
981 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
982 CFStringRef peerID
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
983 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCClearPeerMessageKeyInKVS_Server(peerID
, &error
));
984 CFReleaseNull(peerID
);
987 case kSecXPCOpSendIDSMessage
:
988 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
989 CFStringRef message
= SecXPCDictionaryCopyString(event
, kSecXPCKeySendIDSMessage
, &error
);
990 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSServiceRegistrationTest_Server(message
, &error
));
991 CFReleaseNull(message
);
994 case kSecXPCOpSyncWithKVSPeer
:
995 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
996 CFStringRef peerID
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
997 CFDataRef message
= SecXPCDictionaryCopyData(event
, kSecXPCKeyIDSMessage
, &error
);
998 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRequestSyncWithPeerOverKVS_Server(peerID
, message
, &error
));
999 CFReleaseNull(message
);
1000 CFReleaseNull(peerID
);
1003 case kSecXPCOpSyncWithKVSPeerIDOnly
:
1004 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1005 CFStringRef peerID
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
1006 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRequestSyncWithPeerOverKVSUsingIDOnly_Server(peerID
, &error
));
1007 CFReleaseNull(peerID
);
1010 case kSecXPCOpPingTest
:
1011 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1012 CFStringRef message
= SecXPCDictionaryCopyString(event
, kSecXPCKeySendIDSMessage
, &error
);
1013 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSPingTest_Server(message
, &error
));
1014 CFReleaseNull(message
);
1017 case kSecXPCOpIDSDeviceID
:
1018 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1019 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSDeviceIDIsAvailableTest_Server(&error
));
1022 case kSecXPCOpAccountSetToNew
:
1023 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1024 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCAccountSetToNew_Server(&error
));
1027 case kSecXPCOpResetToOffering
:
1028 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1029 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1030 SOSCCResetToOffering_Server(&error
));
1033 case kSecXPCOpResetToEmpty
:
1034 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1035 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1036 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 kSecXPCOpRemovePeersFromCircle
:
1046 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1047 CFArrayRef applicants
= SecXPCDictionaryCopyPeerInfoArray(event
, kSecXPCKeyPeerInfoArray
, &error
);
1048 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1049 SOSCCRemovePeersFromCircle_Server(applicants
, &error
));
1050 CFReleaseNull(applicants
);
1053 case kSecXPCOpLoggedOutOfAccount
:
1054 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1055 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1056 SOSCCLoggedOutOfAccount_Server(&error
));
1059 case kSecXPCOpBailFromCircle
:
1060 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1061 uint64_t limit_in_seconds
= xpc_dictionary_get_uint64(event
, kSecXPCLimitInMinutes
);
1062 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1063 SOSCCBailFromCircle_Server(limit_in_seconds
, &error
));
1066 case kSecXPCOpAcceptApplicants
:
1067 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1068 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfoArray
);
1069 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1070 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1071 (applicants
&& SOSCCAcceptApplicants_Server(applicants
, &error
)));
1072 CFReleaseSafe(applicants
);
1075 case kSecXPCOpRejectApplicants
:
1076 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1077 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfoArray
);
1078 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1079 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1080 (applicants
&& SOSCCRejectApplicants_Server(applicants
, &error
)));
1081 CFReleaseSafe(applicants
);
1084 case kSecXPCOpSetNewPublicBackupKey
:
1086 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1087 CFDataRef publicBackupKey
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNewPublicBackupKey
, &error
);
1088 SOSPeerInfoRef peerInfo
= SOSCCSetNewPublicBackupKey_Server(publicBackupKey
, &error
);
1089 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1090 CFReleaseNull(peerInfo
);
1092 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1093 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1094 xpc_release(xpc_object
);
1096 CFReleaseNull(peerInfoData
);
1097 CFReleaseSafe(publicBackupKey
);
1102 case kSecXPCOpRegisterRecoveryPublicKey
:
1104 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1105 CFDataRef recovery_key
= SecXPCDictionaryCopyData(event
, kSecXPCKeyRecoveryPublicKey
, &error
);
1107 CFDataRef nullData
= CFDataCreate(kCFAllocatorDefault
, &zero
, 1); // token we send if we really wanted to send NULL
1108 if(CFEqual(recovery_key
, nullData
)) {
1109 CFReleaseNull(recovery_key
);
1111 CFReleaseNull(nullData
);
1112 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRegisterRecoveryPublicKey_Server(recovery_key
, &error
));
1113 CFReleaseNull(recovery_key
);
1117 case kSecXPCOpGetRecoveryPublicKey
:
1119 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1120 xpc_object_t xpc_recovery_object
= NULL
;
1121 CFDataRef recovery
= SOSCCCopyRecoveryPublicKey(&error
);
1123 xpc_recovery_object
= _CFXPCCreateXPCObjectFromCFObject(recovery
);
1125 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_recovery_object
);
1126 CFReleaseNull(recovery
);
1130 case kSecXPCOpSetBagForAllSlices
:
1132 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1133 CFDataRef backupSlice
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
1134 bool includeV0
= xpc_dictionary_get_bool(event
, kSecXPCKeyIncludeV0
);
1135 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, backupSlice
&& SOSCCRegisterSingleRecoverySecret_Server(backupSlice
, includeV0
, &error
));
1136 CFReleaseSafe(backupSlice
);
1140 case kSecXPCOpCopyApplicantPeerInfo
:
1141 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1142 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1143 SOSCCCopyApplicantPeerInfo_Server(&error
),
1147 case kSecXPCOpCopyValidPeerPeerInfo
:
1148 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1149 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1150 SOSCCCopyValidPeerPeerInfo_Server(&error
),
1154 case kSecXPCOpValidateUserPublic
:
1155 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1156 bool trusted
= SOSCCValidateUserPublic_Server(&error
);
1157 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, trusted
);
1160 case kSecXPCOpCopyNotValidPeerPeerInfo
:
1161 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1162 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1163 SOSCCCopyNotValidPeerPeerInfo_Server(&error
),
1167 case kSecXPCOpCopyGenerationPeerInfo
:
1168 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1169 xpc_dictionary_set_and_consume_CFArray(replyMessage
, kSecXPCKeyResult
,
1170 SOSCCCopyGenerationPeerInfo_Server(&error
));
1173 case kSecXPCOpCopyRetirementPeerInfo
:
1174 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1175 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1176 SOSCCCopyRetirementPeerInfo_Server(&error
),
1180 case kSecXPCOpCopyViewUnawarePeerInfo
:
1181 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1182 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1183 SOSCCCopyViewUnawarePeerInfo_Server(&error
),
1187 case kSecXPCOpCopyAccountData
:
1189 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1190 xpc_object_t xpc_account_object
= NULL
;
1191 CFDataRef accountData
= SOSCCCopyAccountState_Server(&error
);
1193 xpc_account_object
= _CFXPCCreateXPCObjectFromCFObject(accountData
);
1195 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_account_object
);
1196 CFReleaseNull(accountData
);
1200 case kSecXPCOpDeleteAccountData
:
1202 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1203 bool status
= SOSCCDeleteAccountState_Server(&error
);
1204 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, status
);
1208 case kSecXPCOpCopyEngineData
:
1210 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1212 xpc_object_t xpc_engine_object
= NULL
;
1213 CFDataRef engineData
= SOSCCCopyEngineData_Server(&error
);
1215 xpc_engine_object
= _CFXPCCreateXPCObjectFromCFObject(engineData
);
1217 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_engine_object
);
1218 CFReleaseNull(engineData
);
1223 case kSecXPCOpDeleteEngineData
:
1225 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1226 bool status
= SOSCCDeleteEngineState_Server(&error
);
1227 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, status
);
1231 case kSecXPCOpCopyEngineState
:
1233 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1234 CFArrayRef array
= SOSCCCopyEngineState_Server(&error
);
1235 CFDataRef derData
= NULL
;
1237 require_quiet(array
, done
);
1238 derData
= CFPropertyListCreateDERData(kCFAllocatorDefault
, array
, &error
);
1240 require_quiet(derData
, done
);
1241 xpc_dictionary_set_data(replyMessage
, kSecXPCKeyResult
, CFDataGetBytePtr(derData
), CFDataGetLength(derData
));
1243 CFReleaseNull(derData
);
1244 CFReleaseNull(array
);
1248 case kSecXPCOpCopyPeerPeerInfo
:
1249 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1250 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1251 SOSCCCopyPeerPeerInfo_Server(&error
),
1255 case kSecXPCOpCopyConcurringPeerPeerInfo
:
1256 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1257 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1258 SOSCCCopyConcurringPeerPeerInfo_Server(&error
),
1262 case kSecXPCOpCopyMyPeerInfo
:
1263 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1264 SOSPeerInfoRef peerInfo
= SOSCCCopyMyPeerInfo_Server(&error
);
1265 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1266 CFReleaseNull(peerInfo
);
1268 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1269 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1270 xpc_release(xpc_object
);
1272 CFReleaseNull(peerInfoData
);
1275 case kSecXPCOpGetLastDepartureReason
:
1276 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1277 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1278 SOSCCGetLastDepartureReason_Server(&error
));
1281 case kSecXPCOpSetLastDepartureReason
:
1282 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1283 int32_t reason
= (int32_t) xpc_dictionary_get_int64(event
, kSecXPCKeyReason
);
1284 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1285 SOSCCSetLastDepartureReason_Server(reason
, &error
));
1288 case kSecXPCOpProcessSyncWithPeers
:
1289 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1290 CFSetRef peers
= SecXPCDictionaryCopySet(event
, kSecXPCKeySet
, &error
);
1291 CFSetRef backupPeers
= SecXPCDictionaryCopySet(event
, kSecXPCKeySet2
, &error
);
1292 if (peers
&& backupPeers
) {
1293 CFSetRef result
= SOSCCProcessSyncWithPeers_Server(peers
, backupPeers
, &error
);
1295 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
1297 CFReleaseNull(result
);
1299 CFReleaseNull(peers
);
1300 CFReleaseNull(backupPeers
);
1303 case kSecXPCOpProcessSyncWithAllPeers
:
1304 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1305 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1306 SOSCCProcessSyncWithAllPeers_Server(&error
));
1309 case soscc_EnsurePeerRegistration_id
:
1310 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1311 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1312 SOSCCProcessEnsurePeerRegistration_Server(&error
));
1315 case kSecXPCOpCopyIncompatibilityInfo
:
1316 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1317 CFStringRef iis
= SOSCCCopyIncompatibilityInfo_Server(&error
);
1318 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, iis
, &error
);
1322 case kSecXPCOpRollKeys
:
1324 bool force
= xpc_dictionary_get_bool(event
, "force");
1325 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1326 _SecServerRollKeys(force
, &client
, &error
));
1329 case kSecXPCOpWaitForInitialSync
:
1330 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1331 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1332 SOSCCWaitForInitialSync_Server(&error
));
1336 case kSecXPCOpCopyYetToSyncViews
:
1337 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1338 CFArrayRef array
= SOSCCCopyYetToSyncViewsList_Server(&error
);
1340 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1341 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1342 xpc_release(xpc_array
);
1344 CFReleaseNull(array
);
1347 case kSecXPCOpSetEscrowRecord
:
1348 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1349 CFStringRef escrow_label
= SecXPCDictionaryCopyString(event
, kSecXPCKeyEscrowLabel
, &error
);
1350 uint64_t tries
= xpc_dictionary_get_int64(event
, kSecXPCKeyTriesLabel
);
1352 bool result
= SOSCCSetEscrowRecord_Server(escrow_label
, tries
, &error
);
1354 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1356 CFReleaseNull(escrow_label
);
1359 case kSecXPCOpGetEscrowRecord
:
1360 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1361 CFDictionaryRef record
= SOSCCCopyEscrowRecord_Server(&error
);
1363 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(record
);
1364 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1365 xpc_release(xpc_dictionary
);
1367 CFReleaseNull(record
);
1370 case kSecXPCOpCopyBackupInformation
:
1371 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1372 CFDictionaryRef record
= SOSCCCopyBackupInformation_Server(&error
);
1374 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(record
);
1375 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1376 xpc_release(xpc_dictionary
);
1378 CFReleaseNull(record
);
1382 case kSecXPCOpCheckPeerAvailability
:
1383 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1384 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCCheckPeerAvailability_Server(&error
));
1389 case kSecXPCOpIsThisDeviceLastBackup
:
1390 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1391 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCkSecXPCOpIsThisDeviceLastBackup_Server(&error
));
1394 case kSecXPCOpPeersHaveViewsEnabled
:
1396 CFArrayRef viewSet
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyArray
, &error
);
1398 CFBooleanRef result
= SOSCCPeersHaveViewsEnabled_Server(viewSet
, &error
);
1399 if (result
!= NULL
) {
1400 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
!= kCFBooleanFalse
);
1403 CFReleaseNull(viewSet
);
1407 case kSecXPCOpWhoAmI
:
1410 xpc_dictionary_set_data(replyMessage
, "musr", CFDataGetBytePtr(client
.musr
), CFDataGetLength(client
.musr
));
1411 xpc_dictionary_set_bool(replyMessage
, "system-keychain", client
.allowSystemKeychain
);
1412 xpc_dictionary_set_bool(replyMessage
, "syncbubble-keychain", client
.allowSyncBubbleKeychain
);
1413 xpc_dictionary_set_bool(replyMessage
, "network-extension", client
.isNetworkExtension
);
1414 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1417 case kSecXPCOpTransmogrifyToSyncBubble
:
1419 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainSyncBubble
, &error
)) {
1421 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1422 CFArrayRef services
= SecXPCDictionaryCopyArray(event
, "services", &error
);
1424 if (uid
&& services
) {
1425 res
= _SecServerTransmogrifyToSyncBubble(services
, uid
, &client
, &error
);
1427 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1428 CFReleaseNull(services
);
1430 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1435 case kSecXPCOpTransmogrifyToSystemKeychain
:
1437 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
)) {
1439 bool res
= _SecServerTransmogrifyToSystemKeychain(&client
, &error
);
1440 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1442 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1448 case kSecXPCOpDeleteUserView
:
1450 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
)) {
1453 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1455 res
= _SecServerDeleteMUSERViews(&client
, uid
, &error
);
1458 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1463 case kSecXPCOpWrapToBackupSliceKeyBagForView
:
1465 CFStringRef viewname
= SecXPCDictionaryCopyString(event
, kSecXPCKeyViewName
, &error
);
1467 CFDataRef plaintext
= SecXPCDictionaryCopyData(event
, kSecXPCData
, &error
);
1469 CFDataRef ciphertext
= NULL
;
1470 CFDataRef bskbEncoded
= NULL
;
1472 bool result
= SOSWrapToBackupSliceKeyBagForView_Server(viewname
, plaintext
, &ciphertext
, &bskbEncoded
, &error
);
1473 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1475 if(!error
&& result
) {
1477 xpc_dictionary_set_data(replyMessage
, kSecXPCData
, CFDataGetBytePtr(ciphertext
), CFDataGetLength(ciphertext
));
1480 xpc_dictionary_set_data(replyMessage
, kSecXPCKeyKeybag
, CFDataGetBytePtr(bskbEncoded
), CFDataGetLength(bskbEncoded
));
1483 CFReleaseSafe(ciphertext
);
1484 CFReleaseSafe(bskbEncoded
);
1486 CFReleaseSafe(plaintext
);
1488 CFReleaseNull(viewname
);
1491 case kSecXPCOpCopyApplication
:
1492 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1493 SOSPeerInfoRef peerInfo
= SOSCCCopyApplication_Server(&error
);
1494 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1495 CFReleaseNull(peerInfo
);
1497 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1498 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1499 xpc_release(xpc_object
);
1501 CFReleaseNull(peerInfoData
);
1504 case kSecXPCOpCopyCircleJoiningBlob
:
1505 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1506 CFDataRef appBlob
= SecXPCDictionaryCopyCFDataRef(event
, kSecXPCData
, &error
);
1507 SOSPeerInfoRef applicant
= SOSPeerInfoCreateFromData(kCFAllocatorDefault
, &error
, appBlob
);
1508 CFDataRef pbblob
= SOSCCCopyCircleJoiningBlob_Server(applicant
, &error
);
1510 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(pbblob
);
1511 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1512 xpc_release(xpc_object
);
1514 CFReleaseNull(pbblob
);
1515 CFReleaseNull(applicant
);
1516 CFReleaseNull(appBlob
);
1519 case kSecXPCOpCopyInitialSyncBlob
:
1520 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1521 CFDataRef initialblob
= SOSCCCopyInitialSyncData_Server(&error
);
1523 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(initialblob
);
1524 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1525 xpc_release(xpc_object
);
1527 CFReleaseNull(initialblob
);
1530 case kSecXPCOpJoinWithCircleJoiningBlob
:
1531 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1532 CFDataRef joiningBlob
= SecXPCDictionaryCopyCFDataRef(event
, kSecXPCData
, &error
);
1533 uint64_t version
= xpc_dictionary_get_uint64(event
, kSecXPCVersion
);
1534 bool retval
= SOSCCJoinWithCircleJoiningBlob_Server(joiningBlob
, (PiggyBackProtocolVersion
) version
, &error
);
1535 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1536 CFReleaseNull(joiningBlob
);
1540 case kSecXPCOpKVSKeyCleanup
:
1541 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1542 bool retval
= SOSCCCleanupKVSKeys_Server(&error
);
1543 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1546 case kSecXPCOpPopulateKVS
:
1547 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1548 bool retval
= SOSCCTestPopulateKVSWithBadKeys_Server(&error
);
1549 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1552 case kSecXPCOpMessageFromPeerIsPending
:
1554 SOSPeerInfoRef peer
= SecXPCDictionaryCopyPeerInfo(event
, kSecXPCKeyPeerInfo
, &error
);
1556 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1557 SOSCCMessageFromPeerIsPending_Server(peer
, &error
));
1559 CFReleaseNull(peer
);
1562 case kSecXPCOpSendToPeerIsPending
:
1564 SOSPeerInfoRef peer
= SecXPCDictionaryCopyPeerInfo(event
, kSecXPCKeyPeerInfo
, &error
);
1566 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1567 SOSCCSendToPeerIsPending(peer
, &error
));
1569 CFReleaseNull(peer
);
1572 case sec_delete_items_with_access_groups_id
:
1574 bool retval
= false;
1575 #if TARGET_OS_IPHONE
1576 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateUninstallDeletion
, &error
)) {
1577 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyAccessGroups
, &error
);
1580 retval
= _SecItemServerDeleteAllWithAccessGroups(accessGroups
, &client
, &error
);
1582 CFReleaseNull(accessGroups
);
1585 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1588 case sec_item_copy_parent_certificates_id
:
1590 CFArrayRef results
= NULL
;
1591 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateCertificateAllAccess
, &error
)) {
1592 CFDataRef issuer
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNormalizedIssuer
, &error
);
1593 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyAccessGroups
, &error
);
1594 if (issuer
&& accessGroups
) {
1595 results
= _SecItemCopyParentCertificates(issuer
, accessGroups
, &error
);
1597 CFReleaseNull(issuer
);
1598 CFReleaseNull(accessGroups
);
1600 SecXPCDictionarySetPListOptional(replyMessage
, kSecXPCKeyResult
, results
, &error
);
1601 CFReleaseNull(results
);
1604 case sec_item_certificate_exists_id
:
1606 bool result
= false;
1607 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateCertificateAllAccess
, &error
)) {
1608 CFDataRef issuer
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNormalizedIssuer
, &error
);
1609 CFDataRef serialNum
= SecXPCDictionaryCopyData(event
, kSecXPCKeySerialNumber
, &error
);
1610 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyAccessGroups
, &error
);
1611 if (issuer
&& serialNum
&& accessGroups
) {
1612 result
= _SecItemCertificateExists(issuer
, serialNum
, accessGroups
, &error
);
1614 CFReleaseNull(issuer
);
1615 CFReleaseNull(serialNum
);
1616 CFReleaseNull(accessGroups
);
1618 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1621 case kSecXPCOpBackupKeybagAdd
: {
1622 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementBackupTableOperations
, &error
)) {
1623 CFDataRef keybag
= NULL
, passcode
= NULL
;
1624 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
1625 CFDataRef identifier
= NULL
;
1626 CFDataRef pathinfo
= NULL
; // really a CFURLRef
1627 bool added
= _SecServerBackupKeybagAdd(&client
, passcode
, &identifier
, &pathinfo
, &error
);
1629 added
&= SecXPCDictionarySetDataOptional(replyMessage
, kSecXPCKeyBackupKeybagIdentifier
, identifier
, &error
);
1630 added
&= SecXPCDictionarySetDataOptional(replyMessage
, kSecXPCKeyBackupKeybagPath
, pathinfo
, &error
);
1631 SecXPCDictionarySetBool(replyMessage
, kSecXPCKeyResult
, added
, NULL
);
1633 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1636 CFReleaseSafe(passcode
);
1637 CFReleaseSafe(keybag
);
1641 case kSecXPCOpBackupKeybagDelete
: {
1643 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementBackupTableOperations
, &error
)) {
1644 bool deleted
= false;
1645 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
1647 CFTypeRef matchLimit
= CFDictionaryGetValue(query
, kSecMatchLimit
);
1648 bool deleteAll
= matchLimit
&& CFEqualSafe(matchLimit
, kSecMatchLimitAll
);
1650 if (deleteAll
&& !EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementBackupTableOperationsDeleteAll
, &error
)) {
1651 // require special entitlement to delete all backup keybags
1653 CFMutableDictionaryRef attributes
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, query
);
1654 CFStringRef requestedAgrp
= CFDictionaryGetValue(attributes
, kSecAttrAccessGroup
);
1655 CFStringRef resolvedAgrp
= NULL
;
1657 CFDictionarySetValue(attributes
, kSecAttrMultiUser
, client
.musr
);
1659 if (extractAccessGroup(&client
, requestedAgrp
, &resolvedAgrp
, &error
)) {
1661 CFDictionarySetValue(attributes
, kSecAttrAccessGroup
, resolvedAgrp
);
1663 deleted
= _SecServerBackupKeybagDelete(attributes
, deleteAll
, &error
);
1665 CFReleaseNull(attributes
);
1668 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, deleted
);
1669 CFReleaseNull(query
);
1673 case kSecXPCOpKeychainControlEndpoint
: {
1674 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainControl
, &error
)) {
1675 xpc_endpoint_t endpoint
= SecServerCreateKeychainControlEndpoint();
1677 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyEndpoint
, endpoint
);
1678 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1679 xpc_release(endpoint
);
1681 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1692 if(SecErrorGetOSStatus(error
) == errSecItemNotFound
|| isSOSErrorCoded(error
, kSOSErrorPublicKeyAbsent
))
1693 secdebug("ipc", "%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1694 else if (SecErrorGetOSStatus(error
) == errSecAuthNeeded
)
1695 secwarning("Authentication is needed %@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1697 secerror("%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1699 xpcError
= SecCreateXPCObjectWithCFError(error
);
1701 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyError
, xpcError
);
1703 } else if (replyMessage
) {
1704 secdebug("ipc", "%@ %@ responding %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyMessage
);
1707 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, &error
, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event
);
1708 secerror("%@: returning error: %@", client
.task
, error
);
1709 xpcError
= SecCreateXPCObjectWithCFError(error
);
1710 replyMessage
= xpc_create_reply_with_format(event
, "{%string: %value}", kSecXPCKeyError
, xpcError
);
1714 xpc_connection_send_message(connection
, replyMessage
);
1715 xpc_release(replyMessage
);
1718 xpc_release(xpcError
);
1719 #if TARGET_OS_IPHONE
1720 pthread_setspecific(taskThreadKey
, NULL
);
1722 CFReleaseSafe(error
);
1723 CFReleaseSafe(client
.accessGroups
);
1724 CFReleaseSafe(client
.musr
);
1725 CFReleaseSafe(client
.task
);
1726 CFReleaseSafe(domains
);
1727 CFReleaseSafe(clientAuditToken
);
1730 static void securityd_xpc_init(const char *service_name
)
1732 #if TARGET_OS_IPHONE
1733 pthread_key_create(&taskThreadKey
, NULL
);
1734 SecTaskDiagnoseEntitlements
= secTaskDiagnoseEntitlements
;
1737 secdebug("serverxpc", "start");
1738 xpc_connection_t listener
= xpc_connection_create_mach_service(service_name
, NULL
, XPC_CONNECTION_MACH_SERVICE_LISTENER
);
1740 seccritical("security failed to register xpc listener for %s, exiting", service_name
);
1744 xpc_connection_set_event_handler(listener
, ^(xpc_object_t connection
) {
1745 if (xpc_get_type(connection
) == XPC_TYPE_CONNECTION
) {
1746 xpc_connection_set_event_handler(connection
, ^(xpc_object_t event
) {
1747 if (xpc_get_type(event
) == XPC_TYPE_DICTIONARY
) {
1748 xpc_retain(connection
);
1750 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
1751 securityd_xpc_dictionary_handler(connection
, event
);
1753 xpc_release(connection
);
1757 xpc_connection_resume(connection
);
1760 xpc_connection_resume(listener
);
1763 xpc_activity_register("com.apple.securityd.daily", XPC_ACTIVITY_CHECK_IN
, ^(xpc_activity_t activity
) {
1764 xpc_activity_state_t activityState
= xpc_activity_get_state(activity
);
1765 if (activityState
== XPC_ACTIVITY_STATE_RUN
) {
1766 SecCKKS24hrNotification();
1773 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1775 #if TARGET_OS_EMBEDDED
1776 static void securityd_soscc_lock_hack() {
1777 dispatch_queue_t soscc_lock_queue
= dispatch_queue_create("soscc_lock_queue", DISPATCH_QUEUE_PRIORITY_DEFAULT
);
1780 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1781 // FIXME: securityd isn't currently registering for any other notifyd events. If/when it does,
1782 // this code will need to be generalized / migrated away from just this specific purpose.
1783 xpc_set_event_stream_handler("com.apple.notifyd.matching", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH
, 0), ^(xpc_object_t object
) {
1784 char *event_description
= xpc_copy_description(object
);
1785 secnotice("events", "%s", event_description
);
1786 free(event_description
);
1789 secnotice("lockassertion", "notify_register_dispatch(kSOSCCHoldLockForInitialSync)");
1790 notify_register_dispatch(kSOSCCHoldLockForInitialSync
, &soscc_tok
, soscc_lock_queue
, ^(int token __unused
) {
1791 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync: grabbing the lock");
1792 CFErrorRef error
= NULL
;
1794 uint64_t one_minute
= 60ull;
1795 if(SecAKSLockUserKeybag(one_minute
, &error
)){
1796 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1797 xpc_transaction_begin();
1799 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, one_minute
*NSEC_PER_SEC
), soscc_lock_queue
, ^{
1800 CFErrorRef localError
= NULL
;
1801 if(!SecAKSUnLockUserKeybag(&localError
))
1802 secerror("failed to unlock: %@", localError
);
1803 CFReleaseNull(localError
);
1804 xpc_transaction_end();
1807 secerror("Failed to take device lock assertion: %@", error
);
1809 CFReleaseNull(error
);
1810 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync => done");
1820 static char homeDir
[PATH_MAX
] = {};
1822 if (homeDir
[0] == '\0') {
1823 struct passwd
* pwd
= getpwuid(getuid());
1827 if (realpath(pwd
->pw_dir
, homeDir
) == NULL
) {
1828 strlcpy(homeDir
, pwd
->pw_dir
, sizeof(homeDir
));
1836 int main(int argc
, char *argv
[])
1838 char *wait4debugger
= getenv("WAIT4DEBUGGER");
1839 if (wait4debugger
&& !strcasecmp("YES", wait4debugger
)) {
1840 seccritical("SIGSTOPing self, awaiting debugger");
1841 kill(getpid(), SIGSTOP
);
1842 seccritical("Again, for good luck (or bad debuggers)");
1843 kill(getpid(), SIGSTOP
);
1846 /* <rdar://problem/15792007> Users with network home folders are unable to use/save password for Mail/Cal/Contacts/websites
1847 Secd doesn't realize DB connections get invalidated when network home directory users logout
1848 and their home gets unmounted. Exit secd, start fresh when user logs back in.
1851 int sessionstatechanged_tok
;
1852 notify_register_dispatch(kSA_SessionStateChangedNotification
, &sessionstatechanged_tok
, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^(int token __unused
) {
1853 // we could be a process running as root.
1854 // However, since root never logs out this isn't an issue.
1855 if (SASSessionStateForUser(getuid()) == kSA_state_loggingout_pointofnoreturn
) {
1856 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, 3ull*NSEC_PER_SEC
), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
1857 xpc_transaction_exit_clean();
1864 #define SECD_PROFILE_NAME "com.apple.secd"
1865 const char *homedir
= homedirPath();
1866 if (homedir
== NULL
)
1867 errx(1, "failed to get home directory for secd");
1869 char *errorbuf
= NULL
;
1870 const char *sandbox_params
[] = {
1876 rc
= sandbox_init_with_parameters(SECD_PROFILE_NAME
, SANDBOX_NAMED
, sandbox_params
, &errorbuf
);
1878 err(1, "Failed to process in a sandbox: %d %s", rc
, errorbuf
);
1879 #endif /* TARGET_OS_OSX */
1881 const char *serviceName
= kSecuritydXPCServiceName
;
1882 /* setup SQDLite before some other component have a chance to create a database connection */
1883 _SecDbServerSetup();
1885 securityd_init_server();
1886 securityd_xpc_init(serviceName
);
1888 SecCreateSecuritydXPCServer();
1889 CKKSControlServerInitialize();
1890 SOSControlServerInitialize();
1891 OctagonControlServerInitialize();
1893 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1894 #if TARGET_OS_EMBEDDED
1895 securityd_soscc_lock_hack();
1901 /* vi:set ts=4 sw=4 et: */