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
);
1084 CFDataRef nullData
= CFDataCreate(kCFAllocatorDefault
, &zero
, 1); // token we send if we really wanted to send NULL
1085 if(CFEqual(recovery_key
, nullData
)) {
1086 CFReleaseNull(recovery_key
);
1088 CFReleaseNull(nullData
);
1089 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRegisterRecoveryPublicKey_Server(recovery_key
, &error
));
1090 CFReleaseNull(recovery_key
);
1094 case kSecXPCOpGetRecoveryPublicKey
:
1096 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1097 xpc_object_t xpc_recovery_object
= NULL
;
1098 CFDataRef recovery
= SOSCCCopyRecoveryPublicKey(&error
);
1100 xpc_recovery_object
= _CFXPCCreateXPCObjectFromCFObject(recovery
);
1102 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_recovery_object
);
1103 CFReleaseNull(recovery
);
1107 case kSecXPCOpSetBagForAllSlices
:
1109 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1110 CFDataRef backupSlice
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
1111 bool includeV0
= xpc_dictionary_get_bool(event
, kSecXPCKeyIncludeV0
);
1112 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, backupSlice
&& SOSCCRegisterSingleRecoverySecret_Server(backupSlice
, includeV0
, &error
));
1113 CFReleaseSafe(backupSlice
);
1117 case kSecXPCOpCopyApplicantPeerInfo
:
1118 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1119 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1120 SOSCCCopyApplicantPeerInfo_Server(&error
),
1124 case kSecXPCOpCopyValidPeerPeerInfo
:
1125 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1126 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1127 SOSCCCopyValidPeerPeerInfo_Server(&error
),
1131 case kSecXPCOpValidateUserPublic
:
1132 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1133 bool trusted
= SOSCCValidateUserPublic_Server(&error
);
1134 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, trusted
);
1137 case kSecXPCOpCopyNotValidPeerPeerInfo
:
1138 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1139 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1140 SOSCCCopyNotValidPeerPeerInfo_Server(&error
),
1144 case kSecXPCOpCopyGenerationPeerInfo
:
1145 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1146 xpc_dictionary_set_and_consume_CFArray(replyMessage
, kSecXPCKeyResult
,
1147 SOSCCCopyGenerationPeerInfo_Server(&error
));
1150 case kSecXPCOpCopyRetirementPeerInfo
:
1151 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1152 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1153 SOSCCCopyRetirementPeerInfo_Server(&error
),
1157 case kSecXPCOpCopyViewUnawarePeerInfo
:
1158 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1159 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1160 SOSCCCopyViewUnawarePeerInfo_Server(&error
),
1164 case kSecXPCOpCopyAccountData
:
1166 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1167 xpc_object_t xpc_account_object
= NULL
;
1168 CFDataRef accountData
= SOSCCCopyAccountState_Server(&error
);
1170 xpc_account_object
= _CFXPCCreateXPCObjectFromCFObject(accountData
);
1172 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_account_object
);
1173 CFReleaseNull(accountData
);
1177 case kSecXPCOpDeleteAccountData
:
1179 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1180 bool status
= SOSCCDeleteAccountState_Server(&error
);
1181 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, status
);
1185 case kSecXPCOpCopyEngineData
:
1187 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1189 xpc_object_t xpc_engine_object
= NULL
;
1190 CFDataRef engineData
= SOSCCCopyEngineData_Server(&error
);
1192 xpc_engine_object
= _CFXPCCreateXPCObjectFromCFObject(engineData
);
1194 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_engine_object
);
1195 CFReleaseNull(engineData
);
1200 case kSecXPCOpDeleteEngineData
:
1202 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1203 bool status
= SOSCCDeleteEngineState_Server(&error
);
1204 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, status
);
1208 case kSecXPCOpCopyEngineState
:
1210 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1211 CFArrayRef array
= SOSCCCopyEngineState_Server(&error
);
1212 CFDataRef derData
= NULL
;
1214 require_quiet(array
, done
);
1215 derData
= CFPropertyListCreateDERData(kCFAllocatorDefault
, array
, &error
);
1217 require_quiet(derData
, done
);
1218 xpc_dictionary_set_data(replyMessage
, kSecXPCKeyResult
, CFDataGetBytePtr(derData
), CFDataGetLength(derData
));
1220 CFReleaseNull(derData
);
1221 CFReleaseNull(array
);
1225 case kSecXPCOpCopyPeerPeerInfo
:
1226 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1227 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1228 SOSCCCopyPeerPeerInfo_Server(&error
),
1232 case kSecXPCOpCopyConcurringPeerPeerInfo
:
1233 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1234 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1235 SOSCCCopyConcurringPeerPeerInfo_Server(&error
),
1239 case kSecXPCOpCopyMyPeerInfo
:
1240 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1241 SOSPeerInfoRef peerInfo
= SOSCCCopyMyPeerInfo_Server(&error
);
1242 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1243 CFReleaseNull(peerInfo
);
1245 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1246 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1247 xpc_release(xpc_object
);
1249 CFReleaseNull(peerInfoData
);
1252 case kSecXPCOpGetLastDepartureReason
:
1253 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1254 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1255 SOSCCGetLastDepartureReason_Server(&error
));
1258 case kSecXPCOpSetLastDepartureReason
:
1259 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1260 int32_t reason
= (int32_t) xpc_dictionary_get_int64(event
, kSecXPCKeyReason
);
1261 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1262 SOSCCSetLastDepartureReason_Server(reason
, &error
));
1265 case kSecXPCOpProcessSyncWithPeers
:
1266 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1267 CFSetRef peers
= SecXPCDictionaryCopySet(event
, kSecXPCKeySet
, &error
);
1268 CFSetRef backupPeers
= SecXPCDictionaryCopySet(event
, kSecXPCKeySet2
, &error
);
1269 if (peers
&& backupPeers
) {
1270 CFSetRef result
= SOSCCProcessSyncWithPeers_Server(peers
, backupPeers
, &error
);
1272 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
1274 CFReleaseNull(result
);
1276 CFReleaseNull(peers
);
1277 CFReleaseNull(backupPeers
);
1280 case kSecXPCOpProcessSyncWithAllPeers
:
1281 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1282 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1283 SOSCCProcessSyncWithAllPeers_Server(&error
));
1286 case soscc_EnsurePeerRegistration_id
:
1287 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1288 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1289 SOSCCProcessEnsurePeerRegistration_Server(&error
));
1292 case kSecXPCOpCopyIncompatibilityInfo
:
1293 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1294 CFStringRef iis
= SOSCCCopyIncompatibilityInfo_Server(&error
);
1295 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, iis
, &error
);
1299 case kSecXPCOpRollKeys
:
1301 bool force
= xpc_dictionary_get_bool(event
, "force");
1302 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1303 _SecServerRollKeys(force
, &client
, &error
));
1306 case kSecXPCOpWaitForInitialSync
:
1307 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1308 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1309 SOSCCWaitForInitialSync_Server(&error
));
1313 case kSecXPCOpCopyYetToSyncViews
:
1314 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1315 CFArrayRef array
= SOSCCCopyYetToSyncViewsList_Server(&error
);
1317 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1318 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1319 xpc_release(xpc_array
);
1321 CFReleaseNull(array
);
1324 case kSecXPCOpSetEscrowRecord
:
1325 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1326 CFStringRef escrow_label
= SecXPCDictionaryCopyString(event
, kSecXPCKeyEscrowLabel
, &error
);
1327 uint64_t tries
= xpc_dictionary_get_int64(event
, kSecXPCKeyTriesLabel
);
1329 bool result
= SOSCCSetEscrowRecord_Server(escrow_label
, tries
, &error
);
1331 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1333 CFReleaseNull(escrow_label
);
1336 case kSecXPCOpGetEscrowRecord
:
1337 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1338 CFDictionaryRef record
= SOSCCCopyEscrowRecord_Server(&error
);
1340 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(record
);
1341 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1342 xpc_release(xpc_dictionary
);
1344 CFReleaseNull(record
);
1347 case kSecXPCOpCopyBackupInformation
:
1348 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1349 CFDictionaryRef record
= SOSCCCopyBackupInformation_Server(&error
);
1351 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(record
);
1352 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1353 xpc_release(xpc_dictionary
);
1355 CFReleaseNull(record
);
1359 case kSecXPCOpCheckPeerAvailability
:
1360 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1361 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCCheckPeerAvailability_Server(&error
));
1366 case kSecXPCOpIsThisDeviceLastBackup
:
1367 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1368 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCkSecXPCOpIsThisDeviceLastBackup_Server(&error
));
1371 case kSecXPCOpPeersHaveViewsEnabled
:
1373 CFArrayRef viewSet
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyArray
, &error
);
1375 CFBooleanRef result
= SOSCCPeersHaveViewsEnabled_Server(viewSet
, &error
);
1377 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
!= kCFBooleanFalse
);
1380 CFReleaseNull(viewSet
);
1384 case kSecXPCOpWhoAmI
:
1387 xpc_dictionary_set_data(replyMessage
, "musr", CFDataGetBytePtr(client
.musr
), CFDataGetLength(client
.musr
));
1388 xpc_dictionary_set_bool(replyMessage
, "system-keychain", client
.allowSystemKeychain
);
1389 xpc_dictionary_set_bool(replyMessage
, "syncbubble-keychain", client
.allowSyncBubbleKeychain
);
1390 xpc_dictionary_set_bool(replyMessage
, "network-extension", client
.isNetworkExtension
);
1391 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1394 case kSecXPCOpTransmogrifyToSyncBubble
:
1396 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainSyncBubble
, &error
)) {
1398 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1399 CFArrayRef services
= SecXPCDictionaryCopyArray(event
, "services", &error
);
1401 if (uid
&& services
) {
1402 res
= _SecServerTransmogrifyToSyncBubble(services
, uid
, &client
, &error
);
1404 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1405 CFReleaseNull(services
);
1407 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1412 case kSecXPCOpTransmogrifyToSystemKeychain
:
1414 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
)) {
1416 bool res
= _SecServerTransmogrifyToSystemKeychain(&client
, &error
);
1417 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1419 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1425 case kSecXPCOpDeleteUserView
:
1427 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
)) {
1430 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1432 res
= _SecServerDeleteMUSERViews(&client
, uid
, &error
);
1435 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1440 case kSecXPCOpWrapToBackupSliceKeyBagForView
:
1442 CFStringRef viewname
= SecXPCDictionaryCopyString(event
, kSecXPCKeyViewName
, &error
);
1444 CFDataRef plaintext
= SecXPCDictionaryCopyData(event
, kSecXPCData
, &error
);
1446 CFDataRef ciphertext
= NULL
;
1447 CFDataRef bskbEncoded
= NULL
;
1449 bool result
= SOSWrapToBackupSliceKeyBagForView_Server(viewname
, plaintext
, &ciphertext
, &bskbEncoded
, &error
);
1450 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1452 if(!error
&& result
) {
1454 xpc_dictionary_set_data(replyMessage
, kSecXPCData
, CFDataGetBytePtr(ciphertext
), CFDataGetLength(ciphertext
));
1457 xpc_dictionary_set_data(replyMessage
, kSecXPCKeyKeybag
, CFDataGetBytePtr(bskbEncoded
), CFDataGetLength(bskbEncoded
));
1460 CFReleaseSafe(ciphertext
);
1461 CFReleaseSafe(bskbEncoded
);
1463 CFReleaseSafe(plaintext
);
1465 CFReleaseNull(viewname
);
1468 case kSecXPCOpCopyApplication
:
1469 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1470 SOSPeerInfoRef peerInfo
= SOSCCCopyApplication_Server(&error
);
1471 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1472 CFReleaseNull(peerInfo
);
1474 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1475 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1476 xpc_release(xpc_object
);
1478 CFReleaseNull(peerInfoData
);
1481 case kSecXPCOpCopyCircleJoiningBlob
:
1482 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1483 CFDataRef appBlob
= SecXPCDictionaryCopyCFDataRef(event
, kSecXPCData
, &error
);
1484 SOSPeerInfoRef applicant
= SOSPeerInfoCreateFromData(kCFAllocatorDefault
, &error
, appBlob
);
1485 CFDataRef pbblob
= SOSCCCopyCircleJoiningBlob_Server(applicant
, &error
);
1487 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(pbblob
);
1488 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1489 xpc_release(xpc_object
);
1491 CFReleaseNull(pbblob
);
1492 CFReleaseNull(applicant
);
1493 CFReleaseNull(appBlob
);
1496 case kSecXPCOpCopyInitialSyncBlob
:
1497 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1498 CFDataRef initialblob
= SOSCCCopyInitialSyncData_Server(&error
);
1500 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(initialblob
);
1501 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1502 xpc_release(xpc_object
);
1504 CFReleaseNull(initialblob
);
1507 case kSecXPCOpJoinWithCircleJoiningBlob
:
1508 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1509 CFDataRef joiningBlob
= SecXPCDictionaryCopyCFDataRef(event
, kSecXPCData
, &error
);
1510 uint64_t version
= xpc_dictionary_get_uint64(event
, kSecXPCVersion
);
1511 bool retval
= SOSCCJoinWithCircleJoiningBlob_Server(joiningBlob
, (PiggyBackProtocolVersion
) version
, &error
);
1512 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1513 CFReleaseNull(joiningBlob
);
1517 case kSecXPCOpKVSKeyCleanup
:
1518 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1519 bool retval
= SOSCCCleanupKVSKeys_Server(&error
);
1520 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1523 case kSecXPCOpPopulateKVS
:
1524 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1525 bool retval
= SOSCCTestPopulateKVSWithBadKeys_Server(&error
);
1526 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1529 case kSecXPCOpMessageFromPeerIsPending
:
1531 SOSPeerInfoRef peer
= SecXPCDictionaryCopyPeerInfo(event
, kSecXPCKeyPeerInfo
, &error
);
1533 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1534 SOSCCMessageFromPeerIsPending_Server(peer
, &error
));
1536 CFReleaseNull(peer
);
1539 case kSecXPCOpSendToPeerIsPending
:
1541 SOSPeerInfoRef peer
= SecXPCDictionaryCopyPeerInfo(event
, kSecXPCKeyPeerInfo
, &error
);
1543 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1544 SOSCCSendToPeerIsPending(peer
, &error
));
1546 CFReleaseNull(peer
);
1549 case sec_delete_items_with_access_groups_id
:
1551 bool retval
= false;
1552 #if TARGET_OS_IPHONE
1553 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateUninstallDeletion
, &error
)) {
1554 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyAccessGroups
, &error
);
1557 retval
= _SecItemServerDeleteAllWithAccessGroups(accessGroups
, &client
, &error
);
1559 CFReleaseNull(accessGroups
);
1562 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1565 case sec_item_copy_parent_certificates_id
:
1567 CFArrayRef results
= NULL
;
1568 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateCertificateAllAccess
, &error
)) {
1569 CFDataRef issuer
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNormalizedIssuer
, &error
);
1570 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyAccessGroups
, &error
);
1571 if (issuer
&& accessGroups
) {
1572 results
= _SecItemCopyParentCertificates(issuer
, accessGroups
, &error
);
1574 CFReleaseNull(issuer
);
1575 CFReleaseNull(accessGroups
);
1577 SecXPCDictionarySetPListOptional(replyMessage
, kSecXPCKeyResult
, results
, &error
);
1578 CFReleaseNull(results
);
1581 case sec_item_certificate_exists_id
:
1583 bool result
= false;
1584 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateCertificateAllAccess
, &error
)) {
1585 CFDataRef issuer
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNormalizedIssuer
, &error
);
1586 CFDataRef serialNum
= SecXPCDictionaryCopyData(event
, kSecXPCKeySerialNumber
, &error
);
1587 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyAccessGroups
, &error
);
1588 if (issuer
&& serialNum
&& accessGroups
) {
1589 result
= _SecItemCertificateExists(issuer
, serialNum
, accessGroups
, &error
);
1591 CFReleaseNull(issuer
);
1592 CFReleaseNull(serialNum
);
1593 CFReleaseNull(accessGroups
);
1595 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1598 case kSecXPCOpCKKSEndpoint
: {
1599 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateCKKS
, &error
)) {
1600 xpc_endpoint_t endpoint
= SecServerCreateCKKSEndpoint();
1602 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyEndpoint
, endpoint
);
1603 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1604 xpc_release(endpoint
);
1606 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1611 case kSecXPCOpSOSEndpoint
: {
1612 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1613 xpc_endpoint_t endpoint
= SOSCCCreateSOSEndpoint_server(&error
);
1615 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyEndpoint
, endpoint
);
1616 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1617 xpc_release(endpoint
);
1619 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1624 case kSecXPCOpSecuritydXPCServerEndpoint
: {
1625 xpc_endpoint_t endpoint
= SecCreateSecuritydXPCServerEndpoint(&error
);
1627 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyEndpoint
, endpoint
);
1628 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1629 xpc_release(endpoint
);
1631 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1635 case kSecXPCOpBackupKeybagAdd
: {
1636 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementBackupTableOperations
, &error
)) {
1637 CFDataRef keybag
= NULL
, passcode
= NULL
;
1638 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
1639 CFDataRef identifier
= NULL
;
1640 CFDataRef pathinfo
= NULL
; // really a CFURLRef
1641 bool added
= _SecServerBackupKeybagAdd(&client
, passcode
, &identifier
, &pathinfo
, &error
);
1643 added
&= SecXPCDictionarySetDataOptional(replyMessage
, kSecXPCKeyBackupKeybagIdentifier
, identifier
, &error
);
1644 added
&= SecXPCDictionarySetDataOptional(replyMessage
, kSecXPCKeyBackupKeybagPath
, pathinfo
, &error
);
1645 SecXPCDictionarySetBool(replyMessage
, kSecXPCKeyResult
, added
, NULL
);
1647 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1650 CFReleaseSafe(passcode
);
1651 CFReleaseSafe(keybag
);
1655 case kSecXPCOpBackupKeybagDelete
: {
1657 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementBackupTableOperations
, &error
)) {
1658 bool deleted
= false;
1659 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
1661 CFTypeRef matchLimit
= CFDictionaryGetValue(query
, kSecMatchLimit
);
1662 bool deleteAll
= matchLimit
&& CFEqualSafe(matchLimit
, kSecMatchLimitAll
);
1664 if (deleteAll
&& !EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementBackupTableOperationsDeleteAll
, &error
)) {
1665 // require special entitlement to delete all backup keybags
1667 CFMutableDictionaryRef attributes
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, query
);
1668 CFStringRef requestedAgrp
= CFDictionaryGetValue(attributes
, kSecAttrAccessGroup
);
1669 CFStringRef resolvedAgrp
= NULL
;
1671 CFDictionarySetValue(attributes
, kSecAttrMultiUser
, client
.musr
);
1673 if (extractAccessGroup(&client
, requestedAgrp
, &resolvedAgrp
, &error
)) {
1675 CFDictionarySetValue(attributes
, kSecAttrAccessGroup
, resolvedAgrp
);
1677 deleted
= _SecServerBackupKeybagDelete(attributes
, deleteAll
, &error
);
1679 CFReleaseNull(resolvedAgrp
);
1680 CFReleaseNull(attributes
);
1683 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, deleted
);
1684 CFReleaseNull(query
);
1694 if(SecErrorGetOSStatus(error
) == errSecItemNotFound
|| isSOSErrorCoded(error
, kSOSErrorPublicKeyAbsent
))
1695 secdebug("ipc", "%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1696 else if (SecErrorGetOSStatus(error
) == errSecAuthNeeded
)
1697 secwarning("Authentication is needed %@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1699 secerror("%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1701 xpcError
= SecCreateXPCObjectWithCFError(error
);
1703 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyError
, xpcError
);
1705 } else if (replyMessage
) {
1706 secdebug("ipc", "%@ %@ responding %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyMessage
);
1709 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, &error
, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event
);
1710 secerror("%@: returning error: %@", client
.task
, error
);
1711 xpcError
= SecCreateXPCObjectWithCFError(error
);
1712 replyMessage
= xpc_create_reply_with_format(event
, "{%string: %value}", kSecXPCKeyError
, xpcError
);
1716 xpc_connection_send_message(connection
, replyMessage
);
1717 xpc_release(replyMessage
);
1720 xpc_release(xpcError
);
1721 #if TARGET_OS_IPHONE
1722 pthread_setspecific(taskThreadKey
, NULL
);
1724 CFReleaseSafe(error
);
1725 CFReleaseSafe(client
.accessGroups
);
1726 CFReleaseSafe(client
.musr
);
1727 CFReleaseSafe(client
.task
);
1728 CFReleaseSafe(domains
);
1729 CFReleaseSafe(clientAuditToken
);
1732 static void securityd_xpc_init(const char *service_name
)
1734 #if TARGET_OS_IPHONE
1735 pthread_key_create(&taskThreadKey
, NULL
);
1736 SecTaskDiagnoseEntitlements
= secTaskDiagnoseEntitlements
;
1739 secdebug("serverxpc", "start");
1740 xpc_connection_t listener
= xpc_connection_create_mach_service(service_name
, NULL
, XPC_CONNECTION_MACH_SERVICE_LISTENER
);
1742 seccritical("security failed to register xpc listener for %s, exiting", service_name
);
1746 xpc_connection_set_event_handler(listener
, ^(xpc_object_t connection
) {
1747 if (xpc_get_type(connection
) == XPC_TYPE_CONNECTION
) {
1748 xpc_connection_set_event_handler(connection
, ^(xpc_object_t event
) {
1749 if (xpc_get_type(event
) == XPC_TYPE_DICTIONARY
) {
1750 xpc_retain(connection
);
1752 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
1753 securityd_xpc_dictionary_handler(connection
, event
);
1755 xpc_release(connection
);
1759 xpc_connection_resume(connection
);
1762 xpc_connection_resume(listener
);
1765 xpc_activity_register("com.apple.securityd.daily", XPC_ACTIVITY_CHECK_IN
, ^(xpc_activity_t activity
) {
1766 xpc_activity_state_t activityState
= xpc_activity_get_state(activity
);
1767 if (activityState
== XPC_ACTIVITY_STATE_RUN
) {
1768 SecCKKS24hrNotification();
1775 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1777 #if TARGET_OS_EMBEDDED
1778 static void securityd_soscc_lock_hack() {
1779 dispatch_queue_t soscc_lock_queue
= dispatch_queue_create("soscc_lock_queue", DISPATCH_QUEUE_PRIORITY_DEFAULT
);
1782 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1783 // FIXME: securityd isn't currently registering for any other notifyd events. If/when it does,
1784 // this code will need to be generalized / migrated away from just this specific purpose.
1785 xpc_set_event_stream_handler("com.apple.notifyd.matching", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH
, 0), ^(xpc_object_t object
) {
1786 char *event_description
= xpc_copy_description(object
);
1787 secnotice("events", "%s", event_description
);
1788 free(event_description
);
1791 secnotice("lockassertion", "notify_register_dispatch(kSOSCCHoldLockForInitialSync)");
1792 notify_register_dispatch(kSOSCCHoldLockForInitialSync
, &soscc_tok
, soscc_lock_queue
, ^(int token __unused
) {
1793 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync: grabbing the lock");
1794 CFErrorRef error
= NULL
;
1796 uint64_t one_minute
= 60ull;
1797 if(SecAKSLockUserKeybag(one_minute
, &error
)){
1798 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1799 xpc_transaction_begin();
1801 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, one_minute
*NSEC_PER_SEC
), soscc_lock_queue
, ^{
1802 CFErrorRef localError
= NULL
;
1803 if(!SecAKSUnLockUserKeybag(&localError
))
1804 secerror("failed to unlock: %@", localError
);
1805 CFReleaseNull(localError
);
1806 xpc_transaction_end();
1809 secerror("Failed to take device lock assertion: %@", error
);
1811 CFReleaseNull(error
);
1812 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync => done");
1822 static char homeDir
[PATH_MAX
] = {};
1824 if (homeDir
[0] == '\0') {
1825 struct passwd
* pwd
= getpwuid(getuid());
1829 if (realpath(pwd
->pw_dir
, homeDir
) == NULL
) {
1830 strlcpy(homeDir
, pwd
->pw_dir
, sizeof(homeDir
));
1838 int main(int argc
, char *argv
[])
1840 char *wait4debugger
= getenv("WAIT4DEBUGGER");
1841 if (wait4debugger
&& !strcasecmp("YES", wait4debugger
)) {
1842 seccritical("SIGSTOPing self, awaiting debugger");
1843 kill(getpid(), SIGSTOP
);
1844 seccritical("Again, for good luck (or bad debuggers)");
1845 kill(getpid(), SIGSTOP
);
1848 /* <rdar://problem/15792007> Users with network home folders are unable to use/save password for Mail/Cal/Contacts/websites
1849 Secd doesn't realize DB connections get invalidated when network home directory users logout
1850 and their home gets unmounted. Exit secd, start fresh when user logs back in.
1853 int sessionstatechanged_tok
;
1854 notify_register_dispatch(kSA_SessionStateChangedNotification
, &sessionstatechanged_tok
, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^(int token __unused
) {
1855 // we could be a process running as root.
1856 // However, since root never logs out this isn't an issue.
1857 if (SASSessionStateForUser(getuid()) == kSA_state_loggingout_pointofnoreturn
) {
1858 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, 3ull*NSEC_PER_SEC
), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
1859 xpc_transaction_exit_clean();
1866 #define SECD_PROFILE_NAME "com.apple.secd"
1867 const char *homedir
= homedirPath();
1868 if (homedir
== NULL
)
1869 errx(1, "failed to get home directory for secd");
1871 char *errorbuf
= NULL
;
1872 const char *sandbox_params
[] = {
1878 rc
= sandbox_init_with_parameters(SECD_PROFILE_NAME
, SANDBOX_NAMED
, sandbox_params
, &errorbuf
);
1880 err(1, "Failed to process in a sandbox: %d %s", rc
, errorbuf
);
1881 #endif /* TARGET_OS_OSX */
1883 const char *serviceName
= kSecuritydXPCServiceName
;
1884 /* setup SQDLite before some other component have a chance to create a database connection */
1885 _SecDbServerSetup();
1887 securityd_init_server();
1888 securityd_xpc_init(serviceName
);
1890 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1891 #if TARGET_OS_EMBEDDED
1892 securityd_soscc_lock_hack();
1898 /* vi:set ts=4 sw=4 et: */