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/SecBase.h>
30 #include <Security/SecBasePriv.h>
31 #include <Security/SecCertificatePriv.h>
32 #include <Security/SecEntitlements.h>
33 #include <Security/SecInternal.h>
34 #include <Security/SecItem.h>
35 #include <Security/SecItemPriv.h> /* For SecItemDeleteAll */
36 #include <Security/SecPolicy.h>
37 #include <Security/SecPolicyInternal.h>
38 #include <Security/SecTask.h>
39 #include <Security/SecTrustInternal.h>
40 #include <Security/SecuritydXPC.h>
41 #include <securityd/OTATrustUtilities.h>
42 #include <securityd/SOSCloudCircleServer.h>
43 #include <securityd/SecItemBackupServer.h>
44 #include <securityd/SecItemServer.h>
45 #include <securityd/SecLogSettingsServer.h>
46 #include <securityd/SecOTRRemote.h>
47 #include <securityd/SecTrustServer.h>
48 #include <securityd/SecTrustStoreServer.h>
49 #include <securityd/iCloudTrace.h>
50 #include <securityd/spi.h>
51 #include <utilities/SecCFError.h>
52 #include <utilities/SecCFWrappers.h>
53 #include <utilities/SecDb.h>
54 #include <utilities/SecIOFormat.h>
55 #include <utilities/SecXPCError.h>
56 #include <utilities/debugging.h>
57 #include <utilities/SecInternalReleasePriv.h>
58 #include <utilities/der_plist_internal.h>
59 #include <utilities/der_plist.h>
60 #include <securityd/personalization.h>
61 #include <securityd/SecPinningDb.h>
63 #include <keychain/ckks/CKKS.h>
65 #include <AssertMacros.h>
66 #include <CoreFoundation/CFXPCBridge.h>
67 #include <CoreFoundation/CoreFoundation.h>
68 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
71 #include <Security/SecTaskPriv.h>
72 #include <login/SessionAgentStatusCom.h>
75 #include <bsm/libbsm.h>
76 #include <ipc/securityd_client.h>
77 #include <libkern/OSAtomic.h>
78 #include <mach/mach.h>
79 #include <mach/message.h>
82 #include <sys/queue.h>
83 #include <sys/sysctl.h>
85 #include <xpc/private.h>
88 #include <ipc/server_security_helpers.h>
89 #include <ipc/server_entitlement_helpers.h>
97 static bool accessGroupPermitted(SecurityClient
* client
, CFArrayRef accessGroups
, CFStringRef accessGroup
) {
98 /* NULL accessGroups is wildcard. */
101 /* Make sure we have a string. */
102 if (!isString(accessGroup
))
105 /* Having the special accessGroup "*" allows access to all accessGroups. */
106 CFRange range
= { 0, CFArrayGetCount(accessGroups
) };
108 (CFArrayContainsValue(accessGroups
, range
, accessGroup
) ||
109 CFArrayContainsValue(accessGroups
, range
, CFSTR("*"))))
115 static bool extractAccessGroup(SecurityClient
*client
, CFStringRef requestedAgrp
, CFStringRef
*resolvedAgrp
, CFErrorRef
*error
) {
118 /* Access group sanity checking.
119 Similar to accessGroupsAllows, but ignores accessGroupIsNetworkExtensionAndClientIsEntitled */
120 CFArrayRef accessGroups
= client
->accessGroups
;
121 CFStringRef agrp
= requestedAgrp
;
122 /* Having the special accessGroup "*" allows access to all accessGroups. */
123 if (CFArrayContainsValue(accessGroups
, CFRangeMake(0,CFArrayGetCount(accessGroups
)), CFSTR("*")))
127 /* The user specified an explicit access group, validate it. */
128 if (!accessGroupPermitted(client
, accessGroups
, requestedAgrp
))
129 ok
= SecError(errSecMissingEntitlement
, error
, CFSTR("explicit accessGroup %@ not in client access %@"), requestedAgrp
, accessGroups
);
131 // We are using an implicit access group
132 // Add it as if the user specified it as an attribute.
133 agrp
= (CFStringRef
)CFArrayGetValueAtIndex(client
->accessGroups
, 0);
136 if (agrp
&& resolvedAgrp
)
137 *resolvedAgrp
= agrp
;
141 static void with_label_and_password(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
)) {
142 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyUserLabel
);
144 if (label_utf8
) { // Anything we would do here requires a user label
145 size_t password_length
= 0;
146 const void *password_data
= xpc_dictionary_get_data(message
, kSecXPCKeyUserPassword
, &password_length
);
148 CFDataRef user_password
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
);
149 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
151 action(user_label
, user_password
);
153 CFReleaseNull(user_password
);
154 CFReleaseNull(user_label
);
158 static void with_label_and_password_and_dsid(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
, CFStringRef dsid
)) {
159 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyUserLabel
);
161 if (label_utf8
) { // Anything we would do here requires a user label
162 size_t password_length
= 0;
163 const void *password_data
= xpc_dictionary_get_data(message
, kSecXPCKeyUserPassword
, &password_length
);
164 const char *xdsid
= xpc_dictionary_get_string(message
, kSecXPCKeyDSID
);
166 CFDataRef user_password
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
);
167 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
168 CFStringRef dsid
= CFStringCreateWithCString(kCFAllocatorDefault
, xdsid
, kCFStringEncodingUTF8
);
170 action(user_label
, user_password
, dsid
);
173 CFReleaseNull(user_password
);
174 CFReleaseNull(user_label
);
178 static void with_label_and_number(xpc_object_t message
, void (^action
)(CFStringRef label
, uint64_t number
)) {
179 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyViewName
);
180 const int64_t number
= xpc_dictionary_get_int64(message
, kSecXPCKeyViewActionCode
);
181 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
183 action(user_label
, number
);
184 CFReleaseNull(user_label
);
187 static CFArrayRef
SecXPCDictionaryCopyPeerInfoArray(xpc_object_t dictionary
, const char *key
, CFErrorRef
*error
) {
188 return CreateArrayOfPeerInfoWithXPCObject(xpc_dictionary_get_value(dictionary
, key
), error
);
191 static CFDataRef
SecXPCDictionaryCopyCFDataRef(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
192 CFDataRef retval
= NULL
;
193 const uint8_t *bytes
= NULL
;
196 bytes
= xpc_dictionary_get_data(message
, key
, &len
);
197 require_action_quiet(bytes
, errOut
, SOSCreateError(kSOSErrorBadKey
, CFSTR("missing CFDataRef info"), NULL
, error
));
198 retval
= CFDataCreate(NULL
, bytes
, len
);
199 require_action_quiet(retval
, errOut
, SOSCreateError(kSOSErrorBadKey
, CFSTR("could not allocate CFDataRef info"), NULL
, error
));
204 static CFSetRef
CreateCFSetRefFromXPCObject(xpc_object_t xpcSetDER
, CFErrorRef
* error
) {
205 CFSetRef retval
= NULL
;
206 require_action_quiet(xpcSetDER
, errOut
, SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedNull
, sSecXPCErrorDomain
, NULL
, error
, NULL
, CFSTR("Unexpected Null Set to decode")));
208 require_action_quiet(xpc_get_type(xpcSetDER
) == XPC_TYPE_DATA
, errOut
, SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, error
, NULL
, CFSTR("xpcSetDER not data, got %@"), xpcSetDER
));
210 const uint8_t* der
= xpc_data_get_bytes_ptr(xpcSetDER
);
211 const uint8_t* der_end
= der
+ xpc_data_get_length(xpcSetDER
);
212 der
= der_decode_set(kCFAllocatorDefault
, kCFPropertyListMutableContainersAndLeaves
, &retval
, error
, der
, der_end
);
213 if (der
!= der_end
) {
214 SecError(errSecDecode
, error
, CFSTR("trailing garbage at end of SecAccessControl data"));
219 CFReleaseNull(retval
);
223 static SOSPeerInfoRef
SecXPCDictionaryCopyPeerInfo(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
225 const uint8_t *der
= xpc_dictionary_get_data(message
, key
, &length
);
227 return SecRequirementError(der
!= NULL
, error
, CFSTR("No data for key %s"), key
) ? SOSPeerInfoCreateFromDER(kCFAllocatorDefault
, error
, &der
, der
+ length
) : NULL
;
230 static CFSetRef
SecXPCSetCreateFromXPCDictionaryElement(xpc_object_t event
, const char *key
) {
231 CFErrorRef error
= NULL
;
232 xpc_object_t object
= xpc_dictionary_get_value(event
, key
);
233 CFSetRef retval
= NULL
;
234 if(object
) retval
= CreateCFSetRefFromXPCObject(object
, &error
);
235 CFReleaseNull(error
);
240 void xpc_dictionary_set_and_consume_CFArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
) {
242 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(cf_array
);
243 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
244 xpc_release(xpc_array
);
246 CFReleaseNull(cf_array
);
250 bool xpc_dictionary_set_and_consume_PeerInfoArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
, CFErrorRef
*error
) {
253 xpc_object_t xpc_array
= CreateXPCObjectWithArrayOfPeerInfo(cf_array
, error
);
255 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
256 xpc_release(xpc_array
);
261 CFReleaseNull(cf_array
);
266 SecDataCopyMmapFileDescriptor(int fd
, void **mem
, size_t *size
, CFErrorRef
*error
)
269 if (fstat(fd
, &sb
) < 0) {
273 *size
= (size_t)sb
.st_size
;
274 if ((off_t
)*size
!= sb
.st_size
) {
278 *mem
= mmap(NULL
, *size
, PROT_READ
, MAP_SHARED
, fd
, 0);
279 if (*mem
== MAP_FAILED
) {
283 return CFDataCreateWithBytesNoCopy(NULL
, *mem
, *size
, kCFAllocatorNull
);
287 SecDataWriteFileDescriptor(int fd
, CFDataRef data
)
289 CFIndex count
= CFDataGetLength(data
);
290 const uint8_t *ptr
= CFDataGetBytePtr(data
);
291 bool writeResult
= false;
294 ssize_t ret
= write(fd
, ptr
, count
);
307 // Returns error if entitlement isn't present.
309 EntitlementPresentAndTrue(uint64_t op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
311 if (!SecTaskGetBooleanValueForEntitlement(clientTask
, entitlement
)) {
312 SecError(errSecMissingEntitlement
, error
, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
)op
), clientTask
, entitlement
);
318 // Per <rdar://problem/13315020> Disable the entitlement check for "keychain-cloud-circle"
319 // we disable entitlement enforcement. However, we still log so we know who needs the entitlement
321 EntitlementPresentOrWhine(uint64_t op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
323 if (!SecTaskGetBooleanValueForEntitlement(clientTask
, entitlement
))
324 secnotice("serverxpc", "%@: %@ lacks entitlement %@", SOSCCGetOperationDescription((enum SecXPCOperation
)op
), clientTask
, entitlement
);
331 EntitlementAbsentOrFalse(uint64_t op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
333 if (SecTaskGetBooleanValueForEntitlement(clientTask
, entitlement
)) {
334 SecError(errSecNotAvailable
, error
, CFSTR("%@: %@ has entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
) op
), clientTask
, entitlement
);
340 static void securityd_xpc_dictionary_handler(const xpc_connection_t connection
, xpc_object_t event
) {
341 xpc_type_t type
= xpc_get_type(event
);
342 __block CFErrorRef error
= NULL
;
343 xpc_object_t xpcError
= NULL
;
344 xpc_object_t replyMessage
= NULL
;
345 CFDataRef clientAuditToken
= NULL
;
346 CFArrayRef domains
= NULL
;
347 SecurityClient client
= {
349 .accessGroups
= NULL
,
351 .uid
= xpc_connection_get_euid(connection
),
352 .allowSystemKeychain
= false,
353 .allowSyncBubbleKeychain
= false,
354 .isNetworkExtension
= false,
355 .canAccessNetworkExtensionAccessGroups
= false,
358 secdebug("serverxpc", "entering");
359 if (type
== XPC_TYPE_DICTIONARY
) {
360 // TODO: Find out what we're dispatching.
361 replyMessage
= xpc_dictionary_create_reply(event
);
363 uint64_t operation
= xpc_dictionary_get_uint64(event
, kSecXPCKeyOperation
);
365 audit_token_t auditToken
= {};
366 xpc_connection_get_audit_token(connection
, &auditToken
);
367 clientAuditToken
= CFDataCreate(kCFAllocatorDefault
, (const UInt8
*)&auditToken
, sizeof(auditToken
));
369 fill_security_client(&client
, xpc_connection_get_euid(connection
), auditToken
);
372 if (operation
== sec_add_shared_web_credential_id
|| operation
== sec_copy_shared_web_credential_id
) {
373 domains
= SecTaskCopySharedWebCredentialDomains(client
.task
);
376 secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64
")", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), operation
);
380 case sec_item_add_id
:
382 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
383 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
385 // Check for any entitlement-required attributes
386 bool entitlementsCorrect
= true;
387 if(CFDictionaryGetValue(query
, kSecAttrDeriveSyncIDFromItemAttributes
) ||
388 CFDictionaryGetValue(query
, kSecAttrPCSPlaintextServiceIdentifier
) ||
389 CFDictionaryGetValue(query
, kSecAttrPCSPlaintextPublicKey
) ||
390 CFDictionaryGetValue(query
, kSecAttrPCSPlaintextPublicIdentity
)) {
391 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_add_id
, client
.task
, kSecEntitlementPrivateCKKSPlaintextFields
, &error
);
393 if (entitlementsCorrect
&& CFDictionaryGetValue(query
, kSecAttrSysBound
)) {
394 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_add_id
, client
.task
, kSecEntitlementPrivateSysBound
, &error
);
397 CFTypeRef result
= NULL
;
398 if(entitlementsCorrect
) {
399 if (_SecItemAdd(query
, &client
, &result
, &error
) && result
) {
400 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
401 CFReleaseNull(result
);
404 CFReleaseNull(query
);
409 case sec_item_copy_matching_id
:
411 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
412 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
414 CFTypeRef result
= NULL
;
415 if (_SecItemCopyMatching(query
, &client
, &result
, &error
) && result
) {
416 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
417 CFReleaseNull(result
);
419 CFReleaseNull(query
);
424 case sec_item_update_id
:
426 if (EntitlementAbsentOrFalse(sec_item_update_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
427 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
429 CFDictionaryRef attributesToUpdate
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyAttributesToUpdate
, &error
);
430 if (attributesToUpdate
) {
431 // Check for any entitlement-required attributes
432 bool entitlementsCorrect
= true;
433 if(CFDictionaryGetValue(query
, kSecAttrDeriveSyncIDFromItemAttributes
) ||
434 CFDictionaryGetValue(attributesToUpdate
, kSecAttrPCSPlaintextServiceIdentifier
) ||
435 CFDictionaryGetValue(attributesToUpdate
, kSecAttrPCSPlaintextPublicKey
) ||
436 CFDictionaryGetValue(attributesToUpdate
, kSecAttrPCSPlaintextPublicIdentity
)) {
437 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_update_id
, client
.task
, kSecEntitlementPrivateCKKSPlaintextFields
, &error
);
439 if (entitlementsCorrect
&& CFDictionaryGetValue(query
, kSecAttrSysBound
)) {
440 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_update_id
, client
.task
, kSecEntitlementPrivateSysBound
, &error
);
443 if(entitlementsCorrect
) {
444 bool result
= _SecItemUpdate(query
, attributesToUpdate
, &client
, &error
);
445 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
447 CFReleaseNull(attributesToUpdate
);
449 CFReleaseNull(query
);
454 case sec_item_delete_id
:
456 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
457 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
459 bool result
= _SecItemDelete(query
, &client
, &error
);
460 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
461 CFReleaseNull(query
);
466 case sec_item_update_token_items_id
:
468 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
469 CFStringRef tokenID
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
470 CFArrayRef attributes
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyQuery
, &error
);
472 bool result
= _SecItemUpdateTokenItems(tokenID
, attributes
, &client
, &error
);
473 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
475 CFReleaseNull(tokenID
);
476 CFReleaseNull(attributes
);
480 case sec_delete_all_id
:
481 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, _SecItemDeleteAll(&error
));
483 case sec_keychain_backup_id
:
485 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
486 CFDataRef keybag
= NULL
, passcode
= NULL
;
487 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybag
, &error
)) {
488 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
489 CFDataRef backup
= _SecServerKeychainCreateBackup(&client
, keybag
, passcode
, &error
);
491 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
493 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, backup
, &error
);
495 bool writeResult
= SecDataWriteFileDescriptor(fd
, backup
);
499 SecError(errSecIO
, &error
, CFSTR("Failed to write backup file: %d"), errno
);
500 SecXPCDictionarySetBool(replyMessage
, kSecXPCKeyResult
, writeResult
, NULL
);
504 CFReleaseSafe(passcode
);
506 CFReleaseSafe(keybag
);
511 case sec_keychain_restore_id
:
513 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
514 CFDataRef backup
= NULL
;
518 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
520 backup
= SecDataCopyMmapFileDescriptor(fd
, &mem
, &size
, &error
);
522 backup
= SecXPCDictionaryCopyData(event
, kSecXPCKeyBackup
, &error
);
525 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
527 CFDataRef passcode
= NULL
;
528 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
529 bool result
= _SecServerKeychainRestore(backup
, &client
, keybag
, passcode
, &error
);
530 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
531 CFReleaseSafe(passcode
);
534 CFReleaseNull(keybag
);
536 CFReleaseNull(backup
);
545 case sec_keychain_backup_keybag_uuid_id
:
547 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
548 CFDataRef backup
= NULL
;
549 CFStringRef uuid
= NULL
;
553 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
555 backup
= SecDataCopyMmapFileDescriptor(fd
, &mem
, &size
, &error
);
557 uuid
= _SecServerBackupCopyUUID(backup
, &error
);
560 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, uuid
, &error
);
562 CFReleaseNull(backup
);
572 case sec_keychain_sync_update_message_id
:
574 CFDictionaryRef updates
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
576 CFArrayRef result
= _SecServerKeychainSyncUpdateMessage(updates
, &error
);
577 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
578 CFReleaseNull(result
);
580 CFReleaseNull(updates
);
583 case sec_keychain_backup_syncable_id
:
585 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
586 CFDictionaryRef oldbackup
= NULL
;
587 if (SecXPCDictionaryCopyDictionaryOptional(event
, kSecXPCKeyBackup
, &oldbackup
, &error
)) {
588 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
590 CFDataRef passcode
= NULL
;
591 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
592 CFDictionaryRef newbackup
= _SecServerBackupSyncable(oldbackup
, keybag
, passcode
, &error
);
594 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, newbackup
, &error
);
595 CFRelease(newbackup
);
597 CFReleaseSafe(passcode
);
599 CFReleaseNull(keybag
);
601 CFReleaseSafe(oldbackup
);
606 case sec_keychain_restore_syncable_id
:
608 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
609 CFDictionaryRef backup
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyBackup
, &error
);
611 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
613 CFDataRef passcode
= NULL
;
614 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
615 bool result
= _SecServerRestoreSyncable(backup
, keybag
, passcode
, &error
);
616 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
617 CFReleaseSafe(passcode
);
619 CFReleaseNull(keybag
);
621 CFReleaseNull(backup
);
626 case sec_item_backup_copy_names_id
:
628 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
629 CFArrayRef names
= SecServerItemBackupCopyNames(&error
);
630 SecXPCDictionarySetPListOptional(replyMessage
, kSecXPCKeyResult
, names
, &error
);
631 CFReleaseSafe(names
);
635 case sec_item_backup_handoff_fd_id
:
637 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
638 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
641 fd
= SecServerItemBackupHandoffFD(backupName
, &error
);
642 CFRelease(backupName
);
644 SecXPCDictionarySetFileDescriptor(replyMessage
, kSecXPCKeyResult
, fd
, &error
);
650 case sec_item_backup_set_confirmed_manifest_id
:
652 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
653 CFDataRef keybagDigest
= NULL
;
654 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybagDigest
, &error
)) {
655 CFDataRef manifest
= NULL
;
656 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &manifest
, &error
)) {
657 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
659 bool result
= SecServerItemBackupSetConfirmedManifest(backupName
, keybagDigest
, manifest
, &error
);
660 CFRelease(backupName
);
661 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
663 CFReleaseSafe(manifest
);
666 CFReleaseNull(keybagDigest
);
670 case sec_item_backup_restore_id
:
672 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
674 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
676 CFStringRef peerID
= NULL
;
677 if (SecXPCDictionaryCopyStringOptional(event
, kSecXPCKeyDigest
, &peerID
, &error
)) {
678 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
680 CFDataRef secret
= SecXPCDictionaryCopyData(event
, kSecXPCKeyUserPassword
, &error
);
682 CFDataRef backup
= SecXPCDictionaryCopyData(event
, kSecXPCData
, &error
);
684 result
= SecServerItemBackupRestore(backupName
, peerID
, keybag
, secret
, backup
, &error
);
691 CFReleaseSafe(peerID
);
693 CFRelease(backupName
);
695 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
699 case sec_add_shared_web_credential_id
:
701 #if TARGET_OS_IOS && !TARGET_OS_BRIDGE
702 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
704 CFTypeRef result
= NULL
;
706 CFStringRef appID
= (client
.task
) ? SecTaskCopyApplicationIdentifier(client
.task
) : NULL
;
707 if (_SecAddSharedWebCredential(query
, &client
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
708 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
709 CFReleaseNull(result
);
711 CFReleaseSafe(appID
);
712 CFReleaseNull(query
);
715 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, kCFBooleanFalse
, &error
);
719 case sec_copy_shared_web_credential_id
:
721 #if TARGET_OS_IOS && !TARGET_OS_BRIDGE
722 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
724 CFTypeRef result
= NULL
;
725 CFStringRef appID
= (client
.task
) ? SecTaskCopyApplicationIdentifier(client
.task
) : NULL
;
726 if (_SecCopySharedWebCredential(query
, &client
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
727 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
728 CFReleaseNull(result
);
730 CFReleaseSafe(appID
);
731 CFReleaseNull(query
);
734 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, kCFBooleanFalse
, &error
);
738 case sec_get_log_settings_id
:
740 CFPropertyListRef currentList
= SecCopyLogSettings_Server(&error
);
742 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, currentList
, &error
);
744 CFReleaseSafe(currentList
);
747 case sec_set_xpc_log_settings_id
:
749 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
751 SecSetXPCLogSettings_Server(newSettings
, &error
);
753 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
754 CFReleaseNull(newSettings
);
757 case sec_set_circle_log_settings_id
:
759 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
761 SecSetCircleLogSettings_Server(newSettings
, &error
);
763 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
764 CFReleaseNull(newSettings
);
767 case sec_otr_session_create_remote_id
:
769 CFDataRef publicPeerId
= NULL
;
770 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCPublicPeerId
, &publicPeerId
, &error
)) {
771 CFDataRef otrSession
= _SecOTRSessionCreateRemote(publicPeerId
, &error
);
773 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, otrSession
, &error
);
774 CFReleaseNull(otrSession
);
776 CFReleaseSafe(publicPeerId
);
780 case sec_otr_session_process_packet_remote_id
:
782 CFDataRef sessionData
= NULL
, inputPacket
= NULL
, outputSessionData
= NULL
, outputPacket
= NULL
;
783 bool readyForMessages
= false;
784 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCOTRSession
, &sessionData
, &error
)) {
785 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &inputPacket
, &error
)) {
786 bool result
= _SecOTRSessionProcessPacketRemote(sessionData
, inputPacket
, &outputSessionData
, &outputPacket
, &readyForMessages
, &error
);
788 SecXPCDictionarySetData(replyMessage
, kSecXPCOTRSession
, outputSessionData
, &error
);
789 SecXPCDictionarySetData(replyMessage
, kSecXPCData
, outputPacket
, &error
);
790 xpc_dictionary_set_bool(replyMessage
, kSecXPCOTRReady
, readyForMessages
);
791 CFReleaseNull(outputSessionData
);
792 CFReleaseNull(outputPacket
);
794 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
796 CFReleaseSafe(inputPacket
);
798 CFReleaseSafe(sessionData
);
802 case kSecXPCOpTryUserCredentials
:
803 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
804 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
805 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
806 SOSCCTryUserCredentials_Server(label
, password
, &error
));
810 case kSecXPCOpSetUserCredentials
:
811 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
812 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
813 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
814 SOSCCSetUserCredentials_Server(label
, password
, &error
));
818 case kSecXPCOpSetUserCredentialsAndDSID
:
819 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
820 with_label_and_password_and_dsid(event
, ^(CFStringRef label
, CFDataRef password
, CFStringRef dsid
) {
821 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
822 SOSCCSetUserCredentialsAndDSID_Server(label
, password
, dsid
, &error
));
827 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
828 with_label_and_number(event
, ^(CFStringRef view
, uint64_t actionCode
) {
829 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
830 SOSCCView_Server(view
, (SOSViewActionCode
)actionCode
, &error
));
834 case kSecXPCOpViewSet
:
835 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
836 CFSetRef enabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyEnabledViewsKey
);
837 CFSetRef disabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyDisabledViewsKey
);
838 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCViewSet_Server(enabledViews
, disabledViews
));
839 CFReleaseNull(enabledViews
);
840 CFReleaseNull(disabledViews
);
843 case kSecXPCOpSecurityProperty
:
844 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
845 with_label_and_number(event
, ^(CFStringRef property
, uint64_t actionCode
) {
846 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
847 SOSCCSecurityProperty_Server(property
, (SOSSecurityPropertyActionCode
)actionCode
, &error
));
851 case kSecXPCOpCanAuthenticate
:
852 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
853 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
854 SOSCCCanAuthenticate_Server(&error
));
857 case kSecXPCOpPurgeUserCredentials
:
858 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
859 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
860 SOSCCPurgeUserCredentials_Server(&error
));
863 case kSecXPCOpDeviceInCircle
:
864 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
865 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
866 SOSCCThisDeviceIsInCircle_Server(&error
));
869 case kSecXPCOpRequestToJoin
:
870 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
871 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
872 SOSCCRequestToJoinCircle_Server(&error
));
875 case kSecXPCOpAccountHasPublicKey
:
876 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
877 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
878 SOSCCAccountHasPublicKey_Server(&error
));
881 case kSecXPCOpAccountIsNew
:
882 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
883 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
884 SOSCCAccountIsNew_Server(&error
));
887 case kSecXPCOpRequestToJoinAfterRestore
:
888 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
889 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
890 SOSCCRequestToJoinCircleAfterRestore_Server(&error
));
893 case kSecXPCOpRequestEnsureFreshParameters
:
894 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
895 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
896 SOSCCRequestEnsureFreshParameters_Server(&error
));
899 case kSecXPCOpGetAllTheRings
:
900 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
901 CFStringRef ringDescriptions
= SOSCCGetAllTheRings_Server(&error
);
902 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(ringDescriptions
);
903 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
904 xpc_release(xpc_dictionary
);
907 case kSecXPCOpApplyToARing
:
908 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
909 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
910 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCApplyToARing_Server(ringName
, &error
));
911 CFReleaseNull(ringName
);
914 case kSecXPCOpWithdrawlFromARing
:
915 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
916 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
917 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCWithdrawlFromARing_Server(ringName
, &error
));
918 CFReleaseNull(ringName
);
921 case kSecXPCOpRingStatus
:
922 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
923 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
924 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRingStatus_Server(ringName
, &error
));
925 CFReleaseNull(ringName
);
928 case kSecXPCOpEnableRing
:
929 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
930 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
931 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCEnableRing_Server(ringName
, &error
));
932 CFReleaseNull(ringName
);
935 case kSecXPCOpRequestDeviceID
:
936 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
937 CFStringRef deviceID
= SOSCCCopyDeviceID_Server(&error
);
939 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, deviceID
, &error
);
941 CFReleaseNull(deviceID
);
944 case kSecXPCOpSetDeviceID
:
945 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
946 CFStringRef IDS
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
947 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCSetDeviceID_Server(IDS
, &error
));
951 case kSecXPCOpHandleIDSMessage
:
952 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
953 CFDictionaryRef IDS
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyIDSMessage
, &error
);
954 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
, SOSCCHandleIDSMessage_Server(IDS
, &error
));
958 case kSecXPCOpClearKVSPeerMessage
:
959 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
960 CFStringRef peerID
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
961 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCClearPeerMessageKeyInKVS_Server(peerID
, &error
));
962 CFReleaseNull(peerID
);
965 case kSecXPCOpSendIDSMessage
:
966 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
967 CFStringRef message
= SecXPCDictionaryCopyString(event
, kSecXPCKeySendIDSMessage
, &error
);
968 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSServiceRegistrationTest_Server(message
, &error
));
969 CFReleaseNull(message
);
972 case kSecXPCOpSyncWithKVSPeer
:
973 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
974 CFStringRef peerID
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
975 CFDataRef message
= SecXPCDictionaryCopyData(event
, kSecXPCKeyIDSMessage
, &error
);
976 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRequestSyncWithPeerOverKVS_Server(peerID
, message
, &error
));
977 CFReleaseNull(peerID
);
980 case kSecXPCOpSyncWithKVSPeerIDOnly
:
981 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
982 CFStringRef peerID
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
983 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRequestSyncWithPeerOverKVSUsingIDOnly_Server(peerID
, &error
));
984 CFReleaseNull(peerID
);
987 case kSecXPCOpPingTest
:
988 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
989 CFStringRef message
= SecXPCDictionaryCopyString(event
, kSecXPCKeySendIDSMessage
, &error
);
990 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSPingTest_Server(message
, &error
));
991 CFReleaseNull(message
);
994 case kSecXPCOpIDSDeviceID
:
995 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
996 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSDeviceIDIsAvailableTest_Server(&error
));
999 case kSecXPCOpAccountSetToNew
:
1000 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1001 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCAccountSetToNew_Server(&error
));
1004 case kSecXPCOpResetToOffering
:
1005 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1006 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1007 SOSCCResetToOffering_Server(&error
));
1010 case kSecXPCOpResetToEmpty
:
1011 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1012 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1013 SOSCCResetToEmpty_Server(&error
));
1016 case kSecXPCOpRemoveThisDeviceFromCircle
:
1017 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1018 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1019 SOSCCRemoveThisDeviceFromCircle_Server(&error
));
1022 case kSecXPCOpRemovePeersFromCircle
:
1023 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1024 CFArrayRef applicants
= SecXPCDictionaryCopyPeerInfoArray(event
, kSecXPCKeyPeerInfoArray
, &error
);
1025 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1026 SOSCCRemovePeersFromCircle_Server(applicants
, &error
));
1027 CFReleaseNull(applicants
);
1030 case kSecXPCOpLoggedOutOfAccount
:
1031 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1032 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1033 SOSCCLoggedOutOfAccount_Server(&error
));
1036 case kSecXPCOpBailFromCircle
:
1037 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1038 uint64_t limit_in_seconds
= xpc_dictionary_get_uint64(event
, kSecXPCLimitInMinutes
);
1039 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1040 SOSCCBailFromCircle_Server(limit_in_seconds
, &error
));
1043 case kSecXPCOpAcceptApplicants
:
1044 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1045 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfoArray
);
1046 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1047 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1048 (applicants
&& SOSCCAcceptApplicants_Server(applicants
, &error
)));
1049 CFReleaseSafe(applicants
);
1052 case kSecXPCOpRejectApplicants
:
1053 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1054 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfoArray
);
1055 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1056 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1057 (applicants
&& SOSCCRejectApplicants_Server(applicants
, &error
)));
1058 CFReleaseSafe(applicants
);
1061 case kSecXPCOpSetNewPublicBackupKey
:
1063 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1064 CFDataRef publicBackupKey
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNewPublicBackupKey
, &error
);
1065 SOSPeerInfoRef peerInfo
= SOSCCSetNewPublicBackupKey_Server(publicBackupKey
, &error
);
1066 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1067 CFReleaseNull(peerInfo
);
1069 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1070 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1071 xpc_release(xpc_object
);
1073 CFReleaseNull(peerInfoData
);
1074 CFReleaseSafe(publicBackupKey
);
1079 case kSecXPCOpRegisterRecoveryPublicKey
:
1081 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1082 CFDataRef recovery_key
= SecXPCDictionaryCopyData(event
, kSecXPCKeyRecoveryPublicKey
, &error
);
1083 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRegisterRecoveryPublicKey_Server(recovery_key
, &error
));
1084 CFReleaseNull(recovery_key
);
1088 case kSecXPCOpGetRecoveryPublicKey
:
1090 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1091 xpc_object_t xpc_recovery_object
= NULL
;
1092 CFDataRef recovery
= SOSCCCopyRecoveryPublicKey(&error
);
1094 xpc_recovery_object
= _CFXPCCreateXPCObjectFromCFObject(recovery
);
1096 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_recovery_object
);
1097 CFReleaseNull(recovery
);
1101 case kSecXPCOpSetBagForAllSlices
:
1103 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1104 CFDataRef backupSlice
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
1105 bool includeV0
= xpc_dictionary_get_bool(event
, kSecXPCKeyIncludeV0
);
1106 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, backupSlice
&& SOSCCRegisterSingleRecoverySecret_Server(backupSlice
, includeV0
, &error
));
1107 CFReleaseSafe(backupSlice
);
1111 case kSecXPCOpCopyApplicantPeerInfo
:
1112 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1113 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1114 SOSCCCopyApplicantPeerInfo_Server(&error
),
1118 case kSecXPCOpCopyValidPeerPeerInfo
:
1119 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1120 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1121 SOSCCCopyValidPeerPeerInfo_Server(&error
),
1125 case kSecXPCOpValidateUserPublic
:
1126 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1127 bool trusted
= SOSCCValidateUserPublic_Server(&error
);
1128 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, trusted
);
1131 case kSecXPCOpCopyNotValidPeerPeerInfo
:
1132 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1133 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1134 SOSCCCopyNotValidPeerPeerInfo_Server(&error
),
1138 case kSecXPCOpCopyGenerationPeerInfo
:
1139 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1140 xpc_dictionary_set_and_consume_CFArray(replyMessage
, kSecXPCKeyResult
,
1141 SOSCCCopyGenerationPeerInfo_Server(&error
));
1144 case kSecXPCOpCopyRetirementPeerInfo
:
1145 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1146 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1147 SOSCCCopyRetirementPeerInfo_Server(&error
),
1151 case kSecXPCOpCopyViewUnawarePeerInfo
:
1152 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1153 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1154 SOSCCCopyViewUnawarePeerInfo_Server(&error
),
1158 case kSecXPCOpCopyAccountData
:
1160 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1161 xpc_object_t xpc_account_object
= NULL
;
1162 CFDataRef accountData
= SOSCCCopyAccountState_Server(&error
);
1164 xpc_account_object
= _CFXPCCreateXPCObjectFromCFObject(accountData
);
1166 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_account_object
);
1167 CFReleaseNull(accountData
);
1171 case kSecXPCOpDeleteAccountData
:
1173 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1174 bool status
= SOSCCDeleteAccountState_Server(&error
);
1175 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, status
);
1179 case kSecXPCOpCopyEngineData
:
1181 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1183 xpc_object_t xpc_engine_object
= NULL
;
1184 CFDataRef engineData
= SOSCCCopyEngineData_Server(&error
);
1186 xpc_engine_object
= _CFXPCCreateXPCObjectFromCFObject(engineData
);
1188 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_engine_object
);
1189 CFReleaseNull(engineData
);
1194 case kSecXPCOpDeleteEngineData
:
1196 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1197 bool status
= SOSCCDeleteEngineState_Server(&error
);
1198 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, status
);
1202 case kSecXPCOpCopyEngineState
:
1204 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1205 CFArrayRef array
= SOSCCCopyEngineState_Server(&error
);
1206 CFDataRef derData
= NULL
;
1208 require_quiet(array
, done
);
1209 derData
= CFPropertyListCreateDERData(kCFAllocatorDefault
, array
, &error
);
1211 require_quiet(derData
, done
);
1212 xpc_dictionary_set_data(replyMessage
, kSecXPCKeyResult
, CFDataGetBytePtr(derData
), CFDataGetLength(derData
));
1214 CFReleaseNull(derData
);
1215 CFReleaseNull(array
);
1219 case kSecXPCOpCopyPeerPeerInfo
:
1220 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1221 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1222 SOSCCCopyPeerPeerInfo_Server(&error
),
1226 case kSecXPCOpCopyConcurringPeerPeerInfo
:
1227 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1228 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1229 SOSCCCopyConcurringPeerPeerInfo_Server(&error
),
1233 case kSecXPCOpCopyMyPeerInfo
:
1234 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1235 SOSPeerInfoRef peerInfo
= SOSCCCopyMyPeerInfo_Server(&error
);
1236 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1237 CFReleaseNull(peerInfo
);
1239 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1240 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1241 xpc_release(xpc_object
);
1243 CFReleaseNull(peerInfoData
);
1246 case kSecXPCOpGetLastDepartureReason
:
1247 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1248 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1249 SOSCCGetLastDepartureReason_Server(&error
));
1252 case kSecXPCOpSetLastDepartureReason
:
1253 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1254 int32_t reason
= (int32_t) xpc_dictionary_get_int64(event
, kSecXPCKeyReason
);
1255 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1256 SOSCCSetLastDepartureReason_Server(reason
, &error
));
1259 case kSecXPCOpProcessSyncWithPeers
:
1260 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1261 CFSetRef peers
= SecXPCDictionaryCopySet(event
, kSecXPCKeySet
, &error
);
1262 CFSetRef backupPeers
= SecXPCDictionaryCopySet(event
, kSecXPCKeySet2
, &error
);
1263 if (peers
&& backupPeers
) {
1264 CFSetRef result
= SOSCCProcessSyncWithPeers_Server(peers
, backupPeers
, &error
);
1266 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
1268 CFReleaseNull(result
);
1270 CFReleaseNull(peers
);
1271 CFReleaseNull(backupPeers
);
1274 case kSecXPCOpProcessSyncWithAllPeers
:
1275 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1276 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1277 SOSCCProcessSyncWithAllPeers_Server(&error
));
1280 case soscc_EnsurePeerRegistration_id
:
1281 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1282 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1283 SOSCCProcessEnsurePeerRegistration_Server(&error
));
1286 case kSecXPCOpCopyIncompatibilityInfo
:
1287 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1288 CFStringRef iis
= SOSCCCopyIncompatibilityInfo_Server(&error
);
1289 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, iis
, &error
);
1293 case kSecXPCOpRollKeys
:
1295 bool force
= xpc_dictionary_get_bool(event
, "force");
1296 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1297 _SecServerRollKeys(force
, &client
, &error
));
1300 case kSecXPCOpWaitForInitialSync
:
1301 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1302 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1303 SOSCCWaitForInitialSync_Server(&error
));
1307 case kSecXPCOpCopyYetToSyncViews
:
1308 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1309 CFArrayRef array
= SOSCCCopyYetToSyncViewsList_Server(&error
);
1311 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1312 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1313 xpc_release(xpc_array
);
1315 CFReleaseNull(array
);
1318 case kSecXPCOpSetEscrowRecord
:
1319 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1320 CFStringRef escrow_label
= SecXPCDictionaryCopyString(event
, kSecXPCKeyEscrowLabel
, &error
);
1321 uint64_t tries
= xpc_dictionary_get_int64(event
, kSecXPCKeyTriesLabel
);
1323 bool result
= SOSCCSetEscrowRecord_Server(escrow_label
, tries
, &error
);
1325 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1327 CFReleaseNull(escrow_label
);
1330 case kSecXPCOpGetEscrowRecord
:
1331 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1332 CFDictionaryRef record
= SOSCCCopyEscrowRecord_Server(&error
);
1334 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(record
);
1335 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1336 xpc_release(xpc_dictionary
);
1338 CFReleaseNull(record
);
1341 case kSecXPCOpCopyBackupInformation
:
1342 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1343 CFDictionaryRef record
= SOSCCCopyBackupInformation_Server(&error
);
1345 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(record
);
1346 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1347 xpc_release(xpc_dictionary
);
1349 CFReleaseNull(record
);
1353 case kSecXPCOpCheckPeerAvailability
:
1354 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1355 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCCheckPeerAvailability_Server(&error
));
1360 case kSecXPCOpIsThisDeviceLastBackup
:
1361 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1362 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCkSecXPCOpIsThisDeviceLastBackup_Server(&error
));
1365 case kSecXPCOpPeersHaveViewsEnabled
:
1367 CFArrayRef viewSet
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyArray
, &error
);
1369 CFBooleanRef result
= SOSCCPeersHaveViewsEnabled_Server(viewSet
, &error
);
1371 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
!= kCFBooleanFalse
);
1374 CFReleaseNull(viewSet
);
1378 case kSecXPCOpWhoAmI
:
1381 xpc_dictionary_set_data(replyMessage
, "musr", CFDataGetBytePtr(client
.musr
), CFDataGetLength(client
.musr
));
1382 xpc_dictionary_set_bool(replyMessage
, "system-keychain", client
.allowSystemKeychain
);
1383 xpc_dictionary_set_bool(replyMessage
, "syncbubble-keychain", client
.allowSyncBubbleKeychain
);
1384 xpc_dictionary_set_bool(replyMessage
, "network-extension", client
.isNetworkExtension
);
1385 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1388 case kSecXPCOpTransmogrifyToSyncBubble
:
1390 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainSyncBubble
, &error
)) {
1392 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1393 CFArrayRef services
= SecXPCDictionaryCopyArray(event
, "services", &error
);
1395 if (uid
&& services
) {
1396 res
= _SecServerTransmogrifyToSyncBubble(services
, uid
, &client
, &error
);
1398 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1399 CFReleaseNull(services
);
1401 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1406 case kSecXPCOpTransmogrifyToSystemKeychain
:
1408 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
)) {
1410 bool res
= _SecServerTransmogrifyToSystemKeychain(&client
, &error
);
1411 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1413 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1419 case kSecXPCOpDeleteUserView
:
1421 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
)) {
1424 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1426 res
= _SecServerDeleteMUSERViews(&client
, uid
, &error
);
1429 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1434 case kSecXPCOpWrapToBackupSliceKeyBagForView
:
1436 CFStringRef viewname
= SecXPCDictionaryCopyString(event
, kSecXPCKeyViewName
, &error
);
1438 CFDataRef plaintext
= SecXPCDictionaryCopyData(event
, kSecXPCData
, &error
);
1440 CFDataRef ciphertext
= NULL
;
1441 CFDataRef bskbEncoded
= NULL
;
1443 bool result
= SOSWrapToBackupSliceKeyBagForView_Server(viewname
, plaintext
, &ciphertext
, &bskbEncoded
, &error
);
1444 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1446 if(!error
&& result
) {
1448 xpc_dictionary_set_data(replyMessage
, kSecXPCData
, CFDataGetBytePtr(ciphertext
), CFDataGetLength(ciphertext
));
1451 xpc_dictionary_set_data(replyMessage
, kSecXPCKeyKeybag
, CFDataGetBytePtr(bskbEncoded
), CFDataGetLength(bskbEncoded
));
1454 CFReleaseSafe(ciphertext
);
1455 CFReleaseSafe(bskbEncoded
);
1457 CFReleaseSafe(plaintext
);
1459 CFReleaseNull(viewname
);
1462 case kSecXPCOpCopyApplication
:
1463 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1464 SOSPeerInfoRef peerInfo
= SOSCCCopyApplication_Server(&error
);
1465 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1466 CFReleaseNull(peerInfo
);
1468 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1469 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1470 xpc_release(xpc_object
);
1472 CFReleaseNull(peerInfoData
);
1475 case kSecXPCOpCopyCircleJoiningBlob
:
1476 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1477 CFDataRef appBlob
= SecXPCDictionaryCopyCFDataRef(event
, kSecXPCData
, &error
);
1478 SOSPeerInfoRef applicant
= SOSPeerInfoCreateFromData(kCFAllocatorDefault
, &error
, appBlob
);
1479 CFDataRef pbblob
= SOSCCCopyCircleJoiningBlob_Server(applicant
, &error
);
1481 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(pbblob
);
1482 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1483 xpc_release(xpc_object
);
1485 CFReleaseNull(pbblob
);
1486 CFReleaseNull(applicant
);
1487 CFReleaseNull(appBlob
);
1490 case kSecXPCOpCopyInitialSyncBlob
:
1491 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1492 CFDataRef initialblob
= SOSCCCopyInitialSyncData_Server(&error
);
1494 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(initialblob
);
1495 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1496 xpc_release(xpc_object
);
1498 CFReleaseNull(initialblob
);
1501 case kSecXPCOpJoinWithCircleJoiningBlob
:
1502 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1503 CFDataRef joiningBlob
= SecXPCDictionaryCopyCFDataRef(event
, kSecXPCData
, &error
);
1504 uint64_t version
= xpc_dictionary_get_uint64(event
, kSecXPCVersion
);
1505 bool retval
= SOSCCJoinWithCircleJoiningBlob_Server(joiningBlob
, (PiggyBackProtocolVersion
) version
, &error
);
1506 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1507 CFReleaseNull(joiningBlob
);
1511 case kSecXPCOpKVSKeyCleanup
:
1512 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1513 bool retval
= SOSCCCleanupKVSKeys_Server(&error
);
1514 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1517 case kSecXPCOpPopulateKVS
:
1518 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1519 bool retval
= SOSCCTestPopulateKVSWithBadKeys_Server(&error
);
1520 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1523 case kSecXPCOpMessageFromPeerIsPending
:
1525 SOSPeerInfoRef peer
= SecXPCDictionaryCopyPeerInfo(event
, kSecXPCKeyPeerInfo
, &error
);
1527 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1528 SOSCCMessageFromPeerIsPending_Server(peer
, &error
));
1530 CFReleaseNull(peer
);
1533 case kSecXPCOpSendToPeerIsPending
:
1535 SOSPeerInfoRef peer
= SecXPCDictionaryCopyPeerInfo(event
, kSecXPCKeyPeerInfo
, &error
);
1537 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1538 SOSCCSendToPeerIsPending(peer
, &error
));
1540 CFReleaseNull(peer
);
1543 case sec_delete_items_with_access_groups_id
:
1545 bool retval
= false;
1546 #if TARGET_OS_IPHONE
1547 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateUninstallDeletion
, &error
)) {
1548 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyAccessGroups
, &error
);
1551 retval
= _SecItemServerDeleteAllWithAccessGroups(accessGroups
, &client
, &error
);
1553 CFReleaseNull(accessGroups
);
1556 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1559 case sec_item_copy_parent_certificates_id
:
1561 CFArrayRef results
= NULL
;
1562 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateCertificateAllAccess
, &error
)) {
1563 CFDataRef issuer
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNormalizedIssuer
, &error
);
1564 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyAccessGroups
, &error
);
1565 if (issuer
&& accessGroups
) {
1566 results
= _SecItemCopyParentCertificates(issuer
, accessGroups
, &error
);
1568 CFReleaseNull(issuer
);
1569 CFReleaseNull(accessGroups
);
1571 SecXPCDictionarySetPListOptional(replyMessage
, kSecXPCKeyResult
, results
, &error
);
1572 CFReleaseNull(results
);
1575 case sec_item_certificate_exists_id
:
1577 bool result
= false;
1578 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateCertificateAllAccess
, &error
)) {
1579 CFDataRef issuer
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNormalizedIssuer
, &error
);
1580 CFDataRef serialNum
= SecXPCDictionaryCopyData(event
, kSecXPCKeySerialNumber
, &error
);
1581 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyAccessGroups
, &error
);
1582 if (issuer
&& serialNum
&& accessGroups
) {
1583 result
= _SecItemCertificateExists(issuer
, serialNum
, accessGroups
, &error
);
1585 CFReleaseNull(issuer
);
1586 CFReleaseNull(serialNum
);
1587 CFReleaseNull(accessGroups
);
1589 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1592 case kSecXPCOpCKKSEndpoint
: {
1593 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateCKKS
, &error
)) {
1594 xpc_endpoint_t endpoint
= SecServerCreateCKKSEndpoint();
1596 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyEndpoint
, endpoint
);
1597 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1598 xpc_release(endpoint
);
1600 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1605 case kSecXPCOpSOSEndpoint
: {
1606 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1607 xpc_endpoint_t endpoint
= SOSCCCreateSOSEndpoint_server(&error
);
1609 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyEndpoint
, endpoint
);
1610 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1611 xpc_release(endpoint
);
1613 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1618 case kSecXPCOpSecuritydXPCServerEndpoint
: {
1619 xpc_endpoint_t endpoint
= SecCreateSecuritydXPCServerEndpoint(&error
);
1621 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyEndpoint
, endpoint
);
1622 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1623 xpc_release(endpoint
);
1625 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1629 case kSecXPCOpBackupKeybagAdd
: {
1630 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementBackupTableOperations
, &error
)) {
1631 CFDataRef keybag
= NULL
, passcode
= NULL
;
1632 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
1633 CFDataRef identifier
= NULL
;
1634 CFDataRef pathinfo
= NULL
; // really a CFURLRef
1635 bool added
= _SecServerBackupKeybagAdd(&client
, passcode
, &identifier
, &pathinfo
, &error
);
1637 added
&= SecXPCDictionarySetDataOptional(replyMessage
, kSecXPCKeyBackupKeybagIdentifier
, identifier
, &error
);
1638 added
&= SecXPCDictionarySetDataOptional(replyMessage
, kSecXPCKeyBackupKeybagPath
, pathinfo
, &error
);
1639 SecXPCDictionarySetBool(replyMessage
, kSecXPCKeyResult
, added
, NULL
);
1641 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1644 CFReleaseSafe(passcode
);
1645 CFReleaseSafe(keybag
);
1649 case kSecXPCOpBackupKeybagDelete
: {
1651 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementBackupTableOperations
, &error
)) {
1652 bool deleted
= false;
1653 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
1655 CFTypeRef matchLimit
= CFDictionaryGetValue(query
, kSecMatchLimit
);
1656 bool deleteAll
= matchLimit
&& CFEqualSafe(matchLimit
, kSecMatchLimitAll
);
1658 if (deleteAll
&& !EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementBackupTableOperationsDeleteAll
, &error
)) {
1659 // require special entitlement to delete all backup keybags
1661 CFMutableDictionaryRef attributes
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, query
);
1662 CFStringRef requestedAgrp
= CFDictionaryGetValue(attributes
, kSecAttrAccessGroup
);
1663 CFStringRef resolvedAgrp
= NULL
;
1665 CFDictionarySetValue(attributes
, kSecAttrMultiUser
, client
.musr
);
1667 if (extractAccessGroup(&client
, requestedAgrp
, &resolvedAgrp
, &error
)) {
1669 CFDictionarySetValue(attributes
, kSecAttrAccessGroup
, resolvedAgrp
);
1671 deleted
= _SecServerBackupKeybagDelete(attributes
, deleteAll
, &error
);
1673 CFReleaseNull(resolvedAgrp
);
1674 CFReleaseNull(attributes
);
1677 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, deleted
);
1678 CFReleaseNull(query
);
1688 if(SecErrorGetOSStatus(error
) == errSecItemNotFound
|| isSOSErrorCoded(error
, kSOSErrorPublicKeyAbsent
))
1689 secdebug("ipc", "%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1690 else if (SecErrorGetOSStatus(error
) == errSecAuthNeeded
)
1691 secwarning("Authentication is needed %@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1693 secerror("%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1695 xpcError
= SecCreateXPCObjectWithCFError(error
);
1697 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyError
, xpcError
);
1699 } else if (replyMessage
) {
1700 secdebug("ipc", "%@ %@ responding %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyMessage
);
1703 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, &error
, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event
);
1704 secerror("%@: returning error: %@", client
.task
, error
);
1705 xpcError
= SecCreateXPCObjectWithCFError(error
);
1706 replyMessage
= xpc_create_reply_with_format(event
, "{%string: %value}", kSecXPCKeyError
, xpcError
);
1710 xpc_connection_send_message(connection
, replyMessage
);
1711 xpc_release(replyMessage
);
1714 xpc_release(xpcError
);
1715 #if TARGET_OS_IPHONE
1716 pthread_setspecific(taskThreadKey
, NULL
);
1718 CFReleaseSafe(error
);
1719 CFReleaseSafe(client
.accessGroups
);
1720 CFReleaseSafe(client
.musr
);
1721 CFReleaseSafe(client
.task
);
1722 CFReleaseSafe(domains
);
1723 CFReleaseSafe(clientAuditToken
);
1726 static void securityd_xpc_init(const char *service_name
)
1728 #if TARGET_OS_IPHONE
1729 pthread_key_create(&taskThreadKey
, NULL
);
1730 SecTaskDiagnoseEntitlements
= secTaskDiagnoseEntitlements
;
1733 secdebug("serverxpc", "start");
1734 xpc_connection_t listener
= xpc_connection_create_mach_service(service_name
, NULL
, XPC_CONNECTION_MACH_SERVICE_LISTENER
);
1736 seccritical("security failed to register xpc listener for %s, exiting", service_name
);
1740 xpc_connection_set_event_handler(listener
, ^(xpc_object_t connection
) {
1741 if (xpc_get_type(connection
) == XPC_TYPE_CONNECTION
) {
1742 xpc_connection_set_event_handler(connection
, ^(xpc_object_t event
) {
1743 if (xpc_get_type(event
) == XPC_TYPE_DICTIONARY
) {
1744 xpc_retain(connection
);
1746 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
1747 securityd_xpc_dictionary_handler(connection
, event
);
1749 xpc_release(connection
);
1753 xpc_connection_resume(connection
);
1756 xpc_connection_resume(listener
);
1759 xpc_activity_register("com.apple.securityd.daily", XPC_ACTIVITY_CHECK_IN
, ^(xpc_activity_t activity
) {
1760 xpc_activity_state_t activityState
= xpc_activity_get_state(activity
);
1761 if (activityState
== XPC_ACTIVITY_STATE_RUN
) {
1762 SecCKKS24hrNotification();
1769 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1771 #if TARGET_OS_EMBEDDED
1772 static void securityd_soscc_lock_hack() {
1773 dispatch_queue_t soscc_lock_queue
= dispatch_queue_create("soscc_lock_queue", DISPATCH_QUEUE_PRIORITY_DEFAULT
);
1776 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1777 // FIXME: securityd isn't currently registering for any other notifyd events. If/when it does,
1778 // this code will need to be generalized / migrated away from just this specific purpose.
1779 xpc_set_event_stream_handler("com.apple.notifyd.matching", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH
, 0), ^(xpc_object_t object
) {
1780 char *event_description
= xpc_copy_description(object
);
1781 secnotice("events", "%s", event_description
);
1782 free(event_description
);
1785 secnotice("lockassertion", "notify_register_dispatch(kSOSCCHoldLockForInitialSync)");
1786 notify_register_dispatch(kSOSCCHoldLockForInitialSync
, &soscc_tok
, soscc_lock_queue
, ^(int token __unused
) {
1787 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync: grabbing the lock");
1788 CFErrorRef error
= NULL
;
1790 uint64_t one_minute
= 60ull;
1791 if(SecAKSLockUserKeybag(one_minute
, &error
)){
1792 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1793 xpc_transaction_begin();
1795 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, one_minute
*NSEC_PER_SEC
), soscc_lock_queue
, ^{
1796 CFErrorRef localError
= NULL
;
1797 if(!SecAKSUnLockUserKeybag(&localError
))
1798 secerror("failed to unlock: %@", localError
);
1799 CFReleaseNull(localError
);
1800 xpc_transaction_end();
1803 secerror("Failed to take device lock assertion: %@", error
);
1805 CFReleaseNull(error
);
1806 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync => done");
1816 static char homeDir
[PATH_MAX
] = {};
1818 if (homeDir
[0] == '\0') {
1819 struct passwd
* pwd
= getpwuid(getuid());
1823 if (realpath(pwd
->pw_dir
, homeDir
) == NULL
) {
1824 strlcpy(homeDir
, pwd
->pw_dir
, sizeof(homeDir
));
1832 int main(int argc
, char *argv
[])
1834 char *wait4debugger
= getenv("WAIT4DEBUGGER");
1835 if (wait4debugger
&& !strcasecmp("YES", wait4debugger
)) {
1836 seccritical("SIGSTOPing self, awaiting debugger");
1837 kill(getpid(), SIGSTOP
);
1838 seccritical("Again, for good luck (or bad debuggers)");
1839 kill(getpid(), SIGSTOP
);
1842 /* <rdar://problem/15792007> Users with network home folders are unable to use/save password for Mail/Cal/Contacts/websites
1843 Secd doesn't realize DB connections get invalidated when network home directory users logout
1844 and their home gets unmounted. Exit secd, start fresh when user logs back in.
1847 int sessionstatechanged_tok
;
1848 notify_register_dispatch(kSA_SessionStateChangedNotification
, &sessionstatechanged_tok
, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^(int token __unused
) {
1849 // we could be a process running as root.
1850 // However, since root never logs out this isn't an issue.
1851 if (SASSessionStateForUser(getuid()) == kSA_state_loggingout_pointofnoreturn
) {
1852 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, 3ull*NSEC_PER_SEC
), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
1853 xpc_transaction_exit_clean();
1860 #define SECD_PROFILE_NAME "com.apple.secd"
1861 const char *homedir
= homedirPath();
1862 if (homedir
== NULL
)
1863 errx(1, "failed to get home directory for secd");
1865 char *errorbuf
= NULL
;
1866 const char *sandbox_params
[] = {
1872 rc
= sandbox_init_with_parameters(SECD_PROFILE_NAME
, SANDBOX_NAMED
, sandbox_params
, &errorbuf
);
1874 err(1, "Failed to process in a sandbox: %d %s", rc
, errorbuf
);
1875 #endif /* TARGET_OS_OSX */
1877 const char *serviceName
= kSecuritydXPCServiceName
;
1878 /* setup SQDLite before some other component have a chance to create a database connection */
1879 _SecDbServerSetup();
1881 securityd_init_server();
1882 securityd_xpc_init(serviceName
);
1884 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1885 #if TARGET_OS_EMBEDDED
1886 securityd_soscc_lock_hack();
1892 /* vi:set ts=4 sw=4 et: */