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@
26 #undef SECUREOBJECTSYNC
27 #undef SHAREDWEBCREDENTIALS
30 #include <os/transaction_private.h>
31 #include <os/variant_private.h>
33 #include "keychain/SecureObjectSync/SOSPeerInfoDER.h"
34 #include <Security/SecureObjectSync/SOSCloudCircle.h>
35 #include <Security/SecureObjectSync/SOSCloudCircleInternal.h>
36 #include "keychain/SecureObjectSync/SOSInternal.h"
37 #include "keychain/SecureObjectSync/SOSPeerInfoCollections.h"
38 #include "keychain/SecureObjectSync/SOSControlServer.h"
39 #include <Security/SecBase.h>
40 #include <Security/SecBasePriv.h>
41 #include <Security/SecCertificatePriv.h>
42 #include <Security/SecEntitlements.h>
43 #include <Security/SecInternal.h>
44 #include <Security/SecItem.h>
45 #include <Security/SecItemPriv.h>
46 #include <Security/SecPolicy.h>
47 #include <Security/SecPolicyInternal.h>
48 #include <Security/SecTask.h>
49 #include <Security/SecTrustInternal.h>
50 #include <Security/SecuritydXPC.h>
51 #include "trust/trustd/OTATrustUtilities.h"
52 #include "keychain/securityd/SOSCloudCircleServer.h"
53 #include "keychain/securityd/SecItemBackupServer.h"
54 #include "keychain/securityd/SecItemServer.h"
55 #include "keychain/securityd/SecLogSettingsServer.h"
56 #include "keychain/securityd/SecOTRRemote.h"
57 #include "trust/trustd/SecTrustServer.h"
58 #include "trust/trustd/SecTrustStoreServer.h"
59 #include "keychain/securityd/iCloudTrace.h"
60 #include "keychain/securityd/spi.h"
61 #include <utilities/SecCFError.h>
62 #include <utilities/SecCFWrappers.h>
63 #include <utilities/SecDb.h>
64 #include <utilities/SecIOFormat.h>
65 #include <utilities/SecXPCError.h>
66 #include <utilities/debugging.h>
67 #include <utilities/SecInternalReleasePriv.h>
68 #include <utilities/der_plist_internal.h>
69 #include <utilities/der_plist.h>
70 #include "trust/trustd/personalization.h"
71 #include "trust/trustd/SecPinningDb.h"
72 #include "keychain/securityd/SFKeychainControlManager.h"
74 #include <keychain/ckks/CKKS.h>
75 #include <keychain/ckks/CKKSControlServer.h>
76 #include "keychain/ot/OctagonControlServer.h"
78 #include "keychain/securityd/SFKeychainServer.h"
80 #include "keychain/securityd/PolicyReporter.h"
83 #include <AssertMacros.h>
84 #include <CoreFoundation/CFXPCBridge.h>
85 #include <CoreFoundation/CoreFoundation.h>
86 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
89 #include <Security/SecTaskPriv.h>
90 #include <login/SessionAgentStatusCom.h>
93 #include <bsm/libbsm.h>
94 #include <ipc/securityd_client.h>
95 #include <libkern/OSAtomic.h>
96 #include <mach/mach.h>
97 #include <mach/message.h>
100 #include <sys/queue.h>
101 #include <sys/sysctl.h>
103 #include <xpc/private.h>
106 #include <ipc/server_security_helpers.h>
107 #include <ipc/server_entitlement_helpers.h>
109 #include "keychain/ot/OT.h"
110 #include "keychain/escrowrequest/EscrowRequestXPCServer.h"
111 #include "keychain/escrowrequest/EscrowRequestServerHelpers.h"
125 _xpc_dictionary_copy_CFString(xpc_object_t xdict
, const char *key
)
127 CFStringRef result
= NULL
;
128 const char *str
= xpc_dictionary_get_string(xdict
, key
);
130 result
= CFStringCreateWithCString(kCFAllocatorDefault
, str
, kCFStringEncodingUTF8
);
137 _xpc_dictionary_copy_CFDataNoCopy(xpc_object_t xdict
, const char *key
)
139 CFDataRef result
= NULL
;
141 const void *ptr
= xpc_dictionary_get_data(xdict
, key
, &len
);
143 result
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, ptr
, len
, kCFAllocatorNull
);
148 static void with_label_and_password(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
)) {
149 CFStringRef user_label
= _xpc_dictionary_copy_CFString(message
, kSecXPCKeyUserLabel
);
150 CFDataRef user_password
= _xpc_dictionary_copy_CFDataNoCopy(message
, kSecXPCKeyUserPassword
);
152 if (user_label
!= NULL
&& user_password
!= NULL
) {
153 action(user_label
, user_password
);
156 CFReleaseNull(user_label
);
157 CFReleaseNull(user_password
);
160 static void with_label_and_password_and_dsid(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
, CFStringRef dsid
)) {
161 CFStringRef user_label
= _xpc_dictionary_copy_CFString(message
, kSecXPCKeyUserLabel
);
162 CFDataRef user_password
= _xpc_dictionary_copy_CFDataNoCopy(message
, kSecXPCKeyUserPassword
);
163 CFStringRef dsid
= _xpc_dictionary_copy_CFString(message
, kSecXPCKeyDSID
);
165 /* dsid is optional */
166 if (user_label
!= NULL
&& user_password
!= NULL
) {
167 action(user_label
, user_password
, dsid
);
170 CFReleaseNull(user_label
);
171 CFReleaseNull(user_password
);
175 static void with_view_and_action(xpc_object_t message
, void (^action
)(CFStringRef view_name
, uint64_t view_action_code
)) {
176 CFStringRef view
= _xpc_dictionary_copy_CFString(message
, kSecXPCKeyViewName
);
177 const int64_t number
= xpc_dictionary_get_int64(message
, kSecXPCKeyViewActionCode
);
180 action(view
, number
);
186 static CFArrayRef
SecXPCDictionaryCopyPeerInfoArray(xpc_object_t dictionary
, const char *key
, CFErrorRef
*error
) {
187 return CreateArrayOfPeerInfoWithXPCObject(xpc_dictionary_get_value(dictionary
, key
), error
);
190 static CFDataRef
SecXPCDictionaryCopyCFDataRef(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
191 CFDataRef retval
= NULL
;
192 const uint8_t *bytes
= NULL
;
195 bytes
= xpc_dictionary_get_data(message
, key
, &len
);
196 require_action_quiet(bytes
, errOut
, SOSCreateError(kSOSErrorBadKey
, CFSTR("missing CFDataRef info"), NULL
, error
));
197 retval
= CFDataCreate(NULL
, bytes
, len
);
198 require_action_quiet(retval
, errOut
, SOSCreateError(kSOSErrorBadKey
, CFSTR("could not allocate CFDataRef info"), NULL
, error
));
203 static CFSetRef
CreateCFSetRefFromXPCObject(xpc_object_t xpcSetDER
, CFErrorRef
* error
) {
204 CFSetRef retval
= NULL
;
205 require_action_quiet(xpcSetDER
, errOut
, SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedNull
, sSecXPCErrorDomain
, NULL
, error
, NULL
, CFSTR("Unexpected Null Set to decode")));
207 require_action_quiet(xpc_get_type(xpcSetDER
) == XPC_TYPE_DATA
, errOut
, SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, error
, NULL
, CFSTR("xpcSetDER not data, got %@"), xpcSetDER
));
209 const uint8_t* der
= xpc_data_get_bytes_ptr(xpcSetDER
);
210 const uint8_t* der_end
= der
+ xpc_data_get_length(xpcSetDER
);
211 der
= der_decode_set(kCFAllocatorDefault
, kCFPropertyListMutableContainersAndLeaves
, &retval
, error
, der
, der_end
);
212 if (der
!= der_end
) {
213 SecError(errSecDecode
, error
, CFSTR("trailing garbage at end of SecAccessControl data"));
218 CFReleaseNull(retval
);
222 static SOSPeerInfoRef
SecXPCDictionaryCopyPeerInfo(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
224 const uint8_t *der
= xpc_dictionary_get_data(message
, key
, &length
);
226 return SecRequirementError(der
!= NULL
, error
, CFSTR("No data for key %s"), key
) ? SOSPeerInfoCreateFromDER(kCFAllocatorDefault
, error
, &der
, der
+ length
) : NULL
;
229 static CFSetRef
SecXPCSetCreateFromXPCDictionaryElement(xpc_object_t event
, const char *key
) {
230 CFErrorRef error
= NULL
;
231 xpc_object_t object
= xpc_dictionary_get_value(event
, key
);
232 CFSetRef retval
= NULL
;
233 if(object
) retval
= CreateCFSetRefFromXPCObject(object
, &error
);
234 CFReleaseNull(error
);
239 void xpc_dictionary_set_and_consume_CFArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
) {
241 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(cf_array
);
242 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
243 xpc_release(xpc_array
);
245 CFReleaseNull(cf_array
);
249 bool xpc_dictionary_set_and_consume_PeerInfoArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
, CFErrorRef
*error
) {
252 xpc_object_t xpc_array
= CreateXPCObjectWithArrayOfPeerInfo(cf_array
, error
);
254 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
255 xpc_release(xpc_array
);
260 CFReleaseNull(cf_array
);
264 #endif /* SECUREOBJECTSYNC */
267 SecDataCopyMmapFileDescriptor(int fd
, void **mem
, size_t *size
, CFErrorRef
*error
)
270 if (fstat(fd
, &sb
) < 0) {
274 *size
= (size_t)sb
.st_size
;
275 if ((off_t
)*size
!= sb
.st_size
) {
279 *mem
= mmap(NULL
, *size
, PROT_READ
, MAP_SHARED
, fd
, 0);
280 if (*mem
== MAP_FAILED
) {
284 return CFDataCreateWithBytesNoCopy(NULL
, *mem
, *size
, kCFAllocatorNull
);
288 SecDataWriteFileDescriptor(int fd
, CFDataRef data
)
290 CFIndex count
= CFDataGetLength(data
);
291 const uint8_t *ptr
= CFDataGetBytePtr(data
);
292 bool writeResult
= false;
295 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
);
319 EntitlementAbsentOrFalse(uint64_t op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
321 if (SecTaskGetBooleanValueForEntitlement(clientTask
, entitlement
)) {
322 SecError(errSecNotAvailable
, error
, CFSTR("%@: %@ has entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
) op
), clientTask
, entitlement
);
328 static void securityd_xpc_dictionary_handler(const xpc_connection_t connection
, xpc_object_t event
) {
329 xpc_type_t type
= xpc_get_type(event
);
330 __block CFErrorRef error
= NULL
;
331 xpc_object_t xpcError
= NULL
;
332 xpc_object_t replyMessage
= NULL
;
333 CFDataRef clientAuditToken
= NULL
;
334 CFArrayRef domains
= NULL
;
335 SecurityClient client
= {
337 .accessGroups
= NULL
,
339 .uid
= xpc_connection_get_euid(connection
),
340 .allowSystemKeychain
= false,
341 .allowSyncBubbleKeychain
= false,
342 .isNetworkExtension
= false,
343 .canAccessNetworkExtensionAccessGroups
= false,
346 secdebug("serverxpc", "entering");
347 if (type
== XPC_TYPE_DICTIONARY
) {
348 // TODO: Find out what we're dispatching.
349 replyMessage
= xpc_dictionary_create_reply(event
);
351 uint64_t operation
= xpc_dictionary_get_uint64(event
, kSecXPCKeyOperation
);
353 audit_token_t auditToken
= {};
354 xpc_connection_get_audit_token(connection
, &auditToken
);
355 clientAuditToken
= CFDataCreate(kCFAllocatorDefault
, (const UInt8
*)&auditToken
, sizeof(auditToken
));
357 if (!fill_security_client(&client
, xpc_connection_get_euid(connection
), auditToken
)) {
358 CFReleaseNull(clientAuditToken
);
359 xpc_connection_send_message(connection
, replyMessage
);
360 xpc_release(replyMessage
);
365 if (operation
== sec_add_shared_web_credential_id
|| operation
== sec_copy_shared_web_credential_id
) {
366 domains
= SecTaskCopySharedWebCredentialDomains(client
.task
);
369 secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64
")", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), operation
);
373 case sec_item_add_id
:
375 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
376 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
378 // Check for any entitlement-required attributes
379 bool entitlementsCorrect
= true;
380 if(CFDictionaryGetValue(query
, kSecAttrDeriveSyncIDFromItemAttributes
) ||
381 CFDictionaryGetValue(query
, kSecAttrPCSPlaintextServiceIdentifier
) ||
382 CFDictionaryGetValue(query
, kSecAttrPCSPlaintextPublicKey
) ||
383 CFDictionaryGetValue(query
, kSecAttrPCSPlaintextPublicIdentity
)) {
384 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_add_id
, client
.task
, kSecEntitlementPrivateCKKSPlaintextFields
, &error
);
386 if (entitlementsCorrect
&& CFDictionaryGetValue(query
, kSecAttrSysBound
)) {
387 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_add_id
, client
.task
, kSecEntitlementPrivateSysBound
, &error
);
390 CFTypeRef result
= NULL
;
391 if(entitlementsCorrect
) {
392 if (_SecItemAdd(query
, &client
, &result
, &error
) && result
) {
393 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
394 CFReleaseNull(result
);
397 CFReleaseNull(query
);
402 case sec_item_copy_matching_id
:
404 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
405 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
407 CFTypeRef result
= NULL
;
408 if (_SecItemCopyMatching(query
, &client
, &result
, &error
) && result
) {
409 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
410 CFReleaseNull(result
);
412 CFReleaseNull(query
);
417 case sec_item_update_id
:
419 if (EntitlementAbsentOrFalse(sec_item_update_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
420 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
422 CFDictionaryRef attributesToUpdate
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyAttributesToUpdate
, &error
);
423 if (attributesToUpdate
) {
424 // Check for any entitlement-required attributes
425 bool entitlementsCorrect
= true;
426 if(CFDictionaryGetValue(query
, kSecAttrDeriveSyncIDFromItemAttributes
) ||
427 CFDictionaryGetValue(attributesToUpdate
, kSecAttrPCSPlaintextServiceIdentifier
) ||
428 CFDictionaryGetValue(attributesToUpdate
, kSecAttrPCSPlaintextPublicKey
) ||
429 CFDictionaryGetValue(attributesToUpdate
, kSecAttrPCSPlaintextPublicIdentity
)) {
430 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_update_id
, client
.task
, kSecEntitlementPrivateCKKSPlaintextFields
, &error
);
432 if (entitlementsCorrect
&& CFDictionaryGetValue(query
, kSecAttrSysBound
)) {
433 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_update_id
, client
.task
, kSecEntitlementPrivateSysBound
, &error
);
436 if(entitlementsCorrect
) {
437 bool result
= _SecItemUpdate(query
, attributesToUpdate
, &client
, &error
);
438 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
440 CFReleaseNull(attributesToUpdate
);
442 CFReleaseNull(query
);
447 case sec_item_delete_id
:
449 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
450 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
452 bool result
= _SecItemDelete(query
, &client
, &error
);
453 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
454 CFReleaseNull(query
);
459 case sec_item_update_token_items_id
:
461 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
462 CFStringRef tokenID
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
463 CFArrayRef attributes
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyQuery
, &error
);
465 bool result
= _SecItemUpdateTokenItems(tokenID
, attributes
, &client
, &error
);
466 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
468 CFReleaseNull(tokenID
);
469 CFReleaseNull(attributes
);
473 case sec_delete_all_id
:
477 /* buddy is temporary allowed to do this */
478 CFStringRef applicationIdentifier
= SecTaskCopyApplicationIdentifier(client
.task
);
479 bool isBuddy
= applicationIdentifier
&&
480 CFEqual(applicationIdentifier
, CFSTR("com.apple.purplebuddy"));
481 CFReleaseNull(applicationIdentifier
);
483 if (isBuddy
|| EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateDeleteAll
, &error
))
485 retval
= _SecItemDeleteAll(&error
);
488 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
491 case sec_keychain_backup_id
:
493 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
494 CFDataRef keybag
= NULL
, passcode
= NULL
;
495 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybag
, &error
)) {
496 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
497 bool emcs
= SecXPCDictionaryGetBool(event
, kSecXPCKeyEMCSBackup
, NULL
);
498 CFDataRef backup
= _SecServerKeychainCreateBackup(&client
, keybag
, passcode
, emcs
, &error
);
500 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
502 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, backup
, &error
);
504 bool writeResult
= SecDataWriteFileDescriptor(fd
, backup
);
508 SecError(errSecIO
, &error
, CFSTR("Failed to write backup file: %d"), errno
);
509 SecXPCDictionarySetBool(replyMessage
, kSecXPCKeyResult
, writeResult
, NULL
);
513 CFReleaseSafe(passcode
);
515 CFReleaseSafe(keybag
);
520 case sec_keychain_restore_id
:
522 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
523 CFDataRef backup
= NULL
;
527 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
529 backup
= SecDataCopyMmapFileDescriptor(fd
, &mem
, &size
, &error
);
531 backup
= SecXPCDictionaryCopyData(event
, kSecXPCKeyBackup
, &error
);
534 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
536 CFDataRef passcode
= NULL
;
537 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
538 bool result
= _SecServerKeychainRestore(backup
, &client
, keybag
, passcode
, &error
);
539 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
540 CFReleaseSafe(passcode
);
543 CFReleaseNull(keybag
);
545 CFReleaseNull(backup
);
554 case sec_keychain_backup_keybag_uuid_id
:
556 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
557 CFDataRef backup
= NULL
;
558 CFStringRef uuid
= NULL
;
562 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
564 backup
= SecDataCopyMmapFileDescriptor(fd
, &mem
, &size
, &error
);
566 uuid
= _SecServerBackupCopyUUID(backup
, &error
);
569 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, uuid
, &error
);
571 CFReleaseNull(backup
);
582 case sec_keychain_sync_update_message_id
:
584 CFDictionaryRef updates
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
586 CFArrayRef result
= _SecServerKeychainSyncUpdateMessage(updates
, &error
);
587 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
588 CFReleaseNull(result
);
590 CFReleaseNull(updates
);
593 case sec_keychain_backup_syncable_id
:
595 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
596 CFDictionaryRef oldbackup
= NULL
;
597 if (SecXPCDictionaryCopyDictionaryOptional(event
, kSecXPCKeyBackup
, &oldbackup
, &error
)) {
598 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
600 CFDataRef passcode
= NULL
;
601 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
602 CFDictionaryRef newbackup
= _SecServerBackupSyncable(oldbackup
, keybag
, passcode
, &error
);
604 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, newbackup
, &error
);
605 CFRelease(newbackup
);
607 CFReleaseSafe(passcode
);
609 CFReleaseNull(keybag
);
611 CFReleaseSafe(oldbackup
);
616 case sec_keychain_restore_syncable_id
:
618 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
619 CFDictionaryRef backup
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyBackup
, &error
);
621 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
623 CFDataRef passcode
= NULL
;
624 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
625 bool result
= _SecServerRestoreSyncable(backup
, keybag
, passcode
, &error
);
626 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
627 CFReleaseSafe(passcode
);
629 CFReleaseNull(keybag
);
631 CFReleaseNull(backup
);
636 case sec_item_backup_copy_names_id
:
638 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
639 CFArrayRef names
= SecServerItemBackupCopyNames(&error
);
640 SecXPCDictionarySetPListOptional(replyMessage
, kSecXPCKeyResult
, names
, &error
);
641 CFReleaseSafe(names
);
645 case sec_item_backup_handoff_fd_id
:
647 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
648 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
651 fd
= SecServerItemBackupHandoffFD(backupName
, &error
);
652 CFRelease(backupName
);
654 SecXPCDictionarySetFileDescriptor(replyMessage
, kSecXPCKeyResult
, fd
, &error
);
660 case sec_item_backup_set_confirmed_manifest_id
:
662 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
663 CFDataRef keybagDigest
= NULL
;
664 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybagDigest
, &error
)) {
665 CFDataRef manifest
= NULL
;
666 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &manifest
, &error
)) {
667 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
669 bool result
= SecServerItemBackupSetConfirmedManifest(backupName
, keybagDigest
, manifest
, &error
);
670 CFRelease(backupName
);
671 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
673 CFReleaseSafe(manifest
);
676 CFReleaseNull(keybagDigest
);
680 case sec_item_backup_restore_id
:
682 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
684 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
686 CFStringRef peerID
= NULL
;
687 if (SecXPCDictionaryCopyStringOptional(event
, kSecXPCKeyDigest
, &peerID
, &error
)) {
688 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
690 CFDataRef secret
= SecXPCDictionaryCopyData(event
, kSecXPCKeyUserPassword
, &error
);
692 CFDataRef backup
= SecXPCDictionaryCopyData(event
, kSecXPCData
, &error
);
694 result
= SecServerItemBackupRestore(backupName
, peerID
, keybag
, secret
, backup
, &error
);
701 CFReleaseSafe(peerID
);
703 CFRelease(backupName
);
705 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
709 case sec_add_shared_web_credential_id
:
711 #if SHAREDWEBCREDENTIALS
712 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
714 CFTypeRef result
= NULL
;
716 CFStringRef appID
= (client
.task
) ? SecTaskCopyApplicationIdentifier(client
.task
) : NULL
;
717 if (_SecAddSharedWebCredential(query
, &client
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
718 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
719 CFReleaseNull(result
);
721 CFReleaseSafe(appID
);
722 CFReleaseNull(query
);
725 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, kCFBooleanFalse
, &error
);
729 case sec_copy_shared_web_credential_id
:
731 #if SHAREDWEBCREDENTIALS
732 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
734 CFTypeRef result
= NULL
;
735 CFStringRef appID
= (client
.task
) ? SecTaskCopyApplicationIdentifier(client
.task
) : NULL
;
736 if (_SecCopySharedWebCredential(query
, &client
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
737 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
738 CFReleaseNull(result
);
740 CFReleaseSafe(appID
);
741 CFReleaseNull(query
);
744 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, kCFBooleanFalse
, &error
);
748 case sec_get_log_settings_id
:
750 CFPropertyListRef currentList
= SecCopyLogSettings_Server(&error
);
752 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, currentList
, &error
);
754 CFReleaseSafe(currentList
);
757 case sec_set_xpc_log_settings_id
:
759 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
761 SecSetXPCLogSettings_Server(newSettings
, &error
);
763 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
764 CFReleaseNull(newSettings
);
767 case sec_set_circle_log_settings_id
:
769 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
771 SecSetCircleLogSettings_Server(newSettings
, &error
);
773 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
774 CFReleaseNull(newSettings
);
777 case sec_otr_session_create_remote_id
:
779 CFDataRef publicPeerId
= NULL
;
780 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCPublicPeerId
, &publicPeerId
, &error
)) {
781 CFDataRef otrSession
= _SecOTRSessionCreateRemote(publicPeerId
, &error
);
783 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, otrSession
, &error
);
784 CFReleaseNull(otrSession
);
786 CFReleaseSafe(publicPeerId
);
790 case sec_otr_session_process_packet_remote_id
:
792 CFDataRef sessionData
= NULL
, inputPacket
= NULL
, outputSessionData
= NULL
, outputPacket
= NULL
;
793 bool readyForMessages
= false;
794 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCOTRSession
, &sessionData
, &error
)) {
795 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &inputPacket
, &error
)) {
796 bool result
= _SecOTRSessionProcessPacketRemote(sessionData
, inputPacket
, &outputSessionData
, &outputPacket
, &readyForMessages
, &error
);
798 SecXPCDictionarySetData(replyMessage
, kSecXPCOTRSession
, outputSessionData
, &error
);
799 SecXPCDictionarySetData(replyMessage
, kSecXPCData
, outputPacket
, &error
);
800 xpc_dictionary_set_bool(replyMessage
, kSecXPCOTRReady
, readyForMessages
);
801 CFReleaseNull(outputSessionData
);
802 CFReleaseNull(outputPacket
);
804 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
806 CFReleaseSafe(inputPacket
);
808 CFReleaseSafe(sessionData
);
812 case kSecXPCOpTryUserCredentials
:
813 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
814 with_label_and_password_and_dsid(event
, ^(CFStringRef label
, CFDataRef password
, CFStringRef dsid
) {
815 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
816 SOSCCTryUserCredentials_Server(label
, password
, dsid
, &error
));
820 case kSecXPCOpSetUserCredentials
:
821 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
822 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
823 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
824 SOSCCSetUserCredentials_Server(label
, password
, &error
));
828 case kSecXPCOpSetUserCredentialsAndDSID
:
829 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
830 with_label_and_password_and_dsid(event
, ^(CFStringRef label
, CFDataRef password
, CFStringRef dsid
) {
831 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
832 SOSCCSetUserCredentialsAndDSID_Server(label
, password
, dsid
, &error
));
836 case kSecXPCOpSetUserCredentialsAndDSIDWithAnalytics
:
837 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
838 with_label_and_password_and_dsid(event
, ^(CFStringRef label
, CFDataRef password
, CFStringRef dsid
) {
839 CFDataRef parentEvent
= NULL
;
840 if(SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeySignInAnalytics
, &parentEvent
, &error
) && parentEvent
!= NULL
){
841 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCSetUserCredentialsAndDSIDWithAnalytics_Server(label
, password
, dsid
, parentEvent
, &error
));
843 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCSetUserCredentialsAndDSID_Server(label
, password
, dsid
, &error
));
845 CFReleaseNull(parentEvent
);
850 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
851 with_view_and_action(event
, ^(CFStringRef view
, uint64_t actionCode
) {
852 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
853 SOSCCView_Server(view
, (SOSViewActionCode
)actionCode
, &error
));
857 case kSecXPCOpViewSet
: // FALLTHROUGH
858 case kSecXPCOpViewSetWithAnalytics
:
859 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
860 CFSetRef enabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyEnabledViewsKey
);
861 CFSetRef disabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyDisabledViewsKey
);
862 CFDataRef parentEvent
= NULL
;
863 if(SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeySignInAnalytics
, &parentEvent
, &error
)){
864 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCViewSetWithAnalytics_Server(enabledViews
, disabledViews
, parentEvent
));
866 CFReleaseNull(enabledViews
);
867 CFReleaseNull(disabledViews
);
868 CFReleaseNull(parentEvent
);
871 case kSecXPCOpCanAuthenticate
:
872 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
873 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
874 SOSCCCanAuthenticate_Server(&error
));
877 case kSecXPCOpPurgeUserCredentials
:
878 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
879 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
880 SOSCCPurgeUserCredentials_Server(&error
));
883 case kSecXPCOpDeviceInCircle
:
884 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
885 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
886 SOSCCThisDeviceIsInCircle_Server(&error
));
889 case kSecXPCOpRequestToJoin
:
890 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
891 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
892 SOSCCRequestToJoinCircle_Server(&error
));
895 case kSecXPCOpRequestToJoinWithAnalytics
:
896 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
897 CFDataRef parentEvent
= NULL
;
898 SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeySignInAnalytics
, &parentEvent
, &error
);
899 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRequestToJoinCircleWithAnalytics_Server(parentEvent
, &error
));
900 CFReleaseNull(parentEvent
);
903 case kSecXPCOpAccountHasPublicKey
:
904 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
905 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
906 SOSCCAccountHasPublicKey_Server(&error
));
910 case kSecXPCOpRequestToJoinAfterRestore
:
911 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
912 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
913 SOSCCRequestToJoinCircleAfterRestore_Server(&error
));
916 case kSecXPCOpRequestToJoinAfterRestoreWithAnalytics
:
917 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
918 CFDataRef parentEvent
= NULL
;
919 if(SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeySignInAnalytics
, &parentEvent
, &error
) && parentEvent
!= NULL
){
920 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRequestToJoinCircleAfterRestoreWithAnalytics_Server(parentEvent
, &error
));
922 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRequestToJoinCircleAfterRestore_Server(&error
));
924 CFReleaseNull(parentEvent
);
927 case kSecXPCOpRequestDeviceID
:
928 case kSecXPCOpSetDeviceID
:
929 case kSecXPCOpHandleIDSMessage
:
930 case kSecXPCOpSyncWithIDSPeer
:
931 case kSecXPCOpSendIDSMessage
:
932 case kSecXPCOpPingTest
:
933 case kSecXPCOpIDSDeviceID
:
934 case kSecXPCOpSyncWithKVSPeerIDOnly
:{
935 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyError
, errSecUnimplemented
);
938 case kSecXPCOpAccountSetToNew
:
939 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
940 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCAccountSetToNew_Server(&error
));
943 case kSecXPCOpResetToOffering
:
944 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
945 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
946 SOSCCResetToOffering_Server(&error
));
949 case kSecXPCOpResetToEmpty
:
950 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
951 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
952 SOSCCResetToEmpty_Server(&error
));
955 case kSecXPCOpResetToEmptyWithAnalytics
:
956 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
957 CFDataRef parentEvent
= NULL
;
958 if(SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeySignInAnalytics
, &parentEvent
, &error
) && parentEvent
!= NULL
){
959 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCResetToEmptyWithAnalytics_Server(parentEvent
, &error
));
961 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCResetToEmpty_Server(&error
));
965 case kSecXPCOpRemoveThisDeviceFromCircle
:
966 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
967 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
968 SOSCCRemoveThisDeviceFromCircle_Server(&error
));
971 case kSecXPCOpRemoveThisDeviceFromCircleWithAnalytics
:
972 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
973 CFDataRef parentEvent
= NULL
;
974 if(SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeySignInAnalytics
, &parentEvent
, &error
) && parentEvent
!= NULL
){
975 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRemoveThisDeviceFromCircleWithAnalytics_Server(parentEvent
, &error
));
977 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRemoveThisDeviceFromCircle_Server(&error
));
979 CFReleaseNull(parentEvent
);
982 case kSecXPCOpRemovePeersFromCircle
:
983 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
984 CFArrayRef applicants
= SecXPCDictionaryCopyPeerInfoArray(event
, kSecXPCKeyPeerInfoArray
, &error
);
985 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
986 SOSCCRemovePeersFromCircle_Server(applicants
, &error
));
987 CFReleaseNull(applicants
);
990 case kSecXPCOpRemovePeersFromCircleWithAnalytics
:
991 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
992 CFArrayRef applicants
= SecXPCDictionaryCopyPeerInfoArray(event
, kSecXPCKeyPeerInfoArray
, &error
);
993 CFDataRef parentEvent
= NULL
;
994 if(SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeySignInAnalytics
, &parentEvent
, &error
) && parentEvent
!= NULL
){
995 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRemovePeersFromCircleWithAnalytics_Server(applicants
, parentEvent
, &error
));
997 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRemovePeersFromCircle_Server(applicants
, &error
));
999 CFReleaseNull(parentEvent
);
1000 CFReleaseNull(applicants
);
1003 case kSecXPCOpLoggedOutOfAccount
:
1004 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1005 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1006 SOSCCLoggedOutOfAccount_Server(&error
));
1009 case kSecXPCOpAcceptApplicants
:
1010 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1011 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfoArray
);
1012 // CreateArrayOfPeerInfoWithXPCObject enforces that xapplicants is a non-NULL xpc data object
1013 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1014 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1015 (applicants
&& SOSCCAcceptApplicants_Server(applicants
, &error
)));
1016 CFReleaseSafe(applicants
);
1019 case kSecXPCOpRejectApplicants
:
1020 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1021 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfoArray
);
1022 // CreateArrayOfPeerInfoWithXPCObject enforces that xapplicants is a non-NULL xpc data object
1023 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1024 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1025 (applicants
&& SOSCCRejectApplicants_Server(applicants
, &error
)));
1026 CFReleaseSafe(applicants
);
1029 case kSecXPCOpSetNewPublicBackupKey
:
1031 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1032 CFDataRef publicBackupKey
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNewPublicBackupKey
, &error
);
1033 if (publicBackupKey
!= NULL
) {
1034 SOSPeerInfoRef peerInfo
= SOSCCSetNewPublicBackupKey_Server(publicBackupKey
, &error
);
1035 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1036 CFReleaseNull(peerInfo
);
1038 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1039 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1040 xpc_release(xpc_object
);
1042 CFReleaseNull(peerInfoData
);
1043 CFReleaseSafe(publicBackupKey
);
1048 case kSecXPCOpRegisterRecoveryPublicKey
:
1050 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1051 CFDataRef recovery_key
= SecXPCDictionaryCopyData(event
, kSecXPCKeyRecoveryPublicKey
, &error
);
1052 if (recovery_key
!= NULL
) {
1054 CFDataRef nullData
= CFDataCreate(kCFAllocatorDefault
, &zero
, 1); // token we send if we really wanted to send NULL
1055 if(CFEqual(recovery_key
, nullData
)) {
1056 CFReleaseNull(recovery_key
);
1058 CFReleaseNull(nullData
);
1059 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRegisterRecoveryPublicKey_Server(recovery_key
, &error
));
1060 CFReleaseNull(recovery_key
);
1065 case kSecXPCOpGetRecoveryPublicKey
:
1067 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1068 xpc_object_t xpc_recovery_object
= NULL
;
1069 CFDataRef recovery
= SOSCCCopyRecoveryPublicKey(&error
);
1071 xpc_recovery_object
= _CFXPCCreateXPCObjectFromCFObject(recovery
);
1073 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_recovery_object
);
1074 CFReleaseNull(recovery
);
1078 case kSecXPCOpSetBagForAllSlices
:
1080 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1081 CFDataRef backupSlice
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
); // NULL checked below
1082 bool includeV0
= xpc_dictionary_get_bool(event
, kSecXPCKeyIncludeV0
); // false is ok, so it's safe for this paramter to be unset or incorrect type
1083 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, backupSlice
&& SOSCCRegisterSingleRecoverySecret_Server(backupSlice
, includeV0
, &error
));
1084 CFReleaseSafe(backupSlice
);
1088 case kSecXPCOpCopyApplicantPeerInfo
:
1089 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1090 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1091 SOSCCCopyApplicantPeerInfo_Server(&error
),
1095 case kSecXPCOpCopyValidPeerPeerInfo
:
1096 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1097 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1098 SOSCCCopyValidPeerPeerInfo_Server(&error
),
1102 case kSecXPCOpValidateUserPublic
:
1103 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1104 bool trusted
= SOSCCValidateUserPublic_Server(&error
);
1105 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, trusted
);
1108 case kSecXPCOpCopyNotValidPeerPeerInfo
:
1109 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1110 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1111 SOSCCCopyNotValidPeerPeerInfo_Server(&error
),
1115 case kSecXPCOpCopyGenerationPeerInfo
:
1116 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1117 xpc_dictionary_set_and_consume_CFArray(replyMessage
, kSecXPCKeyResult
,
1118 SOSCCCopyGenerationPeerInfo_Server(&error
));
1121 case kSecXPCOpCopyRetirementPeerInfo
:
1122 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1123 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1124 SOSCCCopyRetirementPeerInfo_Server(&error
),
1128 case kSecXPCOpCopyViewUnawarePeerInfo
:
1129 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1130 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1131 SOSCCCopyViewUnawarePeerInfo_Server(&error
),
1135 case kSecXPCOpCopyEngineState
:
1137 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1138 CFArrayRef array
= SOSCCCopyEngineState_Server(&error
);
1139 CFDataRef derData
= NULL
;
1141 require_quiet(array
, done
);
1142 derData
= CFPropertyListCreateDERData(kCFAllocatorDefault
, array
, &error
);
1144 require_quiet(derData
, done
);
1145 xpc_dictionary_set_data(replyMessage
, kSecXPCKeyResult
, CFDataGetBytePtr(derData
),CFDataGetLength(derData
));
1147 CFReleaseNull(derData
);
1148 CFReleaseNull(array
);
1152 case kSecXPCOpCopyPeerPeerInfo
:
1153 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1154 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1155 SOSCCCopyPeerPeerInfo_Server(&error
),
1159 case kSecXPCOpCopyConcurringPeerPeerInfo
:
1160 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1161 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1162 SOSCCCopyConcurringPeerPeerInfo_Server(&error
),
1166 case kSecXPCOpCopyMyPeerInfo
:
1167 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1168 SOSPeerInfoRef peerInfo
= SOSCCCopyMyPeerInfo_Server(&error
);
1169 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1170 CFReleaseNull(peerInfo
);
1172 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1173 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1174 xpc_release(xpc_object
);
1176 CFReleaseNull(peerInfoData
);
1179 case kSecXPCOpGetLastDepartureReason
:
1180 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1181 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1182 SOSCCGetLastDepartureReason_Server(&error
));
1185 case kSecXPCOpSetLastDepartureReason
:
1186 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1187 // 0 is a legitimate reason (kSOSDepartureReasonError), so it's safe for this parameter to be unset or incorrect type
1188 int32_t reason
= (int32_t) xpc_dictionary_get_int64(event
, kSecXPCKeyReason
);
1189 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1190 SOSCCSetLastDepartureReason_Server(reason
, &error
));
1193 case kSecXPCOpProcessSyncWithPeers
:
1194 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1195 CFSetRef peers
= SecXPCDictionaryCopySet(event
, kSecXPCKeySet
, &error
);
1196 CFSetRef backupPeers
= SecXPCDictionaryCopySet(event
, kSecXPCKeySet2
, &error
);
1197 if (peers
&& backupPeers
) {
1198 CFSetRef result
= SOSCCProcessSyncWithPeers_Server(peers
, backupPeers
, &error
);
1200 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
1202 CFReleaseNull(result
);
1204 CFReleaseNull(peers
);
1205 CFReleaseNull(backupPeers
);
1208 case kSecXPCOpProcessSyncWithAllPeers
:
1209 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1210 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1211 SOSCCProcessSyncWithAllPeers_Server(&error
));
1214 case soscc_EnsurePeerRegistration_id
:
1215 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1216 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1217 SOSCCProcessEnsurePeerRegistration_Server(&error
));
1220 case kSecXPCOpRollKeys
:
1222 // false is valid, so it's safe for this parameter to be unset or incorrect type
1223 bool force
= xpc_dictionary_get_bool(event
, "force");
1224 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1225 _SecServerRollKeys(force
, &client
, &error
));
1228 case kSecXPCOpWaitForInitialSync
:
1229 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1230 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1231 SOSCCWaitForInitialSync_Server(&error
));
1235 case kSecXPCOpWaitForInitialSyncWithAnalytics
:
1236 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1237 CFDataRef parentEvent
= NULL
;
1238 if(SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeySignInAnalytics
, &parentEvent
, &error
) && parentEvent
!= NULL
){
1239 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCWaitForInitialSyncWithAnalytics_Server(parentEvent
, &error
));
1241 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCWaitForInitialSync_Server(&error
));
1243 CFReleaseNull(parentEvent
);
1246 case kSecXPCOpPeersHaveViewsEnabled
:
1248 CFArrayRef viewSet
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyArray
, &error
);
1250 CFBooleanRef result
= SOSCCPeersHaveViewsEnabled_Server(viewSet
, &error
);
1251 if (result
!= NULL
) {
1252 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
!= kCFBooleanFalse
);
1255 CFReleaseNull(viewSet
);
1259 case kSecXPCOpWhoAmI
:
1262 xpc_dictionary_set_data(replyMessage
, "musr", CFDataGetBytePtr(client
.musr
), CFDataGetLength(client
.musr
));
1263 xpc_dictionary_set_bool(replyMessage
, "system-keychain", client
.allowSystemKeychain
);
1264 xpc_dictionary_set_bool(replyMessage
, "syncbubble-keychain", client
.allowSyncBubbleKeychain
);
1265 xpc_dictionary_set_bool(replyMessage
, "network-extension", client
.isNetworkExtension
);
1266 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1269 case kSecXPCOpTransmogrifyToSyncBubble
:
1271 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainSyncBubble
, &error
)) {
1273 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1274 CFArrayRef services
= SecXPCDictionaryCopyArray(event
, "services", &error
);
1276 if (uid
&& services
) {
1277 res
= _SecServerTransmogrifyToSyncBubble(services
, uid
, &client
, &error
);
1279 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1280 CFReleaseNull(services
);
1282 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1287 case kSecXPCOpTransmogrifyToSystemKeychain
:
1289 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
)) {
1291 bool res
= _SecServerTransmogrifyToSystemKeychain(&client
, &error
);
1292 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1294 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1300 case kSecXPCOpDeleteUserView
:
1302 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
)) {
1305 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1307 res
= _SecServerDeleteMUSERViews(&client
, uid
, &error
);
1310 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1315 case kSecXPCOpCopyApplication
:
1316 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1317 SOSPeerInfoRef peerInfo
= SOSCCCopyApplication_Server(&error
);
1318 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1319 CFReleaseNull(peerInfo
);
1321 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1322 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1323 xpc_release(xpc_object
);
1325 CFReleaseNull(peerInfoData
);
1328 case kSecXPCOpCopyCircleJoiningBlob
:
1329 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1330 CFDataRef appBlob
= SecXPCDictionaryCopyCFDataRef(event
, kSecXPCData
, &error
);
1331 if (appBlob
!= NULL
) {
1332 SOSPeerInfoRef applicant
= SOSPeerInfoCreateFromData(kCFAllocatorDefault
, &error
, appBlob
);
1333 if (applicant
!= NULL
) {
1334 CFDataRef pbblob
= SOSCCCopyCircleJoiningBlob_Server(applicant
, &error
);
1336 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(pbblob
);
1337 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1338 xpc_release(xpc_object
);
1340 CFReleaseNull(pbblob
);
1341 CFReleaseNull(applicant
);
1343 CFReleaseNull(appBlob
);
1347 case kSecXPCOpCopyInitialSyncBlob
:
1348 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1349 uint64_t flags
= xpc_dictionary_get_uint64(event
, kSecXPCKeyFlags
); // 0 is a valid flags, so no error checking
1350 CFDataRef initialblob
= SOSCCCopyInitialSyncData_Server((uint32_t)flags
, &error
);
1352 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(initialblob
);
1353 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1354 xpc_release(xpc_object
);
1356 CFReleaseNull(initialblob
);
1359 case kSecXPCOpJoinWithCircleJoiningBlob
:
1360 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1361 CFDataRef joiningBlob
= SecXPCDictionaryCopyCFDataRef(event
, kSecXPCData
, &error
); // NULL checked below
1362 uint64_t version
= xpc_dictionary_get_uint64(event
, kSecXPCVersion
); // 0 is valid, so this parameter can be unset or incorrect type
1363 if (joiningBlob
!= NULL
) {
1364 bool retval
= SOSCCJoinWithCircleJoiningBlob_Server(joiningBlob
, (PiggyBackProtocolVersion
) version
, &error
);
1365 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1366 CFReleaseNull(joiningBlob
);
1371 case kSecXPCOpKVSKeyCleanup
:
1372 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1373 bool retval
= SOSCCCleanupKVSKeys_Server(&error
);
1374 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1378 case kSecXPCOpMessageFromPeerIsPending
:
1380 SOSPeerInfoRef peer
= SecXPCDictionaryCopyPeerInfo(event
, kSecXPCKeyPeerInfo
, &error
);
1382 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1383 SOSCCMessageFromPeerIsPending_Server(peer
, &error
));
1385 CFReleaseNull(peer
);
1388 case kSecXPCOpSendToPeerIsPending
:
1390 SOSPeerInfoRef peer
= SecXPCDictionaryCopyPeerInfo(event
, kSecXPCKeyPeerInfo
, &error
);
1392 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1393 SOSCCSendToPeerIsPending(peer
, &error
));
1395 CFReleaseNull(peer
);
1398 #endif /* !SECUREOBJECTSYNC */
1399 case sec_delete_items_with_access_groups_id
:
1401 bool retval
= false;
1402 #if TARGET_OS_IPHONE
1403 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateUninstallDeletion
, &error
)) {
1404 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyAccessGroups
, &error
);
1407 retval
= _SecItemServerDeleteAllWithAccessGroups(accessGroups
, &client
, &error
);
1409 CFReleaseNull(accessGroups
);
1412 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1415 case kSecXPCOpBackupKeybagAdd
: {
1416 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementBackupTableOperations
, &error
)) {
1417 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1421 case kSecXPCOpBackupKeybagDelete
: {
1422 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementBackupTableOperations
, &error
)) {
1423 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1427 case kSecXPCOpKeychainControlEndpoint
: {
1428 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainControl
, &error
)) {
1429 xpc_endpoint_t endpoint
= SecServerCreateKeychainControlEndpoint();
1431 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyEndpoint
, endpoint
);
1432 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1433 xpc_release(endpoint
);
1435 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1440 case sec_item_copy_parent_certificates_id
: {
1441 CFArrayRef results
= NULL
;
1442 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateCertificateAllAccess
, &error
)) {
1443 CFDataRef issuer
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNormalizedIssuer
, &error
);
1444 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyAccessGroups
, &error
);
1445 if (issuer
&& accessGroups
) {
1446 results
= _SecItemCopyParentCertificates(issuer
, accessGroups
, &error
);
1448 CFReleaseNull(issuer
);
1449 CFReleaseNull(accessGroups
);
1451 SecXPCDictionarySetPListOptional(replyMessage
, kSecXPCKeyResult
, results
, &error
);
1452 CFReleaseNull(results
);
1455 case sec_item_certificate_exists_id
: {
1456 bool result
= false;
1457 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateCertificateAllAccess
, &error
)) {
1458 CFDataRef issuer
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNormalizedIssuer
, &error
);
1459 CFDataRef serialNum
= SecXPCDictionaryCopyData(event
, kSecXPCKeySerialNumber
, &error
);
1460 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyAccessGroups
, &error
);
1461 if (issuer
&& serialNum
&& accessGroups
) {
1462 result
= _SecItemCertificateExists(issuer
, serialNum
, accessGroups
, &error
);
1464 CFReleaseNull(issuer
);
1465 CFReleaseNull(serialNum
);
1466 CFReleaseNull(accessGroups
);
1468 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1477 if(SecErrorGetOSStatus(error
) == errSecItemNotFound
|| isSOSErrorCoded(error
, kSOSErrorPublicKeyAbsent
))
1478 secdebug("ipc", "%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1479 else if (SecErrorGetOSStatus(error
) == errSecAuthNeeded
)
1480 secwarning("Authentication is needed %@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1482 secerror("%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1484 xpcError
= SecCreateXPCObjectWithCFError(error
);
1486 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyError
, xpcError
);
1488 } else if (replyMessage
) {
1489 secdebug("ipc", "%@ %@ responding %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyMessage
);
1492 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, &error
, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event
);
1493 secerror("%@: returning error: %@", client
.task
, error
);
1494 xpcError
= SecCreateXPCObjectWithCFError(error
);
1495 replyMessage
= xpc_create_reply_with_format(event
, "{%string: %value}", kSecXPCKeyError
, xpcError
);
1499 xpc_connection_send_message(connection
, replyMessage
);
1500 xpc_release(replyMessage
);
1503 xpc_release(xpcError
);
1504 CFReleaseSafe(error
);
1505 CFReleaseSafe(client
.accessGroups
);
1506 CFReleaseSafe(client
.musr
);
1507 CFReleaseSafe(client
.task
);
1508 CFReleaseSafe(domains
);
1509 CFReleaseSafe(clientAuditToken
);
1512 static void securityd_xpc_init(const char *service_name
)
1514 secdebug("serverxpc", "start");
1515 xpc_connection_t listener
= xpc_connection_create_mach_service(service_name
, NULL
, XPC_CONNECTION_MACH_SERVICE_LISTENER
);
1517 seccritical("security failed to register xpc listener for %s, exiting", service_name
);
1521 xpc_connection_set_event_handler(listener
, ^(xpc_object_t connection
) {
1522 if (xpc_get_type(connection
) == XPC_TYPE_CONNECTION
) {
1523 xpc_connection_set_event_handler(connection
, ^(xpc_object_t event
) {
1524 if (xpc_get_type(event
) == XPC_TYPE_DICTIONARY
) {
1525 // Synchronous. The client has a connection pool so they can be somewhat re-entrant if they need.
1526 securityd_xpc_dictionary_handler(connection
, event
);
1529 xpc_connection_resume(connection
);
1532 xpc_connection_resume(listener
);
1535 xpc_activity_register("com.apple.securityd.daily", XPC_ACTIVITY_CHECK_IN
, ^(xpc_activity_t activity
) {
1536 xpc_activity_state_t activityState
= xpc_activity_get_state(activity
);
1537 if (activityState
== XPC_ACTIVITY_STATE_RUN
) {
1538 SecCKKS24hrNotification();
1539 SecOctagon24hrNotification();
1544 #if OCTAGON && !TARGET_OS_BRIDGE
1545 // Kick off reporting tasks.
1546 if (os_variant_has_internal_diagnostics("com.apple.security") && !os_variant_is_recovery("securityd")) {
1547 InitPolicyReporter();
1553 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1555 #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
1556 static void securityd_soscc_lock_hack() {
1557 dispatch_queue_t soscc_lock_queue
= dispatch_queue_create("soscc_lock_queue", DISPATCH_QUEUE_PRIORITY_DEFAULT
);
1560 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1561 // FIXME: securityd isn't currently registering for any other notifyd events. If/when it does,
1562 // this code will need to be generalized / migrated away from just this specific purpose.
1563 xpc_set_event_stream_handler("com.apple.notifyd.matching", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH
, 0), ^(xpc_object_t object
) {
1564 char *event_description
= xpc_copy_description(object
);
1565 secnotice("events", "%s", event_description
);
1566 free(event_description
);
1569 secnotice("lockassertion", "notify_register_dispatch(kSOSCCHoldLockForInitialSync)");
1570 notify_register_dispatch(kSOSCCHoldLockForInitialSync
, &soscc_tok
, soscc_lock_queue
, ^(int token __unused
) {
1571 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync: grabbing the lock");
1572 CFErrorRef error
= NULL
;
1574 uint64_t one_minute
= 60ull;
1575 if(SecAKSUserKeybagHoldLockAssertion(one_minute
, &error
)){
1576 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1577 os_transaction_t transaction
= os_transaction_create("securityd-LockAssertedingHolder");
1579 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, one_minute
*NSEC_PER_SEC
), soscc_lock_queue
, ^{
1580 CFErrorRef localError
= NULL
;
1581 if(!SecAKSUserKeybagDropLockAssertion(&localError
))
1582 secerror("failed to unlock: %@", localError
);
1583 CFReleaseNull(localError
);
1584 os_release(transaction
);
1587 secerror("Failed to take device lock assertion: %@", error
);
1589 CFReleaseNull(error
);
1590 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync => done");
1600 static char homeDir
[PATH_MAX
] = {};
1602 if (homeDir
[0] == '\0') {
1603 struct passwd
* pwd
= getpwuid(getuid());
1607 if (realpath(pwd
->pw_dir
, homeDir
) == NULL
) {
1608 strlcpy(homeDir
, pwd
->pw_dir
, sizeof(homeDir
));
1616 int main(int argc
, char *argv
[])
1618 DisableLocalization();
1620 char *wait4debugger
= getenv("WAIT4DEBUGGER");
1621 if (wait4debugger
&& !strcasecmp("YES", wait4debugger
)) {
1622 seccritical("SIGSTOPing self, awaiting debugger");
1623 kill(getpid(), SIGSTOP
);
1624 seccritical("Again, for good luck (or bad debuggers)");
1625 kill(getpid(), SIGSTOP
);
1628 /* <rdar://problem/15792007> Users with network home folders are unable to use/save password for Mail/Cal/Contacts/websites
1629 Secd doesn't realize DB connections get invalidated when network home directory users logout
1630 and their home gets unmounted. Exit secd, start fresh when user logs back in.
1633 int sessionstatechanged_tok
;
1634 notify_register_dispatch(kSA_SessionStateChangedNotification
, &sessionstatechanged_tok
, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^(int token __unused
) {
1635 // we could be a process running as root.
1636 // However, since root never logs out this isn't an issue.
1637 if (SASSessionStateForUser(getuid()) == kSA_state_loggingout_pointofnoreturn
) {
1638 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, 3ull*NSEC_PER_SEC
), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
1639 xpc_transaction_exit_clean();
1646 #define SECD_PROFILE_NAME "com.apple.secd"
1647 const char *homedir
= homedirPath();
1648 if (homedir
== NULL
)
1649 errx(1, "failed to get home directory for secd");
1651 char *errorbuf
= NULL
;
1652 const char *sandbox_params
[] = {
1658 rc
= sandbox_init_with_parameters(SECD_PROFILE_NAME
, SANDBOX_NAMED
, sandbox_params
, &errorbuf
);
1660 err(1, "Failed to process in a sandbox: %d %s", rc
, errorbuf
);
1661 #endif /* TARGET_OS_OSX */
1663 const char *serviceName
= kSecuritydXPCServiceName
;
1665 // Mark our interest in running some features (before we bring the DB layer up)
1667 EscrowRequestServerSetEnabled(true);
1668 OctagonSetShouldPerformInitialization(true);
1672 /* setup SQDLite before some other component have a chance to create a database connection */
1673 _SecDbServerSetup();
1675 securityd_init_server();
1676 securityd_xpc_init(serviceName
);
1678 SecCreateSecuritydXPCServer();
1679 #if SECUREOBJECTSYNC
1680 SOSControlServerInitialize();
1683 CKKSControlServerInitialize();
1684 OctagonControlServerInitialize();
1685 EscrowRequestXPCServerInitialize();
1688 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1689 #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
1690 securityd_soscc_lock_hack();
1696 /* vi:set ts=4 sw=4 et: */