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 <corecrypto/ccec.h>
34 #include "keychain/SecureObjectSync/SOSPeerInfoDER.h"
35 #include <Security/SecureObjectSync/SOSCloudCircle.h>
36 #include <Security/SecureObjectSync/SOSCloudCircleInternal.h>
37 #include "keychain/SecureObjectSync/SOSInternal.h"
38 #include "keychain/SecureObjectSync/SOSPeerInfoCollections.h"
39 #include "keychain/SecureObjectSync/SOSControlServer.h"
40 #include <Security/SecBase.h>
41 #include <Security/SecBasePriv.h>
42 #include <Security/SecCertificatePriv.h>
43 #include <Security/SecEntitlements.h>
44 #include <Security/SecInternal.h>
45 #include <Security/SecItem.h>
46 #include <Security/SecItemPriv.h>
47 #include <Security/SecPolicy.h>
48 #include <Security/SecPolicyInternal.h>
49 #include <Security/SecTask.h>
50 #include <Security/SecTrustInternal.h>
51 #include <Security/SecuritydXPC.h>
52 #include "trust/trustd/OTATrustUtilities.h"
53 #include "keychain/securityd/SOSCloudCircleServer.h"
54 #include "keychain/securityd/SecItemBackupServer.h"
55 #include "keychain/securityd/SecItemServer.h"
56 #include "keychain/securityd/SecLogSettingsServer.h"
57 #include "keychain/securityd/SecOTRRemote.h"
58 #include "trust/trustd/SecTrustServer.h"
59 #include "trust/trustd/SecTrustStoreServer.h"
60 #include "keychain/securityd/iCloudTrace.h"
61 #include "keychain/securityd/spi.h"
62 #include <utilities/SecAKSWrappers.h>
63 #include <utilities/SecCFError.h>
64 #include <utilities/SecCFWrappers.h>
65 #include <utilities/SecDb.h>
66 #include <utilities/SecIOFormat.h>
67 #include <utilities/SecXPCError.h>
68 #include <utilities/debugging.h>
69 #include <utilities/SecInternalReleasePriv.h>
70 #include <utilities/der_plist_internal.h>
71 #include <utilities/der_plist.h>
72 #include "trust/trustd/personalization.h"
73 #include "trust/trustd/SecPinningDb.h"
74 #include "keychain/securityd/SFKeychainControlManager.h"
76 #include <keychain/ckks/CKKS.h>
77 #include <keychain/ckks/CKKSControlServer.h>
78 #include "keychain/ot/OctagonControlServer.h"
80 #include "keychain/securityd/SFKeychainServer.h"
82 #include "keychain/securityd/PolicyReporter.h"
85 #include <AssertMacros.h>
86 #include <CoreFoundation/CFXPCBridge.h>
87 #include <CoreFoundation/CoreFoundation.h>
88 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
91 #include <Security/SecTaskPriv.h>
92 #include <login/SessionAgentStatusCom.h>
95 #include <bsm/libbsm.h>
96 #include <ipc/securityd_client.h>
97 #include <libkern/OSAtomic.h>
98 #include <mach/mach.h>
99 #include <mach/message.h>
102 #include <sys/queue.h>
103 #include <sys/sysctl.h>
105 #include <xpc/private.h>
108 #include <ipc/server_security_helpers.h>
109 #include <ipc/server_entitlement_helpers.h>
111 #include "keychain/ot/OT.h"
112 #include "keychain/escrowrequest/EscrowRequestXPCServer.h"
113 #include "keychain/escrowrequest/EscrowRequestServerHelpers.h"
123 static void refresh_prng(void)
125 aks_ref_key_t ref
= NULL
;
127 int fd
= open("/dev/random", O_WRONLY
);
129 secerror("failed to open /dev/random (%d)", errno
);
133 /* create class F ref-key, and use its public key as an entropy source */
134 int err
= aks_ref_key_create(bad_keybag_handle
, key_class_f
, key_type_asym_ec_p256
, NULL
, 0, &ref
);
135 if (err
!= kAKSReturnSuccess
) {
136 secerror("failed to create refkey (%d)", err
);
140 size_t pub_key_len
= 0;
141 const uint8_t *pub_key
= aks_ref_key_get_public_key(ref
, &pub_key_len
);
142 if (pub_key_len
> ccec_export_pub_size_cp(ccec_cp_256())) {
143 secerror("invalid pub key (%zu)", pub_key_len
);
147 while (pub_key_len
> 0) {
148 ssize_t n
= write(fd
, pub_key
, pub_key_len
);
150 secerror("failed to write /dev/random (%d)", errno
);
160 aks_ref_key_free(&ref
);
172 _xpc_dictionary_copy_CFString(xpc_object_t xdict
, const char *key
)
174 CFStringRef result
= NULL
;
175 const char *str
= xpc_dictionary_get_string(xdict
, key
);
177 result
= CFStringCreateWithCString(kCFAllocatorDefault
, str
, kCFStringEncodingUTF8
);
184 _xpc_dictionary_copy_CFDataNoCopy(xpc_object_t xdict
, const char *key
)
186 CFDataRef result
= NULL
;
188 const void *ptr
= xpc_dictionary_get_data(xdict
, key
, &len
);
190 result
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, ptr
, len
, kCFAllocatorNull
);
195 static void with_label_and_password(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
)) {
196 CFStringRef user_label
= _xpc_dictionary_copy_CFString(message
, kSecXPCKeyUserLabel
);
197 CFDataRef user_password
= _xpc_dictionary_copy_CFDataNoCopy(message
, kSecXPCKeyUserPassword
);
199 if (user_label
!= NULL
&& user_password
!= NULL
) {
200 action(user_label
, user_password
);
203 CFReleaseNull(user_label
);
204 CFReleaseNull(user_password
);
207 static void with_label_and_password_and_dsid(xpc_object_t message
, void (^action
)(CFStringRef label
, CFDataRef password
, CFStringRef dsid
)) {
208 CFStringRef user_label
= _xpc_dictionary_copy_CFString(message
, kSecXPCKeyUserLabel
);
209 CFDataRef user_password
= _xpc_dictionary_copy_CFDataNoCopy(message
, kSecXPCKeyUserPassword
);
210 CFStringRef dsid
= _xpc_dictionary_copy_CFString(message
, kSecXPCKeyDSID
);
212 /* dsid is optional */
213 if (user_label
!= NULL
&& user_password
!= NULL
) {
214 action(user_label
, user_password
, dsid
);
217 CFReleaseNull(user_label
);
218 CFReleaseNull(user_password
);
222 static void with_view_and_action(xpc_object_t message
, void (^action
)(CFStringRef view_name
, uint64_t view_action_code
)) {
223 CFStringRef view
= _xpc_dictionary_copy_CFString(message
, kSecXPCKeyViewName
);
224 const int64_t number
= xpc_dictionary_get_int64(message
, kSecXPCKeyViewActionCode
);
227 action(view
, number
);
233 static CFArrayRef
SecXPCDictionaryCopyPeerInfoArray(xpc_object_t dictionary
, const char *key
, CFErrorRef
*error
) {
234 return CreateArrayOfPeerInfoWithXPCObject(xpc_dictionary_get_value(dictionary
, key
), error
);
237 static CFDataRef
SecXPCDictionaryCopyCFDataRef(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
238 CFDataRef retval
= NULL
;
239 const uint8_t *bytes
= NULL
;
242 bytes
= xpc_dictionary_get_data(message
, key
, &len
);
243 require_action_quiet(bytes
, errOut
, SOSCreateError(kSOSErrorBadKey
, CFSTR("missing CFDataRef info"), NULL
, error
));
244 retval
= CFDataCreate(NULL
, bytes
, len
);
245 require_action_quiet(retval
, errOut
, SOSCreateError(kSOSErrorBadKey
, CFSTR("could not allocate CFDataRef info"), NULL
, error
));
250 static CFSetRef
CreateCFSetRefFromXPCObject(xpc_object_t xpcSetDER
, CFErrorRef
* error
) {
251 CFSetRef retval
= NULL
;
252 require_action_quiet(xpcSetDER
, errOut
, SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedNull
, sSecXPCErrorDomain
, NULL
, error
, NULL
, CFSTR("Unexpected Null Set to decode")));
254 require_action_quiet(xpc_get_type(xpcSetDER
) == XPC_TYPE_DATA
, errOut
, SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, error
, NULL
, CFSTR("xpcSetDER not data, got %@"), xpcSetDER
));
256 const uint8_t* der
= xpc_data_get_bytes_ptr(xpcSetDER
);
257 const uint8_t* der_end
= der
+ xpc_data_get_length(xpcSetDER
);
258 der
= der_decode_set(kCFAllocatorDefault
, &retval
, error
, der
, der_end
);
259 if (der
!= der_end
) {
260 SecError(errSecDecode
, error
, CFSTR("trailing garbage at end of SecAccessControl data"));
265 CFReleaseNull(retval
);
269 static SOSPeerInfoRef
SecXPCDictionaryCopyPeerInfo(xpc_object_t message
, const char *key
, CFErrorRef
*error
) {
271 const uint8_t *der
= xpc_dictionary_get_data(message
, key
, &length
);
273 return SecRequirementError(der
!= NULL
, error
, CFSTR("No data for key %s"), key
) ? SOSPeerInfoCreateFromDER(kCFAllocatorDefault
, error
, &der
, der
+ length
) : NULL
;
276 static CFSetRef
SecXPCSetCreateFromXPCDictionaryElement(xpc_object_t event
, const char *key
) {
277 CFErrorRef error
= NULL
;
278 xpc_object_t object
= xpc_dictionary_get_value(event
, key
);
279 CFSetRef retval
= NULL
;
280 if(object
) retval
= CreateCFSetRefFromXPCObject(object
, &error
);
281 CFReleaseNull(error
);
286 void xpc_dictionary_set_and_consume_CFArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
) {
288 xpc_object_t xpc_array
= _CFXPCCreateXPCObjectFromCFObject(cf_array
);
289 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
290 xpc_release(xpc_array
);
292 CFReleaseNull(cf_array
);
296 bool xpc_dictionary_set_and_consume_PeerInfoArray(xpc_object_t xdict
, const char *key
, CF_CONSUMED CFArrayRef cf_array
, CFErrorRef
*error
) {
299 xpc_object_t xpc_array
= CreateXPCObjectWithArrayOfPeerInfo(cf_array
, error
);
301 xpc_dictionary_set_value(xdict
, key
, xpc_array
);
302 xpc_release(xpc_array
);
307 CFReleaseNull(cf_array
);
311 #endif /* SECUREOBJECTSYNC */
314 SecDataCopyMmapFileDescriptor(int fd
, void **mem
, size_t *size
, CFErrorRef
*error
)
317 if (fstat(fd
, &sb
) < 0) {
321 *size
= (size_t)sb
.st_size
;
322 if ((off_t
)*size
!= sb
.st_size
) {
326 *mem
= mmap(NULL
, *size
, PROT_READ
, MAP_SHARED
, fd
, 0);
327 if (*mem
== MAP_FAILED
) {
331 return CFDataCreateWithBytesNoCopy(NULL
, *mem
, *size
, kCFAllocatorNull
);
335 SecDataWriteFileDescriptor(int fd
, CFDataRef data
)
337 CFIndex count
= CFDataGetLength(data
);
338 const uint8_t *ptr
= CFDataGetBytePtr(data
);
339 bool writeResult
= false;
342 ssize_t ret
= write(fd
, ptr
, count
);
354 // Returns error if entitlement isn't present.
356 EntitlementPresentAndTrue(uint64_t op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
358 if (!SecTaskGetBooleanValueForEntitlement(clientTask
, entitlement
)) {
359 SecError(errSecMissingEntitlement
, error
, CFSTR("%@: %@ lacks entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
)op
), clientTask
, entitlement
);
366 EntitlementAbsentOrFalse(uint64_t op
, SecTaskRef clientTask
, CFStringRef entitlement
, CFErrorRef
*error
)
368 if (SecTaskGetBooleanValueForEntitlement(clientTask
, entitlement
)) {
369 SecError(errSecNotAvailable
, error
, CFSTR("%@: %@ has entitlement %@"), SOSCCGetOperationDescription((enum SecXPCOperation
) op
), clientTask
, entitlement
);
375 static void securityd_xpc_dictionary_handler(const xpc_connection_t connection
, xpc_object_t event
) {
376 xpc_type_t type
= xpc_get_type(event
);
377 __block CFErrorRef error
= NULL
;
378 xpc_object_t xpcError
= NULL
;
379 xpc_object_t replyMessage
= NULL
;
380 CFDataRef clientAuditToken
= NULL
;
381 CFArrayRef domains
= NULL
;
382 SecurityClient client
= {
384 .accessGroups
= NULL
,
386 .uid
= xpc_connection_get_euid(connection
),
387 .allowSystemKeychain
= false,
388 .allowSyncBubbleKeychain
= false,
389 .isNetworkExtension
= false,
390 .canAccessNetworkExtensionAccessGroups
= false,
391 .applicationIdentifier
= NULL
,
395 secdebug("serverxpc", "entering");
396 if (type
== XPC_TYPE_DICTIONARY
) {
397 // TODO: Find out what we're dispatching.
398 replyMessage
= xpc_dictionary_create_reply(event
);
400 uint64_t operation
= xpc_dictionary_get_uint64(event
, kSecXPCKeyOperation
);
402 audit_token_t auditToken
= {};
403 xpc_connection_get_audit_token(connection
, &auditToken
);
404 clientAuditToken
= CFDataCreate(kCFAllocatorDefault
, (const UInt8
*)&auditToken
, sizeof(auditToken
));
406 if (!fill_security_client(&client
, xpc_connection_get_euid(connection
), auditToken
)) {
407 CFReleaseNull(clientAuditToken
);
408 xpc_connection_send_message(connection
, replyMessage
);
409 xpc_release(replyMessage
);
414 if (operation
== sec_add_shared_web_credential_id
|| operation
== sec_copy_shared_web_credential_id
) {
415 domains
= SecTaskCopySharedWebCredentialDomains(client
.task
);
418 secinfo("serverxpc", "XPC [%@] operation: %@ (%" PRIu64
")", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), operation
);
422 case sec_item_add_id
:
424 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
425 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
427 // Check for any entitlement-required attributes
428 bool entitlementsCorrect
= true;
429 if(CFDictionaryGetValue(query
, kSecAttrDeriveSyncIDFromItemAttributes
) ||
430 CFDictionaryGetValue(query
, kSecAttrPCSPlaintextServiceIdentifier
) ||
431 CFDictionaryGetValue(query
, kSecAttrPCSPlaintextPublicKey
) ||
432 CFDictionaryGetValue(query
, kSecAttrPCSPlaintextPublicIdentity
)) {
433 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_add_id
, client
.task
, kSecEntitlementPrivateCKKSPlaintextFields
, &error
);
435 if(entitlementsCorrect
&&
436 (CFDictionaryGetValue(query
, kSecDataInetExtraNotes
) ||
437 CFDictionaryGetValue(query
, kSecDataInetExtraHistory
) ||
438 CFDictionaryGetValue(query
, kSecDataInetExtraClientDefined0
) ||
439 CFDictionaryGetValue(query
, kSecDataInetExtraClientDefined1
) ||
440 CFDictionaryGetValue(query
, kSecDataInetExtraClientDefined2
) ||
441 CFDictionaryGetValue(query
, kSecDataInetExtraClientDefined3
))) {
442 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_add_id
, client
.task
, kSecEntitlementPrivateInetExpansionFields
, &error
);
445 if (entitlementsCorrect
&& CFDictionaryGetValue(query
, kSecAttrSysBound
)) {
446 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_add_id
, client
.task
, kSecEntitlementPrivateSysBound
, &error
);
449 CFTypeRef result
= NULL
;
450 if(entitlementsCorrect
) {
451 if (_SecItemAdd(query
, &client
, &result
, &error
) && result
) {
452 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
453 CFReleaseNull(result
);
456 CFReleaseNull(query
);
461 case sec_item_copy_matching_id
:
463 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
464 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
466 CFTypeRef result
= NULL
;
467 if (_SecItemCopyMatching(query
, &client
, &result
, &error
) && result
) {
468 SecXPCDictionarySetPListWithRepair(replyMessage
, kSecXPCKeyResult
, result
, true, &error
);
469 CFReleaseNull(result
);
471 CFReleaseNull(query
);
476 case sec_item_update_id
:
478 if (EntitlementAbsentOrFalse(sec_item_update_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
479 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
481 CFDictionaryRef attributesToUpdate
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyAttributesToUpdate
, &error
);
482 if (attributesToUpdate
) {
483 // Check for any entitlement-required attributes
484 bool entitlementsCorrect
= true;
485 if(CFDictionaryGetValue(query
, kSecAttrDeriveSyncIDFromItemAttributes
) ||
486 CFDictionaryGetValue(attributesToUpdate
, kSecAttrPCSPlaintextServiceIdentifier
) ||
487 CFDictionaryGetValue(attributesToUpdate
, kSecAttrPCSPlaintextPublicKey
) ||
488 CFDictionaryGetValue(attributesToUpdate
, kSecAttrPCSPlaintextPublicIdentity
)) {
489 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_update_id
, client
.task
, kSecEntitlementPrivateCKKSPlaintextFields
, &error
);
491 if(entitlementsCorrect
&&
492 (CFDictionaryGetValue(attributesToUpdate
, kSecDataInetExtraNotes
) ||
493 CFDictionaryGetValue(attributesToUpdate
, kSecDataInetExtraHistory
) ||
494 CFDictionaryGetValue(attributesToUpdate
, kSecDataInetExtraClientDefined0
) ||
495 CFDictionaryGetValue(attributesToUpdate
, kSecDataInetExtraClientDefined1
) ||
496 CFDictionaryGetValue(attributesToUpdate
, kSecDataInetExtraClientDefined2
) ||
497 CFDictionaryGetValue(attributesToUpdate
, kSecDataInetExtraClientDefined3
))) {
498 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_update_id
, client
.task
, kSecEntitlementPrivateInetExpansionFields
, &error
);
500 if (entitlementsCorrect
&& CFDictionaryGetValue(query
, kSecAttrSysBound
)) {
501 entitlementsCorrect
= EntitlementPresentAndTrue(sec_item_update_id
, client
.task
, kSecEntitlementPrivateSysBound
, &error
);
504 if(entitlementsCorrect
) {
505 bool result
= _SecItemUpdate(query
, attributesToUpdate
, &client
, &error
);
506 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
508 CFReleaseNull(attributesToUpdate
);
510 CFReleaseNull(query
);
515 case sec_item_delete_id
:
517 if (EntitlementAbsentOrFalse(sec_item_add_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
)) {
518 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
520 bool result
= _SecItemDelete(query
, &client
, &error
);
521 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
522 CFReleaseNull(query
);
527 case sec_item_update_token_items_for_access_groups_id
:
529 if (EntitlementAbsentOrFalse(sec_item_update_token_items_for_access_groups_id
, client
.task
, kSecEntitlementKeychainDeny
, &error
) &&
530 EntitlementPresentAndTrue(sec_item_update_token_items_for_access_groups_id
, client
.task
, kSecEntitlementUpdateTokenItems
, &error
)) {
531 CFStringRef tokenID
= SecXPCDictionaryCopyString(event
, kSecXPCKeyString
, &error
);
532 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyArray
, &error
);
533 CFArrayRef tokenItems
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyQuery
, &error
);
535 bool result
= _SecItemUpdateTokenItemsForAccessGroups(tokenID
, accessGroups
, tokenItems
, &client
, &error
);
536 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
538 CFReleaseNull(tokenID
);
539 CFReleaseNull(accessGroups
);
540 CFReleaseNull(tokenItems
);
544 case sec_delete_all_id
:
548 /* buddy is temporary allowed to do this */
549 CFStringRef applicationIdentifier
= SecTaskCopyApplicationIdentifier(client
.task
);
550 bool isBuddy
= applicationIdentifier
&&
551 CFEqual(applicationIdentifier
, CFSTR("com.apple.purplebuddy"));
552 CFReleaseNull(applicationIdentifier
);
554 if (isBuddy
|| EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateDeleteAll
, &error
))
556 retval
= _SecItemDeleteAll(&error
);
559 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
562 case sec_keychain_backup_id
:
564 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
565 CFDataRef keybag
= NULL
, passcode
= NULL
;
566 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybag
, &error
)) {
567 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
568 bool emcs
= SecXPCDictionaryGetBool(event
, kSecXPCKeyEMCSBackup
, NULL
);
569 CFDataRef backup
= _SecServerKeychainCreateBackup(&client
, keybag
, passcode
, emcs
, &error
);
571 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
573 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, backup
, &error
);
575 bool writeResult
= SecDataWriteFileDescriptor(fd
, backup
);
579 SecError(errSecIO
, &error
, CFSTR("Failed to write backup file: %d"), errno
);
580 SecXPCDictionarySetBool(replyMessage
, kSecXPCKeyResult
, writeResult
, NULL
);
584 CFReleaseSafe(passcode
);
586 CFReleaseSafe(keybag
);
591 case sec_keychain_restore_id
:
593 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
594 CFDataRef backup
= NULL
;
598 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
600 backup
= SecDataCopyMmapFileDescriptor(fd
, &mem
, &size
, &error
);
602 backup
= SecXPCDictionaryCopyData(event
, kSecXPCKeyBackup
, &error
);
605 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
607 CFDataRef passcode
= NULL
;
608 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
609 bool result
= _SecServerKeychainRestore(backup
, &client
, keybag
, passcode
, &error
);
610 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
611 CFReleaseSafe(passcode
);
614 CFReleaseNull(keybag
);
616 CFReleaseNull(backup
);
625 case sec_keychain_backup_keybag_uuid_id
:
627 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
628 CFDataRef backup
= NULL
;
629 CFStringRef uuid
= NULL
;
633 int fd
= SecXPCDictionaryDupFileDescriptor(event
, kSecXPCKeyFileDescriptor
, NULL
);
635 backup
= SecDataCopyMmapFileDescriptor(fd
, &mem
, &size
, &error
);
637 uuid
= _SecServerBackupCopyUUID(backup
, &error
);
640 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, uuid
, &error
);
642 CFReleaseNull(backup
);
653 case sec_keychain_sync_update_message_id
:
655 CFDictionaryRef updates
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
657 CFArrayRef result
= _SecServerKeychainSyncUpdateMessage(updates
, &error
);
658 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
659 CFReleaseNull(result
);
661 CFReleaseNull(updates
);
664 case sec_keychain_backup_syncable_id
:
666 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
667 CFDictionaryRef oldbackup
= NULL
;
668 if (SecXPCDictionaryCopyDictionaryOptional(event
, kSecXPCKeyBackup
, &oldbackup
, &error
)) {
669 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
671 CFDataRef passcode
= NULL
;
672 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
673 CFDictionaryRef newbackup
= _SecServerBackupSyncable(oldbackup
, keybag
, passcode
, &error
);
675 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, newbackup
, &error
);
676 CFRelease(newbackup
);
678 CFReleaseSafe(passcode
);
680 CFReleaseNull(keybag
);
682 CFReleaseSafe(oldbackup
);
687 case sec_keychain_restore_syncable_id
:
689 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
690 CFDictionaryRef backup
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyBackup
, &error
);
692 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
694 CFDataRef passcode
= NULL
;
695 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyUserPassword
, &passcode
, &error
)) {
696 bool result
= _SecServerRestoreSyncable(backup
, keybag
, passcode
, &error
);
697 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
698 CFReleaseSafe(passcode
);
700 CFReleaseNull(keybag
);
702 CFReleaseNull(backup
);
707 case sec_item_backup_copy_names_id
:
709 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
710 CFArrayRef names
= SecServerItemBackupCopyNames(&error
);
711 SecXPCDictionarySetPListOptional(replyMessage
, kSecXPCKeyResult
, names
, &error
);
712 CFReleaseSafe(names
);
716 case sec_item_backup_ensure_copy_view_id
:
718 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
719 CFStringRef viewName
= NULL
;
720 if (SecXPCDictionaryCopyStringOptional(event
, kSecXPCKeyString
, &viewName
, &error
)) {
721 CFStringRef name
= SecServerItemBackupEnsureCopyView(viewName
, &error
);
722 SecXPCDictionarySetString(replyMessage
, kSecXPCKeyResult
, name
, &error
);
728 case sec_item_backup_handoff_fd_id
:
730 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
731 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
734 fd
= SecServerItemBackupHandoffFD(backupName
, &error
);
735 CFRelease(backupName
);
737 SecXPCDictionarySetFileDescriptor(replyMessage
, kSecXPCKeyResult
, fd
, &error
);
743 case sec_item_backup_set_confirmed_manifest_id
:
745 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
746 CFDataRef keybagDigest
= NULL
;
747 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCKeyKeybag
, &keybagDigest
, &error
)) {
748 CFDataRef manifest
= NULL
;
749 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &manifest
, &error
)) {
750 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
752 bool result
= SecServerItemBackupSetConfirmedManifest(backupName
, keybagDigest
, manifest
, &error
);
753 CFRelease(backupName
);
754 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
756 CFReleaseSafe(manifest
);
759 CFReleaseNull(keybagDigest
);
763 case sec_item_backup_restore_id
:
765 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
767 CFStringRef backupName
= SecXPCDictionaryCopyString(event
, kSecXPCKeyBackup
, &error
);
769 CFStringRef peerID
= NULL
;
770 if (SecXPCDictionaryCopyStringOptional(event
, kSecXPCKeyDigest
, &peerID
, &error
)) {
771 CFDataRef keybag
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
);
773 CFDataRef secret
= SecXPCDictionaryCopyData(event
, kSecXPCKeyUserPassword
, &error
);
775 CFDataRef backup
= SecXPCDictionaryCopyData(event
, kSecXPCData
, &error
);
777 result
= SecServerItemBackupRestore(backupName
, peerID
, keybag
, secret
, backup
, &error
);
784 CFReleaseSafe(peerID
);
786 CFRelease(backupName
);
788 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
792 case sec_add_shared_web_credential_id
:
794 #if SHAREDWEBCREDENTIALS
795 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
797 CFTypeRef result
= NULL
;
799 CFStringRef appID
= (client
.task
) ? SecTaskCopyApplicationIdentifier(client
.task
) : NULL
;
800 if (_SecAddSharedWebCredential(query
, &client
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
801 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
802 CFReleaseNull(result
);
804 CFReleaseSafe(appID
);
805 CFReleaseNull(query
);
808 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, kCFBooleanFalse
, &error
);
812 case sec_copy_shared_web_credential_id
:
814 #if SHAREDWEBCREDENTIALS
815 CFDictionaryRef query
= SecXPCDictionaryCopyDictionary(event
, kSecXPCKeyQuery
, &error
);
817 CFTypeRef result
= NULL
;
818 CFStringRef appID
= (client
.task
) ? SecTaskCopyApplicationIdentifier(client
.task
) : NULL
;
819 if (_SecCopySharedWebCredential(query
, &client
, &auditToken
, appID
, domains
, &result
, &error
) && result
) {
820 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
821 CFReleaseNull(result
);
823 CFReleaseSafe(appID
);
824 CFReleaseNull(query
);
827 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, kCFBooleanFalse
, &error
);
831 case sec_get_log_settings_id
:
833 CFPropertyListRef currentList
= SecCopyLogSettings_Server(&error
);
835 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, currentList
, &error
);
837 CFReleaseSafe(currentList
);
840 case sec_set_xpc_log_settings_id
:
842 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
844 SecSetXPCLogSettings_Server(newSettings
, &error
);
846 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
847 CFReleaseNull(newSettings
);
850 case sec_set_circle_log_settings_id
:
852 CFPropertyListRef newSettings
= SecXPCDictionaryCopyPList(event
, kSecXPCKeyQuery
, &error
);
854 SecSetCircleLogSettings_Server(newSettings
, &error
);
856 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
857 CFReleaseNull(newSettings
);
860 case sec_otr_session_create_remote_id
:
862 CFDataRef publicPeerId
= NULL
;
863 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCPublicPeerId
, &publicPeerId
, &error
)) {
864 CFDataRef otrSession
= _SecOTRSessionCreateRemote(publicPeerId
, &error
);
866 SecXPCDictionarySetData(replyMessage
, kSecXPCKeyResult
, otrSession
, &error
);
867 CFReleaseNull(otrSession
);
869 CFReleaseSafe(publicPeerId
);
873 case sec_otr_session_process_packet_remote_id
:
875 CFDataRef sessionData
= NULL
, inputPacket
= NULL
, outputSessionData
= NULL
, outputPacket
= NULL
;
876 bool readyForMessages
= false;
877 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCOTRSession
, &sessionData
, &error
)) {
878 if (SecXPCDictionaryCopyDataOptional(event
, kSecXPCData
, &inputPacket
, &error
)) {
879 bool result
= _SecOTRSessionProcessPacketRemote(sessionData
, inputPacket
, &outputSessionData
, &outputPacket
, &readyForMessages
, &error
);
881 SecXPCDictionarySetData(replyMessage
, kSecXPCOTRSession
, outputSessionData
, &error
);
882 SecXPCDictionarySetData(replyMessage
, kSecXPCData
, outputPacket
, &error
);
883 xpc_dictionary_set_bool(replyMessage
, kSecXPCOTRReady
, readyForMessages
);
884 CFReleaseNull(outputSessionData
);
885 CFReleaseNull(outputPacket
);
887 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
889 CFReleaseSafe(inputPacket
);
891 CFReleaseSafe(sessionData
);
895 case kSecXPCOpTryUserCredentials
:
896 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
897 with_label_and_password_and_dsid(event
, ^(CFStringRef label
, CFDataRef password
, CFStringRef dsid
) {
898 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
899 SOSCCTryUserCredentials_Server(label
, password
, dsid
, &error
));
903 case kSecXPCOpSetUserCredentials
:
904 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
905 with_label_and_password(event
, ^(CFStringRef label
, CFDataRef password
) {
906 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
907 SOSCCSetUserCredentials_Server(label
, password
, &error
));
911 case kSecXPCOpSetUserCredentialsAndDSID
:
912 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
913 with_label_and_password_and_dsid(event
, ^(CFStringRef label
, CFDataRef password
, CFStringRef dsid
) {
914 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
915 SOSCCSetUserCredentialsAndDSID_Server(label
, password
, dsid
, &error
));
920 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
921 with_view_and_action(event
, ^(CFStringRef view
, uint64_t actionCode
) {
922 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
923 SOSCCView_Server(view
, (SOSViewActionCode
)actionCode
, &error
));
927 case kSecXPCOpViewSet
:
928 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
929 CFSetRef enabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyEnabledViewsKey
);
930 CFSetRef disabledViews
= SecXPCSetCreateFromXPCDictionaryElement(event
, kSecXPCKeyDisabledViewsKey
);
931 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCViewSet_Server(enabledViews
, disabledViews
));
932 CFReleaseNull(enabledViews
);
933 CFReleaseNull(disabledViews
);
936 case kSecXPCOpCanAuthenticate
:
937 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
938 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
939 SOSCCCanAuthenticate_Server(&error
));
942 case kSecXPCOpPurgeUserCredentials
:
943 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
944 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
945 SOSCCPurgeUserCredentials_Server(&error
));
948 case kSecXPCOpDeviceInCircle
:
949 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
950 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
951 SOSCCThisDeviceIsInCircle_Server(&error
));
954 case kSecXPCOpRequestToJoin
:
955 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
956 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
957 SOSCCRequestToJoinCircle_Server(&error
));
960 case kSecXPCOpAccountHasPublicKey
:
961 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
962 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
963 SOSCCAccountHasPublicKey_Server(&error
));
967 case kSecXPCOpRequestToJoinAfterRestore
:
968 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
969 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
970 SOSCCRequestToJoinCircleAfterRestore_Server(&error
));
973 case kSecXPCOpRequestDeviceID
:
974 case kSecXPCOpSetDeviceID
:
975 case kSecXPCOpHandleIDSMessage
:
976 case kSecXPCOpSyncWithIDSPeer
:
977 case kSecXPCOpSendIDSMessage
:
978 case kSecXPCOpPingTest
:
979 case kSecXPCOpIDSDeviceID
:
980 case kSecXPCOpSyncWithKVSPeerIDOnly
:{
981 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyError
, errSecUnimplemented
);
984 case kSecXPCOpAccountSetToNew
:
985 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
986 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCAccountSetToNew_Server(&error
));
989 case kSecXPCOpResetToOffering
:
990 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
991 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
992 SOSCCResetToOffering_Server(&error
));
995 case kSecXPCOpResetToEmpty
:
996 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
997 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
998 SOSCCResetToEmpty_Server(&error
));
1001 case kSecXPCOpRemoveThisDeviceFromCircle
:
1002 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1003 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1004 SOSCCRemoveThisDeviceFromCircle_Server(&error
));
1007 case kSecXPCOpRemovePeersFromCircle
:
1008 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1009 CFArrayRef applicants
= SecXPCDictionaryCopyPeerInfoArray(event
, kSecXPCKeyPeerInfoArray
, &error
);
1010 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1011 SOSCCRemovePeersFromCircle_Server(applicants
, &error
));
1012 CFReleaseNull(applicants
);
1015 case kSecXPCOpLoggedIntoAccount
:
1016 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1017 SOSCCNotifyLoggedIntoAccount_Server();
1018 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1022 case kSecXPCOpLoggedOutOfAccount
:
1023 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1024 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1025 SOSCCLoggedOutOfAccount_Server(&error
));
1028 case kSecXPCOpAcceptApplicants
:
1029 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1030 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfoArray
);
1031 // CreateArrayOfPeerInfoWithXPCObject enforces that xapplicants is a non-NULL xpc data object
1032 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1033 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1034 (applicants
&& SOSCCAcceptApplicants_Server(applicants
, &error
)));
1035 CFReleaseSafe(applicants
);
1038 case kSecXPCOpRejectApplicants
:
1039 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1040 xpc_object_t xapplicants
= xpc_dictionary_get_value(event
, kSecXPCKeyPeerInfoArray
);
1041 // CreateArrayOfPeerInfoWithXPCObject enforces that xapplicants is a non-NULL xpc data object
1042 CFArrayRef applicants
= CreateArrayOfPeerInfoWithXPCObject(xapplicants
, &error
); //(CFArrayRef)(_CFXPCCreateCFObjectFromXPCObject(xapplicants));
1043 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1044 (applicants
&& SOSCCRejectApplicants_Server(applicants
, &error
)));
1045 CFReleaseSafe(applicants
);
1048 case kSecXPCOpSetNewPublicBackupKey
:
1050 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1051 CFDataRef publicBackupKey
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNewPublicBackupKey
, &error
);
1052 if (publicBackupKey
!= NULL
) {
1053 SOSPeerInfoRef peerInfo
= SOSCCSetNewPublicBackupKey_Server(publicBackupKey
, &error
);
1054 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1055 CFReleaseNull(peerInfo
);
1057 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1058 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1059 xpc_release(xpc_object
);
1061 CFReleaseNull(peerInfoData
);
1062 CFReleaseSafe(publicBackupKey
);
1067 case kSecXPCOpRegisterRecoveryPublicKey
:
1069 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1070 CFDataRef recovery_key
= SecXPCDictionaryCopyData(event
, kSecXPCKeyRecoveryPublicKey
, &error
);
1071 if (recovery_key
!= NULL
) {
1073 CFDataRef nullData
= CFDataCreate(kCFAllocatorDefault
, &zero
, 1); // token we send if we really wanted to send NULL
1074 if(CFEqual(recovery_key
, nullData
)) {
1075 CFReleaseNull(recovery_key
);
1077 CFReleaseNull(nullData
);
1078 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, SOSCCRegisterRecoveryPublicKey_Server(recovery_key
, &error
));
1079 CFReleaseNull(recovery_key
);
1084 case kSecXPCOpGetRecoveryPublicKey
:
1086 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1087 xpc_object_t xpc_recovery_object
= NULL
;
1088 CFDataRef recovery
= SOSCCCopyRecoveryPublicKey(&error
);
1090 xpc_recovery_object
= _CFXPCCreateXPCObjectFromCFObject(recovery
);
1092 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_recovery_object
);
1093 CFReleaseNull(recovery
);
1097 case kSecXPCOpSetBagForAllSlices
:
1099 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementRestoreKeychain
, &error
)) {
1100 CFDataRef backupSlice
= SecXPCDictionaryCopyData(event
, kSecXPCKeyKeybag
, &error
); // NULL checked below
1101 bool includeV0
= xpc_dictionary_get_bool(event
, kSecXPCKeyIncludeV0
); // false is ok, so it's safe for this paramter to be unset or incorrect type
1102 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, backupSlice
&& SOSCCRegisterSingleRecoverySecret_Server(backupSlice
, includeV0
, &error
));
1103 CFReleaseSafe(backupSlice
);
1107 case kSecXPCOpCopyApplicantPeerInfo
:
1108 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1109 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1110 SOSCCCopyApplicantPeerInfo_Server(&error
),
1114 case kSecXPCOpCopyValidPeerPeerInfo
:
1115 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1116 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1117 SOSCCCopyValidPeerPeerInfo_Server(&error
),
1121 case kSecXPCOpValidateUserPublic
:
1122 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1123 bool trusted
= SOSCCValidateUserPublic_Server(&error
);
1124 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, trusted
);
1127 case kSecXPCOpCopyNotValidPeerPeerInfo
:
1128 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1129 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1130 SOSCCCopyNotValidPeerPeerInfo_Server(&error
),
1134 case kSecXPCOpCopyGenerationPeerInfo
:
1135 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1136 xpc_dictionary_set_and_consume_CFArray(replyMessage
, kSecXPCKeyResult
,
1137 SOSCCCopyGenerationPeerInfo_Server(&error
));
1140 case kSecXPCOpCopyRetirementPeerInfo
:
1141 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1142 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1143 SOSCCCopyRetirementPeerInfo_Server(&error
),
1147 case kSecXPCOpCopyViewUnawarePeerInfo
:
1148 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1149 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1150 SOSCCCopyViewUnawarePeerInfo_Server(&error
),
1154 case kSecXPCOpCopyEngineState
:
1156 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1157 CFArrayRef array
= SOSCCCopyEngineState_Server(&error
);
1158 CFDataRef derData
= NULL
;
1160 require_quiet(array
, done
);
1161 derData
= CFPropertyListCreateDERData(kCFAllocatorDefault
, array
, &error
);
1163 require_quiet(derData
, done
);
1164 xpc_dictionary_set_data(replyMessage
, kSecXPCKeyResult
, CFDataGetBytePtr(derData
),CFDataGetLength(derData
));
1166 CFReleaseNull(derData
);
1167 CFReleaseNull(array
);
1171 case kSecXPCOpCopyPeerPeerInfo
:
1172 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1173 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1174 SOSCCCopyPeerPeerInfo_Server(&error
),
1178 case kSecXPCOpCopyConcurringPeerPeerInfo
:
1179 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1180 xpc_dictionary_set_and_consume_PeerInfoArray(replyMessage
, kSecXPCKeyResult
,
1181 SOSCCCopyConcurringPeerPeerInfo_Server(&error
),
1185 case kSecXPCOpCopyMyPeerInfo
:
1186 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1187 SOSPeerInfoRef peerInfo
= SOSCCCopyMyPeerInfo_Server(&error
);
1188 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1189 CFReleaseNull(peerInfo
);
1191 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1192 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1193 xpc_release(xpc_object
);
1195 CFReleaseNull(peerInfoData
);
1198 case kSecXPCOpGetLastDepartureReason
:
1199 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1200 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1201 SOSCCGetLastDepartureReason_Server(&error
));
1204 case kSecXPCOpSetLastDepartureReason
:
1205 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1206 // 0 is a legitimate reason (kSOSDepartureReasonError), so it's safe for this parameter to be unset or incorrect type
1207 int32_t reason
= (int32_t) xpc_dictionary_get_int64(event
, kSecXPCKeyReason
);
1208 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1209 SOSCCSetLastDepartureReason_Server(reason
, &error
));
1212 case kSecXPCOpProcessSyncWithPeers
:
1213 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1214 CFSetRef peers
= SecXPCDictionaryCopySet(event
, kSecXPCKeySet
, &error
);
1215 CFSetRef backupPeers
= SecXPCDictionaryCopySet(event
, kSecXPCKeySet2
, &error
);
1216 if (peers
&& backupPeers
) {
1217 CFSetRef result
= SOSCCProcessSyncWithPeers_Server(peers
, backupPeers
, &error
);
1219 SecXPCDictionarySetPList(replyMessage
, kSecXPCKeyResult
, result
, &error
);
1221 CFReleaseNull(result
);
1223 CFReleaseNull(peers
);
1224 CFReleaseNull(backupPeers
);
1227 case kSecXPCOpProcessSyncWithAllPeers
:
1228 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1229 xpc_dictionary_set_int64(replyMessage
, kSecXPCKeyResult
,
1230 SOSCCProcessSyncWithAllPeers_Server(&error
));
1233 case soscc_EnsurePeerRegistration_id
:
1234 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainSyncUpdates
, &error
)) {
1235 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1236 SOSCCProcessEnsurePeerRegistration_Server(&error
));
1239 case kSecXPCOpRollKeys
:
1241 // false is valid, so it's safe for this parameter to be unset or incorrect type
1242 bool force
= xpc_dictionary_get_bool(event
, "force");
1243 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1244 _SecServerRollKeys(force
, &client
, &error
));
1247 case kSecXPCOpWaitForInitialSync
:
1248 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1249 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1250 SOSCCWaitForInitialSync_Server(&error
));
1253 case kSecXPCOpPeersHaveViewsEnabled
:
1255 CFArrayRef viewSet
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyArray
, &error
);
1257 CFBooleanRef result
= SOSCCPeersHaveViewsEnabled_Server(viewSet
, &error
);
1258 if (result
!= NULL
) {
1259 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
!= kCFBooleanFalse
);
1262 CFReleaseNull(viewSet
);
1266 case kSecXPCOpWhoAmI
:
1269 xpc_dictionary_set_data(replyMessage
, "musr", CFDataGetBytePtr(client
.musr
), CFDataGetLength(client
.musr
));
1270 xpc_dictionary_set_bool(replyMessage
, "system-keychain", client
.allowSystemKeychain
);
1271 xpc_dictionary_set_bool(replyMessage
, "syncbubble-keychain", client
.allowSyncBubbleKeychain
);
1272 xpc_dictionary_set_bool(replyMessage
, "network-extension", client
.isNetworkExtension
);
1273 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1276 case kSecXPCOpTransmogrifyToSyncBubble
:
1278 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainSyncBubble
, &error
)) {
1280 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1281 CFArrayRef services
= SecXPCDictionaryCopyArray(event
, "services", &error
);
1283 if (uid
&& services
) {
1284 res
= _SecServerTransmogrifyToSyncBubble(services
, uid
, &client
, &error
);
1286 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1287 CFReleaseNull(services
);
1289 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1294 case kSecXPCOpTransmogrifyToSystemKeychain
:
1296 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
)) {
1298 bool res
= _SecServerTransmogrifyToSystemKeychain(&client
, &error
);
1299 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1301 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1307 case kSecXPCOpDeleteUserView
:
1309 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateKeychainMigrateSystemKeychain
, &error
)) {
1312 uid_t uid
= (uid_t
)xpc_dictionary_get_int64(event
, "uid");
1314 res
= _SecServerDeleteMUSERViews(&client
, uid
, &error
);
1317 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, res
);
1322 case kSecXPCOpCopyApplication
:
1323 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1324 SOSPeerInfoRef peerInfo
= SOSCCCopyApplication_Server(&error
);
1325 CFDataRef peerInfoData
= peerInfo
? SOSPeerInfoCopyEncodedData(peerInfo
, kCFAllocatorDefault
, &error
) : NULL
;
1326 CFReleaseNull(peerInfo
);
1328 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(peerInfoData
);
1329 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1330 xpc_release(xpc_object
);
1332 CFReleaseNull(peerInfoData
);
1335 case kSecXPCOpCopyCircleJoiningBlob
:
1336 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1337 CFDataRef appBlob
= SecXPCDictionaryCopyCFDataRef(event
, kSecXPCData
, &error
);
1338 if (appBlob
!= NULL
) {
1339 SOSPeerInfoRef applicant
= SOSPeerInfoCreateFromData(kCFAllocatorDefault
, &error
, appBlob
);
1340 if (applicant
!= NULL
) {
1341 CFDataRef pbblob
= SOSCCCopyCircleJoiningBlob_Server(applicant
, &error
);
1343 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(pbblob
);
1344 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1345 xpc_release(xpc_object
);
1347 CFReleaseNull(pbblob
);
1348 CFReleaseNull(applicant
);
1350 CFReleaseNull(appBlob
);
1354 case kSecXPCOpCopyInitialSyncBlob
:
1355 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1356 uint64_t flags
= xpc_dictionary_get_uint64(event
, kSecXPCKeyFlags
); // 0 is a valid flags, so no error checking
1357 CFDataRef initialblob
= SOSCCCopyInitialSyncData_Server((uint32_t)flags
, &error
);
1359 xpc_object_t xpc_object
= _CFXPCCreateXPCObjectFromCFObject(initialblob
);
1360 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyResult
, xpc_object
);
1361 xpc_release(xpc_object
);
1363 CFReleaseNull(initialblob
);
1366 case kSecXPCOpJoinWithCircleJoiningBlob
:
1367 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementCircleJoin
, &error
)) {
1368 CFDataRef joiningBlob
= SecXPCDictionaryCopyCFDataRef(event
, kSecXPCData
, &error
); // NULL checked below
1369 uint64_t version
= xpc_dictionary_get_uint64(event
, kSecXPCVersion
); // 0 is valid, so this parameter can be unset or incorrect type
1370 if (joiningBlob
!= NULL
) {
1371 bool retval
= SOSCCJoinWithCircleJoiningBlob_Server(joiningBlob
, (PiggyBackProtocolVersion
) version
, &error
);
1372 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1373 CFReleaseNull(joiningBlob
);
1377 case kSecXPCOpKVSKeyCleanup
:
1378 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainCloudCircle
, &error
)) {
1379 bool retval
= SOSCCCleanupKVSKeys_Server(&error
);
1380 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1383 case kSecXPCOpMessageFromPeerIsPending
:
1385 SOSPeerInfoRef peer
= SecXPCDictionaryCopyPeerInfo(event
, kSecXPCKeyPeerInfo
, &error
);
1387 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1388 SOSCCMessageFromPeerIsPending_Server(peer
, &error
));
1390 CFReleaseNull(peer
);
1393 case kSecXPCOpSendToPeerIsPending
:
1395 SOSPeerInfoRef peer
= SecXPCDictionaryCopyPeerInfo(event
, kSecXPCKeyPeerInfo
, &error
);
1397 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
,
1398 SOSCCSendToPeerIsPending(peer
, &error
));
1400 CFReleaseNull(peer
);
1403 #endif /* !SECUREOBJECTSYNC */
1404 case sec_delete_items_with_access_groups_id
:
1406 bool retval
= false;
1407 #if TARGET_OS_IPHONE
1408 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateUninstallDeletion
, &error
)) {
1409 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyAccessGroups
, &error
);
1412 retval
= _SecItemServerDeleteAllWithAccessGroups(accessGroups
, &client
, &error
);
1414 CFReleaseNull(accessGroups
);
1417 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, retval
);
1420 case kSecXPCOpBackupKeybagAdd
: {
1421 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementBackupTableOperations
, &error
)) {
1422 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1426 case kSecXPCOpBackupKeybagDelete
: {
1427 if (EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementBackupTableOperations
, &error
)) {
1428 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1432 case kSecXPCOpKeychainControlEndpoint
: {
1433 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementKeychainControl
, &error
)) {
1434 xpc_endpoint_t endpoint
= SecServerCreateKeychainControlEndpoint();
1436 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyEndpoint
, endpoint
);
1437 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, true);
1438 xpc_release(endpoint
);
1440 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, false);
1445 case sec_item_copy_parent_certificates_id
: {
1446 CFArrayRef results
= NULL
;
1447 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateCertificateAllAccess
, &error
)) {
1448 CFDataRef issuer
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNormalizedIssuer
, &error
);
1449 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyAccessGroups
, &error
);
1450 if (issuer
&& accessGroups
) {
1451 results
= _SecItemCopyParentCertificates(issuer
, accessGroups
, &error
);
1453 CFReleaseNull(issuer
);
1454 CFReleaseNull(accessGroups
);
1456 SecXPCDictionarySetPListOptional(replyMessage
, kSecXPCKeyResult
, results
, &error
);
1457 CFReleaseNull(results
);
1460 case sec_item_certificate_exists_id
: {
1461 bool result
= false;
1462 if(EntitlementPresentAndTrue(operation
, client
.task
, kSecEntitlementPrivateCertificateAllAccess
, &error
)) {
1463 CFDataRef issuer
= SecXPCDictionaryCopyData(event
, kSecXPCKeyNormalizedIssuer
, &error
);
1464 CFDataRef serialNum
= SecXPCDictionaryCopyData(event
, kSecXPCKeySerialNumber
, &error
);
1465 CFArrayRef accessGroups
= SecXPCDictionaryCopyArray(event
, kSecXPCKeyAccessGroups
, &error
);
1466 if (issuer
&& serialNum
&& accessGroups
) {
1467 result
= _SecItemCertificateExists(issuer
, serialNum
, accessGroups
, &error
);
1469 CFReleaseNull(issuer
);
1470 CFReleaseNull(serialNum
);
1471 CFReleaseNull(accessGroups
);
1473 xpc_dictionary_set_bool(replyMessage
, kSecXPCKeyResult
, result
);
1482 if(SecErrorGetOSStatus(error
) == errSecItemNotFound
|| isSOSErrorCoded(error
, kSOSErrorPublicKeyAbsent
))
1483 secdebug("ipc", "%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1484 else if (SecErrorGetOSStatus(error
) == errSecAuthNeeded
)
1485 secwarning("Authentication is needed %@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1487 secerror("%@ %@ %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), error
);
1489 xpcError
= SecCreateXPCObjectWithCFError(error
);
1491 xpc_dictionary_set_value(replyMessage
, kSecXPCKeyError
, xpcError
);
1493 } else if (replyMessage
) {
1494 secdebug("ipc", "%@ %@ responding %@", client
.task
, SOSCCGetOperationDescription((enum SecXPCOperation
)operation
), replyMessage
);
1497 SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType
, sSecXPCErrorDomain
, NULL
, &error
, 0, CFSTR("Messages expect to be xpc dictionary, got: %@"), event
);
1498 secerror("%@: returning error: %@", client
.task
, error
);
1499 xpcError
= SecCreateXPCObjectWithCFError(error
);
1500 replyMessage
= xpc_create_reply_with_format(event
, "{%string: %value}", kSecXPCKeyError
, xpcError
);
1504 xpc_connection_send_message(connection
, replyMessage
);
1505 xpc_release(replyMessage
);
1508 xpc_release(xpcError
);
1510 CFReleaseSafe(error
);
1511 CFReleaseSafe(client
.accessGroups
);
1512 CFReleaseSafe(client
.musr
);
1513 CFReleaseSafe(client
.task
);
1514 CFReleaseNull(client
.applicationIdentifier
);
1515 CFReleaseSafe(domains
);
1516 CFReleaseSafe(clientAuditToken
);
1519 static void securityd_xpc_init(const char *service_name
)
1521 secdebug("serverxpc", "start");
1522 xpc_connection_t listener
= xpc_connection_create_mach_service(service_name
, NULL
, XPC_CONNECTION_MACH_SERVICE_LISTENER
);
1524 seccritical("security failed to register xpc listener for %s, exiting", service_name
);
1528 xpc_connection_set_event_handler(listener
, ^(xpc_object_t connection
) {
1529 if (xpc_get_type(connection
) == XPC_TYPE_CONNECTION
) {
1530 xpc_connection_set_event_handler(connection
, ^(xpc_object_t event
) {
1531 if (xpc_get_type(event
) == XPC_TYPE_DICTIONARY
) {
1532 // Synchronous. The client has a connection pool so they can be somewhat re-entrant if they need.
1533 securityd_xpc_dictionary_handler(connection
, event
);
1536 xpc_connection_resume(connection
);
1539 xpc_connection_resume(listener
);
1542 xpc_activity_register("com.apple.securityd.daily", XPC_ACTIVITY_CHECK_IN
, ^(xpc_activity_t activity
) {
1543 xpc_activity_state_t activityState
= xpc_activity_get_state(activity
);
1544 if (activityState
== XPC_ACTIVITY_STATE_RUN
) {
1545 SecCKKS24hrNotification();
1546 SecOctagon24hrNotification();
1551 xpc_activity_register("com.apple.securityd.prng", XPC_ACTIVITY_CHECK_IN
, ^(xpc_activity_t activity
) {
1552 xpc_activity_state_t state
= xpc_activity_get_state(activity
);
1553 if (state
== XPC_ACTIVITY_STATE_RUN
) {
1558 #if OCTAGON && !TARGET_OS_BRIDGE
1559 // Kick off reporting tasks.
1560 if (os_variant_has_internal_diagnostics("com.apple.security") && !os_variant_is_recovery("securityd")) {
1561 InitPolicyReporter();
1567 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1569 #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR && !TARGET_OS_BRIDGE
1570 static void securityd_soscc_lock_hack() {
1571 dispatch_queue_t soscc_lock_queue
= dispatch_queue_create("soscc_lock_queue", DISPATCH_QUEUE_PRIORITY_DEFAULT
);
1574 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1575 // FIXME: securityd isn't currently registering for any other notifyd events. If/when it does,
1576 // this code will need to be generalized / migrated away from just this specific purpose.
1577 xpc_set_event_stream_handler("com.apple.notifyd.matching", dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH
, 0), ^(xpc_object_t object
) {
1578 char *event_description
= xpc_copy_description(object
);
1579 secnotice("events", "%s", event_description
);
1580 free(event_description
);
1583 secnotice("lockassertion", "notify_register_dispatch(kSOSCCHoldLockForInitialSync)");
1584 notify_register_dispatch(kSOSCCHoldLockForInitialSync
, &soscc_tok
, soscc_lock_queue
, ^(int token __unused
) {
1585 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync: grabbing the lock");
1586 CFErrorRef error
= NULL
;
1588 uint64_t one_minute
= 60ull;
1589 if(SecAKSUserKeybagHoldLockAssertion(one_minute
, &error
)){
1590 // <rdar://problem/22500239> Prevent securityd from quitting while holding a keychain assertion
1591 os_transaction_t transaction
= os_transaction_create("securityd-LockAssertedingHolder");
1593 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, one_minute
*NSEC_PER_SEC
), soscc_lock_queue
, ^{
1594 CFErrorRef localError
= NULL
;
1595 if(!SecAKSUserKeybagDropLockAssertion(&localError
))
1596 secerror("failed to unlock: %@", localError
);
1597 CFReleaseNull(localError
);
1598 os_release(transaction
);
1601 secerror("Failed to take device lock assertion: %@", error
);
1603 CFReleaseNull(error
);
1604 secnotice("lockassertion", "kSOSCCHoldLockForInitialSync => done");
1614 static char homeDir
[PATH_MAX
] = {};
1616 if (homeDir
[0] == '\0') {
1617 struct passwd
* pwd
= getpwuid(getuid());
1621 if (realpath(pwd
->pw_dir
, homeDir
) == NULL
) {
1622 strlcpy(homeDir
, pwd
->pw_dir
, sizeof(homeDir
));
1630 int main(int argc
, char *argv
[])
1632 DisableLocalization();
1634 char *wait4debugger
= getenv("WAIT4DEBUGGER");
1635 if (wait4debugger
&& !strcasecmp("YES", wait4debugger
)) {
1636 seccritical("SIGSTOPing self, awaiting debugger");
1637 kill(getpid(), SIGSTOP
);
1638 seccritical("Again, for good luck (or bad debuggers)");
1639 kill(getpid(), SIGSTOP
);
1642 /* <rdar://problem/15792007> Users with network home folders are unable to use/save password for Mail/Cal/Contacts/websites
1643 Secd doesn't realize DB connections get invalidated when network home directory users logout
1644 and their home gets unmounted. Exit secd, start fresh when user logs back in.
1647 int sessionstatechanged_tok
;
1648 notify_register_dispatch(kSA_SessionStateChangedNotification
, &sessionstatechanged_tok
, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^(int token __unused
) {
1649 // we could be a process running as root.
1650 // However, since root never logs out this isn't an issue.
1651 if (SASSessionStateForUser(getuid()) == kSA_state_loggingout_pointofnoreturn
) {
1652 dispatch_after(dispatch_time(DISPATCH_TIME_NOW
, 3ull*NSEC_PER_SEC
), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
1653 xpc_transaction_exit_clean();
1659 signal(SIGTERM
, SIG_IGN
);
1660 static dispatch_source_t termSource
;
1661 termSource
= dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL
, SIGTERM
, 0, dispatch_get_global_queue(QOS_CLASS_USER_INITIATED
, 0));
1662 dispatch_source_set_event_handler(termSource
, ^{
1663 secnotice("signal", "SIGTERM, exiting when clean ✌️");
1664 xpc_transaction_exit_clean();
1666 dispatch_activate(termSource
);
1669 #define SECD_PROFILE_NAME "com.apple.secd"
1670 const char *homedir
= homedirPath();
1671 if (homedir
== NULL
) {
1672 errx(1, "failed to get home directory for secd");
1675 char *errorbuf
= NULL
;
1676 const char *sandbox_params
[] = {"_HOME", homedir
, NULL
};
1677 int32_t rc
= sandbox_init_with_parameters(SECD_PROFILE_NAME
, SANDBOX_NAMED
, sandbox_params
, &errorbuf
);
1679 errx(1, "Failed to instantiate sandbox: %d %s", rc
, errorbuf
);
1680 /* errx will quit the process */
1682 #endif /* TARGET_OS_OSX */
1684 const char *serviceName
= kSecuritydXPCServiceName
;
1686 // Mark our interest in running some features (before we bring the DB layer up)
1688 EscrowRequestServerSetEnabled(true);
1689 OctagonSetShouldPerformInitialization(true);
1693 /* setup SQDLite before some other component have a chance to create a database connection */
1694 _SecDbServerSetup();
1696 securityd_init_server();
1697 securityd_xpc_init(serviceName
);
1698 SecCreateSecuritydXPCServer();
1700 #if SECUREOBJECTSYNC
1701 SOSControlServerInitialize();
1705 CKKSControlServerInitialize();
1706 OctagonControlServerInitialize();
1707 EscrowRequestXPCServerInitialize();
1710 // <rdar://problem/22425706> 13B104+Roots:Device never moved past spinner after using approval to ENABLE icdp
1711 #if TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR && !TARGET_OS_BRIDGE
1712 securityd_soscc_lock_hack();
1718 /* vi:set ts=4 sw=4 et: */