2 * Copyright (c) 2007-2017 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <Security/SecureObjectSync/SOSPeerInfoDER.h>
25 #include <Security/SecureObjectSync/SOSCloudCircle.h>
26 #include <Security/SecureObjectSync/SOSCloudCircleInternal.h>
27 #include <Security/SecureObjectSync/SOSInternal.h>
28 #include <Security/SecureObjectSync/SOSPeerInfoCollections.h>
29 #include <Security/SecureObjectSync/SOSControlServer.h>
30 #include <Security/SecBase.h>
31 #include <Security/SecBasePriv.h>
32 #include <Security/SecCertificatePriv.h>
33 #include <Security/SecEntitlements.h>
34 #include <Security/SecInternal.h>
35 #include <Security/SecItem.h>
36 #include <Security/SecItemPriv.h>
37 #include <Security/SecPolicy.h>
38 #include <Security/SecPolicyInternal.h>
39 #include <Security/SecTask.h>
40 #include <Security/SecTrustInternal.h>
41 #include <Security/SecuritydXPC.h>
42 #include <securityd/OTATrustUtilities.h>
43 #include <securityd/SOSCloudCircleServer.h>
44 #include <securityd/SecItemBackupServer.h>
45 #include <securityd/SecItemServer.h>
46 #include <securityd/SecLogSettingsServer.h>
47 #include <securityd/SecOTRRemote.h>
48 #include <securityd/SecTrustServer.h>
49 #include <securityd/SecTrustStoreServer.h>
50 #include <securityd/iCloudTrace.h>
51 #include <securityd/spi.h>
52 #include <utilities/SecCFError.h>
53 #include <utilities/SecCFWrappers.h>
54 #include <utilities/SecDb.h>
55 #include <utilities/SecIOFormat.h>
56 #include <utilities/SecXPCError.h>
57 #include <utilities/debugging.h>
58 #include <utilities/SecInternalReleasePriv.h>
59 #include <utilities/der_plist_internal.h>
60 #include <utilities/der_plist.h>
61 #include <securityd/personalization.h>
62 #include <securityd/SecPinningDb.h>
63 #include <securityd/SFKeychainControlManager.h>
65 #include <keychain/ckks/CKKS.h>
66 #include <keychain/ckks/CKKSControlServer.h>
67 #include "keychain/ot/OctagonControlServer.h"
69 #include <AssertMacros.h>
70 #include <CoreFoundation/CFXPCBridge.h>
71 #include <CoreFoundation/CoreFoundation.h>
72 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
75 #include <Security/SecTaskPriv.h>
76 #include <login/SessionAgentStatusCom.h>
79 #include <bsm/libbsm.h>
80 #include <ipc/securityd_client.h>
81 #include <libkern/OSAtomic.h>
82 #include <mach/mach.h>
83 #include <mach/message.h>
86 #include <sys/queue.h>
87 #include <sys/sysctl.h>
89 #include <xpc/private.h>
92 #include <ipc/server_security_helpers.h>
93 #include <ipc/server_entitlement_helpers.h>
101 static bool accessGroupPermitted(SecurityClient
* client
, CFArrayRef accessGroups
, CFStringRef accessGroup
) {
102 /* NULL accessGroups is wildcard. */
105 /* Make sure we have a string. */
106 if (!isString(accessGroup
))
109 /* Having the special accessGroup "*" allows access to all accessGroups. */
110 CFRange range
= { 0, CFArrayGetCount(accessGroups
) };
112 (CFArrayContainsValue(accessGroups
, range
, accessGroup
) ||
113 CFArrayContainsValue(accessGroups
, range
, CFSTR("*"))))
119 static bool extractAccessGroup(SecurityClient
*client
, CFStringRef requestedAgrp
, CFStringRef
*resolvedAgrp
, CFErrorRef
*error
) {
122 /* Access group sanity checking.
123 Similar to accessGroupsAllows, but ignores accessGroupIsNetworkExtensionAndClientIsEntitled */
124 CFArrayRef accessGroups
= client
->accessGroups
;
125 CFStringRef agrp
= requestedAgrp
;
126 /* Having the special accessGroup "*" allows access to all accessGroups. */
127 if (CFArrayContainsValue(accessGroups
, CFRangeMake(0,CFArrayGetCount(accessGroups
)), CFSTR("*")))
131 /* The user specified an explicit access group, validate it. */
132 if (!accessGroupPermitted(client
, accessGroups
, requestedAgrp
))
133 ok
= SecError(errSecMissingEntitlement
, error
, CFSTR("explicit accessGroup %@ not in client access %@"), requestedAgrp
, accessGroups
);
135 // We are using an implicit access group
136 // Add it as if the user specified it as an attribute.
137 agrp
= (CFStringRef
)CFArrayGetValueAtIndex(client
->accessGroups
, 0);
140 if (agrp
&& resolvedAgrp
)
141 *resolvedAgrp
= agrp
;
145 static void with_label_and_password(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
)) {
146 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyUserLabel
);
148 if (label_utf8
) { // Anything we would do here requires a user label
149 size_t password_length
= 0;
150 const void *password_data
= xpc_dictionary_get_data(message
, kSecXPCKeyUserPassword
, &password_length
);
152 CFDataRef user_password
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
);
153 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
155 action(user_label
, user_password
);
157 CFReleaseNull(user_password
);
158 CFReleaseNull(user_label
);
162 static void with_label_and_password_and_dsid(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
, CFStringRef dsid
)) {
163 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyUserLabel
);
165 if (label_utf8
) { // Anything we would do here requires a user label
166 size_t password_length
= 0;
167 const void *password_data
= xpc_dictionary_get_data(message
, kSecXPCKeyUserPassword
, &password_length
);
168 const char *xdsid
= xpc_dictionary_get_string(message
, kSecXPCKeyDSID
);
170 CFDataRef user_password
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, password_data
, password_length
, kCFAllocatorNull
);
171 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
172 CFStringRef dsid
= CFStringCreateWithCString(kCFAllocatorDefault
, xdsid
, kCFStringEncodingUTF8
);
174 action(user_label
, user_password
, dsid
);
177 CFReleaseNull(user_password
);
178 CFReleaseNull(user_label
);
182 static void with_label_and_number(xpc_object_t message
, void (^action
)(CFStringRef label
, uint64_t number
)) {
183 const char *label_utf8
= xpc_dictionary_get_string(message
, kSecXPCKeyViewName
);
184 const int64_t number
= xpc_dictionary_get_int64(message
, kSecXPCKeyViewActionCode
);
185 CFStringRef user_label
= CFStringCreateWithCString(kCFAllocatorDefault
, label_utf8
, kCFStringEncodingUTF8
);
187 action(user_label
, number
);
188 CFReleaseNull(user_label
);
191 static CFArrayRef
SecXPCDictionaryCopyPeerInfoArray(xpc_object_t dictionary
, const char *key
, CFErrorRef
*error
) {
192 return CreateArrayOfPeerInfoWithXPCObject(xpc_dictionary_get_value(dictionary
, key
), error
);
195 static CFDataRef
SecXPCDictionaryCopyCFDataRef(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
196 CFDataRef retval
= NULL
;
197 const uint8_t *bytes
= NULL
;
200 bytes
= xpc_dictionary_get_data(message
, key
, &len
);
201 require_action_quiet(bytes
, errOut
, SOSCreateError(kSOSErrorBadKey
, CFSTR("missing CFDataRef info"), NULL
, error
));
202 retval
= CFDataCreate(NULL
, bytes
, len
);
203 require_action_quiet(retval
, errOut
, SOSCreateError(kSOSErrorBadKey
, CFSTR("could not allocate CFDataRef info"), NULL
, error
));
208 static CFSetRef
CreateCFSetRefFromXPCObject(xpc_object_t xpcSetDER
, CFErrorRef
* error
) {
209 CFSetRef retval
= NULL
;
210 require_action_quiet(xpcSetDER
, errOut
, SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedNull
, sSecXPCErrorDomain
, NULL
, error
, NULL
, CFSTR("Unexpected Null Set to decode")));
212 require_action_quiet(xpc_get_type(xpcSetDER
) == XPC_TYPE_DATA
, errOut
, SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, error
, NULL
, CFSTR("xpcSetDER not data, got %@"), xpcSetDER
));
214 const uint8_t* der
= xpc_data_get_bytes_ptr(xpcSetDER
);
215 const uint8_t* der_end
= der
+ xpc_data_get_length(xpcSetDER
);
216 der
= der_decode_set(kCFAllocatorDefault
, kCFPropertyListMutableContainersAndLeaves
, &retval
, error
, der
, der_end
);
217 if (der
!= der_end
) {
218 SecError(errSecDecode
, error
, CFSTR("trailing garbage at end of SecAccessControl data"));
223 CFReleaseNull(retval
);
227 static SOSPeerInfoRef
SecXPCDictionaryCopyPeerInfo(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
229 const uint8_t *der
= xpc_dictionary_get_data(message
, key
, &length
);
231 return SecRequirementError(der
!= NULL
, error
, CFSTR("No data for key %s"), key
) ? SOSPeerInfoCreateFromDER(kCFAllocatorDefault
, error
, &der
, der
+ length
) : NULL
;
234 static CFSetRef
SecXPCSetCreateFromXPCDictionaryElement(xpc_object_t event
, const char *key
) {
235 CFErrorRef error
= NULL
;
236 xpc_object_t object
= xpc_dictionary_get_value(event
, key
);
237 CFSetRef retval
= NULL
;
238 if(object
) retval
= CreateCFSetRefFromXPCObject(object
, &error
);
239 CFReleaseNull(error
);
244 void xpc_dictionary_set_and_consume_CFArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
) {
246 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(cf_array
);
247 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
248 xpc_release(xpc_array
);
250 CFReleaseNull(cf_array
);
254 bool xpc_dictionary_set_and_consume_PeerInfoArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
, CFErrorRef
*error
) {
257 xpc_object_t xpc_array
= CreateXPCObjectWithArrayOfPeerInfo(cf_array
, error
);
259 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
260 xpc_release(xpc_array
);
265 CFReleaseNull(cf_array
);
270 SecDataCopyMmapFileDescriptor(int fd
, void **mem
, size_t *size
, CFErrorRef
*error
)
273 if (fstat(fd
, &sb
) < 0) {
277 *size
= (size_t)sb
.st_size
;
278 if ((off_t
)*size
!= sb
.st_size
) {
282 *mem
= mmap(NULL
, *size
, PROT_READ
, MAP_SHARED
, fd
, 0);
283 if (*mem
== MAP_FAILED
) {
287 return CFDataCreateWithBytesNoCopy(NULL
, *mem
, *size
, kCFAllocatorNull
);
291 SecDataWriteFileDescriptor(int fd
, CFDataRef data
)
293 CFIndex count
= CFDataGetLength(data
);
294 const uint8_t *ptr
= CFDataGetBytePtr(data
);
295 bool writeResult
= false;
298 ssize_t ret
= write(fd
, ptr
, count
);
311 // Returns error if entitlement isn't present.
313 EntitlementPresentAndTrue(uint64_t op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
315 if (!SecTaskGetBooleanValueForEntitlement(clientTask
, entitlement
)) {
316 SecError(errSecMissingEntitlement
, error
, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
)op
), clientTask
, entitlement
);
322 // Per <rdar://problem/13315020> Disable the entitlement check for "keychain-cloud-circle"
323 // we disable entitlement enforcement. However, we still log so we know who needs the entitlement
325 EntitlementPresentOrWhine(uint64_t op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
327 if (!SecTaskGetBooleanValueForEntitlement(clientTask
, entitlement
))
328 secnotice("serverxpc", "%@: %@ lacks entitlement %@", SOSCCGetOperationDescription((enum SecXPCOperation
)op
), clientTask
, entitlement
);
335 EntitlementAbsentOrFalse(uint64_t op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
337 if (SecTaskGetBooleanValueForEntitlement(clientTask
, entitlement
)) {
338 SecError(errSecNotAvailable
, error
, CFSTR("%@: %@ has entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
) op
), clientTask
, entitlement
);
344 static void securityd_xpc_dictionary_handler(const xpc_connection_t connection
, xpc_object_t event
) {
345 xpc_type_t type
= xpc_get_type(event
);
346 __block CFErrorRef error
= NULL
;
347 xpc_object_t xpcError
= NULL
;
348 xpc_object_t replyMessage
= NULL
;
349 CFDataRef clientAuditToken
= NULL
;
350 CFArrayRef domains
= NULL
;
351 SecurityClient client
= {
353 .accessGroups
= NULL
,
355 .uid
= xpc_connection_get_euid(connection
),
356 .allowSystemKeychain
= false,
357 .allowSyncBubbleKeychain
= false,
358 .isNetworkExtension
= false,
359 .canAccessNetworkExtensionAccessGroups
= false,
362 secdebug("serverxpc", "entering");
363 if (type
== XPC_TYPE_DICTIONARY
) {
364 // TODO: Find out what we're dispatching.
365 replyMessage
= xpc_dictionary_create_reply(event
);
367 uint64_t operation
= xpc_dictionary_get_uint64(event
, kSecXPCKeyOperation
);
369 audit_token_t auditToken
= {};
370 xpc_connection_get_audit_token(connection
, &auditToken
);
371 clientAuditToken
= CFDataCreate(kCFAllocatorDefault
, (const UInt8
*)&auditToken
, sizeof(auditToken
));
373 fill_security_client(&client
, xpc_connection_get_euid(connection
), auditToken
);
376 if (operation
== sec_add_shared_web_credential_id
|| operation
== sec_copy_shared_web_credential_id
) {
377 domains
= SecTaskCopySharedWebCredentialDomains(client
.task
);
380 secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64
")", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), operation
);
384 case sec_item_add_id
:
386 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
387 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
389 // Check for any entitlement-required attributes
390 bool entitlementsCorrect
= true;
391 if(CFDictionaryGetValue(query
, kSecAttrDeriveSyncIDFromItemAttributes
) ||
392 CFDictionaryGetValue(query
, kSecAttrPCSPlaintextServiceIdentifier
) ||
393 CFDictionaryGetValue(query
, kSecAttrPCSPlaintextPublicKey
) ||
394 CFDictionaryGetValue(query
, kSecAttrPCSPlaintextPublicIdentity
)) {
395 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_add_id
, client
.task
, kSecEntitlementPrivateCKKSPlaintextFields
, &error
);
397 if (entitlementsCorrect
&& CFDictionaryGetValue(query
, kSecAttrSysBound
)) {
398 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_add_id
, client
.task
, kSecEntitlementPrivateSysBound
, &error
);
401 CFTypeRef result
= NULL
;
402 if(entitlementsCorrect
) {
403 if (_SecItemAdd(query
, &client
, &result
, &error
) && result
) {
404 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
405 CFReleaseNull(result
);
408 CFReleaseNull(query
);
413 case sec_item_copy_matching_id
:
415 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
416 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
418 CFTypeRef result
= NULL
;
419 if (_SecItemCopyMatching(query
, &client
, &result
, &error
) && result
) {
420 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
421 CFReleaseNull(result
);
423 CFReleaseNull(query
);
428 case sec_item_update_id
:
430 if (EntitlementAbsentOrFalse(sec_item_update_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
431 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
433 CFDictionaryRef attributesToUpdate
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyAttributesToUpdate
, &error
);
434 if (attributesToUpdate
) {
435 // Check for any entitlement-required attributes
436 bool entitlementsCorrect
= true;
437 if(CFDictionaryGetValue(query
, kSecAttrDeriveSyncIDFromItemAttributes
) ||
438 CFDictionaryGetValue(attributesToUpdate
, kSecAttrPCSPlaintextServiceIdentifier
) ||
439 CFDictionaryGetValue(attributesToUpdate
, kSecAttrPCSPlaintextPublicKey
) ||
440 CFDictionaryGetValue(attributesToUpdate
, kSecAttrPCSPlaintextPublicIdentity
)) {
441 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_update_id
, client
.task
, kSecEntitlementPrivateCKKSPlaintextFields
, &error
);
443 if (entitlementsCorrect
&& CFDictionaryGetValue(query
, kSecAttrSysBound
)) {
444 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_update_id
, client
.task
, kSecEntitlementPrivateSysBound
, &error
);
447 if(entitlementsCorrect
) {
448 bool result
= _SecItemUpdate(query
, attributesToUpdate
, &client
, &error
);
449 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
451 CFReleaseNull(attributesToUpdate
);
453 CFReleaseNull(query
);
458 case sec_item_delete_id
:
460 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
461 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
463 bool result
= _SecItemDelete(query
, &client
, &error
);
464 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
465 CFReleaseNull(query
);
470 case sec_item_update_token_items_id
:
472 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
473 CFStringRef tokenID
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
474 CFArrayRef attributes
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyQuery
, &error
);
476 bool result
= _SecItemUpdateTokenItems(tokenID
, attributes
, &client
, &error
);
477 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
479 CFReleaseNull(tokenID
);
480 CFReleaseNull(attributes
);
484 case sec_delete_all_id
:
488 /* buddy is temporary allowed to do this */
489 CFStringRef applicationIdentifier
= SecTaskCopyApplicationIdentifier(client
.task
);
490 bool isBuddy
= applicationIdentifier
&&
491 CFEqual(applicationIdentifier
, CFSTR("com.apple.purplebuddy"));
493 if (isBuddy
|| EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateDeleteAll
, &error
))
495 retval
= _SecItemDeleteAll(&error
);
498 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
501 case sec_keychain_backup_id
:
503 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
504 CFDataRef keybag
= NULL
, passcode
= NULL
;
505 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybag
, &error
)) {
506 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
507 bool emcs
= SecXPCDictionaryGetBool(event
, kSecXPCKeyEMCSBackup
, NULL
);
508 CFDataRef backup
= _SecServerKeychainCreateBackup(&client
, keybag
, passcode
, emcs
, &error
);
510 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
512 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, backup
, &error
);
514 bool writeResult
= SecDataWriteFileDescriptor(fd
, backup
);
518 SecError(errSecIO
, &error
, CFSTR("Failed to write backup file: %d"), errno
);
519 SecXPCDictionarySetBool(replyMessage
, kSecXPCKeyResult
, writeResult
, NULL
);
523 CFReleaseSafe(passcode
);
525 CFReleaseSafe(keybag
);
530 case sec_keychain_restore_id
:
532 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
533 CFDataRef backup
= NULL
;
537 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
539 backup
= SecDataCopyMmapFileDescriptor(fd
, &mem
, &size
, &error
);
541 backup
= SecXPCDictionaryCopyData(event
, kSecXPCKeyBackup
, &error
);
544 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
546 CFDataRef passcode
= NULL
;
547 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
548 bool result
= _SecServerKeychainRestore(backup
, &client
, keybag
, passcode
, &error
);
549 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
550 CFReleaseSafe(passcode
);
553 CFReleaseNull(keybag
);
555 CFReleaseNull(backup
);
564 case sec_keychain_backup_keybag_uuid_id
:
566 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
567 CFDataRef backup
= NULL
;
568 CFStringRef uuid
= NULL
;
572 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
574 backup
= SecDataCopyMmapFileDescriptor(fd
, &mem
, &size
, &error
);
576 uuid
= _SecServerBackupCopyUUID(backup
, &error
);
579 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, uuid
, &error
);
581 CFReleaseNull(backup
);
591 case sec_keychain_sync_update_message_id
:
593 CFDictionaryRef updates
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
595 CFArrayRef result
= _SecServerKeychainSyncUpdateMessage(updates
, &error
);
596 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
597 CFReleaseNull(result
);
599 CFReleaseNull(updates
);
602 case sec_keychain_backup_syncable_id
:
604 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
605 CFDictionaryRef oldbackup
= NULL
;
606 if (SecXPCDictionaryCopyDictionaryOptional(event
, kSecXPCKeyBackup
, &oldbackup
, &error
)) {
607 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
609 CFDataRef passcode
= NULL
;
610 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
611 CFDictionaryRef newbackup
= _SecServerBackupSyncable(oldbackup
, keybag
, passcode
, &error
);
613 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, newbackup
, &error
);
614 CFRelease(newbackup
);
616 CFReleaseSafe(passcode
);
618 CFReleaseNull(keybag
);
620 CFReleaseSafe(oldbackup
);
625 case sec_keychain_restore_syncable_id
:
627 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
628 CFDictionaryRef backup
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyBackup
, &error
);
630 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
632 CFDataRef passcode
= NULL
;
633 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
634 bool result
= _SecServerRestoreSyncable(backup
, keybag
, passcode
, &error
);
635 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
636 CFReleaseSafe(passcode
);
638 CFReleaseNull(keybag
);
640 CFReleaseNull(backup
);
645 case sec_item_backup_copy_names_id
:
647 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
648 CFArrayRef names
= SecServerItemBackupCopyNames(&error
);
649 SecXPCDictionarySetPListOptional(replyMessage
, kSecXPCKeyResult
, names
, &error
);
650 CFReleaseSafe(names
);
654 case sec_item_backup_handoff_fd_id
:
656 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
657 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
660 fd
= SecServerItemBackupHandoffFD(backupName
, &error
);
661 CFRelease(backupName
);
663 SecXPCDictionarySetFileDescriptor(replyMessage
, kSecXPCKeyResult
, fd
, &error
);
669 case sec_item_backup_set_confirmed_manifest_id
:
671 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
672 CFDataRef keybagDigest
= NULL
;
673 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybagDigest
, &error
)) {
674 CFDataRef manifest
= NULL
;
675 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &manifest
, &error
)) {
676 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
678 bool result
= SecServerItemBackupSetConfirmedManifest(backupName
, keybagDigest
, manifest
, &error
);
679 CFRelease(backupName
);
680 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
682 CFReleaseSafe(manifest
);
685 CFReleaseNull(keybagDigest
);
689 case sec_item_backup_restore_id
:
691 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
693 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
695 CFStringRef peerID
= NULL
;
696 if (SecXPCDictionaryCopyStringOptional(event
, kSecXPCKeyDigest
, &peerID
, &error
)) {
697 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
699 CFDataRef secret
= SecXPCDictionaryCopyData(event
, kSecXPCKeyUserPassword
, &error
);
701 CFDataRef backup
= SecXPCDictionaryCopyData(event
, kSecXPCData
, &error
);
703 result
= SecServerItemBackupRestore(backupName
, peerID
, keybag
, secret
, backup
, &error
);
710 CFReleaseSafe(peerID
);
712 CFRelease(backupName
);
714 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
718 case sec_add_shared_web_credential_id
:
720 #if TARGET_OS_IOS && !TARGET_OS_BRIDGE
721 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
723 CFTypeRef result
= NULL
;
725 CFStringRef appID
= (client
.task
) ? SecTaskCopyApplicationIdentifier(client
.task
) : NULL
;
726 if (_SecAddSharedWebCredential(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_copy_shared_web_credential_id
:
740 #if TARGET_OS_IOS && !TARGET_OS_BRIDGE
741 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
743 CFTypeRef result
= NULL
;
744 CFStringRef appID
= (client
.task
) ? SecTaskCopyApplicationIdentifier(client
.task
) : NULL
;
745 if (_SecCopySharedWebCredential(query
, &client
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
746 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
747 CFReleaseNull(result
);
749 CFReleaseSafe(appID
);
750 CFReleaseNull(query
);
753 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, kCFBooleanFalse
, &error
);
757 case sec_get_log_settings_id
:
759 CFPropertyListRef currentList
= SecCopyLogSettings_Server(&error
);
761 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, currentList
, &error
);
763 CFReleaseSafe(currentList
);
766 case sec_set_xpc_log_settings_id
:
768 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
770 SecSetXPCLogSettings_Server(newSettings
, &error
);
772 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
773 CFReleaseNull(newSettings
);
776 case sec_set_circle_log_settings_id
:
778 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
780 SecSetCircleLogSettings_Server(newSettings
, &error
);
782 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
783 CFReleaseNull(newSettings
);
786 case sec_otr_session_create_remote_id
:
788 CFDataRef publicPeerId
= NULL
;
789 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCPublicPeerId
, &publicPeerId
, &error
)) {
790 CFDataRef otrSession
= _SecOTRSessionCreateRemote(publicPeerId
, &error
);
792 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, otrSession
, &error
);
793 CFReleaseNull(otrSession
);
795 CFReleaseSafe(publicPeerId
);
799 case sec_otr_session_process_packet_remote_id
:
801 CFDataRef sessionData
= NULL
, inputPacket
= NULL
, outputSessionData
= NULL
, outputPacket
= NULL
;
802 bool readyForMessages
= false;
803 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCOTRSession
, &sessionData
, &error
)) {
804 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &inputPacket
, &error
)) {
805 bool result
= _SecOTRSessionProcessPacketRemote(sessionData
, inputPacket
, &outputSessionData
, &outputPacket
, &readyForMessages
, &error
);
807 SecXPCDictionarySetData(replyMessage
, kSecXPCOTRSession
, outputSessionData
, &error
);
808 SecXPCDictionarySetData(replyMessage
, kSecXPCData
, outputPacket
, &error
);
809 xpc_dictionary_set_bool(replyMessage
, kSecXPCOTRReady
, readyForMessages
);
810 CFReleaseNull(outputSessionData
);
811 CFReleaseNull(outputPacket
);
813 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
815 CFReleaseSafe(inputPacket
);
817 CFReleaseSafe(sessionData
);
821 case kSecXPCOpTryUserCredentials
:
822 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
823 with_label_and_password_and_dsid(event
, ^(CFStringRef label
, CFDataRef password
, CFStringRef dsid
) {
824 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
825 SOSCCTryUserCredentials_Server(label
, password
, dsid
, &error
));
829 case kSecXPCOpSetUserCredentials
:
830 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
831 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
832 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
833 SOSCCSetUserCredentials_Server(label
, password
, &error
));
837 case kSecXPCOpSetUserCredentialsAndDSID
:
838 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
839 with_label_and_password_and_dsid(event
, ^(CFStringRef label
, CFDataRef password
, CFStringRef dsid
) {
840 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
841 SOSCCSetUserCredentialsAndDSID_Server(label
, password
, dsid
, &error
));
846 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
847 with_label_and_number(event
, ^(CFStringRef view
, uint64_t actionCode
) {
848 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
849 SOSCCView_Server(view
, (SOSViewActionCode
)actionCode
, &error
));
853 case kSecXPCOpViewSet
:
854 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
855 CFSetRef enabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyEnabledViewsKey
);
856 CFSetRef disabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyDisabledViewsKey
);
857 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCViewSet_Server(enabledViews
, disabledViews
));
858 CFReleaseNull(enabledViews
);
859 CFReleaseNull(disabledViews
);
862 case kSecXPCOpSecurityProperty
:
863 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
864 with_label_and_number(event
, ^(CFStringRef property
, uint64_t actionCode
) {
865 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
866 SOSCCSecurityProperty_Server(property
, (SOSSecurityPropertyActionCode
)actionCode
, &error
));
870 case kSecXPCOpCanAuthenticate
:
871 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
872 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
873 SOSCCCanAuthenticate_Server(&error
));
876 case kSecXPCOpPurgeUserCredentials
:
877 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
878 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
879 SOSCCPurgeUserCredentials_Server(&error
));
882 case kSecXPCOpDeviceInCircle
:
883 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
884 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
885 SOSCCThisDeviceIsInCircle_Server(&error
));
888 case kSecXPCOpRequestToJoin
:
889 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
890 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
891 SOSCCRequestToJoinCircle_Server(&error
));
894 case kSecXPCOpAccountHasPublicKey
:
895 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
896 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
897 SOSCCAccountHasPublicKey_Server(&error
));
900 case kSecXPCOpAccountIsNew
:
901 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
902 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
903 SOSCCAccountIsNew_Server(&error
));
906 case kSecXPCOpRequestToJoinAfterRestore
:
907 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
908 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
909 SOSCCRequestToJoinCircleAfterRestore_Server(&error
));
912 case kSecXPCOpRequestEnsureFreshParameters
:
913 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
914 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
915 SOSCCRequestEnsureFreshParameters_Server(&error
));
918 case kSecXPCOpGetAllTheRings
:
919 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
920 CFStringRef ringDescriptions
= SOSCCGetAllTheRings_Server(&error
);
921 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(ringDescriptions
);
922 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
923 xpc_release(xpc_dictionary
);
926 case kSecXPCOpApplyToARing
:
927 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
928 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
929 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCApplyToARing_Server(ringName
, &error
));
930 CFReleaseNull(ringName
);
933 case kSecXPCOpWithdrawlFromARing
:
934 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
935 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
936 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCWithdrawlFromARing_Server(ringName
, &error
));
937 CFReleaseNull(ringName
);
940 case kSecXPCOpRingStatus
:
941 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
942 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
943 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRingStatus_Server(ringName
, &error
));
944 CFReleaseNull(ringName
);
947 case kSecXPCOpEnableRing
:
948 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
949 CFStringRef ringName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
950 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCEnableRing_Server(ringName
, &error
));
951 CFReleaseNull(ringName
);
954 case kSecXPCOpRequestDeviceID
:
955 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
956 CFStringRef deviceID
= SOSCCCopyDeviceID_Server(&error
);
958 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, deviceID
, &error
);
960 CFReleaseNull(deviceID
);
963 case kSecXPCOpSetDeviceID
:
964 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
965 CFStringRef IDS
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
966 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCSetDeviceID_Server(IDS
, &error
));
970 case kSecXPCOpHandleIDSMessage
:
971 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
972 CFDictionaryRef IDS
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyIDSMessage
, &error
);
973 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
, SOSCCHandleIDSMessage_Server(IDS
, &error
));
977 case kSecXPCOpClearKVSPeerMessage
:
978 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
979 CFStringRef peerID
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
980 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCClearPeerMessageKeyInKVS_Server(peerID
, &error
));
981 CFReleaseNull(peerID
);
984 case kSecXPCOpSendIDSMessage
:
985 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
986 CFStringRef message
= SecXPCDictionaryCopyString(event
, kSecXPCKeySendIDSMessage
, &error
);
987 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSServiceRegistrationTest_Server(message
, &error
));
988 CFReleaseNull(message
);
991 case kSecXPCOpSyncWithKVSPeer
:
992 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
993 CFStringRef peerID
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
994 CFDataRef message
= SecXPCDictionaryCopyData(event
, kSecXPCKeyIDSMessage
, &error
);
995 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRequestSyncWithPeerOverKVS_Server(peerID
, message
, &error
));
996 CFReleaseNull(message
);
997 CFReleaseNull(peerID
);
1000 case kSecXPCOpSyncWithKVSPeerIDOnly
:
1001 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1002 CFStringRef peerID
= SecXPCDictionaryCopyString(event
, kSecXPCKeyDeviceID
, &error
);
1003 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRequestSyncWithPeerOverKVSUsingIDOnly_Server(peerID
, &error
));
1004 CFReleaseNull(peerID
);
1007 case kSecXPCOpPingTest
:
1008 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1009 CFStringRef message
= SecXPCDictionaryCopyString(event
, kSecXPCKeySendIDSMessage
, &error
);
1010 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSPingTest_Server(message
, &error
));
1011 CFReleaseNull(message
);
1014 case kSecXPCOpIDSDeviceID
:
1015 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1016 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCIDSDeviceIDIsAvailableTest_Server(&error
));
1019 case kSecXPCOpAccountSetToNew
:
1020 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1021 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCAccountSetToNew_Server(&error
));
1024 case kSecXPCOpResetToOffering
:
1025 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1026 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1027 SOSCCResetToOffering_Server(&error
));
1030 case kSecXPCOpResetToEmpty
:
1031 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1032 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1033 SOSCCResetToEmpty_Server(&error
));
1036 case kSecXPCOpRemoveThisDeviceFromCircle
:
1037 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1038 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1039 SOSCCRemoveThisDeviceFromCircle_Server(&error
));
1042 case kSecXPCOpRemovePeersFromCircle
:
1043 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1044 CFArrayRef applicants
= SecXPCDictionaryCopyPeerInfoArray(event
, kSecXPCKeyPeerInfoArray
, &error
);
1045 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1046 SOSCCRemovePeersFromCircle_Server(applicants
, &error
));
1047 CFReleaseNull(applicants
);
1050 case kSecXPCOpLoggedOutOfAccount
:
1051 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1052 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1053 SOSCCLoggedOutOfAccount_Server(&error
));
1056 case kSecXPCOpBailFromCircle
:
1057 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1058 uint64_t limit_in_seconds
= xpc_dictionary_get_uint64(event
, kSecXPCLimitInMinutes
);
1059 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1060 SOSCCBailFromCircle_Server(limit_in_seconds
, &error
));
1063 case kSecXPCOpAcceptApplicants
:
1064 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1065 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfoArray
);
1066 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1067 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1068 (applicants
&& SOSCCAcceptApplicants_Server(applicants
, &error
)));
1069 CFReleaseSafe(applicants
);
1072 case kSecXPCOpRejectApplicants
:
1073 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1074 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfoArray
);
1075 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1076 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1077 (applicants
&& SOSCCRejectApplicants_Server(applicants
, &error
)));
1078 CFReleaseSafe(applicants
);
1081 case kSecXPCOpSetNewPublicBackupKey
:
1083 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1084 CFDataRef publicBackupKey
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNewPublicBackupKey
, &error
);
1085 SOSPeerInfoRef peerInfo
= SOSCCSetNewPublicBackupKey_Server(publicBackupKey
, &error
);
1086 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1087 CFReleaseNull(peerInfo
);
1089 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1090 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1091 xpc_release(xpc_object
);
1093 CFReleaseNull(peerInfoData
);
1094 CFReleaseSafe(publicBackupKey
);
1099 case kSecXPCOpRegisterRecoveryPublicKey
:
1101 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1102 CFDataRef recovery_key
= SecXPCDictionaryCopyData(event
, kSecXPCKeyRecoveryPublicKey
, &error
);
1104 CFDataRef nullData
= CFDataCreate(kCFAllocatorDefault
, &zero
, 1); // token we send if we really wanted to send NULL
1105 if(CFEqual(recovery_key
, nullData
)) {
1106 CFReleaseNull(recovery_key
);
1108 CFReleaseNull(nullData
);
1109 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRegisterRecoveryPublicKey_Server(recovery_key
, &error
));
1110 CFReleaseNull(recovery_key
);
1114 case kSecXPCOpGetRecoveryPublicKey
:
1116 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1117 xpc_object_t xpc_recovery_object
= NULL
;
1118 CFDataRef recovery
= SOSCCCopyRecoveryPublicKey(&error
);
1120 xpc_recovery_object
= _CFXPCCreateXPCObjectFromCFObject(recovery
);
1122 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_recovery_object
);
1123 CFReleaseNull(recovery
);
1127 case kSecXPCOpSetBagForAllSlices
:
1129 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1130 CFDataRef backupSlice
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
1131 bool includeV0
= xpc_dictionary_get_bool(event
, kSecXPCKeyIncludeV0
);
1132 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, backupSlice
&& SOSCCRegisterSingleRecoverySecret_Server(backupSlice
, includeV0
, &error
));
1133 CFReleaseSafe(backupSlice
);
1137 case kSecXPCOpCopyApplicantPeerInfo
:
1138 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1139 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1140 SOSCCCopyApplicantPeerInfo_Server(&error
),
1144 case kSecXPCOpCopyValidPeerPeerInfo
:
1145 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1146 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1147 SOSCCCopyValidPeerPeerInfo_Server(&error
),
1151 case kSecXPCOpValidateUserPublic
:
1152 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1153 bool trusted
= SOSCCValidateUserPublic_Server(&error
);
1154 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, trusted
);
1157 case kSecXPCOpCopyNotValidPeerPeerInfo
:
1158 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1159 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1160 SOSCCCopyNotValidPeerPeerInfo_Server(&error
),
1164 case kSecXPCOpCopyGenerationPeerInfo
:
1165 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1166 xpc_dictionary_set_and_consume_CFArray(replyMessage
, kSecXPCKeyResult
,
1167 SOSCCCopyGenerationPeerInfo_Server(&error
));
1170 case kSecXPCOpCopyRetirementPeerInfo
:
1171 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1172 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1173 SOSCCCopyRetirementPeerInfo_Server(&error
),
1177 case kSecXPCOpCopyViewUnawarePeerInfo
:
1178 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1179 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1180 SOSCCCopyViewUnawarePeerInfo_Server(&error
),
1184 case kSecXPCOpCopyAccountData
:
1186 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1187 xpc_object_t xpc_account_object
= NULL
;
1188 CFDataRef accountData
= SOSCCCopyAccountState_Server(&error
);
1190 xpc_account_object
= _CFXPCCreateXPCObjectFromCFObject(accountData
);
1192 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_account_object
);
1193 CFReleaseNull(accountData
);
1197 case kSecXPCOpDeleteAccountData
:
1199 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1200 bool status
= SOSCCDeleteAccountState_Server(&error
);
1201 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, status
);
1205 case kSecXPCOpCopyEngineData
:
1207 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1209 xpc_object_t xpc_engine_object
= NULL
;
1210 CFDataRef engineData
= SOSCCCopyEngineData_Server(&error
);
1212 xpc_engine_object
= _CFXPCCreateXPCObjectFromCFObject(engineData
);
1214 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_engine_object
);
1215 CFReleaseNull(engineData
);
1220 case kSecXPCOpDeleteEngineData
:
1222 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1223 bool status
= SOSCCDeleteEngineState_Server(&error
);
1224 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, status
);
1228 case kSecXPCOpCopyEngineState
:
1230 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1231 CFArrayRef array
= SOSCCCopyEngineState_Server(&error
);
1232 CFDataRef derData
= NULL
;
1234 require_quiet(array
, done
);
1235 derData
= CFPropertyListCreateDERData(kCFAllocatorDefault
, array
, &error
);
1237 require_quiet(derData
, done
);
1238 xpc_dictionary_set_data(replyMessage
, kSecXPCKeyResult
, CFDataGetBytePtr(derData
), CFDataGetLength(derData
));
1240 CFReleaseNull(derData
);
1241 CFReleaseNull(array
);
1245 case kSecXPCOpCopyPeerPeerInfo
:
1246 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1247 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1248 SOSCCCopyPeerPeerInfo_Server(&error
),
1252 case kSecXPCOpCopyConcurringPeerPeerInfo
:
1253 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1254 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1255 SOSCCCopyConcurringPeerPeerInfo_Server(&error
),
1259 case kSecXPCOpCopyMyPeerInfo
:
1260 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1261 SOSPeerInfoRef peerInfo
= SOSCCCopyMyPeerInfo_Server(&error
);
1262 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1263 CFReleaseNull(peerInfo
);
1265 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1266 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1267 xpc_release(xpc_object
);
1269 CFReleaseNull(peerInfoData
);
1272 case kSecXPCOpGetLastDepartureReason
:
1273 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1274 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1275 SOSCCGetLastDepartureReason_Server(&error
));
1278 case kSecXPCOpSetLastDepartureReason
:
1279 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1280 int32_t reason
= (int32_t) xpc_dictionary_get_int64(event
, kSecXPCKeyReason
);
1281 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1282 SOSCCSetLastDepartureReason_Server(reason
, &error
));
1285 case kSecXPCOpProcessSyncWithPeers
:
1286 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1287 CFSetRef peers
= SecXPCDictionaryCopySet(event
, kSecXPCKeySet
, &error
);
1288 CFSetRef backupPeers
= SecXPCDictionaryCopySet(event
, kSecXPCKeySet2
, &error
);
1289 if (peers
&& backupPeers
) {
1290 CFSetRef result
= SOSCCProcessSyncWithPeers_Server(peers
, backupPeers
, &error
);
1292 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
1294 CFReleaseNull(result
);
1296 CFReleaseNull(peers
);
1297 CFReleaseNull(backupPeers
);
1300 case kSecXPCOpProcessSyncWithAllPeers
:
1301 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1302 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1303 SOSCCProcessSyncWithAllPeers_Server(&error
));
1306 case soscc_EnsurePeerRegistration_id
:
1307 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1308 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1309 SOSCCProcessEnsurePeerRegistration_Server(&error
));
1312 case kSecXPCOpCopyIncompatibilityInfo
:
1313 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1314 CFStringRef iis
= SOSCCCopyIncompatibilityInfo_Server(&error
);
1315 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, iis
, &error
);
1319 case kSecXPCOpRollKeys
:
1321 bool force
= xpc_dictionary_get_bool(event
, "force");
1322 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1323 _SecServerRollKeys(force
, &client
, &error
));
1326 case kSecXPCOpWaitForInitialSync
:
1327 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1328 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1329 SOSCCWaitForInitialSync_Server(&error
));
1333 case kSecXPCOpCopyYetToSyncViews
:
1334 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1335 CFArrayRef array
= SOSCCCopyYetToSyncViewsList_Server(&error
);
1337 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(array
);
1338 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_array
);
1339 xpc_release(xpc_array
);
1341 CFReleaseNull(array
);
1344 case kSecXPCOpSetEscrowRecord
:
1345 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1346 CFStringRef escrow_label
= SecXPCDictionaryCopyString(event
, kSecXPCKeyEscrowLabel
, &error
);
1347 uint64_t tries
= xpc_dictionary_get_int64(event
, kSecXPCKeyTriesLabel
);
1349 bool result
= SOSCCSetEscrowRecord_Server(escrow_label
, tries
, &error
);
1351 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1353 CFReleaseNull(escrow_label
);
1356 case kSecXPCOpGetEscrowRecord
:
1357 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1358 CFDictionaryRef record
= SOSCCCopyEscrowRecord_Server(&error
);
1360 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(record
);
1361 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1362 xpc_release(xpc_dictionary
);
1364 CFReleaseNull(record
);
1367 case kSecXPCOpCopyBackupInformation
:
1368 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1369 CFDictionaryRef record
= SOSCCCopyBackupInformation_Server(&error
);
1371 xpc_object_t xpc_dictionary
= _CFXPCCreateXPCObjectFromCFObject(record
);
1372 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_dictionary
);
1373 xpc_release(xpc_dictionary
);
1375 CFReleaseNull(record
);
1379 case kSecXPCOpCheckPeerAvailability
:
1380 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1381 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCCheckPeerAvailability_Server(&error
));
1386 case kSecXPCOpIsThisDeviceLastBackup
:
1387 if (EntitlementPresentOrWhine(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1388 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCkSecXPCOpIsThisDeviceLastBackup_Server(&error
));
1391 case kSecXPCOpPeersHaveViewsEnabled
:
1393 CFArrayRef viewSet
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyArray
, &error
);
1395 CFBooleanRef result
= SOSCCPeersHaveViewsEnabled_Server(viewSet
, &error
);
1396 if (result
!= NULL
) {
1397 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
!= kCFBooleanFalse
);
1400 CFReleaseNull(viewSet
);
1404 case kSecXPCOpWhoAmI
:
1407 xpc_dictionary_set_data(replyMessage
, "musr", CFDataGetBytePtr(client
.musr
), CFDataGetLength(client
.musr
));
1408 xpc_dictionary_set_bool(replyMessage
, "system-keychain", client
.allowSystemKeychain
);
1409 xpc_dictionary_set_bool(replyMessage
, "syncbubble-keychain", client
.allowSyncBubbleKeychain
);
1410 xpc_dictionary_set_bool(replyMessage
, "network-extension", client
.isNetworkExtension
);
1411 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1414 case kSecXPCOpTransmogrifyToSyncBubble
:
1416 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainSyncBubble
, &error
)) {
1418 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1419 CFArrayRef services
= SecXPCDictionaryCopyArray(event
, "services", &error
);
1421 if (uid
&& services
) {
1422 res
= _SecServerTransmogrifyToSyncBubble(services
, uid
, &client
, &error
);
1424 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1425 CFReleaseNull(services
);
1427 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1432 case kSecXPCOpTransmogrifyToSystemKeychain
:
1434 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
)) {
1436 bool res
= _SecServerTransmogrifyToSystemKeychain(&client
, &error
);
1437 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1439 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1445 case kSecXPCOpDeleteUserView
:
1447 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
)) {
1450 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1452 res
= _SecServerDeleteMUSERViews(&client
, uid
, &error
);
1455 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1460 case kSecXPCOpWrapToBackupSliceKeyBagForView
:
1462 CFStringRef viewname
= SecXPCDictionaryCopyString(event
, kSecXPCKeyViewName
, &error
);
1464 CFDataRef plaintext
= SecXPCDictionaryCopyData(event
, kSecXPCData
, &error
);
1466 CFDataRef ciphertext
= NULL
;
1467 CFDataRef bskbEncoded
= NULL
;
1469 bool result
= SOSWrapToBackupSliceKeyBagForView_Server(viewname
, plaintext
, &ciphertext
, &bskbEncoded
, &error
);
1470 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1472 if(!error
&& result
) {
1474 xpc_dictionary_set_data(replyMessage
, kSecXPCData
, CFDataGetBytePtr(ciphertext
), CFDataGetLength(ciphertext
));
1477 xpc_dictionary_set_data(replyMessage
, kSecXPCKeyKeybag
, CFDataGetBytePtr(bskbEncoded
), CFDataGetLength(bskbEncoded
));
1480 CFReleaseSafe(ciphertext
);
1481 CFReleaseSafe(bskbEncoded
);
1483 CFReleaseSafe(plaintext
);
1485 CFReleaseNull(viewname
);
1488 case kSecXPCOpCopyApplication
:
1489 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1490 SOSPeerInfoRef peerInfo
= SOSCCCopyApplication_Server(&error
);
1491 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1492 CFReleaseNull(peerInfo
);
1494 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1495 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1496 xpc_release(xpc_object
);
1498 CFReleaseNull(peerInfoData
);
1501 case kSecXPCOpCopyCircleJoiningBlob
:
1502 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1503 CFDataRef appBlob
= SecXPCDictionaryCopyCFDataRef(event
, kSecXPCData
, &error
);
1504 SOSPeerInfoRef applicant
= SOSPeerInfoCreateFromData(kCFAllocatorDefault
, &error
, appBlob
);
1505 CFDataRef pbblob
= SOSCCCopyCircleJoiningBlob_Server(applicant
, &error
);
1507 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(pbblob
);
1508 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1509 xpc_release(xpc_object
);
1511 CFReleaseNull(pbblob
);
1512 CFReleaseNull(applicant
);
1513 CFReleaseNull(appBlob
);
1516 case kSecXPCOpCopyInitialSyncBlob
:
1517 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1518 CFDataRef initialblob
= SOSCCCopyInitialSyncData_Server(&error
);
1520 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(initialblob
);
1521 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1522 xpc_release(xpc_object
);
1524 CFReleaseNull(initialblob
);
1527 case kSecXPCOpJoinWithCircleJoiningBlob
:
1528 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1529 CFDataRef joiningBlob
= SecXPCDictionaryCopyCFDataRef(event
, kSecXPCData
, &error
);
1530 uint64_t version
= xpc_dictionary_get_uint64(event
, kSecXPCVersion
);
1531 bool retval
= SOSCCJoinWithCircleJoiningBlob_Server(joiningBlob
, (PiggyBackProtocolVersion
) version
, &error
);
1532 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1533 CFReleaseNull(joiningBlob
);
1537 case kSecXPCOpKVSKeyCleanup
:
1538 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1539 bool retval
= SOSCCCleanupKVSKeys_Server(&error
);
1540 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1543 case kSecXPCOpPopulateKVS
:
1544 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1545 bool retval
= SOSCCTestPopulateKVSWithBadKeys_Server(&error
);
1546 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1549 case kSecXPCOpMessageFromPeerIsPending
:
1551 SOSPeerInfoRef peer
= SecXPCDictionaryCopyPeerInfo(event
, kSecXPCKeyPeerInfo
, &error
);
1553 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1554 SOSCCMessageFromPeerIsPending_Server(peer
, &error
));
1556 CFReleaseNull(peer
);
1559 case kSecXPCOpSendToPeerIsPending
:
1561 SOSPeerInfoRef peer
= SecXPCDictionaryCopyPeerInfo(event
, kSecXPCKeyPeerInfo
, &error
);
1563 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1564 SOSCCSendToPeerIsPending(peer
, &error
));
1566 CFReleaseNull(peer
);
1569 case sec_delete_items_with_access_groups_id
:
1571 bool retval
= false;
1572 #if TARGET_OS_IPHONE
1573 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateUninstallDeletion
, &error
)) {
1574 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyAccessGroups
, &error
);
1577 retval
= _SecItemServerDeleteAllWithAccessGroups(accessGroups
, &client
, &error
);
1579 CFReleaseNull(accessGroups
);
1582 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1585 case sec_item_copy_parent_certificates_id
:
1587 CFArrayRef results
= NULL
;
1588 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateCertificateAllAccess
, &error
)) {
1589 CFDataRef issuer
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNormalizedIssuer
, &error
);
1590 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyAccessGroups
, &error
);
1591 if (issuer
&& accessGroups
) {
1592 results
= _SecItemCopyParentCertificates(issuer
, accessGroups
, &error
);
1594 CFReleaseNull(issuer
);
1595 CFReleaseNull(accessGroups
);
1597 SecXPCDictionarySetPListOptional(replyMessage
, kSecXPCKeyResult
, results
, &error
);
1598 CFReleaseNull(results
);
1601 case sec_item_certificate_exists_id
:
1603 bool result
= false;
1604 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateCertificateAllAccess
, &error
)) {
1605 CFDataRef issuer
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNormalizedIssuer
, &error
);
1606 CFDataRef serialNum
= SecXPCDictionaryCopyData(event
, kSecXPCKeySerialNumber
, &error
);
1607 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyAccessGroups
, &error
);
1608 if (issuer
&& serialNum
&& accessGroups
) {
1609 result
= _SecItemCertificateExists(issuer
, serialNum
, accessGroups
, &error
);
1611 CFReleaseNull(issuer
);
1612 CFReleaseNull(serialNum
);
1613 CFReleaseNull(accessGroups
);
1615 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1618 case kSecXPCOpBackupKeybagAdd
: {
1619 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementBackupTableOperations
, &error
)) {
1620 CFDataRef keybag
= NULL
, passcode
= NULL
;
1621 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
1622 CFDataRef identifier
= NULL
;
1623 CFDataRef pathinfo
= NULL
; // really a CFURLRef
1624 bool added
= _SecServerBackupKeybagAdd(&client
, passcode
, &identifier
, &pathinfo
, &error
);
1626 added
&= SecXPCDictionarySetDataOptional(replyMessage
, kSecXPCKeyBackupKeybagIdentifier
, identifier
, &error
);
1627 added
&= SecXPCDictionarySetDataOptional(replyMessage
, kSecXPCKeyBackupKeybagPath
, pathinfo
, &error
);
1628 SecXPCDictionarySetBool(replyMessage
, kSecXPCKeyResult
, added
, NULL
);
1630 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1633 CFReleaseSafe(passcode
);
1634 CFReleaseSafe(keybag
);
1638 case kSecXPCOpBackupKeybagDelete
: {
1640 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementBackupTableOperations
, &error
)) {
1641 bool deleted
= false;
1642 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
1644 CFTypeRef matchLimit
= CFDictionaryGetValue(query
, kSecMatchLimit
);
1645 bool deleteAll
= matchLimit
&& CFEqualSafe(matchLimit
, kSecMatchLimitAll
);
1647 if (deleteAll
&& !EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementBackupTableOperationsDeleteAll
, &error
)) {
1648 // require special entitlement to delete all backup keybags
1650 CFMutableDictionaryRef attributes
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, query
);
1651 CFStringRef requestedAgrp
= CFDictionaryGetValue(attributes
, kSecAttrAccessGroup
);
1652 CFStringRef resolvedAgrp
= NULL
;
1654 CFDictionarySetValue(attributes
, kSecAttrMultiUser
, client
.musr
);
1656 if (extractAccessGroup(&client
, requestedAgrp
, &resolvedAgrp
, &error
)) {
1658 CFDictionarySetValue(attributes
, kSecAttrAccessGroup
, resolvedAgrp
);
1660 deleted
= _SecServerBackupKeybagDelete(attributes
, deleteAll
, &error
);
1662 CFReleaseNull(attributes
);
1665 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, deleted
);
1666 CFReleaseNull(query
);
1670 case kSecXPCOpKeychainControlEndpoint
: {
1671 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainControl
, &error
)) {
1672 xpc_endpoint_t endpoint
= SecServerCreateKeychainControlEndpoint();
1674 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyEndpoint
, endpoint
);
1675 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1676 xpc_release(endpoint
);
1678 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1689 if(SecErrorGetOSStatus(error
) == errSecItemNotFound
|| isSOSErrorCoded(error
, kSOSErrorPublicKeyAbsent
))
1690 secdebug("ipc", "%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1691 else if (SecErrorGetOSStatus(error
) == errSecAuthNeeded
)
1692 secwarning("Authentication is needed %@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1694 secerror("%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1696 xpcError
= SecCreateXPCObjectWithCFError(error
);
1698 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyError
, xpcError
);
1700 } else if (replyMessage
) {
1701 secdebug("ipc", "%@ %@ responding %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyMessage
);
1704 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, &error
, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event
);
1705 secerror("%@: returning error: %@", client
.task
, error
);
1706 xpcError
= SecCreateXPCObjectWithCFError(error
);
1707 replyMessage
= xpc_create_reply_with_format(event
, "{%string: %value}", kSecXPCKeyError
, xpcError
);
1711 xpc_connection_send_message(connection
, replyMessage
);
1712 xpc_release(replyMessage
);
1715 xpc_release(xpcError
);
1716 #if TARGET_OS_IPHONE
1717 pthread_setspecific(taskThreadKey
, NULL
);
1719 CFReleaseSafe(error
);
1720 CFReleaseSafe(client
.accessGroups
);
1721 CFReleaseSafe(client
.musr
);
1722 CFReleaseSafe(client
.task
);
1723 CFReleaseSafe(domains
);
1724 CFReleaseSafe(clientAuditToken
);
1727 static void securityd_xpc_init(const char *service_name
)
1729 #if TARGET_OS_IPHONE
1730 pthread_key_create(&taskThreadKey
, NULL
);
1731 SecTaskDiagnoseEntitlements
= secTaskDiagnoseEntitlements
;
1734 secdebug("serverxpc", "start");
1735 xpc_connection_t listener
= xpc_connection_create_mach_service(service_name
, NULL
, XPC_CONNECTION_MACH_SERVICE_LISTENER
);
1737 seccritical("security failed to register xpc listener for %s, exiting", service_name
);
1741 xpc_connection_set_event_handler(listener
, ^(xpc_object_t connection
) {
1742 if (xpc_get_type(connection
) == XPC_TYPE_CONNECTION
) {
1743 xpc_connection_set_event_handler(connection
, ^(xpc_object_t event
) {
1744 if (xpc_get_type(event
) == XPC_TYPE_DICTIONARY
) {
1745 xpc_retain(connection
);
1747 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
1748 securityd_xpc_dictionary_handler(connection
, event
);
1750 xpc_release(connection
);
1754 xpc_connection_resume(connection
);
1757 xpc_connection_resume(listener
);
1760 xpc_activity_register("com.apple.securityd.daily", XPC_ACTIVITY_CHECK_IN
, ^(xpc_activity_t activity
) {
1761 xpc_activity_state_t activityState
= xpc_activity_get_state(activity
);
1762 if (activityState
== XPC_ACTIVITY_STATE_RUN
) {
1763 SecCKKS24hrNotification();
1770 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1772 #if TARGET_OS_EMBEDDED
1773 static void securityd_soscc_lock_hack() {
1774 dispatch_queue_t soscc_lock_queue
= dispatch_queue_create("soscc_lock_queue", DISPATCH_QUEUE_PRIORITY_DEFAULT
);
1777 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1778 // FIXME: securityd isn't currently registering for any other notifyd events. If/when it does,
1779 // this code will need to be generalized / migrated away from just this specific purpose.
1780 xpc_set_event_stream_handler("com.apple.notifyd.matching", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH
, 0), ^(xpc_object_t object
) {
1781 char *event_description
= xpc_copy_description(object
);
1782 secnotice("events", "%s", event_description
);
1783 free(event_description
);
1786 secnotice("lockassertion", "notify_register_dispatch(kSOSCCHoldLockForInitialSync)");
1787 notify_register_dispatch(kSOSCCHoldLockForInitialSync
, &soscc_tok
, soscc_lock_queue
, ^(int token __unused
) {
1788 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync: grabbing the lock");
1789 CFErrorRef error
= NULL
;
1791 uint64_t one_minute
= 60ull;
1792 if(SecAKSLockUserKeybag(one_minute
, &error
)){
1793 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1794 xpc_transaction_begin();
1796 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, one_minute
*NSEC_PER_SEC
), soscc_lock_queue
, ^{
1797 CFErrorRef localError
= NULL
;
1798 if(!SecAKSUnLockUserKeybag(&localError
))
1799 secerror("failed to unlock: %@", localError
);
1800 CFReleaseNull(localError
);
1801 xpc_transaction_end();
1804 secerror("Failed to take device lock assertion: %@", error
);
1806 CFReleaseNull(error
);
1807 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync => done");
1817 static char homeDir
[PATH_MAX
] = {};
1819 if (homeDir
[0] == '\0') {
1820 struct passwd
* pwd
= getpwuid(getuid());
1824 if (realpath(pwd
->pw_dir
, homeDir
) == NULL
) {
1825 strlcpy(homeDir
, pwd
->pw_dir
, sizeof(homeDir
));
1833 int main(int argc
, char *argv
[])
1835 char *wait4debugger
= getenv("WAIT4DEBUGGER");
1836 if (wait4debugger
&& !strcasecmp("YES", wait4debugger
)) {
1837 seccritical("SIGSTOPing self, awaiting debugger");
1838 kill(getpid(), SIGSTOP
);
1839 seccritical("Again, for good luck (or bad debuggers)");
1840 kill(getpid(), SIGSTOP
);
1843 /* <rdar://problem/15792007> Users with network home folders are unable to use/save password for Mail/Cal/Contacts/websites
1844 Secd doesn't realize DB connections get invalidated when network home directory users logout
1845 and their home gets unmounted. Exit secd, start fresh when user logs back in.
1848 int sessionstatechanged_tok
;
1849 notify_register_dispatch(kSA_SessionStateChangedNotification
, &sessionstatechanged_tok
, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^(int token __unused
) {
1850 // we could be a process running as root.
1851 // However, since root never logs out this isn't an issue.
1852 if (SASSessionStateForUser(getuid()) == kSA_state_loggingout_pointofnoreturn
) {
1853 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, 3ull*NSEC_PER_SEC
), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
1854 xpc_transaction_exit_clean();
1861 #define SECD_PROFILE_NAME "com.apple.secd"
1862 const char *homedir
= homedirPath();
1863 if (homedir
== NULL
)
1864 errx(1, "failed to get home directory for secd");
1866 char *errorbuf
= NULL
;
1867 const char *sandbox_params
[] = {
1873 rc
= sandbox_init_with_parameters(SECD_PROFILE_NAME
, SANDBOX_NAMED
, sandbox_params
, &errorbuf
);
1875 err(1, "Failed to process in a sandbox: %d %s", rc
, errorbuf
);
1876 #endif /* TARGET_OS_OSX */
1878 const char *serviceName
= kSecuritydXPCServiceName
;
1879 /* setup SQDLite before some other component have a chance to create a database connection */
1880 _SecDbServerSetup();
1882 securityd_init_server();
1883 securityd_xpc_init(serviceName
);
1885 SecCreateSecuritydXPCServer();
1886 CKKSControlServerInitialize();
1887 SOSControlServerInitialize();
1888 OctagonControlServerInitialize();
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: */